T05: the lab and its labelled mutation catalogue
lab/app.py (users, tenants, auth, resources, sharing, read/write, revoke, audit), lab/http_api.py (JSON API + browser UI, stdlib only), 20 labelled composable version-stamped mutations, ground-truth matrix. 48 tests pass. Detection against the reference scenario: MECHANICAL 0/10 flagged (correct), DEFECT 6/6, SEMANTIC 2/4 with both inert cases declared. - F-0002: M16 and M18 initially escaped detection entirely. A use case protects exactly what it asserts. Resolved by adding two claims already stated as intent in INTENT.md; the six-mutation catalogue would never have surfaced this. - test-id axis added: stable selectors survive most UI mutations, which would make H-001 trivially false. Mutations now vary on preserves_test_ids so the hypothesis is analysed split by that axis rather than rigged. - M12 (semantic deferred revoke) and M19 (defect race) are behaviourally identical and asserted as such - the discrimination problem as a test. lab/minimal.py removed; superseded by lab/app.py. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 1629012@bnt-lap001 Assistant-Session: 78d4fb13-8a1e-474b-87a3-9b9261c49a39
This commit is contained in:
parent
4d3421ca57
commit
4ddb2f896c
22 changed files with 1091 additions and 207 deletions
|
|
@ -15,7 +15,7 @@ from testdriver import (
|
|||
Claim, InadmissibleProvenance, Invariant, Oracle, Provenance, Runner,
|
||||
SemanticAction, StateObserver, SurfaceNotPermitted, Stratum, Verdict,
|
||||
)
|
||||
from lab.minimal import Denied, MinimalLab, ObservationChannel, build_baseline
|
||||
from lab.app import Denied, LabApp, ObservationChannel, build_baseline
|
||||
from scenarios.alice_bob_carol import build
|
||||
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ def test_actors_cannot_be_recorded_as_judgment_collectors():
|
|||
# --- preview of the M05 authorization defect (built properly in T05) --------
|
||||
|
||||
|
||||
class RevokeIsCosmetic(MinimalLab):
|
||||
class RevokeIsCosmetic(LabApp):
|
||||
"""Revocation updates the record and the audit trail but not enforcement.
|
||||
|
||||
This is the shape of a real authorization defect: everything an operator
|
||||
|
|
@ -101,6 +101,10 @@ class RevokeIsCosmetic(MinimalLab):
|
|||
for r in self.audit
|
||||
)
|
||||
|
||||
# NOTE: this predates the mutation catalogue, where the same defect is M15.
|
||||
# Kept as a direct subclass so the kernel test does not depend on the lab
|
||||
# catalogue's wiring being correct.
|
||||
|
||||
|
||||
def test_seeded_authorization_defect_fails_the_run():
|
||||
"""The kernel must report FAIL, not adapt, when revocation does not revoke."""
|
||||
|
|
@ -124,7 +128,8 @@ def test_seeded_authorization_defect_fails_the_run():
|
|||
assert result.verdict is Verdict.FAIL
|
||||
assert result.judgment("c-bob-revoked").verdict is Verdict.FAIL
|
||||
# The claim set is untouched by the failure — there is no path to adapt it.
|
||||
assert USE_CASE.claims[2].text == "Bob cannot read R after revocation"
|
||||
by_id = {c.id: c for c in USE_CASE.claims}
|
||||
assert by_id["c-bob-revoked"].text == "Bob cannot read R after revocation"
|
||||
|
||||
|
||||
def test_defect_run_emits_an_energy_event():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue