Commit Graph

3 Commits

Author SHA1 Message Date
Anso e12602091a fix: repin semver compose tags during fleet self-update (#1587)
* fix: repin semver compose tags during fleet self-update

Fleet updates failed when docker-compose.yml pinned a semver tag because recreate reused the on-disk pin. Pull the target image first, rewrite semver pins via the update helper, and block digest or unresolved pins with fast 409s.

* fix: update OFFLINE_META shape in capability and node-registry meta tests
2026-07-07 14:40:50 -04:00
Anso 0b50c88eb3 fix(fleet): route remote update trigger through getProxyTarget (#1123)
POST /api/fleet/nodes/:id/update and POST /api/fleet/update-all read
node.api_url + node.api_token directly, so a pilot-agent row (which
carries neither) returned "Remote node not configured." and was
filtered out of bulk update. Both routes now resolve the target via
NodeRegistry.getProxyTarget(), which returns the loopback URL for an
active pilot tunnel and the configured api_url for proxy-mode remotes.
fetchMetaForNode replaces the direct fetchRemoteMeta call for the
self-update capability check.

self-update is removed from PILOT_DISABLED_CAPABILITIES so a
Compose-deployed pilot can advertise it; the host-console filter
stays. SelfUpdateService still gates the local-end capability on the
container actually carrying docker-compose labels, so a docker-run
pilot self-disables and the Fleet UI sees a clean 503 instead of an
ambiguous failure.

Tests: new fleet-pilot-update covers the four single-node branches
(success via loopback, null target, no self-update capability, meta
offline) and two update-all cases (mixed-fleet dispatch, all-targets-
null skip). capability-registry-pilot rewired to assert the new
filter set.
2026-05-20 03:35:39 -04:00
Anso 8dd0fce621 fix(fleet): show capabilities, version, metrics, and stacks for pilot-agent nodes (#1044)
When a pilot-agent node was the active node, the UI rendered "does not
advertise this capability" across most tabs, a perpetual "Update
available" badge, and a Fleet card body with blank CPU/RAM/Disk and "No
stacks found". The cause was central-side aggregators in /api/fleet/* and
/api/nodes/:id/meta only fanning out to proxy-mode remotes via
node.api_url + node.api_token, which are null for pilot-agent.

Route every affected aggregator through NodeRegistry.getProxyTarget so
the loopback URL backed by the active pilot tunnel is used uniformly:

- /api/nodes/:id/meta and /api/fleet/update-status fetch via the new
  NodeRegistry.fetchMetaForNode helper (resolves the target, delegates
  to fetchRemoteMeta, returns the shared OFFLINE_META on null).
- fetchRemoteNodeOverview, /api/fleet/configuration,
  /api/fleet/node/:nodeId/stacks, and the stack-containers drilldown
  fetch through target.apiUrl with conditional Authorization.
- fetchRemoteMeta omits the Authorization header when the token is empty
  (pilot-agent loopback) instead of sending a malformed Bearer string.
- Pilot-agent rows preserve pilot_last_seen and mirror it into
  last_successful_contact so the Fleet "last seen" cell renders the
  recent tunnel timestamp during a brief reconnect.

Pilot-mode capability filter excludes capabilities whose central-pilot
path is not yet wired (host-console, self-update). Without this, the
Console tab would surface for an Admiral pilot session and click
through to central's host because the WS upgrade handler still gates
on api_url + api_token. Filtered capabilities are removed at boot via
applyPilotModeCapabilityFilter when SENCHO_MODE=pilot.

Cache invalidation on tunnel-up: the meta cache for a reconnecting
pilot is dropped so the next request rebuilds capabilities and version
through the live bridge instead of waiting for the 3-minute TTL. The
namespace constant moves to helpers/cacheInvalidation.ts alongside the
new invalidateRemoteMetaCache helper.

Husky commit-msg hook: add the missing shebang and a .gitattributes
rule pinning .husky/* to LF line endings so commits do not fail with
"Exec format error" on Windows shells where autocrlf=true converts the
hook to CRLF.

Tests cover Authorization-header behavior, pilot-mode filter idempotency,
fetchMetaForNode dispatch (offline target, pilot-agent loopback,
proxy-mode), and the four affected fleet routes for pilot-agent both
when the tunnel is up and when it is down.
2026-05-14 10:21:08 -04:00