Stability checkpoint v0.6.2 — max_stale_age_s caps stale-on-error window (ADR-0039)

Closes the v0.7 ticket from ADR-0037 + ADR-0038 ("Permanent IdP misconfig
keeps serving compromised state forever"). Both providers now drop their
caches once they age past `max_stale_age_s`, falling back to single-default
(principals) or reject (JWKS / verify_token).

- chore(docs): refresh README to v0.6.1 reality (707963e)
- feat(security): max_stale_age_s caps stale-on-error window (ADR-0039) (5c31247)

CI :
- ✅ MR pipeline #151 green — https://gitlab.com/benoit.besson/secured-claude/-/pipelines/2491860016
- ✅ Main pipeline #152 green — https://gitlab.com/benoit.besson/secured-claude/-/pipelines/2491870895
- ✅ All 5 main-stages : lint / test / security / build / smoke (Kaniko cache hits = 2 min total)

Local test pass :
- ✅ uv run pytest -q → 204 tests pass (was 195 in v0.6.1 ; +9 max-stale-age tests)
- ✅ Coverage 90.74 % total (gate fail_under=90 % held)
- ✅ uv run ruff check src tests → clean
- ✅ uv run ruff format --check src tests → 32 files already formatted
- ✅ uv run mypy src → strict mode clean (13 source files)
- ✅ gitleaks detect → no leaks found

Regression check vs v0.6.1 :
- ✅ Default `max_stale_age_s=None` preserves v0.6.1 stale-forever behaviour
- ✅ HTTPPrincipalProvider TTL cache + bearer auth from ADR-0037 still active
- ✅ OIDCVerifier JWKS fetch + signature validation from ADR-0038 still active
- ✅ /check route still back-compat (verifier=None when issuer unset)
- ✅ docker-compose.yml still bind-mount-free (ADR-0035 + ADR-0036 still apply)
- ✅ 5 cosign-signed images still cover binary + policy bytes (carryover)

- Claude Code wrapped, every tool call gated by Cerbos PDP, audited in SQLite hash-chain log (carryover)

- ✨ Closes the "permanent IdP misconfig serves compromised state forever" gap : a revoked principal / rotated JWKS / retired endpoint now eventually drops back to fail-closed instead of being served indefinitely.
- ✨ Compliance posture : operators can document the maximum window during which a revoked principal / stale JWKS could be served (`SECURED_CLAUDE_MAX_STALE_AGE_S` = 300 s for compliance-sensitive deploys).
- ✨ Brief-outage case (cache age within bound) still serves stale per ADR-0037 ; only crosses to fail-closed past the bound.
- 5 cosign-signed images cover the FULL supply chain (binary + policy bytes) — carryover

- ⏭ N/A — staleness-bound shape only, no new domain features

- ✨ Compliance-tier bounds documented in ADR-0039 :
  - Demo / dev   : None (current behaviour)
  - Production   : 1800 s (30 min, typical SLA-window)
  - Compliance   : 300 s (revoked principal can't survive past page-and-fix)

- ✨ WARNING log line emitted on every drop event (cache age > max_stale_age) — operators tailing logs see the transition. Future ADR can add a Prometheus counter.

- 204 tests pass (was 195 in v0.6.1 ; +4 principals + +4 oidc + 1 invalid-env path)
- Coverage 90.74 % (just above gate ; oidc.py at 91 % after the new helper covered)
- mypy strict clean ; ruff + format clean
- bandit / pip-audit / grype / trivy / gitleaks all clean (carryover)

- 8 stages green on tag pipelines : lint / test / security / build / smoke / publish / release
- 5-image multi-arch (amd64 + arm64) ; cosign keyless OIDC signing on all 5
- Main pipeline 20/20 green (Kaniko cache hits → 2 min total)

- ✨ ADR-0039 added (39 ADRs total ; was 38 in v0.6.1)
- Single shared env knob (SECURED_CLAUDE_MAX_STALE_AGE_S) across both factories — operators almost always want the same bound on principals + JWKS. Per-provider envs deferred to v0.7+ if demand emerges.
- Helper `_too_stale()` on OIDCVerifier mirrors HTTPPrincipalProvider's check ; both modules use the same conceptual model.

- ⏭ N/A — broker is CLI + HTTP only

- ✨ 1 new operator env knob : SECURED_CLAUDE_MAX_STALE_AGE_S (default None = unbounded ; v0.6.1 behaviour preserved)
- Backward-compatible : existing deployments unaffected
- WARNING log per drop event makes the transition operationally visible

- mTLS auth on IdP URL still v0.7+ (cert/key pair env). Bearer-token covers ~80 % per ADR-0037.
- Multi-issuer support not in v0.6.x — operators with N IdPs need v0.7+ (issuer ALLOWLIST).
- Background JWKS refresh thread (proactive re-fetch before TTL expiry) deferred to v0.7+ if request-latency-during-refresh becomes a concern.
- Per-provider stale-age envs (split shared SECURED_CLAUDE_MAX_STALE_AGE_S into 2) deferred to v0.7+ if demand emerges.
- No Prometheus counter for drop events ; operators rely on WARNING log lines for visibility.

- v0.7 — mTLS auth (agent ↔ broker + broker ↔ IdP) + multi-issuer ALLOWLIST + background refresh + Prometheus counters + per-provider env split.