Commit graph

2 commits

Author SHA1 Message Date
6d52b3c623 provisioning-reconciler-demo: wire-announce readiness + --docker node kind
Replace the per-attempt key-file side channel (DEMO_NODE_KEY_FILE,
read_key_report, JoinCheck) with a control-plane announce: node roles
send a tagged gossip frame {attempt, logical_node, key_hex,
endpoint_addr_json} after joining and every heartbeat thereafter.

- iroh-driver: IrohDriver::send_tagged_gossip — fire-and-forget
  tag-routed gossip egress for bridge-less clients (reuses cached/join
  connections, dials with backoff).
- provisioning: BootstrapMsg::Announce — first delivery while
  bootstrapping completes the attempt (collector + exactly-once
  Bootstrapped report); duplicates, misrouted attempts, and
  terminal-phase announces drop. Unit-tested.
- xtask demo: AnnounceActor decodes the tag-routed frame and forwards
  by attempt to the owning bootstrap actor; last_announce_ms is the
  wire heartbeat. LocalProcessLogic keeps only process lifecycle.
- --docker: DockerProcessLogic (kind "docker") — attached
  "docker run --rm" child on a per-run labeled bridge network
  (foreign-node masking: per-container IPs, gateway-dialed
  supervisor). Standalone scratch image from the static-musl xtask
  binary (37MB), staged one-file build context. The container is
  force-removed on every terminal path so a SIGKILLed docker CLI
  cannot orphan a running container.
- Cleanup: no volumes/mounts; label-filtered exit sweep (SIGINT and
  SIGTERM both drain first) + startup sweep of stale demo resources;
  images persist per run token.

Verified live: process kind (kill -> replacement in 3.4s, provision/
remove/kill waves, zero orphans) and docker kind (8-node abuse waves
across docker kill, mid-provision control kills, CLI SIGKILL orphans
force-removed, SIGKILL-crash leftovers swept on restart, clean exits
leave zero containers/networks/CLIs). provisioning 22 + iroh-driver
13 tests pass.
2026-08-16 20:34:15 +04:00
d19dd91324 feat(xtask): provisioning-reconciler-demo with live fleet control
`cargo xtask provisioning-reconciler-demo [--port n] [--nodes n]` boots a
lightweight orchestrator for visual, human-checked E2E confirmation of the
provisioning reconciler: swactor engine + real ClusterDriver + demo
provider, with node children re-exec'ing the same xtask binary in node
role and joining the supervisor over real iroh connections.

- supervisor actor owns driver/provider/shape on a 250ms wall-clock tick,
  mirroring the production ClusterReconciler poll semantics; emits
  prov.reconciler.events/snapshot plus per-node lifecycle/status streams
- k8s-styled reconciler view: ready/desired header, node stage cards,
  commands-out and events-in feeds
- dashboard `demo-control` feature: POST /control/{kill,provision,remove}
  + Fleet Control view; regular builds compile none of it (symbol-verified)
- fleet cards fold proc.<node>.lifecycle and node.status heartbeats into
  per-node pid/state pills that stay live
- hardening: exe resolution survives binary replacement by rebuilds,
  spawn failures feed back as BootstrapFailed so the reconciler retries
  instead of wedging at SshReady, teardown skips exit waits for
  never-started children

Verified in-browser: boot 3/3 converged with real joins; dashboard kill
dips and fully recovers with a replacement; provision +1 → 4/4; remove −2
graceful teardown → 2/2; child process count matches reconciler nodes.
2026-08-15 18:11:33 +04:00