feat(execution): prove fixed grant and cleanup against disposable OpenBao

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
codex 2026-10-16 07:43:52 +02:00
parent 69a792c070
commit 99fd21ee37
9 changed files with 720 additions and 9 deletions

View file

@ -77,6 +77,26 @@ class Call:
return content_hash(encoded({'ordinal':self.ordinal,'kind':self.kind,'method':self.method,
'path':self.path,'payload_sha256':self.payload_sha256}))
def cleanup_specs(operation_id):
"""Deterministic owner cleanup plan; native handles stay in owner memory."""
try: need(str(UUID(operation_id)) == operation_id, 'operation_id_invalid')
except (ValueError, AttributeError, TypeError): raise Refused('operation_id_invalid') from None
policy_name = 'task-exec-' + operation_id
specs = []
for kind, slot, calls in [
('task-token-revoke', 'task', [('POST','auth/token/revoke-self'), ('POST','auth/token/lookup-accessor')]),
('identity-token-revoke', 'identity', [('POST','auth/token/revoke-self'), ('POST','auth/token/lookup-accessor')]),
('grant-policy-delete', 'owner', [('DELETE','sys/policies/acl/'+policy_name), ('GET','sys/policies/acl/'+policy_name)]),
]:
value = {'kind':kind, 'credential_slot':slot, 'operation_id':operation_id,
'calls':[{'method':method,'path':path} for method,path in calls]}
if kind == 'task-token-revoke': value['confirm_not_created_if_no_issue_attempt'] = True
if kind == 'grant-policy-delete': value['skip_delete_if_no_create_attempt'] = True
value['call_digest'] = content_hash(encoded(value))
specs.append(value)
return specs
class Compiler:
def __init__(self, config: OwnerConfig):
need(type(config) is OwnerConfig,'owner_configuration_required')
@ -232,14 +252,47 @@ class Compiler:
return Plan(encoded({'schema':'platform-owner-typed-plan/v1','action':'execute-ccr','operation':'metadata-apply-ccr',
'request':request,'catalog_target':expected['catalog_target'],
'source_pins':dict(self.pins),'task_token_max_ttl':120,'task_token_max_uses':12,
'cleanup_uses_reserved':1}))
'cleanup_uses_reserved':1,'cleanup':cleanup_specs(request['operation_id'])}))
def bind_execution(self, plan, descriptor, owner_descriptor):
"""Bind exact engine descriptor to owner plan; no authorization is created.
owner_descriptor must be installed independently by the owner, never copied
from the request. The engine must separately validate its closed schema and
full canonical request digest/claim/PDP/consume correspondence.
"""
need(type(plan) is Plan and type(descriptor) is dict and type(owner_descriptor) is bytes,
'independent_owner_descriptor_required')
meta=plan.metadata()
need(self.compile(meta['request']).serialized == plan.serialized, 'immutable_plan_changed')
need(encoded(descriptor) == owner_descriptor, 'owner_descriptor_mismatch')
ccr,_,_=self._derive()
expected = {'contract_version':'SECRETS-EXEC-20261011-v1',
'operation_id':meta['request']['operation_id'],
'operation':'metadata-apply-ccr','execution_actor':'service:secrets-engine',
'ccr_id':ccr['id'],'catalog_sha256':meta['request']['catalog_sha256'],
'operations':meta['request']['operations']}
need(all(descriptor.get(k)==v for k,v in expected.items()),'execution_descriptor_plan_mismatch')
bound = dict(meta, execution_descriptor=descriptor,
execution_descriptor_sha256=tagged(owner_descriptor))
# The full descriptor's independently admitted grant immutable digest must
# cover these cleanup commitments. No grant schema exists here yet, so this
# source binding cannot itself admit a grant/native production execution.
return Plan(encoded(bound))
def before_call(self,plan,ordinal):
need(type(plan) is Plan and type(ordinal) is int and 0<=ordinal<6,'fixed_plan_ordinal_required')
try: meta=plan.metadata();fresh=self.compile(meta['request'])
try:
meta=plan.metadata();fresh=self.compile(meta['request'])
if 'execution_descriptor' in meta:
fresh=self.bind_execution(fresh,meta['execution_descriptor'],encoded(meta['execution_descriptor']))
except Refused: raise
except BaseException: raise Refused('invalid_plan') from None
need(fresh.serialized==plan.serialized,'immutable_plan_changed')
# Immediately re-derive owner payload bytes, and reconfirm immutable snapshot after derivation.
_,_,calls=self._derive();need(self.compile(meta['request']).serialized==plan.serialized,'immutable_plan_changed')
_,_,calls=self._derive()
final=self.compile(meta['request'])
if 'execution_descriptor' in meta:
final=self.bind_execution(final,meta['execution_descriptor'],encoded(meta['execution_descriptor']))
need(final.serialized==plan.serialized,'immutable_plan_changed')
return calls[ordinal]