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

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; 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.