hub v0.59.0: Direction-2a agent-plane immediate-sync poke sender + ep0 felhom-poke surface
- internal/poke: pinned-host-key SSH poke sender (wgsync sibling) + fire-and-forget Notifier (PokeHost/PokeAllHosts). Poke refuses non-WG targets pre-dial; contentless via ep0 forced command to the box WG /32:51822. - wiring: Server.SetPoke; applyPBSDR pokes the host after each descriptor gen-bump; handleSetArtifacts (MinAgent floor) pokes all hosts. main.go env POKE_SSH_KEY_FILE (reuses peersync endpoint/hostkey). - scripts/felhom-poke.sh (non-root forced command) + offsite-endpoint.md §11; manifests/hub.yaml Secret/agent-poke + POKE_SSH_KEY_FILE (image tag bump follows the build).
This commit is contained in:
@@ -1,5 +1,43 @@
|
||||
# Felhom Hub — Changelog
|
||||
|
||||
## v0.59.0 — Direction-2a: agent-plane immediate-sync poke sender + ep0 felhom-poke surface (2026-07-16)
|
||||
|
||||
Implements the AGENT-plane half of `documentation/audits/SPIKE-immediate-sync-transport-2026-07-16.md`
|
||||
option (a): an operator agent-plane change (a pbsdr descriptor, a MinAgent floor) now nudges the box
|
||||
in **seconds** via a CONTENTLESS UDP poke relayed hub → ep0 forced-command → wg0-origin → the agent's
|
||||
poke listener (felhom-agent v0.89.0). The spike reserved this transport for the agent plane and
|
||||
measured it at ~0.42 s/poke. Complements v0.58.0's `internal/intent` long-poll wait channel
|
||||
(Direction-2b, the CONTROLLER plane): intent is customer-keyed and wakes the config puller; poke is
|
||||
host-keyed and nudges the agent. Both are fire-and-forget; the 15-min report cycle stays the
|
||||
guarantee. Pairs with felhom-agent v0.89.0 (the listener).
|
||||
|
||||
- **`internal/poke` — the SSH poke sender + notifier.** Third structural sibling of
|
||||
`internal/wgsync`/`internal/tenantsync`: a pinned-host-key (`ssh.FixedHostKey`, algorithm-pinned)
|
||||
in-process SSH client that reuses the peersync endpoint + host key, its OWN forced-command key.
|
||||
`Client.Poke(ctx, boxWGIP)` refuses any target outside `10.77.0.0/24` BEFORE dialing, then SSHes to
|
||||
ep0's `felhom-poke` with the box's WG /32 as the command string (→ `$SSH_ORIGINAL_COMMAND`); the
|
||||
forced command sends one empty UDP datagram to `<ip>:51822`. `Notifier.PokeHost`/`PokeAllHosts`
|
||||
are fire-and-forget (detached goroutine, nil-receiver-safe) — a poke NEVER blocks or fails the
|
||||
operator save; a missing peer / SSH error is logged and the report cycle reconciles. Tests:
|
||||
resolved-IP send, no-peer/store-error no-send, nil no-op, `Poke` pre-dial non-WG refusal.
|
||||
- **Wiring** (`internal/web/server.go`, `internal/web/pbsdr.go`, `internal/web/configs.go`,
|
||||
`cmd/hub/main.go`): `Server.SetPoke`; `applyPBSDR` fires `PokeHost(host.HostID)` after each
|
||||
generation-bumping descriptor save (disable, storage-id/re-enable change, fresh provision);
|
||||
`handleSetArtifacts` (the MinAgent-floor / vouched-agent save) fires `PokeAllHosts()`. **Source note
|
||||
(spec landmark vs source):** the artifact-manifest save does NOT itself bump per-host desired
|
||||
generation — the agent self-update dispatches via signed-ops on the next report — so the fleet poke
|
||||
there accelerates the next report cycle where the floor is applied, rather than delivering a
|
||||
desired-state delta. The sender is env-configured (`POKE_SSH_KEY_FILE`, reusing
|
||||
`WG_ENDPOINT_SSH_ADDR`/`_HOSTKEY`/user); absent Secret → "agent-plane poke disabled".
|
||||
- **ep0 surface** (`scripts/felhom-poke.sh` v1.0.0 + `documentation/runbooks/offsite-endpoint.md`
|
||||
§11): a NON-root (`felhom-peersync`, no sudoers grant — a datagram needs no privilege)
|
||||
forced-command that validates `$SSH_ORIGINAL_COMMAND` to the WG /24 and sends one empty datagram
|
||||
from wg0. Contentless + confined (the WG kernel independently refuses non-peer /32s — spike P1
|
||||
EKEYREJECTED). Port **51822** is a shared cross-repo constant.
|
||||
- **`manifests/hub.yaml`:** `POKE_SSH_KEY_FILE` env + optional `Secret/agent-poke` mounted 0400 at
|
||||
`/etc/hub-secrets/agent-poke/key` (the private key stored out-of-band, per §11). Bump the image tag
|
||||
to `0.59.0` and sync.
|
||||
|
||||
## v0.58.0 — Direction-2 immediate-sync: the hub→box "sync now" wait channel (2026-07-16)
|
||||
|
||||
Implements option (b) of `documentation/audits/SPIKE-immediate-sync-transport-2026-07-16.md`: an
|
||||
|
||||
Reference in New Issue
Block a user