feat(case): KERNEL-2/3 lane resolution and mode-aware admission; CATALOG-1 draft lanes

nk48 1.3 owner review (owner-review-ops-warden.json):
- KERNEL-2: Executor.admit parses catalog_source and resolves descriptor.lane;
  refuses a missing, non-active, undelegated or ungraded lane, an owner outside
  owner_repo, and a mint/change effect on a lane not graded risk high.
  catalog-routing-acceptance still covers the whole catalog digest.
- KERNEL-3: dispatch mode is read from the type's follow_through step
  (warden_executes/attended). The step must declare both booleans and a lane
  and agree with the descriptor's lane and owner. Attended: human actor,
  WARDEN_AGENT_ID unset, parent-session revocation scope, caller lane equal to
  the step lane. Owner: native delegation, owner_repo == descriptor.owner, no
  Warden-executed lane and no Warden-brokered mint.
- CATALOG-1: draft entries keycape-attended-case-change (OW-1.3-C1),
  platform-secret-delivery, consumer-owner-deployment, apps-consumer-handover.
  Not promoted; promotion waits for owner confirmation.
- Fixture catalogs and type steps in tests; published routing_lanes coverage
  and the workload-join count follow the four new not-applicable lanes.

PARAMETER_PINS untouched (PIN-1 waits for founder acknowledgment).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 903097@bnt-lap001
Assistant-Session: aa320c8f-c3fa-46e7-8541-0b58e1e45d23
This commit is contained in:
tegwick 2026-10-17 12:08:49 +02:00
parent 117fec9241
commit a14376cf62
8 changed files with 363 additions and 13 deletions

View file

@ -12,8 +12,47 @@ from warden.case_receipt_state import Outcome, Refused
from warden.case_run import Adapter, Descriptor, Executor, Journal, OwnerResult, digest
@pytest.fixture
def rig(tmp_path):
def lane_entry(lane="issuer-lane", owner="owner", **over):
"""Fixture catalog entry (TEST ONLY; never a real routing pointer)."""
entry = {
"id": lane,
"title": "fixture lane",
"need_keywords": [lane],
"owner_repo": owner,
"subsystem": "fixture",
"warden_executes": False,
"wiki_ref": "wiki/fixture.md",
"canon_ref": "fixture/canon.md",
"reviewed": "2026-10-17",
"status": "active",
"risk": "high",
"workload_ref": {"applicability": "not-applicable", "reason": "fixture"},
"delegation": {
"mode": "native",
"intended_owner": owner,
"reviewed": "2026-10-17",
},
}
entry.update(over)
return entry
def fixture_catalog(*entries):
return yaml.safe_dump({"entries": list(entries) or [lane_entry()]}).encode()
CATALOG = fixture_catalog()
MINT_STEP = {
"id": "mint-secret",
"owner": "owner",
"lane": "issuer-lane",
"warden_executes": True,
"attended": False,
}
def make_rig(tmp_path):
desc = Descriptor(
"warden.case.execution.v1",
"mint-secret",
@ -43,6 +82,7 @@ def rig(tmp_path):
}
],
"execution_descriptors": {"mint-secret": digest(descriptor)},
"follow_through": [dict(MINT_STEP)],
}
}
).encode()
@ -106,7 +146,7 @@ def rig(tmp_path):
("ops-mason-materialization", digest(case), "materialization"),
("owner-descriptor-acceptance:owner", digest(descriptor), "descriptor"),
("type-machine-seam-acceptance", digest(typ), "descriptor"),
("catalog-routing-acceptance", digest(b"catalog"), "descriptor"),
("catalog-routing-acceptance", digest(CATALOG), "descriptor"),
("caller-session:human:operator:issuer-lane", digest(case), "session"),
("session-revocation:issuer-lane", digest(case), "session-revoked"),
("grant-revocation:issuer-lane", digest(case), "grant-revoked"),
@ -136,8 +176,13 @@ def rig(tmp_path):
descriptor_evidence="descriptor",
session_evidence="session",
)
admitted = executor.admit(case, typ, descriptor, b"catalog", **kwargs)
return (executor, admitted, calls, (case, typ, descriptor, b"catalog"), kwargs)
admitted = executor.admit(case, typ, descriptor, CATALOG, **kwargs)
return (executor, admitted, calls, (case, typ, descriptor, CATALOG), kwargs)
@pytest.fixture
def rig(tmp_path):
return make_rig(tmp_path)
def test_commit_running_is_visible_from_separate_connection_before_dispatch(rig):
@ -387,7 +432,7 @@ def test_changed_catalog_pins_cannot_inherit_old_success(rig):
executor, args, calls, sources, kwargs = rig
executor.run(*args)
with pytest.raises(Refused):
executor.admit(*sources[:3], b"changed-catalog", **kwargs)
executor.admit(*sources[:3], fixture_catalog(lane_entry(title="changed")), **kwargs)
assert len(calls) == 1
@ -601,7 +646,7 @@ def test_attempt_identity_changes_with_exact_catalog_revision_and_new_journal(
executor, args, calls, sources, kwargs = rig
executor.run(*args)
original_attempt = calls[-1].attempt_id
new_catalog = b"independently-reviewed-catalog-v2"
new_catalog = fixture_catalog(lane_entry(title="independently reviewed v2"))
old_verifier = executor.evidence_verifier
def verifier(purpose, source, evidence):