"""Narrow staging Mission ingress authenticated by the registered Owner signer. The signed payload binds the method, resource, body and idempotency key. This adapter neither signs requests nor grants Git/worker/production capabilities. """ from __future__ import annotations import argparse import importlib.util import json from pathlib import Path import re import stat import time from http.server import BaseHTTPRequestHandler, HTTPServer from typing import Any from .task_plane.errors import ( ForbiddenError, TaskPlaneHTTPError, UnauthorizedError, ValidationError, ) AUDIENCE = "aios.task-mission-authority.staging.v1" NAMESPACE = "aios-owner-approval-v1" MAX_BODY = 131072 REQUEST_FIELDS = frozenset({ "schema", "audience", "method", "path", "body", "idempotency_key", "issued_at", "expires_at", "nonce", }) def canonical_bytes(value: Any) -> bytes: return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False, allow_nan=False).encode("utf-8") def strict_object(pairs): result = {} for key, value in pairs: if key in result: raise ValidationError("duplicate JSON key") result[key] = value return result class SignedMissionIngress: def __init__( self, service, verifier, *, terminal_proof_importer=None, clock=time.time ): if not callable(getattr(verifier, "verify", None)): raise ValueError("registered Owner verifier required") identity = getattr(verifier, "signer_id", None) if not isinstance(identity, str) or not identity.strip(): raise ValueError("registered signer identity required") self.service = service self.verifier = verifier self.identity = identity self.terminal_proof_importer = terminal_proof_importer self.clock = clock def handle(self, envelope: dict) -> tuple[int, dict]: if not isinstance(envelope, dict) or set(envelope) != { "request", "signature", "key_id" }: raise ValidationError("invalid signed mission envelope") request = envelope["request"] if not isinstance(request, dict) or set(request) != REQUEST_FIELDS: raise ValidationError("invalid mission request fields") if (request["schema"] != "aios.signed-mission-request.v1" or request["audience"] != AUDIENCE): raise ForbiddenError("mission request audience mismatch") issued, expires = request["issued_at"], request["expires_at"] if (type(issued) is not int or type(expires) is not int or not 0 < expires - issued <= 300 or not issued <= self.clock() < expires): raise UnauthorizedError("mission request expired or not yet valid") if (not isinstance(request["nonce"], str) or re.fullmatch(r"[A-Za-z0-9_-]{16,128}", request["nonce"]) is None): raise ValidationError("invalid mission request nonce") if (not isinstance(envelope["signature"], str) or not isinstance(envelope["key_id"], str)): raise UnauthorizedError("Owner signature required") try: verified = self.verifier.verify( namespace=NAMESPACE, payload=canonical_bytes(request), signature=envelope["signature"], key_id=envelope["key_id"], ) except Exception: verified = False if verified is not True: raise UnauthorizedError("Owner signature invalid") method, path, body = request["method"], request["path"], request["body"] key = request["idempotency_key"] if method == "POST" and path == "/missions": if not isinstance(body, dict) or not isinstance(key, str) or not key.strip(): raise ValidationError("mission body and idempotency key required") return 201, self.service.create_mission( body, key, actor_identity=self.identity, ) if (method == "GET" and isinstance(path, str) and re.fullmatch(r"/missions/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}", path) and body is None and key is None): return 200, self.service.get_mission( path.split("/")[2], actor_identity=self.identity, ) if (method == "POST" and isinstance(path, str) and re.fullmatch(r"/tasks/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}/delegate", path)): if not isinstance(body, dict) or not isinstance(key, str) or not key.strip(): raise ValidationError("child body and idempotency key required") return 201, self.service.delegate_mission( path.split("/")[2], body, key, actor_identity=self.identity, ) if (method == "POST" and isinstance(path, str) and re.fullmatch( r"/missions/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}/legacy-attachments", path, )): if not isinstance(body, dict) or not isinstance(key, str) or not key.strip(): raise ValidationError( "legacy attachment body and idempotency key required" ) result = self.service.attach_legacy_attachment( path.split("/")[2], body, key, actor_identity=self.identity, ) return (200 if result.get("idempotent") is True else 201), result if (method == "GET" and isinstance(path, str) and re.fullmatch( r"/missions/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}/" r"legacy-attachments/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}", path, ) and body is None and key is None): pieces = path.split("/") return 200, self.service.get_legacy_attachment( pieces[2], pieces[4], actor_identity=self.identity, ) if (method == "POST" and isinstance(path, str) and re.fullmatch( r"/tasks/[A-Za-z0-9][A-Za-z0-9._:-]{2,179}/reconcile-terminal-proof", path, )): if body != {} or not isinstance(key, str) or not key.strip(): raise ValidationError( "terminal proof trigger requires an empty body and idempotency key" ) if self.terminal_proof_importer is None: raise ForbiddenError("terminal proof importer is not configured") return 200, self.terminal_proof_importer.reconcile( path.split("/")[2], key, actor_identity=self.identity, ) raise ForbiddenError("operation outside mission ingress scope") def load_registered_verifier(path: Path): metadata = path.lstat() if (not stat.S_ISREG(metadata.st_mode) or metadata.st_uid != 0 or metadata.st_mode & 0o022): raise ValueError("Owner verifier must be a root-owned immutable regular file") spec = importlib.util.spec_from_file_location("aios_mission_owner_verifier", path) if spec is None or spec.loader is None: raise ValueError("Owner verifier module unavailable") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module.GrantRootOwnerApprovalVerifier() def make_handler(ingress: SignedMissionIngress): class Handler(BaseHTTPRequestHandler): def log_message(self, *_args): pass # Do not log signed payloads or transport credentials. def respond(self, status, value): raw = canonical_bytes(value) self.send_response(status) self.send_header("Content-Type", "application/json") self.send_header("Cache-Control", "no-store") self.send_header("Content-Length", str(len(raw))) self.end_headers() self.wfile.write(raw) def do_POST(self): try: if self.path != "/v1/signed-request": raise ForbiddenError("unsupported mission ingress route") if self.headers.get("Transfer-Encoding"): raise ValidationError("transfer encoding is unsupported") lengths = self.headers.get_all("Content-Length", []) if len(lengths) != 1 or not lengths[0].isdigit(): raise ValidationError("one content length required") length = int(lengths[0]) if not 0 < length <= MAX_BODY: raise ValidationError("mission request too large or empty") self.connection.settimeout(10) raw = self.rfile.read(length) if len(raw) != length: raise ValidationError("truncated mission request") envelope = json.loads(raw, object_pairs_hook=strict_object) status, result = ingress.handle(envelope) self.respond(status, result) except TaskPlaneHTTPError as exc: self.respond(exc.status_code, exc.to_payload()) except (ValueError, UnicodeError, RecursionError): self.respond(400, {"error": "invalid_json"}) except Exception: self.respond(500, {"error": "mission_authority_unavailable"}) return Handler def main() -> None: from .task_plane.api import TaskPlaneService from .task_plane.mission import MissionAuthority, MissionPrincipalBinding from .task_plane.policy import IdentityVerifier, PolicyEngine from .task_plane.store import TaskPlaneStore parser = argparse.ArgumentParser() parser.add_argument("--db", type=Path, required=True) parser.add_argument("--owner-verifier", type=Path, required=True) parser.add_argument("--port", type=int, required=True) args = parser.parse_args() if not 1024 <= args.port <= 65535: parser.error("unprivileged loopback port required") verifier = load_registered_verifier(args.owner_verifier) identity = verifier.signer_id store = TaskPlaneStore(str(args.db), high_assurance=True) authority = MissionAuthority(store, principal_bindings=[MissionPrincipalBinding( authenticated_identity=identity, owner_principal_id=identity, acceptance_verifier_id="identity-lineage-live-closure-v1", allowed_task_capabilities=( "code.read", "code.write", "test.execute", "governed.write.file", "governed.write.branch", ), max_risk="medium", )]) service = TaskPlaneService(store, policy=PolicyEngine( identity_verifier=IdentityVerifier({identity}), execution_enabled=False, identity_capabilities={identity: {"task.creator", "task.read", "task.delegate"}}, ), mission_authority=authority) ingress = SignedMissionIngress(service, verifier) # SQLite's existing connection and transaction lock share one request thread. HTTPServer(("127.0.0.1", args.port), make_handler(ingress)).serve_forever() if __name__ == "__main__": main()