Stability checkpoint v0.7.0 — mTLS client cert/key on IdP fetches (ADR-0040) Closes the v0.7 mTLS ticket carried since ADR-0037. Both providers now accept a client_cert_path + client_key_path pair ; when both are set, the pair is forwarded as the `cert=` kwarg on every requests.get() call (principals fetch + discovery fetch + JWKS fetch). Covers the residual ~20 % of IdP integrations beyond bearer auth : PKI-backed enterprises, gov / military zero-trust enclaves, HSM-backed keys. Minor bump (v0.6.x → v0.7.0) because mTLS is a substantive auth shape change ; combined with bearer (ADR-0037) + JWT validation (ADR-0038) the broker now covers all 4 standard IdP auth patterns : unauthenticated, bearer-only, mTLS-only, mTLS+bearer. - chore(docs): refresh README to v0.6.2 reality (f8324d8) - feat(security): mTLS client cert/key on IdP fetches (ADR-0040) (90941ca) CI : - ✅ MR pipeline #158 green — https://gitlab.com/benoit.besson/secured-claude/-/pipelines/2491904792 - ✅ Main pipeline #159 green — https://gitlab.com/benoit.besson/secured-claude/-/pipelines/2491916457 - ✅ All 5 main-stages green : lint / test / security / build / smoke Local test pass : - ✅ uv run pytest -q → 216 tests pass (was 204 in v0.6.2 ; +12 mTLS tests) - ✅ Coverage 90.87 % 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.2 : - ✅ Default `client_cert_path=client_key_path=None` preserves v0.6.2 behaviour - ✅ HTTPPrincipalProvider TTL cache + bearer + max-stale-age all still active - ✅ OIDCVerifier JWKS fetch + max-stale-age + signature validation all 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) - ✨ mTLS auth : broker can present a client cert on every IdP fetch (principals + discovery + JWKS). Combined with ADR-0037 (bearer) + ADR-0038 (JWT validation), the broker covers all 4 standard IdP auth patterns. - ✨ PKI-backed enterprises, gov/military zero-trust enclaves, HSM-backed keys all unlock with this rev. - ✨ Both halves of the cert/key pair required ; either-only treated as not configured (rotation-friendly). - 5 cosign-signed images cover the FULL supply chain (binary + policy bytes) — carryover - ⏭ N/A — mTLS auth shape change, no new domain features - ✨ End-to-end PKI integration documented in ADR-0040 : cert-manager / vault-issuer / HSM-backed leaf certs all work via the standard requests `cert=` kwarg. - ✨ Compatible with cipher pinning via custom urllib3 PoolManager (deferred to v0.7+ if a deployment needs FIPS 140-2 mode). - ⏭ N/A — no new metrics. WARNING log emitted on cert-pair-partial-env (operators see in logs). - 216 tests pass (was 204 in v0.6.2 ; +6 principals + +6 oidc covering both-set / partial / kwarg-passes / env-wiring) - Coverage 90.87 % (just above gate ; mTLS branches all hit by the kwarg-pass tests) - 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 - ✨ ADR-0040 added (40 ADRs total ; was 39 in v0.6.2) - Two new shared env vars (SECURED_CLAUDE_IDP_CLIENT_CERT_PATH + _KEY_PATH) — same shared-env pattern as ADR-0039 ; per-provider envs deferred if demand emerges. - Helper `_cert_kwarg()` mirrored across both modules ; consistent both-required semantics. - ⏭ N/A — broker is CLI + HTTP only - ✨ 2 new operator env knobs : SECURED_CLAUDE_IDP_CLIENT_CERT_PATH + SECURED_CLAUDE_IDP_CLIENT_KEY_PATH - Backward-compatible : default both-None matches v0.6.2 - Rotation-atomic : either-half-only is silently no-mTLS, so a cert-rotation script that writes one file then the other doesn't crash the broker - Multi-issuer ALLOWLIST not yet supported — operators with N IdPs need this for v0.7+. - 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 + cert envs (split shared envs) deferred to v0.7+ if demand emerges. - No Prometheus counter for mTLS / cert-rotation / cache-drop events ; operators rely on WARNING log lines. - mTLS for agent ↔ broker (cert-based auth on the hook connection) still v0.7+ ; this rev covers broker ↔ IdP only. - Cipher pinning via custom urllib3 PoolManager not exposed ; FIPS 140-2 deployments need a future ADR. - v0.7.1 — multi-issuer ALLOWLIST (accept JWTs signed by any of N IdPs ; the most-asked v0.7 feature) + Prometheus counters - v0.8 — agent ↔ broker mTLS (replace JWT in hook payload with cert-based auth ; needs server-side cert config in broker startup ; bigger architectural piece)