Skip to content

fix(proxy): harden account routing and process reliability - #1163

Merged
murdore merged 1 commit into
releasefrom
fix/proxy-reliability-hardening
Jul 14, 2026
Merged

murdore merged 1 commit into
releasefrom
fix/proxy-reliability-hardening

Conversation

@murdore

@murdore murdore commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Make launchd the sole restart supervisor for launchd-managed proxies; make the foreground guard cleanup-only and runtime auto-update opt-in.
  • Persist account cooldowns across restarts, honor authoritative unified quota rejection, and never retry accounts with active cooldowns.
  • Serialize cooldown/quota persistence and rotating OAuth refreshes, including callers that observe the newly rotated refresh token.
  • Distinguish terminal credential rejection from transient endpoint failures and preserve manual disable metadata.
  • Add routing.account-allowlist as a fail-closed boundary across TokenStore, legacy-file, and environment credentials.
  • Prevent hidden legacy/environment credentials from activating while any Anthropic TokenStore entry exists.
  • Record upstream stream errors and client cancellation as terminal outcomes instead of successful HTTP 200 completions.
  • Drain and exit deterministically on shutdown, surfacing close failures without leaving rejected signal handlers.

Account isolation

primary-account remains an ordering preference. The new allowlist is the eligibility boundary and is applied before token loading or refresh. Empty means deny all; absent preserves existing unrestricted behavior. Legacy and environment fallbacks require explicit legacy-default or env entries.

Automatic token rotation no longer clears an operator-disabled account. Only explicit login re-enables current disable metadata; legacy refresh_failed records from older releases receive one migration recheck.

Verification

  • pnpm run typecheck: pass.
  • pnpm exec vitest run test/proxyReliabilityHardening.test.ts: 23/23 pass.
  • pnpm test:bugfixes: 89/89 pass.
  • Changed-file ESLint: 0 errors and no new warnings.
  • pnpm run build:cli: pass.
  • Full pre-commit pipeline will run again on the amended commit.

Rollout safety

Development and tests did not start, stop, signal, reconfigure, or install over the live proxy. The existing process-level proxy suite was intentionally not run because it manages global proxy state and processes. Release rollout should use an isolated state directory first, then a controlled launchd replacement with health and restart-count verification.

Copilot AI review requested due to automatic review settings July 14, 2026 18:09
@vercel

vercel Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
neurolink Ready Ready Preview, Comment Jul 14, 2026 6:50pm

@github-actions

github-actions Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: 6b4edd7b015e79259b7ee0e5a8e9e5bfd12d519b
  • Message: fix(proxy): harden routing and process reliability
  • Author: Sachin Sharma

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@github-actions

github-actions Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Documentation Validation Results

🚀 Documentation validation passed!

Check Status Result
Frontmatter Validation ✅ Passed
TypeScript Check ✅ Passed
Build ✅ Passed
Link Validation ✅ Passed

📦 Build artifact uploaded successfully. Ready for deployment preview.

Commit: 77a3b50f1d9a029d653d21d48b4dd01fee4c38a6 | Workflow: View logs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the Claude-compatible proxy’s reliability and safety by persisting rate-limit/auth cooldown state across restarts, tightening account eligibility boundaries via an explicit allowlist, and improving process supervision + streaming terminal outcome telemetry to better reflect real client outcomes.

Changes:

  • Persist per-account cooldown state to disk and restore it at startup; never retry accounts with active cooldowns (including when all accounts are cooling).
  • Add routing.account-allowlist as an eligibility boundary across TokenStore / legacy-file / env credentials; prevent hidden fallbacks when any TokenStore Anthropic entry exists.
  • Improve operational robustness: serialize rotating OAuth refreshes, refine terminal vs transient refresh failures, harden update-state atomic writes, and track stream terminal outcomes (upstream error vs client cancellation vs completion).

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/proxyReliabilityHardening.test.ts Adds regression tests covering cooldown persistence, unified rate-limit handling, refresh classification/serialization, allowlist behavior, stream terminal outcomes, and launchd invariants.
test/continuous-test-suite-bugfixes.ts Updates continuous test assertions to match new “all accounts cooling / earliest retry” behavior and non-rehammering invariant.
src/lib/types/subscription.ts Extends proxy routing config type with accountAllowlist?: string[].
src/lib/types/proxy.ts Adds allowlist/cooldown/stream-outcome related types and updates cooldown/quota documentation.
src/lib/types/cli.ts Persists the enforced account allowlist into proxy runtime state.
src/lib/types/auth.ts Updates disable-reason example to reflect new refresh_invalid semantics.
src/lib/server/routes/claudeProxyRoutes.ts Core logic changes: persisted cooldowns, allowlist enforcement, unified-status handling, refresh classification, non-rehammer routing, and stream terminal outcome telemetry/status reporting.
src/lib/proxy/updateState.ts Hardens atomic update-state writes with per-process unique temp files and cleanup.
src/lib/proxy/tokenRefresh.ts Serializes refresh by refresh-token value, adds transient vs permanent refresh failure classification, and uses shared atomic snapshot writer.
src/lib/proxy/streamOutcome.ts Introduces a first-writer-wins tracker and merge logic for SSE terminal error promotion.
src/lib/proxy/sseInterceptor.ts Captures terminal SSE event: error message into telemetry for downstream terminal-outcome classification.
src/lib/proxy/snapshotPersistence.ts Tightens state-dir permissions and supports serialized atomic snapshot writes.
src/lib/proxy/requestLogger.ts Records terminal stream outcomes distinctly (e.g., terminalStatus/outcome) for mid-stream failures.
src/lib/proxy/proxyPaths.ts Adds cooldownFile to proxy paths for both dev and non-dev state directories.
src/lib/proxy/proxyConfig.ts Adds validation + parsing support for routing.account-allowlist / accountAllowlist.
src/lib/proxy/accountSelection.ts New module for key normalization/equality, allowlist creation, and fallback credential gating rules.
src/lib/proxy/accountQuota.ts Parses authoritative top-level unified status; hardens cache-load concurrency and moves persistence to atomic snapshot writer.
src/lib/proxy/accountCooldown.ts New module implementing restart-safe cooldown persistence with validation and atomic writes.
src/lib/auth/tokenStore.ts Preserves manual disable metadata across automatic token rotations; adds getDisabledReason().
src/cli/commands/proxy.ts Ensures launchd-only restart supervision, makes auto-update opt-in, enforces allowlist at boot, exposes allowlist in status, and improves shutdown drain behavior.
src/cli/commands/auth.ts Makes explicit login re-enable previously disabled accounts (markEnabled).
docs/features/claude-proxy.md Updates user-facing proxy behavior docs for cooldown persistence, allowlist semantics, refresh behavior, and terminal stream outcomes.
docs/features/claude-proxy-config-reference.md Documents new account-allowlist option and updated guard/auto-update behavior and file inventory.
docs/analysis/claude-proxy-reliability-hardening.md Adds incident/root-cause analysis and rollout verification plan for the hardening changeset.
.changeset/proxy-reliability-hardening.md Publishes a patch changeset describing the reliability/security hardening.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/proxy/accountQuota.ts Outdated
Comment thread docs/analysis/claude-proxy-reliability-hardening.md Outdated

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Reviewed the proxy reliability hardening PR (25 changed files, ~2.6K additions). The change addresses real production incidents and the core invariants are well documented. However, I found 5 MAJOR and 3 MINOR new issues that need to be addressed before merge.

Blocking criterion

Per the review charter, 3 or more MAJOR issues in the same PR is a BLOCK. This PR crosses that threshold.

MAJOR issues (blocking)

  1. src/lib/proxy/accountCooldown.ts:saveAccountCooldown — read-modify-write race can violate the extend-only cooldown invariant. Two concurrent callers can load the same stale snapshot and the shorter cooldown wins. Serialize the load-check-write path with a Mutex.

  2. src/lib/proxy/accountCooldown.ts:clearAccountCooldown — same race as above; a concurrent save and clear can clobber each other.

  3. src/lib/proxy/accountQuota.ts:saveAccountQuota — debounced flush snapshots memoryCache at scheduling time, but concurrent first-callers can load {} and wipe each other's account quotas. The load-update-dirty path needs serialization.

  4. src/lib/proxy/tokenRefresh.ts:refreshToken — the in-flight cache is keyed only by the old refresh token. A caller that loads the new rotating token from disk just before the winner persists it will not find an in-flight entry and will trigger a second refresh, invalidating the winner's new token. Cache by account label or also by the new token for SUCCESS_CACHE_MS.

  5. src/cli/commands/proxy.ts:registerProxyShutdownHandlers — process.on("SIGTERM", ...) and SIGINT handlers are async and unprotected; a thrown rejection in shutdown() can hang the process or produce an unintended exit code. Wrap shutdown in try/catch and always exit deterministically.

MINOR issues (non-blocking, please address)

  1. src/lib/server/routes/claudeProxyRoutes.ts — the post-load "credentials changed, re-enabling" log/runtime-clear contradicts the stated invariant that token changes no longer alter eligibility. Clarify or remove the misleading path.

  2. src/lib/server/routes/claudeProxyRoutes.ts — when all accounts are in auth cooldown, loopState.sawTransientFailure is set and the final response falls through to a generic 502 instead of the more accurate auth/reauth message.

  3. src/lib/auth/tokenStore.ts:saveTokens — disable metadata preservation only works when the existing record is already disabled; a save that races ahead of a disable can lose the operator's intent. Consider allowing callers to pass disable state atomically.

Next steps

Please address the five MAJOR items (especially the cooldown/quota races and the shutdown handler) and re-request review. The test coverage for the new behavior is good, but the race windows above are not exercised by the current hermetic tests.

Comment thread src/lib/proxy/accountCooldown.ts Outdated
Comment thread src/lib/proxy/accountCooldown.ts Outdated
Comment thread src/lib/proxy/accountQuota.ts
Comment thread src/lib/proxy/tokenRefresh.ts
Comment thread src/cli/commands/proxy.ts
Comment thread src/lib/server/routes/claudeProxyRoutes.ts
Comment thread src/lib/server/routes/claudeProxyRoutes.ts
Comment thread src/lib/auth/tokenStore.ts
@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Claude proxy gains account allowlists, coordinated OAuth refresh, persistent cooldown and quota state, unified rate-limit handling, terminal stream outcome tracking, and revised launchd/foreground guard lifecycle behavior. Documentation, public types, startup wiring, persistence, routes, and reliability tests are updated accordingly.

Changes

Claude proxy reliability

Layer / File(s) Summary
Configuration and account-selection contracts
src/lib/proxy/accountSelection.ts, src/lib/proxy/proxyConfig.ts, src/lib/types/*, docs/features/claude-proxy*.md
Adds normalized account allowlists, validation, fallback credential rules, cooldown reasons, stream outcome types, and persisted proxy-state fields.
Refresh, quota, and cooldown persistence
src/lib/proxy/tokenRefresh.ts, src/lib/proxy/accountQuota.ts, src/lib/proxy/accountCooldown.ts, src/lib/auth/tokenStore.ts, src/lib/proxy/*Persistence.ts
Coordinates concurrent token refreshes, preserves disabled metadata, classifies permanent refresh failures, and atomically persists quota, cooldown, credential, and update state.
Account routing and stream settlement
src/lib/server/routes/claudeProxyRoutes.ts, src/lib/proxy/sseInterceptor.ts, src/lib/proxy/streamOutcome.ts
Applies allowlists and persisted cooldowns during routing, handles unified quota rejection and refresh cooldowns, and records actual upstream, client-cancelled, and SSE error outcomes.
Proxy startup and lifecycle supervision
src/cli/commands/proxy.ts, src/lib/proxy/proxyPaths.ts, docs/features/claude-proxy*.md
Wires allowlists through startup, maintenance, status, and runtime state; changes launchd plist handling and limits the fail-open guard to foreground proxies.
Reliability validation and diagnostics
test/proxyReliabilityHardening.test.ts, test/continuous-test-suite-bugfixes.ts, src/lib/proxy/requestLogger.ts, src/lib/proxy/sseInterceptor.ts
Covers unified quotas, persistence concurrency, refresh serialization, allowlist behavior, stream terminal outcomes, and lifecycle invariants while enriching stream failure telemetry.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • juspay/neurolink#1143: Related unified Anthropic rate-limit handling, cooldown planning, and account rotation changes.
  • juspay/neurolink#1144: Related quota persistence, loading, and quota-aware Claude proxy routing changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main proxy routing and reliability hardening changes in the PR.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/proxy-reliability-hardening

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.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@murdore
murdore requested a review from Tara-ag July 14, 2026 18:51

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Reviewed the full diff for PR #1163 (23 changed files, +2506/-520).

Existing review comments

All 10 prior inline threads from Tara-ag and copilot-pull-request-reviewer have been addressed by the author in commit 6b4edd7b:

  • cooldown/quota read-modify-write races are now serialized under AsyncMutex;
  • rotating OAuth refresh-token deduplication now caches successes under both the old and newly-rotated token;
  • shutdown handlers drain the server deterministically and surface close errors;
  • TokenStore disable metadata is preserved across automatic saves and protected by the shared mutex;
  • all-auth-cooldown pools now return a specific 503 token_refresh_unavailable response.

New findings this run

  • 0 CRITICAL, 0 MAJOR, 0 MINOR new issues.
  • No hardcoded secrets, injection vectors, SSRF, unsafe eval, or PII exposure in the changed source.
  • No violations of CLAUDE.md Critical Rules enforced outside CI (dynamic-import registry rule, Gemini tools/schema rule, CLI/SDK separation, formatProviderError return rule, public SDK backward compatibility).
  • New types are defined only in the canonical src/lib/types/ location and imported via the barrel.
  • The new account-allowlist boundary is applied consistently across TokenStore, legacy-file, and environment credential discovery, and hidden fallbacks are correctly suppressed while any Anthropic TokenStore entry exists.
  • Cooldown/quota persistence, rotating refresh serialization, stream terminal-outcome tracking, and deterministic shutdown all appear correct.

Tests

The PR adds test/proxyReliabilityHardening.test.ts covering unified rate-limit classification, cooldown/quota persistence races, refresh failure classification, rotating-token serialization, account restriction, stream terminal outcomes, and launchd lifecycle invariants. This aligns with the existing vitest-based test files in the repo.

Verdict

Approve — no new blocking criteria are met.

@murdore
murdore merged commit be7487c into release Jul 14, 2026
18 of 19 checks passed
@murdore
murdore deleted the fix/proxy-reliability-hardening branch July 14, 2026 19:03
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 9.86.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/proxy/tokenRefresh.ts (1)

29-86: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Treat only documented credential failures as terminal

isRefreshCredentialRejection currently classifies 403/404 as permanent. The fallback token endpoint can return a 403 challenge unrelated to refresh-token validity, so a transient infra block could mark a valid account as refresh_invalid and disable it until re-login. Restrict this to the documented invalid-grant responses, or inspect the response body before setting terminalFailure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/proxy/tokenRefresh.ts` around lines 29 - 86, Update
isRefreshCredentialRejection and the terminalFailure assignment in
performTokenRefresh so only documented invalid-grant credential responses are
treated as permanent failures; do not classify generic 403/404 fallback endpoint
responses as terminal. Preserve fallback retry behavior and return the failure
normally unless the status/body confirms an invalid refresh credential.
🧹 Nitpick comments (3)
src/lib/proxy/accountQuota.ts (1)

199-222: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Loaded quota entries aren't validated against the AccountQuota shape.

memoryCache = JSON.parse(raw) as Record<string, AccountQuota>; blindly trusts the on-disk JSON. The sibling accountCooldown.ts module validates each loaded entry (isPersistedCooldown) and drops malformed ones; this module has no equivalent guard, so a stale/corrupted account-quotas.json (e.g. from an older schema or partial external edit) would load fields as undefined/wrong-typed straight into runtime state used for quota-based routing decisions, rather than falling back safely.

♻️ Proposed validation guard
+function isValidAccountQuota(value: unknown): value is AccountQuota {
+  if (!value || typeof value !== "object") {
+    return false;
+  }
+  const c = value as Partial<AccountQuota>;
+  return (
+    typeof c.sessionUsed === "number" &&
+    typeof c.weeklyUsed === "number" &&
+    typeof c.sessionStatus === "string" &&
+    typeof c.weeklyStatus === "string" &&
+    typeof c.lastUpdated === "number"
+  );
+}
+
 async function ensureAccountQuotasLoaded(): Promise<void> {
   if (!cacheLoaded) {
     if (!cacheLoadPromise) {
       cacheLoadPromise = (async () => {
         try {
           const raw = await fs.readFile(getQuotaFilePath(), "utf-8");
-          memoryCache = JSON.parse(raw) as Record<string, AccountQuota>;
+          const parsed = JSON.parse(raw) as Record<string, unknown>;
+          memoryCache = Object.fromEntries(
+            Object.entries(parsed).filter(([, v]) => isValidAccountQuota(v)),
+          ) as Record<string, AccountQuota>;
         } catch {
           memoryCache = {};
         }
         cacheLoaded = true;
       })().finally(() => {
         cacheLoadPromise = null;
       });
     }
     await cacheLoadPromise;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/proxy/accountQuota.ts` around lines 199 - 222, Update
ensureAccountQuotasLoaded to validate parsed entries before assigning
memoryCache, using an AccountQuota-shaped type guard equivalent to
accountCooldown.ts’s isPersistedCooldown pattern. Retain only entries that pass
validation and discard malformed or stale records, falling back to an empty
cache when the parsed data is invalid or not an object.
src/lib/server/routes/claudeProxyRoutes.ts (1)

2897-2985: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated stream-terminal-outcome tracking scaffolding vs. the auth-retry path.

The ReadableStream wrapper here (seed first chunk, pull/cancel handlers driving streamOutcomeTracker.complete()/fail()/cancel(), plus the mid-stream error-event SSE emission) is duplicated almost verbatim in handleAnthropicSuccessfulRetryResponse at lines 3591-3638, differing only in variable names (mainStreamClosed vs retryStreamClosed) and the initial start() seeding. Any future fix to this stream-tracking logic (e.g., an edge case in outcome settlement) needs to be applied in both places.

Consider extracting a shared helper (parameterized by an optional "first chunk to seed" and the reader) that both the initial success path and the auth-retry success path can call, similar to how trackUpstreamReadableStream already centralizes the passthrough-mode variant.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/server/routes/claudeProxyRoutes.ts` around lines 2897 - 2985, Extract
the duplicated stream-terminal tracking and SSE error-handling logic from the
current success path and handleAnthropicSuccessfulRetryResponse into a shared
helper, parameterized by the reader and optional initial chunk. Have both
callers use it while preserving first-chunk seeding, complete/fail/cancel
tracking, stream closure, and mid-stream error-event behavior.
src/cli/commands/proxy.ts (1)

136-188: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the resolved allowlist instead of recomputing it.

resolveStatusPrimaryAccount rebuilds the allowlist via createAccountAllowlist(proxyConfig?.routing?.accountAllowlist) (Lines 140-142) rather than reusing params.accountAllowlist, which was already resolved (with validation/warnings) by resolveBootAccountAllowlist and is available in the /status handler's closure at the call site (Line 1320-1322). Two independent constructions of the same security-relevant allowlist risk silently diverging if one path changes but not the other.

♻️ Proposed fix
 async function resolveStatusPrimaryAccount(
   proxyConfig: LoadedProxyConfig | null,
+  accountAllowlist?: AccountAllowlist,
 ): Promise<ProxyStatusPrimaryAccount> {
   const configured = proxyConfig?.routing?.primaryAccount?.trim() || null;
-  const accountAllowlist = createAccountAllowlist(
-    proxyConfig?.routing?.accountAllowlist,
-  );
   let enabledAnthropicKeys: string[] = [];

and update the call site to pass params.accountAllowlist.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/commands/proxy.ts` around lines 136 - 188, Update
resolveStatusPrimaryAccount to accept the already-resolved accountAllowlist as
an argument and remove its local
createAccountAllowlist(proxyConfig?.routing?.accountAllowlist) construction. At
the /status handler call site, pass params.accountAllowlist from the existing
closure so account filtering reuses the validated allowlist.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli/commands/proxy.ts`:
- Around line 1808-1812: Update StateFileManager.save() to create or write
proxy-state.json with mode 0o600, preserving restrictive permissions even when
the file already exists. In docs/features/claude-proxy-config-reference.md lines
627-633, update the config reference row from “user default” to reflect the
hardened file mode.

In `@src/lib/proxy/sseInterceptor.ts`:
- Around line 415-430: Cap the trimmed derived message assigned in the
error-event branch of the SSE interceptor to MAX_EVENT_DATA_BYTES, matching the
existing fallback truncation. Preserve the nested error.message and top-level
message selection and fallback behavior, while ensuring acc.streamErrorMessage
is bounded before downstream logging and tracing.

---

Outside diff comments:
In `@src/lib/proxy/tokenRefresh.ts`:
- Around line 29-86: Update isRefreshCredentialRejection and the terminalFailure
assignment in performTokenRefresh so only documented invalid-grant credential
responses are treated as permanent failures; do not classify generic 403/404
fallback endpoint responses as terminal. Preserve fallback retry behavior and
return the failure normally unless the status/body confirms an invalid refresh
credential.

---

Nitpick comments:
In `@src/cli/commands/proxy.ts`:
- Around line 136-188: Update resolveStatusPrimaryAccount to accept the
already-resolved accountAllowlist as an argument and remove its local
createAccountAllowlist(proxyConfig?.routing?.accountAllowlist) construction. At
the /status handler call site, pass params.accountAllowlist from the existing
closure so account filtering reuses the validated allowlist.

In `@src/lib/proxy/accountQuota.ts`:
- Around line 199-222: Update ensureAccountQuotasLoaded to validate parsed
entries before assigning memoryCache, using an AccountQuota-shaped type guard
equivalent to accountCooldown.ts’s isPersistedCooldown pattern. Retain only
entries that pass validation and discard malformed or stale records, falling
back to an empty cache when the parsed data is invalid or not an object.

In `@src/lib/server/routes/claudeProxyRoutes.ts`:
- Around line 2897-2985: Extract the duplicated stream-terminal tracking and SSE
error-handling logic from the current success path and
handleAnthropicSuccessfulRetryResponse into a shared helper, parameterized by
the reader and optional initial chunk. Have both callers use it while preserving
first-chunk seeding, complete/fail/cancel tracking, stream closure, and
mid-stream error-event behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c1c34ce-2638-4c3b-b71e-cafbc15ece74

📥 Commits

Reviewing files that changed from the base of the PR and between 6dc4fe3 and 6b4edd7.

📒 Files selected for processing (23)
  • docs/features/claude-proxy-config-reference.md
  • docs/features/claude-proxy.md
  • src/cli/commands/auth.ts
  • src/cli/commands/proxy.ts
  • src/lib/auth/tokenStore.ts
  • src/lib/proxy/accountCooldown.ts
  • src/lib/proxy/accountQuota.ts
  • src/lib/proxy/accountSelection.ts
  • src/lib/proxy/proxyConfig.ts
  • src/lib/proxy/proxyPaths.ts
  • src/lib/proxy/requestLogger.ts
  • src/lib/proxy/snapshotPersistence.ts
  • src/lib/proxy/sseInterceptor.ts
  • src/lib/proxy/streamOutcome.ts
  • src/lib/proxy/tokenRefresh.ts
  • src/lib/proxy/updateState.ts
  • src/lib/server/routes/claudeProxyRoutes.ts
  • src/lib/types/auth.ts
  • src/lib/types/cli.ts
  • src/lib/types/proxy.ts
  • src/lib/types/subscription.ts
  • test/continuous-test-suite-bugfixes.ts
  • test/proxyReliabilityHardening.test.ts

Comment thread src/cli/commands/proxy.ts
Comment thread src/lib/proxy/sseInterceptor.ts

This branch was successfully deployed

1 active deployment
Preview — 6b4edd7b Deployed Jul 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants