Skip to content

feat(auth): /accounts routes — list, switch, remove (slice 3, PR 2/3)#116

Merged
stuffbucket merged 1 commit into
mainfrom
feat/account-routes
Jun 11, 2026
Merged

feat(auth): /accounts routes — list, switch, remove (slice 3, PR 2/3)#116
stuffbucket merged 1 commit into
mainfrom
feat/account-routes

Conversation

@stuffbucket

Copy link
Copy Markdown
Owner

What

PR 2 of 3 for slice 3 — multi-account persistence + quick-switch. The backend for quick-switch over the registry that PR 1 (#115) introduced. No UI yet — these endpoints are inert until PR 3 wires the picker.

New src/routes/settings/accounts.ts (under the existing /settings/api auth gate):

  • GET /settings/api/accounts — the roster + active_key. Tokens are never returned (AccountSummary exposes only login/host/added_via/obtained_at/active; a test asserts no token leaks).
  • POST /accounts/switch {key}pre-flights the target token against Copilot before flipping activeKey (the token's already in the registry, so a bad switch would otherwise cost a full reboot to discover) → specific 422 on a revoked/no-Copilot account; the shell reboots into the new active config on a 2xx.
  • POST /accounts/remove {key} — deletes maximal's own copy from the registry (gh untouched — HARD ISOLATION invariant); clears activeKey if it was the active one.

settings-types.ts: AccountSummary + AccountsListResponse (snake_case, no token).

Refactor (from /simplify)

preflightCopilotError moved out of routes/settings/gh.ts into src/lib/copilot-preflight.ts now that two routes share it (gh-reuse adopt + accounts switch) — routes stay thin HTTP wrappers, the reusable check lives in lib.

Testing

  • bun test — 850 pass / 0 fail (+10 route tests). The tests mock the registry storage boundary + the getCopilotUsage leaf (not the whole gh module), so gh-preflight.test.ts's coverage of the real preflightCopilotError is preserved (avoids the documented cross-file mock.module leak).
  • bun run check:fast clean; knip no new unused; shell tsc clean.
  • /simplify — applied the one actionable finding (the cross-route helper move above); confirmed no token leak + correct mock seam.

Stacked on #115 (merged); rebased onto main.

Backend for quick-switch over the persisted account registry (PR 1). New
src/routes/settings/accounts.ts:
- GET /settings/api/accounts — roster + active_key. Tokens are never
  returned (only login/host/added_via/obtained_at/active).
- POST /accounts/switch {key} — pre-flights the target token against Copilot
  BEFORE flipping the pointer (the token is in-registry, so a bad switch
  would otherwise cost a full reboot to discover) → specific 422 on failure;
  the shell reboots into the new active config on 2xx.
- POST /accounts/remove {key} — deletes maximal's OWN copy from the registry
  (gh untouched, isolation invariant); clears activeKey if it was active.

settings-types: AccountSummary + AccountsListResponse (snake_case, no token).

preflightCopilotError moved out of routes/settings/gh.ts into the new
src/lib/copilot-preflight.ts now that two routes (gh-reuse adopt + accounts
switch) share it — routes stay thin HTTP wrappers, the reusable check lives
in lib (/simplify altitude finding).

No UI yet (PR 3) — endpoints are inert until the picker is wired. +10 route
tests (mock the registry storage + the getCopilotUsage leaf, NOT the gh
module, so gh-preflight coverage of the real preflight is preserved).
@stuffbucket stuffbucket merged commit 547b993 into main Jun 11, 2026
4 checks passed
@stuffbucket stuffbucket deleted the feat/account-routes branch June 11, 2026 21:31
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