NK-WP-0048-T16 r5: regenerate the 1.3 map and both compositions; tests follow the r5 lanes
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

1.3 composes completely with the new lanes and an all-human actor set. 1.2 is
correctly refused on the three moved lanes and stays plan-only. The 1.2
admission test's unique checks move into test_admit_1_3_type.py. Tests run
against ops-warden 117fec9.

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:01:18 +02:00
parent 407ee5ec36
commit 001a38ca2a
6 changed files with 106 additions and 173 deletions

View file

@ -486,10 +486,10 @@ spec:
# Reviewed machine descriptors (NK-WP-0048-T16 successor candidate). Digests are
# generated by sso-mfa/k8s/keycape/compose-1.2-descriptors.py --version 1.3.
execution_descriptors:
bind-env: sha256:d2511dce3d2ff1d380f845920aa168e6fe09c0f0c382482a796a5bf13619905d
deliver-consumer-secret: sha256:9c289f646516923a4c448a2d3cdd45b33115516e6a171b7955924d8b5d852d2b
bind-env: sha256:d5fcb20cf15bf7454890d2529180c582218e3df12584a99162e4b664b899caa0
deliver-consumer-secret: sha256:36281df8139fb1ec64b226d94f80eb592de5addab7063ff54c691c641e275fc7
deliver-secret: sha256:75aaa7346aebdea2a0eb0ba993995515b5248ffefc34caf8e713525e9b58da85
ensure-groups: sha256:4411b5cb8944ee76ca1ade62c0c246f061981fb18f0b9afd05934a8935598dc3
hand-over: sha256:84f0fac401ea2f1e7c305fb1753a34838ac062655199fcfbbd998f39268c3000
ensure-groups: sha256:ebc9d5b9167d18e6015f4bbeb9699e8d396d64fbfaf195142781f84f4f47a70a
hand-over: sha256:1bce07a3229b7d0c7c730f35ce5b40fe471009a82de8dd53788ed970a9be1224
mint-secret: sha256:c92957227235db04953809d92b260d32c8b947472a8e8fd17a258ade3ae8da70
register-client: sha256:3ccc8eed545cf31f8a48feb8afa0c1355e126d9549eef9737d92d0c1b87708a8
register-client: sha256:4ecc769f75433b66c7161f13c0fe7e5599633cf466d46cb6d8031f0456f426e7

View file

@ -6,39 +6,31 @@
"unchanged": true
},
"check_config_digest": "sha256:be37738fe1c08259fb4f9ca0daf0f9301bfffc237e5bb38435525dfbf11ccff5",
"complete_executable_descriptor_set": true,
"complete_executable_descriptor_set": false,
"dispatch_permitted": false,
"execution_descriptors": {
"bind-env": "sha256:d2511dce3d2ff1d380f845920aa168e6fe09c0f0c382482a796a5bf13619905d",
"deliver-consumer-secret": "sha256:9c289f646516923a4c448a2d3cdd45b33115516e6a171b7955924d8b5d852d2b",
"deliver-secret": "sha256:75aaa7346aebdea2a0eb0ba993995515b5248ffefc34caf8e713525e9b58da85",
"ensure-groups": "sha256:4411b5cb8944ee76ca1ade62c0c246f061981fb18f0b9afd05934a8935598dc3",
"hand-over": "sha256:84f0fac401ea2f1e7c305fb1753a34838ac062655199fcfbbd998f39268c3000",
"mint-secret": "sha256:c92957227235db04953809d92b260d32c8b947472a8e8fd17a258ade3ae8da70",
"register-client": "sha256:3ccc8eed545cf31f8a48feb8afa0c1355e126d9549eef9737d92d0c1b87708a8"
},
"execution_descriptors": null,
"owner_review": false,
"params": {
"consumer_owner_repo": "railiance-apps"
},
"refusal": null,
"refusal": "ensure-groups: lane 'keycape-attended-case-change' does not match the 1.2 type",
"review_requirement": "successor candidate only: new descriptor bytes need a reviewed successor revision under canon section 6 and owner review (NK-WP-0048-T16) before pinning",
"schema": "netkingdom.descriptor-composition-candidate.v1",
"selection": "explicit version root 1.2=security-case-type-revisions/1.2; default root unchanged",
"status": "not_an_admission",
"steps": [
{
"candidate_descriptor_digest": "sha256:4411b5cb8944ee76ca1ade62c0c246f061981fb18f0b9afd05934a8935598dc3",
"candidate_descriptor_digest": "sha256:ebc9d5b9167d18e6015f4bbeb9699e8d396d64fbfaf195142781f84f4f47a70a",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/ensure-groups@v1",
"adapter_source": "sha256:87cc12ada32c4d1296070dd1e8586f35151fcb181ecd89d5d1fbb20c78b50a6f",
"adapter_source": "sha256:f93e68e1932c7ca293c9e69e2d0e1843d58d06a8d4892158fe7d1e0393a21ba0",
"allowed_created": [
"service-group",
"service-group-membership"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -48,7 +40,9 @@
"target_parameter": "client_id",
"version": "warden.case.execution.v1"
},
"findings": [],
"findings": [
"lane 'keycape-attended-case-change' != type lane 'key-cape-oidc-login'"
],
"names_confirmed": null,
"owner_confirmation_required": null,
"step": "ensure-groups",
@ -122,16 +116,16 @@
"type_owner": "railiance-platform"
},
{
"candidate_descriptor_digest": "sha256:d2511dce3d2ff1d380f845920aa168e6fe09c0f0c382482a796a5bf13619905d",
"candidate_descriptor_digest": "sha256:d5fcb20cf15bf7454890d2529180c582218e3df12584a99162e4b664b899caa0",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/keycape-bind-env@v1",
"adapter_source": "sha256:cfc8a7f52494869ead07f9878526a27206c99b0f468673e2e7b111d29d175ddf",
"adapter_source": "sha256:dcd43f5ce1c4e829e1198faffc6bfb9cc610509f5176658f42c133accc0a7305",
"allowed_created": [
"keycape-env-binding"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -141,7 +135,9 @@
"target_parameter": "client_id",
"version": "warden.case.execution.v1"
},
"findings": [],
"findings": [
"lane 'keycape-attended-case-change' != type lane 'key-cape-oidc-login'"
],
"names_confirmed": {
"by": "founder",
"on": "2026-10-17",
@ -154,16 +150,16 @@
"type_owner": "net-kingdom"
},
{
"candidate_descriptor_digest": "sha256:3ccc8eed545cf31f8a48feb8afa0c1355e126d9549eef9737d92d0c1b87708a8",
"candidate_descriptor_digest": "sha256:4ecc769f75433b66c7161f13c0fe7e5599633cf466d46cb6d8031f0456f426e7",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/keycape-registration@v1",
"adapter_source": "sha256:8af23cb5d5fff963d2eff65d8b16dcfd395931ad860357846151019a70b2ed34",
"adapter_source": "sha256:b30f7abfbb5bf439c5ce067325b01c8b711076a38a6fb8484f55d5c8912921f3",
"allowed_created": [
"keycape-client"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -173,7 +169,9 @@
"target_parameter": "client_id",
"version": "warden.case.execution.v1"
},
"findings": [],
"findings": [
"lane 'keycape-attended-case-change' != type lane 'key-cape-oidc-login'"
],
"names_confirmed": null,
"owner_confirmation_required": null,
"step": "register-client",
@ -181,11 +179,11 @@
"type_owner": "net-kingdom"
},
{
"candidate_descriptor_digest": "sha256:9c289f646516923a4c448a2d3cdd45b33115516e6a171b7955924d8b5d852d2b",
"candidate_descriptor_digest": "sha256:36281df8139fb1ec64b226d94f80eb592de5addab7063ff54c691c641e275fc7",
"descriptor": {
"actor": "agent",
"actor": "human",
"adapter": "net-kingdom/deliver-consumer-secret@v1",
"adapter_source": "sha256:8ec63233218f2f9571e1f0605ae29b4378f3126d0ff7f5192e35efa4291f72cd",
"adapter_source": "sha256:66f16dcb665216d09ef63a5ca654283a0292005ba4fb4d79c27eeb54b886a385",
"allowed_created": [
"consumer-eso-sa",
"consumer-secretstore",
@ -216,11 +214,11 @@
"type_owner": "{consumer_owner_repo}"
},
{
"candidate_descriptor_digest": "sha256:84f0fac401ea2f1e7c305fb1753a34838ac062655199fcfbbd998f39268c3000",
"candidate_descriptor_digest": "sha256:1bce07a3229b7d0c7c730f35ce5b40fe471009a82de8dd53788ed970a9be1224",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/apps-handover@v1",
"adapter_source": "sha256:ceaefd44168fa49d4ab1bb0f4870fe43ffd3b6a963b59d53970c97b1ed871155",
"adapter_source": "sha256:4439305b3edcd5d51c73e6438744d8895d69c1ccb58854aac79bb489d868cf48",
"allowed_created": [
"handover-receipt"
],

View file

@ -9,13 +9,13 @@
"complete_executable_descriptor_set": true,
"dispatch_permitted": false,
"execution_descriptors": {
"bind-env": "sha256:d2511dce3d2ff1d380f845920aa168e6fe09c0f0c382482a796a5bf13619905d",
"deliver-consumer-secret": "sha256:9c289f646516923a4c448a2d3cdd45b33115516e6a171b7955924d8b5d852d2b",
"bind-env": "sha256:d5fcb20cf15bf7454890d2529180c582218e3df12584a99162e4b664b899caa0",
"deliver-consumer-secret": "sha256:36281df8139fb1ec64b226d94f80eb592de5addab7063ff54c691c641e275fc7",
"deliver-secret": "sha256:75aaa7346aebdea2a0eb0ba993995515b5248ffefc34caf8e713525e9b58da85",
"ensure-groups": "sha256:4411b5cb8944ee76ca1ade62c0c246f061981fb18f0b9afd05934a8935598dc3",
"hand-over": "sha256:84f0fac401ea2f1e7c305fb1753a34838ac062655199fcfbbd998f39268c3000",
"ensure-groups": "sha256:ebc9d5b9167d18e6015f4bbeb9699e8d396d64fbfaf195142781f84f4f47a70a",
"hand-over": "sha256:1bce07a3229b7d0c7c730f35ce5b40fe471009a82de8dd53788ed970a9be1224",
"mint-secret": "sha256:c92957227235db04953809d92b260d32c8b947472a8e8fd17a258ade3ae8da70",
"register-client": "sha256:3ccc8eed545cf31f8a48feb8afa0c1355e126d9549eef9737d92d0c1b87708a8"
"register-client": "sha256:4ecc769f75433b66c7161f13c0fe7e5599633cf466d46cb6d8031f0456f426e7"
},
"owner_review": false,
"params": {
@ -28,17 +28,17 @@
"status": "not_an_admission",
"steps": [
{
"candidate_descriptor_digest": "sha256:4411b5cb8944ee76ca1ade62c0c246f061981fb18f0b9afd05934a8935598dc3",
"candidate_descriptor_digest": "sha256:ebc9d5b9167d18e6015f4bbeb9699e8d396d64fbfaf195142781f84f4f47a70a",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/ensure-groups@v1",
"adapter_source": "sha256:87cc12ada32c4d1296070dd1e8586f35151fcb181ecd89d5d1fbb20c78b50a6f",
"adapter_source": "sha256:f93e68e1932c7ca293c9e69e2d0e1843d58d06a8d4892158fe7d1e0393a21ba0",
"allowed_created": [
"service-group",
"service-group-membership"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -52,7 +52,7 @@
"names_confirmed": null,
"owner_confirmation_required": null,
"step": "ensure-groups",
"type_lane": "key-cape-oidc-login",
"type_lane": "keycape-attended-case-change",
"type_owner": "net-kingdom"
},
{
@ -118,20 +118,20 @@
},
"owner_confirmation_required": null,
"step": "deliver-secret",
"type_lane": null,
"type_lane": "platform-secret-delivery",
"type_owner": "railiance-platform"
},
{
"candidate_descriptor_digest": "sha256:d2511dce3d2ff1d380f845920aa168e6fe09c0f0c382482a796a5bf13619905d",
"candidate_descriptor_digest": "sha256:d5fcb20cf15bf7454890d2529180c582218e3df12584a99162e4b664b899caa0",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/keycape-bind-env@v1",
"adapter_source": "sha256:cfc8a7f52494869ead07f9878526a27206c99b0f468673e2e7b111d29d175ddf",
"adapter_source": "sha256:dcd43f5ce1c4e829e1198faffc6bfb9cc610509f5176658f42c133accc0a7305",
"allowed_created": [
"keycape-env-binding"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -150,20 +150,20 @@
},
"owner_confirmation_required": null,
"step": "bind-env",
"type_lane": "key-cape-oidc-login",
"type_lane": "keycape-attended-case-change",
"type_owner": "net-kingdom"
},
{
"candidate_descriptor_digest": "sha256:3ccc8eed545cf31f8a48feb8afa0c1355e126d9549eef9737d92d0c1b87708a8",
"candidate_descriptor_digest": "sha256:4ecc769f75433b66c7161f13c0fe7e5599633cf466d46cb6d8031f0456f426e7",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/keycape-registration@v1",
"adapter_source": "sha256:8af23cb5d5fff963d2eff65d8b16dcfd395931ad860357846151019a70b2ed34",
"adapter_source": "sha256:b30f7abfbb5bf439c5ce067325b01c8b711076a38a6fb8484f55d5c8912921f3",
"allowed_created": [
"keycape-client"
],
"effect": "change",
"lane": "key-cape-oidc-login",
"lane": "keycape-attended-case-change",
"owner": "net-kingdom",
"retry_safe": false,
"revocation_scopes": [
@ -177,15 +177,15 @@
"names_confirmed": null,
"owner_confirmation_required": null,
"step": "register-client",
"type_lane": "key-cape-oidc-login",
"type_lane": "keycape-attended-case-change",
"type_owner": "net-kingdom"
},
{
"candidate_descriptor_digest": "sha256:9c289f646516923a4c448a2d3cdd45b33115516e6a171b7955924d8b5d852d2b",
"candidate_descriptor_digest": "sha256:36281df8139fb1ec64b226d94f80eb592de5addab7063ff54c691c641e275fc7",
"descriptor": {
"actor": "agent",
"actor": "human",
"adapter": "net-kingdom/deliver-consumer-secret@v1",
"adapter_source": "sha256:8ec63233218f2f9571e1f0605ae29b4378f3126d0ff7f5192e35efa4291f72cd",
"adapter_source": "sha256:66f16dcb665216d09ef63a5ca654283a0292005ba4fb4d79c27eeb54b886a385",
"allowed_created": [
"consumer-eso-sa",
"consumer-secretstore",
@ -212,15 +212,15 @@
},
"owner_confirmation_required": null,
"step": "deliver-consumer-secret",
"type_lane": null,
"type_lane": "consumer-owner-deployment",
"type_owner": "{consumer_owner_repo}"
},
{
"candidate_descriptor_digest": "sha256:84f0fac401ea2f1e7c305fb1753a34838ac062655199fcfbbd998f39268c3000",
"candidate_descriptor_digest": "sha256:1bce07a3229b7d0c7c730f35ce5b40fe471009a82de8dd53788ed970a9be1224",
"descriptor": {
"actor": "human",
"adapter": "net-kingdom/apps-handover@v1",
"adapter_source": "sha256:ceaefd44168fa49d4ab1bb0f4870fe43ffd3b6a963b59d53970c97b1ed871155",
"adapter_source": "sha256:4439305b3edcd5d51c73e6438744d8895d69c1ccb58854aac79bb489d868cf48",
"allowed_created": [
"handover-receipt"
],
@ -245,7 +245,7 @@
},
"owner_confirmation_required": null,
"step": "hand-over",
"type_lane": null,
"type_lane": "apps-consumer-handover",
"type_owner": "{consumer_owner_repo}"
}
],

View file

@ -1,98 +0,0 @@
"""Kernel admission of every 1.2 descriptor with fixture-only trust (NK48-R1-F1).
Descriptor.decode alone missed that the kernel refuses an agent mint. Each of the
seven composed descriptors goes through Warden's own Executor.admit here, with the
real 1.2 type, the 1.2 forgejo example case and the reviewed browser validator.
Adapters are stand-ins carrying only the pinned reference and source; nothing is
dispatched. Admission here is a fixture, not owner admission or a pin.
"""
from dataclasses import replace
import importlib.util
import json
import os
from pathlib import Path
import tempfile
import unittest
from unittest import mock
import yaml
from warden.case_run import Adapter, Executor, Journal, digest
from warden.case_receipt_state import Refused
import warden.case_inputs as inputs
ROOT = Path(__file__).parent
REPO = ROOT.parents[2]
spec = importlib.util.spec_from_file_location('compose_12_admit', ROOT / 'compose-1.2-descriptors.py')
c = importlib.util.module_from_spec(spec)
spec.loader.exec_module(c)
TYPE_DIR = REPO / 'security-case-type-revisions/1.2/oidc-browser-relying-party'
ARTIFACT = json.loads((ROOT / 'descriptor-composition-1.2.candidate.json').read_text())
EVIDENCE = {'fixture-acceptance', 'fixture-materialization', 'fixture-descriptor', 'fixture-session'}
def unused(*_):
raise AssertionError('admission must not dispatch')
class AdmitDescriptorSetTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
case = yaml.safe_load((TYPE_DIR / 'examples/forgejo.yaml').read_bytes())
case['spec'].update(status='materialized', acceptance={
'at': '2026-10-17', 'record': 'fixture-only acceptance, not an owner record',
'by': [{'name': 'fixture', 'role': 'owner'}, {'name': 'fixture', 'role': 'founder'}]})
self.case_source = yaml.safe_dump(case).encode()
self.descriptors = dict(c.adapter_descriptors(ARTIFACT['check_config_digest'],
ARTIFACT['params']['consumer_owner_repo']))
def admit(self, desc, *, actor=None, lane=None):
desc_bytes = c.encode(desc)
typ = yaml.safe_load((TYPE_DIR / 'type.yaml').read_bytes())
typ['spec']['execution_descriptors'] = {desc.step: digest(desc_bytes)}
adapter = Adapter(desc.adapter, desc.adapter_source, unused, unused)
executor = Executor(Journal(Path(self.temp.name) / desc.step),
{adapter.reference: adapter},
lambda purpose, source, evidence: evidence in EVIDENCE,
browser_inputs=inputs.BrowserInputs(REPO))
with mock.patch.dict(os.environ):
os.environ.pop('WARDEN_AGENT_ID', None)
return executor.admit(self.case_source, yaml.safe_dump(typ).encode(), desc_bytes,
b'fixture-only-catalog', principal='founder', actor=actor or desc.actor,
lane=lane or desc.lane, acceptance_evidence='fixture-acceptance',
materialization_evidence='fixture-materialization',
descriptor_evidence='fixture-descriptor', session_evidence='fixture-session')
def test_composed_descriptors_are_the_committed_artifact(self):
self.assertEqual({s: digest(c.encode(d)) for s, d in self.descriptors.items()},
ARTIFACT['execution_descriptors'])
def test_every_1_2_descriptor_passes_kernel_admission(self):
self.assertEqual(len(self.descriptors), 7)
for step, desc in self.descriptors.items():
with self.subTest(step=step):
admitted_desc, invocation, _ = self.admit(desc)
self.assertEqual(admitted_desc, desc)
self.assertEqual((invocation.step, invocation.owner, invocation.lane,
invocation.actor, invocation.target),
(desc.step, desc.owner, desc.lane, desc.actor, 'forgejo'))
def test_mint_secret_admits_only_a_human_actor(self):
mint = self.descriptors['mint-secret']
self.assertEqual((mint.effect, mint.actor), ('mint', 'human'))
with self.assertRaisesRegex(Refused, 'agent mint is forbidden'):
self.admit(replace(mint, actor='agent'))
with self.assertRaisesRegex(Refused, 'principal actor or lane mismatch'):
self.admit(mint, actor='agent')
def test_wrong_lane_is_refused(self):
for step, desc in self.descriptors.items():
with self.subTest(step=step), self.assertRaisesRegex(
Refused, 'principal actor or lane mismatch'):
self.admit(desc, lane='wrong-lane')
if __name__ == '__main__':
unittest.main()

View file

@ -74,7 +74,7 @@ class Admit13TypeTests(unittest.TestCase):
ARTIFACT['params']['consumer_owner_repo'],
version='1.3'))
def admit(self, desc, type_source):
def admit(self, desc, type_source, *, actor=None, lane=None):
desc_bytes = c.encode(desc)
adapter = Adapter(desc.adapter, desc.adapter_source, unused, unused)
executor = Executor(Journal(Path(self.temp.name) / desc.step),
@ -84,7 +84,8 @@ class Admit13TypeTests(unittest.TestCase):
with mock.patch.dict(os.environ):
os.environ.pop('WARDEN_AGENT_ID', None)
return executor.admit(self.case_source, type_source, desc_bytes,
b'fixture-only-catalog', principal='founder', actor=desc.actor, lane=desc.lane,
b'fixture-only-catalog', principal='founder', actor=actor or desc.actor,
lane=lane or desc.lane,
acceptance_evidence='fixture-acceptance',
materialization_evidence='fixture-materialization',
descriptor_evidence='fixture-descriptor', session_evidence='fixture-session')
@ -129,6 +130,22 @@ class Admit13TypeTests(unittest.TestCase):
Refused, 'no exact acknowledged machine descriptor'):
self.admit(changed, acknowledged)
def test_mint_secret_admits_only_a_human_actor(self):
# Moved from test_admit_1_2_adapter_descriptors.py (NK48-R1-F1) in r5.
acknowledged = with_status('acknowledged')
mint = self.descriptors['mint-secret']
self.assertEqual((mint.effect, mint.actor), ('mint', 'human'))
with pinned_13(), self.assertRaisesRegex(Refused, 'principal actor or lane mismatch'):
self.admit(mint, acknowledged, actor='agent')
def test_wrong_lane_is_refused(self):
# Moved from test_admit_1_2_adapter_descriptors.py in r5.
acknowledged = with_status('acknowledged')
for step, desc in self.descriptors.items():
with self.subTest(step=step), pinned_13(), self.assertRaisesRegex(
Refused, 'principal actor or lane mismatch'):
self.admit(desc, acknowledged, lane='wrong-lane')
def test_earlier_versions_carry_no_execution_map(self):
for version in ('1.2',):
path = REPO / f'security-case-type-revisions/{version}/oidc-browser-relying-party/type.yaml'

View file

@ -109,27 +109,43 @@ class ComposeTests(unittest.TestCase):
c.artifact(CHECKER, PARAMS)
self.assertEqual(path.read_bytes(), before)
def test_current_adapters_do_not_compose(self):
# Pins the present source findings; this test must change when they are fixed.
def test_1_2_composition_is_refused_on_the_r5_lanes(self):
# r5 (OW-1.3-C1) moved three net-kingdom steps to keycape-attended-case-change,
# which the acknowledged 1.2 type does not declare. 1.2 stays plan-only.
doc = c.artifact(CHECKER, PARAMS)
# Complete in source with mint-secret's actor 'human'; still not an admission.
self.assertFalse(doc['complete_executable_descriptor_set'])
self.assertIsNone(doc['execution_descriptors'])
findings = {r['step']: r['findings'] for r in doc['steps'] if r['findings']}
self.assertEqual(findings, {step: ["lane 'keycape-attended-case-change' != type lane "
"'key-cape-oidc-login'"]
for step in ('ensure-groups', 'bind-env', 'register-client')})
def test_current_adapters_compose_for_1_3(self):
doc = c.artifact(CHECKER, PARAMS, version='1.3')
self.assertTrue(doc['complete_executable_descriptor_set'])
self.assertEqual(len(doc['execution_descriptors']), 7)
self.assertIsNone(doc['refusal'])
self.assertFalse(doc['admitted'] or doc['owner_review'] or doc['dispatch_permitted'])
findings = {r['step']: r['findings'] for r in doc['steps']}
self.assertEqual({s for s, f in findings.items() if f}, set())
mint = next(r for r in doc['steps'] if r['step'] == 'mint-secret')
self.assertEqual(mint['descriptor']['actor'], 'human')
hand_over = next(r for r in doc['steps'] if r['step'] == 'hand-over')
self.assertEqual(hand_over['descriptor']['owner'], PARAMS['consumer_owner_repo'])
self.assertNotIn('owner', hand_over['names_confirmed'])
self.assertEqual({r['step'] for r in doc['steps'] if r['findings']}, set())
by_step = {r['step']: r['descriptor'] for r in doc['steps']}
self.assertEqual({s: d['actor'] for s, d in by_step.items()},
{s: 'human' for s in by_step}) # RAPPS-1.3-C1: no agent step remains
self.assertEqual({s: d['lane'] for s, d in by_step.items()}, {
'ensure-groups': 'keycape-attended-case-change',
'bind-env': 'keycape-attended-case-change',
'register-client': 'keycape-attended-case-change',
'mint-secret': 'keycape-client-secret-generate',
'deliver-secret': 'platform-secret-delivery',
'deliver-consumer-secret': 'consumer-owner-deployment',
'hand-over': 'apps-consumer-handover'})
self.assertEqual(by_step['hand-over']['owner'], PARAMS['consumer_owner_repo'])
self.assertFalse(any(r['owner_confirmation_required'] for r in doc['steps']))
confirmed = {r['step'] for r in doc['steps'] if r['names_confirmed']}
self.assertEqual(confirmed, {'mint-secret', 'deliver-secret', 'bind-env',
'deliver-consumer-secret', 'hand-over'})
self.assertTrue(all(r['names_confirmed']['by'] == 'founder'
for r in doc['steps'] if r['names_confirmed']))
def test_committed_1_3_artifact_matches_regeneration(self):
import json
committed = json.loads((ROOT / 'descriptor-composition-1.3.candidate.json').read_text())
regenerated = c.artifact(committed['check_config_digest'], committed['params'], version='1.3')
self.assertEqual(json.loads(json.dumps(regenerated)), committed)
def test_committed_artifact_matches_regeneration(self):
import json