feat(admission): founder-signed trust and recovery-attempt admission (WP14 T02, WP15 T05)
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s

Reuse the gated-executor approval pattern: ssh-keygen -Y signatures over exact
bytes, verified against a runtime-unwritable allowed_signers anchor with a fixed
namespace per purpose. load_trust now refuses responder trust without a founder
admission; the KeyCape selector preflight gains --admission for one exact,
bounded recovery attempt. WP14 re-pointed to CUST-WP-0082-T06 and split founder
key admission into human-gated T04; WP15 T04 now requires the signed admission.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 809600@bnt-lap001
Assistant-Session: 40ba228f-c8a0-4ec9-bb29-3129951afdc4
This commit is contained in:
tegwick 2026-10-21 00:30:59 +02:00
parent 497040c58c
commit ebd8e49aff
15 changed files with 469 additions and 29 deletions

View file

@ -20,7 +20,7 @@ from secrets_engine.execution_contract import ExecutionContract
from secrets_engine.task_execution_handoff import (authorize_task_execution,consume_task_execution,
TaskExecutionAuthorization)
from tests.authorization_stub import AuthorizationStub
from tests.signature_support import signature_tools, admit_tools, sign_envelope
from tests.signature_support import signature_tools, admit_tools, sign_envelope, admit
from tests.test_consume_binding_join import _Cfg,_token,APPROVAL_ID
from tests.test_execution_context import entry,descriptor
@ -168,7 +168,7 @@ def test_changed_owner_coordinates_refuse_before_cas(lane,field):
def test_removed_signer_refuses_before_cas(lane):
cfg,e,contract,state=lane;result=prepared(lane)
trust=json.loads(cfg.pdp_trust_file.read_text());trust['keys']={'other':next(iter(trust['keys'].values()))}
cfg.pdp_trust_file.write_text(json.dumps(trust))
cfg.pdp_trust_file.write_text(json.dumps(trust));admit(cfg.pdp_trust_file)
with pytest.raises(DecisionError):consume_task_execution(cfg,result)
assert 'consume' not in state['calls']