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>
8.9 KiB
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
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 (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
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
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
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:
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;
pamtestersmoke 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.