wgtunnel: S3 Part 2 — manager state machine + loop + desired raw-consumer seam
Manager: one-shot registration (marker gate; backoff cap 15m), adopt-lost-marker, re-key-on-mismatch, REVOKED-STAYS-REVOKED teardown (marker kept, zero execs on later ticks), no-teardown-on-absent-data, hash-gated apply (zero execs steady state), restart-not-reload on conf change, self-heal enable. Status stanza with latest-handshakes-ONLY wg read. Collector WireguardReporter seam. desired.Syncer AddConsumer fan-out with panic containment. Red-proofs a/b/d run + reverted; no-key-material-in-logs asserted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -49,6 +49,12 @@ type PBSReporter interface {
|
||||
PBSSnapshots(ctx context.Context) []PBSSnapshot
|
||||
}
|
||||
|
||||
// WireguardReporter is the S3 seam the wgtunnel loop plugs into (same consumer-side pattern —
|
||||
// hub does not import wgtunnel). nil (feature disabled) → no wireguard stanza on the report.
|
||||
type WireguardReporter interface {
|
||||
WireguardStatus(ctx context.Context) *WireguardStatus
|
||||
}
|
||||
|
||||
// Collector builds a HostReport from read-only sources. All deps are behind narrow
|
||||
// interfaces for unit testing.
|
||||
type Collector struct {
|
||||
@@ -61,6 +67,7 @@ type Collector struct {
|
||||
temp TempReader // slice 9: host CPU/chassis temp (nil-safe → nil temp)
|
||||
capProbe func(ctx context.Context) []capability.Status // v0.44.0: privileged-capability self-check (nil → empty)
|
||||
leafFP string // v0.48.0: served local-API leaf fp (static per process; "" when local API disabled)
|
||||
wg WireguardReporter // S3: offsite-tunnel status (nil → stanza omitted)
|
||||
hostID string
|
||||
agentVersion string
|
||||
logger *slog.Logger
|
||||
@@ -110,6 +117,13 @@ func (c *Collector) SetLeafFingerprint(fp string) *Collector {
|
||||
return c
|
||||
}
|
||||
|
||||
// SetWireguardReporter wires the offsite-tunnel status source (S3; nil-safe → stanza omitted).
|
||||
// Returns the collector for chaining.
|
||||
func (c *Collector) SetWireguardReporter(w WireguardReporter) *Collector {
|
||||
c.wg = w
|
||||
return c
|
||||
}
|
||||
|
||||
// Collect builds the report. Best-effort liveness: a failed NodeStatus is a hard
|
||||
// error (no useful report — the cycle skips the POST); a failed per-guest
|
||||
// GuestConfig degrades that guest to status="unknown" without spec but still sends;
|
||||
@@ -143,6 +157,11 @@ func (c *Collector) Collect(ctx context.Context) (*HostReport, error) {
|
||||
// DR recipe host-half — derived from the just-collected guest/storage/PBS facts (no new reads).
|
||||
// Secret-free by construction (identifiers/intents/sizes/coordinates only).
|
||||
report.DRRecipe = BuildDRRecipeHostHalf(report.Guests, report.StorageTargets, report.PBSSnapshots)
|
||||
// S3: offsite-tunnel status stanza (nil reporter = feature disabled → omitted; the pubkey in
|
||||
// it is the operator's revocation-recovery handle).
|
||||
if c.wg != nil {
|
||||
report.Wireguard = c.wg.WireguardStatus(ctx)
|
||||
}
|
||||
return report, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user