railiance-platform/scripts/task_execution_mediator.py
codex 76fdc0b861
All checks were successful
CI Smoke / host-smoke (push) Successful in 3s
CI Smoke / container-smoke (push) Successful in 5s
Bound task execution by absolute call and credential deadlines
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
2026-10-16 17:15:00 +02:00

218 lines
13 KiB
Python

"""Owner mediator seam for the existing strict Secrets handoff and Approval GET.
Only the disposable NativeFixtureAdapter is callable here. No production backend,
caller-supplied authorizer/transport, approval boolean or portable receipt exists.
The strict Secrets module is an explicit external dependency: absence refuses
before credential-bearing requests or native effects, never a permissive fallback.
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime,timezone
import importlib
import json
import os
import stat
from pathlib import Path
from urllib.parse import urlsplit
from task_execution_cleanup import run_cleanup
from task_execution_journal import Binding,Cleanup,Journal,Refused
from task_execution_plan import Compiler,encoded,content_hash
from task_execution_native_fixture import FixtureAdmission,NativeFixtureAdapter,_absolute_budget
@dataclass(frozen=True)
class ConfirmationConfig:
"""Owner-installed independent read credential/route, never request fields."""
origin: str
token_file: Path
timeout_seconds: float = 3
_HANDOFF_FIELDS={'execution_contract','approval_id','request_digest','decision_id',
'native_binding','approval_binding_digest','submitted_request_digest',
'decision_not_before','decision_expires_at','approval_expires_at'}
def _strict_dependency():
try:
module=importlib.import_module('secrets_engine.task_execution_handoff')
for name in ['TaskExecutionAuthorization','TaskExecutionConsumption',
'authorize_task_execution','consume_task_execution']:
if not hasattr(module,name):raise ImportError()
return module
except ImportError:
raise Refused('strict Secrets task execution handoff dependency unavailable') from None
def _trusted_v2(cfg):
return (getattr(cfg,'authorization_policy_package',None)=='secrets-engine.task-execution.service-pilot'
and getattr(cfg,'authorization_policy_version',None)=='v2')
def _read_source_bundle(descriptor):
# Paths/hash expectations come from independently installed owner_descriptor,
# never a requester-selected file lookup. No bytes or raw OS errors escape.
for item in descriptor['source_bundle'].values():
path=Path(item['path']);fd=None
try:
if not path.is_absolute() or path.resolve()!=path:raise ValueError()
fd=os.open(path,os.O_RDONLY|os.O_NOFOLLOW|os.O_NONBLOCK)
before=os.fstat(fd)
if not stat.S_ISREG(before.st_mode) or before.st_nlink!=1 or before.st_mode&0o022 or not 0<before.st_size<=1048576:raise ValueError()
with os.fdopen(fd,'rb',closefd=False) as stream:raw=stream.read(1048577)
after=os.fstat(fd)
identity=lambda value:(value.st_dev,value.st_ino,value.st_size,value.st_mtime_ns,value.st_ctime_ns,value.st_mode,value.st_nlink)
if identity(before)!=identity(after) or len(raw)!=before.st_size or 'sha256:'+content_hash(raw)!=item['sha256']:raise ValueError()
except Exception:raise Refused('exact owner execution source bundle refused') from None
finally:
if fd is not None:os.close(fd)
def _source_bundle(descriptor):
with _absolute_budget(2):_read_source_bundle(descriptor)
def _fresh(cfg,handoff,descriptor):
if _trusted_v2(cfg):_source_bundle(descriptor)
from secrets_engine.application_time import read_window,validity_bounds
lower,upper=validity_bounds(window=read_window(cfg))
try:
parse=lambda value:datetime.fromisoformat(value.replace('Z','+00:00'))
deadline=parse(descriptor['operation_deadline'])
approval=parse(handoff['approval_expires_at']);decision=parse(handoff['decision_expires_at'])
start=parse(handoff['decision_not_before']) if handoff['decision_not_before'] else None
if any(value.tzinfo is None for value in [deadline,approval,decision]) or (start is not None and start.tzinfo is None):raise ValueError()
if upper>=min(deadline,approval,decision) or deadline>min(approval,decision) or (start is not None and lower<start):raise ValueError()
except (KeyError,TypeError,ValueError,AttributeError):
raise Refused('original task authority deadline refused') from None
def _intent(journal,binding,kind,fields):
digest=content_hash(encoded({'kind':kind,**fields}))
ordinal=journal.next_call_ordinal(binding)
journal.before_call(binding,ordinal,digest)
return ordinal,digest
def _unknown(journal,binding):
state=journal.observe(binding)['state']
if state not in {'unknown','failed','cleanup-confirmed'}:
journal.transition(binding,state,'unknown')
def run_native_fixture_task(*,compiler:Compiler,journal:Journal,plan_request:dict,
owner_descriptor:bytes,secrets_cfg,entry,
confirmation:ConfirmationConfig,
native_admission:FixtureAdmission):
"""Authorize inside owner boundary, reserve, consume once, independently GET.
Strict authorization is executed here through the actual Secrets-owned module;
an inbound TaskExecutionAuthorization or arbitrary callable is never accepted.
This function returns closed metadata, not tokens or raw approval/decision data.
Positive execution requires the module's real signed PDP path; the retained v1
Access policy stays DENY-only; actual v2 successor source is separately tested
through its authenticated caller/fresh-source path without runtime admission. Fixture policy/identity admission is independent
synthetic setup and cannot become production acceptance.
"""
strict=_strict_dependency()
from approval_engine.execution_confirmation import ExecutionConfirmationClient
from secrets_engine.execution_contract import ExecutionContract
if type(confirmation) is not ConfirmationConfig or type(native_admission) is not FixtureAdmission:
raise Refused('independent owner provider configuration required')
try:
origin=urlsplit(confirmation.origin)
if origin.scheme not in {'http','https'} or origin.hostname!='127.0.0.1' or not origin.port or origin.username or origin.password or origin.path or origin.query or origin.fragment:
raise ValueError()
if confirmation.origin!=str(getattr(secrets_cfg,'approval_url','')).rstrip('/'):
raise ValueError()
descriptor=ExecutionContract.parse(json.loads(owner_descriptor)).as_dict()
if encoded(descriptor)!=owner_descriptor or native_admission.descriptor!=owner_descriptor:
raise ValueError()
except Exception:
raise Refused('exact owner descriptor or provider route refused') from None
if _trusted_v2(secrets_cfg):_source_bundle(descriptor)
# An independently pinned owner catalogue must match every engine field. Its
# approval IDs are source references, never runtime authority.
proposal=compiler.proposal()
target={key:getattr(entry,key) for key in proposal['catalog_target']}
if encoded(target)!=encoded(proposal['catalog_target']) or entry.id!=proposal['catalog_id'] or entry.stage!='prod':
raise Refused('owner catalogue does not match strict task request')
snapshot={path:compiler.read(Path(path)) for path in compiler.pins}
owner_entry=compiler._catalogue_entry(snapshot)
# Only the served approval pointer is added after issue. Purpose or other
# source approval semantics cannot be substituted through an inbound entry.
without_reference=lambda value:{key:item for key,item in value.items() if key!='authorization_id'}
if encoded(without_reference(entry.approval))!=encoded(without_reference(owner_entry.approval)):
raise Refused('owner approval metadata differs from source')
client=ExecutionConfirmationClient(confirmation.origin,confirmation.token_file,
timeout_seconds=confirmation.timeout_seconds)
with journal.locked():
authorization=strict.authorize_task_execution(secrets_cfg,entry,
execution_contract=ExecutionContract.parse(descriptor))
if type(authorization) is not strict.TaskExecutionAuthorization:
raise Refused('strict task authorization missing')
handoff=authorization.as_owner_handoff()
if type(handoff) is not dict or set(handoff)!=_HANDOFF_FIELDS or encoded(handoff['execution_contract'])!=owner_descriptor:
raise Refused('strict task handoff does not match owner descriptor')
_fresh(secrets_cfg,handoff,descriptor)
request=dict(plan_request,request_digest=handoff['request_digest'])
plan=compiler.bind_execution(compiler.compile(request),descriptor,owner_descriptor)
binding=Binding(handoff['approval_id'],handoff['request_digest'],descriptor['operation_id'],plan.content_digest)
# Constructor validates fixed native origin/fixture process/grant sources
# but performs no native HTTP request or credential acquisition.
native=NativeFixtureAdapter(compiler,plan,journal,binding,native_admission)
journal.reserve(binding,native.cleanup)
fields={key:handoff[key] for key in ['approval_id','request_digest','decision_id']}
try:
ordinal,digest=_intent(journal,binding,'strict-secrets-task-consume',fields)
consumed=strict.consume_task_execution(secrets_cfg,authorization)
if type(consumed) is not strict.TaskExecutionConsumption:
raise Refused('strict task consumption missing')
receipt={key:getattr(consumed,key) for key in ['approval_id','request_digest','decision_id','consumed_at','idempotent']}
if any(receipt[key]!=value for key,value in fields.items()) or receipt['idempotent'] is not False:
raise Refused('historical or mismatched task consumption refused')
stamp=datetime.fromisoformat(receipt['consumed_at'].replace('Z','+00:00'))
if stamp.tzinfo is None:raise Refused('consumption timestamp missing')
journal.after_call(binding,ordinal,digest,content_hash(encoded(receipt)))
_fresh(secrets_cfg,handoff,descriptor)
ordinal,digest=_intent(journal,binding,'independent-approval-consumption-read',fields)
confirmed=client.confirm_consumption(binding.approval_id,binding.request_digest,
handoff['decision_id'],expected_binding=handoff['native_binding'],
expected_pdp_digest=handoff['approval_binding_digest'])
if confirmed!={key:receipt[key] for key in ['approval_id','request_digest','decision_id','consumed_at']}:
raise Refused('independent consumption correspondence refused')
journal.after_call(binding,ordinal,digest,content_hash(encoded(confirmed)))
_fresh(secrets_cfg,handoff,descriptor)
journal.transition(binding,'reserved','consume-confirmed',content_hash(encoded(confirmed)))
except Exception:
_unknown(journal,binding)
raise Refused('task consumption or independent confirmation unconfirmed; no native execution') from None
result={'operation_id':binding.operation_id,'request_digest':binding.request_digest,
'decision_id':handoff['decision_id'],'native_apply':'unverified',
'native_calls_completed':0,'cleanup_confirmed':False}
try:
journal.transition(binding,'consume-confirmed','authenticating')
# Fixture identity is independently seeded synthetic setup, not CCR38
# provenance proof or a production service login.
journal.transition(binding,'authenticating','grant-issuing')
_fresh(secrets_cfg,handoff,descriptor)
native.materialize_grant()
journal.transition(binding,'grant-issued','applying')
for ordinal in range(6):
_fresh(secrets_cfg,handoff,descriptor)
native.metadata_call(ordinal)
result['native_calls_completed']+=1
result['readback_evidence_digest']=native.verify_metadata()
result['native_apply']='verified'
except Exception:
_unknown(journal,binding)
result['native_apply']='unknown'
finally:
result['cleanup_confirmed']=run_cleanup(journal,binding,native)['confirmed']
if result['native_apply']=='verified' and result['cleanup_confirmed']:
journal.transition(binding,'verified','cleanup-confirmed',result['readback_evidence_digest'])
# Readback and cleanup are independent outcomes; no recovery authority
# or native compare-and-swap is implied by either fixture result.
result['business_state']=journal.observe(binding)['state']
return result