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
{{ message }}
Repository navigation
auth: count which proxy key authenticated during a rotation window (previous-key hits per machine on /health) #439
CLAUDISH_PROXY_KEY_PREVIOUS (be940b2, 12/09) keeps a retiring proxy key accepted during a rotation window, so seats can be repointed one at a time. Nothing records which key authenticated a request: matchesProxyKey() (handlers/shared/proxy-keys.ts) returns a boolean, fork/middleware/proxy-auth.ts logs nothing, /health exposes nothing, and captures carry no key class.
So the step that ends the window (unset _PREVIOUS + recreate) is a blind cut. Every holder of the old key that was missed gets 401 at that moment: a seat whose settings.json was not updated, a sidecar or relay .env, an sk-agent config, an external consumer. You only find them by breaking them.
Ask
When a request authenticates with the previous key (not the primary):
Increment a counter keyed by the X-Claudish-Machine header, or by the User-Agent product token when that header is absent (e.g. claude-cli, AsyncOpenAI, open-code-review). Never by IP, never by any key-derived value.
Expose it on /health as proxyKeyPreviousHits: { "<bucket>": <count>, ... } plus proxyKeyPreviousLastAt per bucket, counts only. Omit the field when _PREVIOUS is unset.
Emit one forceConsole marker [ProxyKey] previous key used by <bucket> (n=<count>) at most once per bucket per hour, so docker logs can count it after a restart has reset the in-memory counter.
Cover both auth sites that accept the key: the proxy-auth middleware, and the native proxyKey→Anthropic swap if it also matches _PREVIOUS.
Acceptance
Pins: primary key → no count; previous key → count under the machine header bucket; no header → UA bucket; _PREVIOUS unset → field absent; the marker is rate-limited per bucket.
Mutation: remove the increment → a pin goes red.
No key material, no key fingerprint, no IP in the field, the marker or the logs.
Use
The window closes when every fleet bucket stays at 0 for at least 12 h. Any bucket still counting names the holder still to migrate, before the cut instead of after it.
Activity
fix(auth): count remapped bare claude-* previous-key hits in the exem…
feat(auth): count previous-key hits per bucket during rotation windows (