v0.89.0: pbsdr self-grant (R-22) + escrow config live-reload + agent-plane poke listener (Direction-2a)

- pbsdr: on a 403 pre-check (non-default storage id, no ACL yet) self-grant via the root wrapper then re-read, instead of aborting before the grant — closes F4/R-22. Red-proof TestSelfGrant_PreCheck403DoesNotAbortBeforeGrant.
- escrow preflight: late-bound CurrentPBSStorageID re-reads agent.json so a pbsdr-seeded pbs_storage_id flips the row green in-process (no restart). Red-proof TestEscrowPreflight_PBSStorageIDLiveReload.
- internal/poke: contentless UDP poke listener bound exclusively to the box WG /32 (port 51822), leading-edge debounced, fires the hub-loop out-of-band trigger for an immediate desired-state cycle. First slice of R-13. Red-proofs TestBindConfinement + TestDebounceCoalescesBurst.
This commit is contained in:
2026-07-16 22:47:22 +02:00
parent c040c180e9
commit a659e5dc09
11 changed files with 643 additions and 15 deletions
+18 -3
View File
@@ -34,8 +34,17 @@ import (
type EscrowCeremonyConfig struct {
// SudoPath is the sudo binary ("" → "sudo").
SudoPath string
// PBSStorageID is cfg.Escrow.PBSStorageID ("" = not configured — preflight red).
// PBSStorageID is cfg.Escrow.PBSStorageID at daemon-start ("" = not configured — preflight
// red). It is the FALLBACK snapshot; the live value is CurrentPBSStorageID when wired.
PBSStorageID string
// CurrentPBSStorageID, when set, is called at preflight time to read the LIVE
// escrow.pbs_storage_id. The pbsdr bridge SEEDS this key into agent.json on DR convergence
// (finishConverged → seedEscrowStorageID); a static snapshot taken at daemon start would then
// stay red until a service restart (v0.89.0 live-reload). The wired closure re-reads config
// from disk — exactly what the ceremony subprocess itself loads — so the preflight reflects the
// real state the bare `--selftest=escrow-create` one-liner will see. nil → the PBSStorageID
// snapshot is used (old wiring / tests).
CurrentPBSStorageID func() string
// HubConfigured: hub url + host id + api key all present (the --upload target).
HubConfigured bool
// DRConfigured answers "is the DR tier applied on this box?" (pbsdr.Manager.DRConfigured,
@@ -362,8 +371,14 @@ func (s *Server) handleEscrowPreflight(w http.ResponseWriter, r *http.Request, v
}
items := make([]item, 0, 6)
items = append(items, item{ID: "pbs_storage_id", OK: cfg.PBSStorageID != "",
Detail: map[bool]string{true: cfg.PBSStorageID, false: "escrow.pbs_storage_id not configured"}[cfg.PBSStorageID != ""]})
// Live-reload (v0.89.0): prefer the current on-disk value over the daemon-start snapshot, so a
// pbsdr convergence that just seeded escrow.pbs_storage_id flips this row green with no restart.
storageID := cfg.PBSStorageID
if cfg.CurrentPBSStorageID != nil {
storageID = cfg.CurrentPBSStorageID()
}
items = append(items, item{ID: "pbs_storage_id", OK: storageID != "",
Detail: map[bool]string{true: storageID, false: "escrow.pbs_storage_id not configured"}[storageID != ""]})
drOK := cfg.DRConfigured != nil && cfg.DRConfigured()
items = append(items, item{ID: "dr_tier", OK: drOK,