docs(bulletproof-containers): say which parts of the plan actually shipped

Header claimed the whole 2026-04-22 plan "has been implemented". The
architecture was adopted, but checking each item against the tree:

- The `core/archipelago/src/reconcile/` module the doc lays out in detail —
  desired.rs / current.rs / diff.rs / apply.rs / derived.rs / backoff.rs — was
  never created. The reconciler shipped as container/boot_reconciler.rs +
  container/prod_orchestrator.rs instead.
- FM2's named fix `reconcile::derived::render_bitcoin_conf` does not exist. The
  drift was eliminated a different way: bitcoind runs with an explicit `-conf`
  derived from secrets each start, and stale datadir configs are removed.
- FM1/FM3 are partial — companion UIs are Quadlet units, main app containers are
  not, since `use_quadlet_backends` still defaults false. The "v1.7.48+ full
  reconcile module / main containers become Quadlet units" step has not happened.
- **FM6 was never implemented.** There is no podman corrupt-state probe and no
  `system renumber` recovery anywhere in the tree. The 2026-04 failure that made
  a registry node unreachable would still require manual SSH today — which is
  precisely the "zero-manual-intervention" target this doc opens with.

FM4 and FM5 did ship as described.

Replaced the blanket claim with a per-item table so the doc stays useful as
incident history without reading as a description of the code, and noted that
the unit path throughout says /etc/containers/systemd/ while units are actually
written to ~/.config/containers/systemd/ (the path is rootless).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-08 04:03:45 -04:00
co-authored by Claude Opus 5
parent 0b7fabdfa1
commit 7c214e6497
+20 -4
View File
@@ -1,9 +1,25 @@
# Bulletproof Containers # Bulletproof Containers
**Status**: historical design record — the plan below (agreed 2026-04-22) has **Status**: historical design record (agreed 2026-04-22). The *architecture*
been implemented. For the current description of how the lifecycle works, read level-triggered, desired-state reconciliation — was adopted and is live. Several
[Container lifecycle](container-lifecycle.md); this document is kept for the specifics below were not built as written, so read this for the incident history
incident history and the reasoning that produced the design. 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, **Target**: zero-manual-intervention container lifecycle. A user installs,
uninstalls, reboots, updates, or loses power — every combination must leave the uninstalls, reboots, updates, or loses power — every combination must leave the