2026-09-09 07:06:05 +02:00
#!/usr/bin/env python3
""" Disposable KeyCape image -> actual Secrets Engine client -> Approval Engine.
Synthetic keys / credentials only . No OpenBao , cluster mutation , or model call .
2026-09-09 08:55:46 +02:00
The actual Flex Auth evaluator runs locally with its published policy / registry .
This is component conformance evidence , not production authorization evidence .
2026-09-09 07:06:05 +02:00
"""
from __future__ import annotations
import argparse
import base64
import copy
import hashlib
import http . server
2026-09-10 09:29:38 +02:00
import io
2026-09-09 07:06:05 +02:00
import ipaddress
import json
import os
from pathlib import Path
import secrets
2026-09-10 09:29:38 +02:00
import shutil
2026-09-09 07:06:05 +02:00
import socket
import ssl
import subprocess
import sys
import tempfile
import threading
import time
2026-09-10 09:29:38 +02:00
from contextlib import contextmanager , redirect_stdout
2026-09-09 07:06:05 +02:00
from datetime import datetime , timedelta , timezone
from urllib . error import HTTPError
from urllib . parse import urlencode
from urllib . request import Request , urlopen
from unittest . mock import patch
from wsgiref . simple_server import WSGIRequestHandler , make_server
from cryptography import x509
from cryptography . hazmat . primitives import hashes , serialization
from cryptography . hazmat . primitives . asymmetric import rsa
from cryptography . x509 . oid import NameOID
import yaml
KEYCAPE_IMAGE = " forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611 "
ROOT = Path ( __file__ ) . resolve ( ) . parents [ 1 ]
sys . path [ : 0 ] = [ str ( ROOT / " src " ) , str ( ROOT ) ]
def run ( args ) :
result = subprocess . run ( args , capture_output = True , timeout = 45 )
if result . returncode :
raise RuntimeError ( " contained command failed " )
return result . stdout . decode ( ) . strip ( )
def commit ( path ) :
return run ( [ " git " , " -C " , str ( path ) , " rev-parse " , " HEAD " ] )
def private_write ( path , value ) :
with path . open ( " x " ) as out :
os . chmod ( path , 0o600 )
out . write ( value )
def exercise ( args ) :
sys . path . insert ( 0 , str ( args . approval_engine_source ) )
from approval_engine . api import App
from approval_engine . auth import JWTAuthenticator
from approval_engine . store import Engine
from secrets_engine import cli
from secrets_engine . approval_auth import approval_token , credential_urlopen
from secrets_engine . approval_consume import ConsumeBinding , _expected_request , consume_approval
2026-09-09 08:55:46 +02:00
from secrets_engine . authorization import request_digest , validate_decision_envelope
2026-09-09 07:06:05 +02:00
from secrets_engine . catalog import validate_entry
from secrets_engine . config import Config
from secrets_engine . errors import BackendError , DecisionError
from tests . authorization_stub import AuthorizationStub
from tests . test_catalog import VALID
receipt = {
" schema_version " : 1 , " target " : " disposable local processes; synthetic credentials " ,
" started_at " : datetime . now ( timezone . utc ) . isoformat ( ) ,
" keycape_image " : KEYCAPE_IMAGE ,
" approval_engine_commit " : commit ( args . approval_engine_source ) ,
2026-09-09 08:55:46 +02:00
" flex_auth_commit " : commit ( args . flex_auth_source ) ,
2026-09-09 07:06:05 +02:00
" keycape_contract_commit " : commit ( args . keycape_source ) ,
" consumer_source_sha256 " : {
name : hashlib . sha256 ( ( ROOT / " src/secrets_engine " / name ) . read_bytes ( ) ) . hexdigest ( )
2026-09-10 09:29:38 +02:00
for name in ( " approval_auth.py " , " approval_consume.py " , " approval_claim.py " , " authorization.py " , " config.py " , " service_auth.py " , " cli.py " , " catalog.py " , " exec_owner.py " , " exec_delivery.py " , " routing.py " )
2026-09-09 07:06:05 +02:00
} ,
2026-09-09 08:55:46 +02:00
" limitations " : [ " standalone Flex Auth source, not deployed pin " , " local Approval Engine source, not deployed image " ,
2026-09-09 07:06:05 +02:00
" no live custody or client-side read grant " , " no OpenBao effect or model execution " ] ,
" checks " : { } ,
}
with tempfile . TemporaryDirectory ( prefix = " approval-identity-private- " ) as temporary :
root = Path ( temporary )
2026-09-09 08:55:46 +02:00
source = args . flex_auth_source . resolve ( )
run ( [ " go " , " build " , " -C " , str ( source ) , " -o " , str ( root / " flex-auth " ) , " ./cmd/flex-auth " ] )
producer_files = source / " examples/secrets-engine "
receipt [ " flex_auth_binary_sha256 " ] = hashlib . sha256 ( ( root / " flex-auth " ) . read_bytes ( ) ) . hexdigest ( )
receipt [ " producer_input_sha256 " ] = {
name : hashlib . sha256 ( ( producer_files / name ) . read_bytes ( ) ) . hexdigest ( )
for name in ( " policy_package.md " , " registry_snapshot.json " )
}
class ProducerPDP ( AuthorizationStub ) :
""" Loopback transport only; every decision comes from the Go evaluator. """
last_decision = None
def decision ( self , request ) :
path = root / " check-request.json "
path . write_text ( json . dumps ( request ) )
path . chmod ( 0o600 )
self . last_decision = json . loads ( run ( [ str ( root / " flex-auth " ) , " check " ,
" -policy " , str ( producer_files / " policy_package.md " ) ,
" -registry " , str ( producer_files / " registry_snapshot.json " ) , " -request " , str ( path ) ] ) )
return self . last_decision
def bind_request ( self , request ) :
# At issue, record the evaluator's claim-free digest, even if
# the destructive action denies until approval is supplied.
return self . decision ( request ) [ " binding " ] [ " request_digest " ]
2026-09-09 07:06:05 +02:00
key = rsa . generate_private_key ( public_exponent = 65537 , key_size = 2048 )
private_write ( root / " key.pem " , key . private_bytes ( serialization . Encoding . PEM ,
serialization . PrivateFormat . PKCS8 , serialization . NoEncryption ( ) ) . decode ( ) )
now = datetime . now ( timezone . utc )
name = x509 . Name ( [ x509 . NameAttribute ( NameOID . COMMON_NAME , " local approval identity exercise " ) ] )
cert = ( x509 . CertificateBuilder ( ) . subject_name ( name ) . issuer_name ( name ) . public_key ( key . public_key ( ) )
. serial_number ( x509 . random_serial_number ( ) ) . not_valid_before ( now - timedelta ( minutes = 1 ) )
. not_valid_after ( now + timedelta ( hours = 1 ) )
. add_extension ( x509 . SubjectAlternativeName ( [ x509 . IPAddress ( ipaddress . ip_address ( " 127.0.0.1 " ) ) ] ) , False )
. add_extension ( x509 . BasicConstraints ( ca = True , path_length = None ) , True )
. sign ( key , hashes . SHA256 ( ) ) )
( root / " cert.pem " ) . write_bytes ( cert . public_bytes ( serialization . Encoding . PEM ) )
with socket . socket ( ) as sock :
sock . bind ( ( " 127.0.0.1 " , 0 ) )
keycape_port = sock . getsockname ( ) [ 1 ]
class Proxy ( http . server . BaseHTTPRequestHandler ) :
def log_message ( self , * _args ) :
pass
def proxy ( self ) :
body = self . rfile . read ( int ( self . headers . get ( " Content-Length " , 0 ) ) ) if self . command == " POST " else None
req = Request ( f " http://127.0.0.1: { keycape_port } " + self . path , data = body ,
headers = { k : self . headers [ k ] for k in ( " Content-Type " , " Authorization " ) if k in self . headers } )
try :
response = urlopen ( req , timeout = 10 )
except HTTPError as error :
response = error
with response :
self . send_response ( response . code )
self . send_header ( " Content-Type " , " application/json " )
self . end_headers ( )
self . wfile . write ( response . read ( ) )
do_GET = proxy
do_POST = proxy
server = http . server . ThreadingHTTPServer ( ( " 127.0.0.1 " , 0 ) , Proxy )
context = ssl . SSLContext ( ssl . PROTOCOL_TLS_SERVER )
context . load_cert_chain ( root / " cert.pem " , root / " key.pem " )
server . socket = context . wrap_socket ( server . socket , server_side = True )
issuer = f " https://127.0.0.1: { server . server_port } "
proxy_thread = threading . Thread ( target = server . serve_forever , daemon = True )
proxy_thread . start ( )
config = yaml . safe_load ( ( args . keycape_source / " config/dev-config.yaml " ) . read_text ( ) )
clients = yaml . safe_load ( ( args . keycape_source / " config/service-clients.example.yaml " ) . read_text ( ) ) [ " clients " ]
clients = [ c for c in clients if c [ " clientId " ] in ( " secrets-engine-approval " , " approval-engine-operator " ) ]
assert len ( clients ) == 2
config . update ( issuer = issuer , clients = clients )
config [ " authelia " ] [ " issuer " ] = " https://synthetic-upstream.invalid "
private_write ( root / " config.yaml " , yaml . safe_dump ( config , sort_keys = False ) )
values = { c [ " clientId " ] : secrets . token_urlsafe ( 48 ) for c in clients }
private_write ( root / " env " , " KEYCAPE_CONFIG=/etc/keycape/config.yaml \n " + " " . join (
c [ " secretRef " ] . removeprefix ( " env: " ) + " = " + values [ c [ " clientId " ] ] + " \n " for c in clients ) )
private_write ( root / " approval.secret " , values [ " secrets-engine-approval " ] )
private_write ( root / " pdp.token " , " synthetic-pdp-token " )
container = " approval-identity-exercise- " + secrets . token_hex ( 5 )
created = False
engine = None
api_server = None
pdp = None
try :
run ( [ " docker " , " run " , " -d " , " --rm " , " --name " , container , " --user " , str ( os . getuid ( ) ) ,
" --read-only " , " --cap-drop=ALL " , " --security-opt=no-new-privileges " ,
" --publish " , f " 127.0.0.1: { keycape_port } :8080 " , " --env-file " , str ( root / " env " ) ,
" --mount " , " type=bind,source= " + temporary + " ,target=/etc/keycape,readonly " , KEYCAPE_IMAGE ] )
created = True
with patch . dict ( os . environ , { " SSL_CERT_FILE " : str ( root / " cert.pem " ) , " SECRETS_ENGINE_UNSAFE_DEMO " : " " } ) :
for _ in range ( 40 ) :
try :
with credential_urlopen ( issuer + " /jwks " , timeout = 1 ) as response :
if response . status == 200 :
break
except Exception :
time . sleep ( 0.25 )
else :
raise RuntimeError ( " disposable KeyCape did not start " )
engine = Engine ( root / " approval.sqlite " )
app = App ( engine , JWTAuthenticator ( issuer = issuer , audience = " approval-engine " , jwks_url = issuer + " /jwks " ) )
class Quiet ( WSGIRequestHandler ) :
def log_message ( self , * _args ) :
pass
api_server = make_server ( " 127.0.0.1 " , 0 , app , handler_class = Quiet )
threading . Thread ( target = api_server . serve_forever , daemon = True ) . start ( )
api = f " http://127.0.0.1: { api_server . server_port } "
def operator_token ( scope ) :
credential = base64 . b64encode ( ( " approval-engine-operator: " + values [ " approval-engine-operator " ] ) . encode ( ) ) . decode ( )
req = Request ( issuer + " /token " , data = urlencode ( { " grant_type " : " client_credentials " , " scope " : scope } ) . encode ( ) ,
headers = { " Authorization " : " Basic " + credential } )
with credential_urlopen ( req , timeout = 3 ) as response :
return json . load ( response ) [ " access_token " ]
def operator_request ( path , payload , scope ) :
req = Request ( api + path , data = json . dumps ( payload ) . encode ( ) ,
headers = { " Content-Type " : " application/json " , " Authorization " : " Bearer " + operator_token ( scope ) } )
with credential_urlopen ( req , timeout = 3 ) as response :
return json . load ( response )
raw = copy . deepcopy ( VALID )
raw [ " stage " ] = " prod "
raw [ " approval " ] = { " model " : " bootstrap-only " , " authorization_id " : " synthetic-approval " , " purpose " : " disposable identity proof " }
entry = validate_entry ( raw )
2026-09-09 08:55:46 +02:00
pdp = ProducerPDP ( approval_id = " unused " , package = " secrets-engine.catalog-lane.lifecycle " , version = " v2 " ) . start ( )
2026-09-09 07:06:05 +02:00
cfg = Config ( catalog_dir = root , policy_dir = root , evidence_dir = root / " evidence " , hub_url = " " , bao_addr = " " , topic_id = " " ,
approval_url = api , approval_client_secret_file = root / " approval.secret " ,
keycape_issuer = issuer , keycape_token_url = issuer + " /token " ,
authorization_subject_id = " secrets-engine " , authorization_subject_type = " service " ,
authorization_policy_package = " secrets-engine.catalog-lane.lifecycle " , authorization_policy_version = " v2 " ,
pdp_url = pdp . url , pdp_token_file = root / " pdp.token " )
request = _expected_request ( cfg , entry , " apply " )
digest = pdp . bind_request ( request )
obj = operator_request ( " /v1/approvals " , {
" id " : " synthetic-approval " ,
" binding " : { " action " : " secrets.apply " , " target " : { " id " : entry . id , " stage " : " prod " } ,
" actor " : " service:approval-engine-operator " , " principal " : " synthetic-operator " , " purpose " : " disposable identity proof " } ,
" validity " : { " not_before " : ( now - timedelta ( minutes = 1 ) ) . isoformat ( ) , " expires_at " : ( now + timedelta ( minutes = 10 ) ) . isoformat ( ) } ,
" pdp_digest " : digest , " pdp_path " : True } , " approval:create " )
operator_request ( f " /v1/approvals/ { obj [ ' id ' ] } /entries " , { } , " approval:approve " )
receipt [ " checks " ] [ " operator_issued_and_approved_via_verified_jwt " ] = True
try :
cli . _require_lane_approval ( cfg , entry , " destroy " )
except DecisionError :
assert not engine . claim ( obj [ " id " ] ) [ " consumed " ]
else :
raise AssertionError ( " wrong action accepted " )
receipt [ " checks " ] [ " wrong_action_refused_before_consume " ] = True
cli . _require_lane_approval ( cfg , entry , " apply " )
assert engine . claim ( obj [ " id " ] ) [ " consumed " ]
2026-09-09 08:55:46 +02:00
assert pdp . calls == [ " check " , " check " ]
accepted = pdp . last_decision
assert accepted [ " binding " ] [ " approval_binding_digest " ] == digest
assert accepted [ " binding " ] [ " request_digest " ] != digest
assert accepted [ " binding " ] [ " submitted_request_digest " ] != accepted [ " binding " ] [ " request_digest " ]
assert accepted [ " binding " ] [ " context " ] [ " approval " ] [ " approval_id " ] == obj [ " id " ]
receipt [ " checks " ] [ " producer_origin_join_with_carried_claim " ] = True
2026-09-09 07:06:05 +02:00
receipt [ " checks " ] [ " actual_consumer_claim_check_consume " ] = True
2026-09-09 08:55:46 +02:00
binding = ConsumeBinding ( obj [ " id " ] , accepted [ " binding " ] [ " request_digest " ] , accepted [ " id " ] )
2026-09-09 07:06:05 +02:00
retry = consume_approval ( base_url = api , binding = binding , token_provider = lambda : approval_token ( cfg , scope = " approval:consume " ) )
assert retry . idempotent
receipt [ " checks " ] [ " same_digest_retry_idempotent " ] = True
try :
consume_approval ( base_url = api , binding = ConsumeBinding ( obj [ " id " ] , " sha256: " + " f " * 64 ) ,
token_provider = lambda : approval_token ( cfg , scope = " approval:consume " ) )
except DecisionError :
pass
else :
raise AssertionError ( " different digest accepted " )
receipt [ " checks " ] [ " different_digest_refused " ] = True
try :
cli . _require_lane_approval ( cfg , entry , " apply " )
except DecisionError :
pass
else :
raise AssertionError ( " spent claim accepted " )
receipt [ " checks " ] [ " spent_claim_refused " ] = True
try :
operator_token ( " approval:consume " )
except HTTPError as error :
assert error . code in ( 400 , 401 )
assert json . load ( error ) [ " error " ] == " invalid_profile_usage "
else :
raise AssertionError ( " operator consume scope accepted " )
receipt [ " checks " ] [ " operator_consume_scope_denied_by_issuer " ] = True
( root / " approval.secret " ) . write_text ( " synthetic-wrong-secret " )
try :
approval_token ( cfg , scope = " approval:read " )
except BackendError :
pass
else :
raise AssertionError ( " wrong secret accepted " )
receipt [ " checks " ] [ " wrong_secret_refused " ] = True
assert not ( root / " approval.token " ) . exists ( )
receipt [ " checks " ] [ " no_access_token_file_created " ] = True
2026-09-09 08:55:46 +02:00
# Independent input -> evaluator -> consumer: registry may
# override a caller's same-key facts without breaking replay.
request = json . loads ( ( producer_files / " check_request_allow_rotate.json " ) . read_text ( ) )
request [ " subject " ] [ " attributes " ] = { " roles " : [ " UntrustedCallerRole " ] }
decision = pdp . decision ( request )
assert decision [ " binding " ] [ " subject " ] [ " attributes " ] [ " roles " ] == [ " Operator " ]
assert decision [ " binding " ] [ " submitted_request_digest " ] == request_digest ( request )
validate_decision_envelope ( decision , request ,
accepted_policy_packages = { " secrets-engine.catalog-lane.lifecycle " } , accepted_policy_versions = { " v2 " } )
receipt [ " checks " ] [ " registry_override_accepts_exact_submission " ] = True
replay = copy . deepcopy ( request )
replay [ " subject " ] [ " attributes " ] [ " roles " ] = [ " Operator " ]
try :
validate_decision_envelope ( decision , replay ,
accepted_policy_packages = { " secrets-engine.catalog-lane.lifecycle " } , accepted_policy_versions = { " v2 " } )
except DecisionError :
pass
else :
raise AssertionError ( " changed submission replayed " )
receipt [ " checks " ] [ " same_enriched_result_different_submission_refused " ] = True
# Real dual-control policy: empty claim denies; fresh issued
# claim passes. No destructive backend is connected.
raw [ " approval " ] [ " authorization_id " ] = " synthetic-destroy "
destroy_entry = validate_entry ( raw )
destroy_request = _expected_request ( cfg , destroy_entry , " destroy " )
denied = pdp . decision ( destroy_request )
assert denied [ " effect " ] == " deny " and denied [ " reason " ] == " dual_control_required "
operator_request ( " /v1/approvals " , {
" id " : " synthetic-destroy " , " binding " : { " action " : " secrets.kv.destroy " , " target " : { " id " : destroy_entry . id , " stage " : " prod " } ,
" actor " : " service:approval-engine-operator " , " principal " : " synthetic-operator " , " purpose " : " disposable identity proof " } ,
" validity " : { " not_before " : ( now - timedelta ( minutes = 1 ) ) . isoformat ( ) , " expires_at " : ( now + timedelta ( minutes = 10 ) ) . isoformat ( ) } ,
" pdp_digest " : denied [ " binding " ] [ " request_digest " ] , " pdp_path " : True } , " approval:create " )
operator_request ( " /v1/approvals/synthetic-destroy/entries " , { } , " approval:approve " )
( root / " approval.secret " ) . write_text ( values [ " secrets-engine-approval " ] )
cli . _require_lane_approval ( cfg , destroy_entry , " destroy " )
assert engine . claim ( " synthetic-destroy " ) [ " consumed " ]
receipt [ " checks " ] [ " real_dual_control_denial_then_claim_check_consume " ] = True
2026-09-10 09:29:38 +02:00
if args . exec_owner :
from secrets_engine . errors import DeliveryError
from secrets_engine . exec_owner import owner_digest
from types import SimpleNamespace
# Synthetic recipient and backend, real engine CLI, exact
# producer digest, JWT claim/consume, spawn and environment.
owner_dir = root / " exec-owner "
owner_dir . mkdir ( mode = 0o700 )
executable = owner_dir / " dash "
shutil . copyfile ( " /bin/dash " , executable )
executable . chmod ( 0o700 )
script = owner_dir / " owner.sh "
private_write ( script , ' test " $API_TOKEN " = synthetic-owner-value || exit 10 \n '
' test -z " $SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE " || exit 11 \n '
' test -z " $BAO_TOKEN " || exit 12 \n '
' printf " owner-delivery-ok \\ n " \n ' )
raw [ " approval " ] [ " authorization_id " ] = " synthetic-owner-delivery "
raw [ " delivery_config " ] = { " exec_owner " : {
" status " : " configured " , " owner " : " synthetic-metered-owner " ,
" command " : [ str ( executable ) , str ( script ) ] , " cwd " : str ( owner_dir ) ,
" environment " : { " PATH " : " /usr/bin:/bin " , " LANG " : " C.UTF-8 " } ,
" files " : { str ( p ) : { " sha256 " : hashlib . sha256 ( p . read_bytes ( ) ) . hexdigest ( ) , " private " : True }
for p in [ executable , script ] } ,
} }
2026-09-10 20:16:55 +02:00
if args . human_control :
raw [ " approval " ] . update ( model = " decision " , human_control = True ,
decision_ref = " synthetic-human-lane-review " )
2026-09-10 09:29:38 +02:00
owner_entry = validate_entry ( raw )
req = _expected_request ( cfg , owner_entry , " exec " , fields = ( " api_token " , ) )
owner_request_digest = pdp . bind_request ( req )
2026-09-10 20:16:55 +02:00
def issue_owner ( ident , human_control ) :
# The requester declares intent on an unapproved object;
# only the subsequent human bind discharges the control.
return operator_request ( " /v1/approvals " , {
" id " : ident , " binding " : { " action " : " secrets.exec " , " target " : { " id " : owner_entry . id , " stage " : " prod " } ,
" actor " : " service:approval-engine-operator " , " principal " : " synthetic-operator " , " purpose " : " disposable identity proof " } ,
" validity " : { " not_before " : ( now - timedelta ( minutes = 1 ) ) . isoformat ( ) , " expires_at " : ( now + timedelta ( minutes = 10 ) ) . isoformat ( ) } ,
" pdp_digest " : owner_request_digest , " pdp_path " : True ,
" human_control " : human_control } , " approval:create " )
issue_owner ( " synthetic-owner-delivery " , args . human_control )
if args . human_control :
try :
operator_request ( " /v1/approvals/synthetic-owner-delivery/entries " , { } , " approval:approve " )
except HTTPError as error :
assert error . code == 403
assert engine . get ( " synthetic-owner-delivery " ) . entries == [ ]
else :
raise AssertionError ( " service bound a declared human control " )
# Explicit local fixture: the positive human entry is seeded
# through the store, not a native human login/JWT claim.
engine . add_entry ( " synthetic-owner-delivery " , " fixture:human " ,
principal_type = " human " , evidence_ref = " synthetic-store-fixture " )
issue_owner ( " synthetic-owner-undeclared " , False )
operator_request ( " /v1/approvals/synthetic-owner-undeclared/entries " , { } , " approval:approve " )
receipt [ " checks " ] [ " declared_control_refuses_real_keycape_service_bind " ] = True
receipt [ " limitations " ] . append ( " positive human entry seeded in disposable store; no human JWT/PKCE proof " )
else :
operator_request ( " /v1/approvals/synthetic-owner-delivery/entries " , { } , " approval:approve " )
2026-09-10 09:29:38 +02:00
backend_calls = [ ]
class Backend :
@contextmanager
def approle_session ( self , role ) :
assert role == owner_entry . role_name
yield SimpleNamespace ( client = self )
def _run ( self , command ) :
assert command == [ " kv " , " get " , " -format=json " , f " { owner_entry . mount } / { owner_entry . path } " ]
return SimpleNamespace ( returncode = 0 , stdout = json . dumps ( { " data " : { " data " : { " api_token " : " synthetic-owner-value " } } } ) )
@contextmanager
def open_fixture_backend ( * _args ) :
assert engine . claim ( " synthetic-owner-delivery " ) [ " consumed " ]
backend_calls . append ( " after-consume " )
yield Backend ( )
command = raw [ " delivery_config " ] [ " exec_owner " ] [ " command " ]
cli_args = SimpleNamespace ( catalog = owner_entry . id , field = " api_token " , mode = " exec-env " , command = command )
2026-09-10 20:16:55 +02:00
from secrets_engine . decisions import Decision
lane_review = Decision ( " synthetic-human-lane-review " , " Synthetic lane review " , " approved " , None , " local-fixture " )
with patch . object ( cli , " get_entry " , return_value = owner_entry ) , patch . object ( cli , " _open_backend " , open_fixture_backend ) , patch . object ( cli , " resolve_decision " , return_value = lane_review ) :
if args . human_control :
owner_entry . approval [ " authorization_id " ] = " synthetic-owner-undeclared "
before_checks = len ( pdp . calls )
try :
cli . cmd_exec ( cfg , cli_args )
except DecisionError as error :
assert " human_control " in str ( error )
assert not backend_calls and len ( pdp . calls ) == before_checks
assert not engine . claim ( " synthetic-owner-undeclared " ) [ " consumed " ]
else :
raise AssertionError ( " undeclared control reached the protected action " )
finally :
owner_entry . approval [ " authorization_id " ] = " synthetic-owner-delivery "
receipt [ " checks " ] [ " undeclared_control_refused_before_real_pdp_consume_backend " ] = True
2026-09-10 09:29:38 +02:00
substituted = SimpleNamespace ( * * vars ( cli_args ) )
substituted . command = [ " /bin/echo " , " substitute " ]
try :
cli . cmd_exec ( cfg , substituted )
except DeliveryError :
assert not engine . claim ( " synthetic-owner-delivery " ) [ " consumed " ] and not backend_calls
else :
raise AssertionError ( " substitute recipient accepted " )
original_env = raw [ " delivery_config " ] [ " exec_owner " ] [ " environment " ] [ " LANG " ]
raw [ " delivery_config " ] [ " exec_owner " ] [ " environment " ] [ " LANG " ] = " C "
try :
cli . cmd_exec ( cfg , cli_args )
except DecisionError :
assert not engine . claim ( " synthetic-owner-delivery " ) [ " consumed " ] and not backend_calls
else :
raise AssertionError ( " changed owner replay accepted " )
raw [ " delivery_config " ] [ " exec_owner " ] [ " environment " ] [ " LANG " ] = original_env
output = io . StringIO ( )
with redirect_stdout ( output ) , patch . dict ( os . environ , { " BAO_TOKEN " : " synthetic-parent-only " , " SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE " : str ( root / " approval.secret " ) } ) :
assert cli . cmd_exec ( cfg , cli_args ) == 0
assert " owner-delivery-ok " in output . getvalue ( ) and " synthetic-parent-only " not in output . getvalue ( )
assert backend_calls == [ " after-consume " ]
assert pdp . last_decision [ " binding " ] [ " context " ] [ " exec_owner_sha256 " ] == owner_digest ( owner_entry )
receipt [ " checks " ] . update ( {
" exec_owner_substitution_refused_before_consume_backend " : True ,
" exec_owner_changed_environment_replay_refused_by_real_pdp_join " : True ,
" exec_owner_real_cli_consumes_before_fixture_backend " : True ,
" exec_owner_actual_child_excludes_parent_credentials " : True ,
" exec_owner_digest_preserved_by_real_evaluator " : True ,
} )
2026-09-10 20:16:55 +02:00
if args . human_control :
assert pdp . last_decision [ " binding " ] [ " context " ] [ " human_control " ] is True
assert engine . claim ( " synthetic-owner-delivery " ) [ " binding " ] [ " human_control " ] is True
receipt [ " checks " ] [ " declared_human_intent_preserved_by_real_evaluator " ] = True
receipt [ " checks " ] [ " declared_human_fixture_consumed_before_owner_delivery " ] = True
2026-09-10 09:29:38 +02:00
receipt [ " exec_owner_scope " ] = " Synthetic recipient/backend with real KeyCape, Approval Engine, Flex Auth and Secrets Engine CLI; not native custody or human approval proof "
2026-09-09 07:06:05 +02:00
finally :
if api_server :
api_server . shutdown ( )
api_server . server_close ( )
if pdp :
pdp . stop ( )
if engine :
engine . close ( )
if created :
run ( [ " docker " , " stop " , " --time=5 " , container ] )
server . shutdown ( )
server . server_close ( )
proxy_thread . join ( )
receipt . update ( status = " passed " , cleanup_complete = True , finished_at = datetime . now ( timezone . utc ) . isoformat ( ) )
private_write ( args . receipt , json . dumps ( receipt , indent = 2 ) + " \n " )
def main ( ) :
parser = argparse . ArgumentParser ( description = __doc__ )
parser . add_argument ( " --keycape-source " , required = True , type = Path )
parser . add_argument ( " --approval-engine-source " , required = True , type = Path )
2026-09-09 08:55:46 +02:00
parser . add_argument ( " --flex-auth-source " , required = True , type = Path )
2026-09-09 07:06:05 +02:00
parser . add_argument ( " --receipt " , required = True , type = Path )
2026-09-10 09:29:38 +02:00
parser . add_argument ( " --exec-owner " , action = " store_true " , help = " also prove catalog-bound child delivery against the actual approval/PDP chain " )
2026-09-10 20:16:55 +02:00
parser . add_argument ( " --human-control " , action = " store_true " , help = " require declared human control in the exec-owner exercise; positive human entry is an explicit local store fixture " )
2026-09-09 07:06:05 +02:00
args = parser . parse_args ( )
2026-09-10 20:16:55 +02:00
if args . human_control and not args . exec_owner :
parser . error ( " --human-control requires --exec-owner " )
2026-09-09 07:06:05 +02:00
if args . receipt . exists ( ) :
raise SystemExit ( " receipt path must be new " )
try :
exercise ( args )
except Exception as error :
# Never dump a request, client environment or credential-bearing frame.
print ( " Synthetic approval identity exercise failed: " + type ( error ) . __name__ , file = sys . stderr )
return 1
print ( " Synthetic approval identity exercise passed; temporary resources removed. " )
return 0
if __name__ == " __main__ " :
raise SystemExit ( main ( ) )