Skip to content

fix(app): wire the add-vault chooser + wizard escape hatches + friendly errors (F2/F6/F12/F13/F18) - #10

Merged
unforced merged 1 commit into
mainfrom
app-nav-escapes
Jul 11, 2026
Merged

fix(app): wire the add-vault chooser + wizard escape hatches + friendly errors (F2/F6/F12/F13/F18)#10
unforced merged 1 commit into
mainfrom
app-nav-escapes

Conversation

@unforced

Copy link
Copy Markdown
Contributor

Summary

Fixes a cohesive set of "you can't get back / dead-end" navigation bugs the owner flagged in the app's experiential audit (findings F2, F6, F12, F13), plus a stale doc (F18). These are the clear, redesign-independent fixes — an escape hatch is never the wrong call in any future IA. Explicitly out of scope: the history/replace policy rewrite (F7), the IA redesign (F14/F15), and notes-anatomy work (F8/F9/F10) — those wait for the owner's larger plan.

F2 — the orphaned add-vault chooser is wired in

/vaults's "Add vault" buttons (header + empty-state) pointed at /add — the self-hosted connect URL form, a dead-end for a cloud user (no path to "create", no way back). Both now open /add-vault (AddVaultChooser.tsx), the purpose-built Open/Create/Connect chooser that had zero inbound links anywhere in the app until now. /add stays exactly what it was — the leaf the chooser's "Connect a self-hosted vault" card targets.

Checked VaultPopover.tsx per the brief's example: it has no separate generic "add vault" affordance of its own — its only pointer is "Manage vaults →" → /vaults, which this fix already makes correct transitively. No changes needed there.

F13 — the chooser's "Open" card no longer silently reopens your only vault

Chooser "Open" → /welcome; with exactly one account vault, the dispatcher's classifyVaults auto-runs the welcome-back beat and reopens the vault you're likely already in. Fixed per the plan: the card now links to /welcome?pick=1, and the dispatcher forces the picker whenever ?pick=1 is present and the account has ≥1 vault (falls through to first-vault naming when it has zero).

F6 — the wizard screens have a way out

  • Wordmark (ParachuteMark.tsx) is now a real <Link to="/"> everywhere it renders. Verified every call site first (Landing, Welcome, AddVault, AddVaultChooser, CheckEmail, OAuthCallback) — all six are full-screen wizard Shells with no active vault, so none of them have any other chrome (Rail returns null, Header is lg:hidden). Linking the shared component covers all of them at once; no separate linked variant needed.
  • Added an explicit quiet "← Back" beside the Wordmark on: the vault-naming form (Welcome.tsx, backs up to /add-vault for an add-vault naming or / for first-vault onboarding), the self-hosted connect form (AddVault.tsx, backs up to /), the add-vault chooser (AddVaultChooser.tsx, backs up to /vaults when a vault's already active on this device, else /), and /check-email (backs up to /).
  • Flagged finding: CreationBeatView's error branch (the "Something went sideways" full-screen card, Welcome.tsx around the old :519-537) is pre-existing unreachable dead code — the actual creation-failure catch transitions back to the naming stage (inline error banner on the SAME form, preserving the typed name), never to a creating-kind stage with its own error set. So the literal "Never mind on the creating-error card" ask doesn't apply to a screen that ever renders; the naming form's new Back link is the real escape hatch for that path (left a code comment explaining this; reconciling the dead branch is a separate cleanup, not a nav fix).

F12 — friendly error copy

Root cause: client.ts's jsonOrThrow preferred the server's machine error code over its accompanying friendly message (cloud's account-api.ts restError sends both — e.g. {error: "vault_taken", message: "That vault name is already taken."}) — a plan-limit hit rendered as a bare vault_limit_reached. Swapped the precedence (verified this doesn't break markHubGateFromError's hub-gate check, which compares against a shape that has no message field at all). Added lib/account/error-copy.ts (describeAccountError) as belt-and-suspenders: maps known bare codes to calm copy, generic fallback for unknown ones — covers what the root-cause fix doesn't (an older/self-hosted response with no message). Wired into the vault-naming creation error and Account.tsx's VaultsBlock.open error.

F18 — STYLE.md rewritten against the real palette

Was documenting the retired forest-green identity (#4a7c59/#7ab087); index.css has been the coral brand pass (#bf4a2a/#e05d3c, grass/sun/sage) for a while. Rewrote against the actual tokens + component classes, including the arrival/wizard classes added since (.tile, .composer, .hero-title, .nudge-sun, .note-row, .drop-in/.fade-up) that weren't documented anywhere. Doc-only.

Gates (literal counts)

  • bunx vitest run1284 passed, 0 failed (126 test files)
  • bun run typecheck — clean, no errors
  • bunx biome check .0 errors, 2 warnings (pre-existing useExhaustiveDependencies in src/lib/vault/live-query.ts, a file this PR never touches — confirmed via git diff --stat showing no diff)
  • bun run build — succeeds (pre-existing chunk-size + dynamic/static-import-mix advisories, unrelated to this diff)

Version bump 0.4.1 → 0.4.2 (package.json), CHANGELOG entry added.

Test plan

  • New/updated tests for every finding: Vaults.test.tsx (F2 routing), AddVaultChooser.test.tsx (F13 ?pick=1 + Back link), Welcome.test.tsx (F13 picker-forcing, F6 Back links, F12 friendly copy), AddVault.test.tsx / CheckEmail.test.tsx (F6 Back links), client.test.ts + new error-copy.test.ts (F12 precedence fix + mapping)
  • Self-reviewed the diff; an independent reviewer will run before merge (per workspace governance)
  • Aaron: merge when ready (no auto-merge)

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01XLZtmuSs1RirWGMGyCB1QB

…ly errors (F2/F6/F12/F13/F18)

Owner-flagged "can't get back / dead-end" navigation bugs from the app audit,
plus a stale doc — all redesign-independent so they land ahead of the coming
IA rework:

- F2: /vaults' "Add vault" (header + empty-state) now opens the purpose-built
  add-vault chooser (/add-vault) instead of the self-hosted connect form
  (/add), which had no path to "create" and no way back for a cloud user.
- F13: the chooser's "Open" card links to /welcome?pick=1, forcing the picker
  instead of silently reopening the account's one vault.
- F6: the Wordmark is a real Link to "/" everywhere it renders (every
  full-screen wizard screen shares it), plus an explicit "← Back" on the
  vault-naming form, the self-hosted connect form, the chooser, and
  /check-email — screens that previously had zero chrome and no exit but the
  browser Back button.
- F12: jsonOrThrow now prefers the server's friendly `message` over its bare
  `error` code; a new describeAccountError() belt-and-suspenders maps known
  codes to calm copy for what that doesn't cover (vault-creation and
  vault-open failures).
- F18: STYLE.md rewritten against the live coral palette in index.css (it
  documented the retired forest-green identity).

Version bump 0.4.1 -> 0.4.2, CHANGELOG entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XLZtmuSs1RirWGMGyCB1QB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant