From 30972d8f5415dfe3324fb2719277d343c929cb97 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 17 Jul 2026 17:30:41 +0200 Subject: [PATCH] =?UTF-8?q?hub=20v0.63.0=20=E2=80=94=20system-initiated=20?= =?UTF-8?q?immediacy:=20wire=20poke/bump=20at=20every=20mutation=20site=20?= =?UTF-8?q?that=20lacked=20one?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The immediate-sync arc covered only operator-initiated desired-state changes; system-initiated mutations bumped the generation silently, so a freshly onboarded box waited a full agent tick for state the hub had already minted (observed live at slice-C onboarding). Wire the existing, live-proven notifiers into every system site on the correct plane — call-site wiring only, no new mechanism. Agent plane (poke.Notifier): - web/pbsdr.go: PBSDRAutoProvision (the observed lag), ReissuePBSDR (also lifts the pbsdrheal reconciler escalation, zero reconciler changes), handlePBSDRReissue — each pokes AFTER the successful SetHostDesired, never on a blocked/error path. - api: new nil-safe Poker seam (PokeHost/PokeAllHosts + SetPoker); handleAdminSetDesiredState pokes the target host; handleAdminSetOperatorPeer fires PokeAllHosts only when the fleet generation bump succeeded (fire-after-commit). - main.go: one poke.Notifier now feeds both planes (SetPoke + SetPoker). Controller plane (intent.Hub.Bump): - api/reissueOnReenroll: one nil-guarded bump so a long-polling controller wakes in seconds instead of on the 15-min cycle. Deliberate non-sites (unchanged): WG register (undeliverable pre-tunnel — the agent fast-tick SECONDARY owns it), WG delete (transport removed), pbsdrheal Restage (no generation bump → the 60s ticker is the pickup path). internal/pbsdrheal byte-unchanged. Tests: 10 non-hollow tests (web async channel-synchronized fake sender; api synchronous fake Poker) with explicit zero-count negatives; representative red-proofs per group (A/B/C/D) run-fail-restored. Green: go build/vet/test all pass. --- REUSE.md | 1 + hub/CHANGELOG.md | 36 +++++ hub/cmd/hub/main.go | 8 +- hub/internal/api/handler.go | 34 +++++ hub/internal/api/poke_seam_test.go | 132 +++++++++++++++++++ hub/internal/api/wg.go | 2 + hub/internal/web/pbsdr.go | 3 + hub/internal/web/pbsdr_poke_test.go | 197 ++++++++++++++++++++++++++++ 8 files changed, 411 insertions(+), 2 deletions(-) create mode 100644 hub/internal/api/poke_seam_test.go create mode 100644 hub/internal/web/pbsdr_poke_test.go diff --git a/REUSE.md b/REUSE.md index b7776ea..dfe23b3 100644 --- a/REUSE.md +++ b/REUSE.md @@ -131,6 +131,7 @@ | Web POST action | hub/internal/web/configs.go `handleSetGlobalFloor` (~L602) | CSRF enforced centrally in web ServeHTTP; validate via `normalize*` helper; POST-redirect-GET with `?flash=` token; log INFO on success. | | Optional dependency injection | hub/internal/web/server.go `Set*` setters (~L131–148) / api handler `SetDispatcher` etc. | Constructor takes hard deps; optional subsystems wired via `SetX` after construction; nil = graceful degradation (never panic). | | Seam-injected sender for tests | hub/internal/notify/dispatcher.go `sendEmailFn` (~L33) | Function-field defaulting to the real impl in the constructor; tests overwrite it. Same idea: `mailRateLimiter.now`, `mailrelay.Sender` fake. | +| Immediate-sync notify (per plane) | agent plane: `poke.Notifier` (`web.Server.poke` / `api.Handler.poker` via `SetPoke`/`SetPoker`) — controller plane: `intent.Hub.Bump` (`web.Server.bumpIntent`, `api.Handler.intentHub`) | EVERY desired-state mutation fires the RIGHT plane's notifier AFTER the successful store write, never on an error path (fire-after-commit). Agent-plane pokes a HOST when its generation moved (`SetHostDesired`/`Bump*HostDesired`); controller-plane bumps a CUSTOMER on a controller-visible change. Both receivers COALESCE bursts — add NO hub-side dedup. Deliberate non-sites need a documented reason (undeliverable pre-tunnel, transport removed, or no generation bump → the 60 s ticker is the pickup path). Both seams nil-safe: unset = the ≤15-min cycle still reconciles. Full site inventory: REPORT.md audit table (v0.63.0). | | Website page | website/index.html | UTF-8 **with BOM**; shared `