v5.17.1 — the OAuth lane stops being recorded as a failed identity check
Found in DashClaw's own live ledger: every decision made through the Claude consumer-app connector carried verification_status: 'failed' — the label that means an agent presented a cryptographic identity claim and it was rejected. Nothing of the sort had happened.
The chain
The built-in OAuth authorization server issues opaque access tokens (oat_…). /api/mcp recognizes an OAuth Bearer well enough to assign it the claude-desktop agent id, then forwards that same credential downstream — where guard's identity resolver hands any Bearer to verifyJwt. An opaque string cannot parse, so it landed in the catch that returns failed.
The fix
Only a JWT-shaped Bearer is an identity claim. The Authorization header carries two different things here — an identity JWT (DashClawClient.authToken) and a plain credential — and only the first can meaningfully fail verification. A credential now takes the same path as no token at all (unverified, self-asserted); a JWT-shaped token that does not verify is still failed.
No privilege moved: both states are verified: false, neither applies token claims, and require_verified_parent already escalated on both. The guard hot path also loses a per-request console.warn and a doomed JWT parse.
Ledger history is not rewritten. Decisions recorded before this fix keep failed — the ledger is append-only, so the cutover is documented in docs/agent-identity.md instead.
Also
release:prep no longer fails opaquely when another app owns port 3001. Its pre-flight only noticed a squatter that answers /api/health; anything else 404s, so the check passed, next start could not bind, and the real cause surfaced two minutes later as "instance never reported version". It now probes over raw TCP and moves to the next free port instead of asking you to kill someone else's dev server.
Full write-up: maintainer log, 2026-08-10.