Skip to content

fix(prime): send with the vault credential for a vault-served fallback - #197

Open
iceteaSA wants to merge 1 commit into
cortexkit:mainfrom
iceteaSA:fix/prime-vault-token
Open

fix(prime): send with the vault credential for a vault-served fallback#197
iceteaSA wants to merge 1 commit into
cortexkit:mainfrom
iceteaSA:fix/prime-vault-token

Conversation

@iceteaSA

@iceteaSA iceteaSA commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Bug

sendPrime refreshed a fallback account and then sent the prime request with current.access. For a vault-served fallback the refresh is a deliberate no-op (v1.22.0 custody: the vault owns rotation), so current.access is the frozen sidecar token, which the vault's first rotation revoked. Live result since custody took over work-alt: every prime tick from every plugin process logs

WARN [prime] prime fire failed {"account":"work-alt","status":401,"error":"... OAuth access token has been revoked."}

Same defect class as the quota-poll fix in v1.22.0 (usage endpoint polled with the sidecar token); prime's send path was missed. Harmless beyond the noise, but the account was never primed.

Fix

  • Vault-served fallback with a usable resident credential: send with the vault token. No local refresh, no refreshAccount call.
  • Vault-served but cold: { ok: false, reason: 'vault-cold' }, routed to the quiet skip branch in PrimeManager (debug, existing backoff). Never a prime fire failed warn.
  • Not vault-served: unchanged. Main-account arm byte-identical.
  • A 401 on a vault token reports credential.report_auth_failure (reporter_source: "direct") with the record_version of the credential the prime was sent with, captured at send time. A re-peek after the response could name a version a tick refresh already superseded, which the vault silently ignores by design. Deduped through the same (handle, version) map the request path uses. A sidecar-token 401 is never reported.

Tests

Four regressions in index.test.ts, each proven red first:

mutation red signal
send with account.access again sidecar canary token appears in the request
route vault-cold to the warn branch prime fire failed logged once
re-peek the cache at report time after a tick refresh report missing the sent record_version
drop the provenance fence sidecar 401 produces a report

Gates: core build, root bun run test 1726/0 (169 core + 1557 opencode), typecheck, format:check, biome. Cross-family review (MiniMax M3): APPROVE 0 must / 2 style nits.

Vault-side consequence (confirmed with the Claustrum side): a spurious prime 401 costs one extra rotation per 5 h window; a genuine one latches needs_reauth and the sidebar vaultReauth state agrees.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes prime requests for vault-served fallback accounts sending with the revoked sidecar token, which caused a 401 warn on every tick. Prime now sends with the resident vault credential instead.

Bug Fixes

  • Vault-served fallbacks skip the local refresh and send with the vault token; a cold vault quietly skips the tick instead of logging a fire-failed warn.
  • A 401 on a vault token reports the credential failure with the sent record version; a sidecar-token 401 is never reported.
  • Non-vault accounts keep the existing refresh path unchanged.

Written for commit 69139c0. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 3 files

Confidence score: 5/5

  • In packages/opencode/src/tests/index.test.ts, a failed assertion or await can leave the log sink and debug level installed, contaminating later tests and making failures order-dependent; move cleanup into guaranteed teardown such as afterEach or a finally block.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/src/tests/index.test.ts">

<violation number="1" location="packages/opencode/src/tests/index.test.ts:19896">
P3: The log sink and debug level installed here are reset only at the end of the test body. If any expect or await before `__setLogTestSink(null)` fails, the sink and 'debug' level leak into every later test in the file, since `afterEach` only restores fetch/setInterval. Wrap the sink/level setup and teardown in try/finally so a failure cannot contaminate the rest of the suite.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

const { __setLogTestSink, setLogLevel } = await import(
'@cortexkit/anthropic-auth-core'
)
setLogLevel('debug')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The log sink and debug level installed here are reset only at the end of the test body. If any expect or await before __setLogTestSink(null) fails, the sink and 'debug' level leak into every later test in the file, since afterEach only restores fetch/setInterval. Wrap the sink/level setup and teardown in try/finally so a failure cannot contaminate the rest of the suite.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/tests/index.test.ts, line 19896:

<comment>The log sink and debug level installed here are reset only at the end of the test body. If any expect or await before `__setLogTestSink(null)` fails, the sink and 'debug' level leak into every later test in the file, since `afterEach` only restores fetch/setInterval. Wrap the sink/level setup and teardown in try/finally so a failure cannot contaminate the rest of the suite.</comment>

<file context>
@@ -19682,6 +19715,397 @@ describe('claude-prime direct request', () => {
+    const { __setLogTestSink, setLogLevel } = await import(
+      '@cortexkit/anthropic-auth-core'
+    )
+    setLogLevel('debug')
+    __setLogTestSink((record: any) => records.push(record))
+    mgr.options.refreshQuota = async () => ({ quota: dueQuota, fresh: true })
</file context>

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