fix(cliproxyapi): only hydrate auths into an empty cache

Merged
SH
18d ago
+14-0

Summary

  • hydrateCliproxyAuths ran aws s3 sync s3://.../auths/ -> local on every home-manager switch. s3 sync overwrites any local file whose size differs, regardless of which side is newer.
  • The S3 copies lag the server's rotated Claude refresh tokens (the auth backup can't read some root-owned files the container writes), so on Oct 13 18:00 UTC kyber's three Claude auths were reverted to already-rotated refresh tokens -> invalid_grant: Refresh token not found or invalid -> full re-auth.
  • Hydrate now only pulls when the local auth cache is empty, matching start.sh.

Test plan

  • shellspec spec/cliproxyapi_backup_spec.sh (new case fails without the fix)
  • shellcheck on hydrate.sh

Follow-up not in this PR: root-owned 0600 auth files written by the container are skipped by cliproxyapi-backup-auth, so S3 can still go stale.

🤖 Generated with Claude Code


Summary by cubic

Prevents Cliproxy API auth hydration from overwriting live credentials with stale S3 copies.

s3 sync ran on every home-manager switch and rewrote any local auth file whose size differed, even when the local file was newer. Because S3 can lag behind the server's rotated Claude refresh tokens, a single switch reverted all Claude auths to revoked tokens and forced a full re-auth. Hydration now pulls from S3 only when the local auth cache is empty, matching start.sh.