You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On the substring-fallback detection path, classify-infra-failure.sh knows exactly which published error type it matched (the allowlist at lines ~71-77: authentication_error, billing_error, permission_error, …) and then discards it. The emitted projection carries api_error_status: null on that path, so an operator triaging a class=auth failure gets no discriminator at all — 401 vs 402 vs 403 prescribe three different remedies (rotate token / fix billing in Console / fix key permissions and workspace access), and the operator gets a three-way checklist instead of the specific one.
This is not 402-specific: a substring-detected 403 reproduces it. Independently verified during the #250 ratification review (2026-07-26).
Proposed fix
Carry the matched allowlist token into the structured projection as a NEW key — error_type, deliberately distinct from api_error_status, so an inferred (substring-matched) value is never conflated with an observed numeric status.
Log-hygiene safe by construction. The value comes from the closed published-type allowlist, never from raw model/SDK text.
Existing suite passes. Test 20 (classify-infra-failure.test.sh:~140-144) asserts key presence plus a result/errors leak denylist; it does not pin an exact key set. The new key should get its own presence assertion.
Scope
.github/scripts/classify-infra-failure.sh (source of truth)
render-classify-infra-failure.cjs regeneration → both workflow materializations (claude-review.yml, claude-security-review.yml)
classify-infra-failure.test.sh — new assertions for the key on the substring path and its absence/null on pure-status paths
Problem
On the substring-fallback detection path,
classify-infra-failure.shknows exactly which published error type it matched (the allowlist at lines ~71-77:authentication_error,billing_error,permission_error, …) and then discards it. The emitted projection carriesapi_error_status: nullon that path, so an operator triaging aclass=authfailure gets no discriminator at all — 401 vs 402 vs 403 prescribe three different remedies (rotate token / fix billing in Console / fix key permissions and workspace access), and the operator gets a three-way checklist instead of the specific one.This is not 402-specific: a substring-detected 403 reproduces it. Independently verified during the #250 ratification review (2026-07-26).
Proposed fix
Carry the matched allowlist token into the structured projection as a NEW key —
error_type, deliberately distinct fromapi_error_status, so an inferred (substring-matched) value is never conflated with an observed numeric status.Verified safe and non-breaking before filing:
classify-infra-failure.sh:~81-89; a new key leavesclassandapi_error_statusuntouched, andclass=<token>remains a bare separate term in the::errorannotation (claude-review.yml:~484), so Incident aggregator: dead-credential detection from consumer review-run annotations (scheduled, zero new secrets) #238's aggregator written against today's shape does not break.classify-infra-failure.test.sh:~140-144) asserts key presence plus aresult/errorsleak denylist; it does not pin an exact key set. The new key should get its own presence assertion.Scope
.github/scripts/classify-infra-failure.sh(source of truth)render-classify-infra-failure.cjsregeneration → both workflow materializations (claude-review.yml,claude-security-review.yml)classify-infra-failure.test.sh— new assertions for the key on the substring path and its absence/null on pure-status pathsRefs
#250 (ratification review that surfaced this), #238 (consumer), #248/#249/#251 (classifier lineage).
Filed by an AI agent (work-items:attend-queue lane) as raw intake — untriaged.