Skip to content

perf(git): replace per-request token decryption with indexed hash lookup#279

Open
jaredglaser wants to merge 1 commit into
mainfrom
perf/f18-git-token-hash-lookup
Open

perf(git): replace per-request token decryption with indexed hash lookup#279
jaredglaser wants to merge 1 commit into
mainfrom
perf/f18-git-token-hash-lookup

Conversation

@jaredglaser

Copy link
Copy Markdown
Owner

Summary

Git HTTP auth (src/routes/api/git.$.ts) loaded every git_tokens row and JWE-decrypted each one on every request before the timing-safe compare, making auth O(n) in token count with a JWE decrypt per row.

  • Migration 024_git_token_hash.sql adds a token_hash column (SHA-256 hex of the raw token) with a unique index.
  • createGitToken now writes the hash at creation (hashGitToken in src/lib/git/git-token-auth.ts).
  • Auth is now a single indexed lookup by token_hash plus timingSafeEqual, mirroring the sessions pattern in src/lib/auth/session-manager.ts. A length guard prevents timingSafeEqual from throwing on a malformed stored hash.
  • Rows created before the migration have a NULL hash. Those fall back to the legacy decrypt-and-compare scan (now scoped to WHERE token_hash IS NULL), and the hash is backfilled on a successful match so the next request takes the fast path. Keyring and JWE decrypt load lazily, so the fast path never touches them.
  • Token matching was extracted to src/lib/git/git-token-auth.ts with injected repo and decrypt dependencies so it is unit-testable outside the route file.
  • Repository: findAllEncrypted (sole caller was the route) became findLegacyEncrypted; added findByTokenHash and setTokenHash.

Migration numbering note: open PRs #276 and #278 also claim 024, so renumbering this migration on rebase is expected.

Testing

  • bun run typecheck clean.
  • bun test --isolate src/lib/git/__tests__/git-token-auth.test.ts (8 pass): fast path skips legacy scan and decryption, legacy match backfills the hash, malformed stored hash falls through without throwing, all-decrypt-failure logging, fire-and-forget backfill failure does not throw.
  • bun test --isolate src/lib/database/repositories/__tests__/git-token-repository.test.ts (17 pass): create inserts token_hash, findByTokenHash, findLegacyEncrypted filters NULL-hash rows, setTokenHash.
  • bun test --isolate src/data/__tests__/git-tokens.functions.test.ts (8 pass): created token stores the SHA-256 hash of the raw token.

Closes #243

🤖 Generated with Claude Code

Git HTTP auth loaded every git_tokens row and JWE-decrypted each one on
every request before comparing. Migration 024 adds a token_hash column
(SHA-256 hex of the raw token) with a unique index, token creation now
writes the hash, and auth does a single indexed lookup plus
timingSafeEqual, mirroring the sessions pattern. Rows created before the
migration have a NULL hash; those fall back to the legacy
decrypt-and-compare scan and get their hash backfilled on a successful
match so the next request takes the fast path.

Token matching moved to src/lib/git/git-token-auth.ts with injected
repo and decrypt dependencies so it is unit-testable outside the route.

Closes #243

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@jaredglaser, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 35 minutes and 58 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4460f34e-d2eb-4f8c-be00-442ba7b31e3f

📥 Commits

Reviewing files that changed from the base of the PR and between 5d66d9f and a3450f9.

📒 Files selected for processing (8)
  • migrations/024_git_token_hash.sql
  • src/data/__tests__/git-tokens.functions.test.ts
  • src/data/git-tokens.functions.tsx
  • src/lib/database/repositories/__tests__/git-token-repository.test.ts
  • src/lib/database/repositories/git-token-repository.ts
  • src/lib/git/__tests__/git-token-auth.test.ts
  • src/lib/git/git-token-auth.ts
  • src/routes/api/git.$.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/f18-git-token-hash-lookup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

Git HTTP auth: O(n) token decryption per request

1 participant