from __future__ import annotations import base64 from concurrent.futures import ThreadPoolExecutor import hashlib from pathlib import Path import sys import threading import pytest ROOT = Path(__file__).resolve().parents[1] APP = ROOT / "active-runtime" / "app" if str(APP) not in sys.path: sys.path.insert(0, str(APP)) from aios_task_admission_bootstrap import ( # noqa: E402 OwnerDelegationEpoch, TaskAdmissionBootstrapService, TaskAdmissionError, TaskAdmissionGrant, TaskAdmissionPolicy, TaskAdmissionStore, canonical_json_bytes, ) from aios_task_admission_live_adapters import ( # noqa: E402 AgentTaskAdmissionPort, BoundOwnerAuthorizationBackend, ) BASE_OID = "9" * 40 EXECUTION_DIGEST = "a" * 64 TASK_ID = "repository-discovery-p0-20260903" BRANCH = "agent/repository-discovery-p0-20260902" IDEMPOTENCY = "repository-discovery-p0-admission-20260903" FILES = [ "active-runtime/app/aios_repository_discovery.py", "active-runtime/app/aios_chatgpt_bridge_v2.py", "docs/gitops/openapi-chatgpt-actions.yaml", "tests/test_repository_discovery.py", ] CAPS = [ "governed.task.create", "agent-task:control", "task.principal.issue", "writer.lease", "governed.write.files", "git.read", "testing", "verification", ] class FakeAuthorization: def __init__(self, *, policy_digest: str, now: int = 1_800_000_000): self.now = now self.signature_calls = 0 self.epoch_calls = 0 self.signature_ok = True self.epoch = OwnerDelegationEpoch( epoch_id="epoch-repository-discovery-20260903", owner_identity="owner", trust_domain="aios.owner", repository="aios/aios", allowed_branch_prefixes=("agent/repository-discovery-",), allowed_capabilities=frozenset(CAPS), allowed_file_prefixes=("active-runtime", "docs", "tests"), risk_ceiling="medium", issued_at=now - 60, not_before=now - 60, expires_at=now + 3600, revocation_epoch=0, policy_digest=policy_digest, ) def verify_delegation_epoch(self, epoch_id: str) -> OwnerDelegationEpoch: self.epoch_calls += 1 if epoch_id != self.epoch.epoch_id: raise TaskAdmissionError("UNKNOWN_EPOCH", 403) return self.epoch def verify_owner_signature( self, *, key_id: str, canonical_payload: bytes, signature_b64: str, ) -> str: self.signature_calls += 1 if key_id != "owner-key-1" or not self.signature_ok: raise TaskAdmissionError("TASK_ADMISSION_OWNER_SIGNATURE_INVALID", 403) expected = base64.b64encode( hashlib.sha256(canonical_payload + b"\0owner-key-1").digest() ).decode("ascii") if signature_b64 != expected: raise TaskAdmissionError("TASK_ADMISSION_OWNER_SIGNATURE_INVALID", 403) return "owner" class FakeTaskPort: def __init__(self): self.calls = 0 self.grants = [] self._lock = threading.Lock() def admit(self, grant): with self._lock: self.calls += 1 self.grants.append(grant) return {"task_id": grant.task_id, "state": "QUEUED"} @pytest.fixture def policy(): return TaskAdmissionPolicy( allowed_capabilities=frozenset(CAPS), max_file_count=16, max_task_ttl_seconds=3600, max_envelope_ttl_seconds=900, max_risk="medium", ) @pytest.fixture def service(tmp_path: Path, policy: TaskAdmissionPolicy): now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) return svc, auth, port def request(**overrides): value = { "idempotency_key": IDEMPOTENCY, "task_id": TASK_ID, "repository": "aios/aios", "authority_base_oid": BASE_OID, "target_branch": BRANCH, "generation": 1, "execution_digest": EXECUTION_DIGEST, "requested_capabilities": list(CAPS), "file_allowlist": list(FILES), "risk": "medium", "expires_in_seconds": 600, } value.update(overrides) return value def test_envelope_exact_replay_returns_same_nonce_and_payload(service): svc, _, _ = service first = svc.create_envelope(request()) second = svc.create_envelope(request()) assert first["idempotent"] is False assert second["idempotent"] is True assert first["envelope"] == second["envelope"] assert first["canonical_payload_base64"] == second["canonical_payload_base64"] def test_envelope_idempotency_conflict_fails_closed(service): svc, _, _ = service svc.create_envelope(request()) with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_IDEMPOTENCY_CONFLICT"): svc.create_envelope(request(risk="low")) @pytest.mark.parametrize( "field,value,code", [ ("repository", "other/repo", "TASK_ADMISSION_REPOSITORY_REJECTED"), ("target_branch", "main", "TASK_ADMISSION_BRANCH_REJECTED"), ("authority_base_oid", "HEAD", "TASK_ADMISSION_BASE_OID_INVALID"), ("requested_capabilities", ["production.write"], "TASK_ADMISSION_PROHIBITED_CAPABILITY"), ("requested_capabilities", ["git:*"], "TASK_ADMISSION_CAPABILITY_INVALID"), ("file_allowlist", ["../secrets"], "TASK_ADMISSION_FILE_PATH_INVALID"), ("file_allowlist", ["/etc/passwd"], "TASK_ADMISSION_FILE_PATH_INVALID"), ("risk", "high", "TASK_ADMISSION_RISK_OUT_OF_POLICY"), ], ) def test_envelope_policy_rejects_scope_widening(service, field, value, code): svc, _, _ = service with pytest.raises(TaskAdmissionError, match=code): svc.create_envelope(request(**{field: value})) def test_valid_delegation_epoch_admits_exact_task_once(service): svc, auth, port = service envelope = svc.create_envelope(request())["envelope"] result = svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert result["schema"] == "aios.task-admission-receipt.v1" assert result["task_id"] == TASK_ID assert result["task_state"] == "QUEUED" assert result["parent_epoch_id"] == auth.epoch.epoch_id assert port.calls == 1 replay = svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert replay["task_id"] == TASK_ID assert replay["idempotent"] is True assert port.calls == 1 def test_post_admission_projection_runs_after_exact_task_readback_once( tmp_path: Path, policy: TaskAdmissionPolicy ): auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest()) port = FakeTaskPort() observations = [] def project(grant, task): observations.append((grant.task_id, task["task_id"], task["state"])) return {"job_id": "projected-job"} svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: 1_800_000_000, post_admission=project, ) envelope_id = svc.create_envelope(request())["envelope"]["envelope_id"] proof = { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } first = svc.authorize_and_admit(proof) replay = svc.authorize_and_admit(proof) assert first["task_id"] == TASK_ID assert replay["idempotent"] is True assert observations == [(TASK_ID, TASK_ID, "QUEUED")] def test_epoch_capability_widening_rejected_before_task_port(service): svc, auth, port = service # Envelope policy allows the capability, parent epoch deliberately does not. auth.epoch = OwnerDelegationEpoch( **{ **auth.epoch.as_public_dict(), "allowed_capabilities": frozenset( item for item in CAPS if item != "writer.lease" ), "allowed_branch_prefixes": auth.epoch.allowed_branch_prefixes, "allowed_file_prefixes": auth.epoch.allowed_file_prefixes, } ) envelope = svc.create_envelope(request())["envelope"] with pytest.raises( TaskAdmissionError, match="TASK_ADMISSION_EPOCH_CAPABILITY_WIDENING" ): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.calls == 0 def test_epoch_file_scope_widening_rejected(service): svc, auth, port = service auth.epoch = OwnerDelegationEpoch( **{ **auth.epoch.as_public_dict(), "allowed_capabilities": auth.epoch.allowed_capabilities, "allowed_branch_prefixes": auth.epoch.allowed_branch_prefixes, "allowed_file_prefixes": ("docs",), } ) envelope = svc.create_envelope(request())["envelope"] with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_EPOCH_FILE_WIDENING"): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.calls == 0 def test_revoked_or_expired_epoch_rejected(service): svc, auth, port = service auth.epoch = OwnerDelegationEpoch( **{ **auth.epoch.as_public_dict(), "allowed_capabilities": auth.epoch.allowed_capabilities, "allowed_branch_prefixes": auth.epoch.allowed_branch_prefixes, "allowed_file_prefixes": auth.epoch.allowed_file_prefixes, "revocation_epoch": 1, } ) envelope = svc.create_envelope(request())["envelope"] with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_EPOCH_REVOKED"): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.calls == 0 def test_owner_signature_path_verifies_canonical_payload(service): svc, auth, port = service created = svc.create_envelope(request()) payload = canonical_json_bytes(created["envelope"]) signature = base64.b64encode( hashlib.sha256(payload + b"\0owner-key-1").digest() ).decode("ascii") result = svc.authorize_and_admit( { "envelope_id": created["envelope"]["envelope_id"], "authorization_kind": "owner_signature", "owner_key_id": "owner-key-1", "signature_base64": signature, } ) assert result["authorization_kind"] == "owner_signature" assert result["owner_identity"] == "owner" assert auth.signature_calls == 1 assert port.calls == 1 def test_bad_owner_signature_is_rejected(service): svc, _, port = service envelope = svc.create_envelope(request())["envelope"] with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_OWNER_SIGNATURE_INVALID"): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "owner_signature", "owner_key_id": "owner-key-1", "signature_base64": base64.b64encode(b"bad").decode("ascii"), } ) assert port.calls == 0 def test_expired_envelope_cannot_admit(tmp_path: Path, policy: TaskAdmissionPolicy): now = [1_800_000_000] auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now[0]) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now[0], ) envelope = svc.create_envelope(request(expires_in_seconds=60))["envelope"] now[0] += 61 with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_ENVELOPE_EXPIRED"): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.calls == 0 def test_concurrent_exact_authorization_calls_admit_once(service): svc, auth, port = service envelope_id = svc.create_envelope(request())["envelope"]["envelope_id"] body = { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } with ThreadPoolExecutor(max_workers=16) as pool: results = list(pool.map(lambda _: svc.authorize_and_admit(body), range(16))) assert {item["task_id"] for item in results} == {TASK_ID} assert port.calls == 1 def test_cross_instance_envelope_winner_is_the_durable_value(tmp_path: Path, policy: TaskAdmissionPolicy): auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest()) port = FakeTaskPort() stores = [TaskAdmissionStore(tmp_path / "shared.sqlite3") for _ in range(16)] services = [ TaskAdmissionBootstrapService( store=store, authorization=auth, task_port=port, policy=policy, clock=lambda: 1_800_000_000, ) for store in stores ] with ThreadPoolExecutor(max_workers=16) as pool: values = list(pool.map(lambda svc: svc.create_envelope(request()), services)) assert len({item["envelope"]["envelope_id"] for item in values}) == 1 assert sum(not item["idempotent"] for item in values) == 1 def test_cross_instance_authorization_calls_create_one_task(tmp_path: Path, policy: TaskAdmissionPolicy): auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest()) port = FakeTaskPort() database = tmp_path / "shared.sqlite3" first = TaskAdmissionBootstrapService( store=TaskAdmissionStore(database), authorization=auth, task_port=port, policy=policy, clock=lambda: 1_800_000_000, ) envelope_id = first.create_envelope(request())["envelope"]["envelope_id"] services = [ TaskAdmissionBootstrapService( store=TaskAdmissionStore(database), authorization=auth, task_port=port, policy=policy, clock=lambda: 1_800_000_000, ) for _ in range(16) ] body = { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } with ThreadPoolExecutor(max_workers=16) as pool: values = list(pool.map(lambda svc: svc.authorize_and_admit(body), services)) assert {item["task_id"] for item in values} == {TASK_ID} assert port.calls == 1 @pytest.mark.parametrize("file_name", ["docs//gitops/a.yaml", "docs/./gitops/a.yaml", "docs/a\x00.yaml"]) def test_file_paths_must_already_be_canonical(service, file_name): svc, _, _ = service with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_FILE_PATH_INVALID"): svc.create_envelope(request(file_allowlist=[file_name])) @pytest.mark.parametrize("generation", [True, "1", 1.0, 0]) def test_generation_is_a_strict_positive_integer(service, generation): svc, _, _ = service with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_GENERATION_INVALID"): svc.create_envelope(request(generation=generation)) def test_policy_digest_drift_and_changed_proof_cannot_replay(service): svc, auth, _ = service envelope_id = svc.create_envelope(request())["envelope"]["envelope_id"] body = { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } svc.authorize_and_admit(body) svc.policy = TaskAdmissionPolicy( allowed_capabilities=frozenset(CAPS), policy_digest="policy-has-changed" ) with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_POLICY_DIGEST_DRIFT"): svc.authorize_and_admit(body) def test_grant_expiry_is_clipped_to_parent_epoch(tmp_path: Path, policy: TaskAdmissionPolicy): now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) auth.epoch = OwnerDelegationEpoch( **{**auth.epoch.as_public_dict(), "allowed_capabilities": auth.epoch.allowed_capabilities, "allowed_branch_prefixes": auth.epoch.allowed_branch_prefixes, "allowed_file_prefixes": auth.epoch.allowed_file_prefixes, "expires_at": now + 120} ) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) result = svc.authorize_and_admit({ "envelope_id": svc.create_envelope(request())["envelope"]["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, }) assert port.grants[0].expires_at == now + 120 assert result["task_id"] == TASK_ID def test_owner_backend_uses_bound_caller_and_decoded_armored_signature(policy): captured = {} class Verifier: def verify(self, **kwargs): captured.update(kwargs) return True epoch = FakeAuthorization(policy_digest=policy.normalized_policy_digest()).epoch backend = BoundOwnerAuthorizationBackend( authenticated_caller={"uid": "bridge-service"}, verified_epoch_provider=lambda **kwargs: captured.update(epoch_lookup=kwargs) or epoch, signature_verifier=Verifier(), ) assert backend.verify_delegation_epoch(epoch.epoch_id) == epoch assert captured["epoch_lookup"]["caller"] == {"uid": "bridge-service"} assert backend.verify_owner_signature( key_id="owner-key-1", canonical_payload=b"exact", signature_b64=base64.b64encode(b"-----BEGIN SSH SIGNATURE-----").decode(), ) == "aios-task-grant-signer" assert captured["namespace"] == "aios-owner-approval-v1" assert captured["payload"] == b"exact" def test_official_task_port_reconciles_ambiguous_create(tmp_path: Path, policy): grant = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=FakeAuthorization(policy_digest=policy.normalized_policy_digest()), task_port=FakeTaskPort(), policy=policy, clock=lambda: 1_800_000_000, ) # Construct via the public flow so the port sees a production-shaped grant. created = grant.create_envelope(request())["envelope"] envelope = grant._load_envelope(created["envelope_id"]) task_grant = TaskAdmissionGrant( grant_id="task-grant-adapter-test", envelope_id=envelope.envelope_id, task_id=envelope.task_id, repository=envelope.repository, authority_base_oid=envelope.authority_base_oid, target_branch=envelope.target_branch, generation=envelope.generation, execution_digest=envelope.execution_digest, capabilities=envelope.requested_capabilities, file_allowlist=envelope.file_allowlist, risk=envelope.risk, trust_domain=envelope.trust_domain, policy_digest=envelope.policy_digest, authorization_kind="owner_signature", owner_identity="aios-task-grant-signer", parent_epoch_id=None, issued_at=1_800_000_000, expires_at=1_800_000_600, ) class NotFound(Exception): status = 404 class Transport: def __init__(self): self.calls = []; self.task = None def request(self, method, path, body=None): self.calls.append((method, path, body)) if method == "GET" and self.task is None: raise NotFound() if method == "POST": self.task = {key: value for key, value in body.items() if key != "idempotency_key"} self.task["status"] = "QUEUED" raise TimeoutError("response lost after side effect") return self.task transport = Transport() plan = { "external_job_id": "fixture-job-adapter-01", "repository": task_grant.repository, "target_branch": task_grant.target_branch, "generation": task_grant.generation, "execution_digest": task_grant.execution_digest, } assert AgentTaskAdmissionPort(transport, execution_plan_provider=lambda _: plan).admit(task_grant) == {"task_id": TASK_ID, "state": "QUEUED"} assert [call[:2] for call in transport.calls] == [ ("GET", "/v1/tasks/" + TASK_ID), ("POST", "/v1/tasks"), ("GET", "/v1/tasks/" + TASK_ID), ] def test_execution_identity_is_available_only_to_trusted_post_admission( tmp_path: Path, policy: TaskAdmissionPolicy, ): class NotFound(Exception): status = 404 class Transport: def __init__(self): self.task = None def request(self, method, path, body=None): if method == "GET" and self.task is None: raise NotFound() if method == "POST": self.task = { key: value for key, value in body.items() if key != "idempotency_key" } self.task["status"] = "QUEUED" return self.task plan = { "external_job_id": "job-0123456789abcdef0123456789abcdef", "repository": "aios/aios", "target_branch": BRANCH, "generation": 1, "execution_digest": EXECUTION_DIGEST, } projected: dict[str, object] = {} auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest()) service = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=AgentTaskAdmissionPort( Transport(), execution_plan_provider=lambda _: plan ), policy=policy, clock=lambda: 1_800_000_000, post_admission=lambda _grant, result: projected.update(result), ) envelope_id = service.create_envelope(request())["envelope"]["envelope_id"] receipt = service.authorize_and_admit( { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert receipt["task_id"] == TASK_ID assert "external_job_id" not in receipt assert projected == { "task_id": TASK_ID, "state": "QUEUED", "external_job_id": plan["external_job_id"], } def test_owner_signature_grant_reaches_task_ttl_ceiling_not_envelope_window( tmp_path: Path, policy: TaskAdmissionPolicy ): # V2R2C2 TTL contract: the envelope is a *signing* window. Once the Owner # signature is verified, the consumed envelope must NOT truncate the # derived grant; the grant lifecycle is bounded by the task/grant policy # ceiling (max_task_ttl_seconds = 3600), not the envelope's ~900s window. now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) # Envelope window is short (600s); grant TTL ceiling is 3600s. created = svc.create_envelope(request(expires_in_seconds=600)) payload = canonical_json_bytes(created["envelope"]) signature = base64.b64encode( hashlib.sha256(payload + b"\0owner-key-1").digest() ).decode("ascii") result = svc.authorize_and_admit( { "envelope_id": created["envelope"]["envelope_id"], "authorization_kind": "owner_signature", "owner_key_id": "owner-key-1", "signature_base64": signature, } ) grant = port.grants[0] # Grant must reach the policy ceiling (now + 3600), NOT envelope expiry # (now + 600). This is the core V2R2C2 defect regression. assert grant.expires_at == now + policy.max_task_ttl_seconds assert grant.expires_at >= created["envelope"]["expires_at"] assert result["authorization_kind"] == "owner_signature" def test_envelope_boundary_now_equals_expiry_is_rejected(tmp_path: Path, policy: TaskAdmissionPolicy): # Boundary: authorization at now == envelope.expires_at must be refused # fail-closed (envelope window is expired at that instant). now = [1_800_000_000] auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now[0]) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now[0], ) envelope = svc.create_envelope(request(expires_in_seconds=60))["envelope"] # Advance exactly to the envelope expiry boundary. now[0] = envelope["expires_at"] with pytest.raises(TaskAdmissionError, match="TASK_ADMISSION_ENVELOPE_EXPIRED"): svc.authorize_and_admit( { "envelope_id": envelope["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.calls == 0 def test_delegation_epoch_grant_clips_to_parent_epoch_when_shorter_than_task_ttl( tmp_path: Path, policy: TaskAdmissionPolicy ): # delegation_epoch: when the parent epoch expires before the task TTL # ceiling, the grant must be clipped to the parent epoch expiry (never # outlive the delegating authority). now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) # parent epoch expires far before the task TTL ceiling (3600s). auth.epoch = OwnerDelegationEpoch( **{**auth.epoch.as_public_dict(), "expires_at": now + 120} ) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) result = svc.authorize_and_admit( { "envelope_id": svc.create_envelope(request())["envelope"]["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) assert port.grants[0].expires_at == now + 120 assert port.grants[0].expires_at < now + policy.max_task_ttl_seconds assert result["task_id"] == TASK_ID def test_replay_owner_signature_returns_idempotent_grant_without_new_effect( tmp_path: Path, policy: TaskAdmissionPolicy ): # Replay: the same envelope + Owner signature can only return the original # (identical) grant — it must never mint a second, different grant or # re-invoke the task port side effect. now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) created = svc.create_envelope(request()) payload = canonical_json_bytes(created["envelope"]) signature = base64.b64encode( hashlib.sha256(payload + b"\0owner-key-1").digest() ).decode("ascii") body = { "envelope_id": created["envelope"]["envelope_id"], "authorization_kind": "owner_signature", "owner_key_id": "owner-key-1", "signature_base64": signature, } first = svc.authorize_and_admit(body) replay = svc.authorize_and_admit(body) assert first["idempotent"] is False assert replay["idempotent"] is True assert replay["grant_id"] == first["grant_id"] assert port.calls == 1 # side effect exactly once def test_parent_expiry_conflict_fails_closed_when_grant_would_escape_parent( tmp_path: Path, policy: TaskAdmissionPolicy ): # A grant must never outlive its parent epoch. Simulate a parent whose # expiry would be violated if the code ignored the parent bound; the # service must clip (not mint) or reject, never exceed the parent. now = 1_800_000_000 auth = FakeAuthorization(policy_digest=policy.normalized_policy_digest(), now=now) auth.epoch = OwnerDelegationEpoch( **{**auth.epoch.as_public_dict(), "expires_at": now + 500} ) # parent expires before task ceiling (3600) and before envelope (600) port = FakeTaskPort() svc = TaskAdmissionBootstrapService( store=TaskAdmissionStore(tmp_path / "admission.sqlite3"), authorization=auth, task_port=port, policy=policy, clock=lambda: now, ) result = svc.authorize_and_admit( { "envelope_id": svc.create_envelope(request())["envelope"]["envelope_id"], "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) grant = port.grants[0] assert grant.expires_at <= auth.epoch.expires_at # never escapes parent assert result["task_id"] == TASK_ID def test_status_is_read_only_and_reports_admitted_task(service): svc, auth, _ = service envelope_id = svc.create_envelope(request())["envelope"]["envelope_id"] before = svc.status(envelope_id) assert before["status"] == "PENDING_AUTHORIZATION" assert before["task"] is None svc.authorize_and_admit( { "envelope_id": envelope_id, "authorization_kind": "delegation_epoch", "delegation_epoch_id": auth.epoch.epoch_id, } ) after = svc.status(envelope_id) assert after["status"] == "ADMITTED" assert after["task"]["task_id"] == TASK_ID