Files
authforge/docs/plans/2026-04-27-parallel-fanout-9-10-11.md
michael d20643cde5 docs(plan): coordinator + 3 step-level plans for parallel Phase 9/10/11 fan-out
Ships four documents:
  * 2026-04-27-parallel-fanout-9-10-11.md — coordinator. File-conflict map,
    prep-lane scope rationale, post-prep parallel-safety guarantee, merge
    order rule, and risks.
  * 2026-04-27-prep-shell-and-pending.md — small ~1hr prep lane: extract
    AppContext, add --first-run flag scaffold (with stub firstrun::run),
    add daemon GetPendingStatus D-Bus method + GUI client wrapper, new
    PendingStatus wire type. 6 tasks, single agent.
  * 2026-04-27-phase-10-firstrun.md — first-login flow. Fullscreen modal,
    60s idle watchdog (TDD'd as pure WatchdogState), enrollment via Phase
    8 enroll_dialog, ClearPendingFlag on success, gnome-session-quit on
    idle, autostart .desktop entry, debian install. 6 tasks.
  * 2026-04-27-phase-11-totp.md — TOTP support behind default-on Cargo
    feature. Daemon-side: 160-bit secret + base32 + otpauth URI + atomic
    0600 writes in pam_google_authenticator format. PAM profile renderer
    extension. D-Bus surface. CLI subcommand. GUI tab with QR modal.
    Deviation flagged: TOTP recovery codes reuse the Phase 12 recovery
    flow rather than introducing a parallel hashed-recovery file format.
    9 tasks.

Execution model: prep lane first (single agent ~1hr), then dispatch three
subagents in parallel worktrees for the three follow-on lanes. Per the
conflict map, the lanes are file-disjoint after prep merges; merge order
is any-order.

If all four lanes land cleanly, the roadmap jumps from 13/19 to 17/19
phases code-complete in a single session, leaving Phase 13 (deb finalization),
14 (PPA + smoke), 17 (integration tests), 18 (user docs), and the v1.0
release tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 10:28:23 -07:00

142 lines
8.9 KiB
Markdown

# Parallel-Fan-out Strategy: Phases 9 + 10 + 11 (and the Phase 12 GUI tab)
> **For Claude:** This is a coordinator document, not an implementation plan. Each lane it points to has its own step-level plan that uses `superpowers:executing-plans`. Run the prep lane first; then the three follow-on lanes can execute concurrently in their own worktrees.
**Goal:** Land Phases 9, 10, 11, and the Phase 12 GUI tab as quickly as possible by maximizing concurrent work across worktree-isolated agents.
**Reality:** The naive "three worktrees, all branched off main" approach hits a hard wall — every lane wants to edit `gui/src/main.rs`, two of them want to edit `daemon/src/{dbus,state}.rs`, and at least one tab will need plumbing through `gui/src/bus.rs`. A direct fan-out merges sequentially in practice because every lane has a `main.rs` conflict to resolve.
**Strategy:** A small **prep lane** establishes shared scaffolding — `AppContext`, the `--first-run` flag branch in `main.rs`, and the daemon's pending-flag query D-Bus methods — *before* the fan-out. After prep merges, the three follow-on lanes are file-disjoint and merge in any order.
---
## Conflict map (no prep)
| File | Phase 9 + 12-GUI | Phase 10 (first-login) | Phase 11 (TOTP) |
|---|:---:|:---:|:---:|
| `gui/src/main.rs` | adds `Policy` + `Recovery` ViewStack tabs | adds `--first-run` flag + alternate startup branch | adds `TOTP` ViewStack tab |
| `gui/src/bus.rs` | adds 5 policy/recovery methods | adds 1 pending-status method | adds ~3 TOTP methods |
| `gui/src/keys_page.rs` | constructor migrates to `AppContext` | — | — |
| `gui/src/app_context.rs` | **creates** | reads | reads |
| `daemon/src/dbus.rs` | — | adds `GetPendingStatus` | adds 3 TOTP methods |
| `daemon/src/state.rs` | — | promotes `has_pending` out of `#[cfg(test)]` | adds TOTP enrollment surface |
| `daemon/src/policy_apply.rs` | — | — | renders `pam_google_authenticator.so` when TOTP required |
| `common/src/types.rs` | — | adds `PendingStatus` wire type | adds `TotpEnrollment` + `TotpRecoveryCodes` wire types |
| `daemon/Cargo.toml` | — | — | adds `totp` feature, `totp-rs`, `data-encoding` deps |
| `Cargo.toml` workspace | — | — | adds `totp-rs`, `data-encoding`, `qrcode` to `[workspace.dependencies]` |
| `gui/Cargo.toml` | — | — | adds `qrcode` (feature-gated) |
| `debian/control` | — | maybe (Depends) | adds `Recommends: libpam-google-authenticator` |
| `gui/src/firstrun.rs` | — | **creates** | — |
| `gui/src/totp_page.rs` | — | — | **creates** |
| `gui/src/policy_page.rs` + `recovery_page.rs` | **creates** | — | — |
| `daemon/src/totp/mod.rs` | — | — | **creates** |
**Read:** four files (`gui/src/main.rs`, `gui/src/bus.rs`, `daemon/src/dbus.rs`, `daemon/src/state.rs`) collide across two or three lanes. Without prep, every fan-out merge resolves them by hand.
## Conflict map (with prep lane in place)
After the prep lane lands the shared scaffolding:
| File | Phase 9 + 12-GUI | Phase 10 | Phase 11 |
|---|:---:|:---:|:---:|
| `gui/src/main.rs` | adds 2 lines (tab registrations) | **untouched** — uses prep's `--first-run` branch | adds 1 line (tab registration) |
| `gui/src/bus.rs` | adds 5 methods (additive) | **untouched** — prep has the pending methods | adds 3 methods (additive) |
| `daemon/src/dbus.rs` | — | **untouched** — prep has `GetPendingStatus` | adds 3 methods |
| `daemon/src/state.rs` | — | **untouched** — prep promoted `has_pending` | adds TOTP methods |
| `gui/src/app_context.rs` | reads | reads | reads |
**Read:** the only remaining `main.rs` collisions are tab-registration lines from Lane A and Lane C — those slot into the same ViewStack but on disjoint lines and resolve trivially. All three lanes can land in any order.
---
## The four lanes
### Prep lane (single-agent, ~1 hr wall-clock)
**Plan:** [2026-04-27-prep-shell-and-pending.md](2026-04-27-prep-shell-and-pending.md)
Establishes the cross-cutting infrastructure. Drops Task 1 from the existing Phase 9 plan (AppContext refactor moves here). Adds the daemon's `GetPendingStatus` D-Bus method that Phase 10 needs. Adds `--first-run` flag parsing + a stub `firstrun::run()` so Phase 10 fills it without re-touching `main.rs`.
**Acceptance gate:** workspace tests pass, the `--first-run` flag is parseable but no-ops with a placeholder, the new D-Bus methods round-trip through the p2p test fixture.
**MUST land first.** All three follow-on lanes branch off the merge of prep into main.
### Lane A — GUI policy + recovery (Phase 9 + Phase 12 GUI tab)
**Plan:** [2026-04-27-phase-9-and-12-gui.md](2026-04-27-phase-9-and-12-gui.md) (already written — pre-merge of prep, drop Task 1).
**File footprint:** `gui/src/{policy_form,policy_page,recovery_page}.rs` (new), additive `gui/src/bus.rs` policy + recovery methods, two `add_titled_with_icon` lines in `main.rs`, optional `keys_page.rs` ToastOverlay tweak.
### Lane B — First-login flow (Phase 10)
**Plan:** [2026-04-27-phase-10-firstrun.md](2026-04-27-phase-10-firstrun.md)
**File footprint:** `gui/src/firstrun.rs` (new — fills the prep stub), `gui/data/authforge-firstrun.desktop` (new autostart), `debian/authforge-gui.install` (install autostart entry).
### Lane C — TOTP support (Phase 11)
**Plan:** [2026-04-27-phase-11-totp.md](2026-04-27-phase-11-totp.md)
**File footprint:** `daemon/src/totp/mod.rs` (new), additions to `daemon/src/{state,dbus,policy_apply}.rs`, `daemon/Cargo.toml` feature flag, `gui/src/totp_page.rs` (new), one `main.rs` tab line, `common/src/types.rs` (two new wire types), `debian/control`, workspace + GUI `Cargo.toml`.
---
## Execution model
### Prep lane
```bash
git worktree add .claude/worktrees/prep-shell-and-pending -b feature/prep-shell-and-pending
cd .claude/worktrees/prep-shell-and-pending
# follow 2026-04-27-prep-shell-and-pending.md task-by-task
# tests + clippy + fmt + release build green
# merge --no-ff back to main
git worktree remove .claude/worktrees/prep-shell-and-pending
git branch -d feature/prep-shell-and-pending
```
### Three concurrent follow-on lanes
After prep merges, dispatch three subagents in parallel via `superpowers:dispatching-parallel-agents`:
```text
Subagent 1 (worktree feature/phase-9-and-12-gui):
→ executes 2026-04-27-phase-9-and-12-gui.md (skip Task 1, prep handled it)
Subagent 2 (worktree feature/phase-10-firstrun):
→ executes 2026-04-27-phase-10-firstrun.md
Subagent 3 (worktree feature/phase-11-totp):
→ executes 2026-04-27-phase-11-totp.md
```
Each lane verifies tests + clippy in its own worktree before reporting. Once all three return green, merge them serially into main in any order. The `gui/src/main.rs` ViewStack-tab additions from Lane A and Lane C may produce a 1-line conflict per merge — resolve by including both tab lines.
### Merge order rule
**Any order works.** The conflict on `gui/src/main.rs` is bounded to "both lanes added a tab line in the same area." Resolve by keeping both. No semantic interaction.
---
## Risks
| Risk | Mitigation |
|---|---|
| Prep lane mis-defines the `AppContext` shape and Lane A's plan needs revision. | Lane A's plan is already in this repo and was written assuming the AppContext shape that prep will land. Prep mirrors the structure verbatim — see prep Task 1. If prep's Task 1 deviates, update Lane A's plan in the same commit. |
| Concurrent `cargo` runs across three worktrees race on `~/.cargo/registry` lock. | Brief synchronization (per Phase 4+5 closeout note), not a hang. Acceptable. |
| Phase 11 introduces a `totp` Cargo feature that's default-on; CI must build with feature off too. | Add a `cargo build --workspace --no-default-features` line to the CI workflow as part of Lane C's Task 1. |
| Lane B's `--first-run` runtime behavior depends on a daemon that's running. | Watchdog keeps the modal alive 60s; if no daemon, the modal logs and exits gracefully (mirrors Phase 8's disconnect-banner pattern). Spelled out in Phase 10 Task 4. |
| Lane C's `pam_google_authenticator.so` must already be installed for the rendered profile to validate. | `debian/control` lists it as `Recommends:`, not `Depends:` — installing the daemon doesn't pull it in unless the user opts in. Daemon's `policy_apply::apply` uses the existing rollback path if `pam-auth-update` rejects the profile. |
| Three subagents producing simultaneous output saturates the main session's context. | Subagents run with `report in under 200 words` instructions in their dispatch prompts; details live in commit messages. |
---
## Once-fully-landed roll-up
After all four lanes merge:
- Phase 9: ✅ Code complete (GUI smoke deferred to Phase 14)
- Phase 10: ✅ Code complete (full-flow VM smoke deferred to Phase 14)
- Phase 11: ✅ Code complete (TOTP enrollment + recovery codes; `pamtester` smoke deferred to Phase 14)
- Phase 12: ✅ Done (backend, GUI tab, end-to-end CLI all in)
**Roadmap progress** jumps from 13/19 to **17/19** in the same session, leaving only Phase 13 (deb finalization), 14 (PPA + smoke), 17 (integration tests), 18 (user docs), and the v1.0 release tag.