diff --git a/src/lib/__tests__/idempotency.test.ts b/src/lib/__tests__/idempotency.test.ts index f3f491a4d..1ab4b1fb8 100644 --- a/src/lib/__tests__/idempotency.test.ts +++ b/src/lib/__tests__/idempotency.test.ts @@ -287,6 +287,7 @@ describe("withIdempotency body-content exclusion (P12)", () => { it.each([ ["hlk_ access token", '{"data":{"token":"hlk_abc123"},"error":null}'], ["hlr_ refresh token", '{"data":{"refresh":"hlr_xyz789"},"error":null}'], + ["hls_ share-link token", '{"data":{"link":"hls_def456"},"error":null}'], ["sk- OpenAI key", '{"data":{"echoed":"sk-1234567890"},"error":null}'], [ "sk-ant- Anthropic key", diff --git a/src/lib/idempotency.ts b/src/lib/idempotency.ts index f9c3a8852..6f4db9f56 100644 --- a/src/lib/idempotency.ts +++ b/src/lib/idempotency.ts @@ -224,12 +224,13 @@ export function withIdempotency< // with, but if a future caller forgets we refuse to leak. // `hlk_` = our access tokens // `hlr_` = our refresh tokens + // `hls_` = clinician share-link tokens (v1.11) // `sk-…` = OpenAI / Anthropic keys (full token form, not the // raw substring — a 422 body explaining "task-id…" // or any other word containing `sk-` would otherwise // silently break idempotency for benign retries). const SECRET_PATTERN = - /(?:\b(?:hlk_|hlr_)[A-Za-z0-9_-]+|\bsk-(?:ant-)?[A-Za-z0-9_-]{8,})/; + /(?:\b(?:hlk_|hlr_|hls_)[A-Za-z0-9_-]+|\bsk-(?:ant-)?[A-Za-z0-9_-]{8,})/; const cloned = response.clone(); const text = await cloned.text(); if (!SECRET_PATTERN.test(text)) {