4.3 KiB
4.3 KiB
felhom.eu — task reports
Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.
Direction-2a agent-plane immediate-sync — poke sender + ep0 felhom-poke surface (hub v0.59.0) — 2026-07-16
Baseline: hub v0.58.0 → v0.59.0 (LIVE on prod, ArgoCD Synced/Healthy). Pairs with felhom-agent
v0.89.0 (the poke listener). Green gate go build ./... && go vet ./... && go test ./... passes.
Design contract: documentation/audits/SPIKE-immediate-sync-transport-2026-07-16.md option (a).
What shipped
internal/poke— the SSH poke SENDER (third sibling ofinternal/wgsync/internal/tenantsync): a pinned-host-key (algorithm-pinnedssh.FixedHostKey) in-process client reusing the peersync endpoint + host key, its OWN forced-command key.Client.Poke(ctx, boxWGIP)refuses any target outside10.77.0.0/24BEFORE dialing, then SSHes to ep0'sfelhom-pokewith the box WG /32 as the command string (→$SSH_ORIGINAL_COMMAND) which sends one empty UDP datagram to<ip>:51822.Notifier.PokeHost/PokeAllHostsare fire-and-forget (detached goroutine, nil-receiver-safe) — a poke never blocks or fails the operator save; a missing peer / SSH error is logged, the report cycle reconciles. Tests: resolved-IP send, no-peer / store-error no-send, nil no-op,Pokepre-dial non-WG refusal.- Wiring:
Server.SetPoke;applyPBSDRfiresPokeHost(host.HostID)after each generation-bumping descriptor save;handleSetArtifacts(MinAgent-floor save) firesPokeAllHosts().cmd/hub/main.goenv-configures the sender (POKE_SSH_KEY_FILE, reusingWG_ENDPOINT_SSH_ADDR/_HOSTKEY/user). - ep0 surface:
scripts/felhom-poke.shv1.0.0 — a NON-root (felhom-peersync, no sudoers grant) forced command that validates$SSH_ORIGINAL_COMMANDto the WG /24 and sends one empty datagram from wg0. Contentless + confined (the WG kernel refuses non-peer /32s — spike P1 EKEYREJECTED). Runbookdocumentation/runbooks/offsite-endpoint.md§11. Port 51822 = shared cross-repo constant. manifests/hub.yaml:POKE_SSH_KEY_FILEenv + optionalSecret/agent-pokemounted 0400; image tag0.58.0→0.59.0.
Landmarks as found at source
- Poke wiring is host-keyed (
store.GetWGPeerForHost→ the box WG /32), the sibling of the customer-keyedinternal/intentlong-poll (Direction-2b / controller plane).SetHostDesiredbumps the poked host's generation; the poked immediate report carries the advanced envelope generation → the agent fetches the new descriptor. - Spec-vs-source note (source wins): the MinAgent-floor / artifact-manifest save
(
handleSetArtifacts) does NOT itself bump per-host desired generation — the agent self-update dispatches via signed-ops on the next report — soPokeAllHosts()there accelerates the next report cycle where the floor is applied, rather than delivering a desired-state delta. Kept the poke there (the spec names this handler) and documented the semantics.
Live validation
- Deployed: hub 0.59.0 built + pushed on 180, manifest tag bumped + ArgoCD synced (Synced/Healthy,
rollout complete, image
:0.59.0); after the Secret was created it logsagent-plane poke enabled. - ep0 poke surface installed live (additive;
felhom-peersyncauthorized_keys 2→3 lines, peersync/tenantsync UNCHANGED;/usr/local/bin/felhom-poke0755;Secret/agent-pokeholds the private key, the build-server copy shredded). - ep0 leg live-validated with the poke key: a valid WG target (
10.77.0.2) →poke-fired;8.8.8.8ANDrm -rf /as the SSH command →refused non-WG target(the forced command NEVER executes client input, only reads it as an IP candidate). This proves the full hub→ep0→box datagram path and the credential-theft blast radius (≤ "make a registered box tick"). - Not yet fired end-to-end from an operator save (the config/floor save UIs are password-gated; CC can't log in) and the box-side tick awaits the demo agent reaching v0.89.0 via the floor train (operator vouch) — see the felhom-agent REPORT. Scenario 3's measured save-to-tick latency is the operator follow-up.