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:
2026-07-16 22:48:15 +02:00
parent bdb65a80e8
commit eb227486d0
11 changed files with 567 additions and 0 deletions
@@ -393,3 +393,46 @@ before the hub ever used the surface. The §6-era orphan `root@pam!spike` token
`/datastore/scratch` DatastoreAdmin ACL were removed in the same session (spike flag #1); after
teardown the endpoint holds exactly the real `demo-felhom-01` tenancy. Hub v0.44.0 logs
`PBS DR tenantsync enabled (endpoint 167.233.158.164:22, user felhom-peersync)` on start.
## 11. The felhom-poke surface (agent-plane immediate-sync — Direction-2a, v0.59.0)
The hub's THIRD forced-command surface: a **contentless UDP "sync now" nudge** to a registered
box's WireGuard /32, so a user-triggered agent-plane change (a pbsdr descriptor, a MinAgent floor)
lands in **seconds** instead of the ≤15-min report cycle. Proven end-to-end by
`documentation/audits/SPIKE-immediate-sync-transport-2026-07-16.md` (~0.42 s/poke; reserved there
for the agent plane). Same low-priv `felhom-peersync` user + REUSED endpoint address & pinned host
key, its OWN keypair + script — **peersync/tenantsync files untouched**. Script source of truth:
`scripts/felhom-poke.sh` (v1.0.0). Hub client: `hub/internal/poke`.
**No sudoers grant** — unlike peersync/tenantsync, sending a datagram needs no privilege, so the
forced command runs as `felhom-peersync` directly (`command="/usr/local/bin/felhom-poke"`, no
`sudo`). The fixed poke port is **51822** — a shared cross-repo constant (`felhom-agent`
`internal/poke.Port`, this script's `POKE_PORT`, and the port the listener binds on the box's WG
/32); change it in all three or nowhere.
On the build server (the hub's credential; mirror of §6/§10 — the PRIVATE key ends only in the
Secret):
```sh
ssh-keygen -t ed25519 -f agent-poke-ssh -N "" -C hub-poke@felhom
sudo kubectl -n felhom-system create secret generic agent-poke --from-file=key=agent-poke-ssh
# keep agent-poke-ssh.pub for the box step below, THEN:
shred -u agent-poke-ssh # the private key now exists ONLY in the Secret
```
(The pinned host key + endpoint address are REUSED from the peersync env — no new hostkey entry.
`manifests/hub.yaml` mounts the Secret at `/etc/hub-secrets/agent-poke/key` via `POKE_SSH_KEY_FILE`;
absent Secret → the hub logs "agent-plane poke disabled".)
On the box (ep0), as root — additive; the peersync `authorized_keys` lines are untouched:
```sh
tr -d '\r' < felhom-poke.sh > /tmp/fp && sh -n /tmp/fp
install -o root -g root -m 0755 /tmp/fp /usr/local/bin/felhom-poke && rm /tmp/fp
printf 'restrict,command="/usr/local/bin/felhom-poke" %s\n' "$(cat agent-poke-ssh.pub)" \
>> /home/felhom-peersync/.ssh/authorized_keys
```
Verify (from the build server with the key before it is shredded — pin the host key from §6's on-box
read, never keyscan): `ssh -i agent-poke-ssh felhom-peersync@<ep0> 10.77.0.<box>` → prints
`poke-fired`, and the box's agent journal logs `poke received → triggering an immediate
desired-state cycle`. A non-WG target (`ssh … 8.8.8.8`) → `refused non-WG target`, non-zero exit.
Hub v0.59.0 logs `agent-plane poke enabled (endpoint 167.233.158.164:22, user felhom-peersync)` on
start.