diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 90e7e41c..9b0446b7 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -20,7 +20,7 @@ declared exit criteria (multinode pass + workstreams B/C/F), `.planning/codebase - [x] **FED-06**: On-brand payment success animation — the invoice "paid" tick's circle uses the screensaver-style ring with outer EQ-segment lines (reuse `ScreensaverRing.vue`'s compact size) in place of the current success burst, applied consistently everywhere the paid tick shows - [ ] **FED-08**: Lightning invoices created by the wallet embed route hints (LND `private` flag) so nodes whose channels are unannounced can actually receive payments — diagnosed on archy-x250-mad2 2026-07-31, where every wallet-UI invoice had `route_hints: []` and was unroutable; the bug is unconditional and affects any node without a public channel - [ ] **FED-09**: The container doctor does not restart Tor on every run — it recognises Tor's own setgid `2700` hidden-service directory mode as correct rather than "fixing" it to `700` and restarting, a loop that reset Tor every ~5 minutes, starved it of its consensus/HSDir cache (`No more HSDir available to query`), and broke the mesh's Tor fallback entirely; genuinely permissive modes are still corrected, and a restart backoff makes the failure class non-recurring -- [x] **FED-07**: Fedimint gateway never installs with a pre-set password — gateway credentials are generated per-install via manifest-declared `generated_secrets` (or explicitly set by the user), never baked into the image/manifest; existing installs with the default password get a migration path (BLOCKER — default credentials are a security hole) +- [ ] **FED-07**: Fedimint gateway never installs with a pre-set password — gateway credentials are generated per-install via manifest-declared `generated_secrets` (or explicitly set by the user), never baked into the image/manifest; existing installs with the default password get a migration path (BLOCKER — default credentials are a security hole) ### UI Fixes (UIFIX) — user-reported blockers, added 2026-07-30 @@ -112,7 +112,7 @@ Which phases cover which requirements. Updated during roadmap creation. | FED-04 | Phase 1 | Complete | | FED-05 | Phase 1 | Pending | | FED-06 | Phase 1 | Complete | -| FED-07 | Phase 1 | Complete | +| FED-07 | Phase 1 | Code complete, on-node verification pending (01-16 Task 2) | | FED-08 | Phase 1 | Pending | | FED-09 | Phase 1 | Pending | | UIFIX-01 | Phase 1 | Pending | diff --git a/.planning/todos/pending/2026-08-01-verify-fed07-gateway-credential-rotation-on-node.md b/.planning/todos/pending/2026-08-01-verify-fed07-gateway-credential-rotation-on-node.md new file mode 100644 index 00000000..83bc34f4 --- /dev/null +++ b/.planning/todos/pending/2026-08-01-verify-fed07-gateway-credential-rotation-on-node.md @@ -0,0 +1,80 @@ +--- +created: 2026-08-01T09:45:00.000Z +title: Verify FED-07 gateway credential rotation on a real node (01-16 Task 2) +area: security +severity: major +files: + - core/archipelago/src/container/secrets.rs + - core/archipelago/src/container/prod_orchestrator.rs + - .planning/phases/01-federation-mesh-hardening/01-16-PLAN.md +--- + +## Problem + +FED-07's code is complete and pushed (`42652547` removed every shipped credential, +`9e2d2ef2` added detection + rotation for nodes already carrying one), but **plan 01-16's +blocking Task 2 checkpoint has never been run**, so the requirement is not closed. Two +things are unproven: + +1. **That the recreate actually preserves the gateway's data.** Rotation deliberately + avoids any teardown: it changes the credential, which changes `secret_env_hash`, which + the drift check reads as a container-label mismatch, which fires the platform's own + recreate around the unchanged data directory, ports, volumes and container name. That + chain is confirmed by reading the code (`prod_orchestrator.rs:3309` computes the hash, + `:3374` compares the label) but has **never been observed running**. +2. **That the rotated credential actually authenticates** and the old shipped one is + rejected. + +## Why it was deferred (2026-08-01) + +Checkpoint step 1 was run read-only on archi-dev-box. Findings: + +- **The node is CLEAN** — the hash file is present, `600`, `archipelago:archipelago`, and + is *not* the shipped default. The legacy `fedimint-gateway-password` file also exists. +- **There is no `fedimint-gateway` container.** The app is installed at + `/opt/archipelago/apps/fedimint-gateway`, but nothing is running and + `/var/lib/archipelago/fedimint-gateway` is empty. `archy-fedimint-ui` and + `fedimint-clientd` are running, but they are not the gateway. + +So the rotation path cannot fire naturally here, and steps 5–6 (data survived, gateway +authenticates) have nothing to exercise. Proving it on this box means installing and +starting the gateway first, then deliberately seeding the old value — which the plan's +Planner Assumption already anticipates and requires be recorded. + +The deploy itself is the blocker: **30 containers are running with 4–8 days uptime** +(IndeeHub relay/minio/postgres/ffmpeg, Immich, BTCPay + nbxplorer, netbird, portainer, +strfry, searxng, the archy UI set), the `archipelago` system service is active, and +CLAUDE.md's standing rule is that restarting it SIGKILLs containers until Quadlet is the +default. Step 8 then wants `tests/lifecycle/run-gate.sh` on the same box, which cycles +install/stop/start/reinstall/reboot-survive. Dorian chose to hold rather than take that +blast radius unattended. + +## Solution + +Run 01-16 Task 2's eight steps in a window where restarting `archipelago` on the target is +acceptable. Two viable routes: + +- **On archi-dev-box:** install + start `fedimint-gateway`, put some state in its data + directory, seed the old hash into + `/var/lib/archipelago/secrets/fedimint-gateway-hash`, deploy this build, restart, then + run steps 3–8. Record that the affected state was seeded deliberately. +- **On a node that runs the gateway for real** (.228 is the heavy 14-app node): the + rotation path may exist naturally there, which is stronger evidence than seeding. + +Either way, record in `01-16-SUMMARY.md`: the affected-or-clean verdict, the exact deploy +command, whether the `secret_env_hash` recreate was observed firing, the gate result, and +the fact that archy-x250-dev was offline (single-node verification with the second-node +gap recorded honestly is the expected pattern). + +## Related, found while doing 01-16 + +- **Operator recovery gap:** `handle_package_credentials` + (`core/archipelago/src/api/rpc/package/install.rs:2093`) is a hardcoded if-chain covering + only `filebrowser` and `photoprism`. `fedimint-gateway` falls through to an empty list, + so after a rotation the operator has no in-UI way to get the new password — only the + `0600` file the log line names. Adding one arm closes it; the UI already renders whatever + the RPC returns. +- **`apps/photoprism/manifest.yml:35` ships `PHOTOPRISM_ADMIN_PASSWORD=archipelago`**, and + that same literal is handed to the UI. Same defect class as FED-07 on a different app — + wants its own requirement. +