WARDEN-WP-0044-T01: warden case check-type; revised oidc-rp 1.0 type conforms
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Mechanical follow-through check (lane, warden_executes, value_handling,
attended justification, read-free verification, rollback coverage). The
revised type passes schema; lanes identity-provisioner-groups and
keycape-client-secret-generate are not yet in the catalog (gate T02).

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 327203@bnt-lap001
Assistant-Session: 55028ae3-4914-4bd1-8f5c-815f3527aef0
This commit is contained in:
tegwick 2026-10-09 00:25:11 +02:00
parent 98cb0bc24a
commit 0e7ceb8c06
5 changed files with 349 additions and 1 deletions

127
tests/test_case_type.py Normal file
View file

@ -0,0 +1,127 @@
"""WARDEN-WP-0044-T01: SecurityCaseType follow-through check."""
from __future__ import annotations
import copy
from pathlib import Path
import pytest
import yaml
from typer.testing import CliRunner
from warden.case_type import check_follow_through, load_type
from warden.cli import app
from warden.routing.catalog import load_catalog
LIVE_TYPE = Path.home() / "net-kingdom/security-case-types/oidc-browser-relying-party/type.yaml"
BASE = {
"apiVersion": "netkingdom.io/security-case-type/v0.1",
"kind": "SecurityCaseType",
"spec": {
"id": "t",
"version": "1.0",
"follow_through": [
{"id": "run", "owner": "o", "entry_point": "e", "auth": "a", "lane": "key-cape-oidc-login",
"warden_executes": True, "attended": False, "value_handling": "none"},
{"id": "login", "owner": "o", "entry_point": "e", "auth": "a", "lane": "key-cape-oidc-login",
"warden_executes": False, "attended": True, "value_handling": "none",
"attended_justification": "live registry is a Secret"},
{"id": "handover", "owner": "o", "entry_point": "e", "auth": "a",
"warden_executes": False, "attended": False, "value_handling": "none"},
],
"verification": [{"id": "v", "check": "c", "expect": "present", "reads_secret_value": False}],
"rollback": [{"reverses": "run"}, {"reverses": "login"}, {"reverses": "handover"}],
},
}
@pytest.fixture(scope="module")
def catalog():
return load_catalog()
def _doc(**step_overrides):
doc = copy.deepcopy(BASE)
doc["spec"]["follow_through"][0].update(step_overrides)
return doc
def _codes(report):
return {f.code for f in report.findings}
def test_conforming_type_is_plannable(catalog):
report = check_follow_through(_doc(), catalog)
assert report.plannable, report.findings
assert report.warden_steps == ["run"]
assert report.attended_lanes == ["key-cape-oidc-login"]
def test_executed_step_without_lane_refused(catalog):
doc = _doc()
del doc["spec"]["follow_through"][0]["lane"]
assert "FT-LANE" in _codes(check_follow_through(doc, catalog))
def test_unknown_lane_is_catalog_finding_not_schema(catalog):
report = check_follow_through(_doc(lane="no-such-lane"), catalog)
assert report.schema_ok and not report.plannable
assert _codes(report) == {"LANE-MISSING"}
def test_value_handling_required_and_enumerated(catalog):
assert "FT-VALUE" in _codes(check_follow_through(_doc(value_handling="returned"), catalog))
doc = _doc()
del doc["spec"]["follow_through"][0]["value_handling"]
assert "FT-FIELD" in _codes(check_follow_through(doc, catalog))
def test_attended_needs_justification_and_excludes_execution(catalog):
doc = copy.deepcopy(BASE)
del doc["spec"]["follow_through"][1]["attended_justification"]
doc["spec"]["follow_through"][1]["warden_executes"] = True
msgs = [f.message for f in check_follow_through(doc, catalog).findings if f.code == "FT-ATTEND"]
assert len(msgs) == 2
def test_attended_step_needs_login_lane(catalog):
doc = copy.deepcopy(BASE)
secret_lane = next(e.id for e in catalog.entries if e.is_active and e.reviewed and e.lane == "secret")
doc["spec"]["follow_through"][1]["lane"] = secret_lane
assert "LANE-KIND" in _codes(check_follow_through(doc, catalog))
def test_generated_value_never_in_attended_session(catalog):
doc = copy.deepcopy(BASE)
doc["spec"]["follow_through"][1]["value_handling"] = "generated_in_custody"
assert "FT-VALUE" in _codes(check_follow_through(doc, catalog))
def test_verification_must_not_read_values(catalog):
doc = _doc()
doc["spec"]["verification"][0]["reads_secret_value"] = True
assert "VER-VALUE" in _codes(check_follow_through(doc, catalog))
def test_every_step_reversible(catalog):
doc = _doc()
doc["spec"]["rollback"] = doc["spec"]["rollback"][1:]
assert "RB-MISSING" in _codes(check_follow_through(doc, catalog))
def test_cli_exit_codes(tmp_path):
good, bad = tmp_path / "good.yaml", tmp_path / "bad.yaml"
good.write_text(yaml.safe_dump(_doc()))
bad.write_text(yaml.safe_dump(_doc(lane="no-such-lane")))
runner = CliRunner()
assert runner.invoke(app, ["case", "check-type", str(good), "--json"]).exit_code == 0
assert runner.invoke(app, ["case", "check-type", str(bad), "--json"]).exit_code == 1
@pytest.mark.skipif(not LIVE_TYPE.exists(), reason="net-kingdom checkout not present")
def test_live_oidc_rp_type_schema_conforms(catalog):
"""The revised 1.0 type meets R1-R3/R5-R7; only the two owner lanes are outstanding."""
report = check_follow_through(load_type(LIVE_TYPE), catalog)
assert report.schema_ok, report.findings
assert report.attended_lanes == ["key-cape-oidc-login"]
assert {f.code for f in report.findings} <= {"LANE-MISSING", "LANE-UNREVIEWED"}