"""Single-host operational delegation for AIOS migration. This module is deliberately narrow: * Owner signs only OperationalDelegation and ExpiredTaskRecoveryDecision. * Machine signer signs only WorkerRuntimeBinding and WorkerRuntimeProof. * Every object is bound to one immutable Task identity and a narrow capability set. * There is no arbitrary sign-bytes API. """ from __future__ import annotations from dataclasses import asdict, dataclass import hashlib import json from pathlib import Path import re import time from typing import Any, Mapping, Sequence from aios_single_host_authority import ( DEFAULT_MACHINE_SIGNER_ID, DEFAULT_OWNER_SIGNER_ID, MACHINE_NAMESPACE, OWNER_IDENTITY, OWNER_NAMESPACE, LocalFileSigner, RegistryOwnerApprovalVerifier, SignerRegistry, SingleHostAuthorityError, canonical_json_bytes, sha256_json, verify_sshsig, ) OPERATIONAL_POLICY_SCHEMA = "aios.single-host-operational-policy.v1" OPERATIONAL_DELEGATION_SCHEMA = "aios.owner-operational-delegation.v1" RECOVERY_DECISION_SCHEMA = "aios.expired-task-recovery-decision.v1" WORKER_BINDING_SCHEMA = "aios.worker-runtime-binding.v1" WORKER_PROOF_SCHEMA = "aios.worker-runtime-proof.v1" REVOCATION_SCHEMA = "aios.operational-revocations.v1" ALLOWED_OPERATIONAL_CAPABILITIES = frozenset({ "task.recovery", "worker.runtime.bind", "worker.runtime.proof", "task.claim.guard", }) ALLOWED_EXPECTED_STATE = "EXPIRED" HEX40 = re.compile(r"^[0-9a-f]{40}$") HEX64 = re.compile(r"^[0-9a-f]{64}$") SAFE_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:@/+:-]{2,511}$") CAP = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{1,127}$") class OperationalAuthorityError(RuntimeError): def __init__(self, code: str): super().__init__(code) self.code = code def fail(code: str) -> None: raise OperationalAuthorityError(code) def _exact_fields(value: Mapping[str, Any], fields: set[str], code: str) -> None: if not isinstance(value, Mapping) or set(value) != fields: fail(code) def _safe_id(value: str, code: str) -> str: if not isinstance(value, str) or not SAFE_ID.fullmatch(value): fail(code) return value def _hex(value: str, n: int, code: str) -> str: regex = HEX40 if n == 40 else HEX64 if not isinstance(value, str) or not regex.fullmatch(value): fail(code) return value def _caps(value: Sequence[str], code: str) -> tuple[str, ...]: if not isinstance(value, (list, tuple)) or not value: fail(code) out = tuple(sorted(set(value))) if len(out) != len(value) or any(not isinstance(x, str) or not CAP.fullmatch(x) for x in out): fail(code) return out def task_identity_sha256(task: Mapping[str, Any]) -> str: """Digest only immutable recovery/claim identity fields. Revision, state, attempt and deadline are intentionally excluded. """ fields = ( "task_id", "repository", "target_branch", "base_oid", "generation", "execution_plan_sha256", "external_job_identity", ) try: value = {name: task[name] for name in fields} except KeyError as exc: raise OperationalAuthorityError("TASK_IDENTITY_FIELD_MISSING") from exc _safe_id(str(value["task_id"]), "TASK_ID_INVALID") _safe_id(str(value["repository"]), "REPOSITORY_INVALID") _safe_id(str(value["target_branch"]), "TARGET_BRANCH_INVALID") _hex(str(value["base_oid"]), 40, "BASE_OID_INVALID") if type(value["generation"]) is not int or value["generation"] < 1: fail("GENERATION_INVALID") _hex(str(value["execution_plan_sha256"]), 64, "EXECUTION_PLAN_DIGEST_INVALID") _safe_id(str(value["external_job_identity"]), "EXTERNAL_JOB_IDENTITY_INVALID") return hashlib.sha256(canonical_json_bytes(value)).hexdigest() @dataclass(frozen=True, slots=True) class OperationalPolicy: repository: str task_id: str task_identity_sha256: str target_branch: str base_oid: str generation: int execution_plan_sha256: str external_job_identity: str allowed_capabilities: tuple[str, ...] allowed_worker_ids: tuple[str, ...] maximum_delegation_ttl_seconds: int maximum_recovery_decision_ttl_seconds: int maximum_binding_ttl_seconds: int maximum_proof_ttl_seconds: int maximum_heartbeat_age_seconds: int maximum_task_deadline_extension_seconds: int schema: str = OPERATIONAL_POLICY_SCHEMA def validate(self) -> None: if self.schema != OPERATIONAL_POLICY_SCHEMA: fail("OPERATIONAL_POLICY_SCHEMA_INVALID") _safe_id(self.repository, "OPERATIONAL_POLICY_REPOSITORY_INVALID") _safe_id(self.task_id, "OPERATIONAL_POLICY_TASK_ID_INVALID") _hex(self.task_identity_sha256, 64, "OPERATIONAL_POLICY_TASK_IDENTITY_INVALID") _safe_id(self.target_branch, "OPERATIONAL_POLICY_BRANCH_INVALID") _hex(self.base_oid, 40, "OPERATIONAL_POLICY_BASE_OID_INVALID") if type(self.generation) is not int or self.generation < 1: fail("OPERATIONAL_POLICY_GENERATION_INVALID") _hex(self.execution_plan_sha256, 64, "OPERATIONAL_POLICY_PLAN_INVALID") _safe_id(self.external_job_identity, "OPERATIONAL_POLICY_JOB_INVALID") caps = _caps(self.allowed_capabilities, "OPERATIONAL_POLICY_CAPABILITIES_INVALID") if not set(caps).issubset(ALLOWED_OPERATIONAL_CAPABILITIES): fail("OPERATIONAL_POLICY_CAPABILITY_WIDENING") if not self.allowed_worker_ids or any(not SAFE_ID.fullmatch(x) for x in self.allowed_worker_ids): fail("OPERATIONAL_POLICY_WORKERS_INVALID") bounds = ( (self.maximum_delegation_ttl_seconds, 300, 7 * 24 * 3600), (self.maximum_recovery_decision_ttl_seconds, 30, 900), (self.maximum_binding_ttl_seconds, 60, 24 * 3600), (self.maximum_proof_ttl_seconds, 15, 900), (self.maximum_heartbeat_age_seconds, 5, 300), (self.maximum_task_deadline_extension_seconds, 300, 24 * 3600), ) if any(type(v) is not int or not lo <= v <= hi for v, lo, hi in bounds): fail("OPERATIONAL_POLICY_TTL_INVALID") @property def digest(self) -> str: self.validate() return sha256_json(asdict(self)) @classmethod def from_mapping(cls, value: Mapping[str, Any]) -> "OperationalPolicy": fields = set(cls.__dataclass_fields__) _exact_fields(value, fields, "OPERATIONAL_POLICY_FIELDS_INVALID") try: policy = cls( repository=value["repository"], task_id=value["task_id"], task_identity_sha256=value["task_identity_sha256"], target_branch=value["target_branch"], base_oid=value["base_oid"], generation=value["generation"], execution_plan_sha256=value["execution_plan_sha256"], external_job_identity=value["external_job_identity"], allowed_capabilities=tuple(value["allowed_capabilities"]), allowed_worker_ids=tuple(value["allowed_worker_ids"]), maximum_delegation_ttl_seconds=value["maximum_delegation_ttl_seconds"], maximum_recovery_decision_ttl_seconds=value["maximum_recovery_decision_ttl_seconds"], maximum_binding_ttl_seconds=value["maximum_binding_ttl_seconds"], maximum_proof_ttl_seconds=value["maximum_proof_ttl_seconds"], maximum_heartbeat_age_seconds=value["maximum_heartbeat_age_seconds"], maximum_task_deadline_extension_seconds=value["maximum_task_deadline_extension_seconds"], schema=value["schema"], ) except Exception as exc: raise OperationalAuthorityError("OPERATIONAL_POLICY_FIELDS_INVALID") from exc policy.validate() return policy def build_exact_policy( task: Mapping[str, Any], *, worker_id: str, allowed_capabilities: Sequence[str] = tuple(sorted(ALLOWED_OPERATIONAL_CAPABILITIES)), ) -> OperationalPolicy: identity = task_identity_sha256(task) policy = OperationalPolicy( repository=str(task["repository"]), task_id=str(task["task_id"]), task_identity_sha256=identity, target_branch=str(task["target_branch"]), base_oid=str(task["base_oid"]), generation=int(task["generation"]), execution_plan_sha256=str(task["execution_plan_sha256"]), external_job_identity=str(task["external_job_identity"]), allowed_capabilities=tuple(sorted(allowed_capabilities)), allowed_worker_ids=(worker_id,), maximum_delegation_ttl_seconds=24 * 3600, maximum_recovery_decision_ttl_seconds=300, maximum_binding_ttl_seconds=4 * 3600, maximum_proof_ttl_seconds=300, maximum_heartbeat_age_seconds=30, maximum_task_deadline_extension_seconds=4 * 3600, ) policy.validate() return policy def _signed_payload_dict(payload: Mapping[str, Any], *, key_id: str, namespace: str) -> dict[str, Any]: value = dict(payload) value["signature_namespace"] = namespace value["signature_key_id"] = key_id value["canonical_payload_digest"] = sha256_json(value) return value def _verify_digest_field(payload: Mapping[str, Any]) -> bool: if not isinstance(payload, Mapping) or "canonical_payload_digest" not in payload: return False value = dict(payload) supplied = value.pop("canonical_payload_digest", None) return isinstance(supplied, str) and supplied == sha256_json(value) @dataclass(frozen=True, slots=True) class SignedOperationalArtifact: payload: dict[str, Any] signature: str key_id: str namespace: str @property def canonical_payload(self) -> bytes: return canonical_json_bytes(self.payload) @property def payload_sha256(self) -> str: return hashlib.sha256(self.canonical_payload).hexdigest() def to_dict(self) -> dict[str, Any]: return { "payload": dict(self.payload), "signature": self.signature, "key_id": self.key_id, "namespace": self.namespace, } class OperationalOwnerAuthority: def __init__(self, key_path: Path, policy: OperationalPolicy, *, require_root_owner: bool = True, clock: Any = time.time): policy.validate() self.policy = policy self.signer = LocalFileSigner( Path(key_path), signer_id=DEFAULT_OWNER_SIGNER_ID, namespace=OWNER_NAMESPACE, require_root_owner=require_root_owner, ) self.clock = clock @property def fingerprint(self) -> str: return self.signer.fingerprint def _sign(self, payload: Mapping[str, Any]) -> SignedOperationalArtifact: full = _signed_payload_dict(payload, key_id=self.fingerprint, namespace=OWNER_NAMESPACE) art = self.signer._sign_canonical(full) return SignedOperationalArtifact(dict(art.payload), art.signature, art.key_id, art.namespace) def issue_operational_delegation(self, *, delegation_id: str, nonce: str, ttl_seconds: int) -> SignedOperationalArtifact: now = int(self.clock()) p = self.policy if not SAFE_ID.fullmatch(delegation_id) or not SAFE_ID.fullmatch(nonce): fail("OPERATIONAL_DELEGATION_ID_INVALID") if type(ttl_seconds) is not int or not 60 <= ttl_seconds <= p.maximum_delegation_ttl_seconds: fail("OPERATIONAL_DELEGATION_TTL_INVALID") payload = { "schema": OPERATIONAL_DELEGATION_SCHEMA, "delegation_id": delegation_id, "nonce": nonce, "owner_identity": OWNER_IDENTITY, "repository": p.repository, "task_id": p.task_id, "task_identity_sha256": p.task_identity_sha256, "target_branch": p.target_branch, "base_oid": p.base_oid, "generation": p.generation, "execution_plan_sha256": p.execution_plan_sha256, "external_job_identity": p.external_job_identity, "allowed_capabilities": list(p.allowed_capabilities), "allowed_worker_ids": list(p.allowed_worker_ids), "policy_digest": p.digest, "issued_at": now, "not_before": max(0, now - 5), "expires_at": now + ttl_seconds, "revocation_epoch": 0, "status": "ACTIVE", } return self._sign(payload) def issue_recovery_decision( self, delegation: Mapping[str, Any], *, decision_id: str, nonce: str, expected_revision: int, expected_attempt: int, original_deadline: int, new_deadline: int, ttl_seconds: int, ) -> SignedOperationalArtifact: now = int(self.clock()) verify_delegation_scope(delegation, self.policy, now=now) if "task.recovery" not in delegation["allowed_capabilities"]: fail("RECOVERY_CAPABILITY_NOT_DELEGATED") if not SAFE_ID.fullmatch(decision_id) or not SAFE_ID.fullmatch(nonce): fail("RECOVERY_DECISION_ID_INVALID") if type(expected_revision) is not int or expected_revision < 0 or type(expected_attempt) is not int or expected_attempt < 0: fail("RECOVERY_CAS_INVALID") if type(original_deadline) is not int or type(new_deadline) is not int: fail("RECOVERY_DEADLINE_INVALID") if new_deadline <= now or new_deadline <= original_deadline: fail("RECOVERY_DEADLINE_INVALID") if new_deadline - now > self.policy.maximum_task_deadline_extension_seconds: fail("RECOVERY_DEADLINE_WIDENING") if type(ttl_seconds) is not int or not 15 <= ttl_seconds <= self.policy.maximum_recovery_decision_ttl_seconds: fail("RECOVERY_DECISION_TTL_INVALID") payload = { "schema": RECOVERY_DECISION_SCHEMA, "decision_id": decision_id, "nonce": nonce, "parent_delegation_id": delegation["delegation_id"], "parent_delegation_digest": hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest(), "task_id": self.policy.task_id, "task_identity_sha256": self.policy.task_identity_sha256, "expected_state": ALLOWED_EXPECTED_STATE, "expected_revision": expected_revision, "expected_attempt": expected_attempt, "original_deadline": original_deadline, "new_deadline": new_deadline, "repository": self.policy.repository, "target_branch": self.policy.target_branch, "base_oid": self.policy.base_oid, "generation": self.policy.generation, "execution_plan_sha256": self.policy.execution_plan_sha256, "external_job_identity": self.policy.external_job_identity, "policy_digest": self.policy.digest, "one_time_use": True, "issued_at": now, "not_before": max(0, now - 5), "expires_at": now + ttl_seconds, } return self._sign(payload) class OperationalMachineAuthority: def __init__(self, key_path: Path, policy: OperationalPolicy, *, require_root_owner: bool = True, clock: Any = time.time): policy.validate() self.policy = policy self.signer = LocalFileSigner( Path(key_path), signer_id=DEFAULT_MACHINE_SIGNER_ID, namespace=MACHINE_NAMESPACE, require_root_owner=require_root_owner, ) self.clock = clock @property def fingerprint(self) -> str: return self.signer.fingerprint def _sign(self, payload: Mapping[str, Any]) -> SignedOperationalArtifact: full = _signed_payload_dict(payload, key_id=self.fingerprint, namespace=MACHINE_NAMESPACE) art = self.signer._sign_canonical(full) return SignedOperationalArtifact(dict(art.payload), art.signature, art.key_id, art.namespace) def issue_runtime_binding( self, delegation: Mapping[str, Any], *, binding_id: str, nonce: str, worker_id: str, runtime_id: str, runtime_sha256: str, task_contract_version: str, supported_contract_versions: Sequence[str], required_capabilities: Sequence[str], worker_capabilities: Sequence[str], max_concurrency: int, ttl_seconds: int, ) -> SignedOperationalArtifact: now = int(self.clock()) p = self.policy verify_delegation_scope(delegation, p, now=now) if "worker.runtime.bind" not in delegation["allowed_capabilities"]: fail("RUNTIME_BIND_CAPABILITY_NOT_DELEGATED") if worker_id not in p.allowed_worker_ids: fail("WORKER_ID_NOT_DELEGATED") for val, code in [(binding_id, "BINDING_ID_INVALID"), (nonce, "BINDING_NONCE_INVALID"), (worker_id, "WORKER_ID_INVALID"), (runtime_id, "RUNTIME_ID_INVALID"), (task_contract_version, "CONTRACT_VERSION_INVALID")]: _safe_id(val, code) _hex(runtime_sha256, 64, "RUNTIME_SHA256_INVALID") supported = tuple(sorted(set(supported_contract_versions))) if task_contract_version not in supported or not supported or any(not SAFE_ID.fullmatch(x) for x in supported): fail("CONTRACT_INCOMPATIBLE") required = _caps(required_capabilities, "REQUIRED_CAPABILITIES_INVALID") worker_caps = _caps(worker_capabilities, "WORKER_CAPABILITIES_INVALID") if not set(required).issubset(set(worker_caps)): fail("CAPABILITY_MISMATCH") if type(max_concurrency) is not int or not 1 <= max_concurrency <= 64: fail("MAX_CONCURRENCY_INVALID") if type(ttl_seconds) is not int or not 30 <= ttl_seconds <= p.maximum_binding_ttl_seconds: fail("BINDING_TTL_INVALID") if now + ttl_seconds > int(delegation["expires_at"]): fail("BINDING_EXCEEDS_PARENT") payload = { "schema": WORKER_BINDING_SCHEMA, "binding_id": binding_id, "nonce": nonce, "parent_delegation_id": delegation["delegation_id"], "parent_delegation_digest": hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest(), "repository": p.repository, "task_id": p.task_id, "task_identity_sha256": p.task_identity_sha256, "target_branch": p.target_branch, "base_oid": p.base_oid, "generation": p.generation, "execution_plan_sha256": p.execution_plan_sha256, "external_job_identity": p.external_job_identity, "worker_id": worker_id, "runtime_id": runtime_id, "runtime_sha256": runtime_sha256, "task_contract_version": task_contract_version, "supported_contract_versions": list(supported), "required_capabilities": list(required), "worker_capabilities": list(worker_caps), "max_concurrency": max_concurrency, "policy_digest": p.digest, "issued_at": now, "not_before": max(0, now - 5), "expires_at": now + ttl_seconds, } return self._sign(payload) def issue_runtime_proof( self, delegation: Mapping[str, Any], binding: Mapping[str, Any], *, proof_id: str, nonce: str, heartbeat_at: int, adapter_readiness: bool, resource_readiness: bool, active_claim_count: int, ttl_seconds: int, ) -> SignedOperationalArtifact: now = int(self.clock()) p = self.policy verify_delegation_scope(delegation, p, now=now) verify_binding_scope(binding, delegation, p, now=now) if "worker.runtime.proof" not in delegation["allowed_capabilities"]: fail("RUNTIME_PROOF_CAPABILITY_NOT_DELEGATED") _safe_id(proof_id, "PROOF_ID_INVALID") _safe_id(nonce, "PROOF_NONCE_INVALID") if type(heartbeat_at) is not int or heartbeat_at > now + 5 or now - heartbeat_at > p.maximum_heartbeat_age_seconds: fail("HEARTBEAT_STALE") if adapter_readiness is not True or resource_readiness is not True: fail("RUNTIME_NOT_READY") if type(active_claim_count) is not int or active_claim_count < 0 or active_claim_count >= int(binding["max_concurrency"]): fail("MAX_CONCURRENCY_REACHED") if type(ttl_seconds) is not int or not 10 <= ttl_seconds <= p.maximum_proof_ttl_seconds: fail("PROOF_TTL_INVALID") if now + ttl_seconds > min(int(binding["expires_at"]), int(delegation["expires_at"])): fail("PROOF_EXCEEDS_PARENT") payload = { "schema": WORKER_PROOF_SCHEMA, "proof_id": proof_id, "nonce": nonce, "parent_delegation_id": delegation["delegation_id"], "parent_delegation_digest": hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest(), "binding_id": binding["binding_id"], "binding_digest": hashlib.sha256(canonical_json_bytes(dict(binding))).hexdigest(), "repository": p.repository, "task_id": p.task_id, "task_identity_sha256": p.task_identity_sha256, "generation": p.generation, "execution_plan_sha256": p.execution_plan_sha256, "worker_id": binding["worker_id"], "runtime_id": binding["runtime_id"], "runtime_sha256": binding["runtime_sha256"], "heartbeat_at": heartbeat_at, "adapter_readiness": True, "resource_readiness": True, "active_claim_count": active_claim_count, "max_concurrency": binding["max_concurrency"], "policy_digest": p.digest, "issued_at": now, "expires_at": now + ttl_seconds, } return self._sign(payload) DELEGATION_FIELDS = { "schema","delegation_id","nonce","owner_identity","repository","task_id", "task_identity_sha256","target_branch","base_oid","generation","execution_plan_sha256", "external_job_identity","allowed_capabilities","allowed_worker_ids","policy_digest", "issued_at","not_before","expires_at","revocation_epoch","status", "signature_namespace","signature_key_id","canonical_payload_digest", } BINDING_FIELDS = { "schema","binding_id","nonce","parent_delegation_id","parent_delegation_digest", "repository","task_id","task_identity_sha256","target_branch","base_oid","generation", "execution_plan_sha256","external_job_identity","worker_id","runtime_id","runtime_sha256", "task_contract_version","supported_contract_versions","required_capabilities","worker_capabilities", "max_concurrency","policy_digest","issued_at","not_before","expires_at", "signature_namespace","signature_key_id","canonical_payload_digest", } PROOF_FIELDS = { "schema","proof_id","nonce","parent_delegation_id","parent_delegation_digest", "binding_id","binding_digest","repository","task_id","task_identity_sha256","generation", "execution_plan_sha256","worker_id","runtime_id","runtime_sha256","heartbeat_at", "adapter_readiness","resource_readiness","active_claim_count","max_concurrency", "policy_digest","issued_at","expires_at","signature_namespace","signature_key_id", "canonical_payload_digest", } RECOVERY_FIELDS = { "schema","decision_id","nonce","parent_delegation_id","parent_delegation_digest", "task_id","task_identity_sha256","expected_state","expected_revision","expected_attempt", "original_deadline","new_deadline","repository","target_branch","base_oid","generation", "execution_plan_sha256","external_job_identity","policy_digest","one_time_use", "issued_at","not_before","expires_at","signature_namespace","signature_key_id", "canonical_payload_digest", } def verify_delegation_scope(value: Mapping[str, Any], policy: OperationalPolicy, *, now: int | None = None) -> None: policy.validate() _exact_fields(value, DELEGATION_FIELDS, "OPERATIONAL_DELEGATION_FIELDS_INVALID") now = int(time.time()) if now is None else int(now) if ( value["schema"] != OPERATIONAL_DELEGATION_SCHEMA or value["status"] != "ACTIVE" or value["revocation_epoch"] != 0 or value["owner_identity"] != OWNER_IDENTITY or value["repository"] != policy.repository or value["task_id"] != policy.task_id or value["task_identity_sha256"] != policy.task_identity_sha256 or value["target_branch"] != policy.target_branch or value["base_oid"] != policy.base_oid or value["generation"] != policy.generation or value["execution_plan_sha256"] != policy.execution_plan_sha256 or value["external_job_identity"] != policy.external_job_identity or value["policy_digest"] != policy.digest or not set(value["allowed_capabilities"]).issubset(set(policy.allowed_capabilities)) or not set(value["allowed_worker_ids"]).issubset(set(policy.allowed_worker_ids)) or value["signature_namespace"] != OWNER_NAMESPACE or not _verify_digest_field(value) or not int(value["not_before"]) <= now < int(value["expires_at"]) ): fail("OPERATIONAL_DELEGATION_SCOPE_INVALID") def verify_binding_scope(binding: Mapping[str, Any], delegation: Mapping[str, Any], policy: OperationalPolicy, *, now: int | None = None) -> None: _exact_fields(binding, BINDING_FIELDS, "WORKER_BINDING_FIELDS_INVALID") now = int(time.time()) if now is None else int(now) expected_parent = hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest() if ( binding["schema"] != WORKER_BINDING_SCHEMA or binding["parent_delegation_id"] != delegation["delegation_id"] or binding["parent_delegation_digest"] != expected_parent or binding["repository"] != policy.repository or binding["task_id"] != policy.task_id or binding["task_identity_sha256"] != policy.task_identity_sha256 or binding["target_branch"] != policy.target_branch or binding["base_oid"] != policy.base_oid or binding["generation"] != policy.generation or binding["execution_plan_sha256"] != policy.execution_plan_sha256 or binding["external_job_identity"] != policy.external_job_identity or binding["worker_id"] not in policy.allowed_worker_ids or binding["policy_digest"] != policy.digest or binding["signature_namespace"] != MACHINE_NAMESPACE or not _verify_digest_field(binding) or not int(binding["not_before"]) <= now < int(binding["expires_at"]) ): fail("WORKER_BINDING_SCOPE_INVALID") required = set(binding["required_capabilities"]) worker = set(binding["worker_capabilities"]) if not required.issubset(worker) or binding["task_contract_version"] not in binding["supported_contract_versions"]: fail("WORKER_BINDING_COMPATIBILITY_INVALID") def verify_proof_scope(proof: Mapping[str, Any], binding: Mapping[str, Any], delegation: Mapping[str, Any], policy: OperationalPolicy, *, now: int | None = None) -> None: _exact_fields(proof, PROOF_FIELDS, "WORKER_PROOF_FIELDS_INVALID") now = int(time.time()) if now is None else int(now) if ( proof["schema"] != WORKER_PROOF_SCHEMA or proof["parent_delegation_id"] != delegation["delegation_id"] or proof["parent_delegation_digest"] != hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest() or proof["binding_id"] != binding["binding_id"] or proof["binding_digest"] != hashlib.sha256(canonical_json_bytes(dict(binding))).hexdigest() or proof["repository"] != policy.repository or proof["task_id"] != policy.task_id or proof["task_identity_sha256"] != policy.task_identity_sha256 or proof["generation"] != policy.generation or proof["execution_plan_sha256"] != policy.execution_plan_sha256 or proof["worker_id"] != binding["worker_id"] or proof["runtime_id"] != binding["runtime_id"] or proof["runtime_sha256"] != binding["runtime_sha256"] or proof["max_concurrency"] != binding["max_concurrency"] or proof["policy_digest"] != policy.digest or proof["signature_namespace"] != MACHINE_NAMESPACE or proof["adapter_readiness"] is not True or proof["resource_readiness"] is not True or not _verify_digest_field(proof) or not now < int(proof["expires_at"]) or now - int(proof["heartbeat_at"]) > policy.maximum_heartbeat_age_seconds or int(proof["active_claim_count"]) >= int(proof["max_concurrency"]) ): fail("WORKER_PROOF_SCOPE_INVALID") def verify_recovery_scope(decision: Mapping[str, Any], delegation: Mapping[str, Any], policy: OperationalPolicy, *, now: int | None = None) -> None: _exact_fields(decision, RECOVERY_FIELDS, "RECOVERY_DECISION_FIELDS_INVALID") now = int(time.time()) if now is None else int(now) if ( decision["schema"] != RECOVERY_DECISION_SCHEMA or decision["parent_delegation_id"] != delegation["delegation_id"] or decision["parent_delegation_digest"] != hashlib.sha256(canonical_json_bytes(dict(delegation))).hexdigest() or decision["task_id"] != policy.task_id or decision["task_identity_sha256"] != policy.task_identity_sha256 or decision["expected_state"] != "EXPIRED" or decision["repository"] != policy.repository or decision["target_branch"] != policy.target_branch or decision["base_oid"] != policy.base_oid or decision["generation"] != policy.generation or decision["execution_plan_sha256"] != policy.execution_plan_sha256 or decision["external_job_identity"] != policy.external_job_identity or decision["policy_digest"] != policy.digest or decision["one_time_use"] is not True or decision["signature_namespace"] != OWNER_NAMESPACE or not _verify_digest_field(decision) or not int(decision["not_before"]) <= now < int(decision["expires_at"]) or int(decision["new_deadline"]) <= now ): fail("RECOVERY_DECISION_SCOPE_INVALID") class OperationalVerifier: """Verify signatures through the public root-owned SignerRegistry.""" def __init__(self, registry_path: Path, *, require_root_owner: bool = True): self.registry_path = Path(registry_path) self.require_root_owner = require_root_owner def _verify(self, artifact: SignedOperationalArtifact | Mapping[str, Any], *, role: str, signer_id: str, namespace: str) -> dict[str, Any]: if isinstance(artifact, SignedOperationalArtifact): payload, signature, key_id, artifact_namespace = artifact.payload, artifact.signature, artifact.key_id, artifact.namespace else: _exact_fields(artifact, {"payload","signature","key_id","namespace"}, "SIGNED_ARTIFACT_FIELDS_INVALID") payload, signature, key_id, artifact_namespace = artifact["payload"], artifact["signature"], artifact["key_id"], artifact["namespace"] if artifact_namespace != namespace: fail("SIGNED_ARTIFACT_NAMESPACE_INVALID") registry = SignerRegistry(self.registry_path, require_root_owner=self.require_root_owner) rec = registry.require(signer_id, role=role) if rec.fingerprint != key_id: fail("SIGNED_ARTIFACT_KEY_ID_INVALID") if role == "MACHINE_OPERATIONAL": owner_rec = registry.require(DEFAULT_OWNER_SIGNER_ID, role="OWNER_AUTHORITY") if rec.parent_signer_id != owner_rec.signer_id or rec.parent_fingerprint != owner_rec.fingerprint: fail("MACHINE_PARENT_BINDING_INVALID") # RegistryOwnerApprovalVerifier handles Owner namespace; generic machine uses registry public key. if role == "OWNER_AUTHORITY": verifier = RegistryOwnerApprovalVerifier(self.registry_path, require_root_owner=self.require_root_owner, signer_id=signer_id) ok = verifier.verify(namespace=namespace, payload=canonical_json_bytes(payload), signature=signature, key_id=key_id) else: from aios_single_host_authority import _load_public_key_line pub = _load_public_key_line(rec.public_key) ok = verify_sshsig(pub, canonical_json_bytes(payload), signature, namespace=namespace, expected_key_id=key_id) if not ok: fail("SIGNED_ARTIFACT_SIGNATURE_INVALID") return dict(payload) def owner(self, artifact: SignedOperationalArtifact | Mapping[str, Any]) -> dict[str, Any]: return self._verify(artifact, role="OWNER_AUTHORITY", signer_id=DEFAULT_OWNER_SIGNER_ID, namespace=OWNER_NAMESPACE) def machine(self, artifact: SignedOperationalArtifact | Mapping[str, Any]) -> dict[str, Any]: return self._verify(artifact, role="MACHINE_OPERATIONAL", signer_id=DEFAULT_MACHINE_SIGNER_ID, namespace=MACHINE_NAMESPACE)