Skip to content

fix: stop rejecting valid Anthropic keys — verify against /v1/messages, not /v1/models#18

Merged
archdex-art merged 1 commit into
mainfrom
fix/key-verification-use-messages-endpoint
Jul 17, 2026
Merged

fix: stop rejecting valid Anthropic keys — verify against /v1/messages, not /v1/models#18
archdex-art merged 1 commit into
mainfrom
fix/key-verification-use-messages-endpoint

Conversation

@archdex-art

Copy link
Copy Markdown
Owner

Bug report

"now it is not even taking the api" — after the previous verify-before-save fix (PR #16), a real API key could no longer be saved at all.

Root cause (evidence, not assumption)

The prior verification called GET /v1/models to confirm a key works before persisting it. Anthropic supports scoped/restricted API keys (created with limited permissions in the Console) that can work perfectly for chat completions while lacking permission to list models. A fully valid, working key could get a 403 on /v1/models specifically — which the old code treated as "confirmed invalid" and rejected. This is strictly worse than the bug it was meant to fix: instead of a confusing error deep in a chat turn, the user could no longer save a key at all.

Fix

Verify against POST /v1/messages instead — the exact endpoint the real chat feature actually uses, eliminating the scope-mismatch false-positive class by construction. Sends a deliberately empty/invalid JSON body ({}).

Confirmed live against Anthropic's real API (not assumed): authentication is validated before the request body — a bad key gets a 401 regardless of body content, so this never reaches the model and never consumes a token, while exercising the identical auth path a real chat request takes.

Also hardened the blocking rule to be maximally conservative: only a confirmed 401 blocks a save now (was 401 OR 403). 403/429/5xx/network failures are all treated as "not evidence the key is bad" and the key still saves.

Verification

  • Rewrote anthropicKeyCheck.test.ts: confirms the call targets /v1/messages with the real chat feature's exact auth headers; a 403 (the false-positive class that broke saving) no longer blocks the save and the route test proves the key actually lands in the DB; 401 still correctly blocks and never persists.
  • Live, unmocked smoke test: confirmed a genuinely bad key is still rejected via a real call to Anthropic's actual /v1/messages endpoint and never saved.
  • Full suite 232/232, tsc --noEmit clean, lint baseline unchanged, next build clean.

…s, not /v1/models

Bug report: "now it is not even taking the api" — after the previous fix
(verify-before-save), a real API key could no longer be saved at all.

## Root cause (evidence, not assumption)

The prior verification called GET /v1/models to confirm a key works
before persisting it. Anthropic supports scoped/restricted API keys
(created with limited permissions in the Console) that can work perfectly
for chat completions while lacking permission to list models. A fully
valid, working key could therefore get a 403 on /v1/models specifically —
which the verification code treated as "confirmed invalid" and rejected —
silently blocking the user from ever saving a real, working key. This is
strictly worse than the bug it was meant to fix: instead of a confusing
error deep in a chat turn, the user now couldn't save a key at all.

## Fix

Verify against POST /v1/messages instead — the exact endpoint the real
chat feature actually uses, eliminating the scope-mismatch class of false
positives by construction (whatever this call proves works IS the
capability the app needs). Sends a deliberately empty/invalid JSON body
(`{}`, missing the required model/messages/max_tokens fields).

Confirmed LIVE against Anthropic's real API (not assumed) that
authentication is validated before the request body: a bad key gets a 401
regardless of body content, so this never reaches the model and never
consumes a token, while exercising the identical auth path a real request
takes.

Also hardened the blocking rule to be maximally conservative: only a
confirmed 401 blocks a save now (was 401 OR 403). 403, 429, 5xx, and
network failures are all treated as "not evidence the key is bad" and the
key still saves — a scoped key returning 403 for an unrelated permission
is no longer misread as "this key is broken."

## Verification

- Rewrote anthropicKeyCheck.test.ts: confirms the call targets
  /v1/messages (not /v1/models) with the same auth headers the real
  chat feature sends; a 403 (the exact false-positive class that broke
  saving) no longer blocks the save and the route test proves the key
  actually lands in the DB; 401 still correctly blocks and never persists.
- Live, unmocked smoke test against a running dev server: confirmed a
  genuinely bad key is still rejected via a real call to Anthropic's
  actual /v1/messages endpoint and never saved.
- Full suite 232/232, tsc --noEmit clean, lint baseline unchanged, next
  build clean.
@archdex-art
archdex-art merged commit e3fd64b into main Jul 17, 2026
2 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