From e254fd2000f378fbe24c256cda0c78022fa6d39e Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 23 Aug 2026 00:42:09 +0200 Subject: [PATCH] refine audit-core multidriver use case roles Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02991-be07-7bb3-8b6d-e9701b5621de --- tests/test_audit_core_e2_use_case.py | 13 ++++++- usecases/audit_core_e2_tenant_boundary.py | 41 ++++++++++++++--------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/tests/test_audit_core_e2_use_case.py b/tests/test_audit_core_e2_use_case.py index 7079f4c..95bc33e 100644 --- a/tests/test_audit_core_e2_use_case.py +++ b/tests/test_audit_core_e2_use_case.py @@ -131,6 +131,17 @@ def test_intent_has_independent_provenance_and_separate_roles(): def test_schedule_requires_cleanup_before_finalization(): phases = {phase.id: phase for phase in PHASE_CONTRACTS} - assert phases["finalize-and-deliver"].requires == ("cleanup-custody",) + assert phases["finalize-and-deliver"].requires == ("verify-cleanup",) + assert phases["verify-cleanup"].requires == ("cleanup-custody",) assert phases["cleanup-custody"].requires == ("delete-runner",) assert phases["run-probes"].requires == ("ready-runner",) + + +def test_every_role_participates_in_a_phase(): + declared = {role.id for role in ROLE_CONTRACTS} + scheduled = { + role + for phase in PHASE_CONTRACTS + for role in phase.driver_roles + } + assert scheduled == declared diff --git a/usecases/audit_core_e2_tenant_boundary.py b/usecases/audit_core_e2_tenant_boundary.py index 6cae13d..d588367 100644 --- a/usecases/audit_core_e2_tenant_boundary.py +++ b/usecases/audit_core_e2_tenant_boundary.py @@ -46,7 +46,7 @@ class PhaseContract: """Causal intent for the future orchestrator; never a shell transcript.""" id: str - driver_role: str + driver_roles: tuple[str, ...] requires: tuple[str, ...] completion: str timing: str @@ -101,71 +101,83 @@ ROLE_CONTRACTS = ( PHASE_CONTRACTS = ( PhaseContract( "authorize", - "authorizer", + ("authorizer",), (), "Exact engagement and custody contracts are approved.", "Before projection and before the engagement window opens.", ), PhaseContract( "acknowledge-target", - "target-owner", + ("target-owner",), ("authorize",), "Target owner accepts the exact revision, routes and bounded fixtures.", "Before any temporary credential exists.", ), PhaseContract( "preflight", - "credential-custodian", + ("credential-custodian",), ("acknowledge-target",), "Target is ready and all engagement-specific resources are absent.", "Immediately before the projection cutoff.", ), PhaseContract( "project-custody", - "credential-custodian", + ("credential-custodian",), ("preflight",), "Exactly two scoped handles exist and a value-safe receipt is emitted.", "Inside the narrow projection window; expiry equals engagement end.", ), PhaseContract( "admit-plane", - "security-coordinator", + ("security-coordinator",), ("project-custody",), "Receipt, broker contract, target revision and cleanup authority agree.", "After projection and before any target packet.", ), PhaseContract( "ready-runner", - "cluster-executor", + ("cluster-executor",), ("admit-plane",), "The exact attributed runner is Ready with its Secret mounted.", "Inside the authorized engagement window.", ), PhaseContract( "run-probes", - "security-coordinator", + ( + "security-coordinator", + "tenant-a-attacker", + "tenant-b-control", + ), ("ready-runner",), "Calibrated owner, attacker and absent controls produce a sanitized report.", "Before credential and engagement expiry.", ), PhaseContract( "delete-runner", - "cluster-executor", + ("cluster-executor",), ("run-probes",), "The exact runner pod is absent.", "Immediately after evidence collection.", ), PhaseContract( "cleanup-custody", - "credential-custodian", + ("credential-custodian",), ("delete-runner",), - "Both identities, exact KV paths, projection resources and Secret are absent.", + "Receipt-bound cleanup revokes both identities and removes exact resources.", "Before credential and engagement expiry.", ), PhaseContract( - "finalize-and-deliver", - "security-coordinator", + "verify-cleanup", + ("independent-observer",), ("cleanup-custody",), + "Both identities, exact KV paths, projection resources, Secret and runner " + "are independently absent while the target remains Ready.", + "After cleanup and before credential and engagement expiry.", + ), + PhaseContract( + "finalize-and-deliver", + ("security-coordinator",), + ("verify-cleanup",), "The report is bound to projection and cleanup receipts and reaches risk-nexus.", "Only after cleanup is independently observable.", ), @@ -296,7 +308,7 @@ TEST_USE_CASE = UseCase( "before expiry while the target remains ready", Provenance.SPEC, _cleanup_is_complete, - after_step="cleanup-custody", + after_step="verify-cleanup", source_ref=SPEC_REF, ), ), @@ -328,4 +340,3 @@ TEST_USE_CASE = UseCase( # Alias retained for the existing scenario-module convention. USE_CASE = TEST_USE_CASE -