githubnext/chopinPublic

Let's compose rich plans together

Recover local sign-in from a missing config parent and a failed restore save

Two review findings on the local device-flow branch:

- LocalCredentials.save() used a non-recursive mkdir with an EEXIST
  catch for the plaintext-fallback directory, so a missing ancestor
  (a fresh machine's absent ~/.config) threw ENOENT and made sign-in
  impossible instead of falling back. Use a recursive mkdir at 0700
  and chmod the leaf only when something was created.
- LocalAuth#restore rethrew a failed credentials.save() after a
  restore-time refresh, returning 500 and leaving the spent refresh
  token on disk to be resent on the next request. Wrap that save in
  its own try/catch, revoke the binding, delete the credential, and
  return { clear: true } so the browser goes back to sign-in, matching
  the existing failed-persist pattern in session.ts.

Added one regression test per finding in local-store.test.ts and
local.test.ts; both reproduce their defect at the prior code and pass
after the fix.

Assistant-model: Claude Sonnet 5
Assistant-workflow: local-device-auth (run d9099a2f-b7b0-42cd-9222-9257b1ee0030)
Assistant-verification: Bun unit passed: mise exec -- bun test (1566 pass, 2 PostgreSQL skips, 0 fail)
Assistant-verification: Bun.secrets native passed: TEST_NATIVE_SECRETS=1 mise exec -- bun test apps/server/src/auth/local-store.test.ts (7 pass)
Assistant-verification: Bun typecheck passed: mise exec -- bun run types (all workspaces and E2E)
Assistant-verification: Bun lint passed: mise exec -- bun run ci (dprint, oxlint, token checks)
Assistant-verification: Playwright E2E passed: flock /tmp/chopin-e2e.lock mise exec -- bun run e2e --workers=1 (231/231)
Co-authored-by: Alex Lavaee <lavaman131@github.com>
ALAlex Lavaee authored
06fe8c3Patch
Parent28b9cd5
4 files changed+72-9
StackedSplit
apps/server/src/auth/local-store.test.ts+33 −0
apps/server/src/auth/local-store.ts+2 −8
apps/server/src/auth/local.test.ts+30 −0
apps/server/src/auth/local.ts+7 −1