feat(audit): publish sequenced heartbeat and reconciliation evidence

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ec5-7e2b-7743-ac08-719e1b0f42e2
This commit is contained in:
tegwick 2026-09-05 01:39:48 +02:00
parent fce60099c4
commit b9349782f4
32 changed files with 839 additions and 111 deletions

View file

@ -53,7 +53,9 @@ def _token(private_key: rsa.RSAPrivateKey, *, kid: str = KID, **claim_overrides)
return jwt.encode(claims, private_key, algorithm="RS256", headers={"kid": kid})
def _verifier(jwk: dict, *, required: bool = False, calls: list[int] | None = None) -> KeyCapeTokenVerifier:
def _verifier(
jwk: dict, *, required: bool = False, calls: list[int] | None = None
) -> KeyCapeTokenVerifier:
return KeyCapeTokenVerifier(
jwks_url="https://key-cape.netkingdom.test/jwks",
issuer=ISSUER,
@ -71,6 +73,7 @@ def test_verify_accepts_valid_token() -> None:
assert claims.actor_id == "agent-harness-binky"
assert claims.tenant_id == "tenant:friendly:binky"
assert claims.identity_binding == "key_cape_jwt"
assert claims.lane == "blue"
assert "finance.qonto.read" in claims.scopes
@ -194,6 +197,7 @@ def _settings() -> Settings:
deny_escalation_threshold=3,
deny_escalation_window_seconds=60,
deny_escalation_lockout_seconds=300,
audit_heartbeat_interval_seconds=86400,
key_cape_jwks_url=None,
key_cape_issuer=ISSUER,
key_cape_audience=AUDIENCE,
@ -236,7 +240,9 @@ def test_required_verifier_rejects_missing_bearer_token() -> None:
verifier = _verifier(jwk, required=True)
with pytest.raises(KeyCapeAuthError):
actor_claims_from_headers({"x-actor-id": "someone"}, _settings(), key_cape_verifier=verifier)
actor_claims_from_headers(
{"x-actor-id": "someone"}, _settings(), key_cape_verifier=verifier
)
def test_optional_verifier_falls_back_to_self_asserted_headers_when_absent() -> None:
@ -249,6 +255,7 @@ def test_optional_verifier_falls_back_to_self_asserted_headers_when_absent() ->
assert claims.actor_id == "someone"
assert claims.tenant_id == "binky"
assert claims.identity_binding == "self_asserted"
def test_invalid_bearer_token_is_rejected_even_when_not_required() -> None: