Skip to content

fix(account): preserve full OAuth credential blob for token refresh#104

Merged
himerus merged 13 commits intostagingfrom
fix/oauth-raw-blob-credential
Apr 15, 2026
Merged

fix(account): preserve full OAuth credential blob for token refresh#104
himerus merged 13 commits intostagingfrom
fix/oauth-raw-blob-credential

Conversation

@himerus
Copy link
Copy Markdown
Contributor

@himerus himerus commented Apr 15, 2026

Summary

  • Root cause: readClaudeCodeCredential() extracted only 6 fields from Claude Code's keychain blob, stripping OAuth metadata (tokenEndpoint, clientId, etc.) needed for token refresh. After ~2 hours when the access token expired, Claude Code couldn't refresh → persistent 401 errors breaking cron jobs and overnight workflows.
  • All credential storage/restoration now uses raw blob passthrough — no field extraction or re-wrapping
  • Added keychainSetRaw, keychainGetRaw, readClaudeCodeCredentialRaw, parseCredentialForDisplay, rawCredentialHasToken to keychain module
  • Updated accountAdd, accountSwitch, accountRotate, syncBackActiveCredential to use raw blobs

Post-deploy action

Existing accounts must be rotated once to re-capture the full credential blob:

npx @bookedsolid/reagent@latest account rotate <account-name>
npx @bookedsolid/reagent@latest account switch <account-name>

Test plan

  • npx tsc --noEmit — clean
  • 786 tests pass, 0 failures
  • All 6 preflight gates pass
  • After release: rotate account, switch, verify token survives 2+ hours

himerus and others added 13 commits April 13, 2026 22:17
feat(account): add account verify, preserve credential fields, expiry warnings
fix(account): keychain slot swap for rswitch — sessions survive overnight
This reverts commit b75fb09.
readClaudeCodeCredential() was destructively extracting only 6 fields
from Claude Code's keychain blob, stripping OAuth metadata needed for
token refresh (tokenEndpoint, clientId, etc.). After ~2 hours when the
access token expired, Claude Code could not refresh — causing 401 errors
that broke cron jobs and overnight workflows.

All credential storage and restoration now uses raw blob passthrough:
- Added keychainSetRaw/keychainGetRaw for opaque blob storage
- Added readClaudeCodeCredentialRaw for lossless keychain reads
- Added parseCredentialForDisplay for display-only field extraction
- accountAdd, accountSwitch, accountRotate, syncBackActiveCredential
  all use raw blobs — no field extraction or re-wrapping
@himerus himerus merged commit e1b31be into staging Apr 15, 2026
4 of 10 checks passed
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