56 lines
4.3 KiB
Markdown
56 lines
4.3 KiB
Markdown
# 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](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](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 of `internal/wgsync`/`internal/tenantsync`):
|
|
a pinned-host-key (algorithm-pinned `ssh.FixedHostKey`) in-process client reusing 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 WG /32 as the
|
|
command string (→ `$SSH_ORIGINAL_COMMAND`) which 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, the report cycle
|
|
reconciles. Tests: resolved-IP send, no-peer / store-error no-send, nil no-op, `Poke` pre-dial
|
|
non-WG refusal.
|
|
- **Wiring:** `Server.SetPoke`; `applyPBSDR` fires `PokeHost(host.HostID)` after each generation-bumping
|
|
descriptor save; `handleSetArtifacts` (MinAgent-floor save) fires `PokeAllHosts()`. `cmd/hub/main.go`
|
|
env-configures the sender (`POKE_SSH_KEY_FILE`, reusing `WG_ENDPOINT_SSH_ADDR`/`_HOSTKEY`/user).
|
|
- **ep0 surface:** `scripts/felhom-poke.sh` v1.0.0 — a NON-root (`felhom-peersync`, no sudoers grant)
|
|
forced command that validates `$SSH_ORIGINAL_COMMAND` to the WG /24 and sends one empty datagram
|
|
from wg0. Contentless + confined (the WG kernel refuses non-peer /32s — spike P1 EKEYREJECTED).
|
|
Runbook `documentation/runbooks/offsite-endpoint.md` §11. Port **51822** = shared cross-repo constant.
|
|
- **`manifests/hub.yaml`:** `POKE_SSH_KEY_FILE` env + optional `Secret/agent-poke` mounted 0400; image
|
|
tag `0.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-keyed `internal/intent` long-poll (Direction-2b / controller plane). `SetHostDesired` bumps
|
|
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 — so `PokeAllHosts()` 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 logs `agent-plane poke enabled`.
|
|
- **ep0 poke surface installed live** (additive; `felhom-peersync` authorized_keys 2→3 lines,
|
|
peersync/tenantsync UNCHANGED; `/usr/local/bin/felhom-poke` 0755; `Secret/agent-poke` holds 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.8` AND `rm -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.
|