Point the OpenRouter cycle at memo version 3.
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Fresh receipts use the new approval IDs. A matching live policy and AppRole
skips apply without claiming that approval. A difference fails closed.

Assistant: grok
Assistant-Session: 01a0e2a1-8058-7553-9999-b7d106c17047
This commit is contained in:
codex 2026-09-27 15:33:09 +02:00
parent 1cd546e77c
commit 53825190ca
5 changed files with 47 additions and 17 deletions

View file

@ -1,8 +1,11 @@
# T03 continuation after Railiance Clock deployment
The original requests expired unconsumed. Replacement request IDs and immutable
memo version 2 are recorded in the creation receipt and Secrets Engine workplan.
The exact apply/verify/exec action requests and checker pins are unchanged.
The 2026-09-16 requests were consumed. The next cycle uses three new approval
IDs and immutable memo version 3. The creation receipt is
`docs/evidence/2026-09-27-t03-approval-requests.json`; execution receipts are
`secrets-engine/docs/evidence/2026-09-27-t03-native-execution.json` and
`docs/evidence/2026-09-27-t03-attended-delivery.json`. The exact
apply/verify/exec action requests and checker pins are unchanged.
Run the requester and execution worker with
`/home/worsch/secrets-engine/.venv/bin/python`; this environment includes Clock,
@ -20,6 +23,6 @@ The outer lane remains secrets-engine-approval-client-login; its reviewed
Both retain their own self-revocation and private runtime cleanup.
Human review: https://decisions.coulomb.social/review?memo_id=SECRETS-WP-0010-T03-apply
(and identifiers ending -verify and -exec). Version 2 is required. The requester
has no approval or consume scope; no human entries are copied from version 1.
(and identifiers ending -verify and -exec). Version 3 is required. The requester
has no approval or consume scope; no human entries are copied from version 2.
No execution may begin before the new approvals pass native claim/PDP checks.

View file

@ -7,7 +7,7 @@ from urllib.parse import urlencode
from urllib.error import HTTPError
import jwt
ROOT=Path('/home/worsch/railiance-platform')
RECEIPT=ROOT/'docs/evidence/2026-09-15-t03-renewed-approval-requests.json'
RECEIPT=ROOT/'docs/evidence/2026-09-27-t03-approval-requests.json'
POLICY='workload-kv-read-secrets-engine-requester-client'
KV='platform/data/workloads/secrets-engine/approval-requester'
ISSUER='https://kc.coulomb.social'

View file

@ -5,7 +5,7 @@ from datetime import datetime,timezone
from urllib.request import Request,build_opener,ProxyHandler,HTTPRedirectHandler
ROOT=Path('/home/worsch/railiance-platform')
spec=importlib.util.spec_from_file_location('preflight',ROOT/'scripts/approval-client-reader-preflight.py');pre=importlib.util.module_from_spec(spec);spec.loader.exec_module(pre)
RECEIPT=ROOT/'docs/evidence/2026-09-15-t03-attended-delivery.json'
RECEIPT=ROOT/'docs/evidence/2026-09-27-t03-attended-delivery.json'
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self,*args,**kwargs):return None
@ -19,7 +19,7 @@ if RESUME:RECEIPT=ROOT/'docs/evidence/2026-09-16-t03-resume-attended-delivery.js
def main(receipt):
require(Path.home().parent.name=='.warden-attended-login' and not os.getenv('BAO_TOKEN') and not os.getenv('VAULT_TOKEN'),'attended_reader_required')
require(not Path('/home/worsch/secrets-engine/docs/evidence/'+('2026-09-16-t03-resume-exec.json' if RESUME else '2026-09-15-t03-native-execution.json')).exists(),'execution_receipt_requires_reconciliation')
require(not Path('/home/worsch/secrets-engine/docs/evidence/'+('2026-09-16-t03-resume-exec.json' if RESUME else '2026-09-27-t03-native-execution.json')).exists(),'execution_receipt_requires_reconciliation')
identity=pre.bao('token','lookup','-format=json')['data'];pre.validate_identity(identity)
for path,expected in pre.EXPECTED.items():require(sorted(pre.bao('token','capabilities','-format=json',path))==expected,'reader_scope_failed')
runtime=Path('/run/user')/str(os.getuid());private(runtime,True)

View file

@ -16,10 +16,12 @@ from secrets_engine.decisions import resolve_decision,require_approved
from secrets_engine.openbao import OpenBaoClient
from secrets_engine.exec_owner import validate_delivery_target
from secrets_engine.plan import build_plan
RECEIPT=ROOT/'docs/evidence/2026-09-15-t03-native-execution.json'
RECEIPT=ROOT/'docs/evidence/2026-09-27-t03-native-execution.json'
KUBE=['kubectl','--kubeconfig','/home/worsch/.kube/config-railiance01']
ROLE='se-prod-openrouter-llm-connect'; LANE='openrouter-llm-connect'
IDS={'apply':'9935335c-8e9a-566e-a48e-6a5b5f4882eb','verify':'273d6882-6253-5dc9-ac54-544f92ef5e56','exec':'7ba0c13b-68cd-5b3e-9481-42ba9e385e68'}
PRIOR_IDS={'apply':'9935335c-8e9a-566e-a48e-6a5b5f4882eb','verify':'273d6882-6253-5dc9-ac54-544f92ef5e56','exec':'7ba0c13b-68cd-5b3e-9481-42ba9e385e68'}
IDS={'apply':'b5fcbfcc-ad56-456f-bc36-c823052e9917','verify':'4e9ff881-d59f-4143-9155-929afbe8dd43','exec':'a24e0898-b3c5-4e50-85a8-18a2c2aa229e'}
LIMITS={'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}
def require(value,code):
if not value:raise ValueError(code)
@ -86,10 +88,18 @@ def verify_session_cleanup(client):
del probe_token
return {'unrelated_path_denied':True,'session_revocation_verified':True,'revoked_token_lookup_status':403}
def native_apply_disposition(policy_hcl,existing,role):
if existing is None and role is None:return 'absent'
require(isinstance(existing,str) and isinstance(role,dict) and existing.strip()==policy_hcl.strip() and all(role.get(k)==v for k,v in LIMITS.items()) and role.get('token_policies')==[ROLE],'existing_native_objects_require_reconciliation')
return 'satisfied'
def fresh_apply_plan(policy_hcl,existing,role):
if native_apply_disposition(policy_hcl,existing,role)=='absent':return tuple(IDS),None
return ('verify','exec'),{'action':'apply','already_satisfied':True,'limits':dict(LIMITS)}
def resume_receipt():
prior=json.loads((ROOT/'docs/evidence/2026-09-15-t03-native-execution.json').read_text())
require(prior.get('phase')=='verify_attempt_started' and prior.get('failure_code')=='revoked_token_still_usable','unexpected_prior_failure')
require(prior.get('actions')==[{'action':'apply','approval_id':IDS['apply'],'exit_code':0,'limits':{'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}}],'prior_apply_not_verified')
require(prior.get('actions')==[{'action':'apply','approval_id':PRIOR_IDS['apply'],'exit_code':0,'limits':{'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}}],'prior_apply_not_verified')
return prior
def admin(directory,negative,resume=False):
@ -122,7 +132,14 @@ def admin(directory,negative,resume=False):
fd=os.open(directory/'pdp-caller',os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
with os.fdopen(fd,'w') as out:out.write(run(*KUBE,'-n','secrets-engine','create','token','secrets-engine','--audience=flex-auth','--duration=10m').strip())
# Validate real claims and exact current decisions before any consumption.
# Fresh apply is classified first. A match is left out of this loop so the new apply approval is not claimed or consumed.
actions=('exec',) if resume else tuple(IDS)
if not resume:
client=OpenBaoClient.resolve('http://127.0.0.1:18200')
existing=client.read_policy(ROLE)
role=bao('read','-format=json','auth/approle/role/'+ROLE)['data'] if client.approle_exists(ROLE) else None
actions,satisfied=fresh_apply_plan(build_plan(entries['apply'],'prod').policy_hcl,existing,role)
if satisfied:receipt['actions'].append(satisfied)
for action in actions:
auth=authorize_action(configs[action],entries[action],action,fields=() if action=='apply' else tuple(entries[action].fields),policy_targets=(ROLE,),auth_targets=(ROLE,))
require(auth is not None,'native_authorization_missing')
@ -135,13 +152,13 @@ def admin(directory,negative,resume=False):
require(existing is not None and existing.strip()==plan.policy_hcl.strip(),'applied_policy_drift')
role=bao('read','-format=json','auth/approle/role/'+ROLE)['data']
require(all(role.get(k)==v for k,v in prior['actions'][0]['limits'].items()) and role.get('token_policies')==[ROLE],'applied_role_drift')
code="import json;from approval_engine.store import Engine;e=Engine('/data/approvals.sqlite');print(json.dumps({k:e.claim(v) for k,v in "+repr(IDS)+".items()}))"
code="import json;from approval_engine.store import Engine;e=Engine('/data/approvals.sqlite');print(json.dumps({k:e.claim(v) for k,v in "+repr(PRIOR_IDS)+".items()}))"
claims=json.loads(run(*KUBE,'-n','approval-engine','exec','statefulset/approval-engine','--','python','-c',code))
require(all(claims[a]['consumed'] and claims[a]['approval_id']==IDS[a] for a in ('apply','verify')) and claims['exec']['valid_now'] and not claims['exec']['consumed'],'resume_approval_state_mismatch')
require(all(claims[a]['consumed'] and claims[a]['approval_id']==PRIOR_IDS[a] for a in ('apply','verify')) and claims['exec']['valid_now'] and not claims['exec']['consumed'],'resume_approval_state_mismatch')
receipt['prior_receipt']='2026-09-15-t03-native-execution.json'
receipt['completed_actions_not_replayed']=['apply','verify']
receipt['supplemental_cleanup']=verify_session_cleanup(client);save(receipt)
else:
elif 'apply' in actions:
require(existing is None and not client.approle_exists(ROLE),'existing_native_objects_require_reconciliation')
for action in actions:
receipt['phase']=action+'_attempt_started';save(receipt)
@ -156,8 +173,7 @@ def admin(directory,negative,resume=False):
row={'action':action,'approval_id':IDS[action],'exit_code':rc}
if action=='apply':
role=bao('read','-format=json','auth/approle/role/'+ROLE)['data']
limits={'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}
require(all(role.get(k)==v for k,v in limits.items()) and role.get('token_policies')==[ROLE],'role_limits_mismatch');row['limits']=limits
require(all(role.get(k)==v for k,v in LIMITS.items()) and role.get('token_policies')==[ROLE],'role_limits_mismatch');row['limits']=dict(LIMITS)
elif action=='verify':
row.update(verify_session_cleanup(client))
else:

View file

@ -28,11 +28,22 @@ class TestProbe(unittest.TestCase):
def test_server_failure_is_not_revocation_proof(self):
with self.assertRaisesRegex(ValueError,'revocation_probe_not_definitive'):self.check(500)
def test_reconciled_prior_phase(self):
prior={'phase':'verify_attempt_started','failure_code':'revoked_token_still_usable','actions':[{'action':'apply','approval_id':m.IDS['apply'],'exit_code':0,'limits':{'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}}]}
prior={'phase':'verify_attempt_started','failure_code':'revoked_token_still_usable','actions':[{'action':'apply','approval_id':m.PRIOR_IDS['apply'],'exit_code':0,'limits':{'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}}]}
with patch.object(Path,'read_text',return_value=json.dumps(prior)):
self.assertEqual(m.resume_receipt(),prior)
prior['actions'][0]['approval_id']='other'
with patch.object(Path,'read_text',return_value=json.dumps(prior)):
with self.assertRaisesRegex(ValueError,'prior_apply_not_verified'):m.resume_receipt()
def test_fresh_apply_branch(self):
hcl='path "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n'
role=dict(m.LIMITS,token_policies=[m.ROLE])
self.assertEqual(m.fresh_apply_plan(hcl,None,None),(tuple(m.IDS),None))
actions,row=m.fresh_apply_plan(hcl,hcl+'\n',role)
self.assertEqual(actions,('verify','exec'))
self.assertNotIn('apply',actions)
self.assertEqual(row,{'action':'apply','already_satisfied':True,'limits':dict(m.LIMITS)})
self.assertNotIn('approval_id',row)
for existing,live in ((hcl,None),(None,role),('other\n',role),(hcl,dict(role,token_ttl=1)),(hcl,dict(role,token_policies=[m.ROLE,'default'])),(hcl,dict(role,token_policies=m.ROLE))):
with self.assertRaisesRegex(ValueError,'existing_native_objects_require_reconciliation'):m.fresh_apply_plan(hcl,existing,live)
if __name__=='__main__':unittest.main()