"""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=min(deadline,approval,decision) or deadline>min(approval,decision) or (start is not None and lower