diff --git a/docs/bulletproof-containers.md b/docs/bulletproof-containers.md index 737aca90..f75e845e 100644 --- a/docs/bulletproof-containers.md +++ b/docs/bulletproof-containers.md @@ -1,9 +1,25 @@ # Bulletproof Containers -**Status**: historical design record — the plan below (agreed 2026-04-22) has -been implemented. For the current description of how the lifecycle works, read -[Container lifecycle](container-lifecycle.md); this document is kept for the -incident history and the reasoning that produced the design. +**Status**: historical design record (agreed 2026-04-22). The *architecture* — +level-triggered, desired-state reconciliation — was adopted and is live. Several +specifics below were not built as written, so read this for the incident history +and the reasoning, not as a description of the code. For how the lifecycle +actually works today, read [Container lifecycle](container-lifecycle.md). + +What became of the plan, verified against the tree: + +| Item | Outcome | +|---|---| +| Level-triggered reconciler | ✅ Shipped, but as `container/boot_reconciler.rs` + `container/prod_orchestrator.rs`. The `core/archipelago/src/reconcile/` module laid out below (`desired.rs`/`current.rs`/`diff.rs`/`apply.rs`/…) **was never created** — no file in it exists | +| FM5 post-OTA probe + auto-rollback | ✅ Shipped — `update-pending-verify.json` (`update.rs:100`) | +| FM4 `host.archipelago` alias | ✅ Shipped — `AddHost=host.archipelago:10.89.0.1` in generated units | +| FM1/FM3 Quadlet ownership | ◐ Partial. Companion UIs run as Quadlet units; **main app containers do not** — `use_quadlet_backends` still defaults false, so the "v1.7.48+ full migration" below has not happened | +| FM2 bitcoin.conf drift | ◐ Solved differently. There is no `reconcile::derived::render_bitcoin_conf`; instead bitcoind is run with an explicit `-conf` derived from secrets at each start and stale datadir configs are removed (`remove_stale_bitcoin_conf`) | +| FM6 podman corrupt-state self-heal | ❌ **Not implemented.** No `podman system renumber` recovery, no startup probe for "invalid internal status". The failure that made a node unreachable in 2026-04 would still need manual SSH | + +Note also that the unit paths below say `/etc/containers/systemd/`; units are +actually written per-user to `~/.config/containers/systemd/` +(`quadlet.rs:DEFAULT_REL_UNIT_DIR`), since the whole path is rootless. **Target**: zero-manual-intervention container lifecycle. A user installs, uninstalls, reboots, updates, or loses power — every combination must leave the