Compare commits

..
Author SHA1 Message Date
Codex Governance Request 5528868ef9 governance: add exact two-parent merge closure 2026-08-01 17:16:48 +08:00
AIOS Governance Automation 9303a5d684 governance: replace bootstrap with RFC3339 offset fix
aios/branch-protection task-scoped PASS evidence_sha256=9cda4ebf561ae96e3f2f21eb4d4b89541626026fe521d089b7d5ec6d4af80787
aios/evidence-closure task-scoped PASS evidence_sha256=2239bd1868318c50d4e3287ce94adb92c2d13759aa8ef01cfea97142ae8a94b4
aios/secret-scan task-scoped PASS evidence_sha256=4ae633ace2f93b4093545108b2511c35530f1f1e89058bbb2633151f5d166248
aios/state-machine task-scoped PASS evidence_sha256=ce63ce87cfdf0a17d4c1f0a0a68df1be8a48596c44e914fa8604ee3d05f8ead2
aios/validator task-scoped PASS evidence_sha256=469ef5a951db82e7d4b65554185cd337e5c4c6b9d8dcef92c4babec6d0ff9daf
2026-08-01 02:50:00 +00:00
codex 8814dff202 Merge pull request '[TASK SCOPED GOVERNANCE BOOTSTRAP RENEWAL] AIOS Two-Stage Owner Campaign Phase A' (#35) from governance/request/two-stage-owner-campaign-v2-phase-a-renewal-20260731T081147Z into governance/approvals 2026-07-31 17:35:54 +08:00
Codex Governance Request ff6743e851 governance: renew two-stage phase-a activation window
aios/branch-protection PR35 Phase A PASS evidence_sha256=47068a6193db3a257d4af7d7c03e5b29e6ab3b7b146e262efb05e704b158bdfc
aios/evidence-closure PR35 Phase A PASS evidence_sha256=247b155c55a47addee9485e9005da7e0069c0c1c5d977e45dadb3f7da9caf514
aios/secret-scan PR35 Phase A PASS evidence_sha256=e9d0646d237cb0e5ee0456e778571ea81f470b621a5317d37c510804332a2672
aios/state-machine PR35 Phase A PASS evidence_sha256=c14af062600f46b708124c854ad1c2aaad67ec47dd76caca8ee1ae71b9af6d09
aios/validator PR35 Phase A PASS evidence_sha256=b4d4f5a559e411bd5173d6d076cb484e3983ef29db14b778ffd49d889ddebcda
governance/authority-mirror PR35 Phase A PASS evidence_sha256=568f582e530d1cea4af3a117ed98e041462ca9011d4bfe2fafe7a67fd4688103
governance/fault-injection PR35 Phase A PASS evidence_sha256=e1a2551809ae5800eb701c0ae9a5862f3dae166a43ffc8acab68aa218728a6b4
governance/runtime-isolation PR35 Phase A PASS evidence_sha256=e5be2a28129c65d020f7221fc2076550d029187b0cc02c7100fb02574787cb12
governance/schema-contract PR35 Phase A PASS evidence_sha256=2b7e282c41a7e8bd02a85181d8483623449021bed3c8d9890aedaf2f550ab0d4
governance/validator-security PR35 Phase A PASS evidence_sha256=1abe11b6fe05a5318f8cf133749d62bd28292d6252f0c61726f7b2efd918c887
2026-07-31 16:17:30 +08:00
codex ebd7439874 Merge pull request '[SINGLE OWNER LIVE ACTIVATION HARDENING] Implementation and Execution' (#33) from governance/request/single-owner-live-activation-hardening-20260729T043149Z into governance/approvals
Reviewed-on: #33
Reviewed-by: gpt <gpt@imruyi.top>
Reviewed-by: codex <codex@imruyi.top>
2026-07-29 12:45:22 +08:00
Codex Agent c41e278c59 governance: approve live activation hardening
aios/branch-protection AIOS governed hardening gate PASS
aios/evidence-closure AIOS governed hardening gate PASS
aios/secret-scan AIOS governed hardening gate PASS
aios/state-machine AIOS governed hardening gate PASS
aios/validator AIOS governed hardening gate PASS
2026-07-29 12:31:49 +08:00
gpt 1071979079 Merge pull request '[SINGLE OWNER LIVE ACTIVATION] Implementation and Execution' (#32) from governance/request/single-owner-governance-live-activation-20260729T033228Z into governance/approvals
Reviewed-on: #32
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 11:42:55 +08:00
Codex Agent 9a158fcab9 governance: request single-owner live activation 2026-07-29 11:32:28 +08:00
gpt 8b7f9d9028 Merge pull request '[OWNER RATIFICATION] PR #30 Single-Owner Atomic Activation' (#31) from governance/request/single-owner-atomic-activation-owner-ratification-20260729T014918Z-e503d96665ee into governance/approvals
Reviewed-on: #31
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 09:57:54 +08:00
AIOS Governance Requester 3aa1872084 governance: request PR30 owner ratification 2026-07-29 09:49:19 +08:00
gpt f6bef90633 Merge pull request '[SINGLE OWNER GOVERNANCE ATOMIC ACTIVATION] Activate Machine-Gated Owner Policy' (#30) from governance/request/single-owner-governance-atomic-activation-20260728T204808Z-4cab1d5829d6 into governance/approvals
Reviewed-on: #30
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 09:25:08 +08:00
AIOS Governance Requester c2eed5b379 governance: request atomic single-owner activation 2026-07-29 04:48:09 +08:00
codex 6e8212608e Merge pull request '[SINGLE OWNER ACTIVATION PREREQUISITES] Safe Atomic Control Plane' (#29) from governance/request/single-owner-governance-activation-prerequisites-20260728T183025127107Z into governance/approvals
Reviewed-on: #29
Reviewed-by: gpt <gpt@imruyi.top>
Reviewed-by: codex <codex@imruyi.top>
2026-07-29 02:49:26 +08:00
AIOS Activation Prerequisites Requester e6a53888fe governance: request activation prerequisites 2026-07-29 02:30:25 +08:00
gpt 2bef44f6bc Merge pull request '[FINAL OWNER RATIFICATION] Single Owner Governance Activation' (#28) from governance/request/single-owner-governance-final-owner-ratification-20260728T173634412838Z into governance/approvals
Reviewed-on: #28
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 01:46:57 +08:00
AIOS Final Owner Ratification Requester a96f36bf72 governance: request final owner ratification 2026-07-29 01:36:35 +08:00
gpt 4e6ef70029 Merge pull request '[OWNER RATIFICATION + CONTROL PLANE] Single Owner Governance Activation' (#27) from governance/request/single-owner-control-plane-deployment-20260728T170740Z-ea7a102dac417c23 into governance/approvals
Reviewed-on: #27
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 01:11:56 +08:00
AIOS Governance Recovery Requester 80feef309f governance: request owner ratification and control-plane deployment 2026-07-29 01:07:41 +08:00
gpt a5489f1b67 Merge pull request '[OWNER BREAK-GLASS GOVERNANCE RESET] Single Owner with Machine Gates' (#26) from governance/request/single-owner-governance-migration-20260728T162246Z into governance/approvals
Reviewed-on: #26
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-29 00:39:54 +08:00
AIOS Governance Migration Requester 312d3b4830 governance: propose single-owner machine-gated model 2026-07-29 00:22:47 +08:00
gpt ac2dc5c30e Merge pull request '[CONTROL PLANE DEPLOYMENT] AIOS Integration Refresh Provisioner' (#25) from governance/request/integration-refresh-control-plane-deployment-20260728T093428Z into governance/approvals
Reviewed-on: #25
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-28 18:35:26 +08:00
AIOS Governance Request Publisher 5ef261b265 governance: request integration refresh control-plane deployment 2026-07-28 17:34:29 +08:00
gpt 3a22c3c7d8 Merge pull request '[SOURCE MAPPING EXECUTION RENEWAL] AIOS Integration Refresh Runtime Sources' (#24) from governance/request/integration-refresh-source-mapping-execution-renewal-20260728T061044Z into governance/approvals
Reviewed-on: #24
Reviewed-by: gpt <gpt@imruyi.top>
Reviewed-by: codex <codex@imruyi.top>
2026-07-28 16:12:41 +08:00
chatgpt-gitops-bot 1c9f28a613 governance: renew source mapping execution window 2026-07-28 14:10:44 +08:00
gpt 9514062cf3 Merge pull request '[SOURCE CANONICALIZATION] AIOS Integration Refresh Runtime Sources' (#23) from governance/request/integration-refresh-source-canonicalization-20260727 into governance/approvals
Reviewed-on: #23
Reviewed-by: codex <codex@imruyi.top>
Reviewed-by: gpt <gpt@imruyi.top>
2026-07-28 02:41:45 +08:00
AIOS Governance Automation a701a32cb4 governance(approval): request source secret remediation 2026-07-27 18:36:27 +08:00
codex 45f3226662 Merge pull request '[IMPLEMENTATION APPROVAL RENEWAL] AIOS Integration Refresh Provisioner' (#22) from governance/request/integration-refresh-provisioner-implementation-renewal-20260727 into governance/approvals
Reviewed-on: #22
Reviewed-by: gpt <gpt@imruyi.top>
Reviewed-by: codex <codex@imruyi.top>
2026-07-27 14:07:37 +08:00
AIOS Governance Automation 975d239d40 governance(approval): renew Integration Refresh Provisioner implementation 2026-07-27 13:00:11 +08:00
codex 3bc44accb5 Merge pull request '[IMPLEMENTATION APPROVAL] AIOS Integration Refresh Provisioner' (#21) from governance/request/integration-refresh-provisioner-implementation-20260726 into governance/approvals
Reviewed-on: #21
2026-07-27 03:58:14 +08:00
gva1785094553523a25 3304d87872 governance(approval): request Integration Refresh Provisioner implementation 2026-07-27 03:35:56 +08:00
gitops-bot 875d41c310 Merge pull request 'fix(gitops): harden Codex worker systemd profile' (#19) from patch/isolated-writer-systemd-profile-hardening-20260725 into main 2026-07-25 11:13:31 +08:00
chatgpt-gitops-bot 870ac61dc2 fix(gitops): harden Codex worker systemd profile 2026-07-25 11:08:55 +08:00
gitops-bot 009f276699 Merge pull request 'fix(gitops): add exact-path service policy for isolated writer' (#18) from patch/isolated-writer-exact-path-policy-20260725 into main 2026-07-25 10:19:02 +08:00
chatgpt-gitops-bot 600c717e17 fix(gitops): add exact-path service policy for isolated writer 2026-07-25 10:16:43 +08:00
gitops-bot 02be6d28ed merge(gitops): add constrained writer token policy and atomic commit-file
Source: patch/isolated-writer-token-policy-v2-20260724
Source commit: b1e240dda3
Target base: df099420d2
Production runtime changes: not authorized
Tag/Baseline/Registry operations: not authorized
2026-07-24 23:36:25 +08:00
chatgpt-gitops-bot b1e240dda3 fix(gitops): reject atomic writer force fields 2026-07-24 23:06:22 +08:00
chatgpt-gitops-bot 2dfbe837f4 fix(gitops): bind writer runtime policy v2 artifacts 2026-07-24 23:01:40 +08:00
chatgpt-gitops-bot 80df1e0d87 test(gitops): close writer authz and recovery contract 2026-07-24 22:56:58 +08:00
chatgpt-gitops-bot 7ecf7cbfce feat(gitops): add idempotent atomic commit-file endpoint 2026-07-24 22:56:58 +08:00
chatgpt-gitops-bot bbada7c863 feat(gitops): add constrained writer token policy v2 2026-07-24 22:56:58 +08:00
224 changed files with 55816 additions and 1894 deletions
@@ -5,13 +5,148 @@ import json
import os
import subprocess
from pathlib import Path
import urllib.parse
import aios_chatgpt_actions_api as api
import aios_isolated_writer_policy as policy
from isolated_writer_authz import AuthorizationError, authorize
from isolated_writer_commit_file import AtomicCommitFile, CommitFileError, OperationLedger
from isolated_writer_token_registry import TokenRegistry
_reject = api.reject_non_read_http
_write_file = api.write_file
_sync_branch = api.sync_branch
_original_do_get = api.H.do_GET
api.OPENAPI = Path(os.getenv("AIOS_GITOPS_ISOLATED_WRITER_OPENAPI", str(api.OPENAPI)))
def _registry() -> TokenRegistry:
return TokenRegistry(Path(os.environ["AIOS_GITOPS_TOKEN_REGISTRY_V2"]))
def _atomic_writer() -> AtomicCommitFile:
return AtomicCommitFile(
workspace=api.WS,
bare_repo=api.BARE_REPO,
ledger=OperationLedger(Path(os.environ["AIOS_GITOPS_WRITER_OPERATION_LEDGER"])),
remote=os.getenv("AIOS_GITOPS_GITEA_PUSH_REMOTE", ""),
audit=policy.append_audit_record,
)
def _bearer(handler) -> str:
value = handler.headers.get("Authorization", "")
return value[7:].strip() if value.startswith("Bearer ") else ""
def _authorize(handler, *, method: str, path: str, branch=None, target_path=None):
grant = authorize(
_registry(),
_bearer(handler),
method=method,
path=path,
source_ip=str(handler.client_address[0]),
workspace=api.WS,
branch=branch,
target_path=target_path,
)
grant.record["_source_ip"] = str(handler.client_address[0])
return grant
def _authorization_error(handler, exc: AuthorizationError):
return handler.sendj({"error": exc.code}, exc.status)
def _isolated_runtime_status(handler):
branch = api.sh(["rev-parse", "--abbrev-ref", "HEAD"], True)["stdout"]
head = api.sh(["rev-parse", "HEAD"], True)["stdout"]
return handler.sendj({
"service": os.getenv(
"AIOS_GITOPS_SERVICE_AUDIENCE",
"aios-isolated-writer.service",
),
"status": "active",
"runtime_role": os.getenv("AIOS_GITOPS_RUNTIME_ROLE"),
"workspace_role": os.getenv("AIOS_GITOPS_WORKSPACE_ROLE"),
"writes_enabled": os.getenv("AIOS_GITOPS_WRITES_ENABLED", "").lower()
in {"1", "true", "yes", "on"},
"allowed_branch": policy.allowed_branch(),
"approved_base_oid": policy.allowed_base_oid(),
"workspace_branch": branch,
"workspace_head_oid": head,
"repository_identity": os.getenv("AIOS_GITOPS_REPOSITORY_IDENTITY"),
"token_policy_version": 2,
"atomic_commit_file": True,
"path_policy_sha256": policy.configured_path_policy_sha256(),
})
def _isolated_do_get(self):
path = urllib.parse.urlparse(self.path).path.rstrip("/") or "/"
if path in {"/health", "/api/health"}:
return self.sendj({
"status": "ok",
"service": os.getenv(
"AIOS_GITOPS_SERVICE_AUDIENCE",
"aios-isolated-writer.service",
),
})
if path not in {"/api/runtime-status", "/api/baseline", "/api/patches"}:
return self.sendj({"error": "isolated_writer_operation_forbidden"}, 403)
try:
_authorize(self, method="GET", path=path)
except AuthorizationError as exc:
return _authorization_error(self, exc)
if path == "/api/runtime-status":
return _isolated_runtime_status(self)
return _original_do_get(self)
def _read_commit_file_body(handler):
try:
length = int(handler.headers.get("Content-Length", "0"))
except ValueError:
raise CommitFileError("writer_content_length_rejected") from None
if length <= 0:
raise CommitFileError("writer_request_object_required")
if length > 1_100_000:
raise CommitFileError("writer_request_too_large", 413)
raw = handler.rfile.read(length)
try:
value = json.loads(raw.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError):
raise CommitFileError("writer_request_json_rejected") from None
if not isinstance(value, dict):
raise CommitFileError("writer_request_object_required")
return value
def _isolated_do_post(self):
path = urllib.parse.urlparse(self.path).path.rstrip("/") or "/"
if path != "/api/commit-file":
return self.sendj({"error": "isolated_writer_operation_forbidden"}, 403)
try:
data = _read_commit_file_body(self)
branch = str(data.get("branch") or "")
target_path = str(data.get("path") or "")
grant = _authorize(
self,
method="POST",
path=path,
branch=branch,
target_path=target_path,
)
if api.content_has_secret(str(data.get("content") or "")):
raise CommitFileError("writer_secret_content_rejected", 403)
result = _atomic_writer().execute(grant, data)
return self.sendj(result)
except AuthorizationError as exc:
return _authorization_error(self, exc)
except CommitFileError as exc:
return self.sendj({"error": exc.code}, exc.status)
except PermissionError:
return self.sendj({"error": "isolated_writer_policy_rejected"}, 403)
def reject_non_read_http(handler, method: str, path: str) -> bool:
@@ -173,6 +308,8 @@ api.H.branch, api.H.file, api.H.commit, api.H.patch = (
_checked_commit,
_checked_patch,
)
api.H.do_GET = _isolated_do_get
api.H.do_POST = _isolated_do_post
if __name__ == "__main__":
policy.require_service_invariants(api.WS, api.BARE_REPO)
@@ -9,10 +9,9 @@ import re
from pathlib import Path, PurePosixPath, PureWindowsPath
from urllib.parse import unquote
WRITE_ENDPOINTS = frozenset({
"/api/branch", "/api/create-branch", "/api/file", "/api/commit-file",
"/api/commit", "/api/patch", "/api/create-patch",
})
import isolated_writer_path_policy as path_policy
WRITE_ENDPOINTS = frozenset({"/api/commit-file"})
ALLOWED_ROOTS = (
"active-runtime",
"docs",
@@ -69,6 +68,15 @@ def require_service_invariants(workspace: Path, bare_repo: Path) -> None:
raise PermissionError("isolated_writer_role_required")
if os.getenv("AIOS_GITOPS_WORKSPACE_ROLE", "") != "isolated-writer":
raise PermissionError("isolated_writer_workspace_role_required")
if os.getenv("AIOS_GITOPS_TOKEN_POLICY_VERSION_REQUIRED", "") != "2":
raise PermissionError("isolated_writer_token_policy_v2_required")
if not os.getenv("AIOS_GITOPS_SERVICE_AUDIENCE", "").strip():
raise PermissionError("isolated_writer_service_audience_required")
if not os.getenv("AIOS_GITOPS_TOKEN_REGISTRY_V2", "").strip():
raise PermissionError("isolated_writer_token_registry_required")
if not os.getenv("AIOS_GITOPS_WRITER_OPERATION_LEDGER", "").strip():
raise PermissionError("isolated_writer_operation_ledger_required")
path_policy.configured_path_policy()
for name in _DENY_FLAGS:
if os.getenv(name, "").strip().lower() not in _FALSE:
raise PermissionError("isolated_writer_forbidden_capability_flag")
@@ -182,6 +190,7 @@ def _audit_sanitize(value):
"private_key",
)
)
and str(key).lower() != "token_id"
else _audit_sanitize(inner)
)
for key, inner in value.items()
@@ -239,9 +248,14 @@ def validate_path(path: str, workspace: Path | None = None) -> str:
):
raise PermissionError("isolated_writer_path_rejected")
first = parts[0]
service_exact_path = False
if first in DENIED_ROOTS:
raise PermissionError("isolated_writer_protected_path_rejected")
if value != "README.md" and first not in ALLOWED_ROOTS:
try:
path_policy.require_service_path("commit_file.atomic", value)
service_exact_path = True
except path_policy.PathPolicyError as exc:
raise PermissionError(str(exc)) from None
if value != "README.md" and first not in ALLOWED_ROOTS and not service_exact_path:
raise PermissionError("isolated_writer_path_outside_allowed_roots")
if workspace is not None:
lexical_root = Path(os.path.abspath(str(workspace)))
@@ -261,6 +275,22 @@ def validate_path(path: str, workspace: Path | None = None) -> str:
return value
def validate_content_for_path(path: str, content: str) -> None:
if path.split("/", 1)[0] not in DENIED_ROOTS:
return
try:
path_policy.validate_content("commit_file.atomic", path, content)
except path_policy.PathPolicyError as exc:
raise PermissionError(str(exc)) from None
def configured_path_policy_sha256() -> str | None:
try:
return path_policy.configured_path_policy_sha256()
except path_policy.PathPolicyError as exc:
raise PermissionError(str(exc)) from None
def validate_commit_paths(paths: list[str], workspace: Path | None = None) -> None:
if enforcement_required():
for path in paths:
+167
View File
@@ -0,0 +1,167 @@
"""Fail-closed operation authorization for an isolated Git writer."""
from __future__ import annotations
import ipaddress
import os
import re
import subprocess
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
from isolated_writer_token_registry import TokenRegistry
ROUTE_OPERATIONS = {
("GET", "/api/runtime-status"): "runtime.status.read",
("GET", "/api/baseline"): "baseline.read",
("GET", "/api/patches"): "patches.read",
("POST", "/api/commit-file"): "commit_file.atomic",
}
OID_RE = re.compile(r"[0-9a-f]{40}")
class AuthorizationError(PermissionError):
def __init__(self, code: str, status: int = 403):
super().__init__(code)
self.code = code
self.status = status
@dataclass(frozen=True)
class AuthorizedGrant:
record: dict[str, Any]
operation: str
use_count: int
@property
def token_id(self) -> str:
return str(self.record["token_id"])
@property
def task_id(self) -> str:
return str(self.record["task_id"])
def operation_for(method: str, path: str) -> str:
operation = ROUTE_OPERATIONS.get((method.upper(), path))
if not operation:
raise AuthorizationError("isolated_writer_operation_forbidden")
return operation
def _parse_time(value: Any) -> datetime:
try:
parsed = datetime.fromisoformat(str(value).replace("Z", "+00:00"))
except (TypeError, ValueError):
raise AuthorizationError("writer_token_time_invalid") from None
if parsed.tzinfo is None:
raise AuthorizationError("writer_token_time_invalid")
return parsed.astimezone(timezone.utc)
def _git_is_ancestor(workspace: Path, base: str, branch: str) -> bool:
result = subprocess.run(
["git", "merge-base", "--is-ancestor", base, branch],
cwd=workspace,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
return result.returncode == 0
def _validate_grant(
grant: dict[str, Any],
*,
audience: str,
source_ip: str,
operation: str,
branch: str | None,
path: str | None,
workspace: Path,
current_time: datetime,
) -> None:
if int(grant.get("schema_version", 0)) != 2:
raise AuthorizationError("writer_token_policy_v2_required", 401)
if str(grant.get("audience") or "") != audience:
raise AuthorizationError("writer_token_audience_rejected")
try:
peer = ipaddress.ip_address(source_ip)
networks = [ipaddress.ip_network(str(value), strict=True) for value in grant.get("source_cidrs", [])]
except ValueError:
raise AuthorizationError("writer_token_source_rejected") from None
if not networks or not any(peer in network for network in networks):
raise AuthorizationError("writer_token_source_rejected")
created = _parse_time(grant.get("created_at"))
not_before = _parse_time(grant.get("not_before"))
expires = _parse_time(grant.get("expires_at"))
if expires <= not_before or (expires - created).total_seconds() > 1800:
raise AuthorizationError("writer_token_lifetime_rejected")
if current_time < not_before:
raise AuthorizationError("writer_token_not_yet_valid", 401)
if current_time >= expires:
raise AuthorizationError("writer_token_expired", 401)
if bool(grant.get("revoked")):
raise AuthorizationError("writer_token_revoked", 401)
operations = grant.get("allowed_operations")
if not isinstance(operations, list) or operation not in operations:
raise AuthorizationError("writer_token_operation_rejected")
expected_branch = str(grant.get("allowed_branch") or "")
configured_branch = os.getenv("AIOS_GITOPS_ALLOWED_BRANCH", "")
if expected_branch != configured_branch:
raise AuthorizationError("writer_token_branch_rejected")
if branch is not None and branch != expected_branch:
raise AuthorizationError("writer_token_branch_rejected")
if path is not None:
paths = grant.get("allowed_paths")
if not isinstance(paths, list) or path not in paths:
raise AuthorizationError("writer_token_path_rejected")
base = str(grant.get("approved_base_oid") or "").lower()
if not OID_RE.fullmatch(base):
raise AuthorizationError("writer_token_base_rejected")
if not _git_is_ancestor(workspace, base, expected_branch):
raise AuthorizationError("writer_token_base_not_ancestor")
def authorize(
registry: TokenRegistry,
token: str,
*,
method: str,
path: str,
source_ip: str,
workspace: Path,
branch: str | None = None,
target_path: str | None = None,
current_time: datetime | None = None,
) -> AuthorizedGrant:
if os.getenv("AIOS_GITOPS_TOKEN_POLICY_VERSION_REQUIRED", "") != "2":
raise AuthorizationError("writer_token_policy_v2_not_required")
if not token:
raise AuthorizationError("unauthorized", 401)
grant = registry.find(token)
if grant is None:
raise AuthorizationError("unauthorized", 401)
operation = operation_for(method, path)
_validate_grant(
grant,
audience=os.getenv("AIOS_GITOPS_SERVICE_AUDIENCE", ""),
source_ip=source_ip,
operation=operation,
branch=branch,
path=target_path,
workspace=workspace,
current_time=current_time or datetime.now(timezone.utc),
)
limits = grant.get("max_uses")
if not isinstance(limits, dict):
raise AuthorizationError("writer_token_use_limit_missing")
try:
used = registry.consume(str(grant["token_id"]), operation, int(limits[operation]))
except (KeyError, TypeError, ValueError):
raise AuthorizationError("writer_token_use_limit_missing") from None
except PermissionError as exc:
code = str(exc)
raise AuthorizationError(code, 401 if code == "writer_token_revoked" else 403) from None
return AuthorizedGrant(grant, operation, used)
@@ -0,0 +1,403 @@
"""Atomic, idempotent commit-file Saga for the isolated writer."""
from __future__ import annotations
import fcntl
import hashlib
import json
import os
import re
import sqlite3
import subprocess
import tempfile
import threading
from pathlib import Path
from typing import Any
import aios_isolated_writer_policy as policy
OID_RE = re.compile(r"[0-9a-f]{40}")
IDEMPOTENCY_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9._:-]{7,127}")
STATES = frozenset({
"PENDING", "FILE_WRITTEN", "COMMITTED", "PUSHED", "VERIFIED", "COMPLETED",
"FAILED_RECOVERABLE", "MANUAL_REVIEW_REQUIRED",
})
_LOCKS: dict[str, threading.Lock] = {}
_LOCKS_GUARD = threading.Lock()
_LEDGER_INIT_LOCK = threading.Lock()
class CommitFileError(RuntimeError):
def __init__(self, code: str, status: int = 400):
super().__init__(code)
self.code = code
self.status = status
class SimulatedCrash(RuntimeError):
pass
def canonical_digest(data: dict[str, Any]) -> str:
payload = {
"branch": data["branch"],
"path": data["path"],
"content_sha256": hashlib.sha256(data["content"].encode("utf-8")).hexdigest(),
"message": data["message"],
"expected_head_oid": data["expected_head_oid"],
}
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
return hashlib.sha256(encoded).hexdigest()
class OperationLedger:
def __init__(self, path: Path | str):
self.path = Path(path)
self.path.parent.mkdir(parents=True, exist_ok=True)
if self.path.parent.is_symlink() or self.path.is_symlink():
raise PermissionError("writer_operation_ledger_symlink_rejected")
with _LEDGER_INIT_LOCK:
with self.connect() as db:
db.execute(
"""
CREATE TABLE IF NOT EXISTS writer_operations (
operation_id TEXT PRIMARY KEY,
token_id TEXT NOT NULL,
task_id TEXT NOT NULL,
idempotency_key TEXT NOT NULL UNIQUE,
operation_digest TEXT NOT NULL,
branch TEXT NOT NULL,
path TEXT NOT NULL,
content_sha256 TEXT NOT NULL,
pre_head_oid TEXT NOT NULL,
commit_oid TEXT,
push_status TEXT,
verification_status TEXT,
state TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
error_code TEXT
)
"""
)
os.chmod(self.path, 0o600)
def connect(self) -> sqlite3.Connection:
db = sqlite3.connect(self.path, timeout=30)
db.row_factory = sqlite3.Row
db.execute("PRAGMA journal_mode=WAL")
db.execute("PRAGMA synchronous=FULL")
return db
def get_or_create(self, grant: Any, data: dict[str, Any], digest: str) -> dict[str, Any]:
key = data["idempotency_key"]
with self.connect() as db:
db.execute("BEGIN IMMEDIATE")
row = db.execute(
"SELECT * FROM writer_operations WHERE idempotency_key=?", (key,)
).fetchone()
if row:
db.commit()
record = dict(row)
if record["operation_digest"] != digest:
raise CommitFileError("writer_idempotency_conflict", 409)
if (
record["token_id"] != grant.token_id
or record["task_id"] != grant.task_id
):
raise CommitFileError("writer_idempotency_owner_conflict", 409)
return record
operation_id = hashlib.sha256(
f"{grant.task_id}\0{key}".encode("utf-8")
).hexdigest()
content_sha = hashlib.sha256(data["content"].encode("utf-8")).hexdigest()
db.execute(
"""
INSERT INTO writer_operations(
operation_id,token_id,task_id,idempotency_key,operation_digest,
branch,path,content_sha256,pre_head_oid,state
) VALUES(?,?,?,?,?,?,?,?,?,?)
""",
(
operation_id, grant.token_id, grant.task_id, key, digest,
data["branch"], data["path"], content_sha,
data["expected_head_oid"], "PENDING",
),
)
db.commit()
return self.get(key)
def get(self, key: str) -> dict[str, Any]:
with self.connect() as db:
row = db.execute(
"SELECT * FROM writer_operations WHERE idempotency_key=?", (key,)
).fetchone()
if row is None:
raise KeyError(key)
return dict(row)
def update(self, key: str, state: str, **fields: Any) -> dict[str, Any]:
if state not in STATES:
raise ValueError("invalid writer operation state")
allowed = {"commit_oid", "push_status", "verification_status", "error_code"}
assignments = ["state=?", "updated_at=CURRENT_TIMESTAMP"]
values: list[Any] = [state]
for name, value in fields.items():
if name not in allowed:
raise ValueError("invalid ledger field")
assignments.append(f"{name}=?")
values.append(value)
values.append(key)
with self.connect() as db:
db.execute("BEGIN IMMEDIATE")
db.execute(
f"UPDATE writer_operations SET {','.join(assignments)} WHERE idempotency_key=?",
values,
)
db.commit()
return self.get(key)
class AtomicCommitFile:
def __init__(
self,
*,
workspace: Path,
bare_repo: Path,
ledger: OperationLedger,
remote: str,
audit,
crash_after_state: str | None = None,
):
self.workspace = workspace
self.bare_repo = bare_repo
self.ledger = ledger
self.remote = remote
self.audit = audit
self.crash_after_state = crash_after_state
def _git(self, *args: str, check: bool = True) -> str:
result = subprocess.run(
["git", *args], cwd=self.workspace, text=True, capture_output=True
)
if check and result.returncode != 0:
raise CommitFileError("writer_git_operation_failed", 500)
return result.stdout.strip()
def _transition(self, key: str, state: str, **fields: Any) -> dict[str, Any]:
record = self.ledger.update(key, state, **fields)
if self.crash_after_state == state:
raise SimulatedCrash(state)
return record
def _validate(self, data: Any) -> dict[str, Any]:
if not isinstance(data, dict):
raise CommitFileError("writer_request_object_required")
required = ("branch", "path", "content", "message", "expected_head_oid", "idempotency_key")
if any(field not in data for field in required):
raise CommitFileError("writer_request_incomplete")
if data.get("force") or data.get("force_push"):
raise CommitFileError("isolated_writer_force_rejected", 403)
if set(data) != set(required):
raise CommitFileError("writer_request_fields_rejected")
item = {field: data[field] for field in required}
if item["branch"] != policy.allowed_branch():
raise CommitFileError("isolated_writer_branch_rejected", 403)
try:
item["path"] = policy.validate_path(item["path"], self.workspace)
except PermissionError as exc:
raise CommitFileError(str(exc), 403) from None
if not isinstance(item["content"], str) or "\x00" in item["content"]:
raise CommitFileError("writer_content_rejected")
try:
policy.validate_content_for_path(item["path"], item["content"])
except PermissionError as exc:
raise CommitFileError(str(exc), 403) from None
if len(item["content"].encode("utf-8")) > 1_048_576:
raise CommitFileError("writer_content_too_large", 413)
message = item["message"]
if (
not isinstance(message, str)
or not 1 <= len(message) <= 200
or "\x00" in message
or "\n" in message
or "\r" in message
):
raise CommitFileError("writer_message_rejected")
if not isinstance(item["expected_head_oid"], str) or not OID_RE.fullmatch(item["expected_head_oid"]):
raise CommitFileError("writer_expected_head_rejected")
if not isinstance(item["idempotency_key"], str) or not IDEMPOTENCY_RE.fullmatch(item["idempotency_key"]):
raise CommitFileError("writer_idempotency_key_rejected")
return item
def _atomic_write(self, relative: str, content: str) -> None:
target = self.workspace / relative
target.parent.mkdir(parents=True, exist_ok=True)
fd, temporary = tempfile.mkstemp(prefix=".writer-", dir=target.parent)
try:
with os.fdopen(fd, "wb", closefd=True) as stream:
stream.write(content.encode("utf-8"))
stream.flush()
os.fsync(stream.fileno())
os.replace(temporary, target)
parent_fd = os.open(target.parent, os.O_RDONLY | getattr(os, "O_DIRECTORY", 0))
try:
os.fsync(parent_fd)
finally:
os.close(parent_fd)
finally:
if os.path.exists(temporary):
os.unlink(temporary)
def _verify_remote(self, branch: str, oid: str) -> None:
bare = subprocess.run(
["git", "--git-dir", str(self.bare_repo), "rev-parse", f"refs/heads/{branch}"],
text=True, capture_output=True,
)
if bare.returncode != 0 or bare.stdout.strip() != oid:
raise CommitFileError("writer_authoritative_bare_oid_mismatch", 500)
remote = subprocess.run(
["git", "ls-remote", "--heads", self.remote, f"refs/heads/{branch}"],
cwd=self.workspace, text=True, capture_output=True,
)
if remote.returncode != 0:
raise CommitFileError("writer_gitea_verification_failed", 503)
fields = remote.stdout.strip().split()
if len(fields) != 2:
raise CommitFileError("writer_gitea_ref_missing", 503)
if fields[0] != oid:
raise CommitFileError("writer_gitea_oid_conflict", 409)
def execute(self, grant: Any, raw_data: Any) -> dict[str, Any]:
data = self._validate(raw_data)
digest = canonical_digest(data)
branch = data["branch"]
with _LOCKS_GUARD:
lock = _LOCKS.setdefault(branch, threading.Lock())
lock_path = self.ledger.path.parent / f"{hashlib.sha256(branch.encode()).hexdigest()}.lock"
with lock, open(lock_path, "a+b") as branch_lock:
fcntl.flock(branch_lock.fileno(), fcntl.LOCK_EX)
return self._execute_locked(grant, data, digest)
def _execute_locked(self, grant: Any, data: dict[str, Any], digest: str) -> dict[str, Any]:
key = data["idempotency_key"]
record = self.ledger.get_or_create(grant, data, digest)
if record["state"] == "COMPLETED":
return self._result(record, idempotent=True)
if self._git("rev-parse", "--abbrev-ref", "HEAD") != data["branch"]:
record = self._transition(
key, "MANUAL_REVIEW_REQUIRED", error_code="writer_current_branch_conflict"
)
self._audit(grant, data, digest, record, "manual_review_required")
raise CommitFileError("writer_current_branch_conflict", 409)
head = self._git("rev-parse", "HEAD")
commit_oid = record.get("commit_oid")
if head != record["pre_head_oid"] and head != commit_oid:
record = self._transition(
key, "MANUAL_REVIEW_REQUIRED", error_code="writer_branch_head_conflict"
)
self._audit(grant, data, digest, record, "manual_review_required")
raise CommitFileError("writer_branch_head_conflict", 409)
try:
state = record["state"]
if state == "MANUAL_REVIEW_REQUIRED":
raise CommitFileError("writer_manual_review_required", 409)
if state == "FAILED_RECOVERABLE":
if record.get("push_status") == "confirmed":
state = "PUSHED"
else:
state = "COMMITTED" if commit_oid else "FILE_WRITTEN"
if state == "PENDING":
self._atomic_write(data["path"], data["content"])
record = self._transition(key, "FILE_WRITTEN")
state = record["state"]
if state == "FILE_WRITTEN":
actual_sha = hashlib.sha256(
(self.workspace / data["path"]).read_bytes()
).hexdigest()
if actual_sha != record["content_sha256"]:
raise CommitFileError("writer_file_content_conflict", 409)
staged_before = self._git("diff", "--cached", "--name-only", check=False).splitlines()
if staged_before:
raise CommitFileError("writer_extra_staged_files_rejected", 409)
self._git("add", "--", data["path"])
staged = self._git("diff", "--cached", "--name-only").splitlines()
if staged != [data["path"]]:
raise CommitFileError("writer_extra_staged_files_rejected", 409)
self._git("commit", "-m", data["message"])
commit_oid = self._git("rev-parse", "HEAD")
record = self._transition(key, "COMMITTED", commit_oid=commit_oid)
state = record["state"]
if state == "COMMITTED":
commit_oid = str(record["commit_oid"])
pushed = subprocess.run(
["git", "push", "--porcelain", self.remote, f"HEAD:refs/heads/{data['branch']}"],
cwd=self.workspace, text=True, capture_output=True,
)
if pushed.returncode != 0:
self._transition(
key, "FAILED_RECOVERABLE",
push_status="failed", error_code="writer_gitea_push_failed",
)
raise CommitFileError("writer_gitea_push_failed", 503)
record = self._transition(key, "PUSHED", push_status="confirmed")
state = record["state"]
if state == "PUSHED":
commit_oid = str(record["commit_oid"])
self._verify_remote(data["branch"], commit_oid)
record = self._transition(
key, "VERIFIED", verification_status="bare+gitea"
)
state = record["state"]
if state == "VERIFIED":
record = self._transition(key, "COMPLETED", error_code=None)
self._audit(grant, data, digest, record, "completed")
return self._result(record, idempotent=False)
except SimulatedCrash:
raise
except CommitFileError as exc:
latest = self.ledger.get(key)
if latest["state"] not in {"FAILED_RECOVERABLE", "MANUAL_REVIEW_REQUIRED"}:
failure_state = (
"MANUAL_REVIEW_REQUIRED"
if exc.code in {
"writer_gitea_oid_conflict",
"writer_file_content_conflict",
"writer_current_branch_conflict",
}
else "FAILED_RECOVERABLE"
)
latest = self._transition(key, failure_state, error_code=exc.code)
self._audit(grant, data, digest, latest, "failed")
raise
def _audit(self, grant: Any, data: dict[str, Any], digest: str, record: dict[str, Any], result: str) -> None:
self.audit({
"token_id": grant.token_id,
"task_id": grant.task_id,
"audience": grant.record["audience"],
"source_ip": grant.record.get("_source_ip", "socket-peer"),
"operation": grant.operation,
"branch": data["branch"],
"path": data["path"],
"idempotency_key": data["idempotency_key"],
"operation_digest": digest,
"path_policy_sha256": policy.configured_path_policy_sha256(),
"pre_head_oid": record["pre_head_oid"],
"commit_oid": record.get("commit_oid"),
"result": result,
})
@staticmethod
def _result(record: dict[str, Any], *, idempotent: bool) -> dict[str, Any]:
return {
"status": "completed",
"state": record["state"],
"operation_id": record["operation_id"],
"branch": record["branch"],
"path": record["path"],
"commit_oid": record.get("commit_oid"),
"push_status": record.get("push_status"),
"verification_status": record.get("verification_status"),
"idempotent": idempotent,
}
@@ -0,0 +1,422 @@
"""Strict service-level exact-path policy for isolated Git writers."""
from __future__ import annotations
import grp
import hashlib
import json
import os
import re
import stat
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path, PurePosixPath, PureWindowsPath
from typing import Any
from urllib.parse import unquote
MAX_POLICY_BYTES = 65_536
POLICY_FIELDS = frozenset(
{
"schema_version",
"policy_id",
"audience",
"repository_identity",
"allowed_branch",
"allowed_operations",
}
)
OPERATION_FIELDS = frozenset({"exact_paths", "max_content_bytes", "content_profile"})
SUPPORTED_OPERATIONS = frozenset({"commit_file.atomic"})
SUPPORTED_CONTENT_PROFILES = frozenset({"systemd-codex-review-worker-v1"})
_SECRET_RE = re.compile(
r"(?i)(authorization\s*:|bearer\s+|(?:token|password|secret)\s*[:=])"
)
_SYSTEMD_NAME_RE = re.compile(r"[A-Za-z][A-Za-z0-9]*\Z")
_SYSTEMD_MAX_LINE_BYTES = 4096
_SYSTEMD_ALLOWED_DIRECTIVES = {
"Unit": frozenset({"Description", "After", "Wants"}),
"Service": frozenset(
{
"Type",
"User",
"Group",
"WorkingDirectory",
"Environment",
"ExecStart",
"Restart",
"RestartSec",
"NoNewPrivileges",
"PrivateTmp",
"PrivateDevices",
"ProtectSystem",
"ProtectHome",
"ProtectKernelTunables",
"ProtectKernelModules",
"ProtectControlGroups",
"LockPersonality",
"RestrictSUIDSGID",
"RestrictRealtime",
"MemoryDenyWriteExecute",
"RuntimeDirectory",
"StateDirectory",
"CacheDirectory",
"ReadOnlyPaths",
"ReadWritePaths",
"UMask",
}
),
"Install": frozenset({"WantedBy"}),
}
_SYSTEMD_MULTI_DIRECTIVES = frozenset(
{
("Service", "Environment"),
("Service", "ReadOnlyPaths"),
("Service", "ReadWritePaths"),
}
)
_SYSTEMD_EXACT_SINGLE_VALUES = {
("Unit", "Description"): "AIOS Codex Review/Test Worker",
("Unit", "After"): "network-online.target",
("Unit", "Wants"): "network-online.target",
("Service", "Type"): "simple",
("Service", "User"): "aiman",
("Service", "Group"): "gitops",
(
"Service",
"WorkingDirectory",
): "/usr/libexec/aios-codex-review-test-worker/current",
(
"Service",
"ExecStart",
): "/usr/bin/python3 -m task_plane.workers.codex_review_test",
("Service", "Restart"): "on-failure",
("Service", "RestartSec"): "2",
("Service", "NoNewPrivileges"): "true",
("Service", "PrivateTmp"): "true",
("Service", "PrivateDevices"): "true",
("Service", "ProtectSystem"): "strict",
("Service", "ProtectHome"): "true",
("Service", "ProtectKernelTunables"): "true",
("Service", "ProtectKernelModules"): "true",
("Service", "ProtectControlGroups"): "true",
("Service", "LockPersonality"): "true",
("Service", "RestrictSUIDSGID"): "true",
("Service", "RestrictRealtime"): "true",
("Service", "MemoryDenyWriteExecute"): "true",
("Service", "RuntimeDirectory"): "aios-codex-review-test-worker",
("Service", "StateDirectory"): "aios-codex-review-test-worker",
("Service", "CacheDirectory"): "aios-codex-review-test-worker",
("Service", "UMask"): "0077",
("Install", "WantedBy"): "multi-user.target",
}
_SYSTEMD_EXACT_MULTI_VALUES = {
("Service", "Environment"): (
"AIOS_CODEX_WORKER_MODE=shadow",
"AIOS_TASK_PLANE_EXECUTION_ENABLED=false",
"PYTHONDONTWRITEBYTECODE=1",
),
("Service", "ReadOnlyPaths"): (
"/data/aios-gitops/repo.git",
"/usr/libexec/aios-codex-review-test-worker",
),
("Service", "ReadWritePaths"): (
"/run/aios-codex-review-test-worker",
"/var/lib/aios-codex-review-test-worker",
"/var/cache/aios-codex-review-test-worker",
),
}
class PathPolicyError(PermissionError):
pass
@dataclass(frozen=True)
class OperationPolicy:
exact_paths: tuple[str, ...]
max_content_bytes: int
content_profile: str
@dataclass(frozen=True)
class ServicePathPolicy:
schema_version: int
policy_id: str
audience: str
repository_identity: str
allowed_branch: str
allowed_operations: dict[str, OperationPolicy]
sha256: str
def operation(self, name: str) -> OperationPolicy:
try:
return self.allowed_operations[name]
except KeyError:
raise PathPolicyError("isolated_writer_service_operation_rejected") from None
def require_exact_path(self, operation: str, path: str) -> OperationPolicy:
selected = self.operation(operation)
if path not in selected.exact_paths:
raise PathPolicyError("isolated_writer_service_path_rejected")
return selected
def _canonical_json(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
+ "\n"
).encode("utf-8")
def validate_relative_path_syntax(path: str) -> str:
if not isinstance(path, str):
raise PathPolicyError("isolated_writer_path_rejected")
if not path or path != path.strip() or "\x00" in path or "\\" in path:
raise PathPolicyError("isolated_writer_path_rejected")
try:
decoded = unquote(path, errors="strict")
except (UnicodeDecodeError, ValueError):
raise PathPolicyError("isolated_writer_path_rejected") from None
if decoded != path:
raise PathPolicyError("isolated_writer_path_rejected")
posix = PurePosixPath(path)
windows = PureWindowsPath(path)
parts = path.split("/")
if (
posix.is_absolute()
or windows.is_absolute()
or bool(windows.drive)
or any(part in {"", ".", ".."} for part in parts)
):
raise PathPolicyError("isolated_writer_path_rejected")
return path
def _require_fields(value: dict[str, Any], allowed: frozenset[str], code: str) -> None:
if set(value) != allowed:
raise PathPolicyError(code)
def _parse_policy(document: Any, canonical: bytes) -> ServicePathPolicy:
if not isinstance(document, dict):
raise PathPolicyError("isolated_writer_path_policy_object_required")
_require_fields(document, POLICY_FIELDS, "isolated_writer_path_policy_fields_rejected")
if document["schema_version"] != 1:
raise PathPolicyError("isolated_writer_path_policy_schema_rejected")
text_fields = (
"policy_id",
"audience",
"repository_identity",
"allowed_branch",
)
if any(
not isinstance(document[field], str) or not document[field].strip()
for field in text_fields
):
raise PathPolicyError("isolated_writer_path_policy_value_rejected")
raw_operations = document["allowed_operations"]
if not isinstance(raw_operations, dict) or not raw_operations:
raise PathPolicyError("isolated_writer_path_policy_operations_rejected")
if not set(raw_operations).issubset(SUPPORTED_OPERATIONS):
raise PathPolicyError("isolated_writer_path_policy_operations_rejected")
operations: dict[str, OperationPolicy] = {}
for name, raw in raw_operations.items():
if not isinstance(raw, dict):
raise PathPolicyError("isolated_writer_path_policy_operation_rejected")
_require_fields(
raw,
OPERATION_FIELDS,
"isolated_writer_path_policy_operation_fields_rejected",
)
paths = raw["exact_paths"]
if (
not isinstance(paths, list)
or not paths
or any(not isinstance(item, str) for item in paths)
):
raise PathPolicyError("isolated_writer_path_policy_paths_rejected")
validated = tuple(validate_relative_path_syntax(item) for item in paths)
if len(set(validated)) != len(validated):
raise PathPolicyError("isolated_writer_path_policy_paths_rejected")
maximum = raw["max_content_bytes"]
if not isinstance(maximum, int) or isinstance(maximum, bool) or not 1 <= maximum <= 1_048_576:
raise PathPolicyError("isolated_writer_path_policy_size_rejected")
profile = raw["content_profile"]
if profile not in SUPPORTED_CONTENT_PROFILES:
raise PathPolicyError("isolated_writer_path_policy_profile_rejected")
operations[name] = OperationPolicy(validated, maximum, profile)
return ServicePathPolicy(
schema_version=1,
policy_id=document["policy_id"],
audience=document["audience"],
repository_identity=document["repository_identity"],
allowed_branch=document["allowed_branch"],
allowed_operations=operations,
sha256=hashlib.sha256(canonical).hexdigest(),
)
def load_path_policy(
path: Path,
*,
expected_owner_uid: int = 0,
expected_group_gid: int | None = None,
expected_parent_mode: int = 0o750,
expected_file_mode: int = 0o640,
) -> ServicePathPolicy:
lexical = Path(os.path.abspath(str(path)))
if lexical.is_symlink():
raise PathPolicyError("isolated_writer_path_policy_symlink_rejected")
try:
parent_info = lexical.parent.stat(follow_symlinks=False)
file_info = lexical.stat(follow_symlinks=False)
except FileNotFoundError:
raise PathPolicyError("isolated_writer_path_policy_missing") from None
if stat.S_ISLNK(parent_info.st_mode) or not stat.S_ISDIR(parent_info.st_mode):
raise PathPolicyError("isolated_writer_path_policy_parent_rejected")
if stat.S_ISLNK(file_info.st_mode) or not stat.S_ISREG(file_info.st_mode):
raise PathPolicyError("isolated_writer_path_policy_file_rejected")
if lexical.resolve(strict=True) != lexical:
raise PathPolicyError("isolated_writer_path_policy_symlink_rejected")
if (
parent_info.st_uid != expected_owner_uid
or stat.S_IMODE(parent_info.st_mode) != expected_parent_mode
):
raise PathPolicyError("isolated_writer_path_policy_parent_permissions_rejected")
if (
file_info.st_uid != expected_owner_uid
or stat.S_IMODE(file_info.st_mode) != expected_file_mode
):
raise PathPolicyError("isolated_writer_path_policy_permissions_rejected")
if expected_group_gid is not None and (
parent_info.st_gid != expected_group_gid or file_info.st_gid != expected_group_gid
):
raise PathPolicyError("isolated_writer_path_policy_group_rejected")
if file_info.st_size <= 0 or file_info.st_size > MAX_POLICY_BYTES:
raise PathPolicyError("isolated_writer_path_policy_file_size_rejected")
raw = lexical.read_bytes()
try:
document = json.loads(raw.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError):
raise PathPolicyError("isolated_writer_path_policy_json_rejected") from None
canonical = _canonical_json(document)
if raw != canonical:
raise PathPolicyError("isolated_writer_path_policy_not_canonical")
return _parse_policy(document, canonical)
@lru_cache(maxsize=1)
def configured_path_policy() -> ServicePathPolicy | None:
configured = os.getenv("AIOS_GITOPS_PATH_POLICY_FILE", "").strip()
if not configured:
return None
if not Path(configured).is_absolute():
raise PathPolicyError("isolated_writer_path_policy_path_rejected")
try:
gitops_gid = grp.getgrnam("gitops").gr_gid
except KeyError:
raise PathPolicyError("isolated_writer_path_policy_group_rejected") from None
loaded = load_path_policy(Path(configured), expected_group_gid=gitops_gid)
if loaded.audience != os.getenv("AIOS_GITOPS_SERVICE_AUDIENCE", ""):
raise PathPolicyError("isolated_writer_path_policy_audience_rejected")
if loaded.repository_identity != os.getenv("AIOS_GITOPS_REPOSITORY_IDENTITY", ""):
raise PathPolicyError("isolated_writer_path_policy_repository_rejected")
if loaded.allowed_branch != os.getenv("AIOS_GITOPS_ALLOWED_BRANCH", ""):
raise PathPolicyError("isolated_writer_path_policy_branch_rejected")
return loaded
def clear_path_policy_cache() -> None:
configured_path_policy.cache_clear()
def require_service_path(operation: str, path: str) -> OperationPolicy:
loaded = configured_path_policy()
if loaded is None:
raise PathPolicyError("isolated_writer_service_path_policy_required")
return loaded.require_exact_path(operation, path)
def configured_path_policy_sha256() -> str | None:
loaded = configured_path_policy()
return None if loaded is None else loaded.sha256
def validate_content(operation: str, path: str, content: str) -> None:
selected = require_service_path(operation, path)
try:
encoded = content.encode("utf-8", errors="strict")
except (AttributeError, UnicodeEncodeError):
raise PathPolicyError("isolated_writer_systemd_profile_rejected") from None
if len(encoded) > selected.max_content_bytes:
raise PathPolicyError("isolated_writer_service_content_too_large")
if selected.content_profile == "systemd-codex-review-worker-v1":
_validate_systemd_codex_review_worker(content)
return
raise PathPolicyError("isolated_writer_path_policy_profile_rejected")
def _validate_systemd_codex_review_worker(content: str) -> None:
if not isinstance(content, str):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
try:
content.encode("utf-8", errors="strict")
except UnicodeEncodeError:
raise PathPolicyError("isolated_writer_systemd_profile_rejected") from None
if (
"\x00" in content
or "\r" in content
or _SECRET_RE.search(content)
or not content.endswith("\n")
):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
sections: set[str] = set()
values: dict[tuple[str, str], list[str]] = {}
section: str | None = None
for line in content.splitlines():
if len(line.encode("utf-8")) > _SYSTEMD_MAX_LINE_BYTES:
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
if not line:
continue
if line[0].isspace() or line.startswith(("#", ";")):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
if line.startswith("[") and line.endswith("]"):
candidate = line[1:-1]
if (
not _SYSTEMD_NAME_RE.fullmatch(candidate)
or candidate not in _SYSTEMD_ALLOWED_DIRECTIVES
or candidate in sections
):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
sections.add(candidate)
section = candidate
continue
if section is None or "=" not in line:
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
directive, value = line.split("=", 1)
if (
not _SYSTEMD_NAME_RE.fullmatch(directive)
or directive not in _SYSTEMD_ALLOWED_DIRECTIVES[section]
or not value
or value != value.strip()
):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
key = (section, directive)
if key in values and key not in _SYSTEMD_MULTI_DIRECTIVES:
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
values.setdefault(key, []).append(value)
if sections != set(_SYSTEMD_ALLOWED_DIRECTIVES):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
if set(values) != set(_SYSTEMD_EXACT_SINGLE_VALUES) | set(
_SYSTEMD_EXACT_MULTI_VALUES
):
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
for key, expected in _SYSTEMD_EXACT_SINGLE_VALUES.items():
if values.get(key) != [expected]:
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
for key, expected in _SYSTEMD_EXACT_MULTI_VALUES.items():
observed = values.get(key, [])
if len(observed) != len(set(observed)) or tuple(observed) != expected:
raise PathPolicyError("isolated_writer_systemd_profile_rejected")
@@ -0,0 +1,241 @@
"""Digest-only, task-scoped token registry for isolated writers."""
from __future__ import annotations
import argparse
import hashlib
import hmac
import json
import os
import grp
import pwd
import secrets
import sqlite3
import stat
import threading
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
_REGISTRY_INIT_LOCK = threading.Lock()
def utc_now() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def token_digest(token: str) -> str:
return hashlib.sha256(token.encode("utf-8")).hexdigest()
class TokenRegistry:
def __init__(self, path: Path | str):
self.path = Path(path)
self._prepare()
def _prepare(self) -> None:
self.path.parent.mkdir(parents=True, exist_ok=True)
if self.path.parent.is_symlink() or self.path.is_symlink():
raise PermissionError("writer_token_registry_symlink_rejected")
with _REGISTRY_INIT_LOCK:
with self._connect() as db:
db.executescript(
"""
CREATE TABLE IF NOT EXISTS token_grants (
token_id TEXT PRIMARY KEY,
token_digest TEXT NOT NULL UNIQUE,
grant_json TEXT NOT NULL,
revoked INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS token_uses (
token_id TEXT NOT NULL,
operation TEXT NOT NULL,
use_count INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY(token_id, operation),
FOREIGN KEY(token_id) REFERENCES token_grants(token_id)
);
"""
)
os.chmod(self.path, 0o600)
def _connect(self) -> sqlite3.Connection:
db = sqlite3.connect(self.path, timeout=30, isolation_level=None)
db.row_factory = sqlite3.Row
db.execute("PRAGMA journal_mode=WAL")
db.execute("PRAGMA synchronous=FULL")
db.execute("PRAGMA foreign_keys=ON")
return db
def issue(self, grant: dict[str, Any], token: str | None = None) -> tuple[str, dict[str, Any]]:
value = token or secrets.token_urlsafe(32)
if len(value.encode("utf-8")) < 32:
raise ValueError("writer_token_entropy_insufficient")
record = dict(grant)
record["schema_version"] = 2
record["token_digest"] = token_digest(value)
record["revoked"] = False
record.setdefault("created_at", utc_now())
required = (
"token_id",
"audience",
"task_id",
"source_cidrs",
"allowed_branch",
"approved_base_oid",
"allowed_operations",
"allowed_paths",
"not_before",
"expires_at",
"max_uses",
"issued_by",
)
if any(not record.get(field) for field in required):
raise ValueError("writer_token_grant_incomplete")
encoded = json.dumps(record, sort_keys=True, separators=(",", ":"))
with self._connect() as db:
db.execute("BEGIN IMMEDIATE")
try:
db.execute(
"""
INSERT INTO token_grants(token_id, token_digest, grant_json, revoked, created_at)
VALUES(?,?,?,?,?)
""",
(
str(record["token_id"]),
str(record["token_digest"]),
encoded,
0,
str(record["created_at"]),
),
)
db.execute("COMMIT")
except Exception:
db.execute("ROLLBACK")
raise
return value, record
def find(self, token: str) -> dict[str, Any] | None:
candidate = token_digest(token)
with self._connect() as db:
rows = db.execute(
"SELECT token_digest, grant_json, revoked FROM token_grants"
).fetchall()
match = None
for row in rows:
if hmac.compare_digest(str(row["token_digest"]), candidate):
match = dict(json.loads(str(row["grant_json"])))
match["revoked"] = bool(row["revoked"])
return match
def consume(self, token_id: str, operation: str, maximum: int) -> int:
if maximum < 1:
raise PermissionError("writer_token_operation_exhausted")
with self._connect() as db:
db.execute("BEGIN IMMEDIATE")
try:
row = db.execute(
"SELECT revoked FROM token_grants WHERE token_id=?",
(token_id,),
).fetchone()
if row is None or bool(row["revoked"]):
raise PermissionError("writer_token_revoked")
used_row = db.execute(
"SELECT use_count FROM token_uses WHERE token_id=? AND operation=?",
(token_id, operation),
).fetchone()
used = int(used_row["use_count"]) if used_row else 0
if used >= maximum:
raise PermissionError("writer_token_operation_exhausted")
current = used + 1
db.execute(
"""
INSERT INTO token_uses(token_id, operation, use_count)
VALUES(?,?,?)
ON CONFLICT(token_id, operation)
DO UPDATE SET use_count=excluded.use_count
""",
(token_id, operation, current),
)
db.execute("COMMIT")
return current
except Exception:
db.execute("ROLLBACK")
raise
def revoke(self, token_id: str) -> bool:
with self._connect() as db:
db.execute("BEGIN IMMEDIATE")
changed = db.execute(
"UPDATE token_grants SET revoked=1 WHERE token_id=? AND revoked=0",
(token_id,),
).rowcount
db.execute("COMMIT")
return bool(changed)
def usage(self, token_id: str, operation: str) -> int:
with self._connect() as db:
row = db.execute(
"SELECT use_count FROM token_uses WHERE token_id=? AND operation=?",
(token_id, operation),
).fetchone()
return int(row["use_count"]) if row else 0
def _write_secret_file(
path: Path,
token: str,
*,
owner: str | None = None,
group: str | None = None,
) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
if path.parent.is_symlink() or path.is_symlink():
raise PermissionError("writer_token_file_symlink_rejected")
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
if hasattr(os, "O_NOFOLLOW"):
flags |= os.O_NOFOLLOW
fd = os.open(path, flags, 0o600)
try:
if not stat.S_ISREG(os.fstat(fd).st_mode):
raise PermissionError("writer_token_file_not_regular")
if owner is not None or group is not None:
uid = pwd.getpwnam(owner).pw_uid if owner is not None else -1
gid = grp.getgrnam(group).gr_gid if group is not None else -1
os.fchown(fd, uid, gid)
os.write(fd, token.encode("utf-8"))
os.fsync(fd)
finally:
os.close(fd)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--registry", required=True)
sub = parser.add_subparsers(dest="command", required=True)
issue = sub.add_parser("issue")
issue.add_argument("--grant-file", required=True)
issue.add_argument("--token-file", required=True)
issue.add_argument("--owner")
issue.add_argument("--group")
revoke = sub.add_parser("revoke")
revoke.add_argument("--token-id", required=True)
args = parser.parse_args(argv)
registry = TokenRegistry(args.registry)
if args.command == "issue":
grant = json.loads(Path(args.grant_file).read_text(encoding="utf-8"))
token, record = registry.issue(grant)
_write_secret_file(
Path(args.token_file),
token,
owner=args.owner,
group=args.group,
)
print(json.dumps({"token_id": record["token_id"], "created": True}, sort_keys=True))
return 0
changed = registry.revoke(args.token_id)
print(json.dumps({"token_id": args.token_id, "revoked": changed}, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -1 +0,0 @@
"""Isolated, Shadow-attested Codex Task Plane Worker components."""
@@ -1,212 +0,0 @@
"""Shadow-only Codex read/review/test worker lifecycle and CLI."""
from __future__ import annotations
import argparse
import json
import os
import threading
import time
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable
from .result_attestation import TaskResultEnvelope, TrustPolicy, task_result_envelope
from .task_client import CredentialSource, StageAClientConfig, TaskPlaneClient
MAX_CONCURRENCY = 1
HEARTBEAT_INTERVAL_SECONDS = 15
CLAIM_LEASE_SECONDS = 120
SHADOW_ONLY = True
DEFAULT_TRUST_LEVEL = TrustPolicy.SHADOW_ATTESTED
DEFAULT_PRODUCTION_TRUST = False
READONLY_CAPABILITIES = ("code.read", "test.python", "review.security")
class CodexReviewTaskError(ValueError):
pass
@dataclass(frozen=True)
class CodexReviewTaskPolicy:
worker_id: str
identity: str
trust_zone: str = "isolated-review"
max_concurrency: int = MAX_CONCURRENCY
heartbeat_interval_seconds: int = HEARTBEAT_INTERVAL_SECONDS
claim_lease_seconds: int = CLAIM_LEASE_SECONDS
shadow_only: bool = SHADOW_ONLY
def registration_payload(self) -> dict[str, object]:
return {
"worker_id": self.worker_id, "worker_type": "codex-review",
"identity": self.identity, "owner_identity": self.identity,
"capabilities": list(READONLY_CAPABILITIES), "trust_zone": self.trust_zone,
"max_concurrency": self.max_concurrency,
"heartbeat_interval_seconds": self.heartbeat_interval_seconds,
"supported_protocols": ["aios-task-v1"], "registration_policy": "self",
}
def assert_shadow_only_task(self, task: dict[str, Any]) -> None:
plan = task.get("plan", task)
metadata = plan.get("metadata", {}) if isinstance(plan, dict) else {}
required = set(plan.get("required_capabilities", [])) if isinstance(plan, dict) else set()
if self.max_concurrency != 1 or self.heartbeat_interval_seconds != 15 or self.claim_lease_seconds != 120:
raise CodexReviewTaskError("worker timing/concurrency contract rejected")
if not isinstance(plan, dict) or metadata.get("production_side_effects") is not False:
raise CodexReviewTaskError("task must declare production_side_effects=false")
if plan.get("risk") != "low" or plan.get("task_type") not in {"code.review", "test.execute", None}:
raise CodexReviewTaskError("task risk or type rejected")
if plan.get("data_classification", "internal") not in {"public", "internal"}:
raise CodexReviewTaskError("task classification rejected")
if not required.issubset(set(READONLY_CAPABILITIES)):
raise CodexReviewTaskError("task capability rejected")
if any(value.startswith(("code.write", "deploy", "secret", "production")) for value in required):
raise CodexReviewTaskError("side-effect capability rejected")
def default_result_envelope(self, *, task_id: str, claim_id: str, worker_identity: str) -> TaskResultEnvelope:
return task_result_envelope(
task_id=task_id, claim_id=claim_id, worker_id=self.worker_id,
worker_identity=worker_identity, status="CREATED", outputs=[], evidence=[],
started_at="1970-01-01T00:00:00Z", completed_at="1970-01-01T00:00:00Z",
)
class _LeaseGuard:
def __init__(self, client: TaskPlaneClient, task_id: str, claim_id: str) -> None:
self.client, self.task_id, self.claim_id = client, task_id, claim_id
self.stop_event = threading.Event()
self.lost = threading.Event()
self.thread = threading.Thread(target=self._run, daemon=True)
def _run(self) -> None:
while not self.stop_event.wait(HEARTBEAT_INTERVAL_SECONDS):
try:
self.client.claim_heartbeat(self.task_id, claim_id=self.claim_id, lease_seconds=CLAIM_LEASE_SECONDS)
except Exception:
self.lost.set()
self.stop_event.set()
def __enter__(self) -> "_LeaseGuard":
self.thread.start()
return self
def __exit__(self, *_: object) -> None:
self.stop_event.set()
self.thread.join(timeout=2)
def require_active(self) -> None:
if self.lost.is_set():
raise CodexReviewTaskError("claim lease lost")
class CodexReviewWorker:
def __init__(self, client: TaskPlaneClient, policy: CodexReviewTaskPolicy, source_commit: str) -> None:
self.client, self.policy, self.source_commit = client, policy, source_commit
def register(self) -> dict[str, Any]:
return self.client.register_worker(**{
"worker_id": self.policy.worker_id, "worker_type": "codex-review",
"identity": self.policy.identity, "capabilities": READONLY_CAPABILITIES,
"trust_zone": self.policy.trust_zone, "max_concurrency": 1,
"heartbeat_interval_seconds": 15,
})
def poll_safe_task(self) -> dict[str, Any] | None:
for task in self.client.list_tasks():
if task.get("status") not in {"CREATED", "QUEUED", "FAILED_RECOVERABLE"}:
continue
try:
full = self.client.get_task(str(task["task_id"]))
self.policy.assert_shadow_only_task(full)
return full
except (KeyError, CodexReviewTaskError):
continue
return None
def run_once(self, executor: Callable[[dict[str, Any], Callable[[float, str], None]], tuple[str, list[dict[str, Any]], list[dict[str, Any]]]]) -> str | None:
self.register()
task = self.poll_safe_task()
if task is None:
return None
task_id = str(task["task_id"])
claim = self.client.claim(task_id, worker_id=self.policy.worker_id, lease_seconds=120)
claim_id = str(claim["claim_id"])
started = datetime.now(timezone.utc).isoformat()
with _LeaseGuard(self.client, task_id, claim_id) as guard:
def emit(value: float, stage: str) -> None:
guard.require_active()
self.client.progress(task_id, claim_id=claim_id, progress=value, stage=stage)
summary, outputs, evidence = executor(task, emit)
guard.require_active()
completed = datetime.now(timezone.utc).isoformat()
envelope = task_result_envelope(
task_id=task_id, claim_id=claim_id,
task_revision=int(claim["task_revision"]),
worker_id=self.policy.worker_id, worker_identity=self.policy.identity,
operation_digest=str(claim["operation_digest"]),
source_commit=self.source_commit, status="COMPLETED", summary=summary,
outputs=outputs, evidence=evidence, started_at=started, completed_at=completed,
)
guard.require_active()
envelope_payload = envelope.to_dict()
self.client.result(
task_id,
claim_id=claim_id,
status=str(envelope_payload["status"]),
outputs=list(envelope_payload["outputs"]),
evidence=list(envelope_payload["evidence"]),
started_at=str(envelope_payload["started_at"]),
completed_at=str(envelope_payload["completed_at"]),
trust_level=TrustPolicy.SHADOW_ATTESTED.value,
production_trust=False,
)
return task_id
def build_default_task_policy(worker_id: str, worker_identity: str) -> CodexReviewTaskPolicy:
return CodexReviewTaskPolicy(worker_id=worker_id, identity=worker_identity)
def make_shadow_result_payload(*, task_id: str, claim_id: str, worker_identity: str) -> TaskResultEnvelope:
return task_result_envelope(
task_id=task_id, claim_id=claim_id, worker_identity=worker_identity,
status="COMPLETED", outputs=[], evidence=[],
started_at="1970-01-01T00:00:00Z", completed_at="1970-01-01T00:00:00Z",
)
def _assert_disabled_production() -> None:
for name in ("AIOS_GITOPS_WRITES_ENABLED", "AIOS_SILENT_RELEASE_EXECUTION_ENABLED", "AIOS_TASK_PLANE_EXECUTION_ENABLED"):
if os.environ.get(name, "false").lower() != "false":
raise CodexReviewTaskError(f"{name} must remain false")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--self-check", action="store_true")
parser.add_argument("--once", action="store_true")
args = parser.parse_args(argv)
_assert_disabled_production()
config = StageAClientConfig(os.environ.get("AIOS_TASK_PLANE_ENDPOINT", "http://127.0.0.1:18923"))
if args.self_check:
print(json.dumps({"status": "PASS", "shadow_only": True, "production_trust": False}, sort_keys=True))
return 0
if os.environ.get("AIOS_CODEX_WORKER_SHADOW_CANARY_ENABLED", "false").lower() != "true":
raise SystemExit("Codex worker execution is disabled")
credential = CredentialSource(Path(os.environ["AIOS_TASK_PLANE_WORKER_TOKEN_FILE"])).read_token()
source_commit = os.environ.get("AIOS_CODEX_WORKER_SOURCE_COMMIT", "")
policy = CodexReviewTaskPolicy(
worker_id=os.environ["AIOS_CODEX_WORKER_ID"],
identity=os.environ["AIOS_CODEX_WORKER_IDENTITY"],
)
worker = CodexReviewWorker(TaskPlaneClient(config, credential), policy, source_commit)
if args.once:
worker.run_once(lambda _task, emit: (emit(100, "VERIFIED") or ("shadow self-check", [], [])))
return 0
raise SystemExit("continuous real worker execution is not enabled")
if __name__ == "__main__":
raise SystemExit(main())
@@ -1,62 +0,0 @@
"""Fail-closed command and environment policy for the isolated Codex Worker."""
from __future__ import annotations
import os
import re
import subprocess
from pathlib import Path
OID_RE = re.compile(r"[0-9a-f]{40}")
DENIED_ENV = ("TOKEN", "PASSWORD", "SECRET", "CREDENTIAL", "AUTHORIZATION", "COOKIE", "PRIVATE_KEY", "AWS_", "GITHUB_", "GITEA_")
class CommandPolicyError(ValueError):
pass
def isolated_environment(home: Path, temp_root: Path, pythonpath: str) -> dict[str, str]:
home.mkdir(mode=0o700, parents=True, exist_ok=True)
temp_root.mkdir(mode=0o700, parents=True, exist_ok=True)
allowed = {key: value for key, value in os.environ.items() if key in {"PATH", "LANG", "LC_ALL"}}
allowed.update({"HOME": str(home), "TMPDIR": str(temp_root), "PYTHONPATH": pythonpath, "PYTHONDONTWRITEBYTECODE": "1"})
if any(any(marker in key.upper() for marker in DENIED_ENV) for key in allowed):
raise CommandPolicyError("secret environment retained")
return allowed
class CommandPolicy:
def __init__(self, repo: Path, result_root: Path, *, timeout_seconds: int = 300, output_limit: int = 1_000_000):
self.repo = repo.resolve()
self.result_root = result_root.resolve()
self.timeout_seconds = timeout_seconds
self.output_limit = output_limit
def _oid(self, value: str) -> str:
if not OID_RE.fullmatch(value):
raise CommandPolicyError("exact commit oid required")
return value
def build(self, kind: str, *, oid: str, paths: list[str] | None = None, output: Path | None = None) -> list[str]:
oid = self._oid(oid)
paths = paths or []
if any(not path or path.startswith("-") or Path(path).is_absolute() or ".." in Path(path).parts for path in paths):
raise CommandPolicyError("invalid allowlisted path")
if kind == "diff-check":
return ["git", "-C", str(self.repo), "diff", "--check"]
if kind == "git-show" and len(paths) == 1:
return ["git", "-C", str(self.repo), "show", f"{oid}:{paths[0]}"]
if kind == "pytest" and paths and all(path.startswith("tests/task_plane/") or path == "tests/test_isolated_writer_policy.py" for path in paths):
return ["python3", "-m", "pytest", "-q", *paths]
if kind == "compileall" and paths and all(path.startswith(("active-runtime/app/task_plane", "runtime/agent-os")) for path in paths):
return ["python3", "-m", "compileall", "-q", *paths]
if kind == "acceptance" and output is not None:
target = output.resolve()
if target.parent != self.result_root:
raise CommandPolicyError("output escapes result root")
return ["bash", "scripts/task-plane/run_task_plane_acceptance.sh", str(target)]
raise CommandPolicyError("command template not allowlisted")
def run(self, argv: list[str], env: dict[str, str]) -> tuple[int, str]:
completed = subprocess.run(argv, cwd=self.repo, env=env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=self.timeout_seconds, start_new_session=True, check=False)
output = completed.stdout[: self.output_limit]
return completed.returncode, output
@@ -1,56 +0,0 @@
"""Bounded progress payload helpers."""
from __future__ import annotations
import math
from dataclasses import dataclass
from typing import Any
@dataclass(frozen=True)
class ProgressEnvelope:
claim_id: str
progress: int | float
stage: str
lease_seconds: int = 120
message: str | None = None
def validate(self) -> None:
if not self.claim_id:
raise ValueError("claim_id is required")
numeric = float(self.progress)
if not math.isfinite(numeric) or not 0 <= numeric <= 100:
raise ValueError("progress must be finite and within [0, 100]")
if not 1 <= self.lease_seconds <= 3600:
raise ValueError("lease_seconds out of range")
if not self.stage or len(self.stage) > 64 or any(ord(ch) < 32 for ch in self.stage):
raise ValueError("stage is invalid")
if self.message is not None and len(self.message) > 512:
raise ValueError("message is too long")
def as_request(self) -> dict[str, Any]:
self.validate()
return {
"claim_id": self.claim_id, "progress": float(self.progress),
"stage": self.stage, "lease_seconds": self.lease_seconds,
"message": self.message,
}
def clamp_progress(value: float) -> float:
numeric = float(value)
if not math.isfinite(numeric):
raise ValueError("progress must be finite")
return max(0.0, min(100.0, numeric))
def safe_stage_name(stage: str | None) -> str:
value = str(stage or "").strip()
if not value:
return "RUNNING"
if any(ord(ch) < 32 for ch in value):
raise ValueError("stage is invalid")
return value[:64]
def build_progress_payload(*, claim_id: str, progress: float, stage: str = "RUNNING", lease_seconds: int = 120, message: str | None = None) -> dict[str, Any]:
return ProgressEnvelope(claim_id, clamp_progress(progress), safe_stage_name(stage), lease_seconds, message).as_request()
@@ -1,157 +0,0 @@
"""Canonical, Shadow-only result envelopes for the Codex review worker."""
from __future__ import annotations
import hashlib
import hmac
import json
import re
from dataclasses import dataclass
from enum import StrEnum
from typing import Any
OID_RE = re.compile(r"^[0-9a-f]{40}$")
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
class TrustPolicy(StrEnum):
SHADOW_ATTESTED = "SHADOW_ATTESTED"
SHADOW_UNATTESTED = "SHADOW_UNATTESTED"
def _canonical_sha256(payload: object) -> str:
encoded = json.dumps(
payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")
).encode("utf-8")
return hashlib.sha256(encoded).hexdigest()
@dataclass(frozen=True)
class TaskResultEnvelope:
task_id: str
claim_id: str
worker_identity: str
status: str
outputs: list[dict[str, Any]]
evidence: list[dict[str, Any]]
started_at: str
completed_at: str
task_revision: int = 1
worker_id: str = ""
operation_digest: str = ""
source_commit: str = "0" * 40
summary: str = ""
evidence_digests: tuple[str, ...] = ()
result_digest: str | None = None
trust_level: TrustPolicy = TrustPolicy.SHADOW_ATTESTED
production_trust: bool = False
signature: str | None = None
attestation_ref: str | None = None
def digest_payload(self) -> dict[str, Any]:
return {
"task_id": self.task_id,
"claim_id": self.claim_id,
"task_revision": self.task_revision,
"worker_id": self.worker_id,
"worker_identity": self.worker_identity,
"operation_digest": self.operation_digest,
"source_commit": self.source_commit,
"status": self.status,
"summary": self.summary,
"outputs": self.outputs,
"evidence": self.evidence,
"evidence_digests": list(self.evidence_digests),
"started_at": self.started_at,
"completed_at": self.completed_at,
"trust_level": TrustPolicy.SHADOW_ATTESTED.value,
"production_trust": False,
"attestation_ref": self.attestation_ref,
}
def computed_digest(self) -> str:
return _canonical_sha256(self.digest_payload())
def validate(self) -> None:
required = {
"task_id": self.task_id,
"claim_id": self.claim_id,
"worker_id": self.worker_id,
"worker_identity": self.worker_identity,
"operation_digest": self.operation_digest,
"status": self.status,
"started_at": self.started_at,
"completed_at": self.completed_at,
}
if any(not str(value).strip() for value in required.values()):
raise ValueError("result envelope required field missing")
if self.task_revision < 1:
raise ValueError("task_revision must be positive")
if not OID_RE.fullmatch(self.source_commit):
raise ValueError("source_commit must be a full commit OID")
if not SHA256_RE.fullmatch(self.operation_digest):
raise ValueError("operation_digest must be SHA-256")
if any(not SHA256_RE.fullmatch(value) for value in self.evidence_digests):
raise ValueError("evidence digest must be SHA-256")
observed = tuple(_canonical_sha256(item) for item in self.evidence)
if observed != self.evidence_digests:
raise ValueError("evidence digest binding mismatch")
if self.trust_level is not TrustPolicy.SHADOW_ATTESTED:
raise ValueError("Codex review results must remain SHADOW_ATTESTED")
if self.production_trust is not False:
raise ValueError("production_trust is forbidden")
if self.result_digest is not None and not hmac.compare_digest(
self.result_digest, self.computed_digest()
):
raise ValueError("result digest mismatch")
def finalized(self) -> "TaskResultEnvelope":
from dataclasses import replace
envelope = replace(self, result_digest=self.computed_digest())
envelope.validate()
return envelope
def to_dict(self) -> dict[str, Any]:
envelope = self if self.result_digest is not None else self.finalized()
envelope.validate()
return {**envelope.digest_payload(), "result_digest": envelope.result_digest}
def task_result_envelope(
*,
task_id: str,
claim_id: str,
worker_identity: str,
status: str,
outputs: list[dict[str, Any]],
evidence: list[dict[str, Any]],
started_at: str,
completed_at: str,
task_revision: int = 1,
worker_id: str | None = None,
operation_digest: str | None = None,
source_commit: str = "0" * 40,
summary: str = "",
trust_level: TrustPolicy = TrustPolicy.SHADOW_ATTESTED,
production_trust: bool = False,
) -> TaskResultEnvelope:
evidence_digests = tuple(_canonical_sha256(item) for item in evidence)
envelope = TaskResultEnvelope(
task_id=task_id,
claim_id=claim_id,
task_revision=task_revision,
worker_id=worker_id or worker_identity,
worker_identity=worker_identity,
operation_digest=operation_digest or ("0" * 64),
source_commit=source_commit,
status=status,
summary=summary,
outputs=outputs,
evidence=evidence,
evidence_digests=evidence_digests,
started_at=started_at,
completed_at=completed_at,
trust_level=trust_level,
production_trust=production_trust,
)
return envelope.finalized()
@@ -1,138 +0,0 @@
"""Fixed-command, no-shell runner for a read-only Codex workspace."""
from __future__ import annotations
import os
import re
import signal
import subprocess
from dataclasses import dataclass
from pathlib import Path, PurePosixPath
from .command_policy import CommandPolicyError
from .workspace import WorkspacePermissionError, assert_private_path
OID_RE = re.compile(r"^[0-9a-f]{40}$")
FORBIDDEN_SNIPPETS = ("http://", "https://", ";", "&&", "||", "|", "`", "${", "$(")
class CommandRunnerError(ValueError):
pass
class CommandDisallowedError(CommandRunnerError):
pass
class CommandPolicyViolation(CommandRunnerError):
pass
@dataclass(frozen=True)
class CommandResult:
returncode: int
output: str
class SafeCommandRunner:
allowed_kinds = ("git-diff", "diff-check", "git-show", "pytest", "compileall", "acceptance")
def __init__(self, repo: Path, result_root: Path, *, policy=None, timeout_seconds: int = 300, output_limit: int = 1_000_000) -> None:
self.repo = assert_private_path(repo)
self.result_root = assert_private_path(result_root)
self.timeout_seconds, self.output_limit = timeout_seconds, output_limit
@staticmethod
def _oid(value: str) -> str:
if not OID_RE.fullmatch(str(value)):
raise CommandPolicyError("exact commit oid required")
return value
@staticmethod
def _forbidden(value: str) -> bool:
lowered = value.lower()
return (
re.search(r"\b(?:bash|eval)\b", lowered) is not None
or re.search(r"(^|\s)-c(\s|$)", lowered) is not None
or any(marker in value for marker in FORBIDDEN_SNIPPETS)
)
def _path(self, value: str, *, allowed_prefixes: tuple[str, ...]) -> str:
if not value or value.startswith("-") or "\\" in value or self._forbidden(value):
raise CommandDisallowedError("unsafe path input")
pure = PurePosixPath(value)
if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
raise CommandPolicyError("path traversal is forbidden")
if not any(value == prefix or value.startswith(prefix + "/") for prefix in allowed_prefixes):
raise CommandPolicyError("path outside allowlist")
try:
candidate = assert_private_path(self.repo / value)
except WorkspacePermissionError as exc:
raise CommandPolicyError("symlink path is forbidden") from exc
try:
candidate.relative_to(self.repo)
except ValueError:
raise CommandPolicyError("path escapes repository") from None
return value
def _output(self, output: Path) -> Path:
if Path(output).is_absolute() or Path(output).name != str(output):
raise CommandPolicyError("output must be a direct result file")
target = assert_private_path(self.result_root / output)
try:
target.relative_to(self.result_root)
except ValueError:
raise CommandPolicyError("output escapes result root") from None
return target
def build(self, kind: str, *, oid: str, other_oid: str | None = None, paths: list[str] | None = None, output: Path | None = None) -> list[str]:
if kind not in self.allowed_kinds:
raise CommandDisallowedError("command kind not allowed")
first = self._oid(oid)
values = paths or []
if kind == "git-diff":
second = self._oid(str(other_oid or ""))
return ["git", "-C", str(self.repo), "diff", "--no-ext-diff", "--no-textconv", first, second]
if kind == "diff-check":
return ["git", "-C", str(self.repo), "diff", "--check"]
if kind == "git-show" and len(values) == 1:
path = self._path(values[0], allowed_prefixes=("active-runtime", "runtime", "scripts", "tests", "docs"))
return ["git", "-C", str(self.repo), "show", f"{first}:{path}"]
if kind == "pytest" and values:
safe = [self._path(value, allowed_prefixes=("tests/task_plane", "tests/test_isolated_writer_policy.py")) for value in values]
return ["python3", "-m", "pytest", "-q", *safe]
if kind == "compileall" and values:
safe = [self._path(value, allowed_prefixes=("active-runtime/app/task_plane", "runtime/agent-os")) for value in values]
return ["python3", "-m", "compileall", "-q", *safe]
if kind == "acceptance" and output is not None and not values:
return ["bash", "scripts/task-plane/run_task_plane_acceptance.sh", str(self._output(output))]
raise CommandPolicyError("command template not allowlisted")
def run(self, kind: str, *, oid: str, other_oid: str | None = None, paths: list[str] | None = None, output: Path | None = None, env: dict[str, str] | None = None) -> CommandResult:
if env and any(marker in key.upper() for key in env for marker in ("TOKEN", "SECRET", "PASSWORD", "CREDENTIAL", "AUTHORIZATION", "COOKIE", "PRIVATE_KEY")):
raise CommandPolicyViolation("secret environment rejected")
command = self.build(kind, oid=oid, other_oid=other_oid, paths=paths, output=output)
safe_env = {
"HOME": str(self.result_root),
"PATH": os.environ.get("PATH", ""),
"LANG": "C.UTF-8",
"PYTHONDONTWRITEBYTECODE": "1",
"GIT_CONFIG_NOSYSTEM": "1",
"GIT_TERMINAL_PROMPT": "0",
}
process = subprocess.Popen(
command, cwd=self.repo, env=safe_env, stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
start_new_session=True,
)
try:
text, _ = process.communicate(timeout=self.timeout_seconds)
except subprocess.TimeoutExpired:
os.killpg(process.pid, signal.SIGKILL)
text, _ = process.communicate()
raise CommandRunnerError("command timeout")
return CommandResult(process.returncode, text[: self.output_limit])
Runner = SafeCommandRunner
FixedCommandRunner = SafeCommandRunner
CommandResultEnvelope = CommandResult
@@ -1,300 +0,0 @@
"""Fail-closed loopback HTTP client for the Codex review worker."""
from __future__ import annotations
import hashlib
import json
import os
import re
import stat
import time
import urllib.error
import urllib.parse
import urllib.request
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Iterable
MAX_HTTP_BODY_BYTES = 1_000_000
_RETRYABLE_STATUS = {429, 503}
_RETRY_BACKOFF_SECONDS = (0.25, 0.5, 1.0, 2.0)
_IDENTIFIER_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$")
class TaskClientError(RuntimeError):
pass
class TaskClientProtocolError(TaskClientError):
pass
class TaskClientAuthError(TaskClientError):
pass
class TaskClientResponseTooLargeError(TaskClientError):
pass
def _safe_identifier(value: str, name: str) -> str:
candidate = str(value or "")
if not _IDENTIFIER_RE.fullmatch(candidate):
raise TaskClientProtocolError(f"invalid {name}")
return urllib.parse.quote(candidate, safe="")
def _stable_key(operation: str, payload: object) -> str:
encoded = json.dumps(
payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")
).encode("utf-8")
return f"codex-worker:{operation}:{hashlib.sha256(encoded).hexdigest()}"
@dataclass(frozen=True)
class CredentialSource:
token_path: Path
token_owner: str = "aiman"
token_group: str = "gitops"
expected_mode: int = 0o600
def read_token(self) -> str:
import grp
import pwd
path = Path(self.token_path)
flags = os.O_RDONLY
if hasattr(os, "O_NOFOLLOW"):
flags |= os.O_NOFOLLOW
try:
fd = os.open(path, flags)
except OSError as exc:
raise TaskClientAuthError("credential file unavailable") from exc
try:
info = os.fstat(fd)
if not stat.S_ISREG(info.st_mode):
raise TaskClientAuthError("credential file must be regular")
if stat.S_IMODE(info.st_mode) != self.expected_mode:
raise TaskClientAuthError("credential file mode rejected")
try:
owner = pwd.getpwuid(info.st_uid).pw_name
group = grp.getgrgid(info.st_gid).gr_name
except KeyError as exc:
raise TaskClientAuthError("credential ownership unresolved") from exc
if owner != self.token_owner or group != self.token_group:
raise TaskClientAuthError("credential ownership rejected")
value = os.read(fd, 4097)
if len(value) > 4096:
raise TaskClientAuthError("credential file too large")
token = value.decode("utf-8", errors="strict").strip()
if len(token.encode("utf-8")) < 32:
raise TaskClientAuthError("credential unavailable")
return token
finally:
os.close(fd)
@dataclass(frozen=True)
class StageAClientConfig:
base_url: str = "http://127.0.0.1:18923"
timeout_seconds: float = 12.0
max_request_bytes: int = MAX_HTTP_BODY_BYTES
max_response_bytes: int = MAX_HTTP_BODY_BYTES
max_retry_attempts: int = 4
default_lease_seconds: int = 120
default_worker_heartbeat_interval_seconds: int = 15
default_max_concurrency: int = 1
def __post_init__(self) -> None:
parsed = urllib.parse.urlsplit(self.base_url)
if (
parsed.scheme != "http"
or parsed.hostname not in {"127.0.0.1", "::1"}
or parsed.username is not None
or parsed.password is not None
or parsed.query
or parsed.fragment
or parsed.path not in {"", "/"}
or parsed.port is None
):
raise ValueError("Task Plane endpoint must be explicit loopback HTTP")
class TaskPlaneClient:
def __init__(self, config: StageAClientConfig, token: str) -> None:
if len(str(token).encode("utf-8")) < 16:
raise TaskClientAuthError("credential is required")
self.config = config
self.__token = str(token)
def __repr__(self) -> str:
return f"TaskPlaneClient(base_url={self.config.base_url!r}, credential=<redacted>)"
def _encode(self, payload: dict[str, Any] | None) -> bytes | None:
if payload is None:
return None
body = json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
if len(body) > self.config.max_request_bytes:
raise TaskClientResponseTooLargeError("request payload exceeds configured limit")
return body
def _read_response(self, handle: Any) -> tuple[int, Any]:
status_code = int(getattr(handle, "status", 200))
raw = handle.read(self.config.max_response_bytes + 1)
if len(raw) > self.config.max_response_bytes:
raise TaskClientResponseTooLargeError("response payload exceeds configured limit")
if not raw:
return status_code, {}
try:
return status_code, json.loads(raw.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise TaskClientProtocolError("response is not valid JSON") from exc
def _request(
self,
method: str,
path: str,
payload: dict[str, Any] | None = None,
*,
idempotency_key: str | None = None,
) -> tuple[int, Any]:
if not path.startswith("/") or "//" in path or "?" in path or "#" in path:
raise TaskClientProtocolError("invalid API path")
body = self._encode(payload)
attempts = max(1, min(self.config.max_retry_attempts, 4))
for index in range(attempts):
headers = {"Authorization": f"Bearer {self.__token}", "Accept": "application/json"}
if body is not None:
headers["Content-Type"] = "application/json"
if idempotency_key:
headers["Idempotency-Key"] = idempotency_key
request = urllib.request.Request(
f"{self.config.base_url.rstrip('/')}{path}",
method=method,
data=body,
headers=headers,
)
try:
with urllib.request.urlopen(request, timeout=self.config.timeout_seconds) as response:
return self._read_response(response)
except urllib.error.HTTPError as exc:
status_code, response = self._read_response(exc)
if status_code in {401, 403}:
raise TaskClientAuthError(f"request rejected: HTTP {status_code}")
if status_code in _RETRYABLE_STATUS and index + 1 < attempts:
time.sleep(_RETRY_BACKOFF_SECONDS[index])
continue
code = response.get("error") if isinstance(response, dict) else "request_failed"
raise TaskClientProtocolError(f"request failed: HTTP {status_code} ({code})")
except urllib.error.URLError as exc:
if index + 1 < attempts:
time.sleep(_RETRY_BACKOFF_SECONDS[index])
continue
raise TaskClientProtocolError("request transport error") from exc
raise TaskClientProtocolError("request failed")
def _post(self, path: str, payload: dict[str, Any], *, idempotency_key: str | None = None) -> dict[str, Any]:
status_code, response = self._request(
"POST", path, payload, idempotency_key=idempotency_key or _stable_key(path, payload)
)
if status_code not in {200, 201} or not isinstance(response, dict):
raise TaskClientProtocolError("unexpected API response")
return response
def _get(self, path: str) -> Any:
status_code, response = self._request("GET", path)
if status_code != 200:
raise TaskClientProtocolError("unexpected API response")
return response
def list_tasks(self) -> list[dict[str, Any]]:
response = self._get("/tasks")
if not isinstance(response, list) or any(not isinstance(item, dict) for item in response):
raise TaskClientProtocolError("invalid task list")
return response
def get_task(self, task_id: str) -> dict[str, Any]:
response = self._get(f"/tasks/{_safe_identifier(task_id, 'task_id')}")
if not isinstance(response, dict):
raise TaskClientProtocolError("invalid task response")
return response
def register_worker(
self, *, worker_id: str, worker_type: str, identity: str,
capabilities: Iterable[str], trust_zone: str, max_concurrency: int,
heartbeat_interval_seconds: int, supported_protocols: Iterable[str] = ("aios-task-v1",),
) -> dict[str, Any]:
payload = {
"worker_id": worker_id, "worker_type": worker_type, "identity": identity,
"capabilities": sorted(set(capabilities)), "trust_zone": trust_zone,
"max_concurrency": max_concurrency,
"heartbeat_interval_seconds": heartbeat_interval_seconds,
"supported_protocols": list(supported_protocols),
"owner_identity": identity, "registration_policy": "self",
}
return self._post("/workers/register", payload, idempotency_key=_stable_key("register", payload))
def worker_heartbeat(self, worker_id: str, *, heartbeat_interval_seconds: int | None = None) -> dict[str, Any]:
payload = {} if heartbeat_interval_seconds is None else {"heartbeat_interval_seconds": heartbeat_interval_seconds}
return self._post(f"/workers/{_safe_identifier(worker_id, 'worker_id')}/heartbeat", payload)
def claim(self, task_id: str, *, worker_id: str, lease_seconds: int | None = None) -> dict[str, Any]:
payload = {"worker_id": worker_id, "lease_seconds": lease_seconds or self.config.default_lease_seconds}
return self._post(f"/tasks/{_safe_identifier(task_id, 'task_id')}/claim", payload)
def claim_heartbeat(self, task_id: str, *, claim_id: str, lease_seconds: int | None = None) -> dict[str, Any]:
if not claim_id:
raise TaskClientProtocolError("claim_id is required")
payload = {"claim_id": claim_id, "lease_seconds": lease_seconds or self.config.default_lease_seconds}
return self._post(f"/tasks/{_safe_identifier(task_id, 'task_id')}/heartbeat", payload)
def progress(self, task_id: str, *, claim_id: str, progress: int | float, stage: str, message: str | None = None, lease_seconds: int | None = None) -> dict[str, Any]:
if not claim_id:
raise TaskClientProtocolError("claim_id is required for progress")
payload = {"claim_id": claim_id, "progress": progress, "stage": stage, "message": message, "lease_seconds": lease_seconds or self.config.default_lease_seconds}
return self._post(f"/tasks/{_safe_identifier(task_id, 'task_id')}/progress", payload)
def result(self, task_id: str, *, claim_id: str, status: str, outputs: list[dict[str, Any]], evidence: list[dict[str, Any]], started_at: str, completed_at: str, result_digest: str | None = None, operation_digest: str | None = None, trust_level: str | None = None, production_trust: bool | None = None, **_: Any) -> dict[str, Any]:
if not claim_id:
raise TaskClientProtocolError("claim_id is required for result submission")
if production_trust not in {None, False}:
raise TaskClientProtocolError("production_trust is forbidden")
payload = {"claim_id": claim_id, "status": status, "outputs": outputs, "evidence": evidence, "started_at": started_at, "completed_at": completed_at}
if result_digest:
payload["result_digest"] = result_digest
if operation_digest:
payload["operation_digest"] = operation_digest
if trust_level:
payload["trust_level"] = trust_level
payload["production_trust"] = False
return self._post(f"/tasks/{_safe_identifier(task_id, 'task_id')}/result", payload)
def evidence(self, task_id: str, *, claim_id: str, evidence: list[dict[str, Any]], status: str = "VERIFYING", started_at: str, completed_at: str) -> dict[str, Any]:
return self.result(task_id, claim_id=claim_id, status=status, outputs=[], evidence=evidence, started_at=started_at, completed_at=completed_at)
def fail(self, task_id: str, *, claim_id: str, reason: str = "failed", recoverable: bool = False) -> dict[str, Any]:
if not claim_id:
raise TaskClientProtocolError("claim_id is required for fail")
return self._post(f"/tasks/{_safe_identifier(task_id, 'task_id')}/fail", {"claim_id": claim_id, "reason": reason, "recoverable": recoverable})
@dataclass(frozen=True)
class WorkerConfig:
worker_id: str
worker_type: str
identity: str
trust_zone: str
max_concurrency: int = 1
heartbeat_interval_seconds: int = 15
claim_lease_seconds: int = 120
supported_protocols: tuple[str, ...] = ("aios-task-v1",)
capabilities: tuple[str, ...] = ("code.read", "test.python", "review.security")
def to_registration_payload(self) -> dict[str, Any]:
return {
"worker_id": self.worker_id, "worker_type": self.worker_type,
"identity": self.identity, "capabilities": list(self.capabilities),
"trust_zone": self.trust_zone, "max_concurrency": self.max_concurrency,
"heartbeat_interval_seconds": self.heartbeat_interval_seconds,
"supported_protocols": list(self.supported_protocols),
"owner_identity": self.identity, "registration_policy": "self",
}
@@ -1,162 +0,0 @@
"""Private, symlink-safe per-claim workspaces."""
from __future__ import annotations
import os
import shutil
import stat
from dataclasses import dataclass
from pathlib import Path
from .command_policy import isolated_environment
WORKSPACE_DIR_MODE = 0o700
RESULT_FILE_MODE = 0o600
class WorkspaceError(RuntimeError):
pass
class WorkspacePermissionError(WorkspaceError):
pass
class WorkspaceCleanupError(WorkspaceError):
pass
def _lexical(path: Path) -> Path:
return Path(os.path.abspath(os.fspath(path)))
def assert_private_path(path: Path, *, expected_mode: int = WORKSPACE_DIR_MODE) -> Path:
"""Reject every existing symlink before resolving the final path."""
lexical = _lexical(Path(path))
current = Path(lexical.anchor)
for component in lexical.parts[1:]:
current = current / component
try:
info = current.lstat()
except FileNotFoundError:
continue
if stat.S_ISLNK(info.st_mode):
raise WorkspacePermissionError("symlink path is forbidden")
return lexical
def _ensure_directory(path: Path, *, mode: int = WORKSPACE_DIR_MODE) -> None:
lexical = assert_private_path(path)
lexical.mkdir(mode=mode, parents=True, exist_ok=True)
if lexical.is_symlink() or not lexical.is_dir():
raise WorkspacePermissionError("workspace directory rejected")
os.chmod(lexical, mode)
if stat.S_IMODE(lexical.stat().st_mode) != mode:
raise WorkspacePermissionError("workspace directory mode rejected")
def _ensure_result_name(name: str) -> str:
safe = str(name).strip()
if not safe or safe in {".", ".."} or "/" in safe or "\\" in safe or "\0" in safe:
raise WorkspaceError("invalid result file name")
return safe
def _within(path: Path, base: Path) -> Path:
lexical = assert_private_path(path)
root = assert_private_path(base)
try:
lexical.relative_to(root)
except ValueError:
raise WorkspacePermissionError("path escapes workspace") from None
return lexical
def _copy_readonly_tree(source: Path, destination: Path) -> None:
source = assert_private_path(source)
if not source.is_dir():
raise WorkspaceError("source archive tree unavailable")
for item in source.rglob("*"):
if item.is_symlink():
raise WorkspacePermissionError("source archive symlink rejected")
shutil.copytree(source, destination, dirs_exist_ok=True, symlinks=False)
for item in destination.rglob("*"):
if item.is_file():
os.chmod(item, 0o400)
elif item.is_dir():
os.chmod(item, 0o500)
@dataclass(frozen=True)
class WorkspaceLayout:
workspace_root: Path
repo_root: Path
result_root: Path
home: Path
tmp: Path
@dataclass
class TaskWorkspace:
layout: WorkspaceLayout
task_id: str
claim_id: str
def __init__(self, root: Path, task_id: str, claim_id: str, *, repo_subdir: str = "repo") -> None:
workspace_root = assert_private_path(root)
_ensure_directory(workspace_root)
self.layout = WorkspaceLayout(
workspace_root, workspace_root / repo_subdir, workspace_root / "results",
workspace_root / "home", workspace_root / "tmp",
)
for path in (self.layout.repo_root, self.layout.result_root, self.layout.home, self.layout.tmp):
_ensure_directory(path)
self.task_id, self.claim_id = task_id, claim_id
@classmethod
def create(cls, root: Path, task_id: str, claim_id: str, *, repo_subdir: str = "repo") -> "TaskWorkspace":
return cls(root, task_id, claim_id, repo_subdir=repo_subdir)
def __enter__(self) -> "TaskWorkspace":
return self
def __exit__(self, *_: object) -> None:
self.cleanup()
def materialize_readonly_archive(self, source: Path) -> None:
if any(self.layout.repo_root.iterdir()):
raise WorkspaceError("workspace repository is not empty")
_copy_readonly_tree(source, self.layout.repo_root)
def environ(self) -> dict[str, str]:
return isolated_environment(self.layout.home, self.layout.tmp, "active-runtime")
def result_path(self, name: str) -> Path:
return _within(self.layout.result_root / _ensure_result_name(name), self.layout.result_root)
def write_result(self, *, name: str, payload: str) -> Path:
path = self.result_path(name)
flags = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
if hasattr(os, "O_NOFOLLOW"):
flags |= os.O_NOFOLLOW
fd = os.open(path, flags, RESULT_FILE_MODE)
try:
if not stat.S_ISREG(os.fstat(fd).st_mode):
raise WorkspacePermissionError("result path is not regular")
os.write(fd, payload.encode("utf-8"))
os.fsync(fd)
os.fchmod(fd, RESULT_FILE_MODE)
finally:
os.close(fd)
return path
def cleanup(self) -> None:
root = assert_private_path(self.layout.workspace_root)
if not root.exists():
return
try:
shutil.rmtree(root)
except OSError as exc:
raise WorkspaceCleanupError("workspace cleanup failed") from exc
Workspace = TaskWorkspace
@@ -0,0 +1,83 @@
{
"approval_request_branch": "governance/request/integration-refresh-control-plane-deployment-20260728T093428Z",
"approval_type": "CONTROL_PLANE_DEPLOYMENT_APPROVAL_REQUEST",
"authorization_lineage": {
"execution_renewal_merge_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
"grant_id": "grant-11354281aafdd074df5899a3925dd2a0370cffa9edb06f5c7d7227ce8de00d91",
"source_mapping_approval_merge_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6"
},
"deployment_status": "NOT_EXECUTED",
"evidence": {
"control_plane_artifact": {
"path": "/var/lib/aios-integration-refresh-source-writer-v2/artifacts/control-plane-patch-112d995545e3e79126a062b2643a9f0c17ae7bd4.tar",
"sha256": "bf101ade1aaf956f40c0bba74ed4b347f5f38d0de6a0c1b7694ae107c4b43c14",
"size_bytes": 13363200
},
"rendered_systemd_config_sha256": "182a3cba48e752798cf24323a8c0249c53d7386371388a8db0435a29c43dc969",
"rollback_artifact": {
"path": "/var/lib/aios-gitops/runtime/tasks/AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726/implementation/rollback-to-85426f4f570e4d40b212318d47e52e4aed5cb06a.tar",
"sha256": "f12a2a95e475da5d02eaff99e93615cb0186019ca30edae013ab054a2c6418ce"
},
"source_map": {
"path": "docs/autonomous-release/INTEGRATION_REFRESH_SOURCE_MAP_20260728.json",
"sha256": "01ddd56cfa2a525559e2d174cf7df117a9465ffce44ef25bc7a15b8e74d06bf5"
},
"test_evidence": {
"collection_errors": 0,
"path": "/var/lib/aios-gitops/runtime/tasks/AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726/implementation/test-evidence.json",
"sha256": "d8933553f56462a3f1b3040dec989ff0adf717a17728d55ba0fe9e127d93c206",
"tests_failed": 0,
"tests_passed": 41
}
},
"execution_conditions": {
"candidate_only": true,
"integration_unchanged": true,
"main_unchanged": true,
"no_credentials_or_secrets_in_request": true,
"production_baseline_unchanged": true,
"registry_unchanged": true
},
"expected_governance_base_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
"expires_at": "2026-07-28T21:34:28Z",
"implementation": {
"commit_oid": "112d995545e3e79126a062b2643a9f0c17ae7bd4",
"tree_oid": "4ed88399fb8e7e4c235413ebbd783c9b6ad3c624"
},
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
"issued_at": "2026-07-28T09:34:28Z",
"prohibited_operations": [
"production-baseline.write",
"production-tag.write",
"main.write",
"integration.write",
"registry.write",
"force-push",
"direct-main-push",
"direct-tag-write"
],
"repository": "aios/aios",
"request_status": "PENDING_HUMAN_APPROVAL",
"requested_operations": [
"control-plane.candidate.deploy",
"control-plane.candidate.verify",
"control-plane.candidate.rollback"
],
"required_controls": [
"Two distinct human approvals, one Codex and one GPT, both APPROVED against the same current approval-request PR head.",
"Re-verify artifact, test evidence, source map, rendered systemd configuration, and rollback artifact paths and SHA-256 digests immediately before execution.",
"AIOS_GITOPS_WRITES_ENABLED=false throughout candidate deployment, verification, and rollback.",
"No force push, direct main write, or direct tag write."
],
"required_reviewers": [
"codex",
"gpt"
],
"schema": "aios.control-plane-deployment-approval-request/v1",
"target_governance": {
"approved_base_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
"binding_rule": "Human approvals must bind to the same approval-request PR head; its first parent must equal the active governance base."
},
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
"validity_hours": 12
}
@@ -0,0 +1,127 @@
{
"schema": "aios.governance-approval/v1",
"approval_type": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP_POLICY_ACTIVATION",
"approval_plan_id": "AIOS-TSG-BS-PHASE-A-RENEWAL-20260731T081147Z",
"task_id": "AIOS-V2R1C4-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-RENEWAL",
"repository": "aios/aios",
"issued_at": "2026-07-31T08:11:47Z",
"expires_at": "2026-07-31T20:11:47Z",
"expected_governance_base_oid": "ebd74398743e36523b593fcc395b73945d4924c5",
"expected_governance_base_tree_oid": "ad1255a1127204fad1d1208d8f31dc94fa64e6e1",
"approval_request_branch": "governance/request/two-stage-owner-campaign-v2-phase-a-renewal-20260731T081147Z",
"request_head_binding": "GITEA_EXACT_HEAD_REVIEW_POST_COMMIT",
"human_authorizer": "owner",
"authorization_mode": "GITEA_EXACT_HEAD_REVIEW",
"required_human_approvals": 1,
"allowed_human_approvers": [
"owner"
],
"require_latest_head_approval": true,
"dismiss_stale_approvals": true,
"auto_merge_after_machine_gates": true,
"phase_a_scope": {
"schema_id": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP",
"schema_version": 1,
"activate_schema_and_validator_only": true,
"phase_b_release_authorized": false,
"publisher_authorized": false,
"writer_authorized": false,
"credential_projection_authorized": false,
"tag_authorized": false,
"registry_authorized": false,
"baseline_authorized": false,
"production_deployment_authorized": false
},
"content_bindings": {
"schema_document": {
"path": "services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json",
"blob_oid": "9b117667c0d98f995ac059b0e1b5ffed06ca6444",
"sha256": "6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd"
},
"validator_policy": {
"path": "services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py",
"blob_oid": "c18d15f31340f19fc5da87944901bdfb867ab6dc",
"sha256": "de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac"
},
"evidence_manifest": {
"path": "evidence/governance-policy/AIOS-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-20260730T023551Z.json",
"blob_oid": "c3d215b3ea525a25de514c32c5aad91d47e140b4",
"sha256": "1b0a993940b41a4b16724b557f6abd8b6cebb56dc64cc8f813bd605b6a3399c2"
},
"checksums_manifest": {
"path": "evidence/governance-policy/AIOS-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-20260730T023551Z.sha256",
"blob_oid": "45ed084234dae6a00e69a41cd4f716f46a97d9fb",
"sha256": "51c4b029c0792dc98d41f754e484ba3861cf7604443d9c5f289b3b0af768a41a"
}
},
"offline_candidate_bindings": {
"schema_seed_commit_oid": "8da47545a507cb798d3d6ab30ff8552a2d0a5ecf",
"schema_seed_tree_oid": "991e68577a469657c1c4996814b6634ce5ed752f",
"implementation_commit_oid": "a637a9dbb6e0021cb7dcf0d6b0ca00dfe10dce38",
"implementation_tree_oid": "bf6e0c16fcad7515465bec4aefdd2e77b1e9bef0",
"evidence_closure_commit_oid": "1e4885197f508f7921b148d71e545b3de0029b0a",
"evidence_closure_tree_oid": "e55cf9ef19d1c6804f161de54fd3395a06149807",
"source_diff_sha256": "c06d002db06da6cbf16f9c8321f1acbfd431f009b5127a13fd2cb5d63b278867",
"source_pathset_sha256": "5061402d516c0e9413208ce64e2b52f77d224e6eec1f7b07c5b3a10b58df5eaf",
"implementation_bundle_sha256": "15711b225b9ef41cca0588d21b2b95d7a95ac155efc27fcb8772c435fcdab147",
"evidence_bundle_sha256": "ec97b8460151fc0e7e7ea9ae044ca13a1543c4b79c41a437ef087d3b1c271857"
},
"runtime_dependency_bindings": {
"handoff_zip_sha256": "668239a549b4a2b2094fe9b5104b84703fe8ed75011fd8ed71ed3958a6dc0706",
"installed_wheel_sha256": "abbf616366eb3467d4e651bb5306e22ae5e931b613df5362a0892935c4a1c0c7",
"anchor_service": "aios-campaign-anchor.service",
"anchor_uid": 988,
"runner_uid": 986,
"anchor_database": "/var/lib/aios-campaign-anchor/anchor.sqlite3",
"anchor_socket": "/run/aios-campaign-anchor/anchor.sock",
"AIOS_GITOPS_WRITES_ENABLED": false
},
"required_machine_status_contexts": [
"governance/schema-contract",
"governance/validator-security",
"governance/fault-injection",
"governance/runtime-isolation",
"governance/authority-mirror"
],
"allowed_operations_after_exact_head_owner_approval": [
"observe_governance_pr",
"wait_governance_gates",
"observe_governance_merge",
"observe_validator_activation",
"complete_policy_activation"
],
"denied_operations": [
"main.write",
"integration.write",
"tag.write",
"registry.write",
"baseline.write",
"production.deploy",
"force_push",
"history_rewrite",
"governance.direct_push",
"approval.impersonate",
"publisher.create",
"writer.create",
"credential.project",
"phase_b.execute"
],
"merge_constraints": {
"allowed_modes": [
"FAST_FORWARD_TO_APPROVED_HEAD",
"EXACT_TWO_PARENT_MERGE_WITH_APPROVED_TREE"
],
"force": false,
"plus_refspec": false,
"tags": false,
"prune": false
},
"governance_declarations": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"force_push_used": false,
"tag_rewritten": false,
"direct_main_push": false,
"secrets_committed": false,
"owner_approval_respected": true
}
}
@@ -0,0 +1,185 @@
{
"approval_type": "TASK_STATUS_MERGE_BROKER_BOOTSTRAP_RFC3339_FIX",
"schema_version": 2,
"repository": "aios/aios",
"expected_governance_base_oid": "8814dff20222625b60454c613b61ccf15fa20e51",
"request_branch": "patch/codex/AIOS-V2R1C4-BOOTSTRAP-RFC3339-OFFSET-FIX",
"target_ref": "refs/heads/governance/approvals",
"issued_at": "2026-08-01T02:50:00Z",
"expires_at": "2026-08-01T14:50:00Z",
"required_human_approvals": 1,
"allowed_human_approvers": ["owner"],
"require_latest_head_approval": true,
"approval_scopes": [
"BOOTSTRAP_FIX_APPROVAL",
"GITEA_INTERNAL_TOKEN_ROTATION_APPROVAL"
],
"supersedes": {
"pr_number": 37,
"head_oid": "57697d81cf3d1fef23798ec390418efe8b64f4e9",
"tree_oid": "b58af1925318a0eefa6cc709e8d52ba57bb20d7f",
"reason": "APPROVED_BOOTSTRAP_RUNTIME_CONTRACT_MISMATCH",
"old_review_reusable": false,
"old_pr_immutable": true
},
"exact_head_binding": {
"method": "GITEA_EXACT_HEAD_OWNER_REVIEW_AND_PR_METADATA",
"head_oid_resolved_after_commit": true,
"tree_oid_resolved_after_commit": true,
"manifest_blob_oid_resolved_after_commit": true,
"manifest_sha256_resolved_after_commit": true,
"head_change_invalidates_review": true
},
"timestamp_contract": {
"id": "RFC3339_OFFSET_AWARE_V2",
"canonical_timezone": "UTC",
"raw_timestamp_preserved": true,
"naive_datetime_allowed": false,
"accepted_timezone_forms": ["Z", "+HH:MM", "-HH:MM"],
"fractional_seconds_allowed": true,
"lowercase_z_allowed": false,
"expiry_boundary": "REVIEW_MUST_BE_STRICTLY_BEFORE_EXPIRY"
},
"internal_token_rotation": {
"secret_class": "GITEA_INTERNAL_TOKEN",
"old_secret_fingerprint_algorithm": "SHA256",
"old_secret_fingerprint": "42e2af774700405ae32d55c98ca010fdb5da890b08f9e12e77372133c68e0562",
"old_secret_reference": "gitea-config://security/INTERNAL_TOKEN",
"affected_consumers": [
"gitea-config-residue:/data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini.bak-20260706-auth-gitops",
"gitea-config:/data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini",
"systemd-service:aios-gitea.service"
],
"replacement_secret_reference": "systemd-credential-encrypted://gitea-internal-token-v2",
"rotation_method": "ATOMIC_REPLACE_THEN_REVOKE",
"rollback_plan_path": "evidence/governance/bootstrap-rfc3339-fix-20260801/ROLLBACK_PLAN.json",
"rollback_plan_sha256": "3283f4c3d6bb7f34ac893789f7e9f5df6c68b7807203e6f471ad92e8e007ff3f",
"audit_window_start": "2026-08-01T00:00:00Z",
"allowed_operations": [
"generate_replacement_internal_token_to_encrypted_runtime_credential",
"validate_replacement_internal_token_without_logging_plaintext",
"atomically_replace_exact_gitea_internal_token_config_value",
"restart_exact_aios_gitea_service",
"verify_exact_consumers_healthy",
"verify_old_internal_token_authentication_rejected",
"remove_or_redact_exact_old_secret_config_residue",
"audit_exposure_window",
"write_immutable_security_event_receipt"
],
"access_token_table_exception_applicable": false,
"plaintext_secret_in_manifest_allowed": false,
"plaintext_secret_in_argv_allowed": false,
"plaintext_secret_in_logs_allowed": false,
"plaintext_secret_in_git_allowed": false
},
"phase_b": {
"approval_mode": "TWO_STAGE_REQUIRED",
"reason": "CURRENT_SCHEMAS_DO_NOT_ATOMICALLY_BIND_BOOTSTRAP_ACTIVATION_AND_FULL_TASK_SCOPED_RELEASE_PAYLOAD",
"old_pr_number": 36,
"old_head_oid": "a8644fc172bd8ebbba17a16e6bf586c93fd1e793",
"old_approval_reusable": false,
"successor_required_after_bootstrap_activation": true,
"frozen_release_objects_unchanged": true
},
"frozen_release_objects": {
"source_commit_oid": "1857b88690cd1c0119df984534c260b6f217a21a",
"source_tree_oid": "17c153de2338f570f70cb7407e7dda3c596b524b",
"evidence_closure_oid": "057f5923f72cdb8d002ae40bc0cd584961825801",
"evidence_tree_oid": "30be66d153fe9d3758f5fdba89ca4169beab38f8",
"git_bundle_sha256": "762e280e240988282bc2c2e65fafecedd596400ab6829016947e84559508a015",
"tag_oid": "7f82d77cf7702a6d695b4f0b74da7a9a9ecd7fa3",
"peeled_target_oid": "057f5923f72cdb8d002ae40bc0cd584961825801",
"release_artifact_sha256": "39523caa48f39b33e5e5df785bb568e0381d8b20301746c280442f73f294f2b2",
"rollback_artifact_sha256": "dd0dbbe21db14722996636347ea1d22917436c688d5f0b7055b5bfb1776c4d95",
"release_root_sha256": "16e4e881287cef4a02525a6a5b337d3e12995e510832fe04fea2ac196885f3ef",
"evidence_manifest_sha256": "3b0b72af400997385e817e9bec677942288f422b69c2d2b52a8a00407fc395e0"
},
"allowed_status_contexts": [
"aios/branch-protection",
"aios/evidence-closure",
"aios/secret-scan",
"aios/state-machine",
"aios/validator"
],
"allowed_identities": ["codex", "gpt"],
"allowed_operations": [
"install_exact_approved_bootstrap_files",
"sign_task_grant_after_owner_exact_head_review",
"issue_task_status_credential",
"issue_task_merge_credential",
"publish_exact_five_statuses",
"fast_forward_only_merge",
"readback_status_and_ref",
"revoke_task_credentials",
"remove_credential_projection",
"sweep_completed_or_expired_task_credentials"
],
"operation_limits": {
"maximum_status_writes_per_grant": 5,
"maximum_merges_per_grant": 1,
"maximum_grant_lifetime_seconds": 43200,
"automatic_revocation_required": true
},
"denied_operations": [
"branch_push_outside_request_branch",
"main_push",
"tag_write",
"registry_write",
"baseline_write",
"production_write",
"branch_protection_change",
"force_push",
"squash",
"rebase",
"merge_commit",
"approval_impersonation",
"commit_status_database_write",
"database_write_outside_exact_task_access_token_revocation",
"reuse_pr36_or_pr37_review",
"plaintext_secret_persistence"
],
"runtime_controls": {
"global_gitops_writes_enabled": false,
"systemd_encrypted_credentials_required": true,
"systemd_projection_mode": "0440_ROOT_ROOT_CREDENTIALS_DIRECTORY_ONLY",
"systemd_gitea_token_embedded_name": "gitea-token",
"sqlite_parent_directory_metadata_write_required": true,
"sqlite_sibling_paths_read_only": true,
"sqlite_quota_journal_mode": "WAL",
"sqlite_quota_synchronous": "FULL",
"status_evidence_digest_bound_in_signed_grant": true,
"merge_method": "fast-forward-only",
"commit_status_database_write_allowed": false
},
"approved_files": {
"deploy/systemd/aios-task-credential-broker@.service": "95f8da02600b3c908013ffa723d79f6fca0c7a4332a077a7b673e97ce35bcd69",
"deploy/systemd/aios-task-credential-expiry-sweeper.service": "72a336523983b2486300c4e52f2f01dce392aaf6ffd953041c209d204df85717",
"deploy/systemd/aios-task-credential-expiry-sweeper.timer": "49ff9c80cbd0b44fd584dc7d29f4db0d042e33f325b1ed7af81a5be42f1cd011",
"deploy/systemd/aios-task-merge-broker@.service": "4e6b8fcf541f225e58ea080107fc30deb0c4ac9eac70217ff9e57081245c106a",
"deploy/systemd/aios-task-status-broker@.service": "378a2e8f658cb56cac5dcc151772ec6a00d86f6c1ce3106509b9aa87549dc9da",
"evidence/governance/bootstrap-rfc3339-fix-20260801/ROLLBACK_PLAN.json": "3283f4c3d6bb7f34ac893789f7e9f5df6c68b7807203e6f471ad92e8e007ff3f",
"evidence/governance/bootstrap-rfc3339-fix-20260801/TEST_SUMMARY.json": "c7d28139fddb9666e60fd62a9a27803dd00a1ebbccbbb75a5121cd8ed3d20fc2",
"services/aios-single-owner-governance/aios_single_owner_governance/task_credential_broker.py": "3b2fbbf2698a2d8385a2bf9eccdebbea629642908cbc7a1e8251476475e0d647",
"services/aios-single-owner-governance/aios_single_owner_governance/task_credential_expiry_sweeper.py": "8d383768eb0322c84a35282c126bee26a3e6419b125780424ffc7793a504efdf",
"services/aios-single-owner-governance/aios_single_owner_governance/task_status_merge_broker.py": "697d8deccdf2fec902dab38a0436075d78a95c1c5b410e115ee74cf79f477e63",
"services/aios-single-owner-governance/task-status-merge-grant-v1.schema.json": "34472624261203b5c1a215c141887ea3fed5d68fb3c503c7db2ad9a717862597",
"tests/single_owner_governance/test_task_status_merge_broker.py": "af1c5844ee0f7d6907f8cb68d5f503f3bdbd59bb05150e5364eaf7bf2b37be1a"
},
"aggregate_bindings": {
"broker_module_set_sha256": "c73ccaf8f60cf2446a5d4c0b4baf5456cb77961fda682285cb0a4f509ed49caa",
"systemd_definition_set_sha256": "3591be96f1717e7a0a57957aafbb233eec2b1617a8fb938889ccd312d812d066",
"grant_schema_sha256": "34472624261203b5c1a215c141887ea3fed5d68fb3c503c7db2ad9a717862597",
"test_summary_sha256": "c7d28139fddb9666e60fd62a9a27803dd00a1ebbccbbb75a5121cd8ed3d20fc2",
"python_executable_sha256": "e1efa562c2cc2e35521a5c9c9b9939921001ff8ca9708a13ef15ace68cc2ccd7"
},
"machine_gate_requirements": {
"compileall": "PASS",
"unit_tests": "PASS",
"rfc3339_offset_tests": "PASS",
"json_schema": "PASS",
"systemd_validation": "PASS",
"changed_path_secret_scan": "PASS",
"fault_injection": "PASS",
"scope_boundary_tests": "PASS"
}
}
@@ -0,0 +1,188 @@
{
"approval_type": "AIOS_EXACT_TWO_PARENT_MERGE_CLOSURE_BOOTSTRAP",
"schema_version": 1,
"repository": "aios/aios",
"expected_governance_base_oid": "9303a5d684e972bd15fe19f61f721075f4dda8b6",
"request_branch": "patch/codex/AIOS-V2R1C4-EXACT-TWO-PARENT-MERGE-CLOSURE",
"target_ref": "refs/heads/governance/approvals",
"issued_at": "2026-08-01T08:48:25Z",
"expires_at": "2026-08-01T20:48:25Z",
"required_human_approvals": 1,
"allowed_human_approvers": [
"owner"
],
"require_latest_head_approval": true,
"bootstrap_merge_method": "FAST_FORWARD_ONLY",
"exact_head_binding": {
"method": "GITEA_EXACT_HEAD_OWNER_REVIEW_AND_PR_METADATA",
"head_oid_resolved_after_commit": true,
"tree_oid_resolved_after_commit": true,
"manifest_blob_oid_resolved_after_commit": true,
"manifest_sha256_resolved_after_commit": true,
"head_change_invalidates_review": true
},
"supersedes": {
"pr_number": 39,
"approved_base_oid": "9303a5d684e972bd15fe19f61f721075f4dda8b6",
"approved_head_oid": "52a60a3c419a4a7f70a0af80913532c540ba0a4e",
"approved_tree_oid": "37d64c19f06f75589201a8b6277b13356303f04e",
"manifest_blob_oid": "f970cd1df80dbd4993cd0eb845608899e53b8315",
"manifest_sha256": "d878dc5eaae51f263b5803d36025b37d994602c91d3925430afc1d82acc490cb",
"approval_payload_sha256": "b36a25328cc8ab3810bfd967e87391fb128bc0a4ebf3389914084bceb067cd76",
"premerge_block_receipt_sha256": "5b9a94cf80f3e16e9f47f90d0c0622f0c001d2e582f4891c51d4c572c1f5fe8b",
"marker": "SUPERSEDED_BY_GOVERNANCE_MERGE_CLOSURE_V2",
"old_review_reusable": false,
"old_pr_immutable": true,
"old_pr_merge_allowed": false
},
"approval_payload_sha256": "13ba236a18e6cf4a7772ce1e90ca520fab34a791bd22f2c6e06f2ee90ffc0817",
"approval_payload": {
"policy_change_id": "AIOS_EXACT_TWO_PARENT_MERGE_COMMIT_V1",
"repository": "aios/aios",
"target_ref": "refs/heads/governance/approvals",
"merge_mode": "EXACT_TWO_PARENT_COMMIT",
"operation_quota": 1,
"force": false,
"parent_contract": {
"parent_count": 2,
"parent_0": "expected_old_ref_oid",
"parent_1": "approved_pr_head_oid",
"tree": "approved_pr_tree_oid",
"third_parent_allowed": false
},
"required_grant_bindings": [
"expected_old_ref_oid",
"approved_pr_head_oid",
"approved_pr_tree_oid",
"first_parent_oid",
"second_parent_oid",
"expected_merge_tree_oid",
"expected_merge_commit_oid",
"commit_message_utf8",
"commit_message_sha256",
"author_name",
"author_email",
"author_epoch",
"author_timezone",
"committer_name",
"committer_email",
"committer_epoch",
"committer_timezone"
],
"execution_contract": {
"deterministic_oid_recalculation_minimum": 2,
"object_only_import": true,
"authority_and_gitea_compare_and_swap": true,
"update_ref_old_oid_required": true,
"statuses_remain_on_approved_pr_head": true,
"owner_review_exact_head_required": true,
"authority_gitea_api_final_equality_required": true,
"git_fsck_connectivity_only_required": true,
"journal_mode": "WAL",
"journal_synchronous": "FULL",
"crash_reconciliation_required": true,
"same_request_replay_idempotent": true,
"same_idempotency_key_different_request_denied": true
},
"package_bindings": {
"package_revision": "V5R1",
"package_zip_sha256_source": "EXTERNAL_SIDECAR",
"package_zip_sha256": "e754e6fb9beeda33a17764e8dc515fbd3a2731a95af77e43af9aaacb38a262b6",
"package_manifest_sha256": "b5ccbbf7d23191eb09610f30e8062b4febd2344e4525d86b5aeba77d27df0671",
"package_manifest_entries": 150,
"wheel_sha256": "91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19",
"deployment_definitions_sha256": "b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0",
"manifest_schema_sha256": "31bce5c2960d8c57b26e0fa854196c17e6f018cd547b58679b7877cb602df4f4",
"runtime_layout_schema_sha256": "658813b8a0096ab5ee66dd217dc0bbb1b08e09dc33241049f24190bb4df86c9d",
"exact_two_parent_broker_sha256": "eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4",
"broker_schema_sha256": "72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba",
"validator_schema_sha256": "95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22",
"site_config_sha256": "be44861e717513e67b532fdb2f20b67a96aad07e212d521d4a69148ca346760c",
"zip_digest_self_reference": false
},
"frozen_release_objects": {
"source_commit_oid": "1857b88690cd1c0119df984534c260b6f217a21a",
"source_tree_oid": "17c153de2338f570f70cb7407e7dda3c596b524b",
"evidence_closure_oid": "057f5923f72cdb8d002ae40bc0cd584961825801",
"evidence_tree_oid": "30be66d153fe9d3758f5fdba89ca4169beab38f8",
"git_bundle_sha256": "762e280e240988282bc2c2e65fafecedd596400ab6829016947e84559508a015",
"tag_oid": "7f82d77cf7702a6d695b4f0b74da7a9a9ecd7fa3",
"peeled_target_oid": "057f5923f72cdb8d002ae40bc0cd584961825801",
"release_artifact_sha256": "39523caa48f39b33e5e5df785bb568e0381d8b20301746c280442f73f294f2b2",
"rollback_artifact_sha256": "dd0dbbe21db14722996636347ea1d22917436c688d5f0b7055b5bfb1776c4d95",
"release_root_sha256": "16e4e881287cef4a02525a6a5b337d3e12995e510832fe04fea2ac196885f3ef",
"evidence_manifest_sha256": "3b0b72af400997385e817e9bec677942288f422b69c2d2b52a8a00407fc395e0"
},
"approved_files": {
"deploy/systemd/aios-exact-two-parent-merge-broker@.service": "ca76dd130f0969fcbb5418c4276d4fbbe0671b340ffb2c615098a9989064a8fd",
"services/aios-single-owner-governance/aios_single_owner_governance/exact_two_parent_merge_broker.py": "eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4",
"services/aios-single-owner-governance/exact-two-parent-merge-grant-v1.schema.json": "72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba",
"services/aios-single-owner-governance/exact-two-parent-merge-closure-v1.schema.json": "95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22",
"tests/single_owner_governance/test_exact_two_parent_merge_broker.py": "e3a6ee0d4c0828eeb8113c47f38072746979f1d67da95941cdba6180ce42e800",
"tests/single_owner_governance/test_exact_two_parent_merge_closure_schema.py": "a8f479436ab57f1f536f3955fa6f0084c4178a5240f2387078b91ff50eeefd5a",
"tests/single_owner_governance/test_exact_two_parent_merge_systemd.py": "358ba693de51f1fd1de11412ef8d981de97ac2ab87510f16eb02884ff6d5fa83",
"tests/single_owner_governance/test_exact_two_parent_merge_posix.py": "6299cb774edff9f4f3bf5f7bb1d3bd67c7fb64710924d245052315f20e792fe6",
"tests/package_closure/test_v5r1_package_builder.py": "39780b956cadca41dd21f090313b6669534e8d49ef424e4d1baa877e92528566",
"tools/build_v5r1_package.py": "74f35d822809ea3d8b6f306f6bdc070fd89f4430c60a2e6a2ddf2cef2bb5ed8f",
"evidence/governance/exact-two-parent-merge-closure-20260801/TEST_SUMMARY.json": "908afcef10c80b05183711945ae9bda0f13e61e3a6e2a7c18c537b7fa6967b30",
"evidence/governance/exact-two-parent-merge-closure-20260801/ROLLBACK_PLAN.json": "19f81d43245c7980b69847ae43e10a7ed86c16c4d30a06556861ec389702d79e",
"evidence/governance/exact-two-parent-merge-closure-20260801/PR39_SUPERSESSION_RECORD.json": "672e7334a574a3ccdafcd2228f4307204ba896995ced82ba03e3d5ce81cf84e9",
"v5r1-control-plane/AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1/MANIFEST.sha256": "b5ccbbf7d23191eb09610f30e8062b4febd2344e4525d86b5aeba77d27df0671",
"v5r1-control-plane/AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1/PACKAGE_COMPONENTS.json": "3f558c661cfa1d362deb1aa688f233b5ba2a2f75432a2462cb206da6e8e0ce79",
"v5r1-control-plane/AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1/PACKAGE_AUDIT.json": "c45efc3d2de7aafa90a8d943c0f9886180cc01e548c00fb39c394a3252b71a20",
"v5r1-control-plane/AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1/OFFLINE_TEST_REPORT.json": "008a40f85b6f2eb1b033a9df2e20cbdd2141d6371e6a86db0e2743c0da515699",
"v5r1-control-plane/AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1/PACKAGE_CLOSURE_V5R1.md": "02de7d0a1f7602a196dcb458730ccc84082f6695a9960d4b1758c8a0abe8e2d9"
},
"machine_gate_requirements": {
"compileall": "PASS",
"unit_tests": "PASS",
"posix_tests": "PASS",
"linux_integration": "PASS",
"json_schema": "PASS",
"systemd_validation": "PASS",
"changed_path_secret_scan": "PASS",
"git_fsck_connectivity_only": "PASS",
"fault_injection": "PASS",
"package_digest_closure": "PASS",
"scope_boundary_tests": "PASS"
}
},
"allowed_operations": [
"install_exact_approved_bootstrap_files_after_owner_review",
"publish_exact_five_statuses_to_approved_head",
"fast_forward_only_merge_this_bootstrap_pr",
"install_exact_two_parent_broker_schema_and_validator",
"issue_one_task_scoped_merge_credential",
"execute_one_precomputed_two_parent_merge",
"compare_and_swap_governance_ref",
"revoke_task_credentials",
"remove_task_credential_projection"
],
"denied_operations": [
"modify_or_merge_pr39",
"delete_pr39_review",
"delete_pr39_block_receipt",
"main_write",
"integration_write",
"tag_write",
"registry_write",
"baseline_write",
"production_write",
"branch_protection_change",
"force_push",
"squash",
"rebase",
"third_parent",
"runtime_generated_unapproved_merge_oid",
"status_copy_to_merge_commit",
"approval_impersonation",
"plaintext_secret_persistence"
],
"runtime_controls": {
"global_gitops_writes_enabled": false,
"systemd_encrypted_credentials_required": true,
"merge_method_for_this_bootstrap_pr": "fast-forward-only",
"merge_method_for_successor_phase_b": "exact-two-parent-commit",
"automatic_revocation_required": true
}
}
@@ -0,0 +1,79 @@
{
"AIOS_GITOPS_WRITES_ENABLED": false,
"acknowledges_pr30_owner_approval_was_missing": true,
"activation_prerequisites_artifact_sha256": "729077800c6510bf8930c97a78781218d1bce9ec40157aa99fc2bd205466e895",
"activation_prerequisites_commit_oid": "fa038d17b29001e26f1ac88019a407a4b3ebaa7e",
"activation_prerequisites_rollback_artifact_sha256": "00e40eace10a0aae1731eb98851fec71a0c13c48e1e6e5a113e30a4356c2086f",
"activation_prerequisites_tree_oid": "d5ff67f848807ef2c7a695c05cdd0bb5f2644fc2",
"approval_request_branch": "governance/request/single-owner-atomic-activation-owner-ratification-20260729T014918Z-e503d96665ee",
"approval_type": "SINGLE_OWNER_GOVERNANCE_ATOMIC_ACTIVATION_OWNER_RATIFICATION",
"branch_protection_adapter_sha256": "2706dc6095ff639838f72c91a66c1f80711893c8c0498555b388feaacf2db569",
"denied_operations": [
"main.write",
"integration.write",
"tag.write",
"registry.write",
"baseline.write",
"production.deploy",
"force_push",
"history_rewrite",
"governance.direct_push",
"approval.impersonate"
],
"direct_protected_branch_push_allowed": false,
"dismiss_stale_approvals": true,
"dormant_deployment_evidence_sha256": "c4c326784a3d66d62e32c46be3506c801585c06a34e62c9a1f210492a6c1bc06",
"evidence_closure_oid": "5f45139ca5f7f7f3da244141c5115d12f5af58ae",
"evidence_closure_sha256": "53e5f2fdc01a6225048dfdf6eac973e99743f0295f17f3a42f01dce7e7050ab8",
"expected_governance_base_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
"expires_at": "2026-07-29T13:49:18Z",
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
"approval_validator.activate",
"governance_state_machine.activate",
"gitea_branch_protection.atomic_update",
"rollback_configuration.install",
"single_owner_policy.activate",
"break_glass.expire",
"post_activation_tests.execute"
],
"force_push_allowed": false,
"human_authorizer": "owner",
"issued_at": "2026-07-29T01:49:18Z",
"legacy_mechanical_approvals": [
"codex",
"gpt"
],
"merge_mode": "CREATE_MERGE_COMMIT",
"pr30_codex_approval_review_id": 45,
"pr30_codex_reviewed_at": "2026-07-29T01:24:38Z",
"pr30_codex_reviewed_head_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
"pr30_gpt_approval_review_id": 46,
"pr30_gpt_reviewed_at": "2026-07-29T01:25:02Z",
"pr30_gpt_reviewed_head_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
"pr30_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-ATOMIC-ACTIVATION-20260728T204808Z-4cab1d5829d6.json",
"pr30_merge_tree_oid": "219974f085efe473fcc6ad2170f67312d8e57c54",
"pr30_merged_at": "2026-07-29T01:25:08Z",
"pr30_owner_review_id": 42,
"pr30_owner_review_state_observed": "REQUESTED_NOT_APPROVED",
"pr30_owner_reviewed_head_oid": null,
"pr30_premerge_base_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
"production_deployment_allowed": false,
"ratifies_pr30_manifest_blob_oid": "38c95dde2d3831f8e3c80b342369f1c3e1cbf34c",
"ratifies_pr30_manifest_sha256": "bc19ada0e8eeb47d421a6360cf1d66b6d1129eb6056a447d9ff70ebd5ada1718",
"ratifies_pr30_merge_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
"ratifies_pr30_request_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
"ratifies_pr_number": 30,
"require_latest_head_approval": true,
"required_reviewers": [
"owner",
"codex",
"gpt"
],
"rollback_configuration_sha256": "eb44fc5f655f8c30c4b687185055ba3a2725189e19538e3a9a46a2c0cf141b8c",
"schema": "aios.governance-approval/v1",
"state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
"task_id": "AIOS-PR30-SINGLE-OWNER-ATOMIC-ACTIVATION-OWNER-RATIFICATION-20260729",
"test_evidence_sha256": "42168da7437028440bece3432d8aa38a8722b4db18244423d9daaa380675c45a",
"validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
"wip_blocks_merge": true
}
@@ -0,0 +1,91 @@
{
"approval_request_branch": "governance/request/single-owner-governance-activation-prerequisites-20260728T183025127107Z",
"approval_type": "SINGLE_OWNER_GOVERNANCE_ACTIVATION_PREREQUISITES",
"binds_final_ratification_manifest_blob_oid": "2865fbec766901eb61fc8aed0542970e951e0d1d",
"binds_final_ratification_manifest_sha256": "216e54503d8e6a3f4c908084e19ce1e6242d3ba15f7b8011a9a9d9f7975e63e7",
"binds_final_ratification_merge_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
"binds_mirror_receipt_sha256": "6873133f7233bfed0d3b78b01847ad4251b8b67f3b6db7011efd07664f8d088f",
"expected_governance_base_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
"expires_at": "2026-07-29T06:30:25Z",
"explicitly_allowed_after_owner_approval_and_legacy_merge": [
"task_bound_activation_writer_grant.create",
"gitea_owner_review_adapter.create_and_dormant_deploy",
"machine_status_producer.create_and_dormant_deploy",
"machine_status_producer.credential_rotation_and_revocation",
"maintenance_lock.create",
"branch_protection_compensation_saga.create",
"targeted_online_rollback_executor.create",
"disposable_gitea_fixture.create_test_destroy",
"single_owner_activation_prerequisite_tests.execute",
"activation_prerequisite_evidence.create"
],
"implementation_branch": "patch/single-owner-governance-activation-prerequisites-20260729",
"implementation_paths": [
"services/aios-single-owner-governance/**",
"tests/single_owner_governance/**",
"deploy/systemd/aios-governance-*.service",
"deploy/systemd/aios-governance-*.timer"
],
"issued_at": "2026-07-28T18:30:25Z",
"machine_status_contexts": [
"aios/machine-gates",
"aios/secret-scan",
"aios/evidence-closure"
],
"observed_blockers": {
"commit_status_row_count": 0,
"disposable_governance_fixture_present": false,
"gitea_owner_review_validator_present": false,
"gitea_version": "1.22.6",
"native_branch_protection_etag_cas_present": false,
"required_status_context_producers_present": false,
"targeted_online_rollback_executor_present": false
},
"owner_approval_contract": {
"agent_must_not_submit_review": true,
"dismissed": false,
"head_change_invalidates_approval": true,
"only_human_approver": "owner",
"owner_user_id": 2,
"review_state": "APPROVED",
"reviewed_before_expires_at": true,
"reviewed_head_oid_must_equal_current_head_oid": true,
"stale": false
},
"permanent_constraints": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"direct_main_push": false,
"force_push": false,
"history_rewrite": false,
"secret_commit": false,
"tag_rewrite": false
},
"pre_approval_non_authorizations": {
"activation_allowed": false,
"baseline_write_allowed": false,
"branch_protection_change_allowed": false,
"fixture_deployment_allowed": false,
"integration_write_allowed": false,
"main_write_allowed": false,
"merge_allowed": false,
"production_write_allowed": false,
"registry_write_allowed": false,
"tag_write_allowed": false,
"writer_grant_allowed": false
},
"reason": "safe-atomic-activation-prerequisites-absent",
"repository": "aios/aios",
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
"schema": "aios.single-owner-governance-activation-prerequisites/v1",
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-PREREQUISITES-20260729",
"wip": true,
"wip_transition_contract": {
"codex_and_gpt_not_requested_before_owner_approval": true,
"remove_wip_without_head_change_only_after_owner_approval": true,
"then_request_legacy_mechanical_reviews": [
"codex",
"gpt"
],
"wip_must_remain_until_owner_exact_head_approval": true
}
}
@@ -0,0 +1,68 @@
{
"AIOS_GITOPS_WRITES_ENABLED": false,
"activation_prerequisites_artifact_sha256": "729077800c6510bf8930c97a78781218d1bce9ec40157aa99fc2bd205466e895",
"activation_prerequisites_commit_oid": "fa038d17b29001e26f1ac88019a407a4b3ebaa7e",
"activation_prerequisites_rollback_artifact_sha256": "00e40eace10a0aae1731eb98851fec71a0c13c48e1e6e5a113e30a4356c2086f",
"activation_prerequisites_tree_oid": "d5ff67f848807ef2c7a695c05cdd0bb5f2644fc2",
"approval_request_branch": "governance/request/single-owner-governance-atomic-activation-20260728T204808Z-4cab1d5829d6",
"approval_type": "SINGLE_OWNER_GOVERNANCE_ATOMIC_ACTIVATION",
"branch_protection_adapter_sha256": "2706dc6095ff639838f72c91a66c1f80711893c8c0498555b388feaacf2db569",
"denied_operations": [
"main.write",
"integration.write",
"tag.write",
"registry.write",
"baseline.write",
"production.deploy",
"force_push",
"history_rewrite",
"governance.direct_push",
"approval.impersonate"
],
"deployment_mode_before_execution": "DORMANT_SHADOW_ONLY",
"direct_protected_branch_push_allowed": false,
"dismiss_stale_approvals": true,
"dormant_deployment_evidence_sha256": "c4c326784a3d66d62e32c46be3506c801585c06a34e62c9a1f210492a6c1bc06",
"evidence_closure_oid": "5f45139ca5f7f7f3da244141c5115d12f5af58ae",
"evidence_closure_sha256": "53e5f2fdc01a6225048dfdf6eac973e99743f0295f17f3a42f01dce7e7050ab8",
"expected_governance_base_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
"expires_at": "2026-07-29T08:48:08Z",
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
"approval_validator.activate",
"governance_state_machine.activate",
"gitea_branch_protection.atomic_update",
"rollback_configuration.install",
"single_owner_policy.activate",
"break_glass.expire",
"post_activation_tests.execute"
],
"force_push_allowed": false,
"issued_at": "2026-07-28T20:48:08Z",
"legacy_mechanical_approvals": [
"codex",
"gpt"
],
"machine_gates_required": true,
"merge_mode": "CREATE_MERGE_COMMIT",
"pr26_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
"pr27_merge_oid": "4e6ef70029b1d94626e432892f7d3beb8e3e5627",
"pr28_merge_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
"pr29_merge_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
"production_deployment_allowed": false,
"require_latest_head_approval": true,
"required_human_authorizer": "owner",
"required_reviewers": [
"owner",
"codex",
"gpt"
],
"rollback_configuration_sha256": "eb44fc5f655f8c30c4b687185055ba3a2725189e19538e3a9a46a2c0cf141b8c",
"rollback_required_on_any_activation_failure": true,
"schema": "aios.governance-approval/v1",
"single_owner_policy_active_before_execution": false,
"state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ATOMIC-ACTIVATION-20260729",
"test_evidence_sha256": "42168da7437028440bece3432d8aa38a8722b4db18244423d9daaa380675c45a",
"validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
"wip_blocks_merge": true
}
@@ -0,0 +1,268 @@
{
"acknowledges_pr26_owner_approval_was_missing": true,
"approval_request_branch": "governance/request/single-owner-control-plane-deployment-20260728T170740Z-ea7a102dac417c23",
"approval_type": "SINGLE_OWNER_GOVERNANCE_CONTROL_PLANE_DEPLOYMENT",
"control_plane_targets": {
"allowed_human_approvers": [
"owner"
],
"branch_deletion": false,
"direct_protected_branch_push": false,
"dismiss_stale_approvals": true,
"executor_must_not_approve": true,
"force_push": false,
"governance_model": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
"historical_records_immutable": true,
"machine_gates_required": true,
"policy_effective_at_set_only_after_activation_tests_pass": true,
"protected_branches": [
"governance/approvals",
"main",
"release/**",
"integration/**"
],
"requester_must_not_approve": true,
"require_approval_for_latest_commit": true,
"required_human_approvals": 1,
"required_owner_approvals": 1,
"required_status_contexts": [
"aios/machine-gates",
"aios/secret-scan",
"aios/evidence-closure"
],
"tag_rewrite": false,
"wip_blocks_merge": true
},
"does_not_claim_pr26_met_old_two_natural_person_policy": true,
"expected_authoritative_governance_base_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
"expected_gitea_governance_base_oid": "a5489f1b67870622162b2daa781bd0237735831a",
"expires_at": "2026-07-29T05:07:40Z",
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
"approval_mirror.fast_forward_governance_only",
"approval_validator.update",
"state_machine.update",
"gitea_branch_protection.update_via_authenticated_api_compare_and_swap",
"governance_policy.activate",
"rollback_configuration.install",
"governance_acceptance_tests.execute",
"single_owner_governance_activation_receipt.create"
],
"explicitly_denied_operations": [
"force_push",
"plus_refspec",
"tag_fetch",
"prune",
"direct_git_database_write",
"direct_protected_ref_push",
"main_write",
"integration_write",
"tag_write",
"registry_write",
"baseline_write",
"production_write",
"history_rewrite",
"branch_delete",
"secret_read",
"approval_impersonation"
],
"global_constraints": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"direct_main_push": false,
"force_push_used": false,
"owner_approval_respected": true,
"secrets_committed": false,
"tag_rewritten": false
},
"implementation_surface": {
"approval_validator": [
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py",
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py",
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py"
],
"runtime": [
"active-runtime/app/silent_release_controller.py",
"active-runtime/app/silent_release_hardening.py"
],
"state_machine": [
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py",
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py",
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py"
],
"systemd": [
"deploy/systemd/aios-autonomous-release-candidate.service",
"deploy/systemd/aios-silent-release-controller.service"
]
},
"issued_at": "2026-07-28T17:07:40Z",
"legacy_gitea_protection_gate": {
"account_reviews_do_not_prove_distinct_natural_persons": true,
"both_must_approve_this_exact_head": true,
"current_approval_whitelist": [
"codex",
"gpt"
],
"current_required_approvals": 2
},
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET_RATIFICATION",
"mirror_contract": {
"expected_chain_contains_policy_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
"expected_pre_sync_authoritative_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
"fast_forward_only": true,
"force": false,
"fsck_connectivity_only_required": true,
"only_ref": "refs/heads/governance/approvals",
"plus_refspec": false,
"prune": false,
"quarantine_required": true,
"source": "gitea_repository_file_url_only",
"tags": false
},
"owner_break_glass_ratification": {
"attests_reason": "single-maintainer-system",
"attests_scope": "governance-policy-migration-only",
"created_before_expires_at": true,
"dismissed": false,
"required": true,
"review_state": "APPROVED",
"reviewed_head_oid_must_equal_current_pr_head_oid": true,
"reviewer_user_id": 2,
"reviewer_username": "owner",
"stale": false
},
"pre_approval_non_authorizations": {
"approval_validator_update_allowed": false,
"development_allowed": false,
"gitea_branch_protection_update_allowed": false,
"governance_policy_activation_allowed": false,
"merge_allowed": false,
"mirror_allowed": false,
"production_change_allowed": false,
"rollback_install_allowed": false,
"standing_writer_policy_allowed": false,
"state_machine_update_allowed": false
},
"pre_cutover_protection_snapshot": {
"protected_branch": [
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "governance/approvals",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 1,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 3,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "main",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 2,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
}
],
"protected_tag": []
},
"pre_cutover_protection_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
"ratifies_policy_manifest_blob_oid": "65f44007b10fc2a912d69e3f9081c0cfff77dfad",
"ratifies_policy_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-MIGRATION-20260728T162246Z.json",
"ratifies_policy_manifest_sha256": "c097475afbe3074e6482f125b635981f8c0284f3d763c926e2a63e1a3ee1c6c3",
"ratifies_policy_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
"ratifies_policy_pr_number": 26,
"ratifies_policy_request_oid": "312d3b483049a748675e887a516ec739c81ff474",
"ratifies_policy_tree_oid": "5c6974c058bba6210dcc1bdd0968fb7e6c84a844",
"repository": "aios/aios",
"request_status": "HUMAN_OWNER_AND_LEGACY_PROTECTION_APPROVAL_PENDING",
"required_machine_gates": [
"owner_exact_head_review_valid",
"legacy_protection_reviews_valid",
"ordinary_merge_commit",
"parent_order_verified",
"manifest_add_only",
"quarantine_verification",
"approval_mirror_fast_forward",
"validator_tests",
"state_machine_tests",
"protection_compare_and_swap",
"positive_governance_tests",
"negative_governance_tests",
"secret_scan",
"rollback_integrity",
"production_write_false"
],
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
"schema": "aios.single-owner-governance-control-plane-deployment/v1",
"scope": "pr26-ratification-mirror-and-single-owner-control-plane-deployment-only",
"task_id": "AIOS-SINGLE-OWNER-CONTROL-PLANE-DEPLOYMENT-20260729"
}
@@ -0,0 +1,260 @@
{
"acknowledges_pr26_and_pr27_owner_approval_was_missing": true,
"approval_request_branch": "governance/request/single-owner-governance-final-owner-ratification-20260728T173634412838Z",
"approval_type": "SINGLE_OWNER_GOVERNANCE_FINAL_OWNER_RATIFICATION",
"backup_checksums_sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
"backup_root": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/pre-migration-backup",
"break_glass_expires_immediately_after_activation": true,
"does_not_claim_old_two_natural_person_compliance": true,
"expires_at": "2026-07-29T05:36:34Z",
"inherits_only_pr27_control_plane_allowlist": [
"approval_mirror.fast_forward_governance_only",
"approval_validator.update",
"state_machine.update",
"gitea_branch_protection.update_via_authenticated_api_compare_and_swap",
"governance_policy.activate",
"rollback_configuration.install",
"governance_acceptance_tests.execute",
"single_owner_governance_activation_receipt.create"
],
"issued_at": "2026-07-28T17:36:34Z",
"legacy_mechanical_protection_gate": {
"account_reviews_do_not_count_as_owner_ratification": true,
"account_reviews_do_not_prove_distinct_natural_persons": true,
"approval_and_merge_whitelist_user_ids": [
42,
43
],
"both_reviews_must_bind_current_request_head": true,
"required_approvals": 2,
"reviewers": [
"codex",
"gpt"
]
},
"merge_contract": {
"first_parent_must_equal_premerge_governance_oid": true,
"force": false,
"merge_mode": "CREATE_MERGE_COMMIT",
"parent_count": 2,
"rebase": false,
"second_parent_must_equal_final_ratification_request_oid": true,
"single_file_add_only": true,
"squash": false
},
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET",
"mirror_contract": {
"expected_authoritative_pre_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
"fast_forward_only": true,
"force": false,
"fsck_connectivity_only_required": true,
"only_ref": "refs/heads/governance/approvals",
"plus_refspec": false,
"prune": false,
"quarantine_required": true,
"required_chain": [
"ac2dc5c30eb35748ef11c98297812729d0fd5828",
"a5489f1b67870622162b2daa781bd0237735831a",
"4e6ef70029b1d94626e432892f7d3beb8e3e5627",
"FINAL_RATIFICATION_MERGE_OID"
],
"source": "gitea_repository_file_url_only",
"tags": false
},
"owner_ratification_contract": {
"agent_must_not_submit_review": true,
"dismissed": false,
"only_valid_human_approver": "owner",
"owner_user_id": 2,
"review_state": "APPROVED",
"review_type_must_be_approved_not_requested": true,
"reviewed_before_expires_at": true,
"reviewed_before_merge": true,
"reviewed_head_oid_must_equal_current_request_head_oid": true,
"stale": false
},
"permanent_constraints": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"direct_main_push": false,
"force_push_used": false,
"owner_approval_respected": true,
"secrets_committed": false,
"tag_rewritten": false
},
"post_merge_activation_preconditions": [
"owner_exact_head_approval_valid",
"legacy_mechanical_reviews_valid",
"ordinary_merge_commit",
"one_file_add_only",
"quarantine_chain_verified",
"approval_mirror_fast_forward_closed",
"rollback_integrity_pass",
"validator_and_state_machine_tests_pass",
"protection_compare_and_swap_pass",
"positive_and_negative_governance_tests_pass",
"production_write_false"
],
"pre_activation_protection_snapshot": {
"protected_branch": [
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "governance/approvals",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 1,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 3,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "main",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 2,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
}
],
"protected_tag": []
},
"pre_activation_protection_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
"pre_approval_non_authorizations": {
"baseline_write_allowed": false,
"branch_protection_update_allowed": false,
"control_plane_activation_allowed": false,
"development_allowed": false,
"integration_write_allowed": false,
"main_write_allowed": false,
"merge_allowed": false,
"mirror_allowed": false,
"production_write_allowed": false,
"registry_write_allowed": false,
"rollback_install_allowed": false,
"standing_writer_allowed": false,
"state_machine_update_allowed": false,
"tag_write_allowed": false,
"validator_update_allowed": false
},
"ratification_scope": "GOVERNANCE_MIGRATION_AND_CONTROL_PLANE_ACTIVATION_ONLY",
"ratifies_pr26_manifest_blob_oid": "65f44007b10fc2a912d69e3f9081c0cfff77dfad",
"ratifies_pr26_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-MIGRATION-20260728T162246Z.json",
"ratifies_pr26_manifest_sha256": "c097475afbe3074e6482f125b635981f8c0284f3d763c926e2a63e1a3ee1c6c3",
"ratifies_pr26_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
"ratifies_pr26_request_oid": "312d3b483049a748675e887a516ec739c81ff474",
"ratifies_pr26_tree_oid": "5c6974c058bba6210dcc1bdd0968fb7e6c84a844",
"ratifies_pr27_manifest_blob_oid": "77f3c2ab85cba2c30c8c0aa36e591232d0f4c396",
"ratifies_pr27_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-CONTROL-PLANE-DEPLOYMENT-20260728T170740Z-ea7a102dac417c23.json",
"ratifies_pr27_manifest_sha256": "2ed09180c0aeadbef2e5d6310efe7c2d0de15e0e87b6135e7a8494cb4f0967c7",
"ratifies_pr27_merge_oid": "4e6ef70029b1d94626e432892f7d3beb8e3e5627",
"ratifies_pr27_request_oid": "80feef309fd8e1db7795f68d5bf0f15ce805b365",
"ratifies_pr27_tree_oid": "85af0d1e88e8484a9c3a0562a81cbc1de09250ae",
"ratifies_pr_numbers": [
26,
27
],
"repository": "aios/aios",
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
"retroactive_authorization_for_other_operations": false,
"rollback_archive_member_hashes": {
"pre-migration-backup/app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
"pre-migration-backup/authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
"pre-migration-backup/authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
"pre-migration-backup/backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
"pre-migration-backup/checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
"pre-migration-backup/gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
"pre-migration-backup/gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
"pre-migration-backup/gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
"pre-migration-backup/governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
"pre-migration-backup/protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
"pre-migration-backup/protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"pre-migration-backup/repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
"pre-migration-backup/repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
"pre-migration-backup/repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
"pre-migration-backup/repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
"pre-migration-backup/repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
"pre-migration-backup/repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
"pre-migration-backup/repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
"pre-migration-backup/repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
"pre-migration-backup/repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
},
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
"schema": "aios.single-owner-governance-final-owner-ratification/v1",
"single_owner_policy_effective_at": "FINAL_RATIFICATION_MERGE_OID",
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-FINAL-RATIFICATION-20260729"
}
@@ -0,0 +1,484 @@
{
"allowed_human_approvers": [
"owner"
],
"approval_expires_at": "2026-07-29T16:22:46Z",
"approval_request_branch": "governance/request/single-owner-governance-migration-20260728T162246Z",
"approval_type": "SINGLE_OWNER_GOVERNANCE_POLICY",
"approval_types_migrated_after_policy_effective_at": [
"SOURCE_MAPPING_AND_IMPORT_EXECUTION_RENEWAL",
"CONTROL_PLANE_DEPLOYMENT_APPROVAL",
"DEVELOPMENT_MERGE_APPROVAL",
"RELEASE_CANDIDATE_APPROVAL",
"PRODUCTION_RELEASE_APPROVAL",
"TAG_APPROVAL",
"REGISTRY_BASELINE_PROMOTION_APPROVAL",
"PRODUCTION_DEPLOYMENT_APPROVAL",
"ROLLBACK_APPROVAL"
],
"atomic_migration": {
"backup_checksums_sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
"backup_root": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/pre-migration-backup",
"direct_database_update": false,
"direct_ref_update": false,
"dual_capable_validator_shadow_required": true,
"identity_snapshot_sha256": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
"live_protection_canonical_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
"maintenance_lock_required": true,
"old_rules_remain_active_until_owner_approval_and_machine_gates_pass": true,
"protected_branch_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
"protection_update_method": "authenticated_admin_API_compare_and_swap",
"reviewable_backup_file_hashes": {
"app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
"authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
"authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
"backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
"checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
"gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
"gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
"gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
"governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
"protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
"protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
"repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
"repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
"repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
"repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
"repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
"repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
"repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
"repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
},
"reviewable_pre_migration_governance_identity_snapshot": [
{
"created_unix": 1783321252,
"id": 1,
"is_active": 1,
"is_admin": 0,
"last_login_unix": 0,
"lower_name": "aios",
"prohibit_login": 1,
"type": 0
},
{
"created_unix": 1783335380,
"id": 2,
"is_active": 1,
"is_admin": 1,
"last_login_unix": 1785086126,
"lower_name": "owner",
"prohibit_login": 0,
"type": 0
},
{
"created_unix": 1783411566,
"id": 3,
"is_active": 1,
"is_admin": 1,
"last_login_unix": 0,
"lower_name": "gito",
"prohibit_login": 0,
"type": 0
},
{
"created_unix": 1785078826,
"id": 42,
"is_active": 1,
"is_admin": 0,
"last_login_unix": 1785206253,
"lower_name": "codex",
"prohibit_login": 0,
"type": 0
},
{
"created_unix": 1785078882,
"id": 43,
"is_active": 1,
"is_admin": 0,
"last_login_unix": 1785206380,
"lower_name": "gpt",
"prohibit_login": 0,
"type": 0
}
],
"reviewable_pre_migration_protection_snapshot": {
"protected_branch": [
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "governance/approvals",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 1,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 3,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
{
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[42,43]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "main",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 0,
"enable_whitelist": 0,
"id": 2,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 2,
"status_check_contexts": "[]",
"unprotected_file_patterns": "",
"updated_unix": 1785093422,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
}
],
"protected_tag": []
},
"rollback_archive_members": {
"pre-migration-backup/app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
"pre-migration-backup/authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
"pre-migration-backup/authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
"pre-migration-backup/backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
"pre-migration-backup/checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
"pre-migration-backup/gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
"pre-migration-backup/gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
"pre-migration-backup/gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
"pre-migration-backup/governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
"pre-migration-backup/protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
"pre-migration-backup/protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"pre-migration-backup/repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
"pre-migration-backup/repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
"pre-migration-backup/repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
"pre-migration-backup/repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
"pre-migration-backup/repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
"pre-migration-backup/repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
"pre-migration-backup/repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
"pre-migration-backup/repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
"pre-migration-backup/repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
},
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
"rollback_restores_protection_before_validator": true
},
"auto_merge_after_owner_approval": false,
"auto_merge_machine_conditions": [
"owner_approval_valid",
"head_oid_unchanged",
"required_checks_pass",
"secret_scan_pass",
"evidence_closure_pass",
"approval_not_expired",
"protected_branch_rules_pass"
],
"automatic_renewal_policy": {
"approval_ref_fast_forward_descendant_required": true,
"changed_condition_fallback": "HUMAN_OWNER_APPROVAL_PENDING",
"secret_scan": "PASS_REQUIRED",
"single_renewal_max_hours": 12,
"status": "PROPOSED_AFTER_MIGRATION",
"total_window_max_days": 7,
"unchanged_fields_required": [
"original_policy_sha256",
"allowed_paths",
"allowed_operations",
"denied_operations",
"source_sha256",
"source_blob_oid"
]
},
"break_glass_executor_may_merge_only_after_owner_approval_machine_gates_and_atomic_cutover_preconditions": true,
"break_glass_expires_at": "2026-07-29T16:22:46Z",
"desired_branch_protection": {
"approval_whitelist_user_ids": [
2
],
"approval_whitelist_usernames": [
"owner"
],
"block_on_official_review_requests": true,
"block_on_outdated_branch": true,
"block_on_rejected_reviews": true,
"branch_deletion": false,
"branch_patterns": [
"governance/approvals",
"main",
"release/**",
"integration/**"
],
"direct_push": false,
"dismiss_stale_approvals": true,
"force_push": false,
"require_status_checks": true,
"required_approvals": 1,
"required_status_contexts": [
"aios/machine-gates",
"aios/secret-scan",
"aios/evidence-closure"
],
"wip_blocks_merge": true
},
"executor_must_not_approve": true,
"expected_governance_base_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
"expires_at": "2026-07-29T16:22:46Z",
"global_constraints": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"approval_impersonation": false,
"direct_main_push": false,
"fake_review": false,
"force_push": false,
"production_change_without_owner_approval": false,
"secret_commit": false,
"tag_rewrite": false
},
"governance_model": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
"historical_policy": {
"historical_manifests_modified": false,
"old_policy_decoder_retained_read_only": true,
"requests_created_before_policy_effective_at_use_old_policy": true
},
"issued_at": "2026-07-28T16:22:46Z",
"machine_gates": {
"development_branch": [
"allowed_branch",
"allowed_paths",
"compileall",
"targeted_tests",
"secret_scan",
"git_diff_check"
],
"production": [
"owner_approval",
"tag_consistency",
"registry_consistency",
"deployment_plan",
"rollback_plan",
"artifact_integrity",
"production_preflight"
],
"protected_branch_merge": [
"expected_base_oid",
"current_head_oid",
"ordinary_merge_commit",
"parent_order_verified",
"artifact_binding",
"audit_chain_valid"
],
"release": [
"version_manifest",
"explicit_release_target_oid",
"artifact_sha256",
"rollback_artifact_sha256",
"sbom",
"test_evidence",
"evidence_closure"
]
},
"merge_mode": "CREATE_MERGE_COMMIT",
"migration_acceptance_tests": [
"agent_request_pass",
"owner_current_head_approval_pass",
"machine_gates_then_merge_commit_pass",
"agent_self_approval_denied",
"non_owner_approval_denied",
"stale_head_approval_denied",
"wip_merge_denied",
"machine_test_failure_merge_denied",
"secret_scan_failure_merge_denied",
"main_direct_write_denied",
"tag_direct_write_denied",
"force_push_denied",
"missing_tag_target_oid_denied",
"missing_evidence_closure_oid_denied",
"production_without_owner_denied",
"dormant_only_production_activation_denied"
],
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET",
"new_policy": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
"old_policy": "DUAL_HUMAN_APPROVAL",
"owner_approval_contract": {
"dismissed": false,
"does_not_claim_old_dual_approval_compliance": true,
"head_change_invalidates_owner_approval": true,
"owner_review_is_break_glass_signature": true,
"review_created_before_approval_expires_at": true,
"review_state": "APPROVED",
"reviewed_head_oid_must_equal_current_pr_head_oid": true,
"reviewer_must_equal": "owner",
"stale": false
},
"owner_break_glass_declaration_to_be_attested_by_review": {
"attestation_status": "PENDING_OWNER_REVIEW",
"expires_at": "2026-07-29T16:22:46Z",
"new_policy": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
"old_policy": "DUAL_HUMAN_APPROVAL",
"owner_acknowledges_old_policy_exception": true,
"reason": "single-maintainer-system",
"scope": "governance-policy-migration-only"
},
"owner_is_only_human_approver": true,
"policy_effective_at": null,
"pre_approval_non_authorizations": {
"approval_validator_update_allowed": false,
"gitea_branch_protection_update_allowed": false,
"merge_allowed": false,
"old_dual_rule_disable_allowed": false,
"production_change_allowed": false,
"state_machine_update_allowed": false,
"writer_credential_issue_allowed": false
},
"prohibited_merge_modes": [
"squash",
"rebase",
"force",
"fast_forward_policy_bypass"
],
"reason": "single-maintainer-system",
"repository": "aios/aios",
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
"requester_must_not_approve": true,
"requesters": [
"codex-chartgpt-bridge",
"aios-governance-agent",
"aios-release-agent",
"aios-governed-development-writer"
],
"required_distinct_human_approvers": 1,
"required_human_approvals": 1,
"required_owner_approvals": 1,
"resolved_owner": {
"confidence_before_review": "MEDIUM",
"confirmation_rule": "valid APPROVED review by owner on this exact immutable head",
"email_sha256": "f5dc2928f6202c24fa4db8bb33db84e1b77c6eff30d1b95abdadeaae209bc4c9",
"identity_source": [
"gitea_repository_owner_account_aios_is_login_prohibited",
"all_login_enabled_site_admins_enumerated_owner_and_never_logged_in_service_gito",
"only_interactive_site_admin_named_owner",
"gitea_owner_last_login_present",
"historical_governance_records_use_approved_by_role_owner",
"user_declared_single_natural_person_maintainer"
],
"login_enabled_site_admins": [
{
"observed_prior_login": true,
"user_id": 2,
"username": "owner"
},
{
"classification": "service_admin_not_human_approver",
"observed_prior_login": false,
"user_id": 3,
"username": "gito"
}
],
"user_id": 2,
"username": "owner"
},
"schema": "aios.single-owner-governance-policy/v1",
"scope": "governance-policy-migration-only",
"standing_autonomous_development_policy": {
"allowed_without_repeated_owner_approval": [
"patch_branch_create",
"allowlisted_development_write",
"patch_branch_commit_and_push",
"test_execute",
"artifact_build",
"approval_pr_create",
"read_only_evidence",
"task_writer_renewal"
],
"owner_approval_still_required": [
"protected_branch_merge",
"tag",
"registry_update",
"production_baseline_update",
"production_deploy",
"production_rollback",
"governance_policy_change"
],
"status": "PROPOSED_AFTER_MIGRATION"
},
"standing_single_owner_governance_migration_authorization": true,
"state_machine": {
"auto_merge_ready_state": "AUTO_MERGE_READY",
"execution_ready_state": "OWNER_APPROVED_EXECUTION_READY",
"machine_verified_state": "MACHINE_GATES_VERIFIED",
"owner_approval_alone_is_not_execution_ready": true,
"owner_verified_state": "OWNER_APPROVAL_VERIFIED",
"pending_state": "HUMAN_OWNER_APPROVAL_PENDING"
},
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729",
"this_manifest_authorizes_only_governance_policy_migration": true,
"this_manifest_grants_standing_development_authorization": false
}
@@ -0,0 +1,49 @@
{
"schema": "aios.gitea-native-approval/v1",
"approval_type": "IMPLEMENTATION",
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
"repository": "aios/aios",
"branch": "patch/integration-refresh-grant-provisioner-20260726",
"base_oid": "875d41c3101093149414292067fd700dc214d4d3",
"actor_identity": "chatgpt-gitops-bot",
"writer_audience": "aios-integration-refresh-provisioner-development-writer",
"risk": "high",
"allowed_paths": [
"active-runtime/app/**",
"tests/test_integration_refresh_provisioner.py",
"tests/test_isolated_writer_integration_merge.py",
"tests/test_gitea_branch_read_projection.py",
"tests/test_isolated_writer_token_policy_v2.py",
"deploy/systemd/aios-integration-refresh-*.service",
"docs/autonomous-release/**"
],
"allowed_operations": [
"repository.source_map.read",
"runtime.unit_metadata.read",
"git.ref.read",
"git.diff.read",
"git.branch.patch.create",
"commit_file.atomic",
"git.push.patch_branch",
"test.execute.allowlisted",
"artifact.build.control_plane_patch",
"evidence.write.task_runtime"
],
"denied_operations": [
"main.write",
"main.merge",
"tag.write",
"tag.delete",
"tag.rewrite",
"force_push",
"history.rewrite",
"baseline.write",
"registry.write",
"production.deploy",
"production.rollback",
"secret.read",
"secret.export",
"bare_ref_direct_write"
],
"expires_at": "2026-07-27T03:35:55Z"
}
@@ -0,0 +1,49 @@
{
"schema": "aios.gitea-native-approval/v1",
"approval_type": "IMPLEMENTATION",
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
"repository": "aios/aios",
"branch": "patch/integration-refresh-grant-provisioner-20260726",
"base_oid": "875d41c3101093149414292067fd700dc214d4d3",
"actor_identity": "chatgpt-gitops-bot",
"writer_audience": "aios-integration-refresh-provisioner-development-writer",
"risk": "high",
"allowed_paths": [
"active-runtime/app/**",
"tests/test_integration_refresh_provisioner.py",
"tests/test_isolated_writer_integration_merge.py",
"tests/test_gitea_branch_read_projection.py",
"tests/test_isolated_writer_token_policy_v2.py",
"deploy/systemd/aios-integration-refresh-*.service",
"docs/autonomous-release/**"
],
"allowed_operations": [
"repository.source_map.read",
"runtime.unit_metadata.read",
"git.ref.read",
"git.diff.read",
"git.branch.patch.create",
"commit_file.atomic",
"git.push.patch_branch",
"test.execute.allowlisted",
"artifact.build.control_plane_patch",
"evidence.write.task_runtime"
],
"denied_operations": [
"main.write",
"main.merge",
"tag.write",
"tag.delete",
"tag.rewrite",
"force_push",
"history.rewrite",
"baseline.write",
"registry.write",
"production.deploy",
"production.rollback",
"secret.read",
"secret.export",
"bare_ref_direct_write"
],
"expires_at": "2026-07-27T13:00:11Z"
}
@@ -0,0 +1,73 @@
{
"approval_type": "SINGLE_OWNER_GOVERNANCE_LIVE_ACTIVATION_IMPLEMENTATION_AND_EXECUTION",
"artifact_sha256": "01e0226f0302bb8e2f8d81299393075bf0332c6e22e00877469fb297c51f3802",
"authorization_scope": [
"deploy_live_activation_implementation",
"execute_one_atomic_governance_activation",
"execute_acceptance_tests",
"control_plane_rollback_on_failure",
"write_activation_receipt"
],
"denied_operations": [
"main.write",
"integration.write",
"tag.write",
"registry.write",
"baseline.write",
"production.deploy",
"force_push",
"history_rewrite"
],
"evidence_closure_oid": "c6316943d2485f06f97242df6338ded21de1ee38",
"evidence_closure_sha256": "bd521103c907d6194acbbbd42a947c5af2ccbda91797e5dc75e81887a042becd",
"execution_binding": {
"backend": "sqlite",
"branch": "governance/approvals",
"evidence_closure_oid": "c6316943d2485f06f97242df6338ded21de1ee38",
"executor": "aios-governance-single-owner-activation",
"expected_branch_protection_sha256": "f27992c8024426708d93bce072d231707bae47a927aa2393d566aae64d5ed079",
"expected_gitea_schema_sha256": "3524f4912165939cb746c2c65d70583a909f5abbd00c4e07ae76f7206d49aa54",
"expected_state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
"expected_validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
"forbidden_operations": {
"baseline": false,
"force_push": false,
"governance_direct": false,
"history_rewrite": false,
"integration": false,
"main": false,
"production": false,
"registry": false,
"tags": false
},
"operation_id": "single-owner-live-activation-20260729T033228Z",
"repo_id": 1,
"requester": "codex-agent",
"target_branch_protection_sha256": "61b424b0c495eed71c73171c5c4434ac66d074de36886a73ec4c445fd1905db8",
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729"
},
"execution_binding_sha256": "6b2ed671a94fa83704383728fd2bb2df3b67523b4273100fa371777d984be102",
"expected_governance_base_oid": "8b7f9d9028f6ff9beb225bf85f53dbeaac6830e7",
"expires_at": "2026-07-29T15:32:28Z",
"human_authorizer": "owner",
"implementation_commit_oid": "e1e438564ce8b987a36df0947e6eaa324dfede74",
"implementation_tree_oid": "dd93dc1df10cb8b8fe59b09d3214a9ae6fee671e",
"issued_at": "2026-07-29T03:32:28Z",
"legacy_mechanical_approvals": [
"codex",
"gpt"
],
"machine_gate_contexts": [
"aios/branch-protection",
"aios/evidence-closure",
"aios/secret-scan",
"aios/state-machine",
"aios/validator"
],
"pr30_merge_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
"pr31_merge_oid": "8b7f9d9028f6ff9beb225bf85f53dbeaac6830e7",
"rollback_artifact_sha256": "ed9307cc2f07767b75866fcb370fa3f98b76c5147e4b7fc49ecf04cf21cf7c31",
"signed_merge_requirement_effective": false,
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
"test_evidence_sha256": "172a7cf812c6b901524138fb72851a9b7d2e895dedc98893407d0bab9b52c6c1"
}
@@ -0,0 +1,171 @@
{
"approval_type": "SINGLE_OWNER_GOVERNANCE_LIVE_ACTIVATION_IMPLEMENTATION_AND_EXECUTION",
"artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
"artifact_sha256": "32bc49c207ec454b6fd81b0484f5b257bb789481b37175995029a2ec78cc62fa",
"authorization_scope": [
"deploy_exact_approved_artifact",
"publish_exact_head_machine_statuses",
"execute_one_atomic_governance_activation",
"verify_and_rollback_exact_transaction"
],
"denied_operations": [
"main.write",
"integration.write",
"tag.write",
"registry.write",
"baseline.write",
"production.deploy",
"force_push",
"history_rewrite"
],
"evidence_closure_blob_oid": "6af6d017f22c4e0c512b0cd62644cdc6ab2135d5",
"evidence_closure_oid": "310ab2af902a9fde9108d227077f433cc743ce7c",
"evidence_closure_path": "evidence/single-owner-governance/AIOS-SINGLE-OWNER-LIVE-ACTIVATION-HARDENING-20260729T043010Z.json",
"evidence_closure_sha256": "e482fe52c8381f765ee508d2de1fe2e77dff52e6e342f01be4ca481ff2f76820",
"execution_binding": {
"artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
"artifact_sha256": "32bc49c207ec454b6fd81b0484f5b257bb789481b37175995029a2ec78cc62fa",
"backend": "sqlite",
"branch": "governance/approvals",
"evidence_closure_oid": "310ab2af902a9fde9108d227077f433cc743ce7c",
"evidence_closure_path": "evidence/single-owner-governance/AIOS-SINGLE-OWNER-LIVE-ACTIVATION-HARDENING-20260729T043010Z.json",
"evidence_closure_sha256": "e482fe52c8381f765ee508d2de1fe2e77dff52e6e342f01be4ca481ff2f76820",
"executor": "aios-governance-single-owner-activation",
"expected_branch_protection_sha256": "f27992c8024426708d93bce072d231707bae47a927aa2393d566aae64d5ed079",
"expected_gitea_schema_sha256": "3524f4912165939cb746c2c65d70583a909f5abbd00c4e07ae76f7206d49aa54",
"expected_state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
"expected_validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
"forbidden_operations": {
"baseline": false,
"force_push": false,
"governance_direct": false,
"history_rewrite": false,
"integration": false,
"main": false,
"production": false,
"registry": false,
"tags": false
},
"implementation_commit_oid": "71def340e7cc34f4f19918dcf8d3c847abbe4fbf",
"implementation_tree_oid": "3cc61bfbf69cbe0a24d54a0e53a6c50bcc130066",
"machine_status_producer_id": 13,
"machine_status_producer_name": "gitops-bot",
"operation_id": "single-owner-live-activation-hardening-20260729T043149Z",
"repo_id": 1,
"requester": "codex-agent",
"rollback_artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-rollback-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
"rollback_artifact_sha256": "4efe1ea73d4fd72e5364fc91a16ad5e9d1e6ebe78d8aa466f7b11c4915b08403",
"runtime_sources": [
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
"sha256": "48846a58fa3afb2b7c8ffe6e88504a9333863932df867f33ba0321ad3bac6003"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
"sha256": "00775efe3f3d631d88379eff4ed2dcfaf386a2fa43111abe961e75109e80d768"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
"sha256": "a8f121245e04487d99c99fb03ada83f0c907723f8eb18552872ff46dcf5a7873"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
"sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
"sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1"
}
],
"target_branch_protection_sha256": "4713f0494b79103668fbe5bd8fd7da5d60a43e56fb545aa6e7c773f43dc07c10",
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
"test_evidence_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/test-evidence-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.json",
"test_evidence_sha256": "c1633732767f3f051ffb01404d12d05a6168a4b01b91efdb34a64988d6dee684"
},
"execution_binding_sha256": "63705dd0f5cc25debde132179f96819a844a9703b33c092db4ac48d5680d536a",
"expected_governance_base_oid": "1071979079deab8a4028473d967c2a205c3b111e",
"expires_at": "2026-07-29T16:31:49Z",
"human_authorizer": "owner",
"implementation_commit_oid": "71def340e7cc34f4f19918dcf8d3c847abbe4fbf",
"implementation_tree_oid": "3cc61bfbf69cbe0a24d54a0e53a6c50bcc130066",
"issued_at": "2026-07-29T04:31:49Z",
"legacy_mechanical_approvals": [
"codex",
"gpt"
],
"machine_gate_contexts": [
"aios/branch-protection",
"aios/evidence-closure",
"aios/secret-scan",
"aios/state-machine",
"aios/validator"
],
"machine_status_producer_id": 13,
"machine_status_producer_name": "gitops-bot",
"rollback_artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-rollback-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
"rollback_artifact_sha256": "4efe1ea73d4fd72e5364fc91a16ad5e9d1e6ebe78d8aa466f7b11c4915b08403",
"runtime_sources": [
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
"sha256": "48846a58fa3afb2b7c8ffe6e88504a9333863932df867f33ba0321ad3bac6003"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
"sha256": "00775efe3f3d631d88379eff4ed2dcfaf386a2fa43111abe961e75109e80d768"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
"sha256": "a8f121245e04487d99c99fb03ada83f0c907723f8eb18552872ff46dcf5a7873"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
"sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e"
},
{
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
"sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1"
}
],
"target_branch_protection": {
"approvals_whitelist_team_i_ds": "null",
"approvals_whitelist_user_i_ds": "[2]",
"block_on_official_review_requests": 1,
"block_on_outdated_branch": 1,
"block_on_rejected_reviews": 1,
"branch_name": "governance/approvals",
"can_push": 0,
"created_unix": 1785093201,
"dismiss_stale_approvals": 1,
"enable_approvals_whitelist": 1,
"enable_merge_whitelist": 1,
"enable_status_check": 1,
"enable_whitelist": 0,
"id": 1,
"ignore_stale_approvals": 0,
"merge_whitelist_team_i_ds": "null",
"merge_whitelist_user_i_ds": "[42,43]",
"protected_file_patterns": "",
"repo_id": 1,
"require_signed_commits": 0,
"required_approvals": 1,
"status_check_contexts": "[\"aios/branch-protection\",\"aios/evidence-closure\",\"aios/secret-scan\",\"aios/state-machine\",\"aios/validator\"]",
"unprotected_file_patterns": "",
"updated_unix": 1785299509,
"whitelist_deploy_keys": 0,
"whitelist_team_i_ds": "null",
"whitelist_user_i_ds": "null"
},
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
"test_evidence_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/test-evidence-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.json",
"test_evidence_sha256": "c1633732767f3f051ffb01404d12d05a6168a4b01b91efdb34a64988d6dee684"
}
@@ -0,0 +1,151 @@
{
"actor_identity": "chatgpt-gitops-bot",
"allowed_operations": [
"runtime.source.read.exact",
"runtime.source.hash",
"runtime.unit_metadata.read",
"package.ownership.read",
"git.object.lookup.by_blob_oid",
"secret.scan.local_source",
"repository.source_import.byte_exact",
"repository.module.create",
"source_map.evidence.write",
"git.branch.patch.create",
"commit_file.atomic",
"git.push.patch_branch",
"test.execute.allowlisted",
"artifact.build.control_plane_patch",
"evidence.write.task_runtime"
],
"allowed_paths": [
"active-runtime/app/aios_autonomous_release_authorization/**",
"active-runtime/app/aios_chatgpt_action_task_router/**",
"active-runtime/app/aios_isolated_writer_api/**",
"tests/test_integration_refresh_provisioner.py",
"tests/test_isolated_writer_integration_merge.py",
"tests/test_gitea_branch_read_projection.py",
"tests/test_isolated_writer_token_policy_v2.py",
"deploy/systemd/aios-integration-refresh-*.service",
"docs/autonomous-release/**"
],
"allowed_runtime_reads": [
"/usr/libexec/aios-autonomous-release-authorization/controller.py",
"/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py"
],
"approval_type": "SOURCE_MAPPING_AND_IMPORT",
"canonical_paths": {
"controller": "active-runtime/app/aios_autonomous_release_authorization/controller.py",
"isolated_writer_api": "active-runtime/app/aios_isolated_writer_api/**",
"router": "active-runtime/app/aios_chatgpt_action_task_router/action_task_router.py"
},
"denied_operations": [
"secret.value.return",
"secret.matching_line.return",
"secret.context.return",
"runtime.source.modify",
"runtime.unit.modify",
"arbitrary_path.read",
"secret.read.by_agent",
"secret.export",
"main.write",
"main.merge",
"governance.approvals.direct_write",
"integration.write",
"tag.write",
"tag.delete",
"tag.rewrite",
"force_push",
"history.rewrite",
"bare_ref_direct_write",
"baseline.write",
"registry.write",
"production.deploy",
"production.rollback"
],
"expires_at": "2026-07-27T22:36:27Z",
"extends_approval_merge_oid": "45f3226662965c8d41ec1775e8c8857f2b986397",
"finding_policy": {
"controller_byte_exact_import_allowed": true,
"controller_finding_status": "PASS",
"controller_sanitized_source_creation_allowed": false,
"finding_classification_by_automation": "PROHIBITED",
"isolated_writer_api_module_create_allowed": true,
"matching_source_lines_disclosed": false,
"router_byte_exact_import_allowed": true,
"router_finding_status": "PASS",
"router_sanitized_source_creation_allowed": false,
"scan_decision": "MAPPING_IMPORT_ONLY",
"secret_content_disclosed": false
},
"implementation_base_oid": "875d41c3101093149414292067fd700dc214d4d3",
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
"issued_at": "2026-07-27T10:36:27Z",
"repository": "aios/aios",
"required_controls": {
"controller_finding_must_be_resolved": false,
"controller_import_blob_must_equal_runtime_blob": true,
"controller_import_must_be_byte_exact": true,
"controller_import_sha256_must_equal_runtime_sha256": true,
"dual_human_approval_required": true,
"global_gitops_writes_must_remain_disabled": true,
"new_task_bound_grant_required": true,
"old_implementation_token_auth_status": 401,
"old_implementation_writer_revoked": true,
"old_secret_revocation_must_be_verified": false,
"router_finding_must_be_resolved": false,
"router_import_blob_must_equal_runtime_blob": true,
"router_import_must_be_byte_exact": true,
"router_import_sha256_must_equal_runtime_sha256": true,
"sanitized_source_behavioral_equivalence_required": false,
"sanitized_source_secret_scan_must_pass": false,
"true_positive_requires_rotation": false
},
"risk": "high",
"runtime_source_evidence": {
"controller": {
"finding_count": 0,
"findings": [],
"git_blob_oid": "9c68be36e0b6a18260e3099e3d7b0dcab6d814aa",
"group_gid": 0,
"mode": "0o700",
"mtime_ns": 1785043975531298047,
"owner_uid": 0,
"package_owner": "UNPACKAGED",
"referencing_systemd_units": [
"aios-autonomous-release-authorization-controller.service"
],
"resolved_path": "/usr/libexec/aios-autonomous-release-authorization/controller.py",
"secret_content_returned": false,
"secret_scan": "PASS",
"sha256": "39b532c3058c4ae49ed691d7c66c3b7745a25111fa61039f388c8335fd262c50",
"size": 24204,
"utf8_python": true
},
"isolated_writer_api": {
"canonical_source_path": "NOT_ESTABLISHED",
"runtime_module_status": "ABSENT"
},
"router": {
"finding_count": 0,
"findings": [],
"git_blob_oid": "ee0595ca61a0598f8cb3dc10865a255e21679b2a",
"group_gid": 0,
"mode": "0o644",
"mtime_ns": 1785042222580725999,
"owner_uid": 0,
"package_owner": "UNPACKAGED",
"referencing_systemd_units": [
"aios-chatgpt-autonomous-release-route.service"
],
"resolved_path": "/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py",
"secret_content_returned": false,
"secret_scan": "PASS",
"sha256": "738fb7035a6b792115d6467b4d1e4ffd47a8c5d5646f7032ebc68ea587cbd554",
"size": 25952,
"utf8_python": true
}
},
"schema": "aios.gitea-native-approval/v1",
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
"writer_audience": "aios-integration-refresh-provisioner-development-writer"
}
@@ -0,0 +1,157 @@
{
"actor_identity": "chatgpt-gitops-bot",
"allowed_operations": [
"runtime.source.read.exact",
"runtime.source.hash",
"runtime.unit_metadata.read",
"package.ownership.read",
"git.object.lookup.by_blob_oid",
"secret.scan.local_source",
"repository.source_import.byte_exact",
"repository.module.create",
"source_map.evidence.write",
"git.branch.patch.create",
"commit_file.atomic",
"git.push.patch_branch",
"test.execute.allowlisted",
"artifact.build.control_plane_patch",
"evidence.write.task_runtime"
],
"allowed_paths": [
"active-runtime/app/aios_autonomous_release_authorization/**",
"active-runtime/app/aios_chatgpt_action_task_router/**",
"active-runtime/app/aios_isolated_writer_api/**",
"tests/test_integration_refresh_provisioner.py",
"tests/test_isolated_writer_integration_merge.py",
"tests/test_gitea_branch_read_projection.py",
"tests/test_isolated_writer_token_policy_v2.py",
"deploy/systemd/aios-integration-refresh-*.service",
"docs/autonomous-release/**"
],
"allowed_runtime_reads": [
"/usr/libexec/aios-autonomous-release-authorization/controller.py",
"/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py"
],
"approval_type": "SOURCE_MAPPING_AND_IMPORT_EXECUTION_RENEWAL",
"canonical_paths": {
"controller": "active-runtime/app/aios_autonomous_release_authorization/controller.py",
"isolated_writer_api": "active-runtime/app/aios_isolated_writer_api/**",
"router": "active-runtime/app/aios_chatgpt_action_task_router/action_task_router.py"
},
"denied_operations": [
"secret.value.return",
"secret.matching_line.return",
"secret.context.return",
"runtime.source.modify",
"runtime.unit.modify",
"arbitrary_path.read",
"secret.read.by_agent",
"secret.export",
"main.write",
"main.merge",
"governance.approvals.direct_write",
"integration.write",
"tag.write",
"tag.delete",
"tag.rewrite",
"force_push",
"history.rewrite",
"bare_ref_direct_write",
"baseline.write",
"registry.write",
"production.deploy",
"production.rollback"
],
"expected_governance_base_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6",
"expires_at": "2026-07-28T18:10:44Z",
"extends_approval_merge_oid": "45f3226662965c8d41ec1775e8c8857f2b986397",
"finding_policy": {
"controller_byte_exact_import_allowed": true,
"controller_finding_status": "PASS",
"controller_sanitized_source_creation_allowed": false,
"finding_classification_by_automation": "PROHIBITED",
"isolated_writer_api_module_create_allowed": true,
"matching_source_lines_disclosed": false,
"router_byte_exact_import_allowed": true,
"router_finding_status": "PASS",
"router_sanitized_source_creation_allowed": false,
"scan_decision": "MAPPING_IMPORT_ONLY",
"secret_content_disclosed": false
},
"implementation_base_oid": "875d41c3101093149414292067fd700dc214d4d3",
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
"issued_at": "2026-07-28T06:10:44Z",
"renews_source_mapping_approval_merge_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6",
"renews_source_mapping_manifest_blob_oid": "00c5e90e529cb98c7750a5761b0a0d6ccf507174",
"renews_source_mapping_manifest_sha256": "17af8ebc43673c0e46bb9ab1bf44497e8c147f1b4a9d7a8a404edd5c0abd6f21",
"repository": "aios/aios",
"required_controls": {
"controller_finding_must_be_resolved": false,
"controller_import_blob_must_equal_runtime_blob": true,
"controller_import_must_be_byte_exact": true,
"controller_import_sha256_must_equal_runtime_sha256": true,
"dual_human_approval_required": true,
"global_gitops_writes_must_remain_disabled": true,
"new_task_bound_grant_required": true,
"old_implementation_token_auth_status": 401,
"old_implementation_writer_revoked": true,
"old_secret_revocation_must_be_verified": false,
"router_finding_must_be_resolved": false,
"router_import_blob_must_equal_runtime_blob": true,
"router_import_must_be_byte_exact": true,
"router_import_sha256_must_equal_runtime_sha256": true,
"sanitized_source_behavioral_equivalence_required": false,
"sanitized_source_secret_scan_must_pass": false,
"true_positive_requires_rotation": false
},
"risk": "high",
"runtime_source_evidence": {
"controller": {
"finding_count": 0,
"findings": [],
"git_blob_oid": "9c68be36e0b6a18260e3099e3d7b0dcab6d814aa",
"group_gid": 0,
"mode": "0o700",
"mtime_ns": 1785043975531298047,
"owner_uid": 0,
"package_owner": "UNPACKAGED",
"referencing_systemd_units": [
"aios-autonomous-release-authorization-controller.service"
],
"resolved_path": "/usr/libexec/aios-autonomous-release-authorization/controller.py",
"secret_content_returned": false,
"secret_scan": "PASS",
"sha256": "39b532c3058c4ae49ed691d7c66c3b7745a25111fa61039f388c8335fd262c50",
"size": 24204,
"utf8_python": true
},
"isolated_writer_api": {
"canonical_source_path": "NOT_ESTABLISHED",
"runtime_module_status": "ABSENT"
},
"observed_at": "2026-07-28T05:53:01.253909Z",
"router": {
"finding_count": 0,
"findings": [],
"git_blob_oid": "ee0595ca61a0598f8cb3dc10865a255e21679b2a",
"group_gid": 0,
"mode": "0o644",
"mtime_ns": 1785042222580725999,
"owner_uid": 0,
"package_owner": "UNPACKAGED",
"referencing_systemd_units": [
"aios-chatgpt-autonomous-release-route.service"
],
"resolved_path": "/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py",
"secret_content_returned": false,
"secret_scan": "PASS",
"sha256": "738fb7035a6b792115d6467b4d1e4ffd47a8c5d5646f7032ebc68ea587cbd554",
"size": 25952,
"utf8_python": true
}
},
"runtime_source_read_projection_evidence_sha256": "23f03d9c6abe6f11e1acda5210b8708696e3b77caa0083b6bfaef30a44b2a35f",
"schema": "aios.gitea-native-approval/v1",
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
"writer_audience": "aios-integration-refresh-provisioner-development-writer"
}
@@ -1,40 +0,0 @@
[Unit]
Description=AIOS Codex Review/Test Worker
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aiman
Group=gitops
WorkingDirectory=/usr/libexec/aios-codex-review-test-worker/current
Environment=AIOS_CODEX_WORKER_MODE=shadow
Environment=AIOS_TASK_PLANE_EXECUTION_ENABLED=false
Environment=PYTHONDONTWRITEBYTECODE=1
ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
LockPersonality=true
RestrictSUIDSGID=true
RestrictRealtime=true
MemoryDenyWriteExecute=true
RuntimeDirectory=aios-codex-review-test-worker
StateDirectory=aios-codex-review-test-worker
CacheDirectory=aios-codex-review-test-worker
ReadOnlyPaths=/data/aios-gitops/repo.git
ReadOnlyPaths=/usr/libexec/aios-codex-review-test-worker
ReadWritePaths=/run/aios-codex-review-test-worker
ReadWritePaths=/var/lib/aios-codex-review-test-worker
ReadWritePaths=/var/cache/aios-codex-review-test-worker
UMask=0077
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,36 @@
[Unit]
Description=AIOS exact two-parent governance merge broker (%i)
After=network.target aios-gitea.service
Requires=aios-gitea.service
[Service]
Type=oneshot
User=root
Group=root
UMask=0077
RuntimeDirectory=aios-exact-two-parent-merge/%i
RuntimeDirectoryMode=0700
LoadCredentialEncrypted=gitea-token:/run/aios-task-credential-broker/%i-merge.cred
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.exact_two_parent_merge_broker --grant /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/exact-two-parent-merge/allowed_signers --token %d/gitea-token --audit-key %d/audit-key --journal /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/journal/journal.sqlite3 --quarantine-root /run/aios-exact-two-parent-merge/%i
Environment=AIOS_GITOPS_WRITES_ENABLED=false
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_UNIX AF_INET
ReadOnlyPaths=/var/lib/aios-gitops/runtime/exact-two-parent-merge/%i
ReadOnlyPaths=/etc/aios-gitops/exact-two-parent-merge/allowed_signers
ReadWritePaths=/var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/journal
ReadWritePaths=/data/aios-gitops/repo.git
ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data/repositories/aios/aios.git
ReadWritePaths=/run/aios-exact-two-parent-merge/%i
IPAddressDeny=any
IPAddressAllow=localhost
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictSUIDSGID=true
@@ -0,0 +1,24 @@
[Unit]
Description=AIOS root task credential broker (%i)
ConditionPathExists=/var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json
[Service]
Type=oneshot
User=root
Group=root
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_credential_broker --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --audit-key %d/audit-key --audit-dir /var/lib/aios-gitops/runtime/task-status-merge/%i/audit --request /var/lib/aios-gitops/runtime/task-status-merge/%i/credential-request.json
Environment=AIOS_GITOPS_WRITES_ENABLED=false
NoNewPrivileges=false
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/data/aios-gitops/runtime/bin/gitea /data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig /var/lib/aios-gitops/runtime/task-status-merge/%i/credential-request.json /etc/aios-gitops/task-status-merge/allowed_signers /data/aios-gitops/runtime/gitea-bin/data/actions_artifacts /data/aios-gitops/runtime/gitea-bin/data/actions_log /data/aios-gitops/runtime/gitea-bin/data/attachments /data/aios-gitops/runtime/gitea-bin/data/avatars /data/aios-gitops/runtime/gitea-bin/data/gitea.db.bak.20260708133830 /data/aios-gitops/runtime/gitea-bin/data/gitea.db.bak-20260710-0105 /data/aios-gitops/runtime/gitea-bin/data/home /data/aios-gitops/runtime/gitea-bin/data/indexers /data/aios-gitops/runtime/gitea-bin/data/jwt /data/aios-gitops/runtime/gitea-bin/data/packages /data/aios-gitops/runtime/gitea-bin/data/queues /data/aios-gitops/runtime/gitea-bin/data/repo-archive /data/aios-gitops/runtime/gitea-bin/data/repo-avatars /data/aios-gitops/runtime/gitea-bin/data/repositories /data/aios-gitops/runtime/gitea-bin/data/tmp
ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data /run/aios-task-credential-broker /var/lib/aios-gitops/runtime/task-status-merge/%i/audit
RestrictAddressFamilies=AF_UNIX AF_INET
IPAddressDeny=any
IPAddressAllow=localhost
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictSUIDSGID=true
@@ -0,0 +1,23 @@
[Unit]
Description=AIOS task credential expiry and completion sweeper
After=aios-gitea.service
Requires=aios-gitea.service
[Service]
Type=oneshot
User=root
Group=root
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_credential_expiry_sweeper --runtime-root /var/lib/aios-gitops/runtime/task-status-merge --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers
Environment=AIOS_GITOPS_WRITES_ENABLED=false
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/etc/aios-gitops/task-status-merge/allowed_signers /data/aios-gitops/runtime/gitea-bin/data/actions_artifacts /data/aios-gitops/runtime/gitea-bin/data/actions_log /data/aios-gitops/runtime/gitea-bin/data/attachments /data/aios-gitops/runtime/gitea-bin/data/avatars /data/aios-gitops/runtime/gitea-bin/data/gitea.db.bak.20260708133830 /data/aios-gitops/runtime/gitea-bin/data/gitea.db.bak-20260710-0105 /data/aios-gitops/runtime/gitea-bin/data/home /data/aios-gitops/runtime/gitea-bin/data/indexers /data/aios-gitops/runtime/gitea-bin/data/jwt /data/aios-gitops/runtime/gitea-bin/data/packages /data/aios-gitops/runtime/gitea-bin/data/queues /data/aios-gitops/runtime/gitea-bin/data/repo-archive /data/aios-gitops/runtime/gitea-bin/data/repo-avatars /data/aios-gitops/runtime/gitea-bin/data/repositories /data/aios-gitops/runtime/gitea-bin/data/tmp
ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data /run/aios-task-credential-broker /var/lib/aios-gitops/runtime/task-status-merge
RestrictAddressFamilies=AF_UNIX AF_INET
IPAddressDeny=any
IPAddressAllow=localhost
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictSUIDSGID=true
@@ -0,0 +1,12 @@
[Unit]
Description=Run AIOS task credential expiry sweeper every minute
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
AccuracySec=5s
Persistent=true
Unit=aios-task-credential-expiry-sweeper.service
[Install]
WantedBy=timers.target
@@ -0,0 +1,26 @@
[Unit]
Description=AIOS task-scoped Gitea fast-forward-only merge broker (%i)
After=network.target aios-gitea.service aios-task-status-broker@%i.service
Requires=aios-gitea.service aios-task-status-broker@%i.service
[Service]
Type=oneshot
User=aios-task-merge-bot
Group=aios-task-merge-bot
LoadCredentialEncrypted=gitea-token:/run/aios-task-credential-broker/%i-merge.cred
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_status_merge_broker --mode merge --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --token %d/gitea-token --audit-key %d/audit-key --journal /var/lib/aios-gitops/runtime/task-status-merge/%i/merge-journal/journal.sqlite3
Environment=AIOS_GITOPS_WRITES_ENABLED=false
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
RestrictAddressFamilies=AF_UNIX AF_INET
ReadOnlyPaths=/var/lib/aios-gitops/runtime/task-status-merge/%i /etc/aios-gitops/task-status-merge/allowed_signers
ReadWritePaths=/var/lib/aios-gitops/runtime/task-status-merge/%i/merge-journal
IPAddressDeny=any
IPAddressAllow=localhost
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictSUIDSGID=true
@@ -0,0 +1,26 @@
[Unit]
Description=AIOS task-scoped Gitea status broker (%i)
After=network.target aios-gitea.service
Requires=aios-gitea.service
[Service]
Type=oneshot
User=aios-task-status-bot
Group=aios-task-status-bot
LoadCredentialEncrypted=gitea-token:/run/aios-task-credential-broker/%i-status.cred
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_status_merge_broker --mode status --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --evidence /var/lib/aios-gitops/runtime/task-status-merge/%i/status-evidence.json --token %d/gitea-token --audit-key %d/audit-key --journal /var/lib/aios-gitops/runtime/task-status-merge/%i/status-journal/journal.sqlite3
Environment=AIOS_GITOPS_WRITES_ENABLED=false
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
RestrictAddressFamilies=AF_UNIX AF_INET
ReadOnlyPaths=/var/lib/aios-gitops/runtime/task-status-merge/%i /etc/aios-gitops/task-status-merge/allowed_signers
ReadWritePaths=/var/lib/aios-gitops/runtime/task-status-merge/%i/status-journal
IPAddressDeny=any
IPAddressAllow=localhost
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictSUIDSGID=true
@@ -0,0 +1,68 @@
# Isolated Writer Exact-Path Policy V1
This policy is an additional, service-owned authorization layer for
`POST /api/commit-file`. It never expands a Token Policy V2 grant.
An atomic write is permitted only when all of the following agree:
1. socket peer, audience, operation, branch, base and exact path in the
Token Policy V2 grant;
2. service audience, repository identity, branch, operation and exact path
in `AIOS_GITOPS_PATH_POLICY_FILE`;
3. lexical path, resolved containment and symlink checks;
4. the configured content-size and content-profile checks;
5. operation digest, expected branch HEAD and durable operation ledger.
Any failed layer returns a fail-closed policy error. Coarse `/api/file` and
`/api/commit` routes remain forbidden.
## File contract
The configured path must be absolute. The parent directory must be
`root:gitops 0750`; the regular, non-symlink file must be
`root:gitops 0640`. JSON must use UTF-8 canonical encoding with sorted keys,
compact separators and one trailing newline. Unknown fields, unsupported
operations or profiles, duplicate paths, oversized policies and
group/world-writable files are rejected during Writer startup.
Example:
```json
{"allowed_branch":"patch/codex-review-test-worker-20260724","allowed_operations":{"commit_file.atomic":{"content_profile":"systemd-codex-review-worker-v1","exact_paths":["deploy/systemd/aios-codex-review-test-worker.service"],"max_content_bytes":32768}},"audience":"aios-codex-review-worker-writer.service","policy_id":"codex-review-worker-path-policy-v1","repository_identity":"aios/aios","schema_version":1}
```
The SHA-256 of the canonical policy is exposed in the isolated runtime
status and written to the operation audit record. The request body cannot
select or override the policy file.
## Content profile
`systemd-codex-review-worker-v1` is an exact, fail-closed unit grammar. The
only sections are `[Unit]`, `[Service]` and `[Install]`. Each section has a
directive allowlist; every single-value directive and every repeated
`Environment`, `ReadOnlyPaths` and `ReadWritePaths` entry must match the
governed Shadow unit contract exactly.
The profile fixes the Python module
`task_plane.workers.codex_review_test`, `User=aiman`, `Group=gitops`,
the controlled `/usr/libexec/aios-codex-review-test-worker/current`
working directory, all hardening switches and the three permitted
environment variables. It grants read access only to the authoritative
bare repository and the versioned worker artifact, and write access only
to the worker runtime, state and cache directories.
Unknown sections or directives are rejected, including lifecycle hooks,
credential injection, environment imports, root images, bind mounts,
capability expansion, devices, sockets and top-level writable paths. The
parser also rejects duplicate sections, duplicate single-value directives,
empty resets, continuation lines, CRLF, NUL, non-UTF-8 surrogate content,
overlong lines and Unicode lookalike directive names. It does not use
`ConfigParser(strict=False)` or silently merge repeated values.
Production credentials, if later authorized, must be supplied by a
separately governed deployment drop-in. They are not permitted in the
source unit or this content profile.
Policy changes require a separate maintenance branch and Owner-reviewed
ordinary merge commit. A task-scoped Writer must not edit its own policy
file.
+44
View File
@@ -51,6 +51,31 @@ components:
path: {type: string, example: docs/gitops/chatgpt-change.md}
content: {type: string}
message: {type: string}
AtomicFileCommitRequest:
type: object
additionalProperties: false
required: [branch, path, content, message, expected_head_oid, idempotency_key]
properties:
branch:
type: string
pattern: '^patch/[A-Za-z0-9._/-]+$'
path:
type: string
minLength: 1
maxLength: 512
content:
type: string
maxLength: 1048576
message:
type: string
minLength: 1
maxLength: 200
expected_head_oid:
type: string
pattern: '^[0-9a-f]{40}$'
idempotency_key:
type: string
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$'
CommitRequest:
type: object
properties:
@@ -428,6 +453,25 @@ paths:
schema: {$ref: '#/components/schemas/FileCommitRequest'}
responses: {'200': {description: File committed}, '400': {description: Secret rejected or invalid path}, '401': {description: Unauthorized}}
x-openai-isConsequential: true
/api/commit-file:
post:
operationId: commitFileAtomic
summary: Atomically write one allowlisted file, commit, push, and verify using Token Policy V2
security: [{bearerAuth: []}]
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AtomicFileCommitRequest'}
responses:
'200': {description: Completed or idempotently replayed}
'400': {description: Invalid canonical request}
'401': {description: Missing, invalid, expired, or revoked Token Policy V2 grant}
'403': {description: Audience, source, branch, operation, path, or policy denied}
'409': {description: Idempotency conflict or manual review required}
'413': {description: Request too large}
'503': {description: Push or remote verification unavailable; recoverable}
x-openai-isConsequential: true
/api/commit:
post:
operationId: commitChanges
@@ -1,6 +0,0 @@
{
"schema_version": 1,
"task": "codex-review-test-worker",
"writer_role": "isolated-writer",
"status": "READY"
}
@@ -1,36 +0,0 @@
# Codex Read/Review/Test Worker
This package defines a Shadow-only Task Plane worker for allowlisted code reading,
review, Python tests, compile checks, and Task Plane acceptance. It is not a
production execution authorization.
Safety invariants:
- `max_concurrency=1`, heartbeat 15 seconds, claim lease 120 seconds.
- Task Plane endpoint must be explicit loopback HTTP.
- credentials are read only from a regular, non-symlink `0600` file.
- only low-risk `code.review` and `test.execute` tasks with
`production_side_effects=false` and public/internal data are eligible.
- credential-secret, write, deployment, production, arbitrary shell, network,
path traversal, symlink escape, revision expressions, and secret environment
variables are rejected.
- `ResultEnvelope` is canonical-digest-bound and always has
`trust_level=SHADOW_ATTESTED`, `production_trust=false`.
The committed systemd unit is deliberately non-installable and runs only
`--self-check`. Enabling a real Worker or changing any production execution flag
requires a separate Owner approval and a separately bound artifact.
Artifact build:
```bash
python3 scripts/build_codex_review_worker_artifact.py \
--git-dir /data/aios-gitops/repo.git \
--commit <exact-branch-commit> \
--output <new-empty-output-directory>
```
The temporary canary uses `127.0.0.1:18923`, an isolated state root, an ephemeral
credential file, and a no-`.git` source tree. Remove the unit, token, and state
after acceptance. Do not deploy this package to the existing Task Plane Shadow
runtime as part of build/canary acceptance.
@@ -0,0 +1,75 @@
{
"evidence_type": "TWO_STAGE_OWNER_CAMPAIGN_V2_PHASE_A_CANDIDATE",
"generated_at": "2026-07-30T02:35:51Z",
"execution_status": "PARTIALLY_COMPLETED",
"blocking_layer": "PHASE_A_OWNER_EXACT_HEAD_APPROVAL",
"repository": "aios/aios",
"governance_base_oid": "ebd74398743e36523b593fcc395b73945d4924c5",
"governance_tree_oid": "ad1255a1127204fad1d1208d8f31dc94fa64e6e1",
"authority_main_oid": "875d41c3101093149414292067fd700dc214d4d3",
"schema_seed_commit_oid": "8da47545a507cb798d3d6ab30ff8552a2d0a5ecf",
"schema_seed_tree_oid": "991e68577a469657c1c4996814b6634ce5ed752f",
"candidate_source_commit_oid": "a637a9dbb6e0021cb7dcf0d6b0ca00dfe10dce38",
"candidate_source_tree_oid": "bf6e0c16fcad7515465bec4aefdd2e77b1e9bef0",
"candidate_diff_sha256": "c06d002db06da6cbf16f9c8321f1acbfd431f009b5127a13fd2cb5d63b278867",
"candidate_files_sha256": "5061402d516c0e9413208ce64e2b52f77d224e6eec1f7b07c5b3a10b58df5eaf",
"candidate_file_count": 44,
"schema_document_path": "services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json",
"schema_document_sha256": "6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd",
"validator_policy_path": "services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py",
"validator_policy_sha256": "de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac",
"two_stage_policy_schema_sha256": "6b4def7c1eef19c01ef73c43252eb0cd1a87c103e1047249a3cfcc75c7922bf6",
"two_stage_release_schema_sha256": "82ee589dc87db6998ddf0779ce264194cadea0deca66088b0797378f6ce89ad3",
"runtime_observer_sha256": "181e632192f1417a98c1efb35631cf80246759080b2e04243576abcdc7da22af",
"journal_anchor_sha256": "18feb0792b95f1060aa696cc60943379695a246984aecf76098838f9ed37426e",
"package_zip_sha256": "668239a549b4a2b2094fe9b5104b84703fe8ed75011fd8ed71ed3958a6dc0706",
"candidate_bundle_sha256": "15711b225b9ef41cca0588d21b2b95d7a95ac155efc27fcb8772c435fcdab147",
"anchor_install_wheel_sha256": "abbf616366eb3467d4e651bb5306e22ae5e931b613df5362a0892935c4a1c0c7",
"tests": {
"two_stage_campaign": {"passed": 67, "failed": 0, "skipped": 0, "collection_errors": 0},
"single_owner_governance": {"passed": 105, "failed": 0, "subtests_passed": 17, "collection_errors": 0},
"task_scoped_bootstrap": {"passed": 15, "failed": 0, "collection_errors": 0},
"compileall": "PASS",
"quarantine_fsck": "PASS",
"systemd_verify": "PASS_WITH_UNRELATED_HOST_WARNINGS"
},
"anchor": {
"service_status": "active",
"anchor_uid": 988,
"runner_uid": 986,
"uids_distinct": true,
"runner_database_write": "DENIED",
"unauthorized_socket_peer": "DENIED",
"runner_registration_action": "ANCHOR_REQUEST_INVALID",
"journal_mode": "WAL",
"synchronous": "FULL",
"foreign_keys": "ON",
"restart_open_reservation": "PASS",
"selftest_open_reservation_cleanup": "ABORTED"
},
"phase_separation": {
"required_owner_decisions": 2,
"phase_a_authorization": "GITEA_EXACT_HEAD_REVIEW",
"phase_b_authorization": "DETACHED_SSH_SIGNATURE",
"phase_a_release_authority": false,
"one_shot_authority": false
},
"isolation": {
"AIOS_GITOPS_WRITES_ENABLED": false,
"publisher_created": false,
"writer_created": false,
"credential_projection_created": false,
"target_branch_created": false,
"tag_created": false,
"registry_modified": false,
"baseline_modified": false,
"production_modified": false
},
"governance": {
"force_push_used": false,
"tag_rewritten": false,
"direct_main_push": false,
"secrets_committed": false,
"owner_approval_respected": true
}
}
@@ -0,0 +1,44 @@
1f4a83cf91e9aacb6f50bc4fb24d4f745a7a31fd1dd7f2d3d3ed0de05e38234f deploy/systemd/aios-campaign-anchor.service
6b2525d31b8544488bce1544deb39a087cc2d830fb1b16fda26cde6ce430dbd2 deploy/systemd/aios-policy-activation-verification@.service
fad52587775ff5f1c5cc16862c5fb1d910bb097c6b3330c00d75db4f7bef0bbd deploy/systemd/aios-policy-campaign-register@.service
de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py
6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json
5b6d65ae34b2c3bebc1bde8f38c6b0bb73269336d7d4ee5e3416f79c323134d6 services/aios-two-stage-owner-campaign/ANCHOR_REGISTRATION_CONTRACT.md
8ba5278f96447bf4308813b49fcc433d0cc7a5019cd9e78aeb0d8ada5f00d53b services/aios-two-stage-owner-campaign/README.md
7285527358bc8da1d4bc7ff70162dfc3a734086851b734daac89d6f9b330798d services/aios-two-stage-owner-campaign/SECURITY_DELTA_V2.md
89f03fdf156d35807bf39f2f1dbf304c01e7e9ad64399276fb72c68d795eda65 services/aios-two-stage-owner-campaign/STEP_EXECUTOR_CONTRACT.md
7453177223b62509e4854051a75d53f24d8d1f737986f309cc6ae7a2e721459f services/aios-two-stage-owner-campaign/TWO_STAGE_OWNER_INTERACTION_SPEC.md
9308ee245a28a0f0ff623fbfc8e3961204b8e67194bffe536a9c3485ca126ac7 services/aios-two-stage-owner-campaign/examples/allowed_signers.example
9ac7b7fdeb73a99d4f41bf3410ef16f67091d85f9082075287d388e6e5e37eed services/aios-two-stage-owner-campaign/examples/campaign-anchor.env.example
926f0c0cfb7bd6db0ebab6bcb5a0530057b8d38ae1e0b436a69a12b44039462b services/aios-two-stage-owner-campaign/examples/executor-release.example.json
8d46ec9279eb58c03337d41b63de2abdd9eb0d03f98f0806768dcd309d481ee9 services/aios-two-stage-owner-campaign/examples/policy-activation-verification.example.json
b34d8895fe872ef27c62c759449757def698eb05157daff8badd0c86f64ee18c services/aios-two-stage-owner-campaign/examples/release-campaign-manifest.example.json
a2992f493cf0547e1f4acd3fcd9b20e03c912d8b255e196f640d47e291ec9d8e services/aios-two-stage-owner-campaign/examples/runtime-observer-policy.example.json
150c9a8debdcaa4dbb9fd51817ca8710ef805a32f2f96dc5490d0c4f77f2cb6f services/aios-two-stage-owner-campaign/examples/runtime-observer-release.example.json
675b39d13223ad281a4d14a04e739639e470e4e2a2591b85264ba37f840f2b49 services/aios-two-stage-owner-campaign/payload/scripts/generate_diff_chunks.py
5751764275e626c787dad17c2561edd86b2710ae0b3cfeafeec44d98126d9015 services/aios-two-stage-owner-campaign/payload/services/aios-autonomous-control-plane/aios_autonomous_control_plane/lineage_audit.py
2b501bf32a22e1b10c7254d2268d11aa2424aac5756c52441557c25dbaaaa8d5 services/aios-two-stage-owner-campaign/payload/tests/autonomous_control_plane/test_lineage_audit_v3.py
3f118bc7a4f2bdfdd47e2c86112e87f95162dba4d88c1579337bd1d442ec9832 services/aios-two-stage-owner-campaign/pyproject.toml
6b4def7c1eef19c01ef73c43252eb0cd1a87c103e1047249a3cfcc75c7922bf6 services/aios-two-stage-owner-campaign/schemas/governance-policy-activation-verification-v1.schema.json
82ee589dc87db6998ddf0779ce264194cadea0deca66088b0797378f6ce89ad3 services/aios-two-stage-owner-campaign/schemas/task-scoped-release-campaign-v1.schema.json
d04543b5407dcefc0a41af1b8a65ebc2e62f779582ae959449f1ac37b305eecf services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/__init__.py
935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/__main__.py
4e317e2fbf912662bfbf57d2f7fe1a9f7fd3d8c00f7ad09602d9e885ee4ef3cc services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/canonical.py
863be28723553e5bf5df90eda49e96edf8417e765da7b41579f050b04336d480 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/cli.py
dae1e0ed0f841d928a1dd5094c64b1f39b3213301c1da747f45d032a18833c1e services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/errors.py
baf8931566d2c2fb2985d1814b5ded89719bb4b0eba01e94cca9f3690baadeb2 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/executor.py
18feb0792b95f1060aa696cc60943379695a246984aecf76098838f9ed37426e services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/journal_anchor.py
e24765d3c62f9934a921f099e43a002d349a6c9934438da82040e40238070c58 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/orchestrator.py
181e632192f1417a98c1efb35631cf80246759080b2e04243576abcdc7da22af services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/runtime_observer.py
3f3ce81490b6f0893665ba296fc23be904ae0e5dcbcd3b602e25feb2571262b0 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/signature.py
c71d85d5df2ed0e5367de9aacd230f586e77f3b4c11cf52960c84bbdeec43eb7 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/state_machine.py
75ea8ed1c9b49b1ca3ce452fe229524ebd0ccd802945d3362dd668602ce1f98c services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/validator.py
b1be7e1ed0fa0e16e041f77200d651cf46f6bb029c89d31f0b286d32c026cb66 services/aios-two-stage-owner-campaign/tests/test_canonical_snapshot.py
0bb956135c90cf71fcb655c4d700c1f71c3442b9e9fddc376959890cdad823de services/aios-two-stage-owner-campaign/tests/test_executor_v2.py
9bb8a9f1c3bd9aaf44db3dd2f5b810eb0cb650da0e5a5f5e2ea50be46f12664d services/aios-two-stage-owner-campaign/tests/test_lineage_payload.py
681c14ddc0be90f94fd3c3d8a6768fe602ec8acd130ed00a8668505d2db57aa2 services/aios-two-stage-owner-campaign/tests/test_orchestrator_v2.py
9edf44fe0129098c31d66f6b6f7ab252879b425e2844969d09e22c3c88e6b77d services/aios-two-stage-owner-campaign/tests/test_runtime_observer.py
204e77c760380f8e29d10fc0afa4227497109d27493245c55a851de6ff69ac86 services/aios-two-stage-owner-campaign/tests/test_signature.py
9bc5dfa237e6bf37ccc90bbc618a807892d323cdd41345717b296838b44cd22a services/aios-two-stage-owner-campaign/tests/test_state_machine.py
a9ef9c11120f480e0cde3ccbf8a816705621506657d8ac10faf7e38fb54bf367 services/aios-two-stage-owner-campaign/tests/test_validator.py
4ec67865474c6c7ebaa7d125490486e8644618b1666cbde597420e4e6fe8f1d4 tests/single_owner_governance/test_task_scoped_bootstrap.py
@@ -0,0 +1,28 @@
{
"plan_id": "AIOS-BOOTSTRAP-RFC3339-FIX-ROLLBACK-V1",
"schema_version": 1,
"repository": "aios/aios",
"approved_base_oid": "8814dff20222625b60454c613b61ccf15fa20e51",
"governance_history_rewrite_allowed": false,
"steps": [
"stop_uncompleted_task_status_merge_units",
"revoke_exact_task_tokens_and_verify_http_401",
"remove_all_runtime_credential_projections",
"remove_unactivated_runtime_units_and_non_root_task_accounts",
"verify_governance_refs_and_production_refs_unchanged"
],
"internal_token_rotation": {
"rollback_allowed_before_old_secret_revocation": true,
"rollback_source": "root_only_encrypted_runtime_credential",
"rollback_allowed_after_old_secret_revocation": false,
"post_revocation_recovery": "issue_another_replacement_secret_under_new_governed_operation",
"plaintext_secret_in_evidence_allowed": false
},
"required_closure": {
"temporary_accounts_remaining": 0,
"temporary_credentials_remaining": 0,
"credential_projections_remaining": 0,
"old_task_tokens_http_status": 401,
"AIOS_GITOPS_WRITES_ENABLED": false
}
}
@@ -0,0 +1,30 @@
{
"schema_id": "AIOS_BOOTSTRAP_RFC3339_FIX_TEST_SUMMARY",
"schema_version": 1,
"candidate_tree_before_manifest": "c72b13bfe0656de9deeff9652e3e13ada81b110e",
"local_unittest": {
"tests_passed": 19,
"tests_failed": 0,
"tests_skipped": 0
},
"remote_posix": {
"pytest_tests_passed": 19,
"pytest_subtests_passed": 16,
"tests_failed": 0,
"tests_skipped": 0,
"compileall": "PASS",
"json_schema": "PASS",
"systemd_validation": "PASS"
},
"secret_scan": {
"scanner": "gitleaks",
"exact_changed_paths": "PASS",
"exact_changed_path_findings": 0,
"whole_tree_existing_findings": 10,
"whole_tree_findings_claimed_as_new": false
},
"python_executable": {
"path": "/usr/bin/python3.12",
"sha256": "e1efa562c2cc2e35521a5c9c9b9939921001ff8ca9708a13ef15ace68cc2ccd7"
}
}
@@ -0,0 +1,19 @@
{
"schema_id": "AIOS_GOVERNANCE_PR_SUPERSESSION_RECORD_V1",
"recorded_at": "2026-08-01T08:48:25Z",
"repository": "aios/aios",
"pr_number": 39,
"approved_base_oid": "9303a5d684e972bd15fe19f61f721075f4dda8b6",
"approved_head_oid": "52a60a3c419a4a7f70a0af80913532c540ba0a4e",
"approved_tree_oid": "37d64c19f06f75589201a8b6277b13356303f04e",
"manifest_blob_oid": "f970cd1df80dbd4993cd0eb845608899e53b8315",
"manifest_sha256": "d878dc5eaae51f263b5803d36025b37d994602c91d3925430afc1d82acc490cb",
"approval_payload_sha256": "b36a25328cc8ab3810bfd967e87391fb128bc0a4ebf3389914084bceb067cd76",
"premerge_block_receipt_path": "/var/lib/aios-gitops/runtime/task-status-merge/pr39-52a60a3c419a/audit/premerge-contract-block.json",
"premerge_block_receipt_sha256": "5b9a94cf80f3e16e9f47f90d0c0622f0c001d2e582f4891c51d4c572c1f5fe8b",
"marker": "SUPERSEDED_BY_GOVERNANCE_MERGE_CLOSURE_V2",
"pr_head_mutated": false,
"pr_merged": false,
"review_deleted": false,
"block_receipt_deleted": false
}
@@ -0,0 +1,25 @@
{
"schema_id": "AIOS_EXACT_TWO_PARENT_MERGE_BOOTSTRAP_ROLLBACK_V1",
"generated_at": "2026-08-01T08:48:25Z",
"repository": "aios/aios",
"governance_ref": "refs/heads/governance/approvals",
"pre_activation_oid": "9303a5d684e972bd15fe19f61f721075f4dda8b6",
"strategy": "DISABLE_RUNTIME_COMPONENT_WITHOUT_REWRITING_GOVERNANCE_HISTORY",
"steps": [
"stop_and_disable_only_the_exact_two_parent_merge_broker_instance",
"revoke_its_task_scoped_merge_and_audit_credentials",
"remove_only_its_task_scoped_runtime_projection",
"verify_authority_gitea_and_api_governance_refs_remain_equal",
"verify_aios_gitops_writes_enabled_remains_false",
"preserve_the_approved_governance_commit_and_all_audit_receipts"
],
"forbidden": [
"force_push",
"governance_ref_rewind",
"tag_rewrite",
"main_write",
"production_write",
"review_deletion",
"block_receipt_deletion"
]
}
@@ -0,0 +1,43 @@
{
"schema_id": "AIOS_EXACT_TWO_PARENT_MERGE_TEST_SUMMARY_V1",
"generated_at": "2026-08-01T08:48:25Z",
"platform": {
"git": "2.43.0",
"python": "3.12.3",
"system": "Linux x86_64",
"systemd": "255"
},
"results": {
"compileall": "PASS",
"exact_two_parent_and_package_closure_tests": {
"passed": 14,
"failed": 0,
"skipped": 0
},
"task_scoped_release_control_plane_tests": {
"passed": 377,
"failed": 0,
"skipped": 0
},
"json_schema": "PASS",
"systemd_analyze_verify": "PASS",
"systemd_analyze_verify_target": "aios-exact-two-parent-merge-broker@.service",
"systemd_analyze_verify_log_sha256": "c5e82657bcf5d534577181d950a46973f0c47e282b05666e27047fcd61b8058d",
"secret_scan": "PASS",
"git_fsck_connectivity_only": "PASS",
"fault_injection": "PASS",
"deterministic_commit_oid_recalculation": "PASS",
"deterministic_wheel_two_builds": "PASS",
"deterministic_zip_two_builds": "PASS",
"independent_zip_extract_and_manifest_validation": "PASS"
},
"package": {
"revision": "V5R1",
"zip_sha256": "e754e6fb9beeda33a17764e8dc515fbd3a2731a95af77e43af9aaacb38a262b6",
"manifest_sha256": "b5ccbbf7d23191eb09610f30e8062b4febd2344e4525d86b5aeba77d27df0671",
"manifest_entries": 150,
"wheel_sha256": "91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19",
"deployment_definitions_sha256": "b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0"
},
"live_mutation_performed": false
}
@@ -1,20 +0,0 @@
{
"schema_version": 1,
"component": "aios-codex-review-test-worker",
"mode": "SHADOW_ONLY",
"production_trust": false,
"production_execution_authorized": false,
"required_acceptance": [
"exact_commit_artifact",
"no_git_canary",
"worker_registration",
"claim_lease_heartbeat",
"progress",
"result_envelope",
"lease_loss_stops_result",
"unsafe_tasks_rejected",
"secret_scan",
"production_side_effects_false"
],
"runtime_result": "GENERATED_OUTSIDE_GIT_DURING_CANARY"
}
@@ -1,138 +0,0 @@
#!/usr/bin/env python3
"""Build a no-.git, exact-commit Codex review worker artifact."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import re
import shutil
import subprocess
import tarfile
from pathlib import Path
OID_RE = re.compile(r"^[0-9a-f]{40}$")
SECRET_PATTERNS = (
re.compile(rb"Authorization:\s*Bearer\s+[A-Za-z0-9._~+/=-]{16,}", re.I),
re.compile(rb"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----"),
re.compile(rb"(?:ghp|glpat)_[A-Za-z0-9_-]{20,}", re.I),
)
PACKAGE_PATHS = (
"active-runtime/app/task_plane",
"runtime/agent-os",
"tests/task_plane",
"tests/test_isolated_writer_policy.py",
"scripts/task-plane",
"scripts/run_codex_review_worker_acceptance.py",
"scripts/build_codex_review_worker_artifact.py",
"deploy/systemd/aios-codex-review-test-worker.service",
"docs/task-plane",
"reports/codex-review-worker-acceptance.json",
)
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def atomic_json(path: Path, payload: object) -> None:
temporary = path.with_suffix(path.suffix + ".tmp")
with temporary.open("w", encoding="utf-8", newline="\n") as stream:
json.dump(payload, stream, sort_keys=True, separators=(",", ":"))
stream.write("\n")
stream.flush()
os.fsync(stream.fileno())
os.replace(temporary, path)
def git(git_dir: Path, *args: str) -> str:
return subprocess.run(
["git", f"--git-dir={git_dir}", *args], check=True,
capture_output=True, text=True, timeout=60,
env={"PATH": os.environ.get("PATH", "")},
).stdout.strip()
def build(git_dir: Path, commit: str, output: Path) -> dict[str, str]:
commit = git(git_dir, "rev-parse", f"{commit}^{{commit}}")
if not OID_RE.fullmatch(commit):
raise ValueError("exact commit OID required")
tree_oid = git(git_dir, "rev-parse", f"{commit}^{{tree}}")
for required in PACKAGE_PATHS:
probe = subprocess.run(
["git", f"--git-dir={git_dir}", "cat-file", "-e", f"{commit}:{required}"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
if probe.returncode != 0:
raise RuntimeError(f"required artifact path missing: {required}")
if output.exists():
raise FileExistsError("output already exists")
output.mkdir(parents=True, mode=0o700)
source_tar = output / "codex-review-worker-source.tar"
subprocess.run(
[
"git", f"--git-dir={git_dir}", "archive", "--format=tar",
f"--output={source_tar}", commit, "--", *PACKAGE_PATHS,
],
check=True, timeout=120, env={"PATH": os.environ.get("PATH", "")},
)
source = output / "source"
source.mkdir(mode=0o700)
with tarfile.open(source_tar, "r") as archive:
archive.extractall(source, filter="data")
if any(item.name == ".git" for item in source.rglob("*")):
raise RuntimeError("artifact contains Git metadata")
findings = []
for item in sorted(path for path in source.rglob("*") if path.is_file() and path.stat().st_size < 5_000_000):
data = item.read_bytes()
if any(pattern.search(data) for pattern in SECRET_PATTERNS):
findings.append(item.relative_to(source).as_posix())
if findings:
raise RuntimeError("secret scan failed")
tracked = git(
git_dir, "ls-tree", "-r", "--name-only", commit, "--", *PACKAGE_PATHS
).splitlines()
files = [
{"path": name, "sha256": sha256(source / name), "size": (source / name).stat().st_size}
for name in tracked if (source / name).is_file()
]
manifest = {"schema_version": 1, "commit": commit, "tree_oid": tree_oid, "files": files}
atomic_json(output / "manifest.json", manifest)
shutil.copyfile(source_tar, output / "rollback-source.tar")
unit = source / "deploy/systemd/aios-codex-review-test-worker.service"
closure = {
"schema_version": 1,
"commit": commit,
"tree_oid": tree_oid,
"artifact_sha256": sha256(source_tar),
"manifest_sha256": sha256(output / "manifest.json"),
"rollback_artifact_sha256": sha256(output / "rollback-source.tar"),
"systemd_unit_sha256": sha256(unit),
"no_git": True,
"secret_scan": "PASS",
}
atomic_json(output / "package-closure.json", closure)
closure["package_closure_sha256"] = sha256(output / "package-closure.json")
with (output / "checksums.sha256").open("w", encoding="utf-8", newline="\n") as stream:
for item in sorted(path for path in output.iterdir() if path.is_file() and path.name != "checksums.sha256"):
stream.write(f"{sha256(item)} {item.name}\n")
return closure
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--git-dir", required=True, type=Path)
parser.add_argument("--commit", required=True)
parser.add_argument("--output", required=True, type=Path)
args = parser.parse_args()
print(json.dumps(build(args.git_dir.resolve(), args.commit, args.output.resolve()), sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -1,159 +0,0 @@
#!/usr/bin/env python3
"""Run or serve an isolated Codex Worker Shadow canary."""
from __future__ import annotations
import argparse
import hashlib
import hmac
import json
import os
import stat
import sys
import urllib.request
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "active-runtime"))
from app.task_plane.api import TaskPlaneService, run_server
from app.task_plane.policy import IdentityVerifier, PolicyEngine, ReadonlyWorkerProfile
from app.task_plane.store import TaskPlaneStore
from app.task_plane.workers.codex_review_test import (
CodexReviewTaskPolicy,
CodexReviewWorker,
READONLY_CAPABILITIES,
)
from app.task_plane.workers.task_client import CredentialSource, StageAClientConfig, TaskPlaneClient
IDENTITY = "spiffe://aios/agent/codex/review-test-canary"
WORKER_ID = "codex-review-test-canary"
def _token(path: Path) -> str:
info = path.lstat()
if path.is_symlink() or not stat.S_ISREG(info.st_mode) or stat.S_IMODE(info.st_mode) != 0o600:
raise SystemExit("canary credential reference rejected")
value = path.read_text(encoding="utf-8").strip()
if len(value.encode("utf-8")) < 32:
raise SystemExit("canary credential unavailable")
return value
def serve(host: str, port: int, state_root: Path, token_file: Path) -> None:
if host not in {"127.0.0.1", "::1"}:
raise SystemExit("canary must bind loopback")
token = _token(token_file)
profile = ReadonlyWorkerProfile(
worker_id=WORKER_ID, identity=IDENTITY,
capabilities=frozenset(READONLY_CAPABILITIES),
)
policy = PolicyEngine(
identity_verifier=IdentityVerifier({IDENTITY}),
execution_enabled=False,
readonly_worker_execution_enabled=True,
readonly_worker_profiles=[profile],
identity_capabilities={
IDENTITY: {"task.creator", "task.read", "task.audit", "task.claim", "worker.self_register"}
},
)
state_root.mkdir(mode=0o700, parents=True, exist_ok=True)
store = TaskPlaneStore(str(state_root / "task-plane.sqlite3"), high_assurance=True)
service = TaskPlaneService(store, policy=policy)
run_server(host, port, service, authenticator=lambda candidate: IDENTITY if hmac.compare_digest(candidate, token) else None)
def _post(base_url: str, token: str, path: str, payload: dict, key: str | None = None) -> dict:
body = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
if key:
headers["Idempotency-Key"] = key
request = urllib.request.Request(base_url + path, data=body, headers=headers, method="POST")
with urllib.request.urlopen(request, timeout=15) as response:
return json.loads(response.read().decode("utf-8"))
def run(base_url: str, token_file: Path, source_commit: str, report: Path) -> dict:
token = _token(token_file)
task_id = "CODEX-CANARY-" + source_commit[:12]
task = {
"task_id": task_id, "task_type": "code.review", "risk": "low",
"required_capabilities": ["code.read"],
"metadata": {"production_side_effects": False},
"data_classification": "internal", "network_policy": "deny",
"allowed_input_paths": ["active-runtime/app/task_plane"],
"allowed_output_paths": ["reports/canary.json"],
}
_post(base_url, token, "/tasks", task, "codex-canary-create-" + source_commit)
client = TaskPlaneClient(StageAClientConfig(base_url), token)
progress = []
def executor(_task, emit):
emit(25, "CLAIMED")
progress.append(25)
emit(100, "VERIFIED")
progress.append(100)
return "shadow canary completed", [{"kind": "summary", "status": "PASS"}], [{"kind": "test", "sha256": hashlib.sha256(source_commit.encode()).hexdigest()}]
worker = CodexReviewWorker(
client, CodexReviewTaskPolicy(WORKER_ID, IDENTITY), source_commit
)
completed_task = worker.run_once(executor)
task_after = client.get_task(task_id)
unsafe_rejected = 0
for unsafe in (
{"risk": "high", "task_type": "code.review", "metadata": {"production_side_effects": False}},
{"risk": "low", "task_type": "code.review", "metadata": {"production_side_effects": True}},
{"risk": "low", "task_type": "code.review", "metadata": {"production_side_effects": False}, "data_classification": "credential-secret"},
{"risk": "low", "task_type": "code.review", "metadata": {"production_side_effects": False}, "required_capabilities": ["code.write"]},
):
try:
worker.policy.assert_shadow_only_task(unsafe)
except Exception:
unsafe_rejected += 1
checks = {
"worker_registration": "PASS",
"task_claim": "PASS" if completed_task == task_id else "FAIL",
"heartbeat": "PASS",
"progress": "PASS" if progress == [25, 100] else "FAIL",
"result_envelope": "PASS" if task_after.get("status") == "COMPLETED" else "FAIL",
"unsafe_task_rejections": "PASS" if unsafe_rejected == 4 else "FAIL",
"network_endpoint_loopback": "PASS",
"production_side_effects": False,
"git_write_count": 0,
"tag_write_count": 0,
"baseline_write_count": 0,
"registry_write_count": 0,
"deployment_count": 0,
}
result = {
"schema_version": 1, "source_commit": source_commit,
"task_id": task_id, "worker_id": WORKER_ID, "checks": checks,
"passed": not any(value == "FAIL" for value in checks.values()),
}
encoded = (json.dumps(result, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8")
report.write_bytes(encoded)
result["report_sha256"] = hashlib.sha256(encoded).hexdigest()
return result
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--serve-canary", action="store_true")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=18923)
parser.add_argument("--state-root", type=Path)
parser.add_argument("--token-file", required=True, type=Path)
parser.add_argument("--source-commit")
parser.add_argument("--report", type=Path)
args = parser.parse_args()
if args.serve_canary:
serve(args.host, args.port, args.state_root, args.token_file)
return 0
if not args.source_commit or args.report is None:
raise SystemExit("--source-commit and --report are required")
print(json.dumps(run(f"http://{args.host}:{args.port}", args.token_file, args.source_commit, args.report), sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,364 @@
from __future__ import annotations
import argparse
from dataclasses import dataclass
from datetime import datetime, timezone
import hashlib
import hmac
import json
from pathlib import Path
import re
import sqlite3
import subprocess
from typing import Any, Protocol
from .task_status_merge_broker import ALLOWED_CONTEXTS, ALLOWED_IDENTITIES, ContractDenied, GiteaClient, _time, canonical, read_runtime_secret
OID = re.compile(r"^[0-9a-f]{40}$")
SHA256 = re.compile(r"^[0-9a-f]{64}$")
TZ = re.compile(r"^[+-](?:(?:0\d|1[0-3])[0-5]\d|1400)$")
EMAIL = re.compile(r"^[^\s<>@]+@[^\s<>@]+$")
AUTHORITY_REPO = "/data/aios-gitops/repo.git"
GITEA_REPO = "/data/aios-gitops/runtime/gitea-bin/data/repositories/aios/aios.git"
QUARANTINE_ROOT = "/run/aios-exact-two-parent-merge"
SIGNER = "aios-exact-two-parent-merge-grant-signer"
NAMESPACE = "aios-exact-two-parent-merge-grant-v1"
FIELDS = frozenset({
"schema_id", "schema_version", "repository", "target_ref", "merge_mode", "operation_quota", "force",
"pr_number", "expected_old_ref_oid", "approved_pr_head_oid", "approved_pr_tree_oid", "first_parent_oid",
"second_parent_oid", "expected_merge_tree_oid", "expected_merge_commit_oid", "commit_message_utf8",
"commit_message_sha256", "author_name", "author_email", "author_epoch", "author_timezone",
"committer_name", "committer_email", "committer_epoch", "committer_timezone", "manifest_path",
"manifest_blob_oid", "manifest_sha256", "payload_sha256", "status_identity", "merge_identity",
"status_contexts", "status_evidence_sha256", "issued_at", "expires_at", "audit_key_ref",
"grant_signer_identity", "grant_signature_namespace",
})
def _require_oid(value: Any, error: str = "OID_INVALID") -> str:
if not isinstance(value, str) or not OID.fullmatch(value):
raise ContractDenied(error)
return value
def _identity(name: Any, email: Any, epoch: Any, zone: Any, error: str) -> None:
if (not isinstance(name, str) or not name or any(c in name for c in "\r\n\0<>")
or not isinstance(email, str) or not EMAIL.fullmatch(email)
or type(epoch) is not int or epoch < 0 or not isinstance(zone, str) or not TZ.fullmatch(zone)):
raise ContractDenied(error)
@dataclass(frozen=True)
class ExactGrant:
raw: dict[str, Any]
issued_at: datetime
expires_at: datetime
@classmethod
def from_dict(cls, value: dict[str, Any], *, now: datetime | None = None) -> "ExactGrant":
if not isinstance(value, dict) or set(value) != FIELDS:
raise ContractDenied("GRANT_FIELDS_INVALID")
fixed = {
"schema_id": "AIOS_EXACT_TWO_PARENT_MERGE_COMMIT_V1", "schema_version": 1,
"repository": "aios/aios", "target_ref": "refs/heads/governance/approvals",
"merge_mode": "EXACT_TWO_PARENT_COMMIT", "operation_quota": 1, "force": False,
"grant_signer_identity": SIGNER, "grant_signature_namespace": NAMESPACE,
}
if any(value[key] != expected for key, expected in fixed.items()):
raise ContractDenied("FIXED_FIELD_INVALID")
if type(value["pr_number"]) is not int or value["pr_number"] <= 0:
raise ContractDenied("PR_INVALID")
for key in ("expected_old_ref_oid", "approved_pr_head_oid", "approved_pr_tree_oid", "first_parent_oid",
"second_parent_oid", "expected_merge_tree_oid", "expected_merge_commit_oid", "manifest_blob_oid"):
_require_oid(value[key])
if (value["first_parent_oid"] != value["expected_old_ref_oid"]
or value["second_parent_oid"] != value["approved_pr_head_oid"]
or value["expected_merge_tree_oid"] != value["approved_pr_tree_oid"]):
raise ContractDenied("PARENT_OR_TREE_BINDING_INVALID")
message = value["commit_message_utf8"]
if (not isinstance(message, str) or not message or "\0" in message or "\r" in message
or not message.endswith("\n") or message.endswith("\n\n")
or hashlib.sha256(message.encode("utf-8")).hexdigest() != value["commit_message_sha256"]):
raise ContractDenied("COMMIT_MESSAGE_INVALID")
if not isinstance(value["commit_message_sha256"], str) or not SHA256.fullmatch(value["commit_message_sha256"]):
raise ContractDenied("COMMIT_MESSAGE_SHA256_INVALID")
_identity(value["author_name"], value["author_email"], value["author_epoch"], value["author_timezone"], "AUTHOR_INVALID")
_identity(value["committer_name"], value["committer_email"], value["committer_epoch"], value["committer_timezone"], "COMMITTER_INVALID")
if (not isinstance(value["manifest_path"], str) or not re.fullmatch(r"approvals/[A-Za-z0-9._/-]+\.json", value["manifest_path"])
or ".." in value["manifest_path"].split("/")):
raise ContractDenied("MANIFEST_PATH_INVALID")
for key in ("manifest_sha256", "payload_sha256"):
if not isinstance(value[key], str) or not SHA256.fullmatch(value[key]):
raise ContractDenied("SHA256_INVALID")
if value["status_identity"] not in ALLOWED_IDENTITIES or value["merge_identity"] not in ALLOWED_IDENTITIES:
raise ContractDenied("IDENTITY_INVALID")
if set(value["status_contexts"]) != ALLOWED_CONTEXTS or len(value["status_contexts"]) != 5:
raise ContractDenied("STATUS_CONTEXTS_INVALID")
evidence = value["status_evidence_sha256"]
if not isinstance(evidence, dict) or set(evidence) != ALLOWED_CONTEXTS or any(not isinstance(x, str) or not SHA256.fullmatch(x) for x in evidence.values()):
raise ContractDenied("STATUS_EVIDENCE_INVALID")
if not isinstance(value["audit_key_ref"], str) or not re.fullmatch(r"systemd-credential://[A-Za-z0-9_.-]+", value["audit_key_ref"]):
raise ContractDenied("AUDIT_KEY_REFERENCE_INVALID")
issued, expires = _time(value["issued_at"]), _time(value["expires_at"])
current = now or datetime.now(timezone.utc)
if (expires - issued).total_seconds() <= 0 or (expires - issued).total_seconds() > 43200 or current >= expires:
raise ContractDenied("GRANT_EXPIRED_OR_LIFETIME_INVALID")
return cls(dict(value), issued, expires)
@property
def digest(self) -> str:
return hashlib.sha256(canonical(self.raw)).hexdigest()
def commit_payload(self) -> bytes:
v = self.raw
lines = [
f"tree {v['expected_merge_tree_oid']}", f"parent {v['first_parent_oid']}", f"parent {v['second_parent_oid']}",
f"author {v['author_name']} <{v['author_email']}> {v['author_epoch']} {v['author_timezone']}",
f"committer {v['committer_name']} <{v['committer_email']}> {v['committer_epoch']} {v['committer_timezone']}", "",
]
return ("\n".join(lines) + v["commit_message_utf8"]).encode("utf-8")
def calculated_oid(self) -> str:
payload = self.commit_payload()
return hashlib.sha1(b"commit " + str(len(payload)).encode() + b"\0" + payload).hexdigest()
def load_signed_grant(grant_path: Path, signature_path: Path, allowed_signers: Path) -> ExactGrant:
if any(not path.is_absolute() or path.is_symlink() for path in (grant_path, signature_path, allowed_signers)):
raise ContractDenied("GRANT_SIGNATURE_PATH_UNSAFE")
raw = grant_path.read_bytes()
try:
value = json.loads(raw)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ContractDenied("GRANT_JSON_INVALID") from exc
if raw != canonical(value) + b"\n":
raise ContractDenied("GRANT_NOT_CANONICAL")
grant = ExactGrant.from_dict(value)
try:
subprocess.run(["/usr/bin/ssh-keygen", "-Y", "verify", "-f", str(allowed_signers), "-I", SIGNER,
"-n", NAMESPACE, "-s", str(signature_path)], input=raw, check=True,
stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError) as exc:
raise ContractDenied("GRANT_SIGNATURE_INVALID") from exc
return grant
class API(Protocol):
def get(self, path: str) -> Any: ...
class Git(Protocol):
def commit_tree(self, quarantine: Path, tree: str, parents: list[str], message: bytes, env: dict[str, str]) -> str: ...
def verify_commit(self, repository: str, oid: str) -> dict[str, Any]: ...
def tree(self, repository: str, oid: str) -> str: ...
def blob(self, repository: str, commit: str, path: str) -> str: ...
def blob_data(self, repository: str, oid: str) -> bytes: ...
def import_object(self, repository: str, source: Path, oid: str) -> None: ...
def fsck(self, repository: str, oid: str) -> None: ...
def ref(self, repository: str, ref: str) -> str: ...
def update_ref(self, repository: str, ref: str, new: str, old: str) -> None: ...
class SubprocessGit:
"""Production git adapter; every mutating command is object-only or CAS-only."""
def __init__(self, *, gitea_repo: str = GITEA_REPO) -> None:
self.gitea_repo = gitea_repo
def _run(self, arguments: list[str], *, payload: bytes | None = None, env: dict[str, str] | None = None) -> bytes:
try:
return subprocess.run(arguments, input=payload, check=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, env=env).stdout
except (OSError, subprocess.CalledProcessError) as exc:
raise ContractDenied("GIT_OPERATION_FAILED") from exc
def commit_tree(self, quarantine: Path, tree: str, parents: list[str], message: bytes, env: dict[str, str]) -> str:
self._run(["/usr/bin/git", "init", "--bare", str(quarantine)])
environment = {
"PATH": "/usr/bin:/bin",
"LANG": "C",
"LC_ALL": "C",
"GIT_CONFIG_NOSYSTEM": "1",
"GIT_CONFIG_GLOBAL": "/dev/null",
}
environment.update(env)
environment["GIT_ALTERNATE_OBJECT_DIRECTORIES"] = f"{self.gitea_repo}/objects"
oid = self._run(["/usr/bin/git", f"--git-dir={quarantine}", "commit-tree", tree,
"-p", parents[0], "-p", parents[1]], payload=message, env=environment).decode().strip()
return _require_oid(oid, "QUARANTINE_OBJECT_INVALID")
def _git(self, repository: str, *args: str) -> bytes:
return self._run(["/usr/bin/git", f"--git-dir={repository}", *args])
def tree(self, repository: str, oid: str) -> str:
return _require_oid(self._git(repository, "show", "-s", "--format=%T", oid).decode().strip(), "TREE_READBACK_INVALID")
def blob(self, repository: str, commit: str, path: str) -> str:
fields = self._git(repository, "ls-tree", commit, "--", path).decode().split()
if len(fields) < 3 or fields[1] != "blob": raise ContractDenied("MANIFEST_BLOB_BINDING_INVALID")
return _require_oid(fields[2], "MANIFEST_BLOB_BINDING_INVALID")
def blob_data(self, repository: str, oid: str) -> bytes:
return self._git(repository, "cat-file", "blob", oid)
def verify_commit(self, repository: str, oid: str) -> dict[str, Any]:
raw = self._git(repository, "cat-file", "commit", oid).decode("utf-8")
header, message = raw.split("\n\n", 1)
rows = header.splitlines(); parents = [x.removeprefix("parent ") for x in rows if x.startswith("parent ")]
tree = next((x.removeprefix("tree ") for x in rows if x.startswith("tree ")), "")
author = next((x.removeprefix("author ") for x in rows if x.startswith("author ")), "")
committer = next((x.removeprefix("committer ") for x in rows if x.startswith("committer ")), "")
return {"tree": tree, "parents": parents, "author": author, "committer": committer, "message": message}
def import_object(self, repository: str, source: Path, oid: str) -> None:
payload = self._git(str(source), "cat-file", "commit", oid)
observed = self._run(["/usr/bin/git", f"--git-dir={repository}", "hash-object", "-t", "commit", "-w", "--stdin"], payload=payload).decode().strip()
if observed != oid:
raise ContractDenied("OBJECT_IMPORT_OID_MISMATCH")
def fsck(self, repository: str, oid: str) -> None:
self._git(repository, "fsck", "--connectivity-only", oid)
def ref(self, repository: str, ref: str) -> str:
return _require_oid(self._run(["/usr/bin/git", f"--git-dir={repository}", "rev-parse", "--verify", ref]).decode().strip(), "REF_READBACK_INVALID")
def update_ref(self, repository: str, ref: str, new: str, old: str) -> None:
try:
self._run(["/usr/bin/git", f"--git-dir={repository}", "update-ref", ref, new, old])
except ContractDenied as exc:
raise ContractDenied("GOVERNANCE_REF_COMPARE_AND_SWAP_FAILED") from exc
class ExactTwoParentMergeBroker:
def __init__(self, grant: ExactGrant, api: API, git: Git, journal_path: Path,
audit_key: bytes, quarantine_root: Path | None = None):
self.grant, self.api, self.git = grant, api, git
self.journal_path = Path(journal_path)
quarantine_base = Path(quarantine_root) if quarantine_root is not None else Path(QUARANTINE_ROOT)
self.quarantine_root = quarantine_base / grant.digest
if not audit_key: raise ContractDenied("AUDIT_KEY_EMPTY")
self.audit_key = bytes(audit_key)
def _preflight(self, *, reconciling: bool) -> None:
v = self.grant.raw
user = self.api.get("/user")
if not isinstance(user, dict) or user.get("login") != v["merge_identity"]:
raise ContractDenied("MERGE_IDENTITY_INVALID")
pr = self.api.get(f"/repos/aios/aios/pulls/{v['pr_number']}")
reviews = self.api.get(f"/repos/aios/aios/pulls/{v['pr_number']}/reviews")
if (not isinstance(pr, dict) or (pr.get("head") or {}).get("sha") != v["approved_pr_head_oid"]
or (pr.get("base") or {}).get("ref") != "governance/approvals"
or (not reconciling and (pr.get("state") != "open"
or (pr.get("base") or {}).get("sha") != v["expected_old_ref_oid"]
or pr.get("mergeable") is not True))):
raise ContractDenied("PR_BINDING_INVALID")
if self.git.tree(GITEA_REPO, v["approved_pr_head_oid"]) != v["approved_pr_tree_oid"]:
raise ContractDenied("APPROVED_TREE_MISMATCH")
blob = self.git.blob(GITEA_REPO, v["approved_pr_head_oid"], v["manifest_path"])
raw_manifest = self.git.blob_data(GITEA_REPO, blob)
try:
manifest = json.loads(raw_manifest)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ContractDenied("MANIFEST_PAYLOAD_BINDING_INVALID") from exc
if (not isinstance(manifest, dict) or "approval_payload" not in manifest
or blob != v["manifest_blob_oid"] or hashlib.sha256(raw_manifest).hexdigest() != v["manifest_sha256"]
or hashlib.sha256(canonical(manifest["approval_payload"])).hexdigest() != v["payload_sha256"]):
raise ContractDenied("MANIFEST_PAYLOAD_BINDING_INVALID")
owners = [r for r in reviews if isinstance(r, dict) and (r.get("user") or {}).get("id") == 2 and (r.get("user") or {}).get("login") == "owner"] if isinstance(reviews, list) else []
if not owners or any(k not in max(owners, key=lambda r: int(r.get("id") or -1)) for k in ("state", "commit_id")):
raise ContractDenied("OWNER_APPROVAL_INVALID")
review = max(owners, key=lambda r: int(r.get("id") or -1))
if review.get("state") != "APPROVED" or review.get("commit_id") != v["approved_pr_head_oid"] or review.get("official") is not True or review.get("stale") is not False or review.get("dismissed") is not False:
raise ContractDenied("OWNER_APPROVAL_INVALID")
try: submitted = _time(str(review.get("submitted_at") or ""))
except ContractDenied as exc: raise ContractDenied("OWNER_APPROVAL_INVALID") from exc
if submitted < self.grant.issued_at or submitted >= self.grant.expires_at: raise ContractDenied("OWNER_APPROVAL_OUTSIDE_WINDOW")
rows = self.api.get(f"/repos/aios/aios/commits/{v['approved_pr_head_oid']}/statuses")
latest: dict[str, dict[str, Any]] = {}
for row in rows if isinstance(rows, list) else []:
if not isinstance(row, dict) or row.get("context") not in ALLOWED_CONTEXTS: continue
context = row["context"]; key = (str(row.get("created_at") or ""), int(row.get("id") or 0))
if context not in latest or key > (str(latest[context].get("created_at") or ""), int(latest[context].get("id") or 0)): latest[context] = row
if set(latest) != ALLOWED_CONTEXTS or any(r.get("status", r.get("state")) != "success" or r.get("sha") != v["approved_pr_head_oid"] or (r.get("creator") or {}).get("login") != v["status_identity"] or not str(r.get("description") or "").endswith(v["status_evidence_sha256"][c]) for c, r in latest.items()):
raise ContractDenied("STATUS_BINDING_INVALID")
def _journal(self) -> sqlite3.Connection:
db = sqlite3.connect(self.journal_path, isolation_level=None)
if str(db.execute("PRAGMA journal_mode=WAL").fetchone()[0]).lower() != "wal": raise ContractDenied("JOURNAL_MODE_INVALID")
db.execute("PRAGMA synchronous=FULL")
if int(db.execute("PRAGMA synchronous").fetchone()[0]) != 2: raise ContractDenied("JOURNAL_SYNCHRONOUS_INVALID")
db.execute("CREATE TABLE IF NOT EXISTS exact_merge(request_sha256 TEXT PRIMARY KEY, state TEXT NOT NULL, receipt BLOB, previous_hash TEXT, audit_hash TEXT)")
return db
def execute(self) -> dict[str, Any]:
db = self._journal()
try:
row = db.execute("SELECT request_sha256,state,receipt FROM exact_merge").fetchone()
if row:
if row[0] != self.grant.digest: raise ContractDenied("JOURNAL_REQUEST_MISMATCH")
if row[1] == "COMMITTED": return json.loads(row[2])
else:
db.execute("BEGIN IMMEDIATE"); db.execute("INSERT INTO exact_merge(request_sha256,state) VALUES(?, 'RESERVED')", (self.grant.digest,)); db.execute("COMMIT")
payload, expected = self.grant.commit_payload(), self.grant.raw["expected_merge_commit_oid"]
old = self.grant.raw["expected_old_ref_oid"]
observed = {repo: self.git.ref(repo, self.grant.raw["target_ref"]) for repo in (GITEA_REPO, AUTHORITY_REPO)}
if any(value not in {old, expected} for value in observed.values()):
raise ContractDenied("GOVERNANCE_REF_COMPARE_AND_SWAP_FAILED")
self._preflight(reconciling=expected in observed.values())
if self.grant.calculated_oid() != expected:
raise ContractDenied("EXPECTED_COMMIT_OID_MISMATCH")
env = {"GIT_AUTHOR_NAME": self.grant.raw["author_name"], "GIT_AUTHOR_EMAIL": self.grant.raw["author_email"], "GIT_AUTHOR_DATE": f"{self.grant.raw['author_epoch']} {self.grant.raw['author_timezone']}", "GIT_COMMITTER_NAME": self.grant.raw["committer_name"], "GIT_COMMITTER_EMAIL": self.grant.raw["committer_email"], "GIT_COMMITTER_DATE": f"{self.grant.raw['committer_epoch']} {self.grant.raw['committer_timezone']}"}
a = self.git.commit_tree(self.quarantine_root / "a", self.grant.raw["expected_merge_tree_oid"], [old, self.grant.raw["approved_pr_head_oid"]], self.grant.raw["commit_message_utf8"].encode(), env)
b = self.git.commit_tree(self.quarantine_root / "b", self.grant.raw["expected_merge_tree_oid"], [old, self.grant.raw["approved_pr_head_oid"]], self.grant.raw["commit_message_utf8"].encode(), env)
if a != expected or b != expected or a != b:
raise ContractDenied("DETERMINISTIC_COMMIT_MISMATCH")
expected_meta = {"tree": self.grant.raw["expected_merge_tree_oid"], "parents": [old, self.grant.raw["approved_pr_head_oid"]], "author": f"{self.grant.raw['author_name']} <{self.grant.raw['author_email']}> {self.grant.raw['author_epoch']} {self.grant.raw['author_timezone']}", "committer": f"{self.grant.raw['committer_name']} <{self.grant.raw['committer_email']}> {self.grant.raw['committer_epoch']} {self.grant.raw['committer_timezone']}", "message": self.grant.raw["commit_message_utf8"]}
if self.git.verify_commit(str(self.quarantine_root / "a"), a) != expected_meta or self.git.verify_commit(str(self.quarantine_root / "b"), b) != expected_meta: raise ContractDenied("COMMIT_VERIFICATION_INVALID")
for repo in (GITEA_REPO, AUTHORITY_REPO):
self.git.import_object(repo, self.quarantine_root / "a", expected)
if self.git.verify_commit(repo, expected) != expected_meta: raise ContractDenied("IMPORTED_COMMIT_VERIFICATION_INVALID")
self.git.fsck(repo, expected)
new = expected
observed = {repo: self.git.ref(repo, self.grant.raw["target_ref"]) for repo in (GITEA_REPO, AUTHORITY_REPO)}
if any(value not in {old, new} for value in observed.values()):
raise ContractDenied("GOVERNANCE_REF_COMPARE_AND_SWAP_FAILED")
for repo, value in observed.items():
if value == old:
self.git.update_ref(repo, self.grant.raw["target_ref"], new, old)
final = {repo: self.git.ref(repo, self.grant.raw["target_ref"]) for repo in (GITEA_REPO, AUTHORITY_REPO)}
if set(final.values()) != {new}:
raise ContractDenied("CAS_READBACK_INVALID")
branch = self.api.get("/repos/aios/aios/branches/governance%2Fapprovals")
if not isinstance(branch, dict) or (branch.get("commit") or {}).get("id") != new: raise ContractDenied("GITEA_BRANCH_READBACK_INVALID")
receipt = {"schema_id":"AIOS_EXACT_TWO_PARENT_MERGE_CLOSURE_V1","schema_version":1,"status":"PASS","repository":"aios/aios","target_ref":self.grant.raw["target_ref"],"merge_mode":self.grant.raw["merge_mode"],"force":False,"request_sha256":self.grant.digest,"expected_old_ref_oid":old,"approved_pr_head_oid":self.grant.raw["approved_pr_head_oid"],"approved_pr_tree_oid":self.grant.raw["approved_pr_tree_oid"],"merge_commit_oid":expected,"parent_oids":[old,self.grant.raw["approved_pr_head_oid"]],"tree_oid":self.grant.raw["approved_pr_tree_oid"],"commit_message_sha256":self.grant.raw["commit_message_sha256"],"owner_review_exact_head":True,"required_statuses_exact_head":True,"quarantine_reproducibility":"PASS","authority_fsck":"PASS","gitea_fsck":"PASS","authority_ref_oid":final[AUTHORITY_REPO],"gitea_ref_oid":final[GITEA_REPO],"gitea_api_ref_oid":(branch.get("commit") or {}).get("id")}
prior = db.execute("SELECT audit_hash FROM exact_merge WHERE audit_hash IS NOT NULL ORDER BY rowid DESC LIMIT 1").fetchone(); previous = prior[0] if prior else "0" * 64
receipt["audit_chain_hash"] = hashlib.sha256(previous.encode() + canonical(receipt)).hexdigest()
receipt["audit_hmac_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
db.execute("UPDATE exact_merge SET state='COMMITTED',receipt=?,previous_hash=?,audit_hash=? WHERE request_sha256=?", (canonical(receipt), previous, receipt["audit_chain_hash"], self.grant.digest))
return receipt
finally:
db.close()
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="aios-exact-two-parent-merge-broker")
parser.add_argument("--grant", required=True, type=Path)
parser.add_argument("--grant-signature", required=True, type=Path)
parser.add_argument("--allowed-signers", required=True, type=Path)
parser.add_argument("--token", required=True, type=Path)
parser.add_argument("--audit-key", required=True, type=Path)
parser.add_argument("--journal", required=True, type=Path)
parser.add_argument("--quarantine-root", required=True, type=Path)
args = parser.parse_args(argv)
if any(not path.is_absolute() for path in (args.grant, args.grant_signature, args.allowed_signers, args.token, args.audit_key, args.journal, args.quarantine_root)):
raise ContractDenied("CLI_PATH_NOT_ABSOLUTE")
grant = load_signed_grant(args.grant, args.grant_signature, args.allowed_signers)
result = ExactTwoParentMergeBroker(grant, GiteaClient(args.token), SubprocessGit(), args.journal,
read_runtime_secret(args.audit_key), args.quarantine_root).execute()
print(canonical(result).decode("utf-8"))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,238 @@
from __future__ import annotations
import argparse
import hashlib
import hmac
import json
import os
from pathlib import Path
import sqlite3
import subprocess
from datetime import datetime, timezone
import urllib.error
import urllib.request
from .task_status_merge_broker import ContractDenied, TaskGrant, canonical, load_signed_task_grant, read_runtime_secret
GITEA_BIN = Path("/data/aios-gitops/runtime/bin/gitea")
GITEA_CONFIG = Path("/data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini")
GITEA_DB = Path("/data/aios-gitops/runtime/gitea-bin/data/gitea.db")
RUNUSER = Path("/usr/sbin/runuser")
SYSTEMD_CREDS = Path("/usr/bin/systemd-creds")
GIT = Path("/usr/bin/git")
GITEA_REPOSITORY = Path("/data/aios-gitops/runtime/gitea-bin/data/repositories/aios/aios.git")
def _git(*arguments: str, input_bytes: bytes | None = None) -> bytes:
return subprocess.run(
[str(GIT), f"--git-dir={GITEA_REPOSITORY}", *arguments], input=input_bytes,
check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
).stdout
def _verify_local_governance_binding(grant: TaskGrant) -> None:
"""Verify the exact open PR and latest Owner review without issuing a token."""
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
connection.row_factory = sqlite3.Row
try:
pr = connection.execute(
"SELECT pr.head_branch,pr.base_branch,pr.merge_base,pr.has_merged,i.is_closed "
"FROM pull_request pr JOIN issue i ON i.id=pr.issue_id JOIN repository repo ON repo.id=i.repo_id "
"WHERE repo.owner_name='aios' AND repo.lower_name='aios' AND pr.[index]=?",
(grant.raw["pr_number"],),
).fetchone()
review = connection.execute(
"SELECT r.type,r.commit_id,r.official,r.stale,r.dismissed,r.created_unix,u.id,u.lower_name "
"FROM review r JOIN user u ON u.id=r.reviewer_id JOIN issue i ON i.id=r.issue_id "
"JOIN repository repo ON repo.id=i.repo_id "
"WHERE repo.owner_name='aios' AND repo.lower_name='aios' AND i.[index]=? "
"AND u.id=2 AND u.lower_name='owner' ORDER BY r.id DESC LIMIT 1",
(grant.raw["pr_number"],),
).fetchone()
finally:
connection.close()
if pr is None or pr["base_branch"] != "governance/approvals" or pr["merge_base"] != grant.raw["base_oid"] or pr["has_merged"] != 0 or pr["is_closed"] != 0:
raise ContractDenied("LOCAL_PR_BINDING_INVALID")
head = _git("rev-parse", f"refs/heads/{pr['head_branch']}").decode().strip()
base = _git("rev-parse", "refs/heads/governance/approvals").decode().strip()
if head != grant.raw["target_commit"] or base != grant.raw["base_oid"]:
raise ContractDenied("LOCAL_REF_BINDING_INVALID")
if review is None or review["type"] != 1 or review["commit_id"] != head or review["official"] != 1 or review["stale"] != 0 or review["dismissed"] != 0:
raise ContractDenied("LOCAL_OWNER_APPROVAL_MISSING")
submitted = datetime.fromtimestamp(review["created_unix"], tz=timezone.utc)
if submitted < grant.issued_at or submitted >= grant.expires_at:
raise ContractDenied("LOCAL_OWNER_APPROVAL_EXPIRED")
tree = _git("show", "-s", "--format=%T", head).decode().strip()
if tree != grant.raw["approved_tree_oid"]:
raise ContractDenied("APPROVED_TREE_MISMATCH")
entry = _git("ls-tree", head, "--", grant.raw["manifest_path"]).decode().strip().split()
if len(entry) < 3 or entry[1] != "blob" or entry[2] != grant.raw["manifest_blob_oid"]:
raise ContractDenied("MANIFEST_BLOB_BINDING_INVALID")
manifest = _git("cat-file", "blob", grant.raw["manifest_blob_oid"])
if hashlib.sha256(manifest).hexdigest() != grant.raw["manifest_sha256"]:
raise ContractDenied("MANIFEST_SHA256_MISMATCH")
def _safe_absolute(path: Path, expected_parent: Path) -> None:
if not path.is_absolute() or path.is_symlink() or path.parent != expected_parent:
raise ContractDenied("CREDENTIAL_PATH_UNSAFE")
class TaskCredentialBroker:
def __init__(self, grant: TaskGrant, audit_dir: Path, audit_key: bytes):
self.grant = grant
self.audit_key = bytes(audit_key)
if not self.audit_key:
raise ContractDenied("CREDENTIAL_AUDIT_KEY_EMPTY")
self.audit_dir = Path(audit_dir)
if not self.audit_dir.is_absolute() or self.audit_dir.is_symlink():
raise ContractDenied("AUDIT_DIR_UNSAFE")
def provision(self, *, identity: str, token_name: str, encrypted_path: Path) -> dict:
if os.geteuid() != 0:
raise ContractDenied("ROOT_BROKER_REQUIRED")
expected = self.grant.raw["status_identity"] if token_name.endswith("-status") else self.grant.raw["merge_identity"]
if identity != expected or identity not in {"codex", "gpt"}:
raise ContractDenied("IDENTITY_BINDING_INVALID")
prefix = f"pr{self.grant.raw['pr_number']}-{self.grant.raw['target_commit'][:12]}"
if token_name not in {f"{prefix}-status", f"{prefix}-merge"}:
raise ContractDenied("TOKEN_NAME_INVALID")
_safe_absolute(encrypted_path, Path("/run/aios-task-credential-broker"))
if encrypted_path.exists():
raise ContractDenied("CREDENTIAL_PATH_EXISTS")
_verify_local_governance_binding(self.grant)
command = [str(RUNUSER), "-u", "aiman", "--", str(GITEA_BIN), "admin", "user", "generate-access-token", "--config", str(GITEA_CONFIG), "--username", identity, "--token-name", token_name, "--scopes", "write:repository", "--raw"]
issued = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
if len(issued) < 32 or b"\n" in issued or b"\x00" in issued:
raise ContractDenied("ISSUED_TOKEN_INVALID")
subprocess.run([str(SYSTEMD_CREDS), "encrypt", "--name=gitea-token", "-", str(encrypted_path)], input=issued, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
os.chmod(encrypted_path, 0o400)
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
try:
rows = connection.execute("SELECT t.id,u.id FROM access_token t JOIN user u ON u.id=t.uid WHERE u.lower_name=? AND t.name=? AND t.scope='write:repository'", (identity, token_name)).fetchall()
finally:
connection.close()
if len(rows) != 1:
raise ContractDenied("TOKEN_DATABASE_BINDING_MISSING")
row = rows[0]
receipt = {"status": "PASS", "operation": "credential_provision", "identity": identity, "token_name": token_name, "token_id": int(row[0]), "token_uid": int(row[1]), "grant_sha256": self.grant.digest, "credential_ref": f"systemd-credential-encrypted://{encrypted_path.name}"}
return self._audit(receipt)
def revoke(self, *, receipt: dict, encrypted_path: Path) -> dict:
if os.geteuid() != 0:
raise ContractDenied("ROOT_BROKER_REQUIRED")
_safe_absolute(encrypted_path, Path("/run/aios-task-credential-broker"))
self.validate_provision_receipt(receipt, encrypted_path)
decrypted = subprocess.run([str(SYSTEMD_CREDS), "decrypt", str(encrypted_path), "-"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
if len(decrypted) < 32 or b"\n" in decrypted or b"\x00" in decrypted:
raise ContractDenied("PROJECTED_TOKEN_INVALID")
token_header = {"Authorization": "token " + decrypted.decode("utf-8")}
preflight = urllib.request.Request("http://127.0.0.1:3000/api/v1/repos/aios/aios", headers=token_header)
try:
with urllib.request.urlopen(preflight, timeout=10) as response:
if response.status != 200:
raise ContractDenied("TOKEN_PREFLIGHT_STATUS_INVALID")
except urllib.error.HTTPError as exc:
raise ContractDenied(f"TOKEN_PREFLIGHT_FAILED:{exc.code}") from exc
connection = sqlite3.connect(GITEA_DB)
try:
connection.execute("BEGIN IMMEDIATE")
cursor = connection.execute(
"DELETE FROM access_token WHERE id=? AND uid=? AND name=? AND scope='write:repository'",
(receipt["token_id"], receipt["token_uid"], receipt["token_name"]),
)
if cursor.rowcount != 1:
raise ContractDenied("TOKEN_REVOCATION_MISMATCH")
connection.commit()
except Exception:
connection.rollback()
raise
finally:
connection.close()
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
try:
remaining = connection.execute("SELECT COUNT(*) FROM access_token WHERE id=?", (receipt["token_id"],)).fetchone()[0]
finally:
connection.close()
if remaining != 0:
raise ContractDenied("TOKEN_REVOCATION_READBACK_MISMATCH")
request = urllib.request.Request("http://127.0.0.1:3000/api/v1/repos/aios/aios", headers=token_header)
try:
urllib.request.urlopen(request, timeout=10)
raise ContractDenied("REVOKED_TOKEN_STILL_ACCEPTED")
except urllib.error.HTTPError as exc:
if exc.code != 401:
raise ContractDenied("REVOCATION_HTTP_STATUS_INVALID") from exc
encrypted_path.unlink(missing_ok=True)
result = {"status": "PASS", "operation": "credential_revoke", "identity": receipt["identity"], "token_name": receipt["token_name"], "token_id": receipt["token_id"], "grant_sha256": self.grant.digest, "token_rows_remaining": 0, "credential_projection_remaining": False, "old_token_http_status": 401}
return self._audit(result)
def validate_provision_receipt(self, receipt: dict, encrypted_path: Path) -> None:
required = {"status", "operation", "identity", "token_name", "token_id", "token_uid", "grant_sha256", "credential_ref", "audit_sha256", "audit_hmac_signature"}
expected_credential_ref = f"systemd-credential-encrypted://{encrypted_path.name}"
unsigned_receipt = {key: value for key, value in receipt.items() if key not in {"audit_sha256", "audit_hmac_signature"}}
expected_name_prefix = f"pr{self.grant.raw['pr_number']}-{self.grant.raw['target_commit'][:12]}"
if (set(receipt) != required or receipt["status"] != "PASS" or receipt["operation"] != "credential_provision"
or receipt["grant_sha256"] != self.grant.digest or receipt["identity"] not in {self.grant.raw["status_identity"], self.grant.raw["merge_identity"]}
or receipt["token_name"] not in {f"{expected_name_prefix}-status", f"{expected_name_prefix}-merge"}
or receipt["credential_ref"] != expected_credential_ref
or hashlib.sha256(canonical(unsigned_receipt)).hexdigest() != receipt["audit_sha256"]
or not hmac.compare_digest(receipt["audit_hmac_signature"], hmac.new(self.audit_key, canonical(unsigned_receipt), hashlib.sha256).hexdigest())):
raise ContractDenied("PROVISION_RECEIPT_INVALID")
def _audit(self, value: dict) -> dict:
raw = canonical(value)
result = dict(value)
result["audit_sha256"] = hashlib.sha256(raw).hexdigest()
result["audit_hmac_signature"] = hmac.new(self.audit_key, raw, hashlib.sha256).hexdigest()
self.audit_dir.mkdir(mode=0o750, parents=True, exist_ok=True)
destination = self.audit_dir / f"{value['operation']}-{value['token_name']}.json"
descriptor = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0), 0o640)
try:
os.write(descriptor, canonical(result) + b"\n")
os.fsync(descriptor)
finally:
os.close(descriptor)
return result
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="aios-task-credential-broker")
parser.add_argument("--grant", required=True, type=Path)
parser.add_argument("--audit-dir", required=True, type=Path)
parser.add_argument("--operation", choices=("provision", "revoke"))
parser.add_argument("--identity")
parser.add_argument("--token-name")
parser.add_argument("--encrypted-path", type=Path)
parser.add_argument("--receipt", type=Path)
parser.add_argument("--request", type=Path)
parser.add_argument("--grant-signature", required=True, type=Path)
parser.add_argument("--allowed-signers", required=True, type=Path)
parser.add_argument("--audit-key", required=True, type=Path)
args = parser.parse_args(argv)
grant = load_signed_task_grant(args.grant, args.grant_signature, args.allowed_signers)
broker = TaskCredentialBroker(grant, args.audit_dir, read_runtime_secret(args.audit_key))
if args.request is not None:
request = json.loads(args.request.read_text(encoding="utf-8"))
if not isinstance(request, dict) or set(request) not in ({"operation", "identity", "token_name", "encrypted_path"}, {"operation", "identity", "token_name", "encrypted_path", "receipt"}):
raise ContractDenied("CREDENTIAL_REQUEST_INVALID")
args.operation = request["operation"]
args.identity = request["identity"]
args.token_name = request["token_name"]
args.encrypted_path = Path(request["encrypted_path"])
args.receipt = Path(request["receipt"]) if "receipt" in request else None
if args.operation is None or args.identity is None or args.token_name is None or args.encrypted_path is None:
raise ContractDenied("CREDENTIAL_REQUEST_INCOMPLETE")
if args.operation == "provision":
result = broker.provision(identity=args.identity, token_name=args.token_name, encrypted_path=args.encrypted_path)
else:
if args.receipt is None:
raise ContractDenied("RECEIPT_REQUIRED")
result = broker.revoke(receipt=json.loads(args.receipt.read_text(encoding="utf-8")), encrypted_path=args.encrypted_path)
print(json.dumps(result, sort_keys=True, separators=(",", ":")))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,94 @@
from __future__ import annotations
import argparse
from datetime import datetime, timezone
import json
import os
from pathlib import Path
import sqlite3
import subprocess
from .task_credential_broker import SYSTEMD_CREDS, TaskCredentialBroker
from .task_status_merge_broker import ContractDenied, load_signed_task_grant
RUNTIME_ROOT = Path("/var/lib/aios-gitops/runtime/task-status-merge")
CREDENTIAL_ROOT = Path("/run/aios-task-credential-broker")
def _operation_complete(task_dir: Path, token_name: str) -> bool:
if token_name.endswith("-status"):
journal, operation = task_dir / "status-journal" / "journal.sqlite3", "statuses"
elif token_name.endswith("-merge"):
journal, operation = task_dir / "merge-journal" / "journal.sqlite3", "merge"
else:
raise ContractDenied("SWEEPER_TOKEN_NAME_INVALID")
if not journal.is_file() or journal.is_symlink():
return False
connection = sqlite3.connect(f"file:{journal}?mode=ro", uri=True)
try:
row = connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
finally:
connection.close()
return row == ("COMMITTED",)
def sweep(runtime_root: Path, allowed_signers: Path, *, now: datetime | None = None) -> list[dict]:
if os.geteuid() != 0:
raise ContractDenied("ROOT_SWEEPER_REQUIRED")
if runtime_root != RUNTIME_ROOT or runtime_root.is_symlink():
raise ContractDenied("SWEEPER_ROOT_INVALID")
current = now or datetime.now(timezone.utc)
results: list[dict] = []
for task_dir in sorted(runtime_root.iterdir() if runtime_root.exists() else []):
if not task_dir.is_dir() or task_dir.is_symlink():
raise ContractDenied("SWEEPER_TASK_DIR_INVALID")
grant_path, signature_path = task_dir / "grant.json", task_dir / "grant.sig"
if not grant_path.is_file() or not signature_path.is_file():
raise ContractDenied("SWEEPER_GRANT_INCOMPLETE")
grant = load_signed_task_grant(grant_path, signature_path, allowed_signers, now=current, allow_expired=True)
audit_credential = CREDENTIAL_ROOT / f"{task_dir.name}-audit.cred"
if not audit_credential.is_file() or audit_credential.is_symlink():
raise ContractDenied("SWEEPER_TASK_AUDIT_CREDENTIAL_MISSING")
audit_key = subprocess.run(
[str(SYSTEMD_CREDS), "decrypt", str(audit_credential), "-"], check=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
).stdout.strip()
if not audit_key or b"\n" in audit_key or b"\x00" in audit_key:
raise ContractDenied("SWEEPER_TASK_AUDIT_KEY_INVALID")
broker = TaskCredentialBroker(grant, task_dir / "audit", audit_key)
for receipt_path in sorted((task_dir / "audit").glob("credential_provision-*.json")):
if receipt_path.is_symlink():
raise ContractDenied("SWEEPER_RECEIPT_UNSAFE")
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
token_name = str(receipt.get("token_name") or "")
credential_ref = str(receipt.get("credential_ref") or "")
prefix = "systemd-credential-encrypted://"
if not credential_ref.startswith(prefix):
raise ContractDenied("SWEEPER_CREDENTIAL_REF_INVALID")
encrypted_path = CREDENTIAL_ROOT / credential_ref.removeprefix(prefix)
revoked_receipt = task_dir / "audit" / f"credential_revoke-{token_name}.json"
if revoked_receipt.exists():
if encrypted_path.exists():
raise ContractDenied("SWEEPER_REVOKED_PROJECTION_REAPPEARED")
continue
if current < grant.expires_at and not _operation_complete(task_dir, token_name):
continue
if not encrypted_path.is_file() or encrypted_path.is_symlink():
raise ContractDenied("SWEEPER_CREDENTIAL_PROJECTION_MISSING")
results.append(broker.revoke(receipt=receipt, encrypted_path=encrypted_path))
return results
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="aios-task-credential-expiry-sweeper")
parser.add_argument("--runtime-root", required=True, type=Path)
parser.add_argument("--allowed-signers", required=True, type=Path)
args = parser.parse_args(argv)
result = sweep(args.runtime_root, args.allowed_signers)
print(json.dumps({"status": "PASS", "revoked": result}, sort_keys=True, separators=(",", ":")))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,472 @@
from __future__ import annotations
import argparse
from dataclasses import dataclass
from datetime import datetime, timezone
import hashlib
import hmac
import json
import os
from pathlib import Path
import re
import sqlite3
import stat
import subprocess
from typing import Any, Protocol
import urllib.error
import urllib.parse
import urllib.request
ALLOWED_CONTEXTS = frozenset({
"aios/branch-protection",
"aios/evidence-closure",
"aios/secret-scan",
"aios/state-machine",
"aios/validator",
})
ALLOWED_IDENTITIES = frozenset({"codex", "gpt"})
OID = re.compile(r"^[0-9a-f]{40}$")
SHA256 = re.compile(r"^[0-9a-f]{64}$")
SECRET_REF = re.compile(r"^systemd-credential://[A-Za-z0-9_.-]+$")
SUPERSEDED_PR_NUMBER = 36
SUPERSEDED_HEAD_OID = "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"
FIELDS = frozenset({
"schema_id", "schema_version", "repository", "pr_number", "base_oid",
"target_commit", "approved_tree_oid", "manifest_path", "manifest_blob_oid", "manifest_sha256",
"payload_sha256", "status_identity", "merge_identity", "status_contexts",
"status_write_quota", "merge_quota", "merge_method", "branch_push_allowed",
"tag_write_allowed", "main_write_allowed", "registry_write_allowed",
"baseline_write_allowed", "production_write_allowed", "issued_at", "expires_at",
"audit_key_ref", "grant_signer_identity", "grant_signature_namespace",
"status_evidence_sha256", "supersedes_pr_number", "supersedes_head_oid",
"renewal_required", "timestamp_contract", "canonical_timezone",
"raw_timestamp_preserved", "naive_datetime_allowed",
})
RFC3339 = re.compile(
r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$"
)
class ContractDenied(RuntimeError):
pass
def canonical(value: Any) -> bytes:
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
def _time(value: str) -> datetime:
if not isinstance(value, str) or value != value.strip() or not RFC3339.fullmatch(value):
raise ContractDenied("TIMESTAMP_INVALID")
try:
normalized = value[:-1] + "+00:00" if value.endswith("Z") else value
parsed = datetime.fromisoformat(normalized)
except ValueError as exc:
raise ContractDenied("TIMESTAMP_INVALID") from exc
if parsed.tzinfo is None or parsed.utcoffset() is None:
raise ContractDenied("TIMESTAMP_TIMEZONE_REQUIRED")
return parsed.astimezone(timezone.utc)
def _utc_timestamp(value: datetime) -> str:
normalized = value.astimezone(timezone.utc).isoformat()
return normalized[:-6] + "Z" if normalized.endswith("+00:00") else normalized
@dataclass(frozen=True)
class TaskGrant:
raw: dict[str, Any]
issued_at: datetime
expires_at: datetime
@classmethod
def from_dict(cls, value: dict[str, Any], *, now: datetime | None = None,
allow_expired: bool = False) -> "TaskGrant":
if not isinstance(value, dict) or set(value) != FIELDS:
raise ContractDenied("GRANT_FIELDS_INVALID")
if value["schema_id"] != "AIOS_TASK_STATUS_MERGE_GRANT" or value["schema_version"] != 1:
raise ContractDenied("GRANT_SCHEMA_INVALID")
if value["repository"] != "aios/aios" or type(value["pr_number"]) is not int or value["pr_number"] <= 0:
raise ContractDenied("REPOSITORY_OR_PR_MISMATCH")
for field in ("base_oid", "target_commit", "approved_tree_oid", "manifest_blob_oid"):
if not isinstance(value[field], str) or not OID.fullmatch(value[field]):
raise ContractDenied("OID_INVALID")
if not isinstance(value["manifest_path"], str) or not re.fullmatch(r"approvals/[A-Za-z0-9._/-]+\.json", value["manifest_path"]) or ".." in value["manifest_path"].split("/"):
raise ContractDenied("MANIFEST_PATH_INVALID")
for field in ("manifest_sha256", "payload_sha256"):
if not isinstance(value[field], str) or not SHA256.fullmatch(value[field]):
raise ContractDenied("SHA256_INVALID")
evidence = value["status_evidence_sha256"]
if not isinstance(evidence, dict) or set(evidence) != ALLOWED_CONTEXTS or any(not isinstance(item, str) or not SHA256.fullmatch(item) for item in evidence.values()):
raise ContractDenied("STATUS_EVIDENCE_BINDING_INVALID")
if value["supersedes_pr_number"] != SUPERSEDED_PR_NUMBER or value["pr_number"] == SUPERSEDED_PR_NUMBER:
raise ContractDenied("RENEWAL_PR_INVALID")
if value["supersedes_head_oid"] != SUPERSEDED_HEAD_OID or value["supersedes_head_oid"] == value["target_commit"] or value["renewal_required"] is not True:
raise ContractDenied("RENEWAL_BINDING_INVALID")
if value["status_identity"] not in ALLOWED_IDENTITIES or value["merge_identity"] not in ALLOWED_IDENTITIES:
raise ContractDenied("IDENTITY_NOT_ALLOWED")
if set(value["status_contexts"]) != ALLOWED_CONTEXTS or len(value["status_contexts"]) != 5:
raise ContractDenied("STATUS_CONTEXTS_INVALID")
if value["status_write_quota"] != 5 or value["merge_quota"] != 1:
raise ContractDenied("QUOTA_INVALID")
if value["merge_method"] != "fast-forward-only":
raise ContractDenied("MERGE_METHOD_INVALID")
denied = (
"branch_push_allowed", "tag_write_allowed", "main_write_allowed",
"registry_write_allowed", "baseline_write_allowed", "production_write_allowed",
)
if any(value[field] is not False for field in denied):
raise ContractDenied("WRITE_SCOPE_EXPANDED")
if not isinstance(value["audit_key_ref"], str) or not SECRET_REF.fullmatch(value["audit_key_ref"]):
raise ContractDenied("AUDIT_KEY_REFERENCE_INVALID")
if value["grant_signer_identity"] != "aios-task-grant-signer" or value["grant_signature_namespace"] != "aios-task-status-merge-grant-v1":
raise ContractDenied("GRANT_SIGNATURE_POLICY_INVALID")
if (value["timestamp_contract"] != "RFC3339_OFFSET_AWARE_V2"
or value["canonical_timezone"] != "UTC"
or value["raw_timestamp_preserved"] is not True
or value["naive_datetime_allowed"] is not False):
raise ContractDenied("TIMESTAMP_CONTRACT_INVALID")
issued, expires = _time(value["issued_at"]), _time(value["expires_at"])
current = now or datetime.now(timezone.utc)
lifetime = (expires - issued).total_seconds()
if lifetime <= 0 or lifetime > 12 * 3600 or (not allow_expired and current >= expires):
raise ContractDenied("GRANT_EXPIRED_OR_LIFETIME_INVALID")
return cls(dict(value), issued, expires)
@property
def digest(self) -> str:
return hashlib.sha256(canonical(self.raw)).hexdigest()
def load_signed_task_grant(grant_path: Path, signature_path: Path, allowed_signers: Path,
*, now: datetime | None = None, allow_expired: bool = False) -> TaskGrant:
for path in (grant_path, signature_path, allowed_signers):
if not path.is_absolute() or path.is_symlink():
raise ContractDenied("GRANT_SIGNATURE_PATH_UNSAFE")
raw = grant_path.read_bytes()
if len(raw) > 1024 * 1024:
raise ContractDenied("GRANT_TOO_LARGE")
try:
value = json.loads(raw)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ContractDenied("GRANT_JSON_INVALID") from exc
if raw != canonical(value) + b"\n":
raise ContractDenied("GRANT_NOT_CANONICAL")
grant = TaskGrant.from_dict(value, now=now, allow_expired=allow_expired)
command = [
"/usr/bin/ssh-keygen", "-Y", "verify", "-f", str(allowed_signers),
"-I", "aios-task-grant-signer", "-n", "aios-task-status-merge-grant-v1",
"-s", str(signature_path),
]
try:
subprocess.run(command, input=raw, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError) as exc:
raise ContractDenied("GRANT_SIGNATURE_INVALID") from exc
return grant
class API(Protocol):
def get(self, path: str) -> Any: ...
def post(self, path: str, payload: dict[str, Any]) -> Any: ...
def read_runtime_secret(path: Path) -> bytes:
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
descriptor = os.open(path, flags)
try:
metadata = os.fstat(descriptor)
mode = stat.S_IMODE(metadata.st_mode)
credential_directory = os.environ.get("CREDENTIALS_DIRECTORY")
systemd_projection = (
credential_directory is not None
and path.parent == Path(credential_directory)
and mode == 0o440
and metadata.st_uid == 0
and metadata.st_gid == 0
)
if not stat.S_ISREG(metadata.st_mode) or (mode != 0o400 and not systemd_projection):
raise ContractDenied("CREDENTIAL_FILE_UNSAFE")
value = os.read(descriptor, 16 * 1024 + 1)
finally:
os.close(descriptor)
if not value or len(value) > 16 * 1024 or b"\x00" in value or b"\n" in value.strip():
raise ContractDenied("CREDENTIAL_CONTENT_INVALID")
return value.strip()
class _NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
class GiteaClient:
def __init__(self, token_path: Path, api_base: str = "http://127.0.0.1:3000/api/v1"):
parsed = urllib.parse.urlparse(api_base)
if parsed.scheme != "http" or parsed.hostname != "127.0.0.1" or parsed.path.rstrip("/") != "/api/v1" or parsed.username or parsed.password or parsed.query or parsed.fragment:
raise ContractDenied("GITEA_API_ORIGIN_INVALID")
self.token_path = Path(token_path)
self.api_base = api_base.rstrip("/")
self.opener = urllib.request.build_opener(_NoRedirect)
def _request(self, method: str, path: str, payload: dict[str, Any] | None = None) -> Any:
if not path.startswith("/") or ".." in path.split("/"):
raise ContractDenied("GITEA_API_PATH_INVALID")
token = read_runtime_secret(self.token_path).decode("utf-8")
body = canonical(payload) if payload is not None else None
request = urllib.request.Request(self.api_base + path, data=body, method=method, headers={"Authorization": f"token {token}", "Content-Type": "application/json", "Accept": "application/json"})
try:
with self.opener.open(request, timeout=20) as response:
raw = response.read(2 * 1024 * 1024 + 1)
except (urllib.error.URLError, OSError) as exc:
raise ContractDenied(f"GITEA_API_FAILED:{type(exc).__name__}") from exc
if len(raw) > 2 * 1024 * 1024:
raise ContractDenied("GITEA_API_RESPONSE_TOO_LARGE")
return json.loads(raw.decode("utf-8")) if raw else None
def get(self, path: str) -> Any:
return self._request("GET", path)
def post(self, path: str, payload: dict[str, Any]) -> Any:
return self._request("POST", path, payload)
class QuotaJournal:
def __init__(self, path: Path, grant: TaskGrant):
self.path = Path(path)
self.grant = grant
self.connection = sqlite3.connect(self.path, isolation_level=None)
journal_mode = self.connection.execute("PRAGMA journal_mode=WAL").fetchone()
if journal_mode is None or str(journal_mode[0]).lower() != "wal":
raise ContractDenied("JOURNAL_MODE_INVALID")
self.connection.execute("PRAGMA synchronous=FULL")
synchronous = self.connection.execute("PRAGMA synchronous").fetchone()
if synchronous is None or int(synchronous[0]) != 2:
raise ContractDenied("JOURNAL_SYNCHRONOUS_INVALID")
self.connection.execute("CREATE TABLE IF NOT EXISTS quota(operation TEXT PRIMARY KEY, state TEXT NOT NULL, effect_sha256 TEXT)")
self.connection.execute("CREATE TABLE IF NOT EXISTS audit(seq INTEGER PRIMARY KEY AUTOINCREMENT, event BLOB NOT NULL, previous_hash TEXT NOT NULL, event_hash TEXT NOT NULL UNIQUE)")
def close(self) -> None:
self.connection.close()
def reserve(self, operation: str) -> str:
limit = {"statuses": 1, "merge": 1}.get(operation)
if limit is None:
raise ContractDenied("OPERATION_INVALID")
self.connection.execute("BEGIN IMMEDIATE")
try:
row = self.connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
if row and row[0] == "COMMITTED":
raise ContractDenied("STATUS_QUOTA_EXHAUSTED" if operation == "statuses" else "MERGE_QUOTA_EXHAUSTED")
if row and row[0] != "RESERVED":
raise ContractDenied("JOURNAL_STATE_INVALID")
if not row:
self.connection.execute("INSERT INTO quota(operation,state,effect_sha256) VALUES(?,'RESERVED',NULL)", (operation,))
self.connection.execute("COMMIT")
return "RESERVED"
except Exception:
self.connection.execute("ROLLBACK")
raise
def state(self, operation: str) -> str | None:
row = self.connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
return str(row[0]) if row else None
def commit(self, operation: str, effect: dict[str, Any]) -> None:
digest = hashlib.sha256(canonical(effect)).hexdigest()
self.connection.execute("BEGIN IMMEDIATE")
try:
row = self.connection.execute("SELECT state,effect_sha256 FROM quota WHERE operation=?", (operation,)).fetchone()
if row is None or row[0] not in {"RESERVED", "COMMITTED"}:
raise ContractDenied("RESERVATION_MISSING")
if row[0] == "COMMITTED" and row[1] != digest:
raise ContractDenied("COMMITTED_EFFECT_MISMATCH")
self.connection.execute("UPDATE quota SET state='COMMITTED',effect_sha256=? WHERE operation=?", (digest, operation))
self.connection.execute("COMMIT")
except Exception:
self.connection.execute("ROLLBACK")
raise
def append(self, event: dict[str, Any]) -> str:
row = self.connection.execute("SELECT event_hash FROM audit ORDER BY seq DESC LIMIT 1").fetchone()
previous = row[0] if row else "0" * 64
raw = canonical(event)
digest = hashlib.sha256(previous.encode() + raw).hexdigest()
self.connection.execute("INSERT INTO audit(event,previous_hash,event_hash) VALUES(?,?,?)", (raw, previous, digest))
return digest
def verify_chain(self) -> bool:
previous = "0" * 64
for raw, observed_previous, observed_hash in self.connection.execute("SELECT event,previous_hash,event_hash FROM audit ORDER BY seq"):
if observed_previous != previous or hashlib.sha256(previous.encode() + raw).hexdigest() != observed_hash:
return False
previous = observed_hash
return True
def _latest_statuses(values: Any) -> dict[str, dict[str, Any]]:
if not isinstance(values, list):
raise ContractDenied("STATUS_RESPONSE_INVALID")
latest: dict[str, tuple[tuple[str, int], dict[str, Any]]] = {}
for item in values:
if not isinstance(item, dict) or item.get("context") not in ALLOWED_CONTEXTS:
continue
key = (str(item.get("created_at") or ""), int(item.get("id") or 0))
context = item["context"]
if context not in latest or key > latest[context][0]:
latest[context] = (key, item)
return {context: item for context, (_, item) in latest.items()}
def _verify_owner_binding(api: API, grant: TaskGrant) -> tuple[dict[str, Any], dict[str, Any]]:
pr_number = grant.raw["pr_number"]
head, base = grant.raw["target_commit"], grant.raw["base_oid"]
pr = api.get(f"/repos/aios/aios/pulls/{pr_number}")
reviews = api.get(f"/repos/aios/aios/pulls/{pr_number}/reviews")
if not isinstance(pr, dict) or pr.get("state") != "open" or pr.get("mergeable") is not True or (pr.get("head") or {}).get("sha") != head or (pr.get("base") or {}).get("sha") != base or (pr.get("base") or {}).get("ref") != "governance/approvals":
raise ContractDenied("PR_BINDING_INVALID")
if not isinstance(reviews, list):
raise ContractDenied("REVIEW_RESPONSE_INVALID")
owners = [item for item in reviews if isinstance(item, dict) and (item.get("user") or {}).get("login") == "owner" and (item.get("user") or {}).get("id") == 2]
if not owners:
raise ContractDenied("OWNER_EXACT_HEAD_APPROVAL_MISSING")
latest = max(owners, key=lambda item: int(item.get("id") or -1))
if latest.get("state") != "APPROVED" or latest.get("commit_id") != head or latest.get("official") is not True or latest.get("stale") is not False or latest.get("dismissed") is not False:
raise ContractDenied("OWNER_EXACT_HEAD_APPROVAL_MISSING")
raw_timestamp = str(latest.get("submitted_at") or "")
submitted = _time(raw_timestamp)
if submitted < grant.issued_at or submitted >= grant.expires_at:
raise ContractDenied("OWNER_APPROVAL_EXPIRED")
normalized_review = dict(latest)
normalized_review["review_timestamp_raw"] = raw_timestamp
normalized_review["review_timestamp_utc"] = _utc_timestamp(submitted)
return pr, normalized_review
def _signed_receipt(value: dict[str, Any], key: bytes) -> dict[str, Any]:
if not key:
raise ContractDenied("AUDIT_KEY_EMPTY")
result = dict(value)
result["audit_signature"] = hmac.new(key, canonical(value), hashlib.sha256).hexdigest()
return result
class StatusBroker:
def __init__(self, grant: TaskGrant, journal: QuotaJournal, api: API, audit_key: bytes):
self.grant, self.journal, self.api, self.audit_key = grant, journal, api, audit_key
def publish(self, evidence: list[dict[str, Any]]) -> dict[str, Any]:
if not isinstance(evidence, list) or len(evidence) != 5:
raise ContractDenied("EVIDENCE_SET_INVALID")
mapped = {item.get("context"): item for item in evidence if isinstance(item, dict)}
if set(mapped) != ALLOWED_CONTEXTS or any(set(item) != {"context", "evidence_sha256"} or not SHA256.fullmatch(str(item["evidence_sha256"])) or item["evidence_sha256"] != self.grant.raw["status_evidence_sha256"].get(context) for context, item in mapped.items()):
raise ContractDenied("EVIDENCE_SET_INVALID")
_, review = _verify_owner_binding(self.api, self.grant)
self.journal.reserve("statuses")
published = []
head = self.grant.raw["target_commit"]
pr_number = self.grant.raw["pr_number"]
observed_before = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
already = _latest_statuses(observed_before)
already = {context: item for context, item in already.items()
if item.get("status", item.get("state")) == "success"
and item.get("sha", head) == head
and (item.get("creator") or {}).get("login") == self.grant.raw["status_identity"]
and str(item.get("description") or "").endswith(mapped[context]["evidence_sha256"])}
for context in sorted(ALLOWED_CONTEXTS):
digest = mapped[context]["evidence_sha256"]
if context in already:
published.append({"context": context, "evidence_sha256": digest, "status_id": already[context].get("id"), "reconciled": True})
continue
response = self.api.post(f"/repos/aios/aios/statuses/{head}", {
"state": "success", "context": context,
"description": f"task-scoped PASS evidence_sha256={digest}",
"target_url": f"https://g.cnnetmkt.top/git/aios/aios/pulls/{pr_number}",
})
if not isinstance(response, dict) or response.get("context") != context or response.get("status", response.get("state")) != "success":
raise ContractDenied("STATUS_PUBLICATION_FAILED")
published.append({"context": context, "evidence_sha256": digest, "status_id": response.get("id")})
observed = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
latest = _latest_statuses(observed)
if set(latest) != ALLOWED_CONTEXTS or any(
item.get("status", item.get("state")) != "success"
or item.get("sha", head) != head
or (item.get("creator") or {}).get("login") != self.grant.raw["status_identity"]
or not str(item.get("description") or "").endswith(mapped[context]["evidence_sha256"])
for context, item in latest.items()
):
raise ContractDenied("STATUS_READBACK_INVALID")
receipt = {"status": "PASS", "operation": "publish_statuses", "grant_sha256": self.grant.digest, "target_commit": head, "published_count": 5, "published": published, "review_timestamp_raw": review["review_timestamp_raw"], "review_timestamp_utc": review["review_timestamp_utc"]}
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
receipt["audit_chain_hash"] = self.journal.append(receipt)
self.journal.commit("statuses", receipt)
return receipt
class MergeBroker:
def __init__(self, grant: TaskGrant, journal: QuotaJournal, api: API, audit_key: bytes):
self.grant, self.journal, self.api, self.audit_key = grant, journal, api, audit_key
def merge(self) -> dict[str, Any]:
head, base = self.grant.raw["target_commit"], self.grant.raw["base_oid"]
pr_number = self.grant.raw["pr_number"]
pr = self.api.get(f"/repos/aios/aios/pulls/{pr_number}")
if isinstance(pr, dict) and pr.get("merged") is True:
observed_branch = self.api.get("/repos/aios/aios/branches/governance%2Fapprovals")
if pr.get("merge_commit_sha") != head or (observed_branch.get("commit") or {}).get("id") != head or self.journal.state("merge") != "RESERVED":
raise ContractDenied("FAST_FORWARD_RESULT_MISMATCH")
receipt = {"status": "PASS", "operation": "fast_forward_merge", "grant_sha256": self.grant.digest, "pr_number": pr_number, "governance_oid": head, "merge_method": "fast-forward-only", "reconciled": True}
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
receipt["audit_chain_hash"] = self.journal.append(receipt)
self.journal.commit("merge", receipt)
return receipt
pr, review = _verify_owner_binding(self.api, self.grant)
statuses = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
latest = _latest_statuses(statuses)
if set(latest) != ALLOWED_CONTEXTS or any(item.get("status", item.get("state")) != "success" or item.get("sha", head) != head or (item.get("creator") or {}).get("login") != self.grant.raw["status_identity"] or not str(item.get("description") or "").endswith(self.grant.raw["status_evidence_sha256"][context]) for context, item in latest.items()):
raise ContractDenied("MACHINE_STATUS_INVALID")
self.journal.reserve("merge")
self.api.post(f"/repos/aios/aios/pulls/{pr_number}/merge", {"Do": "fast-forward-only", "head_commit_id": head, "force_merge": False, "delete_branch_after_merge": False})
observed_pr = self.api.get(f"/repos/aios/aios/pulls/{pr_number}")
observed_branch = self.api.get("/repos/aios/aios/branches/governance%2Fapprovals")
if observed_pr.get("merged") is not True or observed_pr.get("merge_commit_sha") != head or (observed_branch.get("commit") or {}).get("id") != head:
raise ContractDenied("FAST_FORWARD_RESULT_MISMATCH")
receipt = {"status": "PASS", "operation": "fast_forward_merge", "grant_sha256": self.grant.digest, "pr_number": pr_number, "governance_oid": head, "merge_method": "fast-forward-only", "review_timestamp_raw": review["review_timestamp_raw"], "review_timestamp_utc": review["review_timestamp_utc"]}
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
receipt["audit_chain_hash"] = self.journal.append(receipt)
self.journal.commit("merge", receipt)
return receipt
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="aios-task-status-merge-broker")
parser.add_argument("--mode", required=True, choices=("status", "merge"))
parser.add_argument("--grant", required=True, type=Path)
parser.add_argument("--token", required=True, type=Path)
parser.add_argument("--audit-key", required=True, type=Path)
parser.add_argument("--grant-signature", required=True, type=Path)
parser.add_argument("--allowed-signers", required=True, type=Path)
parser.add_argument("--journal", required=True, type=Path)
parser.add_argument("--evidence", type=Path)
args = parser.parse_args(argv)
grant = load_signed_task_grant(args.grant, args.grant_signature, args.allowed_signers)
journal = QuotaJournal(args.journal, grant)
try:
client = GiteaClient(args.token)
key = read_runtime_secret(args.audit_key)
if args.mode == "status":
if args.evidence is None:
raise ContractDenied("EVIDENCE_REQUIRED")
result = StatusBroker(grant, journal, client, key).publish(json.loads(args.evidence.read_text(encoding="utf-8")))
else:
if args.evidence is not None:
raise ContractDenied("EVIDENCE_FORBIDDEN")
result = MergeBroker(grant, journal, client, key).merge()
print(json.dumps(result, sort_keys=True, separators=(",", ":")))
return 0
finally:
journal.close()
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,69 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "AIOS_EXACT_TWO_PARENT_MERGE_CLOSURE_V1",
"type": "object",
"additionalProperties": false,
"required": [
"schema_id",
"schema_version",
"status",
"repository",
"target_ref",
"merge_mode",
"force",
"request_sha256",
"expected_old_ref_oid",
"approved_pr_head_oid",
"approved_pr_tree_oid",
"merge_commit_oid",
"parent_oids",
"tree_oid",
"commit_message_sha256",
"owner_review_exact_head",
"required_statuses_exact_head",
"quarantine_reproducibility",
"authority_fsck",
"gitea_fsck",
"authority_ref_oid",
"gitea_ref_oid",
"gitea_api_ref_oid",
"audit_chain_hash",
"audit_hmac_signature"
],
"properties": {
"schema_id": {"const": "AIOS_EXACT_TWO_PARENT_MERGE_CLOSURE_V1"},
"schema_version": {"const": 1},
"status": {"const": "PASS"},
"repository": {"const": "aios/aios"},
"target_ref": {"const": "refs/heads/governance/approvals"},
"merge_mode": {"const": "EXACT_TWO_PARENT_COMMIT"},
"force": {"const": false},
"request_sha256": {"$ref": "#/$defs/sha256"},
"expected_old_ref_oid": {"$ref": "#/$defs/oid"},
"approved_pr_head_oid": {"$ref": "#/$defs/oid"},
"approved_pr_tree_oid": {"$ref": "#/$defs/oid"},
"merge_commit_oid": {"$ref": "#/$defs/oid"},
"parent_oids": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {"$ref": "#/$defs/oid"}
},
"tree_oid": {"$ref": "#/$defs/oid"},
"commit_message_sha256": {"$ref": "#/$defs/sha256"},
"owner_review_exact_head": {"const": true},
"required_statuses_exact_head": {"const": true},
"quarantine_reproducibility": {"const": "PASS"},
"authority_fsck": {"const": "PASS"},
"gitea_fsck": {"const": "PASS"},
"authority_ref_oid": {"$ref": "#/$defs/oid"},
"gitea_ref_oid": {"$ref": "#/$defs/oid"},
"gitea_api_ref_oid": {"$ref": "#/$defs/oid"},
"audit_chain_hash": {"$ref": "#/$defs/sha256"},
"audit_hmac_signature": {"$ref": "#/$defs/sha256"}
},
"$defs": {
"oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
}
}
@@ -0,0 +1 @@
{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"AIOS_EXACT_TWO_PARENT_MERGE_COMMIT_V1","type":"object","additionalProperties":false,"required":["schema_id","schema_version","repository","target_ref","merge_mode","operation_quota","force","pr_number","expected_old_ref_oid","approved_pr_head_oid","approved_pr_tree_oid","first_parent_oid","second_parent_oid","expected_merge_tree_oid","expected_merge_commit_oid","commit_message_utf8","commit_message_sha256","author_name","author_email","author_epoch","author_timezone","committer_name","committer_email","committer_epoch","committer_timezone","manifest_path","manifest_blob_oid","manifest_sha256","payload_sha256","status_identity","merge_identity","status_contexts","status_evidence_sha256","issued_at","expires_at","audit_key_ref","grant_signer_identity","grant_signature_namespace"],"properties":{"schema_id":{"const":"AIOS_EXACT_TWO_PARENT_MERGE_COMMIT_V1"},"schema_version":{"const":1},"repository":{"const":"aios/aios"},"target_ref":{"const":"refs/heads/governance/approvals"},"merge_mode":{"const":"EXACT_TWO_PARENT_COMMIT"},"operation_quota":{"const":1},"force":{"const":false},"pr_number":{"type":"integer","minimum":1},"expected_old_ref_oid":{"pattern":"^[0-9a-f]{40}$"},"approved_pr_head_oid":{"pattern":"^[0-9a-f]{40}$"},"approved_pr_tree_oid":{"pattern":"^[0-9a-f]{40}$"},"first_parent_oid":{"pattern":"^[0-9a-f]{40}$"},"second_parent_oid":{"pattern":"^[0-9a-f]{40}$"},"expected_merge_tree_oid":{"pattern":"^[0-9a-f]{40}$"},"expected_merge_commit_oid":{"pattern":"^[0-9a-f]{40}$"},"commit_message_utf8":{"type":"string"},"commit_message_sha256":{"pattern":"^[0-9a-f]{64}$"},"author_epoch":{"type":"integer","minimum":0},"committer_epoch":{"type":"integer","minimum":0},"author_timezone":{"pattern":"^[+-]((0\\d|1[0-3])[0-5]\\d|1400)$"},"committer_timezone":{"pattern":"^[+-]((0\\d|1[0-3])[0-5]\\d|1400)$"},"status_contexts":{"type":"array","minItems":5,"maxItems":5,"uniqueItems":true},"status_evidence_sha256":{"type":"object"},"issued_at":{"type":"string"},"expires_at":{"type":"string"},"grant_signer_identity":{"const":"aios-exact-two-parent-merge-grant-signer"},"grant_signature_namespace":{"const":"aios-exact-two-parent-merge-grant-v1"}}}
@@ -0,0 +1,323 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP",
"title": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP observed approval envelope",
"description": "Versioned fail-closed validation envelope assembled from an immutable request plus observed Owner, Git, machine-gate, runtime, and mirror evidence.",
"x-schema-version": 1,
"x-schema-status": "CANDIDATE",
"type": "object",
"additionalProperties": false,
"required": [
"document_kind",
"request_id",
"schema_id",
"schema_version",
"request_created_at",
"request_expires_at",
"requester_identity",
"repository_identity",
"approval_plan_path",
"approval_plan_blob_oid",
"approval_plan_sha256",
"schema_document_sha256",
"validator_policy_sha256",
"required_machine_contexts",
"governance_base_ref",
"governance_base_oid",
"request_head_ref",
"request_head_oid",
"code_base_ref",
"code_base_oid",
"candidate_commit_oid",
"candidate_parent_oid",
"candidate_tree_oid",
"candidate_diff_sha256",
"candidate_files_sha256",
"target_ref",
"target_initial_state",
"provision_publisher",
"provision_writer",
"provision_credential_projection",
"publisher_identity",
"writer_identity",
"credential_secret_ref",
"publisher_scope",
"writer_scope",
"credential_scope",
"observed_preapproval_operations",
"allowed_operations",
"allowed_operations_sha256",
"denied_operations",
"maximum_operation_count",
"maximum_pr_count",
"maximum_branch_count",
"maximum_commit_count",
"allowed_paths",
"allowed_paths_sha256",
"approved_at",
"expires_at",
"maximum_lifetime_seconds",
"auto_revoke",
"required_human_approvals",
"allowed_human_approvers",
"approved_by",
"owner_review_id",
"owner_review_commit_oid",
"approval_plan_id",
"approval_audit_event_id",
"production_runtime_anchor_change",
"production_writes_enabled",
"tag_operations",
"registry_operations",
"baseline_operations",
"deployment_operations",
"force_push_allowed",
"tag_rewrite_allowed",
"direct_main_push_allowed"
],
"properties": {
"document_kind": {"const": "ENVELOPE"},
"request_id": {"type": "string", "minLength": 3, "maxLength": 192, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]+$"},
"schema_id": {"const": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP"},
"schema_version": {"const": 1},
"request_created_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
"request_expires_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
"requester_identity": {"$ref": "#/$defs/identity"},
"repository_identity": {"const": "aios/aios"},
"approval_plan_path": {"type": "string", "pattern": "^approvals/governance-bootstrap/[A-Za-z0-9._-]+\\.json$"},
"approval_plan_blob_oid": {"$ref": "#/$defs/oid"},
"approval_plan_sha256": {"$ref": "#/$defs/sha256"},
"schema_document_sha256": {"$ref": "#/$defs/sha256"},
"validator_policy_sha256": {"$ref": "#/$defs/sha256"},
"required_machine_contexts": {
"type": "array",
"minItems": 5,
"maxItems": 5,
"uniqueItems": true,
"items": {"enum": [
"governance/authority-mirror",
"governance/fault-injection",
"governance/runtime-isolation",
"governance/schema-contract",
"governance/validator-security"
]}
},
"governance_base_ref": {"const": "refs/heads/governance/approvals"},
"governance_base_oid": {"$ref": "#/$defs/oid"},
"request_head_ref": {"type": "string", "pattern": "^refs/heads/governance/request/[A-Za-z0-9._/-]+$"},
"request_head_oid": {"$ref": "#/$defs/oid"},
"code_base_ref": {"type": "string", "pattern": "^refs/heads/patch/[A-Za-z0-9._/-]+$"},
"code_base_oid": {"$ref": "#/$defs/oid"},
"candidate_commit_oid": {"$ref": "#/$defs/oid"},
"candidate_parent_oid": {"$ref": "#/$defs/oid"},
"candidate_tree_oid": {"$ref": "#/$defs/oid"},
"candidate_diff_sha256": {"$ref": "#/$defs/sha256"},
"candidate_files_sha256": {"$ref": "#/$defs/sha256"},
"target_ref": {"type": "string", "pattern": "^refs/heads/patch/[A-Za-z0-9._/-]+$"},
"target_initial_state": {"const": "ABSENT"},
"provision_publisher": {"const": true},
"provision_writer": {"const": true},
"provision_credential_projection": {"const": true},
"publisher_identity": {"$ref": "#/$defs/identity"},
"writer_identity": {"$ref": "#/$defs/identity"},
"credential_secret_ref": {"type": "string", "pattern": "^(systemd-credential|secret-ref)://[A-Za-z0-9_.-]+$"},
"publisher_scope": {
"type": "object",
"additionalProperties": false,
"required": ["repository", "local_code_write", "administrator"],
"properties": {
"repository": {"const": "aios/aios"},
"local_code_write": {"const": false},
"administrator": {"const": false}
}
},
"writer_scope": {
"type": "object",
"additionalProperties": false,
"required": ["repository", "remote_credentials", "remote_push", "run_as_root"],
"properties": {
"repository": {"const": "aios/aios"},
"remote_credentials": {"const": false},
"remote_push": {"const": false},
"run_as_root": {"const": false}
}
},
"credential_scope": {
"type": "object",
"additionalProperties": false,
"required": [
"provider", "projection", "audience", "writer_visible",
"runtime_anchor_visible", "expires_with_request", "revocation_required",
"post_revoke_http_status"
],
"properties": {
"provider": {"const": "systemd"},
"projection": {"const": "LoadCredential"},
"audience": {"$ref": "#/$defs/identity"},
"writer_visible": {"const": false},
"runtime_anchor_visible": {"const": false},
"expires_with_request": {"const": true},
"revocation_required": {"const": true},
"post_revoke_http_status": {"const": 401}
}
},
"observed_preapproval_operations": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"uniqueItems": true,
"items": {"enum": [
"create_governance_request_branch",
"create_governance_approval_pr"
]}
},
"allowed_operations": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {"enum": [
"provision_task_publisher",
"provision_task_writer",
"provision_task_credential_projection",
"create_approved_code_branch",
"push_approved_code_branch",
"read_remote_refs",
"revoke_task_credentials",
"remove_task_identities"
]}
},
"allowed_operations_sha256": {"$ref": "#/$defs/sha256"},
"denied_operations": {"type": "array", "minItems": 12, "uniqueItems": true, "items": {"type": "string"}},
"maximum_operation_count": {"type": "integer", "minimum": 1, "maximum": 10},
"maximum_pr_count": {"const": 1},
"maximum_branch_count": {"const": 1},
"maximum_commit_count": {"const": 1},
"allowed_paths": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
"allowed_paths_sha256": {"$ref": "#/$defs/sha256"},
"approved_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
"expires_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
"maximum_lifetime_seconds": {"type": "integer", "minimum": 1, "maximum": 43200},
"auto_revoke": {"const": true},
"required_human_approvals": {"const": 1},
"allowed_human_approvers": {"const": ["owner"]},
"approved_by": {"const": "owner"},
"owner_review_id": {"type": "integer", "minimum": 1},
"owner_review_commit_oid": {"$ref": "#/$defs/oid"},
"approval_plan_id": {"type": "string", "minLength": 3, "maxLength": 192},
"approval_audit_event_id": {"type": "string", "minLength": 3, "maxLength": 192},
"production_runtime_anchor_change": {"const": false},
"production_writes_enabled": {"const": false},
"tag_operations": {"const": false},
"registry_operations": {"const": false},
"baseline_operations": {"const": false},
"deployment_operations": {"const": false},
"force_push_allowed": {"const": false},
"tag_rewrite_allowed": {"const": false},
"direct_main_push_allowed": {"const": false}
},
"$defs": {
"plan": {
"type": "object",
"additionalProperties": false,
"required": [
"document_kind", "schema_id", "schema_version", "payload_sha256",
"payload"
],
"properties": {
"document_kind": {"const": "PLAN"},
"schema_id": {"const": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP_PLAN"},
"schema_version": {"const": 1},
"payload_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"payload": {"$ref": "#/$defs/planPayload"}
}
},
"planPayload": {
"type": "object",
"additionalProperties": false,
"required": [
"allowed_human_approvers", "allowed_operations", "allowed_operations_sha256",
"allowed_paths", "allowed_paths_sha256", "approval_plan_id", "approval_plan_path",
"approved_by", "auto_revoke", "baseline_operations", "candidate_commit_oid",
"candidate_diff_sha256", "candidate_files_sha256", "candidate_parent_oid",
"candidate_tree_oid", "code_base_oid", "code_base_ref", "credential_scope",
"credential_secret_ref", "denied_operations", "deployment_operations",
"direct_main_push_allowed", "expires_at", "force_push_allowed",
"governance_base_oid", "governance_base_ref", "maximum_branch_count",
"maximum_commit_count", "maximum_lifetime_seconds", "maximum_operation_count",
"maximum_pr_count", "observed_preapproval_operations",
"production_runtime_anchor_change", "production_writes_enabled",
"provision_credential_projection", "provision_publisher", "provision_writer",
"publisher_identity", "publisher_scope", "registry_operations",
"repository_identity", "request_created_at", "request_expires_at",
"request_head_ref", "request_id", "requester_identity",
"required_human_approvals", "required_machine_contexts",
"schema_document_sha256", "schema_id", "schema_version", "tag_operations",
"tag_rewrite_allowed", "target_initial_state", "target_ref",
"validator_policy_sha256", "writer_identity", "writer_scope"
],
"properties": {
"allowed_human_approvers": {"$ref": "#/properties/allowed_human_approvers"},
"allowed_operations": {"$ref": "#/properties/allowed_operations"},
"allowed_operations_sha256": {"$ref": "#/properties/allowed_operations_sha256"},
"allowed_paths": {"$ref": "#/properties/allowed_paths"},
"allowed_paths_sha256": {"$ref": "#/properties/allowed_paths_sha256"},
"approval_plan_id": {"$ref": "#/properties/approval_plan_id"},
"approval_plan_path": {"$ref": "#/properties/approval_plan_path"},
"approved_by": {"$ref": "#/properties/approved_by"},
"auto_revoke": {"$ref": "#/properties/auto_revoke"},
"baseline_operations": {"$ref": "#/properties/baseline_operations"},
"candidate_commit_oid": {"$ref": "#/properties/candidate_commit_oid"},
"candidate_diff_sha256": {"$ref": "#/properties/candidate_diff_sha256"},
"candidate_files_sha256": {"$ref": "#/properties/candidate_files_sha256"},
"candidate_parent_oid": {"$ref": "#/properties/candidate_parent_oid"},
"candidate_tree_oid": {"$ref": "#/properties/candidate_tree_oid"},
"code_base_oid": {"$ref": "#/properties/code_base_oid"},
"code_base_ref": {"$ref": "#/properties/code_base_ref"},
"credential_scope": {"$ref": "#/properties/credential_scope"},
"credential_secret_ref": {"$ref": "#/properties/credential_secret_ref"},
"denied_operations": {"$ref": "#/properties/denied_operations"},
"deployment_operations": {"$ref": "#/properties/deployment_operations"},
"direct_main_push_allowed": {"$ref": "#/properties/direct_main_push_allowed"},
"expires_at": {"$ref": "#/properties/expires_at"},
"force_push_allowed": {"$ref": "#/properties/force_push_allowed"},
"governance_base_oid": {"$ref": "#/properties/governance_base_oid"},
"governance_base_ref": {"$ref": "#/properties/governance_base_ref"},
"maximum_branch_count": {"$ref": "#/properties/maximum_branch_count"},
"maximum_commit_count": {"$ref": "#/properties/maximum_commit_count"},
"maximum_lifetime_seconds": {"$ref": "#/properties/maximum_lifetime_seconds"},
"maximum_operation_count": {"$ref": "#/properties/maximum_operation_count"},
"maximum_pr_count": {"$ref": "#/properties/maximum_pr_count"},
"observed_preapproval_operations": {"$ref": "#/properties/observed_preapproval_operations"},
"production_runtime_anchor_change": {"$ref": "#/properties/production_runtime_anchor_change"},
"production_writes_enabled": {"$ref": "#/properties/production_writes_enabled"},
"provision_credential_projection": {"$ref": "#/properties/provision_credential_projection"},
"provision_publisher": {"$ref": "#/properties/provision_publisher"},
"provision_writer": {"$ref": "#/properties/provision_writer"},
"publisher_identity": {"$ref": "#/properties/publisher_identity"},
"publisher_scope": {"$ref": "#/properties/publisher_scope"},
"registry_operations": {"$ref": "#/properties/registry_operations"},
"repository_identity": {"$ref": "#/properties/repository_identity"},
"request_created_at": {"$ref": "#/properties/request_created_at"},
"request_expires_at": {"$ref": "#/properties/request_expires_at"},
"request_head_ref": {"$ref": "#/properties/request_head_ref"},
"request_id": {"$ref": "#/properties/request_id"},
"requester_identity": {"$ref": "#/properties/requester_identity"},
"required_human_approvals": {"$ref": "#/properties/required_human_approvals"},
"required_machine_contexts": {"$ref": "#/properties/required_machine_contexts"},
"schema_document_sha256": {"$ref": "#/properties/schema_document_sha256"},
"schema_id": {"$ref": "#/properties/schema_id"},
"schema_version": {"$ref": "#/properties/schema_version"},
"tag_operations": {"$ref": "#/properties/tag_operations"},
"tag_rewrite_allowed": {"$ref": "#/properties/tag_rewrite_allowed"},
"target_initial_state": {"$ref": "#/properties/target_initial_state"},
"target_ref": {"$ref": "#/properties/target_ref"},
"validator_policy_sha256": {"$ref": "#/properties/validator_policy_sha256"},
"writer_identity": {"$ref": "#/properties/writer_identity"},
"writer_scope": {"$ref": "#/properties/writer_scope"}
}
},
"oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"identity": {"type": "string", "minLength": 3, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]+$"}
}
}
@@ -0,0 +1,69 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "AIOS_TASK_STATUS_MERGE_GRANT_V1",
"type": "object",
"additionalProperties": false,
"required": [
"schema_id", "schema_version", "repository", "pr_number", "base_oid",
"target_commit", "approved_tree_oid", "manifest_path", "manifest_blob_oid", "manifest_sha256",
"payload_sha256", "status_identity", "merge_identity", "status_contexts",
"status_write_quota", "merge_quota", "merge_method", "branch_push_allowed",
"tag_write_allowed", "main_write_allowed", "registry_write_allowed",
"baseline_write_allowed", "production_write_allowed", "issued_at", "expires_at",
"audit_key_ref", "grant_signer_identity", "grant_signature_namespace",
"status_evidence_sha256", "supersedes_pr_number", "supersedes_head_oid",
"renewal_required", "timestamp_contract", "canonical_timezone",
"raw_timestamp_preserved", "naive_datetime_allowed"
],
"properties": {
"schema_id": {"const": "AIOS_TASK_STATUS_MERGE_GRANT"},
"schema_version": {"const": 1},
"repository": {"const": "aios/aios"},
"pr_number": {"type": "integer", "minimum": 1},
"base_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"target_commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"approved_tree_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"manifest_path": {"type": "string", "pattern": "^approvals/[A-Za-z0-9._/-]+\\.json$"},
"manifest_blob_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"manifest_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"payload_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"status_evidence_sha256": {
"type": "object", "additionalProperties": false,
"required": ["aios/branch-protection", "aios/evidence-closure", "aios/secret-scan", "aios/state-machine", "aios/validator"],
"properties": {
"aios/branch-protection": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"aios/evidence-closure": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"aios/secret-scan": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"aios/state-machine": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
"aios/validator": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
}
},
"supersedes_pr_number": {"const": 36},
"supersedes_head_oid": {"const": "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"},
"renewal_required": {"const": true},
"timestamp_contract": {"const": "RFC3339_OFFSET_AWARE_V2"},
"canonical_timezone": {"const": "UTC"},
"raw_timestamp_preserved": {"const": true},
"naive_datetime_allowed": {"const": false},
"status_identity": {"enum": ["codex", "gpt"]},
"merge_identity": {"enum": ["codex", "gpt"]},
"status_contexts": {
"type": "array", "minItems": 5, "maxItems": 5, "uniqueItems": true,
"items": {"enum": ["aios/branch-protection", "aios/evidence-closure", "aios/secret-scan", "aios/state-machine", "aios/validator"]}
},
"status_write_quota": {"const": 5},
"merge_quota": {"const": 1},
"merge_method": {"const": "fast-forward-only"},
"branch_push_allowed": {"const": false},
"tag_write_allowed": {"const": false},
"main_write_allowed": {"const": false},
"registry_write_allowed": {"const": false},
"baseline_write_allowed": {"const": false},
"production_write_allowed": {"const": false},
"issued_at": {"type": "string", "format": "date-time"},
"expires_at": {"type": "string", "format": "date-time"},
"audit_key_ref": {"type": "string", "pattern": "^systemd-credential://[A-Za-z0-9_.-]+$"},
"grant_signer_identity": {"const": "aios-task-grant-signer"},
"grant_signature_namespace": {"const": "aios-task-status-merge-grant-v1"}
}
}
@@ -0,0 +1,93 @@
from __future__ import annotations
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[2]
import sys
sys.path.insert(0, str(ROOT / "tools"))
from build_v5r1_package import ( # noqa: E402
PackageClosureError,
build_deterministic_zip,
validate_package,
write_manifest,
)
class V5R1PackageBuilderTests(unittest.TestCase):
def setUp(self) -> None:
self.temporary = tempfile.TemporaryDirectory()
self.root = Path(self.temporary.name) / "AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1"
self.root.mkdir()
(self.root / "payload.txt").write_text("fixed payload\n", encoding="utf-8", newline="\n")
(self.root / "PACKAGE_COMPONENTS.json").write_text(
json.dumps(
{
"package_zip_sha256_source": "EXTERNAL_SIDECAR",
"wheel_sha256": "1" * 64,
"deployment_definitions_sha256": "2" * 64,
},
sort_keys=True,
separators=(",", ":"),
)
+ "\n",
encoding="utf-8",
newline="\n",
)
def tearDown(self) -> None:
self.temporary.cleanup()
def test_two_independent_archives_are_byte_identical_and_sidecar_matches(self) -> None:
write_manifest(self.root)
first = self.root.parent / "first.zip"
second = self.root.parent / "second.zip"
first_sidecar = self.root.parent / "first-SHA256.txt"
second_sidecar = self.root.parent / "second-SHA256.txt"
first_digest = build_deterministic_zip(self.root, first, first_sidecar)
second_digest = build_deterministic_zip(self.root, second, second_sidecar)
self.assertEqual(first.read_bytes(), second.read_bytes())
self.assertEqual(first_digest, hashlib.sha256(first.read_bytes()).hexdigest())
self.assertEqual(second_digest, first_digest)
self.assertEqual(first_sidecar.read_text(encoding="ascii"), f"{first_digest} first.zip\n")
self.assertEqual(second_sidecar.read_text(encoding="ascii"), f"{first_digest} second.zip\n")
def test_manifest_covers_every_other_file_but_never_itself(self) -> None:
write_manifest(self.root)
lines = (self.root / "MANIFEST.sha256").read_text(encoding="ascii").splitlines()
paths = [line.split(" ", 1)[1] for line in lines]
self.assertEqual(paths, sorted(paths, key=lambda value: value.encode("utf-8")))
self.assertEqual(paths, ["PACKAGE_COMPONENTS.json", "payload.txt"])
self.assertNotIn("MANIFEST.sha256", paths)
validate_package(self.root)
def test_formal_declarations_reject_self_reference_and_stale_placeholders(self) -> None:
cases = [
{"package_zip_sha256": "3" * 64},
{"package_zip_sha256_source": "EXTERNAL_AFTER_PACKAGING"},
{"package_zip_sha256_source": "EXTERNAL_SIDECAR", "wheel_sha256": "0" * 64},
{"package_zip_sha256_source": "EXTERNAL_SIDECAR", "marker": "EXAMPLE-NOT-AUTHORIZATION"},
]
for replacement in cases:
with self.subTest(replacement=replacement):
document = dict(replacement)
document.setdefault("wheel_sha256", "1" * 64)
document.setdefault("deployment_definitions_sha256", "2" * 64)
(self.root / "PACKAGE_COMPONENTS.json").write_text(
json.dumps(document, sort_keys=True, separators=(",", ":")) + "\n",
encoding="utf-8",
newline="\n",
)
write_manifest(self.root)
with self.assertRaises(PackageClosureError):
validate_package(self.root)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,104 @@
from __future__ import annotations
from datetime import datetime, timedelta, timezone
import hashlib
from pathlib import Path
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "services" / "aios-single-owner-governance"))
from aios_single_owner_governance.exact_two_parent_merge_broker import ( # noqa: E402
AUTHORITY_REPO, GITEA_REPO, ContractDenied, ExactGrant, ExactTwoParentMergeBroker,
)
OLD, HEAD, TREE = "a" * 40, "b" * 40, "c" * 40
CONTEXTS = ["aios/branch-protection", "aios/evidence-closure", "aios/secret-scan", "aios/state-machine", "aios/validator"]
def grant() -> dict:
now = datetime.now(timezone.utc).replace(microsecond=0)
raw=b'{"approval_payload":{"phase":"B"},"other":true}\n'; raw_digest=hashlib.sha256(raw).hexdigest(); payload_digest=hashlib.sha256(b'{"phase":"B"}').hexdigest(); value = {"schema_id":"AIOS_EXACT_TWO_PARENT_MERGE_COMMIT_V1","schema_version":1,"repository":"aios/aios","target_ref":"refs/heads/governance/approvals","merge_mode":"EXACT_TWO_PARENT_COMMIT","operation_quota":1,"force":False,"pr_number":39,"expected_old_ref_oid":OLD,"approved_pr_head_oid":HEAD,"approved_pr_tree_oid":TREE,"first_parent_oid":OLD,"second_parent_oid":HEAD,"expected_merge_tree_oid":TREE,"expected_merge_commit_oid":"0"*40,"commit_message_utf8":"merge approved PR 39\n","commit_message_sha256":"","author_name":"AIOS","author_email":"aios@example.test","author_epoch":1,"author_timezone":"+0000","committer_name":"AIOS","committer_email":"aios@example.test","committer_epoch":1,"committer_timezone":"+0000","manifest_path":"approvals/manifest.json","manifest_blob_oid":"d"*40,"manifest_sha256":raw_digest,"payload_sha256":payload_digest,"status_identity":"codex","merge_identity":"gpt","status_contexts":CONTEXTS,"status_evidence_sha256":{c:"3"*64 for c in CONTEXTS},"issued_at":now.isoformat().replace("+00:00","Z"),"expires_at":(now+timedelta(hours=1)).isoformat().replace("+00:00","Z"),"audit_key_ref":"systemd-credential://audit","grant_signer_identity":"aios-exact-two-parent-merge-grant-signer","grant_signature_namespace":"aios-exact-two-parent-merge-grant-v1"}
value["commit_message_sha256"] = hashlib.sha256(value["commit_message_utf8"].encode()).hexdigest()
provisional = ExactGrant.from_dict(value)
value["expected_merge_commit_oid"] = provisional.calculated_oid()
return value
class API:
def __init__(self): self.base, self.head, self.tree, self.review = OLD, HEAD, TREE, HEAD; self.statuses = True; self.branch = HEAD; self.review_time=None; self.status_rows=None; self.login="gpt"; self.state="open"; self.mergeable=True
def get(self, path):
if path == "/user": return {"login":self.login}
if path.endswith("/reviews"): return [{"id":1,"state":"APPROVED","commit_id":self.review,"official":True,"stale":False,"dismissed":False,"submitted_at":self.review_time or datetime.now(timezone.utc).isoformat().replace("+00:00","Z"),"user":{"id":2,"login":"owner"}}]
if "branches/" in path: return {"commit":{"id":self.branch}}
if path.endswith("/statuses"): return self.status_rows if self.status_rows is not None else ([{"context":c,"status":"success","sha":HEAD,"creator":{"login":"codex"},"description":"x"+"3"*64,"created_at":"2026-01-01T00:00:00Z","id":1} for c in CONTEXTS] if self.statuses else [])
return {"state":self.state,"mergeable":self.mergeable,"head":{"sha":self.head,"repo":{"tree_oid":self.tree}},"base":{"sha":self.base,"ref":"governance/approvals"}}
class Git:
def __init__(self, oid): self.oid=oid; self.refs={GITEA_REPO:OLD,AUTHORITY_REPO:OLD}; self.parents=[]
def commit_tree(self, q, tree, parents, message, env): self.tree_value=tree; self.parents=parents; self.message=message.decode(); self.env=env; return self.oid
def verify_commit(self, repo, oid): return {"tree":self.tree_value,"parents":self.parents,"author":f"AIOS <aios@example.test> 1 +0000","committer":f"AIOS <aios@example.test> 1 +0000","message":self.message}
def tree(self, repo, oid): return TREE
def blob(self, repo, commit, path): return "d"*40
def blob_data(self, repo, oid): return b'{"approval_payload":{"phase":"B"},"other":true}\n'
def import_object(self, repo, source, oid): pass
def fsck(self, repo, oid): pass
def ref(self, repo, ref): return self.refs[repo]
def update_ref(self, repo, ref, new, old):
if self.refs[repo] != old: raise AssertionError("CAS")
self.refs[repo]=new
class Tests(unittest.TestCase):
def test_latest_status_window_manifest_branch_and_unknown_ref_fail_closed(self):
item=ExactGrant.from_dict(grant())
cases=[]
api=API(); api.review_time=item.expires_at.isoformat().replace("+00:00","Z"); cases.append((api,Git(item.raw["expected_merge_commit_oid"])))
api=API(); api.status_rows=[{"context":c,"status":"success","sha":HEAD,"creator":{"login":"codex"},"description":"bad","created_at":"2026-02-01T00:00:00Z","id":2} for c in CONTEXTS]; cases.append((api,Git(item.raw["expected_merge_commit_oid"])))
api=API(); api.branch="f"*40; cases.append((api,Git(item.raw["expected_merge_commit_oid"])))
api=API(); api.login="codex"; cases.append((api,Git(item.raw["expected_merge_commit_oid"])))
api=API(); git=Git(item.raw["expected_merge_commit_oid"]); git.refs[GITEA_REPO]="e"*40; cases.append((api,git))
for api, git in cases:
with self.subTest(api=api), tempfile.TemporaryDirectory() as d, self.assertRaises(ContractDenied): ExactTwoParentMergeBroker(item,api,git,Path(d)/"j",b"audit").execute()
def test_commit_bytes_fix_order_count_tree_message_and_identities(self):
item=ExactGrant.from_dict(grant()); payload=item.commit_payload().decode()
self.assertEqual(payload.split("\n")[:3],[f"tree {TREE}",f"parent {OLD}",f"parent {HEAD}"])
self.assertEqual(payload.count("parent "),2)
self.assertTrue(payload.endswith("merge approved PR 39\n"))
for key, value in [("author_epoch",-1),("committer_epoch","1"),("author_email","x@@y"),("committer_name","x\r")]:
changed=grant(); changed[key]=value
with self.subTest(key=key), self.assertRaises(ContractDenied): ExactGrant.from_dict(changed)
def test_fixed_fields_and_all_grant_negative_classes(self):
for key, bad in [("first_parent_oid",HEAD),("second_parent_oid",OLD),("expected_merge_tree_oid",OLD),("target_ref","refs/heads/main"),("operation_quota",2),("commit_message_utf8","bad"),("author_timezone","UTC"),("author_name","bad\n"),("status_contexts",CONTEXTS[:4])]:
v=grant(); v[key]=bad
if key == "commit_message_utf8": v["commit_message_sha256"]=hashlib.sha256(bad.encode()).hexdigest()
with self.subTest(key=key), self.assertRaises(ContractDenied): ExactGrant.from_dict(v)
def test_expected_oid_and_preflight_negative_cases(self):
v=grant(); v["expected_merge_commit_oid"]="f"*40
with self.assertRaises(ContractDenied): ExactGrant.from_dict(v) if False else ExactTwoParentMergeBroker(ExactGrant.from_dict(v),API(),Git("f"*40),Path(tempfile.mktemp()),b"audit").execute()
for attr, value in [("base","e"*40),("head","e"*40),("tree","e"*40),("review","e"*40),("statuses",False)]:
item=ExactGrant.from_dict(grant()); api=API(); setattr(api,attr,value)
with self.subTest(attr=attr), tempfile.TemporaryDirectory() as d, self.assertRaises(ContractDenied): ExactTwoParentMergeBroker(item,api,Git(item.raw["expected_merge_commit_oid"]),Path(d)/"j",b"audit").execute()
def test_same_request_replays_and_different_request_fails(self):
item=ExactGrant.from_dict(grant()); git=Git(item.raw["expected_merge_commit_oid"])
with tempfile.TemporaryDirectory() as d:
path=Path(d)/"j"; api=API(); api.branch=item.raw["expected_merge_commit_oid"]; broker=ExactTwoParentMergeBroker(item,api,git,path,b"audit"); first=broker.execute(); self.assertEqual(first,broker.execute())
changed=grant(); changed["pr_number"]=40; changed["expected_merge_commit_oid"]=ExactGrant.from_dict(changed).calculated_oid()
with self.assertRaisesRegex(ContractDenied,"JOURNAL_REQUEST_MISMATCH"): ExactTwoParentMergeBroker(ExactGrant.from_dict(changed),API(),Git(changed["expected_merge_commit_oid"]),path,b"audit").execute()
def test_partial_old_new_reconciles_only_remaining_cas(self):
item=ExactGrant.from_dict(grant()); git=Git(item.raw["expected_merge_commit_oid"]); git.refs[GITEA_REPO]=item.raw["expected_merge_commit_oid"]
with tempfile.TemporaryDirectory() as d:
api=API(); api.branch=item.raw["expected_merge_commit_oid"]; api.base=item.raw["expected_merge_commit_oid"]; api.state="closed"; api.mergeable=False
self.assertEqual(ExactTwoParentMergeBroker(item,api,git,Path(d)/"j",b"audit").execute()["status"],"PASS")
def test_task_scoped_quarantine_and_explicit_cas_failure(self):
item=ExactGrant.from_dict(grant())
with tempfile.TemporaryDirectory() as d:
root=Path(d)
first=ExactTwoParentMergeBroker(item,API(),Git(item.raw["expected_merge_commit_oid"]),root/"j1",b"audit",root/"instance-a")
second=ExactTwoParentMergeBroker(item,API(),Git(item.raw["expected_merge_commit_oid"]),root/"j2",b"audit",root/"instance-b")
self.assertNotEqual(first.quarantine_root,second.quarantine_root)
self.assertEqual(first.quarantine_root.name,item.digest)
drift=Git(item.raw["expected_merge_commit_oid"]); drift.refs[AUTHORITY_REPO]="e"*40
with self.assertRaisesRegex(ContractDenied,"GOVERNANCE_REF_COMPARE_AND_SWAP_FAILED"):
ExactTwoParentMergeBroker(item,API(),drift,root/"j3",b"audit",root/"instance-c").execute()
if __name__ == "__main__": unittest.main()
@@ -0,0 +1,81 @@
from __future__ import annotations
import json
from pathlib import Path
import unittest
import jsonschema
ROOT = Path(__file__).resolve().parents[2]
SCHEMA_PATH = (
ROOT
/ "services"
/ "aios-single-owner-governance"
/ "exact-two-parent-merge-closure-v1.schema.json"
)
def valid_closure() -> dict:
old = "a" * 40
head = "b" * 40
tree = "c" * 40
merge = "d" * 40
return {
"schema_id": "AIOS_EXACT_TWO_PARENT_MERGE_CLOSURE_V1",
"schema_version": 1,
"status": "PASS",
"repository": "aios/aios",
"target_ref": "refs/heads/governance/approvals",
"merge_mode": "EXACT_TWO_PARENT_COMMIT",
"force": False,
"request_sha256": "1" * 64,
"expected_old_ref_oid": old,
"approved_pr_head_oid": head,
"approved_pr_tree_oid": tree,
"merge_commit_oid": merge,
"parent_oids": [old, head],
"tree_oid": tree,
"commit_message_sha256": "2" * 64,
"owner_review_exact_head": True,
"required_statuses_exact_head": True,
"quarantine_reproducibility": "PASS",
"authority_fsck": "PASS",
"gitea_fsck": "PASS",
"authority_ref_oid": merge,
"gitea_ref_oid": merge,
"gitea_api_ref_oid": merge,
"audit_chain_hash": "3" * 64,
"audit_hmac_signature": "4" * 64,
}
class ExactTwoParentMergeClosureSchemaTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.schema = json.loads(SCHEMA_PATH.read_text(encoding="utf-8"))
jsonschema.Draft202012Validator.check_schema(cls.schema)
cls.validator = jsonschema.Draft202012Validator(cls.schema)
def test_valid_exact_closure_passes(self) -> None:
self.validator.validate(valid_closure())
def test_shape_and_scope_expansion_fail_closed(self) -> None:
mutations = {
"one_parent": ("parent_oids", ["a" * 40]),
"three_parents": ("parent_oids", ["a" * 40, "b" * 40, "e" * 40]),
"main_ref": ("target_ref", "refs/heads/main"),
"force": ("force", True),
"unverified_owner": ("owner_review_exact_head", False),
"unverified_status": ("required_statuses_exact_head", False),
"failed_fsck": ("authority_fsck", "FAIL"),
}
for name, (field, value) in mutations.items():
with self.subTest(name=name):
document = valid_closure()
document[field] = value
self.assertTrue(list(self.validator.iter_errors(document)))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,77 @@
from __future__ import annotations
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "services" / "aios-single-owner-governance"))
from aios_single_owner_governance.exact_two_parent_merge_broker import SubprocessGit # noqa: E402
@unittest.skipUnless(os.name == "posix" and Path("/usr/bin/git").is_file(), "POSIX Git integration")
class ExactTwoParentMergePosixTests(unittest.TestCase):
def _git(self, repository: Path, *arguments: str, payload: bytes | None = None, env=None) -> str:
return subprocess.run(
["/usr/bin/git", f"--git-dir={repository}", *arguments],
input=payload,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
).stdout.decode().strip()
def test_real_git_build_import_fsck_and_exact_cas(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
gitea, authority = root / "gitea.git", root / "authority.git"
subprocess.run(["/usr/bin/git", "init", "--bare", str(gitea)], check=True, stdout=subprocess.DEVNULL)
subprocess.run(["/usr/bin/git", "init", "--bare", str(authority)], check=True, stdout=subprocess.DEVNULL)
tree = self._git(gitea, "mktree", payload=b"")
identity = {
**os.environ,
"GIT_AUTHOR_NAME": "AIOS Test",
"GIT_AUTHOR_EMAIL": "test@aios.invalid",
"GIT_AUTHOR_DATE": "1785542400 +0000",
"GIT_COMMITTER_NAME": "AIOS Test",
"GIT_COMMITTER_EMAIL": "test@aios.invalid",
"GIT_COMMITTER_DATE": "1785542400 +0000",
}
base = self._git(gitea, "commit-tree", tree, payload=b"base\n", env=identity)
head = self._git(gitea, "commit-tree", tree, "-p", base, payload=b"head\n", env=identity)
for repository in (gitea, authority):
if repository == authority:
subprocess.run(
["/usr/bin/git", f"--git-dir={repository}", "fetch", "--no-tags", "--no-write-fetch-head", f"file://{gitea}", head],
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
)
self._git(repository, "update-ref", "refs/heads/governance/approvals", base)
adapter = SubprocessGit(gitea_repo=str(gitea))
fixed = {
"GIT_AUTHOR_NAME": "AIOS Merge",
"GIT_AUTHOR_EMAIL": "merge@aios.invalid",
"GIT_AUTHOR_DATE": "1785546000 +0000",
"GIT_COMMITTER_NAME": "AIOS Merge",
"GIT_COMMITTER_EMAIL": "merge@aios.invalid",
"GIT_COMMITTER_DATE": "1785546000 +0000",
}
first = adapter.commit_tree(root / "q1.git", tree, [base, head], b"exact merge\n", fixed)
second = adapter.commit_tree(root / "q2.git", tree, [base, head], b"exact merge\n", fixed)
self.assertEqual(first, second)
self.assertEqual(adapter.verify_commit(str(root / "q1.git"), first)["parents"], [base, head])
for repository in (gitea, authority):
adapter.import_object(str(repository), root / "q1.git", first)
adapter.fsck(str(repository), first)
adapter.update_ref(str(repository), "refs/heads/governance/approvals", first, base)
self.assertEqual(adapter.ref(str(repository), "refs/heads/governance/approvals"), first)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,39 @@
from __future__ import annotations
from pathlib import Path
import unittest
ROOT = Path(__file__).resolve().parents[2]
UNIT = ROOT / "deploy" / "systemd" / "aios-exact-two-parent-merge-broker@.service"
class ExactTwoParentMergeSystemdTests(unittest.TestCase):
def test_unit_is_single_purpose_and_keeps_global_writes_disabled(self) -> None:
raw = UNIT.read_text(encoding="utf-8")
required = (
"User=root",
"Environment=AIOS_GITOPS_WRITES_ENABLED=false",
"aios_single_owner_governance.exact_two_parent_merge_broker",
"--grant /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/grant.json",
"--grant-signature /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/grant.sig",
"--journal /var/lib/aios-gitops/runtime/exact-two-parent-merge/%i/journal/journal.sqlite3",
"--quarantine-root /run/aios-exact-two-parent-merge/%i",
"ReadWritePaths=/data/aios-gitops/repo.git",
"ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data/repositories/aios/aios.git",
"ReadWritePaths=/run/aios-exact-two-parent-merge/%i",
"IPAddressDeny=any",
"IPAddressAllow=localhost",
"NoNewPrivileges=true",
)
for value in required:
with self.subTest(value=value):
self.assertIn(value, raw)
forbidden = ("AIOS_GITOPS_WRITES_ENABLED=true", "--force", "refs/heads/main", "refs/tags/")
for value in forbidden:
with self.subTest(forbidden=value):
self.assertNotIn(value, raw)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,440 @@
from __future__ import annotations
from datetime import datetime, timedelta, timezone
import json
from pathlib import Path
import sys
import subprocess
import tempfile
import unittest
from unittest import mock
import urllib.error
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "services" / "aios-single-owner-governance"))
from aios_single_owner_governance.task_status_merge_broker import ( # noqa: E402
ALLOWED_CONTEXTS,
ContractDenied,
MergeBroker,
QuotaJournal,
StatusBroker,
TaskGrant,
_time,
_utc_timestamp,
canonical,
load_signed_task_grant,
read_runtime_secret,
)
from aios_single_owner_governance.task_credential_broker import TaskCredentialBroker # noqa: E402
from aios_single_owner_governance import task_credential_expiry_sweeper as sweeper # noqa: E402
HEAD = "d" * 40
OLD_HEAD = "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"
BASE = "8814dff20222625b60454c613b61ccf15fa20e51"
def grant() -> dict:
now = datetime.now(timezone.utc).replace(microsecond=0)
value = {
"schema_id": "AIOS_TASK_STATUS_MERGE_GRANT",
"schema_version": 1,
"repository": "aios/aios",
"pr_number": 36,
"base_oid": BASE,
"target_commit": HEAD,
"approved_tree_oid": "3649be2dac8fcea3a79cb1604b2cfb63f6cc0307",
"manifest_path": "approvals/release-campaign/AIOS-V2R1C4-PHASE-B-RENEWAL.json",
"manifest_blob_oid": "d6e4431992e4315799c7f0487f2b12a20d0e2890",
"manifest_sha256": "2555c5e37f77f1d0aac51864733b55ee3e91169ae76bf67e8817de6d1874eea4",
"payload_sha256": "4db7d3fd5aaa00a65eabfce7501f275b5f6c8a2587b6153fa8066ec0dafa5d6d",
"status_evidence_sha256": {context: "1" * 64 for context in ALLOWED_CONTEXTS},
"supersedes_pr_number": 36,
"supersedes_head_oid": OLD_HEAD,
"renewal_required": True,
"timestamp_contract": "RFC3339_OFFSET_AWARE_V2",
"canonical_timezone": "UTC",
"raw_timestamp_preserved": True,
"naive_datetime_allowed": False,
"status_identity": "codex",
"merge_identity": "codex",
"status_contexts": sorted(ALLOWED_CONTEXTS),
"status_write_quota": 5,
"merge_quota": 1,
"merge_method": "fast-forward-only",
"branch_push_allowed": False,
"tag_write_allowed": False,
"main_write_allowed": False,
"registry_write_allowed": False,
"baseline_write_allowed": False,
"production_write_allowed": False,
"issued_at": now.isoformat().replace("+00:00", "Z"),
"expires_at": (now + timedelta(hours=1)).isoformat().replace("+00:00", "Z"),
"audit_key_ref": "systemd-credential://task-audit-hmac",
"grant_signer_identity": "aios-task-grant-signer",
"grant_signature_namespace": "aios-task-status-merge-grant-v1",
}
value["pr_number"] = 37
return value
class FakeAPI:
def __init__(self, *, with_statuses: bool = False, fail_status_after: int | None = None,
fail_after_merge: bool = False, review_timestamp: str | None = None,
reviewer: str = "owner", review_commit: str = HEAD):
self.posts: list[tuple[str, dict]] = []
self.merged = False
self.status_rows = [{"id": index + 1, "context": value, "status": "success", "sha": HEAD,
"description": "task-scoped PASS evidence_sha256=" + "1" * 64,
"creator": {"login": "codex"}} for index, value in enumerate(ALLOWED_CONTEXTS)] if with_statuses else []
self.fail_status_after = fail_status_after
self.fail_after_merge = fail_after_merge
self.base = BASE
self.review_timestamp = review_timestamp or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
self.reviewer = reviewer
self.review_commit = review_commit
def get(self, path: str):
if path.endswith("/reviews"):
return [{
"id": 76,
"state": "APPROVED",
"commit_id": self.review_commit,
"official": True,
"stale": False,
"dismissed": False,
"submitted_at": self.review_timestamp,
"user": {"id": 2 if self.reviewer == "owner" else 42, "login": self.reviewer},
}]
if path.endswith("/statuses"):
return list(self.status_rows)
if path.endswith("/branches/governance%2Fapprovals"):
return {"name": "governance/approvals", "commit": {"id": HEAD if self.merged else BASE}}
if path.endswith("/pulls/37"):
return {
"number": 37,
"state": "closed" if self.merged else "open",
"merged": self.merged,
"mergeable": True,
"head": {"sha": HEAD},
"base": {"sha": self.base, "ref": "governance/approvals"},
"merge_commit_sha": HEAD if self.merged else None,
}
raise AssertionError(path)
def post(self, path: str, payload: dict):
self.posts.append((path, payload))
if path.endswith("/merge"):
assert payload == {
"Do": "fast-forward-only",
"head_commit_id": HEAD,
"force_merge": False,
"delete_branch_after_merge": False,
}
self.merged = True
if self.fail_after_merge:
raise ContractDenied("SIMULATED_POST_MERGE_LOSS")
return {"merged": True}
if self.fail_status_after is not None and len(self.status_rows) >= self.fail_status_after:
raise ContractDenied("SIMULATED_STATUS_FAILURE")
row = {"id": len(self.posts), "context": payload["context"], "status": "success", "sha": HEAD,
"description": payload["description"],
"creator": {"login": "codex"}}
self.status_rows.append(row)
return row
def evidence() -> list[dict]:
return [{"context": value, "evidence_sha256": "1" * 64} for value in sorted(ALLOWED_CONTEXTS)]
class TaskStatusMergeBrokerTests(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory()
self.root = Path(self.temporary.name)
self.journals: list[QuotaJournal] = []
def tearDown(self):
for journal in self.journals:
journal.close()
self.temporary.cleanup()
def journal(self, item: TaskGrant) -> QuotaJournal:
value = QuotaJournal(self.root / "journal.sqlite3", item)
self.journals.append(value)
return value
def test_status_broker_publishes_exact_five_and_quota_is_single_use(self):
item = TaskGrant.from_dict(grant())
api = FakeAPI()
journal = self.journal(item)
receipt = StatusBroker(item, journal, api, b"audit-key").publish(evidence())
self.assertEqual(receipt["status"], "PASS")
self.assertEqual(receipt["published_count"], 5)
self.assertEqual({entry[1]["context"] for entry in api.posts}, ALLOWED_CONTEXTS)
with self.assertRaisesRegex(ContractDenied, "STATUS_QUOTA_EXHAUSTED"):
StatusBroker(item, journal, api, b"audit-key").publish(evidence())
def test_rfc3339_offset_parser_normalizes_to_utc(self):
cases = {
"2026-08-01T02:03:02Z": "2026-08-01T02:03:02Z",
"2026-08-01T10:03:02+08:00": "2026-08-01T02:03:02Z",
"2026-07-31T18:03:02-08:00": "2026-08-01T02:03:02Z",
"2026-08-01T10:03:02.123456+08:00": "2026-08-01T02:03:02.123456Z",
}
for raw, expected in cases.items():
with self.subTest(raw=raw):
self.assertEqual(_utc_timestamp(_time(raw)), expected)
def test_rfc3339_offset_parser_rejects_ambiguous_or_invalid_values(self):
invalid = [
"2026-08-01T10:03:02", "2026-08-01", "2026-08-01T10:03:02+0800",
"2026-08-01T10:03:02+25:00", "2026-08-01T10:03:02z",
" 2026-08-01T10:03:02+08:00", "2026-08-01T10:03:02+08:00 ",
None, 1, [],
]
for raw in invalid:
with self.subTest(raw=raw):
with self.assertRaisesRegex(ContractDenied, "TIMESTAMP_INVALID"):
_time(raw) # type: ignore[arg-type]
def test_offset_review_preserves_raw_and_canonical_utc_in_receipt(self):
value = grant()
value["issued_at"] = "2026-08-01T00:00:00Z"
value["expires_at"] = "2026-08-01T12:00:00Z"
item = TaskGrant.from_dict(value, now=datetime(2026, 8, 1, 3, tzinfo=timezone.utc))
api = FakeAPI(review_timestamp="2026-08-01T10:03:02+08:00")
receipt = StatusBroker(item, self.journal(item), api, b"audit-key").publish(evidence())
self.assertEqual(receipt["review_timestamp_raw"], "2026-08-01T10:03:02+08:00")
self.assertEqual(receipt["review_timestamp_utc"], "2026-08-01T02:03:02Z")
def test_review_expiry_boundary_is_fail_closed(self):
value = grant()
value["issued_at"] = "2026-08-01T00:00:00Z"
value["expires_at"] = "2026-08-01T02:03:02Z"
item = TaskGrant.from_dict(value, now=datetime(2026, 8, 1, 1, tzinfo=timezone.utc))
for raw in ("2026-08-01T02:03:02Z", "2026-08-01T02:03:03Z"):
with self.subTest(raw=raw), self.assertRaisesRegex(ContractDenied, "OWNER_APPROVAL_EXPIRED"):
StatusBroker(item, self.journal(item), FakeAPI(review_timestamp=raw), b"audit-key").publish(evidence())
def test_wrong_reviewer_and_reviewed_head_remain_rejected(self):
item = TaskGrant.from_dict(grant())
for api in (FakeAPI(reviewer="codex"), FakeAPI(review_commit="e" * 40)):
with self.assertRaisesRegex(ContractDenied, "OWNER_EXACT_HEAD_APPROVAL_MISSING"):
StatusBroker(item, self.journal(item), api, b"audit-key").publish(evidence())
def test_merge_broker_uses_fast_forward_only_and_binds_exact_head(self):
item = TaskGrant.from_dict(grant())
api = FakeAPI(with_statuses=True)
journal = self.journal(item)
receipt = MergeBroker(item, journal, api, b"audit-key").merge()
self.assertEqual(receipt["status"], "PASS")
self.assertEqual(receipt["governance_oid"], HEAD)
self.assertTrue(api.merged)
with self.assertRaisesRegex(ContractDenied, "MERGE_QUOTA_EXHAUSTED"):
MergeBroker(item, journal, FakeAPI(with_statuses=True), b"audit-key").merge()
def test_contract_rejects_scope_expansion_secret_and_wrong_identity(self):
value = grant()
value["main_write_allowed"] = True
with self.assertRaisesRegex(ContractDenied, "WRITE_SCOPE_EXPANDED"):
TaskGrant.from_dict(value)
def test_unbound_evidence_fails_closed(self):
item = TaskGrant.from_dict(grant())
changed = evidence()
changed[0]["evidence_sha256"] = "2" * 64
with self.assertRaisesRegex(ContractDenied, "EVIDENCE_SET_INVALID"):
StatusBroker(item, self.journal(item), FakeAPI(), b"audit-key").publish(changed)
def test_grant_requires_detached_asymmetric_signature(self):
grant_path = self.root / "grant.json"
signature_path = self.root / "grant.sig"
allowed_signers = self.root / "allowed_signers"
raw = canonical(grant()) + b"\n"
grant_path.write_bytes(raw)
signature_path.write_text("ssh-signature", encoding="utf-8")
allowed_signers.write_text("aios-task-grant-signer ssh-ed25519 AAAA", encoding="utf-8")
with mock.patch("aios_single_owner_governance.task_status_merge_broker.subprocess.run") as runner:
item = load_signed_task_grant(grant_path, signature_path, allowed_signers)
self.assertEqual(item.raw["pr_number"], 37)
self.assertEqual(runner.call_args.kwargs["input"], raw)
with mock.patch(
"aios_single_owner_governance.task_status_merge_broker.subprocess.run",
side_effect=subprocess.CalledProcessError(255, ["ssh-keygen"]),
):
with self.assertRaisesRegex(ContractDenied, "GRANT_SIGNATURE_INVALID"):
load_signed_task_grant(grant_path, signature_path, allowed_signers)
def test_base_movement_blocks_status_publication_before_side_effect(self):
item = TaskGrant.from_dict(grant())
api = FakeAPI()
api.base = "c" * 40
with self.assertRaisesRegex(ContractDenied, "PR_BINDING_INVALID"):
StatusBroker(item, self.journal(item), api, b"audit-key").publish(evidence())
self.assertEqual(api.posts, [])
def test_credential_provision_rechecks_local_owner_and_refs_before_issuance(self):
item = TaskGrant.from_dict(grant())
broker = TaskCredentialBroker(item, self.root / "audit", b"audit-key")
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=0, create=True), \
mock.patch("aios_single_owner_governance.task_credential_broker._safe_absolute"), \
mock.patch("aios_single_owner_governance.task_credential_broker._verify_local_governance_binding", side_effect=ContractDenied("LOCAL_OWNER_APPROVAL_MISSING")), \
mock.patch("aios_single_owner_governance.task_credential_broker.subprocess.run") as runner:
with self.assertRaisesRegex(ContractDenied, "LOCAL_OWNER_APPROVAL_MISSING"):
broker.provision(
identity="codex",
token_name="pr37-dddddddddddd-status",
encrypted_path=Path("/run/aios-task-credential-broker/status.cred"),
)
runner.assert_not_called()
value = grant()
value["status_identity"] = "gitops-bot"
with self.assertRaisesRegex(ContractDenied, "IDENTITY_NOT_ALLOWED"):
TaskGrant.from_dict(value)
def test_systemd_credential_projection_mode_and_name_are_supported_exactly(self):
metadata = mock.Mock(st_mode=0o100440, st_uid=0, st_gid=0)
credential = Path("/run/credentials/unit/gitea-token")
with mock.patch.dict("os.environ", {"CREDENTIALS_DIRECTORY": str(credential.parent)}), \
mock.patch("aios_single_owner_governance.task_status_merge_broker.os.open", return_value=7), \
mock.patch("aios_single_owner_governance.task_status_merge_broker.os.fstat", return_value=metadata), \
mock.patch("aios_single_owner_governance.task_status_merge_broker.os.read", return_value=b"x" * 40), \
mock.patch("aios_single_owner_governance.task_status_merge_broker.os.close"):
self.assertEqual(read_runtime_secret(credential), b"x" * 40)
item = TaskGrant.from_dict(grant())
broker = TaskCredentialBroker(item, self.root / "provision-audit", b"audit-key")
connection = mock.MagicMock()
connection.execute.return_value.fetchall.return_value = [(101, 42)]
issued = mock.Mock(stdout=b"x" * 40)
encrypted = mock.Mock(stdout=b"")
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=0, create=True), \
mock.patch("aios_single_owner_governance.task_credential_broker._safe_absolute"), \
mock.patch("aios_single_owner_governance.task_credential_broker._verify_local_governance_binding"), \
mock.patch("aios_single_owner_governance.task_credential_broker.os.chmod"), \
mock.patch("aios_single_owner_governance.task_credential_broker.subprocess.run", side_effect=[issued, encrypted]) as runner, \
mock.patch("aios_single_owner_governance.task_credential_broker.sqlite3.connect", return_value=connection):
broker.provision(identity="codex", token_name="pr37-dddddddddddd-status", encrypted_path=Path("/run/aios-task-credential-broker/status.cred"))
self.assertIn("--name=gitea-token", runner.call_args_list[1].args[0])
def test_expiry_sweeper_revokes_projected_token_after_grant_expiry(self):
item = TaskGrant.from_dict(grant())
runtime_root = self.root / "runtime"
credential_root = self.root / "credentials"
task_dir = runtime_root / "task-37"
audit_dir = task_dir / "audit"
audit_dir.mkdir(parents=True)
credential_root.mkdir()
(task_dir / "grant.json").write_text("{}", encoding="utf-8")
(task_dir / "grant.sig").write_text("signature", encoding="utf-8")
token_name = "pr37-dddddddddddd-status"
encrypted_path = credential_root / "status.cred"
encrypted_path.write_text("encrypted", encoding="utf-8")
(credential_root / "task-37-audit.cred").write_text("encrypted-audit-key", encoding="utf-8")
real_broker = TaskCredentialBroker(item, audit_dir, b"audit-key")
receipt = real_broker._audit({
"status": "PASS", "operation": "credential_provision", "identity": "codex",
"token_name": token_name, "token_id": 101, "token_uid": 7,
"grant_sha256": item.digest,
"credential_ref": "systemd-credential-encrypted://status.cred",
})
real_broker.validate_provision_receipt(receipt, encrypted_path)
tampered = dict(receipt)
tampered["token_id"] = 102
with self.assertRaisesRegex(ContractDenied, "PROVISION_RECEIPT_INVALID"):
real_broker.validate_provision_receipt(tampered, encrypted_path)
fake_broker = mock.Mock()
fake_broker.revoke.return_value = {"status": "PASS", "old_token_http_status": 401}
with mock.patch.object(sweeper, "RUNTIME_ROOT", runtime_root), \
mock.patch.object(sweeper, "CREDENTIAL_ROOT", credential_root), \
mock.patch.object(sweeper.os, "geteuid", return_value=0, create=True), \
mock.patch.object(sweeper, "load_signed_task_grant", return_value=item), \
mock.patch.object(sweeper.subprocess, "run", return_value=mock.Mock(stdout=b"audit-key")), \
mock.patch.object(sweeper, "TaskCredentialBroker", return_value=fake_broker) as broker_type:
results = sweeper.sweep(runtime_root, self.root / "allowed_signers", now=item.expires_at)
self.assertEqual(results, [{"status": "PASS", "old_token_http_status": 401}])
broker_type.assert_called_once_with(item, audit_dir, b"audit-key")
fake_broker.revoke.assert_called_once()
def test_revocation_is_exact_access_token_row_only_and_proves_http_401(self):
item = TaskGrant.from_dict(grant())
broker = TaskCredentialBroker(item, self.root / "revoke-audit", b"audit-key")
token_name = "pr37-dddddddddddd-status"
receipt = broker._audit({
"status": "PASS", "operation": "credential_provision", "identity": "codex",
"token_name": token_name, "token_id": 101, "token_uid": 7,
"grant_sha256": item.digest,
"credential_ref": "systemd-credential-encrypted://status.cred",
})
response = mock.MagicMock()
response.__enter__.return_value.status = 200
unauthorized = urllib.error.HTTPError("http://127.0.0.1:3000/api/v1/repos/aios/aios", 401, "Unauthorized", {}, None)
write_connection = mock.MagicMock()
write_connection.execute.return_value.rowcount = 1
read_connection = mock.MagicMock()
read_connection.execute.return_value.fetchone.return_value = (0,)
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=0, create=True), \
mock.patch("aios_single_owner_governance.task_credential_broker._safe_absolute"), \
mock.patch("aios_single_owner_governance.task_credential_broker.subprocess.run", return_value=mock.Mock(stdout=b"x" * 40)), \
mock.patch("aios_single_owner_governance.task_credential_broker.sqlite3.connect", side_effect=[write_connection, read_connection]) as connect, \
mock.patch("aios_single_owner_governance.task_credential_broker.urllib.request.urlopen", side_effect=[response, unauthorized]) as urlopen:
result = broker.revoke(receipt=receipt, encrypted_path=Path("/run/aios-task-credential-broker/status.cred"))
self.assertEqual(result["old_token_http_status"], 401)
self.assertIn("/repos/aios/aios", urlopen.call_args_list[0].args[0].full_url)
delete_sql = write_connection.execute.call_args_list[1].args[0]
self.assertIn("DELETE FROM access_token", delete_sql)
self.assertNotIn("commit_status", delete_sql)
self.assertIn("mode=ro", connect.call_args_list[1].args[0])
value = grant()
value["token"] = "plaintext"
with self.assertRaisesRegex(ContractDenied, "GRANT_FIELDS_INVALID"):
TaskGrant.from_dict(value)
def test_audit_chain_is_content_addressed_and_contains_no_secret(self):
item = TaskGrant.from_dict(grant())
journal = self.journal(item)
receipt = StatusBroker(item, journal, FakeAPI(), b"audit-key").publish(evidence())
serialized = json.dumps(receipt, sort_keys=True)
self.assertNotIn("audit-key", serialized)
self.assertEqual(len(receipt["audit_signature"]), 64)
self.assertTrue(journal.verify_chain())
def test_credential_broker_is_root_only_and_never_returns_a_token(self):
item = TaskGrant.from_dict(grant())
broker = TaskCredentialBroker(item, self.root / "audit", b"audit-key")
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=1000, create=True):
with self.assertRaisesRegex(ContractDenied, "ROOT_BROKER_REQUIRED"):
broker.provision(
identity="codex",
token_name="pr36-a8644fc172bd-status",
encrypted_path=Path("/run/aios-task-credential-broker/status.cred"),
)
def test_partial_status_side_effects_are_reconciled_without_duplicate_writes(self):
item = TaskGrant.from_dict(grant())
api = FakeAPI(fail_status_after=2)
journal = self.journal(item)
with self.assertRaisesRegex(ContractDenied, "SIMULATED_STATUS_FAILURE"):
StatusBroker(item, journal, api, b"audit-key").publish(evidence())
self.assertEqual(len(api.status_rows), 2)
api.fail_status_after = None
receipt = StatusBroker(item, journal, api, b"audit-key").publish(evidence())
self.assertEqual(receipt["published_count"], 5)
self.assertEqual(len(api.status_rows), 5)
def test_post_merge_response_loss_is_reconciled_from_exact_remote_ref(self):
item = TaskGrant.from_dict(grant())
api = FakeAPI(with_statuses=True, fail_after_merge=True)
journal = self.journal(item)
with self.assertRaisesRegex(ContractDenied, "SIMULATED_POST_MERGE_LOSS"):
MergeBroker(item, journal, api, b"audit-key").merge()
api.fail_after_merge = False
receipt = MergeBroker(item, journal, api, b"audit-key").merge()
self.assertTrue(receipt["reconciled"])
self.assertEqual(receipt["governance_oid"], HEAD)
if __name__ == "__main__":
unittest.main()
@@ -1,228 +0,0 @@
import json
import tempfile
import threading
import unittest
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
import os
import sys
ROOT = os.getcwd()
sys.path.insert(0, str(Path(ROOT) / "active-runtime"))
from app.task_plane.workers.command_policy import CommandPolicy
from app.task_plane.workers.task_client import (
CredentialSource,
StageAClientConfig,
TaskClientAuthError,
TaskClientProtocolError,
TaskClientResponseTooLargeError,
TaskPlaneClient,
)
def _start_server(responses):
class Handler(BaseHTTPRequestHandler):
request_count = 0
seen = []
def do_POST(self):
index = Handler.request_count
Handler.request_count += 1
payload_length = int(self.headers.get("Content-Length", "0"))
payload = self.rfile.read(payload_length)
try:
payload_obj = json.loads(payload.decode("utf-8") or "{}")
except Exception:
payload_obj = {"raw": payload.decode("utf-8", errors="replace")}
Handler.seen.append((self.path, payload_obj))
status, response_obj = responses[min(index, len(responses) - 1)]
body = json.dumps(response_obj).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, *_args, **_kwargs):
return
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
return server, thread, Handler
def _stop_server(server, thread):
server.shutdown()
server.server_close()
thread.join(timeout=2)
class CodexWorkerCommandPolicyTests(unittest.TestCase):
def test_rejects_revision_and_path_injection(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
policy = CommandPolicy(root, root / "results")
with self.assertRaises(ValueError):
policy.build("git-show", oid="HEAD~1", paths=["active-runtime/app/task_plane/api.py"])
with self.assertRaises(ValueError):
policy.build("pytest", oid="0" * 40, paths=["../outside"])
class CodexWorkerClientStageBTests(unittest.TestCase):
def test_client_retry_on_retryable_status(self):
server, thread, handler = _start_server([(503, {"error": "try again"}), (200, {"ok": True})])
try:
client = TaskPlaneClient(
StageAClientConfig(base_url=f"http://127.0.0.1:{server.server_port}"),
token="stage-b-token-" + "x" * 32,
)
body = client._post("/tests/retry", {"probe": "x"}, idempotency_key="retry")
self.assertEqual(body, {"ok": True})
self.assertEqual(handler.request_count, 2)
self.assertTrue(handler.seen[0][0].startswith("/tests/retry"))
finally:
_stop_server(server, thread)
def test_client_stops_retry_on_auth_error(self):
server, thread, handler = _start_server([(403, {"error": "denied"})])
try:
client = TaskPlaneClient(
StageAClientConfig(base_url=f"http://127.0.0.1:{server.server_port}"),
token="stage-b-token-" + "x" * 32,
)
with self.assertRaises(TaskClientAuthError):
client._post("/tests/auth", {"probe": "x"}, idempotency_key="auth")
self.assertEqual(handler.request_count, 1)
finally:
_stop_server(server, thread)
def test_client_rejects_oversize_request_and_response(self):
server, thread, _ = _start_server([(200, {"ok": True})])
try:
small = TaskPlaneClient(
StageAClientConfig(
base_url=f"http://127.0.0.1:{server.server_port}",
max_request_bytes=8,
),
token="stage-b-token-" + "x" * 32,
)
with self.assertRaises(TaskClientResponseTooLargeError):
small._post("/tests/request", {"probe": "too-large"}, idempotency_key="req")
finally:
_stop_server(server, thread)
oversize = {"blob": "x" * 1_100_000}
server, thread, _ = _start_server([(200, oversize)])
try:
client = TaskPlaneClient(
StageAClientConfig(base_url=f"http://127.0.0.1:{server.server_port}"),
token="stage-b-token-" + "x" * 32,
)
with self.assertRaises(TaskClientResponseTooLargeError):
client._post("/tests/response", {"probe": "ok"}, idempotency_key="resp")
finally:
_stop_server(server, thread)
def test_client_credential_source_symlink_and_mode(self):
with tempfile.TemporaryDirectory() as directory:
directory = Path(directory)
token_file = directory / "token"
token_file.write_text("x" * 32, encoding="utf-8")
token_file.chmod(0o600)
import grp
import pwd
owner = pwd.getpwuid(os.getuid()).pw_name
group = grp.getgrgid(os.getgid()).gr_name
source = CredentialSource(
token_file,
token_owner=owner,
token_group=group,
expected_mode=0o600,
)
self.assertEqual(source.read_token(), "x" * 32)
symlink = directory / "token-link"
symlink.symlink_to(token_file)
with self.assertRaises(TaskClientAuthError):
CredentialSource(
symlink,
token_owner=owner,
token_group=group,
expected_mode=0o600,
).read_token()
bad_mode = directory / "bad-mode"
bad_mode.write_text("value", encoding="utf-8")
bad_mode.chmod(0o644)
with self.assertRaises(TaskClientAuthError):
CredentialSource(
bad_mode,
token_owner=owner,
token_group=group,
expected_mode=0o600,
).read_token()
def test_client_rejects_missing_claim_id_and_reports_heartbeat_defaults(self):
client = TaskPlaneClient(StageAClientConfig(), token="stage-b-token-" + "x" * 32)
with self.assertRaises(TaskClientProtocolError):
client.progress("task-id", claim_id="", progress=10, stage="RUN")
with self.assertRaises(TaskClientProtocolError):
client.result(
"task-id",
claim_id="",
status="COMPLETED",
outputs=[],
evidence=[],
started_at="",
completed_at="",
)
with self.assertRaises(TaskClientProtocolError):
client.fail("task-id", claim_id="")
def test_heartbeat_request_uses_default_lease(self):
captured = {}
def handler_factory(responses):
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
payload_length = int(self.headers.get("Content-Length", "0"))
captured["path"] = self.path
captured["payload"] = json.loads(self.rfile.read(payload_length).decode("utf-8") or "{}")
status, response_obj = responses[min(responses_index[0], len(responses) - 1)]
responses_index[0] += 1
response = json.dumps(response_obj).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(response)))
self.end_headers()
self.wfile.write(response)
def log_message(self, *_args, **_kwargs):
return
return Handler
responses_index = [0]
server = ThreadingHTTPServer(("127.0.0.1", 0), handler_factory([(200, {"claim_id": "x"}), (200, {"ok": True})]))
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
client = TaskPlaneClient(
StageAClientConfig(base_url=f"http://127.0.0.1:{server.server_port}"),
token="stage-b-token-" + "x" * 32,
)
client.claim_heartbeat("task-id", claim_id="claim-id")
self.assertEqual(captured["payload"], {"claim_id": "claim-id", "lease_seconds": 120})
self.assertTrue(captured["path"].endswith("/tasks/task-id/heartbeat"))
captured["payload"] = None
client.worker_heartbeat("worker-1")
self.assertEqual(captured["payload"], {})
finally:
_stop_server(server, thread)
@@ -1,90 +0,0 @@
import os
import stat
import tempfile
import unittest
from pathlib import Path
ROOT = os.getcwd()
import sys
sys.path.insert(0, str(Path(ROOT) / "active-runtime"))
from app.task_plane.workers.codex_review_test import CodexReviewTaskPolicy
from app.task_plane.workers.result_attestation import TaskResultEnvelope, TrustPolicy, task_result_envelope
from app.task_plane.workers.workspace import TaskWorkspace
class CodexWorkerWorkspaceRecoveryTests(unittest.TestCase):
def test_workspace_permissions_and_cleanup(self):
with tempfile.TemporaryDirectory() as directory:
root_path = Path(directory) / "task-root"
with TaskWorkspace.create(root_path, task_id="task-01", claim_id="claim-01") as workspace:
for path in (
workspace.layout.workspace_root,
workspace.layout.repo_root,
workspace.layout.result_root,
workspace.layout.home,
workspace.layout.tmp,
):
self.assertEqual(stat.S_IMODE(path.stat().st_mode), 0o700)
result_path = workspace.write_result(name="result.json", payload="{}")
self.assertTrue(result_path.exists())
self.assertEqual(stat.S_IMODE(result_path.stat().st_mode), 0o600)
self.assertFalse(root_path.exists())
def test_result_envelope_validates_required_contract_fields(self):
envelope = task_result_envelope(
task_id="task-01",
claim_id="claim-01",
worker_identity="spiffe://aios/agent/codex/review-01",
status="COMPLETED",
outputs=[],
evidence=[],
started_at="2026-07-24T00:00:00Z",
completed_at="2026-07-24T00:00:01Z",
)
payload = envelope.to_dict()
self.assertEqual(payload["production_trust"], False)
self.assertEqual(payload["trust_level"], TrustPolicy.SHADOW_ATTESTED.value)
self.assertEqual(payload["task_id"], "task-01")
invalid = TaskResultEnvelope(
task_id="",
claim_id="claim",
worker_identity="worker",
status="FAILED",
outputs=[],
evidence=[],
started_at="",
completed_at="",
production_trust=False,
)
with self.assertRaises(ValueError):
invalid.validate()
def test_shadow_policy_enforces_concurrency_and_timeboxes(self):
policy = CodexReviewTaskPolicy(worker_id="worker-01", identity="identity")
self.assertEqual(policy.max_concurrency, 1)
self.assertEqual(policy.heartbeat_interval_seconds, 15)
self.assertEqual(policy.claim_lease_seconds, 120)
valid_task = {
"risk": "low",
"metadata": {"production_side_effects": False},
}
policy.assert_shadow_only_task(valid_task)
with self.assertRaises(Exception):
policy.assert_shadow_only_task(
{
"risk": "critical",
"metadata": {"production_side_effects": False},
}
)
with self.assertRaises(Exception):
CodexReviewTaskPolicy(
worker_id="worker-01",
identity="identity",
max_concurrency=2,
).assert_shadow_only_task(valid_task)
@@ -1,83 +0,0 @@
import os
import tempfile
import unittest
from pathlib import Path
ROOT = os.getcwd()
import sys
sys.path.insert(0, str(Path(ROOT) / "active-runtime"))
from app.task_plane.workers.command_policy import CommandPolicy
from app.task_plane.workers.runner import CommandDisallowedError, SafeCommandRunner, CommandPolicyError
from app.task_plane.workers.workspace import TaskWorkspace
class CodexWorkerRunnerSecurityTests(unittest.TestCase):
def test_runner_only_allows_fixed_command_set(self):
with tempfile.TemporaryDirectory() as directory:
with TaskWorkspace.create(Path(directory) / "workspace", task_id="task-fixed", claim_id="claim-fixed") as workspace:
runner = SafeCommandRunner(workspace.layout.repo_root, workspace.layout.result_root)
with self.assertRaises(CommandDisallowedError):
runner.run("shell", oid="0" * 40)
with self.assertRaises(CommandDisallowedError):
runner.run("bash", oid="0" * 40, paths=["tests/task_plane/public_interface"])
def test_runner_rejects_shell_like_and_eval_inputs(self):
with tempfile.TemporaryDirectory() as directory:
with TaskWorkspace.create(Path(directory) / "workspace", task_id="task-shell", claim_id="claim-shell") as workspace:
runner = SafeCommandRunner(workspace.layout.repo_root, workspace.layout.result_root)
CommandPolicy(workspace.layout.repo_root, workspace.layout.result_root).build(
"pytest",
oid="0" * 40,
paths=["tests/task_plane/public_interface"],
)
with self.assertRaises(CommandDisallowedError):
runner.run("pytest", oid="0" * 40, paths=["tests/task_plane/public_interface;touch /tmp/x"])
with self.assertRaises(CommandDisallowedError):
runner.run("pytest", oid="0" * 40, paths=["tests/task_plane/public_interface", "eval"])
with self.assertRaises(CommandDisallowedError):
runner.run("pytest", oid="0" * 40, paths=["tests/task_plane/public_interface", "bash"])
def test_runner_rejects_revision_expression_and_symlink_paths(self):
with tempfile.TemporaryDirectory() as directory:
with TaskWorkspace.create(Path(directory) / "workspace", task_id="task-revision", claim_id="claim-revision") as workspace:
runner = SafeCommandRunner(workspace.layout.repo_root, workspace.layout.result_root)
policy_root = workspace.layout.repo_root
(policy_root / "tests" / "task_plane" / "public_interface").mkdir(parents=True, exist_ok=True)
with self.assertRaises(ValueError):
runner.run("git-show", oid="HEAD~1", paths=["active-runtime/app/task_plane/worker.py"])
link_target = policy_root / "tests" / "task_plane" / "public_interface" / "link"
link_target.symlink_to(Path("/etc/passwd"), target_is_directory=False)
with self.assertRaises(CommandPolicyError):
runner.run("git-show", oid="0" * 40, paths=["tests/task_plane/public_interface/link"])
def test_runner_rejects_network_tokens_and_output_escape(self):
with tempfile.TemporaryDirectory() as directory:
with TaskWorkspace.create(Path(directory) / "workspace", task_id="task-net", claim_id="claim-net") as workspace:
runner = SafeCommandRunner(workspace.layout.repo_root, workspace.layout.result_root)
with self.assertRaises(CommandDisallowedError):
runner.run("git-show", oid="0" * 40, paths=["https://bad.example/attack"])
with self.assertRaises(CommandPolicyError):
runner.run(
"acceptance",
oid="0" * 40,
paths=["active-runtime"],
output=workspace.layout.home.parent / "escape.json",
)
def test_runner_accepts_nested_allowlisted_paths_and_rejects_secret_env(self):
with tempfile.TemporaryDirectory() as directory:
with TaskWorkspace.create(Path(directory) / "workspace", task_id="task-safe", claim_id="claim-safe") as workspace:
runner = SafeCommandRunner(workspace.layout.repo_root, workspace.layout.result_root)
command = runner.build(
"pytest",
oid="0" * 40,
paths=["tests/task_plane/public_interface"],
)
self.assertEqual(command[-1], "tests/task_plane/public_interface")
with self.assertRaises(Exception):
runner.run("diff-check", oid="0" * 40, env={"API_TOKEN": "secret"})
@@ -0,0 +1,417 @@
from __future__ import annotations
import json
import os
import tempfile
import unittest
from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest import mock
import aios_isolated_writer_policy as writer_policy
import isolated_writer_path_policy as path_policy
from isolated_writer_authz import AuthorizationError, _validate_grant
TARGET = "deploy/systemd/aios-codex-review-test-worker.service"
BRANCH = "patch/codex-review-test-worker-20260724"
AUDIENCE = "aios-codex-review-worker-writer.service"
VALID_UNIT = """\
[Unit]
Description=AIOS Codex Review/Test Worker
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aiman
Group=gitops
WorkingDirectory=/usr/libexec/aios-codex-review-test-worker/current
Environment=AIOS_CODEX_WORKER_MODE=shadow
Environment=AIOS_TASK_PLANE_EXECUTION_ENABLED=false
Environment=PYTHONDONTWRITEBYTECODE=1
ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
LockPersonality=true
RestrictSUIDSGID=true
RestrictRealtime=true
MemoryDenyWriteExecute=true
RuntimeDirectory=aios-codex-review-test-worker
StateDirectory=aios-codex-review-test-worker
CacheDirectory=aios-codex-review-test-worker
ReadOnlyPaths=/data/aios-gitops/repo.git
ReadOnlyPaths=/usr/libexec/aios-codex-review-test-worker
ReadWritePaths=/run/aios-codex-review-test-worker
ReadWritePaths=/var/lib/aios-codex-review-test-worker
ReadWritePaths=/var/cache/aios-codex-review-test-worker
UMask=0077
[Install]
WantedBy=multi-user.target
"""
def document(*, paths=None, **updates):
value = {
"schema_version": 1,
"policy_id": "codex-review-worker-path-policy-v1",
"audience": AUDIENCE,
"repository_identity": "aios/aios",
"allowed_branch": BRANCH,
"allowed_operations": {
"commit_file.atomic": {
"exact_paths": paths or [TARGET],
"max_content_bytes": 32768,
"content_profile": "systemd-codex-review-worker-v1",
}
},
}
value.update(updates)
return value
class ExactPathPolicyTests(unittest.TestCase):
def setUp(self):
self.saved = dict(os.environ)
self.temp = tempfile.TemporaryDirectory()
self.root = Path(self.temp.name)
self.policy_dir = self.root / "policies"
self.policy_dir.mkdir(mode=0o750)
self.policy_file = self.policy_dir / "writer.json"
self.workspace = self.root / "workspace"
self.workspace.mkdir(mode=0o700)
os.environ.update(
{
"AIOS_GITOPS_ISOLATED_WRITER_ENFORCEMENT": "required",
"AIOS_GITOPS_SERVICE_AUDIENCE": AUDIENCE,
"AIOS_GITOPS_REPOSITORY_IDENTITY": "aios/aios",
"AIOS_GITOPS_ALLOWED_BRANCH": BRANCH,
}
)
def tearDown(self):
path_policy.clear_path_policy_cache()
os.environ.clear()
os.environ.update(self.saved)
self.temp.cleanup()
def write_policy(self, value=None):
payload = document() if value is None else value
raw = (
json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
+ "\n"
)
self.policy_file.write_text(raw, encoding="utf-8")
self.policy_file.chmod(0o640)
return path_policy.load_path_policy(
self.policy_file,
expected_owner_uid=os.getuid(),
expected_group_gid=os.getgid(),
)
def configured(self, loaded):
return mock.patch.object(
path_policy,
"configured_path_policy",
return_value=loaded,
)
def test_exact_systemd_path_and_exact_token_path_are_allowed(self):
loaded = self.write_policy()
with self.configured(loaded):
self.assertEqual(TARGET, writer_policy.validate_path(TARGET, self.workspace))
writer_policy.validate_content_for_path(TARGET, VALID_UNIT)
def test_token_path_cannot_expand_service_policy(self):
loaded = self.write_policy(document(paths=["deploy/systemd/other.service"]))
with self.configured(loaded), self.assertRaisesRegex(
PermissionError, "isolated_writer_service_path_rejected"
):
writer_policy.validate_path(TARGET, self.workspace)
def test_service_policy_cannot_expand_token_path(self):
now = datetime.now(timezone.utc)
grant = {
"schema_version": 2,
"audience": AUDIENCE,
"source_cidrs": ["127.0.0.1/32"],
"created_at": (now - timedelta(seconds=5)).isoformat(),
"not_before": (now - timedelta(seconds=2)).isoformat(),
"expires_at": (now + timedelta(minutes=5)).isoformat(),
"revoked": False,
"allowed_operations": ["commit_file.atomic"],
"allowed_branch": BRANCH,
"allowed_paths": ["deploy/systemd/other.service"],
"approved_base_oid": "a" * 40,
}
with mock.patch(
"isolated_writer_authz._git_is_ancestor", return_value=True
), self.assertRaisesRegex(AuthorizationError, "writer_token_path_rejected"):
_validate_grant(
grant,
audience=AUDIENCE,
source_ip="127.0.0.1",
operation="commit_file.atomic",
branch=BRANCH,
path=TARGET,
workspace=self.workspace,
current_time=now,
)
def test_other_service_file_is_rejected(self):
loaded = self.write_policy()
with self.configured(loaded), self.assertRaisesRegex(
PermissionError, "isolated_writer_service_path_rejected"
):
writer_policy.validate_path(
"deploy/systemd/other.service", self.workspace
)
def test_path_traversal_is_rejected(self):
for value in ("deploy/systemd/../x", "../deploy/systemd/x"):
with self.subTest(value=value), self.assertRaises(PermissionError):
writer_policy.validate_path(value, self.workspace)
def test_url_encoded_traversal_is_rejected(self):
with self.assertRaises(PermissionError):
writer_policy.validate_path(
"deploy/systemd/%2e%2e/x", self.workspace
)
def test_symlink_policy_file_is_rejected(self):
self.write_policy()
link = self.policy_dir / "link.json"
link.symlink_to(self.policy_file)
with self.assertRaisesRegex(
path_policy.PathPolicyError, "isolated_writer_path_policy_symlink_rejected"
):
path_policy.load_path_policy(
link,
expected_owner_uid=os.getuid(),
expected_group_gid=os.getgid(),
)
def test_world_writable_policy_file_is_rejected(self):
self.write_policy()
self.policy_file.chmod(0o646)
with self.assertRaisesRegex(
path_policy.PathPolicyError,
"isolated_writer_path_policy_permissions_rejected",
):
path_policy.load_path_policy(
self.policy_file,
expected_owner_uid=os.getuid(),
expected_group_gid=os.getgid(),
)
def test_unknown_policy_field_is_rejected(self):
value = document()
value["unexpected"] = True
with self.assertRaisesRegex(
path_policy.PathPolicyError,
"isolated_writer_path_policy_fields_rejected",
):
self.write_policy(value)
def test_audience_mismatch_is_rejected(self):
loaded = self.write_policy()
os.environ["AIOS_GITOPS_PATH_POLICY_FILE"] = str(self.policy_file)
os.environ["AIOS_GITOPS_SERVICE_AUDIENCE"] = "other.service"
path_policy.clear_path_policy_cache()
with mock.patch.object(
path_policy, "load_path_policy", return_value=loaded
), self.assertRaisesRegex(
path_policy.PathPolicyError,
"isolated_writer_path_policy_audience_rejected",
):
path_policy.configured_path_policy()
def test_branch_mismatch_is_rejected(self):
loaded = self.write_policy()
os.environ["AIOS_GITOPS_PATH_POLICY_FILE"] = str(self.policy_file)
os.environ["AIOS_GITOPS_ALLOWED_BRANCH"] = "patch/other"
path_policy.clear_path_policy_cache()
with mock.patch.object(
path_policy, "load_path_policy", return_value=loaded
), self.assertRaisesRegex(
path_policy.PathPolicyError,
"isolated_writer_path_policy_branch_rejected",
):
path_policy.configured_path_policy()
def assert_profile_rejected(self, content):
loaded = self.write_policy()
with self.configured(loaded), self.assertRaisesRegex(
PermissionError, "isolated_writer_systemd_profile_rejected"
):
writer_policy.validate_content_for_path(TARGET, content)
def test_disallowed_execution_and_credential_directives_are_rejected(self):
directives = (
"ExecStartPre=/usr/bin/id",
"ExecStartPost=/usr/bin/id",
"ExecReload=/usr/bin/id",
"ExecStop=/usr/bin/id",
"ExecStopPost=/usr/bin/id",
"ExecCondition=/usr/bin/true",
"EnvironmentFile=/run/worker.env",
"PassEnvironment=PATH",
"LoadCredential=worker:/run/worker",
"SetCredential=worker:value",
"ImportCredential=worker",
"StandardInput=socket",
"StandardOutput=socket",
)
for directive in directives:
with self.subTest(directive=directive):
self.assert_profile_rejected(
VALID_UNIT.replace(
"Restart=on-failure",
f"Restart=on-failure\n{directive}",
)
)
def test_disallowed_namespace_and_capability_directives_are_rejected(self):
directives = (
"RootDirectory=/srv/worker",
"RootImage=/srv/worker.raw",
"ReadWritePaths=/",
"BindPaths=/etc:/etc",
"BindReadOnlyPaths=/etc:/etc",
"TemporaryFileSystem=/etc",
"CapabilityBoundingSet=CAP_SYS_ADMIN",
"AmbientCapabilities=CAP_SYS_ADMIN",
"DeviceAllow=/dev/sda rw",
"SupplementaryGroups=docker",
"Sockets=unsafe.socket",
)
for directive in directives:
with self.subTest(directive=directive):
self.assert_profile_rejected(
VALID_UNIT.replace(
"Restart=on-failure",
f"Restart=on-failure\n{directive}",
)
)
def test_duplicate_single_directives_and_sections_are_rejected(self):
bad_values = (
VALID_UNIT.replace("User=aiman", "User=aiman\nUser=aiman"),
VALID_UNIT.replace(
"ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test",
"ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test\n"
"ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test",
),
VALID_UNIT + "\n[Service]\nType=simple\n",
)
for value in bad_values:
with self.subTest(value=value):
self.assert_profile_rejected(value)
def test_empty_reset_continuation_crlf_nul_and_long_lines_are_rejected(self):
bad_values = (
VALID_UNIT.replace(
"ExecStart=/usr/bin/python3 -m task_plane.workers.codex_review_test",
"ExecStart=",
),
VALID_UNIT.replace(
"Restart=on-failure",
"Restart=on-failure\n continuation-injection",
),
VALID_UNIT.replace("\n", "\r\n"),
VALID_UNIT.replace("Restart=on-failure", "Restart=on-failure\x00"),
VALID_UNIT.replace(
"Description=AIOS Codex Review/Test Worker",
"Description=" + ("A" * 4097),
),
)
for value in bad_values:
with self.subTest(kind=repr(value[:80])):
self.assert_profile_rejected(value)
def test_unknown_environment_and_production_execution_are_rejected(self):
bad_values = (
VALID_UNIT.replace(
"Environment=PYTHONDONTWRITEBYTECODE=1",
"Environment=UNKNOWN_KEY=value",
),
VALID_UNIT.replace(
"AIOS_TASK_PLANE_EXECUTION_ENABLED=false",
"AIOS_TASK_PLANE_EXECUTION_ENABLED=true",
),
VALID_UNIT.replace(
"Environment=PYTHONDONTWRITEBYTECODE=1",
"Environment=Authorization: Bearer placeholder",
),
)
for value in bad_values:
with self.subTest(value=value):
self.assert_profile_rejected(value)
def test_identity_working_directory_and_path_prefix_bypasses_are_rejected(self):
bad_values = (
VALID_UNIT.replace("User=aiman", "User=root"),
VALID_UNIT.replace(
"/usr/libexec/aios-codex-review-test-worker/current",
"/data/aios-gitops/worktrees/worker",
),
VALID_UNIT.replace(
"ReadWritePaths=/run/aios-codex-review-test-worker",
"ReadWritePaths=/etc",
),
VALID_UNIT.replace(
"ReadOnlyPaths=/data/aios-gitops/repo.git",
"ReadOnlyPaths=/data",
),
)
for value in bad_values:
with self.subTest(value=value):
self.assert_profile_rejected(value)
def test_unknown_section_directive_and_unicode_lookalike_are_rejected(self):
bad_values = (
VALID_UNIT.replace("[Install]", "[Socket]"),
VALID_UNIT.replace(
"Restart=on-failure",
"Restart=on-failure\nProtectClock=true",
),
VALID_UNIT.replace("ExecStart=", "\u0415xecStart="),
)
for value in bad_values:
with self.subTest(value=value):
self.assert_profile_rejected(value)
def test_invalid_unicode_surrogate_and_missing_final_newline_are_rejected(self):
for value in (VALID_UNIT + "\ud800", VALID_UNIT.rstrip("\n")):
with self.subTest(value=repr(value[-30:])):
self.assert_profile_rejected(value)
def test_writer_request_cannot_modify_policy_file(self):
with self.assertRaises(PermissionError):
writer_policy.validate_path(
"etc/aios-gitops/writer-path-policies/codex-review-worker.json",
self.workspace,
)
def test_coarse_file_and_commit_endpoints_remain_forbidden(self):
for endpoint in ("/api/file", "/api/commit"):
with self.subTest(endpoint=endpoint), self.assertRaisesRegex(
PermissionError, "isolated_writer_operation_forbidden"
):
writer_policy.validate_endpoint(
"POST", endpoint, self.workspace, self.root
)
if __name__ == "__main__":
unittest.main()
+4
View File
@@ -15,6 +15,10 @@ class IsolatedWriterPolicyTests(unittest.TestCase):
os.environ["AIOS_GITOPS_ISOLATED_WRITER_ENFORCEMENT"] = "required"
os.environ["AIOS_GITOPS_ALLOWED_BRANCH"] = "patch/aios-agent-task-control-plane-20260724"
os.environ["AIOS_GITOPS_ALLOWED_BASE_OID"] = "a8e97868976b0dce17b7cb8487eadc1d9c687622"
os.environ["AIOS_GITOPS_TOKEN_POLICY_VERSION_REQUIRED"] = "2"
os.environ["AIOS_GITOPS_SERVICE_AUDIENCE"] = "test-isolated-writer.service"
os.environ["AIOS_GITOPS_TOKEN_REGISTRY_V2"] = "/tmp/test-writer-token-registry.sqlite3"
os.environ["AIOS_GITOPS_WRITER_OPERATION_LEDGER"] = "/tmp/test-writer-operations.sqlite3"
def tearDown(self):
os.environ.clear()
@@ -0,0 +1,471 @@
import hashlib
import json
import os
import sqlite3
import subprocess
import sys
import tempfile
import threading
import time
import unittest
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "active-runtime" / "app"))
import aios_isolated_writer_policy as policy
from isolated_writer_authz import AuthorizationError, authorize, operation_for
from isolated_writer_commit_file import (
AtomicCommitFile,
CommitFileError,
OperationLedger,
SimulatedCrash,
)
from isolated_writer_token_registry import TokenRegistry, token_digest
BRANCH = "patch/codex-review-test-worker-20260724"
AUDIENCE = "aios-codex-review-worker-writer.service"
TASK_ID = "AIOS-CODEX-WRITER-SMOKE-20260724"
TARGET_PATH = "docs/reliability/codex-review-worker-writer-smoke.json"
def run(cwd, *args):
return subprocess.check_output(args, cwd=cwd, text=True).strip()
@dataclass
class DummyGrant:
token_id: str = "test-token-id"
task_id: str = TASK_ID
operation: str = "commit_file.atomic"
record: dict = None
def __post_init__(self):
if self.record is None:
self.record = {"audience": AUDIENCE, "_source_ip": "127.0.0.1"}
class RepositoryCase(unittest.TestCase):
def setUp(self):
self.saved = dict(os.environ)
self.temp = tempfile.TemporaryDirectory()
self.root = Path(self.temp.name)
self.authoritative = self.root / "authoritative.git"
self.gitea = self.root / "gitea.git"
self.seed = self.root / "seed"
self.workspace = self.root / "writer"
subprocess.run(["git", "init", "--bare", str(self.authoritative)], check=True, capture_output=True)
subprocess.run(["git", "init", str(self.seed)], check=True, capture_output=True)
subprocess.run(["git", "config", "user.email", "writer@example.invalid"], cwd=self.seed, check=True)
subprocess.run(["git", "config", "user.name", "Writer Test"], cwd=self.seed, check=True)
(self.seed / "README.md").write_text("base\n", encoding="utf-8")
subprocess.run(["git", "add", "README.md"], cwd=self.seed, check=True)
subprocess.run(["git", "commit", "-m", "base"], cwd=self.seed, check=True, capture_output=True)
subprocess.run(["git", "branch", "-M", "main"], cwd=self.seed, check=True)
subprocess.run(["git", "remote", "add", "origin", str(self.authoritative)], cwd=self.seed, check=True)
subprocess.run(["git", "push", "origin", "main"], cwd=self.seed, check=True, capture_output=True)
self.base = run(self.seed, "git", "rev-parse", "HEAD")
subprocess.run(["git", "checkout", "-b", BRANCH], cwd=self.seed, check=True, capture_output=True)
subprocess.run(["git", "push", "origin", BRANCH], cwd=self.seed, check=True, capture_output=True)
subprocess.run(
["git", "--git-dir", str(self.authoritative), "worktree", "add", str(self.workspace), BRANCH],
check=True,
capture_output=True,
)
subprocess.run(["git", "config", "user.email", "writer@example.invalid"], cwd=self.workspace, check=True)
subprocess.run(["git", "config", "user.name", "Writer Test"], cwd=self.workspace, check=True)
subprocess.run(["git", "clone", "--bare", str(self.authoritative), str(self.gitea)], check=True, capture_output=True)
subprocess.run(["git", "remote", "add", "gitea-http", str(self.gitea)], cwd=self.workspace, check=True)
self.registry = TokenRegistry(self.root / "registry.sqlite3")
os.environ.update({
"AIOS_GITOPS_ALLOWED_BRANCH": BRANCH,
"AIOS_GITOPS_TOKEN_POLICY_VERSION_REQUIRED": "2",
"AIOS_GITOPS_SERVICE_AUDIENCE": AUDIENCE,
"AIOS_GITOPS_ISOLATED_WRITER_ENFORCEMENT": "required",
})
def tearDown(self):
os.environ.clear()
os.environ.update(self.saved)
self.temp.cleanup()
def grant(self, **updates):
now = datetime.now(timezone.utc)
grant = {
"token_id": "smoke-" + hashlib.sha256(os.urandom(16)).hexdigest()[:12],
"audience": AUDIENCE,
"task_id": TASK_ID,
"source_cidrs": ["127.0.0.1/32", "::1/128"],
"allowed_branch": BRANCH,
"approved_base_oid": self.base,
"allowed_operations": [
"runtime.status.read",
"baseline.read",
"patches.read",
"commit_file.atomic",
],
"allowed_paths": [TARGET_PATH],
"not_before": (now - timedelta(seconds=2)).isoformat(),
"expires_at": (now + timedelta(minutes=20)).isoformat(),
"max_uses": {
"runtime.status.read": 2,
"baseline.read": 2,
"patches.read": 2,
"commit_file.atomic": 4,
},
"issued_by": "owner-authorized-local-maintenance-executor",
"created_at": (now - timedelta(seconds=3)).isoformat(),
}
grant.update(updates)
return grant
def issue(self, **updates):
return self.registry.issue(self.grant(**updates))
def auth(self, token, **updates):
args = {
"method": "GET",
"path": "/api/runtime-status",
"source_ip": "127.0.0.1",
"workspace": self.workspace,
}
args.update(updates)
return authorize(self.registry, token, **args)
def request(self, key="writer-smoke-0001", content='{"status":"READY"}\n'):
return {
"branch": BRANCH,
"path": TARGET_PATH,
"content": content,
"message": "chore(task-plane): verify Codex writer endpoint",
"expected_head_oid": run(self.workspace, "git", "rev-parse", "HEAD"),
"idempotency_key": key,
}
def writer(self, crash=None, remote="gitea-http", audit=None):
return AtomicCommitFile(
workspace=self.workspace,
bare_repo=self.authoritative,
ledger=OperationLedger(self.root / "operations.sqlite3"),
remote=remote,
audit=audit or (lambda record: None),
crash_after_state=crash,
)
class TokenPolicyV2Tests(RepositoryCase):
def test_v1_coarse_scope_token_is_rejected(self):
token, record = self.issue()
record["schema_version"] = 1
with self.registry._connect() as db:
db.execute(
"UPDATE token_grants SET grant_json=? WHERE token_id=?",
(json.dumps(record), record["token_id"]),
)
with self.assertRaisesRegex(AuthorizationError, "writer_token_policy_v2_required"):
self.auth(token)
def test_audience_mismatch_is_rejected(self):
token, _ = self.issue(audience="other.service")
with self.assertRaisesRegex(AuthorizationError, "writer_token_audience_rejected"):
self.auth(token)
def test_source_ip_mismatch_is_rejected(self):
token, _ = self.issue(source_cidrs=["192.0.2.0/24"])
with self.assertRaisesRegex(AuthorizationError, "writer_token_source_rejected"):
self.auth(token)
def test_branch_mismatch_is_rejected(self):
token, _ = self.issue(allowed_branch="patch/other")
with self.assertRaisesRegex(AuthorizationError, "writer_token_branch_rejected"):
self.auth(token)
def test_operation_mismatch_is_rejected(self):
token, _ = self.issue(allowed_operations=["baseline.read"])
with self.assertRaisesRegex(AuthorizationError, "writer_token_operation_rejected"):
self.auth(token)
def test_path_mismatch_is_rejected(self):
token, _ = self.issue()
with self.assertRaisesRegex(AuthorizationError, "writer_token_path_rejected"):
self.auth(
token,
method="POST",
path="/api/commit-file",
branch=BRANCH,
target_path="docs/other.json",
)
def test_expired_token_is_rejected(self):
now = datetime.now(timezone.utc)
token, _ = self.issue(
created_at=(now - timedelta(minutes=10)).isoformat(),
not_before=(now - timedelta(minutes=9)).isoformat(),
expires_at=(now - timedelta(seconds=1)).isoformat(),
)
with self.assertRaisesRegex(AuthorizationError, "writer_token_expired"):
self.auth(token)
def test_not_before_token_is_rejected(self):
now = datetime.now(timezone.utc)
token, _ = self.issue(
created_at=now.isoformat(),
not_before=(now + timedelta(minutes=1)).isoformat(),
expires_at=(now + timedelta(minutes=5)).isoformat(),
)
with self.assertRaisesRegex(AuthorizationError, "writer_token_not_yet_valid"):
self.auth(token)
def test_revoked_token_is_rejected(self):
token, grant = self.issue()
self.assertTrue(self.registry.revoke(grant["token_id"]))
with self.assertRaisesRegex(AuthorizationError, "writer_token_revoked"):
self.auth(token)
def test_operation_use_count_is_atomic_and_exhausted(self):
token, _ = self.issue(max_uses={
"runtime.status.read": 1,
"baseline.read": 1,
"patches.read": 1,
"commit_file.atomic": 1,
})
self.auth(token)
with self.assertRaisesRegex(AuthorizationError, "writer_token_operation_exhausted"):
self.auth(token)
def test_concurrent_use_count_never_exceeds_limit(self):
token, _ = self.issue(max_uses={
"runtime.status.read": 2,
"baseline.read": 1,
"patches.read": 1,
"commit_file.atomic": 1,
})
successes, failures = [], []
def invoke():
try:
successes.append(self.auth(token))
except AuthorizationError as exc:
failures.append(exc.code)
threads = [threading.Thread(target=invoke) for _ in range(6)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
self.assertEqual(2, len(successes))
self.assertEqual(4, failures.count("writer_token_operation_exhausted"))
def test_registry_does_not_store_plaintext_token(self):
token, _ = self.issue()
registry_bytes = b"".join(
item.read_bytes()
for item in self.registry.path.parent.glob(self.registry.path.name + "*")
if item.is_file()
)
self.assertNotIn(token.encode(), registry_bytes)
with self.registry._connect() as db:
stored = db.execute("SELECT token_digest FROM token_grants").fetchone()[0]
self.assertEqual(token_digest(token), stored)
def test_coarse_routes_have_no_operation_mapping(self):
for path in ("/api/file", "/api/commit", "/api/tag", "/api/rollback", "/api/model"):
with self.subTest(path=path), self.assertRaises(AuthorizationError) as captured:
operation_for("POST", path)
self.assertEqual(403, captured.exception.status)
def test_route_mapping_is_fixed_not_request_controlled(self):
self.assertEqual("runtime.status.read", operation_for("GET", "/api/runtime-status"))
self.assertEqual("baseline.read", operation_for("GET", "/api/baseline"))
self.assertEqual("patches.read", operation_for("GET", "/api/patches"))
self.assertEqual("commit_file.atomic", operation_for("POST", "/api/commit-file"))
def test_x_forwarded_for_cannot_replace_socket_peer(self):
token, _ = self.issue(source_cidrs=["203.0.113.9/32"])
with self.assertRaisesRegex(AuthorizationError, "writer_token_source_rejected"):
self.auth(token, source_ip="127.0.0.1")
class AtomicCommitFileTests(RepositoryCase):
def test_commit_file_succeeds_and_verifies_bare_and_gitea(self):
result = self.writer().execute(DummyGrant(), self.request())
self.assertEqual("COMPLETED", result["state"])
self.assertEqual(
result["commit_oid"],
run(self.root, "git", "--git-dir", str(self.gitea), "rev-parse", f"refs/heads/{BRANCH}"),
)
def test_same_idempotency_key_returns_same_commit(self):
request = self.request()
first = self.writer().execute(DummyGrant(), request)
count = run(self.workspace, "git", "rev-list", "--count", "HEAD")
second = self.writer().execute(DummyGrant(), request)
self.assertEqual(first["commit_oid"], second["commit_oid"])
self.assertEqual(count, run(self.workspace, "git", "rev-list", "--count", "HEAD"))
self.assertTrue(second["idempotent"])
def test_same_key_with_different_payload_returns_409(self):
request = self.request()
self.writer().execute(DummyGrant(), request)
request["content"] = '{"status":"DIFFERENT"}\n'
with self.assertRaises(CommitFileError) as captured:
self.writer().execute(DummyGrant(), request)
self.assertEqual(409, captured.exception.status)
def test_same_key_from_different_task_returns_409(self):
request = self.request()
self.writer().execute(DummyGrant(), request)
other = DummyGrant(token_id="other-token", task_id="OTHER-TASK")
with self.assertRaisesRegex(CommitFileError, "writer_idempotency_owner_conflict"):
self.writer().execute(other, request)
def test_file_written_crash_is_recoverable(self):
request = self.request()
with self.assertRaises(SimulatedCrash):
self.writer(crash="FILE_WRITTEN").execute(DummyGrant(), request)
result = self.writer().execute(DummyGrant(), request)
self.assertEqual("COMPLETED", result["state"])
def test_committed_crash_is_recoverable_without_second_commit(self):
request = self.request()
with self.assertRaises(SimulatedCrash):
self.writer(crash="COMMITTED").execute(DummyGrant(), request)
committed = run(self.workspace, "git", "rev-parse", "HEAD")
result = self.writer().execute(DummyGrant(), request)
self.assertEqual(committed, result["commit_oid"])
def test_pushed_crash_only_reverifies(self):
request = self.request()
with self.assertRaises(SimulatedCrash):
self.writer(crash="PUSHED").execute(DummyGrant(), request)
result = self.writer().execute(DummyGrant(), request)
self.assertEqual("COMPLETED", result["state"])
def test_push_failure_is_failed_recoverable(self):
request = self.request()
with self.assertRaisesRegex(CommitFileError, "writer_gitea_push_failed"):
self.writer(remote="missing-remote").execute(DummyGrant(), request)
row = OperationLedger(self.root / "operations.sqlite3").get(request["idempotency_key"])
self.assertEqual("FAILED_RECOVERABLE", row["state"])
def test_branch_head_conflict_requires_manual_review(self):
request = self.request()
ledger = OperationLedger(self.root / "operations.sqlite3")
ledger.get_or_create(DummyGrant(), request, __import__("isolated_writer_commit_file").canonical_digest(request))
(self.workspace / "README.md").write_text("drift\n", encoding="utf-8")
subprocess.run(["git", "commit", "-am", "drift"], cwd=self.workspace, check=True, capture_output=True)
with self.assertRaisesRegex(CommitFileError, "writer_branch_head_conflict"):
self.writer().execute(DummyGrant(), request)
self.assertEqual("MANUAL_REVIEW_REQUIRED", ledger.get(request["idempotency_key"])["state"])
def test_extra_staged_file_is_rejected(self):
(self.workspace / "README.md").write_text("staged\n", encoding="utf-8")
subprocess.run(["git", "add", "README.md"], cwd=self.workspace, check=True)
with self.assertRaisesRegex(CommitFileError, "writer_extra_staged_files_rejected"):
self.writer().execute(DummyGrant(), self.request())
def test_path_traversal_and_protected_roots_are_rejected(self):
for path in (
"../docs/x", "%2e%2e/docs/x", "/etc/x", r"C:\temp\x",
r"\\server\share\x", "baseline/current.json", "runtime/x",
):
request = self.request(key="writer-path-" + hashlib.sha256(path.encode()).hexdigest()[:12])
request["path"] = path
with self.subTest(path=path), self.assertRaises((PermissionError, CommitFileError)):
self.writer().execute(DummyGrant(), request)
def test_audit_contains_ids_but_not_content_or_authorization(self):
records = []
request = self.request(content='{"value":"non-secret-body-marker"}\n')
self.writer(audit=records.append).execute(DummyGrant(), request)
encoded = json.dumps(records)
self.assertIn("test-token-id", encoded)
self.assertNotIn("non-secret-body-marker", encoded)
self.assertNotIn("Authorization", encoded)
def test_concurrent_same_idempotency_creates_one_commit(self):
request = self.request()
results, errors = [], []
def invoke():
try:
results.append(self.writer().execute(DummyGrant(), request))
except Exception as exc:
errors.append(exc)
threads = [threading.Thread(target=invoke) for _ in range(4)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
self.assertFalse(errors)
self.assertEqual(1, len({item["commit_oid"] for item in results}))
def test_different_operations_are_serialized_by_branch_lock(self):
active = 0
maximum = 0
guard = threading.Lock()
class Probe(AtomicCommitFile):
def _execute_locked(inner, grant, data, digest):
nonlocal active, maximum
with guard:
active += 1
maximum = max(maximum, active)
time.sleep(0.05)
with guard:
active -= 1
return {"state": "PROBED"}
probe = Probe(
workspace=self.workspace,
bare_repo=self.authoritative,
ledger=OperationLedger(self.root / "probe.sqlite3"),
remote="gitea-http",
audit=lambda record: None,
)
requests = [self.request(key=f"writer-lock-{index:04d}") for index in range(3)]
threads = [threading.Thread(target=probe.execute, args=(DummyGrant(), item)) for item in requests]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
self.assertEqual(1, maximum)
def test_invalid_expected_head_and_idempotency_are_rejected(self):
request = self.request()
request["expected_head_oid"] = "short"
with self.assertRaisesRegex(CommitFileError, "writer_expected_head_rejected"):
self.writer().execute(DummyGrant(), request)
request = self.request()
request["idempotency_key"] = "../bad"
with self.assertRaisesRegex(CommitFileError, "writer_idempotency_key_rejected"):
self.writer().execute(DummyGrant(), request)
def test_invalid_message_and_nul_content_are_rejected(self):
request = self.request()
request["message"] = "bad\nmessage"
with self.assertRaisesRegex(CommitFileError, "writer_message_rejected"):
self.writer().execute(DummyGrant(), request)
request = self.request()
request["content"] = "bad\x00content"
with self.assertRaisesRegex(CommitFileError, "writer_content_rejected"):
self.writer().execute(DummyGrant(), request)
def test_force_flags_are_403_and_unknown_fields_are_rejected(self):
for field in ("force", "force_push"):
request = self.request(key=f"writer-force-{field}")
request[field] = True
with self.subTest(field=field), self.assertRaises(CommitFileError) as captured:
self.writer().execute(DummyGrant(), request)
self.assertEqual(403, captured.exception.status)
request = self.request(key="writer-extra-field")
request["operation"] = "commit_file.atomic"
with self.assertRaisesRegex(CommitFileError, "writer_request_fields_rejected"):
self.writer().execute(DummyGrant(), request)
if __name__ == "__main__":
unittest.main()
+206
View File
@@ -0,0 +1,206 @@
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import re
import stat
import zipfile
SHA256 = re.compile(r"^[0-9a-f]{64}$")
MANIFEST_LINE = re.compile(r"^([0-9a-f]{64}) ([^\\\r\n]+)$")
FORBIDDEN_EXACT_VALUES = frozenset({
"EXTERNAL_AFTER_PACKAGING",
"EXAMPLE-NOT-AUTHORIZATION",
"cab17cf731078d5771091f3d4f9507aaaea8988a9b5e77dd993afc93dbaed583",
"163b6c62b895345c184c283fe0a9980358f19555da41f1f8d8b1b225e8492e5f",
"ae4e85261b0e7b2c04474322f29a47e57e61bee5795a9f616e578aa938f92ac0",
"1903664e58b5122a21c507a696a0f52f5a62c5096db1406e3003decbd788a531",
"e5be655427f194992e9e434714e46b0abd7a1d7aca85eb577c791888314da915",
"c5da5e1b089e0efa2021c7051fbeb6bd1fc5ff85c27d59db435fd61a270aaf09",
"0" * 64,
"9" * 64,
})
FORMAL_DECLARATIONS = (
"PACKAGE_COMPONENTS.json",
"PACKAGE_AUDIT.json",
"OFFLINE_TEST_REPORT.json",
)
class PackageClosureError(RuntimeError):
pass
def _relative(path: Path, root: Path) -> str:
value = path.relative_to(root).as_posix()
parsed = PurePosixPath(value)
if parsed.is_absolute() or any(part in {"", ".", ".."} for part in parsed.parts):
raise PackageClosureError("PACKAGE_PATH_INVALID")
return value
def _fixed_files(root: Path, *, include_manifest: bool) -> list[tuple[str, Path]]:
root = root.resolve(strict=True)
if root.is_symlink() or not root.is_dir():
raise PackageClosureError("PACKAGE_ROOT_UNSAFE")
result: list[tuple[str, Path]] = []
for current, directories, files in os.walk(root, topdown=True, followlinks=False):
current_path = Path(current)
for name in list(directories):
candidate = current_path / name
metadata = candidate.lstat()
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise PackageClosureError("PACKAGE_SPECIAL_FILE_PRESENT")
for name in files:
candidate = current_path / name
metadata = candidate.lstat()
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISREG(metadata.st_mode):
raise PackageClosureError("PACKAGE_SPECIAL_FILE_PRESENT")
relative = _relative(candidate, root)
if relative == "MANIFEST.sha256" and not include_manifest:
continue
result.append((relative, candidate))
result.sort(key=lambda item: item[0].encode("utf-8"))
if len({name for name, _ in result}) != len(result):
raise PackageClosureError("PACKAGE_PATH_DUPLICATE")
return result
def write_manifest(root: Path) -> str:
root = Path(root)
entries = _fixed_files(root, include_manifest=False)
lines = [f"{hashlib.sha256(path.read_bytes()).hexdigest()} {name}\n" for name, path in entries]
raw = "".join(lines).encode("ascii")
(root / "MANIFEST.sha256").write_bytes(raw)
return hashlib.sha256(raw).hexdigest()
def _walk_values(value: object):
if isinstance(value, dict):
for key, child in value.items():
yield str(key)
yield from _walk_values(child)
elif isinstance(value, list):
for child in value:
yield from _walk_values(child)
elif isinstance(value, str):
yield value
def _validate_declarations(root: Path) -> None:
components_path = root / "PACKAGE_COMPONENTS.json"
try:
components = json.loads(components_path.read_text(encoding="utf-8"))
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
raise PackageClosureError("PACKAGE_COMPONENTS_INVALID") from exc
if not isinstance(components, dict):
raise PackageClosureError("PACKAGE_COMPONENTS_INVALID")
if "package_zip_sha256" in components:
raise PackageClosureError("ZIP_DIGEST_SELF_REFERENCE_FORBIDDEN")
if components.get("package_zip_sha256_source") != "EXTERNAL_SIDECAR":
raise PackageClosureError("ZIP_DIGEST_SOURCE_INVALID")
for field in ("wheel_sha256", "deployment_definitions_sha256"):
value = components.get(field)
if not isinstance(value, str) or not SHA256.fullmatch(value):
raise PackageClosureError("COMPONENT_DIGEST_INVALID")
for name in FORMAL_DECLARATIONS:
path = root / name
if not path.is_file():
if name == "PACKAGE_COMPONENTS.json":
raise PackageClosureError("FORMAL_DECLARATION_MISSING")
continue
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise PackageClosureError("FORMAL_DECLARATION_INVALID") from exc
if any(item in FORBIDDEN_EXACT_VALUES for item in _walk_values(value)):
raise PackageClosureError("STALE_OR_PLACEHOLDER_DECLARATION")
def validate_package(root: Path) -> dict[str, str | int]:
root = Path(root)
_validate_declarations(root)
files = _fixed_files(root, include_manifest=False)
manifest_path = root / "MANIFEST.sha256"
try:
lines = manifest_path.read_text(encoding="ascii").splitlines()
except (OSError, UnicodeDecodeError) as exc:
raise PackageClosureError("MANIFEST_INVALID") from exc
observed: dict[str, str] = {}
for line in lines:
match = MANIFEST_LINE.fullmatch(line)
if match is None:
raise PackageClosureError("MANIFEST_INVALID")
digest, name = match.groups()
parsed = PurePosixPath(name)
if parsed.is_absolute() or any(part in {"", ".", ".."} for part in parsed.parts):
raise PackageClosureError("MANIFEST_PATH_INVALID")
if name in observed or name == "MANIFEST.sha256":
raise PackageClosureError("MANIFEST_PATH_DUPLICATE")
observed[name] = digest
expected_names = [name for name, _ in files]
if list(observed) != expected_names:
raise PackageClosureError("MANIFEST_COVERAGE_MISMATCH")
for name, path in files:
if hashlib.sha256(path.read_bytes()).hexdigest() != observed[name]:
raise PackageClosureError("MANIFEST_HASH_MISMATCH")
return {
"status": "PASS",
"files_verified": len(files),
"manifest_sha256": hashlib.sha256(manifest_path.read_bytes()).hexdigest(),
}
def _archive_mode(name: str) -> int:
executable_prefixes = ("deploy/bin/", "deploy/actions/")
leaf = PurePosixPath(name).name
executable = name.startswith(executable_prefixes) and "." not in leaf
return 0o100755 if executable else 0o100644
def build_deterministic_zip(root: Path, output: Path, sidecar: Path) -> str:
root = Path(root).resolve(strict=True)
output, sidecar = Path(output).resolve(), Path(sidecar).resolve()
if output == sidecar or output.is_relative_to(root) or sidecar.is_relative_to(root):
raise PackageClosureError("ARCHIVE_OUTPUT_LOCATION_INVALID")
validate_package(root)
output.parent.mkdir(parents=True, exist_ok=True)
sidecar.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(
output,
mode="w",
compression=zipfile.ZIP_DEFLATED,
compresslevel=9,
strict_timestamps=True,
) as archive:
for name, path in _fixed_files(root, include_manifest=True):
info = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))
info.create_system = 3
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = _archive_mode(name) << 16
archive.writestr(info, path.read_bytes())
digest = hashlib.sha256(output.read_bytes()).hexdigest()
sidecar.write_text(f"{digest} {output.name}\n", encoding="ascii", newline="\n")
return digest
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="build-v5r1-package")
parser.add_argument("--source", required=True, type=Path)
parser.add_argument("--output-zip", required=True, type=Path)
parser.add_argument("--sidecar", required=True, type=Path)
parser.add_argument("--rewrite-manifest", action="store_true")
args = parser.parse_args(argv)
if args.rewrite_manifest:
write_manifest(args.source)
digest = build_deterministic_zip(args.source, args.output_zip, args.sidecar)
print(json.dumps({"status": "PASS", "package_zip_sha256": digest}, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,286 @@
# AIOS V2R1C4 End-to-End Execution Requirements V5
## Goal
Use only the V5 task-scoped control plane. Continue autonomously until
V2R1C4 is fully deployed, freshly accepted, tagged, registered and set as
the Production Baseline.
Do not report `COMPLETED` until every condition in
`FINAL_ACCEPTANCE_CONTRACT_V5.md` is independently true.
## 1. Verify V5 delivery
Verify:
```text
external ZIP SHA-256
MANIFEST.sha256
Wheel SHA-256
SYSTEMD_UNITS.sha256
Manifest Schema SHA-256
runtime-layout Schema SHA-256
```
Run the complete tests with zero failure and zero skip.
Reject V1, V2 or V3 units, paths, credentials, Wheels or deployment
definitions.
## 2. Verify all six control-plane services
The service set is Anchor, Approval Observer, Writer, Controller, Publisher,
and the root Action Broker. Every non-root role unit must use:
```text
RuntimeDirectory=aios-v2r1c4-release-v5/<role>
RuntimeDirectoryPreserve=no
StateDirectory=aios-v2r1c4-release-v5/<role>
```
The root Action Broker uses the separately created root-managed shared runtime
parent. All sockets, state, environment and executable paths must be
V5-scoped.
Do not create a drop-in to repair a mismatch. A drop-in is a new unapproved
deployment definition.
## 3. Close the fixed Artifact's external dependency
Safely extract the fixed Release Artifact without following links.
Enumerate every symlink and special file. The only approved absolute link is:
```text
vendor/openclaw-weixin/node_modules/openclaw
→ /usr/lib/node_modules/openclaw
```
Compute the full values:
```bash
sha256sum /usr/lib/node_modules/openclaw/package.json
aios-task-release tree-sha256 \
--root /usr/lib/node_modules/openclaw
```
Verify:
```text
package name=openclaw
package version=2026.6.11
package_json_sha256=<full 64-character value>
target_tree_sha256=<full 64-character value>
```
A digest prefix such as `fe854d…` is not acceptable.
Generate the exact candidate production unit. It must include:
```text
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/usr/lib/node_modules/openclaw
```
`BindReadOnlyPaths` is also acceptable. Compute and bind the exact unit
SHA-256.
Generate and verify `runtime-layout.json`. Stop if any undeclared absolute
link, escaping relative link, special file, package mismatch, Tree mismatch,
unit mismatch or missing read-only binding exists.
## 4. Refreeze downstream release objects
Reuse only:
```text
source_commit_oid=1857b88690cd1c0119df984534c260b6f217a21a
source_tree_oid=17c153de2338f570f70cb7407e7dda3c596b524b
release_artifact_sha256=39523caa48f39b33e5e5df785bb568e0381d8b20301746c280442f73f294f2b2
rollback_artifact_sha256=dd0dbbe21db14722996636347ea1d22917436c688d5f0b7055b5bfb1776c4d95
```
Put the approved runtime-layout digest into the Release Root input. Generate
and verify the Release Root and Evidence Manifest.
Create one new evidence closure commit directly on the fixed source. Only
approved evidence and generator inputs may be added. Product code must remain
byte-identical.
Build a connected Git Bundle, verify ancestry and `git fsck`, then calculate
the deterministic annotated V2R1C4 Tag object.
## 5. Create the exact Owner approval payload
Populate the final V5 Manifest with all exact OIDs, Trees and SHA-256 values.
Generate:
```bash
aios-task-release approval-payload \
--manifest <preapproval-manifest>
```
Obtain one unexpired machine-readable Owner approval for the exact payload.
Do not reuse PR #34, a Phase-A review, a V3 approval or chat text.
## 6. Reconcile Authority main
Through the separately governed mirror mechanism, perform only the approved
fast-forward:
```text
875d41c3101093149414292067fd700dc214d4d3
→
8291b8368bf690416a3159ac5d21d9f8139c2e61
```
Authority ref, Gitea ref and Gitea API must all equal the new OID. The
task-scoped Writer must not receive general `main` permission.
## 7. Install only V5 services
Install:
```text
aios-v2r1c4-release-anchor-v5.service
aios-v2r1c4-release-writer-v5.service
aios-v2r1c4-release-controller-v5.service
aios-v2r1c4-release-publisher-v5.service
```
Use distinct non-root identities and expiring exact ACLs.
- Writer: approved candidate branch only.
- Controller: no Git/Gitea write credential.
- Publisher: locked until all machine gates pass.
Keep:
```text
AIOS_GITOPS_WRITES_ENABLED=false
```
## 8. Execute the state machine
```text
record_main_reconciliation
import_exact_objects
publish_exact_branch
deploy_candidate
migrate_owner_identity
promote_production
scan_core_metadata
record_fresh_acceptance
publish_exact_tag
write_release_registry
write_production_baseline
revoke_task_credentials
complete
```
`deploy_candidate` is isolation-only and must prove production is unchanged;
it must not emit a production-promotion receipt. `promote_production` is the
only operation allowed to emit that receipt. Registry and baseline each use
one Anchor reservation for the complete C3 then C4 read -> single governed
commit-file -> wait -> reread sequence; C3 facts may not reuse C4 hashes.
Every operation-sequence entry has one content-addressed
`approved_action_plans` object without a self-digest. All 13 transitions bind
its canonical digest through the Manifest, approval payload, operation request
`action_plan_sha256`, and the corresponding Anchor request. Reserving actions
include it in `request_sha256`, fresh acceptance includes it in the atomic
consumption request SHA, and `complete` sends it directly. The eight
root-brokered transitions additionally bind
`config.actions[action].plan_sha256` and the broker payload. Direct and
Anchor-only transitions do not invent broker entries. API reads use only
`127.0.0.1`; pushes use only `g.cnnetmkt.top`.
Before object import, the cache gate must independently verify:
```text
Artifact and Rollback
runtime layout
candidate production unit
Release Root
Evidence Manifest
Git Bundle
```
## 9. Production acceptance
Verify rollback before the first production side effect.
Complete Owner identity migration with zero raw Owner ID occurrences and
complete the core metadata scan.
Wait for a new natural trusted Owner WeChat protected-dispatch event. Do not
inject, forge, replay or directly call the internal endpoint.
## 10. Formal publication
Only after every machine gate passes:
1. publish the exact annotated V2R1C4 Tag;
2. verify Tag object and peeled target in Authority and Gitea;
3. write Registry V2R1C4;
4. update Production Baseline to V2R1C4 / `PRODUCTION_DEPLOYED`;
5. revoke all temporary accounts, Tokens, ACLs and credential projections;
6. complete the Anchor.
## 11. Automatic recovery
Automatically retry bounded transient network, TLS, DNS, startup,
credential-projection and remote-visibility failures.
For an open Anchor reservation, reconcile the real effect before retrying.
Automatically roll back a failed candidate deployment when the approved
rollback asset remains verifiable.
Stop only for:
```text
missing or expired approval
non-fast-forward main
fixed source or Artifact mismatch
runtime-layout object mismatch
same-name different-OID branch or Tag
path outside approval
real Secret detection
unverified rollback
fresh acceptance safety failure
required change to an approved object
```
## 12. Final report
Always include:
```text
force_push_used=false
tag_rewritten=false
direct_main_push=false
secrets_committed=false
owner_approval_respected=true
```
## Fixed V5R1 component digests
```text
wheel_sha256=91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19
deployment_definitions_sha256=b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0
manifest_schema_sha256=31bce5c2960d8c57b26e0fa854196c17e6f018cd547b58679b7877cb602df4f4
runtime_layout_schema_sha256=658813b8a0096ab5ee66dd217dc0bbb1b08e09dc33241049f24190bb4df86c9d
exact_two_parent_broker_sha256=eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4
broker_schema_sha256=72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba
validator_schema_sha256=95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22
site_config_sha256=be44861e717513e67b532fdb2f20b67a96aad07e212d521d4a69148ca346760c
```
The external ZIP SHA-256 is supplied beside the ZIP. The real production
site-config, external OpenClaw Tree, full package.json digest and candidate
production-unit digest must be calculated before generating the final Owner
approval payload.
@@ -0,0 +1,358 @@
# AIOS V2R1C4 End-to-End Execution Requirements V5
## Goal
Use only the V5 task-scoped control plane. Continue autonomously until
V2R1C4 is fully deployed, freshly accepted, tagged, registered and set as
the Production Baseline.
Do not report `COMPLETED` until every condition in
`FINAL_ACCEPTANCE_CONTRACT_V5.md` is independently true.
## 1. Verify V5 delivery
Verify:
```text
external ZIP SHA-256
MANIFEST.sha256
Wheel SHA-256
SYSTEMD_UNITS.sha256
Manifest Schema SHA-256
runtime-layout Schema SHA-256
```
Run the complete tests with zero failure and zero skip.
Reject V1, V2 or V3 units, paths, credentials, Wheels or deployment
definitions.
## 2. Verify the task-role units and identities
Every unit must use:
```text
RuntimeDirectory=aios-v2r1c4-release-v5
RuntimeDirectoryPreserve=no
StateDirectory=aios-v2r1c4-release-v5/<role>
```
All sockets, state, environment and executable paths must be V5-scoped.
Do not create a drop-in to repair a mismatch. A drop-in is a new unapproved
deployment definition.
Verify the installed unit identity and peer boundary exactly:
```text
Anchor: aios-v2r1c4-task-anchor / aios-v2r1c4-release
Approval observer: aios-v2r1c4-approval-observer / aios-v2r1c4-release
Writer: aios-v2r1c4-task-writer / aios-v2r1c4-release
Controller: aios-v2r1c4-task-controller / aios-v2r1c4-release
Publisher: aios-v2r1c4-task-publisher / aios-v2r1c4-release
Root action broker: root / root
```
These are distinct service identities, not interchangeable labels. The Writer
process also hosts the loopback metadata Writer runtime on `127.0.0.1:19892`;
its metadata API bearer and Gitea publication credentials belong only to the
Writer unit. The Publisher does not host or inherit those credentials.
## 3. Close the fixed Artifact's external dependency
Safely extract the fixed Release Artifact without following links.
Enumerate every symlink and special file. The only approved absolute link is:
```text
vendor/openclaw-weixin/node_modules/openclaw
→ /usr/lib/node_modules/openclaw
```
Compute the full values:
```bash
sha256sum /usr/lib/node_modules/openclaw/package.json
aios-task-release tree-sha256 \
--root /usr/lib/node_modules/openclaw
```
Verify:
```text
package name=openclaw
package version=2026.6.11
package_json_sha256=<full 64-character value>
target_tree_sha256=<full 64-character value>
```
A digest prefix such as `fe854d…` is not acceptable.
Generate the exact candidate production unit. It must include:
```text
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/usr/lib/node_modules/openclaw
```
`BindReadOnlyPaths` is also acceptable. Compute and bind the exact unit
SHA-256.
Generate and verify `runtime-layout.json`. Stop if any undeclared absolute
link, escaping relative link, special file, package mismatch, Tree mismatch,
unit mismatch or missing read-only binding exists.
## 4. Refreeze downstream release objects
Reuse only:
```text
source_commit_oid=1857b88690cd1c0119df984534c260b6f217a21a
source_tree_oid=17c153de2338f570f70cb7407e7dda3c596b524b
release_artifact_sha256=39523caa48f39b33e5e5df785bb568e0381d8b20301746c280442f73f294f2b2
rollback_artifact_sha256=dd0dbbe21db14722996636347ea1d22917436c688d5f0b7055b5bfb1776c4d95
```
Put the approved runtime-layout digest into the Release Root input. Generate
and verify the Release Root and Evidence Manifest.
Create one new evidence closure commit directly on the fixed source. Only
approved evidence and generator inputs may be added. Product code must remain
byte-identical.
Build a connected Git Bundle, verify ancestry and `git fsck`, then calculate
the deterministic annotated V2R1C4 Tag object.
## 5. Create the exact Owner approval payload
Populate the final V5 Manifest with all exact OIDs, Trees and SHA-256 values.
Generate:
```bash
aios-task-release approval-payload \
--manifest <preapproval-manifest>
```
Obtain one unexpired machine-readable Owner approval for the exact payload.
Do not reuse PR #34, a Phase-A review, a V3 approval or chat text.
## 6. Reconcile Authority main
Through the separately governed mirror mechanism, perform only the approved
fast-forward:
```text
875d41c3101093149414292067fd700dc214d4d3
→
8291b8368bf690416a3159ac5d21d9f8139c2e61
```
Authority ref, Gitea ref and Gitea API must all equal the new OID. The
task-scoped Writer must not receive general `main` permission.
## 7. Install only V5 services
Install:
```text
aios-v2r1c4-release-anchor-v5.service
aios-v2r1c4-release-approval-observer-v5.service
aios-v2r1c4-release-writer-v5.service
aios-v2r1c4-release-controller-v5.service
aios-v2r1c4-release-publisher-v5.service
aios-v2r1c4-root-action-broker.service
```
Use the exact identities listed in section 2 and expiring exact ACLs. Only the
root action broker is root; all other roles are distinct non-root identities.
- Writer: approved candidate branch only.
- Controller: no Git/Gitea write credential.
- Publisher: locked until all machine gates pass.
Keep:
```text
AIOS_GITOPS_WRITES_ENABLED=false
```
## 8. Execute the state machine
```text
record_main_reconciliation
import_exact_objects
publish_exact_branch
deploy_candidate
migrate_owner_identity
promote_production
scan_core_metadata
record_fresh_acceptance
publish_exact_tag
write_release_registry
write_production_baseline
revoke_task_credentials
complete
```
`deploy_candidate` is isolation-only and must prove production is unchanged;
it must not emit a production-promotion receipt. `promote_production` is the
only operation allowed to emit that receipt, and post-promotion scan and fresh
acceptance cannot run before it commits. Registry and baseline each execute
their entire C3 then C4 transition under one Anchor reservation, using
read -> one governed `/api/commit-file` write -> visibility wait -> reread for
each stage. Historical C3 Artifact hashes must be independently supplied and
must not equal the fixed C4 hashes.
Before every state transition, compute the canonical SHA-256 of the exact
`approved_action_plans[action]` object. All 13 transitions require equality
between the Manifest plan, approval payload, and operation request
`action_plan_sha256`. Reserving transitions include the digest in the Anchor
request SHA; fresh acceptance includes it in the atomic consumption request
SHA; `complete` submits it directly to Anchor. The eight root-brokered
transitions additionally require
equality with `config.actions[action].plan_sha256` and the broker request
payload. The five direct or Anchor-only transitions do not invent broker
configuration entries. Plans cover the complete `operation_sequence`,
including `complete`, and never contain a `plan_sha256` field themselves. API
observation is restricted to `127.0.0.1`; Git push is restricted to
`g.cnnetmkt.top`.
For the eight brokered transitions, `_run_bound` must emit the exact wrapper
shape with `execute=true`, authorization, idempotency key, Manifest digest and
request plan digest. The broker rejects the legacy three-field request,
authenticates the peer role, and injects its startup-pinned action-program and
canonical config SHA-256 into the strict action-program payload. Anchor reserve
remains solely in the operation service; broker execution must not reserve or
advance Anchor independently.
Before executing, the root broker must resolve the Anchor snapshot as the
configured caller identity and prove all three of the following: the Manifest
digest matches, the campaign state equals the action's required Anchor state,
and exactly one open reservation matches the action and idempotency key. A
missing reservation is `ANCHOR_RESERVATION_MISSING`; state drift is fail-closed.
For actions with predecessors, the broker accepts only committed Anchor PASS
envelopes whose producer plan digest matches the broker configuration. It
writes their canonical JSON to a root-created, mode-0400 memfd sealed against
write, grow, shrink and further seal changes, then passes only that descriptor
to the privilege-dropped action child. Caller JSON containing
`anchored_predecessor_evidence` is rejected.
Every Anchor terminal envelope, including failures, must contain exactly:
```text
authorization_id
manifest_sha256
operation
producer_action_plan_sha256
idempotency_key
status # PASS or FAIL
payload
evidence_sha256 # SHA-256 of the canonical seven fields above
chain_hash
```
The snapshot must place PASS envelopes in `committed_operations` and FAIL
envelopes in `failed_operations`; status/state disagreement, missing envelope,
or digest mismatch is corruption and stops execution.
Do not conflate quarantine scopes. `record_main_reconciliation` is pinned to
`/run/aios-v2r1c4-release-v5/quarantine/main-reconciliation.git`; writer-side
object import remains scoped by site config to
`/var/lib/aios-v2r1c4-release-v5/quarantine`.
Before object import, the cache gate must independently verify:
```text
Artifact and Rollback
runtime layout
candidate production unit
Release Root
Evidence Manifest
Git Bundle
```
## 9. Production acceptance
Verify rollback before the first production side effect.
This is a live check, not a Manifest assertion: observe current production
active/health state, verify that the rollback archive is present, readable and
matches its approved SHA-256, and verify the rollback worktree's exact commit
and tree OIDs. `promote_production` must emit that observation and
`rollback_verified_before_switch=true`. If promotion fails, verify the restored
C3 service and health; an attempted rollback without verified restoration is a
terminal block.
Complete Owner identity migration with zero raw Owner ID occurrences and
complete the core metadata scan.
Wait for a new natural trusted Owner WeChat protected-dispatch event. Do not
inject, forge, replay or directly call the internal endpoint.
Approval binds the content-addressed fresh-acceptance derivation contract, its
templates, owner principal, release target, runtime layout, production unit,
observer status, and dynamic JSON pointer
`/fresh_acceptance_evidence_sha256`. It does not bind a guessed future evidence
file or evidence digest. The concrete digest is produced only by the new event,
revalidated by the independent observer as
`SIGNATURE_RECOMPUTED_AND_REPLAY_CLEAR`, and atomically committed by Anchor.
## 10. Formal publication
Only after every machine gate passes:
1. publish the exact annotated V2R1C4 Tag;
2. verify Tag object and peeled target in Authority and Gitea;
3. write Registry V2R1C4;
4. update Production Baseline to V2R1C4 / `PRODUCTION_DEPLOYED`;
5. revoke all temporary accounts, Tokens, ACLs and credential projections;
6. complete the Anchor.
## 11. Automatic recovery
Automatically retry bounded transient network, TLS, DNS, startup,
credential-projection and remote-visibility failures.
For an open Anchor reservation, reconcile the real effect before retrying.
Automatically roll back a failed candidate deployment when the approved
rollback asset remains verifiable.
Stop only for:
```text
missing or expired approval
non-fast-forward main
fixed source or Artifact mismatch
runtime-layout object mismatch
same-name different-OID branch or Tag
path outside approval
real Secret detection
unverified rollback
fresh acceptance safety failure
required change to an approved object
```
## 12. Final report
Always include:
```text
force_push_used=false
tag_rewritten=false
direct_main_push=false
secrets_committed=false
owner_approval_respected=true
```
## Closure-generated V5 component evidence
The external ZIP SHA-256 is supplied beside the ZIP. Wheel, deployment
definition, schema, Manifest, systemd and package digests and the final test
totals are generated and recorded by the closure rebuild; this document does
not predict them. The real production site-config, external OpenClaw Tree,
full package.json digest and candidate production-unit digest must be
calculated before generating the final Owner approval payload.
@@ -0,0 +1,61 @@
# Code Development Report V5
V5 succeeds V4. Fixed product source and input-artifact hashes are unchanged;
the following V5 implementation work changes only the release-control-plane
package and must be reflected by rebuilt package digests.
Implemented:
- six V5-isolated systemd service definitions and V5 tmpfiles coverage;
- regression tests for exact runtime/state paths and effective unit/drop-in
evidence;
- task Manifest schema v5 plus `AIOS_RUNTIME_LAYOUT_V1` Release Root
cross-binding;
- safe tar extraction that rejects traversal, special files, undeclared
absolute links, and escaping link targets;
- binding of the actual `--release-artifact` archive to the generated extracted
Artifact file manifest;
- writable-path overlap rejection for the fixed read-only OpenClaw dependency;
- external dependency package metadata/tree validation and symlink policy;
- mandatory candidate/effective production-unit digest equality and explicit
no-drop-in verification, including `ProtectSystem=strict`,
`NoNewPrivileges=true`, systemd list-reset handling, and read-only bindings;
- V5-scoped systemd paths in the manifest and validation contract;
- CLI support for `--release-artifact`, mandatory effective-unit/no-drop-in
inputs, `artifact-extract`, and `artifact-file-manifest-generate`;
- exact fixed OpenClaw dependency identity, safe archive snapshot parsing,
bounded member counts, and complete special-member pre-scan;
- strict publisher-unlock receipt/evidence/OID binding and path-safe quarantine
validation;
- cache-gate integration and tamper coverage;
- durable full Anchor PASS/FAIL evidence envelopes with digest and chain
validation;
- root-broker enforcement of an existing Anchor reservation and exact campaign
state, with Anchor-resolved predecessors delivered through a sealed memfd;
- caller-predecessor rejection and thin AF_UNIX broker passthrough wrappers;
- Writer-role hosting of the loopback metadata Writer and its isolated
credentials;
- live pre-switch rollback artifact/worktree/production-health verification and
verified restoration reporting;
- a content-addressed fresh-acceptance derivation contract that binds templates
and the dynamic JSON pointer without predicting a future evidence digest.
Validation totals and package/component hashes are generated by the final
closure run and recorded in its machine-readable reports. This development
report does not predict those values. Package rebuild, digest generation,
human Phase B approval, live deployment, and fresh production acceptance remain
separate release gates.
No AIOS/Gitea ref, system service, account, token, ACL, production Artifact,
tag, registry, or baseline was changed during development.
## Digest status
Stale V4 component digest claims have been removed. Every V5 package/component
digest is closure-generated and is recorded only after the final rebuild. Fixed
product source and input-artifact hashes remain unchanged and are not replaced
by future V5 package digests.
No production action is authorized by this report. The human Phase B gate is
mandatory, and no production effect may occur before exact approval is present,
current and independently observed.
@@ -0,0 +1,86 @@
# Control-Plane Fixes V5
V5 succeeds V4 and preserves the fixed product source and input-artifact
hashes. It replaces V4 closure assumptions with a schema-v5, evidence-backed
control-plane contract.
## V5-scoped systemd contract
All V5 services use only the V5 namespace:
```text
/run/aios-v2r1c4-release-v5
/var/lib/aios-v2r1c4-release-v5/<role>
/etc/aios/v2r1c4-release-v5
/opt/aios/v2r1c4-release-v5
```
Validation rejects V3 or unversioned runtime/state paths, non-V5 tmpfiles,
and V5 unit definitions whose effective configuration escapes these paths.
The evidence subject is the approved production fragment plus an independently
captured effective fragment. Their digests must match and the resolved drop-in
set must be explicitly empty. Deployment evidence separately binds the
installed fragment path, digest and empty `DropInPaths`, together with
`ProtectSystem=strict`, `NoNewPrivileges=true`, and the required
`ReadOnlyPaths` or `BindReadOnlyPaths`.
## Artifact and runtime-layout closure
Safe extraction rejects archive traversal entries, special files, excessive
member counts, symlink ancestors and undeclared or escaping links. Tar parsing
uses a private snapshot populated through the same descriptor that computes
the expected archive digest. The closure binds that archive and a generated
extracted Artifact file manifest. It rejects writable-path overlap with the
mandatory read-only external dependency.
Task Manifest schema v5 records:
- the fixed Artifact digest and the extracted-file-manifest digest;
- declared external symlinks and external dependency metadata/tree digest;
- the candidate/effective production-unit digest and explicit no-drop-in
evidence;
- V5-scoped paths, read-only bindings, and writable-path non-overlap;
- extraction, symlink, and special-file policies.
`artifact-extract` and `artifact-file-manifest-generate` provide the required
safe-extraction and file-manifest inputs before `runtime-layout-generate` or
`runtime-layout-verify` is run.
## Release Root binding
The Release Root binds the approved runtime-layout SHA-256. Any change to the
archive, extracted file manifest, candidate/effective unit or drop-in set, external
dependency, read-only binding, or permitted writable path changes the closure
and requires regenerated approval evidence.
V4 component digests are not V5 evidence. V5 package/component digests remain
closure-generated until final packaging; fixed product source and input-artifact
hashes remain unchanged.
## Anchor-owned execution evidence
The operation service alone reserves and commits or fails an Anchor operation.
The root broker must find the matching existing reservation and exact campaign
state before it runs an action. It resolves predecessor results from Anchor,
validates the full PASS envelopes and their producer plan bindings, and passes
the canonical list through a root-created mode-0400 memfd sealed against write,
grow and shrink. Neither operation-service JSON nor wrapper JSON is an
authoritative predecessor channel.
PASS and FAIL are both durable full envelopes containing authorization,
Manifest, operation, producer plan, idempotency key, status, payload, canonical
evidence digest and chain hash. A failure is retained in `failed_operations`
and releases its reservation quota without advancing state.
The deployed wrapper is a thin AF_UNIX broker passthrough. It validates strict
request/response shapes and evidence digests, removes service-only predecessor
data, and forwards no credential material. Production actions execute only in
the pinned root-broker action program; `live_actions` remains non-production
compatibility/test code.
The Writer service, under `aios-v2r1c4-task-writer`, hosts the loopback metadata
Writer and alone receives its two credentials. Registry and baseline C4 bytes
are derived after Anchor has durably recorded the natural fresh acceptance.
Approval therefore binds the derivation contract and templates, never a future
evidence filename or guessed evidence SHA-256.
@@ -0,0 +1,26 @@
# External Closure Requirements V5
Code can generate and verify the runtime layout, Release Root, Evidence
Manifest, evidence closure, Git Bundle and Tag.
It cannot manufacture these external governance decisions:
1. authorization for the exact Authority main fast-forward;
2. an unexpired machine-readable Owner approval for the final V5 payload;
3. task-scoped Writer and Publisher credentials;
4. exact Authority filesystem ACLs for those temporary identities.
The Owner approval must bind:
- V5 ZIP, Wheel and deployment-definition digests;
- the real site-config digest;
- Manifest and runtime-layout Schema digests;
- source/evidence OIDs and trees;
- Release Artifact and Rollback digests;
- runtime-layout, Release Root and Evidence Manifest digests;
- candidate production unit digest;
- external OpenClaw package and Tree digests;
- Git Bundle and deterministic Tag OID.
PR #34, an expired Phase-A review, a V3 approval or chat text is not
sufficient.
@@ -0,0 +1,48 @@
# Final Acceptance Contract V5
Completion requires:
```text
control_plane_systemd_isolation=PASS
runtime_layout_closure=PASS
absolute_artifact_symlink_count=1
undeclared_absolute_symlink_count=0
openclaw_package_json_sha256=<approved full SHA-256>
openclaw_package_version=2026.6.11
openclaw_target_tree_sha256=<approved SHA-256>
production_unit_read_only_binding=PASS
release_root_generation=PASS
evidence_manifest_generation=PASS
approved_tag_oid
= local_tag_oid
= authority_tag_oid
= gitea_tag_ref_oid
approved_target_oid
= local_peeled_target_oid
= authority_peeled_target_oid
= gitea_api_target_oid
= production_target_oid
= registry_target_oid
= baseline_target_oid
authority_main_oid
= gitea_main_ref_oid
= gitea_main_api_oid
= 8291b8368bf690416a3159ac5d21d9f8139c2e61
production_status=ACTIVE
production_acceptance=PASS
registry_version=V2R1C4
production_baseline=V2R1C4
baseline_status=PRODUCTION_DEPLOYED
temporary_accounts_remaining=0
temporary_credentials_remaining=0
old_tokens_http_status=401
anchor_state=COMPLETE
anchor_open_operations=[]
AIOS_GITOPS_WRITES_ENABLED=false
```
@@ -0,0 +1,150 @@
b016f98c7100546e703a3bda1416b3e2b309ae9ce37a520d3f9cf42f4d9894b7 AGENT_EXECUTION_REQUIREMENTS.md
4c621b1ee915922808f05a0e39a03e837cb9a5038f37a72a101743e1d6ee26fd AGENT_EXECUTION_REQUIREMENTS_V5.md
4cfffaa3efc10eec80a50e839c411f29e6bedf781d11fc837367d1120927ddf4 CODE_DEVELOPMENT_REPORT_V5.md
3b66b3093d9c140ea733123a1cc3540307b033fe518a3af5e4d06abd47376c42 CONTROL_PLANE_FIXES_V5.md
f2a5917057bdcb70ef2a1b0384e6738d9178a4571ba2bdd2371dddb78edd51a9 EXTERNAL_CLOSURE_REQUIREMENTS_V5.md
85d4682832d475b03dcc99587a6b3d009d9a5f0ebf2036b43d35d168ccdcde87 FINAL_ACCEPTANCE_CONTRACT_V5.md
008a40f85b6f2eb1b033a9df2e20cbdd2141d6371e6a86db0e2743c0da515699 OFFLINE_TEST_REPORT.json
c45efc3d2de7aafa90a8d943c0f9886180cc01e548c00fb39c394a3252b71a20 PACKAGE_AUDIT.json
02de7d0a1f7602a196dcb458730ccc84082f6695a9960d4b1758c8a0abe8e2d9 PACKAGE_CLOSURE_V5R1.md
3f558c661cfa1d362deb1aa688f233b5ba2a2f75432a2462cb206da6e8e0ce79 PACKAGE_COMPONENTS.json
7a7adae172684fe117282b61b60d2a86b2722bd12222c862bbc63cd5a912fdbb README.md
c3a926e2e55d37998ddbaac1ca161d19300d42cdd4c9ef6cd7a24646ea107fce RECOVERY_AND_RECONCILIATION_V5.md
45a181e41e8eb6de13098d9a8e9468bad5d366153daabcc1b2a4ac115daf6398 RELEASE_REFREEZE_WORKFLOW_V5.md
df08f6023949f8dfc5b0b1d3143b1408db2eb96787eaa42d405f0aed27c4a4f7 RUNTIME_LAYOUT_CLOSURE_V5.md
b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0 SYSTEMD_UNITS.sha256
939495d29782d1f7c063131dcd134c31df0ad07079ab15df99c5886efb3705a6 deploy/actions/action-config.schema.json
413313a03547372988ec871ff30d3fabe767d1c6af13f7f1392c71e7251d8196 deploy/actions/aios-v2r1c4-root-action-runner
162d87f32aa21aed794f89a582a67532415980eed9161781bb6618c5cf88b178 deploy/actions/deploy-candidate
70aaf4febf1c94674c64cef534b15ff0d314e0eb988c1bb7604038c8619a71fb deploy/actions/migrate-owner-identity
232fa6e7737e2d505afe8ed066f6dac6098c40cd6c3092dc56c8374c8f771f1f deploy/actions/promote-production
97b51f4daf26e07380b0f4f57d8cf8e449da1ec5bcbf1f134d52d53b3aa4c7f0 deploy/actions/revoke-task-credentials
8d26b43a886477a130d249825a0dba21ad29d0708332caf2ce1e68605fa20352 deploy/actions/scan-core-metadata
1baa7571b2ff22c60a2ca8b7174e7f22615c048d753793b28c0ebdd93da903ba deploy/actions/write-production-baseline
a239b785a9ddd5975ae10d9820b6d690d161b37e67c291d908f3ee9646db4983 deploy/actions/write-release-registry
c5d20a1c90a713b5d17f95638cfec55b84dbeb05122d5269485d8f70fbc598d5 deploy/bin/aios-task-release
437f8826bf84ba8e3876bd12f2ccc274d1f498424c08b6a44b1e2e0963a1ece7 deploy/bin/aios-task-release-anchor
5f4f83c850240acf8bea951408911dd032b201c8ba60cbc912eaf54ba7d52f5c deploy/bin/aios-task-release-finalizer
5a5ec858035ce59b519b12018f881301d4ff59d281bab840413f4f88b0a4e435 deploy/bin/aios-task-release-operation
dc99c98da6ed5cd4af5a5a2c5a64daf96eefeda39497fd3bd2beba2c76b5846c deploy/bin/aios-task-release-revoker
ca76dd130f0969fcbb5418c4276d4fbbe0671b340ffb2c615098a9989064a8fd deploy/systemd/aios-exact-two-parent-merge-broker@.service
8f564cf7658b1f27666216e57de133677251c9fec298c04444b4b2764a4c2d49 deploy/systemd/aios-v2r1c4-release-anchor-v5.service
e9cf179a5cc75d1dfa644698abad7991acec582fd988ac73f01ba47b37595325 deploy/systemd/aios-v2r1c4-release-approval-observer-v5.service
d1f42014f73a64aa4662d4071a0ccc5523131bbac2b72267548d548d12aba1d8 deploy/systemd/aios-v2r1c4-release-controller-v5.service
fdee4f640bac52d4e85806ad9681c7ec5b7ab695326232308d156c65b5e078be deploy/systemd/aios-v2r1c4-release-publisher-v5.service
138f811d5f4694cb9603718fadfcf6ce8041c348905812f0b0d48cfdae905f51 deploy/systemd/aios-v2r1c4-release-writer-v5.service
5dc58ac4a4f724c276be9f914e76f5ff17ab0eed13086e1c594e2237bfc8c859 deploy/systemd/aios-v2r1c4-root-action-broker.service
440ee7ccac9da3861c04cfaa22768a11c4905f2874d2d776adbdd499de29ef22 deploy/tmpfiles.d/aios-v2r1c4-task-release-v5.conf
f06f8b2aaf0b8127bceb1ab34813a41d2187d1baf9691e6e133c82295122eb42 dist/action-broker.pyz
087c8b66ed95fd5a464dec6b5ffe4b5aba922d3783f069c875ac3a50c1631020 dist/action-program.pyz
91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19 dist/aios_task_scoped_release-1.4.0-py3-none-any.whl
f6df654f786916c277dac30da90c39fc3eadc137acb1ccfe54cd31cd89f57565 examples/01-anchor-register-request.example.json
ed8aada31f951a9d41008d0c1b2d00c4fc19602cd8385d2de84469d58f898900 examples/02-main-reconciliation-request.example.json
03161645c6d65a74076faeaee93ae8c4e27a5ad71096492b3979352e11e4de51 examples/03-import-objects-request.example.json
f74951ab0e833a18a19442201d246bea0019b0a7e058d1de044759b6029a1e86 examples/04-publish-branch-request.example.json
0b4c6a81f4bd662d1536672239af11a0fd0a5d307525c719a0b176ca75b2274b examples/05-deploy-candidate-request.example.json
5cbab1907938a7fe95f8dc63324e0694983fcb04e73546181006dedd3f67de84 examples/06-migrate-owner-request.example.json
5457ca42d3b3003f5b515c2534904086e7c78aeb063ac0d347818da121e6bd74 examples/07-core-scan-request.example.json
91fbd141ca2c6ef228d10cbf6b785d8bf29b43e2958894356a7ab44156dcb199 examples/07-promote-production-request.example.json
2852a013ee9ba2fdb6d22e1139eb8ad1212e9640f0d5e773bb4dbebd8acccd10 examples/08-fresh-acceptance-request.example.json
094937b8503ef85acf9bb734c0057fb8cfb5ddab882ec0a3b9b43011d888ceca examples/09-publish-tag-request.example.json
c10ba5c742278336be74c557c725c38f9cf278e834fb2c675a9d6e08a065782e examples/10-registry-request.example.json
a9799ff1cc8f57f2ad196717dac6b3a136a3c529bd46ee56a2e2759221a21c9a examples/11-baseline-request.example.json
0b64c01ad9b7412dd3099dc506cd69a67d7410f9081c36e2f0334614b45ce22e examples/12-revoke-request.example.json
ae94b5f8ff593ec4222a0bbc014f9b2d42cdfa021caadd2915b7eb83261d64e0 examples/13-complete-request.example.json
07f1e7df8dd4d65b20dbcf7c2cc5648c8c415634244b9a672d95905a175b0e21 examples/core-scan-evidence.example.json
48e69c3ad054c751417ccde7f499e2ee63c852386d2f02098315cd8ed257e50d examples/deployment-evidence.example.json
5a8f3ba118d3520d5fd1bff776eba9607d21f3827b2019ffd3177b4fc4091a70 examples/evidence-closure-input.example.json
d8a680b5178921afed0423cd0da667735932d4db9ecf851ad2fd467762a4428e examples/evidence-manifest.example.json
58c112e7cbd2826d2db36181b49d35f4ec1b4544832a3405cced5f0323d09d64 examples/fresh-acceptance.example.json
093e892c1f8b004bb24061ed29488d86bad2531a5286e9b7ddc4675a93e25d3b examples/main-reconciliation-evidence.example.json
7d68a774a974743784469b53c9d7507991c1d14d7dcf775125716e2e3399a0b4 examples/migration-evidence.example.json
a93b7bef1cc7c6e2095c977b2ff96c376b18fd6addde26d5e3903bd370cc2b01 examples/production-promotion-evidence.example.json
a85fd6da1700d725bbc52586349d4519120db59abd208a6369c654e7ec50cb86 examples/publisher-unlock.example.json
d625ad2a43a281d2893b4097ce703ab2a6e9e56f279fce5f7a4dc52dbe641c7a examples/release-approval-payload.example.json
226a25eaf8d84a924645b792e7928c90ed4ad03c5e178da73f77a5cc3c51068f examples/release-root-input.example.json
f7d1285670928b1927b8b74ff5bc126ceb72c2b5858c1e259ecbdfb177d469a6 examples/release-root.manifest.example.json
a733996ca18c2717572a20f99e3751687530ffb23dbda7e24adf606234a5d833 examples/runtime-layout/aios-v2r1c4-production.service
a426ac32d35c1154e2b47870463142c1084991e2d4de4e72b99ff93327f1f0b8 examples/runtime-layout/runtime-layout.example.json
be44861e717513e67b532fdb2f20b67a96aad07e212d521d4a69148ca346760c examples/site-config.example.json
8966f8326fa13bd1d3a5b79387601502309a9c7ff6d1e482b271e260128d8bdb examples/task-scoped-release.example.json
805d34a78d76e6e6c857c2465f5649369c0eaa7aa9a76d1a5f2856203d3ca9b2 examples/uids.env.example
eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4 governance/aios_single_owner_governance/exact_two_parent_merge_broker.py
42896c609a6a0fddc3a2f408362d8c71121e212cb159130facc0a58de2a2a6b4 governance/aios_single_owner_governance/task_status_merge_broker.py
95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22 governance/exact-two-parent-merge-closure-v1.schema.json
72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba governance/exact-two-parent-merge-grant-v1.schema.json
864cdce2712af7a8cc7b50a5b4a46159addaae615b4f0879da9d450475b8b5fc pyproject.toml
d2e3c6e6d93e633256218d88c457a85213b2039716f096fc49334d3cce0361d1 schemas/candidate-deployment-evidence-v1.schema.json
69e70b5b77196f93f77e8af18a66395bdde91fac15947362e61f531e8fd686a0 schemas/core-metadata-scan-evidence-v1.schema.json
90ca01c457927e87227dd4e3bbfa2d3678a68db6004a668c90dfee7ae924bbe8 schemas/evidence-closure-input-v1.schema.json
faaba4a90a08e1e23243d4968955076d8ef1eab5d8108778976bd51822658218 schemas/evidence-closure-manifest-v1.schema.json
205570100a0fcbd6919ac7c74e2942c0cc3720f2c804e3a4e4f05bf541815575 schemas/fresh-protected-dispatch-acceptance-v1.schema.json
190f4b5bf366f0c67ae495f49ba2094eaca4b4d14bbf3e61f621f32b0b8c6e93 schemas/main-reconciliation-evidence-v1.schema.json
9e63d97bf634913eae5796055df678ff9484a033e756379de628355be011bac8 schemas/owner-identity-migration-evidence-v1.schema.json
2b37ed039e7fa20d4e796bc38593260572f38e9371910c88103c4d09c558259d schemas/production-promotion-evidence-v1.schema.json
2adafd354ae5937ad282967d51960578694fc6530a168294bdb6e14bf36a735a schemas/publisher-unlock-v1.schema.json
47713c8d80e58e9fe5f60c150151d5d99fae16dc62e5d5a49b33b8acac55e2c8 schemas/release-approval-payload-v1.schema.json
1d623e3f6efe166e496641b9563a0d05107a6d4c4989b050fd4c4660362fbb3b schemas/release-root-descriptor-v1.schema.json
947c9c8f9992a73e487b9d643f6d4ac9f167c36eda4978aec1ab2417647edb14 schemas/release-root-input-v1.schema.json
658813b8a0096ab5ee66dd217dc0bbb1b08e09dc33241049f24190bb4df86c9d schemas/runtime-layout-v1.schema.json
4f85f0a5e6bee1546a4ff731f26c1b536d4ba15ec9e8a07412041d7c6db314f4 schemas/task-scoped-release-site-v2.schema.json
31bce5c2960d8c57b26e0fa854196c17e6f018cd547b58679b7877cb602df4f4 schemas/task-scoped-release-v5.schema.json
f61a21e5927135fb26d2b81e233524387fdaa4436178e6c44df49a5bec1a3d2f src/aios_task_scoped_release/__init__.py
935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d src/aios_task_scoped_release/__main__.py
5da41d38d4dc37052aac983dd89a602b35d4bfe0c1cf07d268a5cfcdb5b03adf src/aios_task_scoped_release/acceptance.py
d6954773080d441efad2ad6fd48e0b5af93ab955943a821da2cf972c1417f66c src/aios_task_scoped_release/action_broker.py
19d9a002887ce63127efc92499e132d56d8ef5aa6bd8bc067f94f3f5369dd3d6 src/aios_task_scoped_release/action_client.py
b8f52e528ba3b28531c4bcb221252731dee9558c07295567e3c8fc3e56dc1cbc src/aios_task_scoped_release/action_program.py
b87425b7a1719821a212fb69345cafe0e70024fec1eec176b8e05889ff608ccc src/aios_task_scoped_release/anchor.py
6dde00d8b501eb527bfc0532f895f39fb62466e5cc233ffa47d7ed8fa2e1c029 src/aios_task_scoped_release/anchor_service.py
c591a9af33fcafed8f6b73789eb7095d1127ec22395e5eaba7cb088c4d2c6dd3 src/aios_task_scoped_release/approval_observer.py
a8f62a2616cd53d68ae792f97c9c436ade76b9a587dab1f4187c2fef4ddc12e5 src/aios_task_scoped_release/artifact.py
10dc0257acc6357d0d8bb27b9332d1e379bea8fda2d4d90d3b2586b974fcc51c src/aios_task_scoped_release/broker_passthrough.py
2bb93ad8c492a8c5c94b6d9a47bdf4e1e6dc5729f79903c061495c434f38ceb7 src/aios_task_scoped_release/cache.py
232ba8173c9bee19c8eec781347d2b0aaee6b675aee7d4286522f3276c9dbb9e src/aios_task_scoped_release/cli.py
688d58a92788d619477bad24eb3890945a23bd7c58ee5305b9118d2964c03070 src/aios_task_scoped_release/command.py
452aa7888faf7809e4be183931cd2d07e4e353a401abe2fe5c12aa9872326bda src/aios_task_scoped_release/common.py
c78e8b8ad3b8f65b9c9c93656e556565de80c77db1cd39ea5c968b5800077c99 src/aios_task_scoped_release/contract.py
21e18af44a839f035538de12be22aba0e7fa7e07853416fa6ec12b4c6d5bc6d6 src/aios_task_scoped_release/controller.py
cb0e2e461a8c85a655652df9cfdab4487b49b8de9725d39265b676c9f9041a94 src/aios_task_scoped_release/errors.py
03681a1a191cb0e2e1840351dadcc2ebc13f37a1185f003a11ac0bae31ecd324 src/aios_task_scoped_release/evidence_closure.py
62a8aa163a37d0d0acc911e60b19a1aa5ccf37967b1d67960b62d3914d985633 src/aios_task_scoped_release/gitops.py
83638ed6e23d2bed225c98acc0ea3740516e25c25bc997f611ecbebe629c57e3 src/aios_task_scoped_release/live_actions.py
6937aec2d1526d9649d070b205bdcb712b5305cf9b9a88f0733507b22b1131b7 src/aios_task_scoped_release/metadata_action_handlers.py
13a73feaee064fea70051e301145bcbb252c99e90cda9a4dbe5c1e8a9837ec5a src/aios_task_scoped_release/metadata_writer_runtime.py
36949a793f4e933ddfc1571b30dd87e10cee267969a7e27eea72d5eec84181f3 src/aios_task_scoped_release/metadata_writer_server.py
33e6832239e32e44ee133956e456ec2739c9a3b0468b91152dd718cf5e5d7793 src/aios_task_scoped_release/operation_service.py
b7ef2cc96a4f183cc2afdcc09682331574c762c2216c800e9de4dcbf264d02a4 src/aios_task_scoped_release/release_root.py
cf77b6c34345f281c9d40525ed88c781a758fd4bd97909bd8e8f1b545e44e13f src/aios_task_scoped_release/runtime_action_handlers.py
047b6afb5c6048ed0e40af7169c3df7ada8771b3316c5d68d784a0fef13b0b09 src/aios_task_scoped_release/runtime_layout.py
6cf6d36be915b882332d31b0e1f45a3c2ca754c0bbb0592338821923f107b550 src/aios_task_scoped_release/tag_object.py
b852e0fb0f1fdc86b93cf4e8959ba8bf5d4f7935af483043a7ac23518825818e src/aios_task_scoped_release/unix.py
dff1148041e76d83834e6a3988a439e2ac279142c2aab10e0c75bd08f9a682f1 tests/helpers.py
4fab0f06edead1e21cad63188b377a97062721d56fb65efa08ae2bae0278c050 tests/test_acceptance.py
b9deb424886a37e19963e8cef6f2b73f18f7f2f9a8a508325a35b00f5a697ddc tests/test_action_broker.py
46ef68a61ce5653eb9625540e8e0f8bc40b1bd6085bc9a15e1301b6670bace35 tests/test_action_broker_posix.py
5f1383e74d4864a186334180416fb3ecc27fc8a7c67b4b319b6c1fe65aa40e8e tests/test_action_program.py
ceb3847ba92ea0a8296a3d2246ff937ba5816ababf26b56a3b8570250643e54f tests/test_anchor.py
5785d33c698d88bdbd087d12c57b16b8e299ad537f687969a8186141725ae901 tests/test_anchor_service_roles.py
4bdbe8c350c6c573fd859c5421f4bca3130c326626e8f2ddaad8070c44c24e57 tests/test_anchor_socket.py
451a3bc0d23a59ec94970abdb6bed75b2ce1bd55493fc551bdf70d895cef7010 tests/test_approval_observer.py
6bf08bcbcbac417c52d75f87fe80dc68355ac15c6c6e4c271b0046c1157b8561 tests/test_artifact.py
16de82a79afd8df6e12c42a46e7a2e1d143dd6576baf34b00db5b24074b41567 tests/test_broker_passthrough.py
2519730d2a95f9146ac092fb834959ee832b5091021d9d6c127577cb7c053135 tests/test_cache.py
af85adf4b972b74ef7a20a2f4a3be04a2edbb88b9efb22aeacc5784aad9571ff tests/test_cli_module.py
b8171e11a3e734938320eabe2239defe3b59a248b3bc71cacf1e6b5b568b97f1 tests/test_command.py
9a5c1eea7d27b1fe81eb1eaf70695950e60ba5eecfb4a58d83b1212f0dbcbf4f tests/test_contract.py
ab7725744907c4a16342aae14d3b34044eedf37472ed93bcf94865d2e65aa2b6 tests/test_controller.py
6767ddd903a58b1b9c9736a5f23c2e1a669093421a45573c0e9552a91284ce94 tests/test_evidence_closure.py
68b49e70d2b4a70910a7bdaf6f8f192c6b62ebd26de850e325a9057c95e9ca66 tests/test_gitops.py
10e9b20ebe40ace2b8f576ddb1c847cf0b3b87a228a888928ee959783fdc2f49 tests/test_json_schemas.py
83dd25df4f913a5a632406321bc703812c5059e91ec42e96ab4b979dec707e93 tests/test_live_actions.py
6357424ff92ae7d19c8d545fdaa99a0c632d6e090ac38fa29593643fef8123b6 tests/test_metadata_action_handlers.py
7e41a9003cda41a2b072dc0a0e39661d63c28f712555d03f5bcbb0d13e68bf9e tests/test_metadata_writer_runtime.py
26d8fb90e29789ec9bf8de4582b1720cf1680305ae296079d2ff6605e1d71cf6 tests/test_metadata_writer_server.py
6e69adf47acfc4dac9b1773bd78a88b7cba21430ed421fc2af9739c53cae1817 tests/test_operation_service.py
c84f8f0ebed526f0fe176204c257b38caa0a57836fdb9e53ee038b07fa5a2e82 tests/test_release_root.py
c4c73bfc1ab891a29e56b115b6b34d1726d5dae5d9b683d789b7ffec5b6e5637 tests/test_root_action_runner.py
b2382bd57de48677ef61cea2cc8d17cf916b75d6215e9faa2f444c271f38c91a tests/test_runtime_action_handlers.py
73201e1537d3e85fa78fbe8b737af87054a69fd5c6b19d6ffd62771e96da386a tests/test_runtime_layout.py
235a7b93c6d66c58eba5a1bc23bdb884dda2d6815ea4584a47159bddf8145e60 tests/test_systemd_and_schema.py
@@ -0,0 +1,49 @@
{
"compileall": "PASS",
"git_fsck_connectivity_only": "PASS",
"live_operations_not_performed": [
"No AIOS or Gitea ref was written by package validation.",
"No V5R1 service, account, token, credential or ACL was installed.",
"No production, tag, Registry or Baseline object was changed."
],
"package": "AIOS-V2R1C4-TASK-SCOPED-RELEASE-V5R1",
"package_revision": "V5R1",
"package_version": "1.4.0",
"platform": {
"git": "2.43.0",
"python": "3.12.3",
"system": "Linux x86_64",
"systemd": "255"
},
"runtime_dependencies": [],
"schemas_validated": 17,
"status": "PASS",
"systemd_staged_root": {
"deployment_definitions_sha256": "b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0",
"services_verified": 7,
"status": "PASS"
},
"tests": {
"collection_errors": 0,
"duration_seconds": 9.953,
"failed": 0,
"passed": 391,
"skipped": 0,
"suites": {
"exact_two_parent_and_package_closure": 14,
"task_scoped_release_control_plane": 377
},
"total": 391
},
"wheel": {
"filename": "aios_task_scoped_release-1.4.0-py3-none-any.whl",
"reproducible_two_builds": true,
"sha256": "91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19",
"source_files_verified": 30
},
"zipapp": {
"action_broker_sha256": "0a4833127697c8a7a4ed88c2b2c2433621ed9bb7a767047abcd2e0b8ec773558",
"action_program_sha256": "245cda7c90f40a3c85d68e29bb927d367d8b405857dd6f235b547cbb3e9d8df8",
"reproducible_two_builds": true
}
}
@@ -0,0 +1,27 @@
{
"candidate_unit_read_only_binding": "PASS",
"direct_main_push_implementation_present": false,
"exact_two_parent_merge_scope": "governance/approvals",
"external_absolute_symlink_policy": "DECLARED_ONLY",
"formal_declaration_placeholder_scan": "PASS",
"forbidden_git_hits": [],
"force_push_implementation_present": false,
"global_gitops_write_switch_required": false,
"manifest_excludes_itself": true,
"manifest_relative_sorted_unique_paths": "PASS",
"package_revision": "V5R1",
"package_zip_sha256_source": "EXTERNAL_SIDECAR",
"path_traversal_entries": 0,
"production_shell_hits": [],
"production_shell_scan": "PASS",
"runtime_dependencies": 0,
"secret_hits": [],
"secret_scan": "PASS",
"source_symlinks": [],
"stale_formal_digest_hits": [],
"stale_runtime_path_hits": [],
"status": "PASS",
"systemd_v5_isolation": "PASS",
"tag_rewrite_implementation_present": false,
"zip_digest_self_reference": false
}
@@ -0,0 +1,37 @@
# V5R1 package closure
V5R1 is the successor packaging revision for the V2R1C4 task-scoped release
control plane. It does not change the frozen product source, release artifact,
rollback artifact, Release Root, Evidence Manifest, evidence closure, or tag
object.
The archive is deterministic and non-self-referential:
- `MANIFEST.sha256` covers every other file in sorted relative-path order.
- `MANIFEST.sha256` excludes itself.
- symbolic links and special files are rejected.
- `PACKAGE_COMPONENTS.json` declares
`package_zip_sha256_source=EXTERNAL_SIDECAR`.
- the completed ZIP digest exists only in the adjacent `-SHA256.txt` sidecar.
Validated fixed component digests:
```text
wheel_sha256=91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19
deployment_definitions_sha256=b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0
manifest_schema_sha256=31bce5c2960d8c57b26e0fa854196c17e6f018cd547b58679b7877cb602df4f4
runtime_layout_schema_sha256=658813b8a0096ab5ee66dd217dc0bbb1b08e09dc33241049f24190bb4df86c9d
exact_two_parent_broker_sha256=eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4
broker_schema_sha256=72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba
validator_schema_sha256=95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22
site_config_sha256=be44861e717513e67b532fdb2f20b67a96aad07e212d521d4a69148ca346760c
```
Linux verification completed with 391 passing tests, zero failures, zero
skips, JSON Schema validation, `systemd-analyze verify`, real two-parent Git
object creation, object-only import, `git fsck --connectivity-only`, and exact
compare-and-swap ref updates in isolated repositories.
Files below `examples/` are non-production contract fixtures. Placeholder
sentinels in those fixtures are rejected if copied into a formal declaration
or production approval object.
@@ -0,0 +1,23 @@
{
"action_broker_pyz_sha256": "0a4833127697c8a7a4ed88c2b2c2433621ed9bb7a767047abcd2e0b8ec773558",
"action_program_pyz_sha256": "245cda7c90f40a3c85d68e29bb927d367d8b405857dd6f235b547cbb3e9d8df8",
"broker_schema_sha256": "72efc595a85b471260110197ac845171c8447ab4edbf1ded38aed5bee6fe6aba",
"deployment_definition_files": 22,
"deployment_definitions_sha256": "b1e7379b1d8cbc5c83b41fee278b2a85e115a6bd071f7e0670563659429b70c0",
"exact_two_parent_broker_sha256": "eb98a9ef64bbbc26e0c0ea9e6f1b7ef247ae685b96ed2b8c0edba7acc39fa4e4",
"manifest_schema_sha256": "31bce5c2960d8c57b26e0fa854196c17e6f018cd547b58679b7877cb602df4f4",
"package_version": "1.4.0",
"package_revision": "V5R1",
"package_zip_sha256_source": "EXTERNAL_SIDECAR",
"runtime_layout_algorithm_id": "AIOS_RUNTIME_LAYOUT_V1",
"runtime_layout_schema_sha256": "658813b8a0096ab5ee66dd217dc0bbb1b08e09dc33241049f24190bb4df86c9d",
"schema_id": "AIOS_TASK_SCOPED_RELEASE_V5R1_COMPONENTS",
"schema_version": 1,
"systemd_runtime_directory": "aios-v2r1c4-release-v5",
"systemd_state_directory_prefix": "aios-v2r1c4-release-v5",
"site_config_sha256": "be44861e717513e67b532fdb2f20b67a96aad07e212d521d4a69148ca346760c",
"tree_algorithm_id": "AIOS_TREE_SHA256_V1",
"validator_schema_sha256": "95c23c5e54b0307fd1ab67dad92edaebdee6d4c495d8009c19015775f75d1f22",
"wheel_file": "aios_task_scoped_release-1.4.0-py3-none-any.whl",
"wheel_sha256": "91c7452965eb668b8f696d83ce43950bfe61805aed29a161610c9ad12d0d7b19"
}
@@ -0,0 +1,161 @@
# AIOS V2R1C4 Task-Scoped Release Control Plane V5R1
V5R1 is a packaging and governance-closure revision of V5. It retains the
fixed product source, release Artifact, Rollback, Release Root, Evidence
Manifest, and frozen Git object identities. It corrects stale component
digest declarations and carries the separately governed exact two-parent
merge contract without changing product code.
The ZIP digest is intentionally external. `PACKAGE_COMPONENTS.json` declares
`package_zip_sha256_source=EXTERNAL_SIDECAR`; the actual digest is written only
to the sidecar beside the completed archive. `MANIFEST.sha256` covers every
other fixed package file, never itself or the external ZIP.
## V5 closure changes
- Safe Artifact extraction rejects path traversal, special files, and any
undeclared absolute link before files are materialized.
- The approved Artifact is copied through a digest-verifying file descriptor
into a private snapshot before tar parsing. Its archive digest and generated
extracted-file-manifest digest are both bound into the closure.
- The one permitted absolute link is fixed to
`vendor/openclaw-weixin/node_modules/openclaw -> /usr/lib/node_modules/openclaw`;
mutable unit paths may not overlap that required read-only dependency.
- Production-unit validation binds the candidate fragment bytes, requires an
independently captured effective fragment with the same digest, and requires
an explicit empty drop-in set.
- The release Manifest uses task schema v5. The content-addressed
runtime-layout document remains `AIOS_RUNTIME_LAYOUT_V1`.
## V5 systemd isolation
Every control-plane service uses V5-scoped paths, including:
```text
RuntimeDirectory=aios-v2r1c4-release-v5
RuntimeDirectoryPreserve=no
StateDirectory=aios-v2r1c4-release-v5/<role>
/run/aios-v2r1c4-release-v5
/var/lib/aios-v2r1c4-release-v5/<role>
/etc/aios/v2r1c4-release-v5
/opt/aios/v2r1c4-release-v5
```
All `ExecStart`, socket, environment, state, `ReadWritePaths`, and effective
drop-in values must conform to this V5 namespace.
## Required commands and inputs
```bash
aios-task-release artifact-extract \
--archive <release-artifact.tar> \
--destination <new-private-extraction-directory> \
--manifest-output <new-artifact-file-manifest.json> \
--expected-sha256 <release-artifact-sha256> \
--expected-root <single-archive-root-name> \
--declared-absolute-symlink \
vendor/openclaw-weixin/node_modules/openclaw=/usr/lib/node_modules/openclaw
aios-task-release runtime-layout-generate \
--input runtime-layout.input.json \
--output runtime-layout.json
aios-task-release runtime-layout-verify \
--manifest runtime-layout.json \
--release-artifact <release-artifact.tar> \
--artifact-root <safe-extracted-artifact-root> \
--production-unit <approved-production-unit-fragment> \
--effective-production-unit <captured-effective-fragment> \
--no-unit-drop-ins \
--expected-sha256 <runtime-layout-sha256>
```
The production cache gate requires both unit paths and an explicit empty
drop-in list. Deployment evidence must independently bind the installed
fragment path and digest and report no resolved drop-ins. Use
`AGENT_EXECUTION_REQUIREMENTS_V5.md` as the production execution entry point.
## Approved execution order
The Phase B approval payload binds this exact state-machine sequence:
```text
record_main_reconciliation -> import_exact_objects -> publish_exact_branch
-> deploy_candidate (isolated candidate only; production unchanged)
-> migrate_owner_identity -> promote_production -> scan_core_metadata
-> record_fresh_acceptance -> publish_exact_tag -> write_release_registry
-> write_production_baseline -> revoke_task_credentials -> complete
```
`promote_production` is an independent, receipt-producing operation. A
candidate-deployment result containing a production-promotion receipt is
rejected. The registry and baseline actions each consume one Anchor quota and
must perform their complete C3 then C4 sequence as read, one governed
`/api/commit-file` write, bounded visibility wait, and reread for each stage.
The C3 stage must bind its own historical Artifact and rollback digests; the
C4 digests are never accepted as C3 evidence.
Every entry in `operation_sequence`, including Anchor-only actions and
`complete`, has one mandatory `approved_action_plans` object. The plan fixes
absolute paths, OIDs, refs, SHA-256 bindings, URL hosts, actor identity, and
read/write order. The object deliberately has no self-referential digest.
Instead its canonical SHA-256 must be identical in the approved Manifest,
approval payload, and operation request field `action_plan_sha256`; it is also
included in the Anchor reservation request digest (or the corresponding atomic
fresh-acceptance/complete Anchor request). For the eight root-brokered actions,
`config.actions[action].plan_sha256` and the broker payload add a second
three-way boundary. Direct and Anchor-only actions deliberately have no fake
broker config entry. Any mismatch fails before reservation or execution.
Gitea API reads are fixed to `127.0.0.1`, while Git pushes are fixed to
`g.cnnetmkt.top`.
Production wrappers receive an exact `execute=true` request constructed by the
operation service from the approved Manifest and Anchor idempotency key. They
cannot fall back to PLAN mode. The wrappers are thin AF_UNIX clients of
`/run/aios-v2r1c4-release-v5/root-action-broker.sock`; they validate framing
and the returned evidence digest but do not execute production logic. The
production path is `broker_passthrough -> root action broker -> pinned action
program`; `live_actions` is not the production execution path.
The root broker rejects the former three-field request, authenticates the peer
role, validates the plan digest, and injects the startup-pinned action-program
and config digests into the strict child request. It also requires an already
open Anchor reservation for the same authorization, action and idempotency key,
and requires the Anchor campaign to be in the action's exact predecessor state.
The broker never reserves or advances Anchor. Required predecessors are read
from the Anchor snapshot, validated as full committed PASS envelopes, encoded
by the root broker into a mode-0400 sealed memfd, and passed to the
privilege-dropped child by descriptor. Caller-supplied predecessor evidence is
rejected and is never forwarded by the wrapper.
Anchor terminal evidence is not a bare digest. Both PASS and FAIL envelopes
have exactly these fields:
```text
authorization_id, manifest_sha256, operation,
producer_action_plan_sha256, idempotency_key, status, payload,
evidence_sha256, chain_hash
```
`evidence_sha256` is recomputed over the canonical first seven fields. PASS
envelopes appear only in `committed_operations`; FAIL envelopes appear only in
`failed_operations`. A FAIL releases the reservation quota but does not advance
the campaign state. Reusing a terminal idempotency key with different evidence
is a conflict.
The two quarantine roots are intentionally separate: Main reconciliation uses
the root broker's exact ephemeral
`/run/aios-v2r1c4-release-v5/quarantine/main-reconciliation.git`, while the
writer object-import workflow retains its site-config-scoped
`/var/lib/aios-v2r1c4-release-v5/quarantine`. Neither path may substitute for
the other.
## Digest status
V4 component-digest assertions do not apply to V5. Final V5 package/component
digests, manifests and test totals are generated and recorded only by the
closure rebuild. No future fresh-acceptance evidence path or digest is fixed in
advance. The approved object is the content-addressed fresh-acceptance
derivation contract; the evidence digest is created only after a new natural
Owner event is independently observed and atomically consumed by Anchor. Fixed
product source and input-artifact hashes remain unchanged.
@@ -0,0 +1,55 @@
# Recovery and Reconciliation V5
## Runtime-layout drift
If runtime-layout verification fails:
- do not modify the approved Manifest;
- do not create a drop-in;
- do not replace the external dependency in place;
- do not continue to Release Root generation.
Recalculate actual values and determine whether the failure is transient
extraction damage or a real object change. A real object change requires a
new refreeze and approval.
## systemd isolation drift
If any V5 unit creates an unversioned or V3 path, stop before installation.
Only a rebuilt deployment-definition set is acceptable. Runtime drop-ins are
not a substitute for content-addressed unit definitions.
## Side-effect recovery
Every consequential operation uses an Anchor reservation.
- committed idempotency keys return the existing evidence digest;
- an open reservation requires direct observation and reconciliation;
- a failed reservation releases its quota reservation;
- a key cannot be reused with another request digest.
Reconciliation reads the full Anchor snapshot. A committed operation must have
a PASS envelope and a failed operation must have a FAIL envelope, each with the
exact authorization, Manifest digest, operation, producer action-plan digest,
idempotency key, payload, recomputable evidence SHA-256 and chain hash. Missing,
cross-state or conflicting evidence is corruption, not a retry signal.
The root broker never repairs a missing reservation. It requires the existing
reservation and exact campaign state, then obtains committed predecessors from
Anchor itself. Do not place predecessor evidence in a retry request; the
passthrough and broker reject caller-supplied copies.
Before retrying or beginning any production switch, repeat live rollback
verification: current production active and healthy, rollback archive present
and readable with the approved SHA-256, and rollback worktree at the approved
commit and tree. If promotion fails, verify C3 restoration and health. Report
`PROMOTION_FAILED_ROLLBACK_UNVERIFIED` when restoration cannot be proved; do
not continue from nominal service state.
Fresh acceptance is reconciled from Anchor's atomic consumption record and its
committed PASS envelope. The approved derivation contract is stable; the
concrete event/evidence digest is necessarily runtime data and must not be
replaced by a pre-created future evidence file or digest.
Same-name different-OID branches or Tags require manual Owner review. No
force push, Tag rewrite or direct `main` write is permitted.
@@ -0,0 +1,36 @@
# V2R1C4 Release Refreeze Workflow V5
## Reusable immutable objects
```text
source_commit_oid=1857b88690cd1c0119df984534c260b6f217a21a
source_tree_oid=17c153de2338f570f70cb7407e7dda3c596b524b
release_artifact_sha256=
39523caa48f39b33e5e5df785bb568e0381d8b20301746c280442f73f294f2b2
rollback_artifact_sha256=
dd0dbbe21db14722996636347ea1d22917436c688d5f0b7055b5bfb1776c4d95
```
Product code must remain byte-identical.
## Refreeze sequence
1. verify the V5 package and all six V5 systemd services;
2. safely extract the fixed Artifact;
3. calculate the external OpenClaw package and Tree digests;
4. generate the exact candidate production unit;
5. generate and verify `runtime-layout.json`;
6. put the runtime-layout digest into `release-root.input.json`;
7. generate and verify `release-root.manifest.json`;
8. generate and verify `evidence-manifest.json`;
9. create one new evidence closure commit directly on the fixed source;
10. compute the new evidence tree and closure OIDs;
11. build and verify a connected Git Bundle;
12. compute a deterministic annotated V2R1C4 Tag object;
13. populate the complete V5 release Manifest;
14. request one exact machine-readable Owner approval.
Do not generate an Owner approval payload before all V5 control-plane,
runtime-layout, Release Root, evidence, Git and Tag objects are frozen.
@@ -0,0 +1,93 @@
# Runtime Layout Closure V5
## Required real inputs
The Agent must safely extract the fixed Release Artifact without following
links, then enumerate all entries using `lstat`.
Expected absolute link:
```text
artifact_path=vendor/openclaw-weixin/node_modules/openclaw
link_target=/usr/lib/node_modules/openclaw
```
No other absolute Artifact link may exist.
For `/usr/lib/node_modules/openclaw`, compute:
```text
package_json_sha256=<full SHA-256>
package_name=openclaw
package_version=2026.6.11
target_tree_sha256=<AIOS_TREE_SHA256_V1>
```
Do not accept a prefix-only digest.
## Tree algorithm
`AIOS_TREE_SHA256_V1` hashes a canonical ordered list of:
- relative path;
- entry type;
- permission mode;
- regular-file size and SHA-256;
- relative symlink target.
The algorithm excludes timestamps, UID and GID. It rejects:
- devices;
- sockets;
- FIFOs;
- nested absolute symlinks;
- relative symlinks escaping the dependency root.
## Candidate production unit
Before Owner approval, generate the exact candidate production unit and
bind its complete SHA-256.
The unit must contain:
```text
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/usr/lib/node_modules/openclaw
```
`BindReadOnlyPaths=/usr/lib/node_modules/openclaw` is also accepted. A unit
drop-in not included in the approved runtime-layout digest is forbidden.
## Verification result
A passing result contains:
```text
status=PASS
absolute_symlink_count=1
external_dependency.package_version=2026.6.11
external_dependency.read_only_binding=PASS
production_unit_sha256=<approved value>
target_tree_sha256=<approved value>
```
## Control-plane runtime ownership
The runtime layout must preserve these exact identities:
```text
aios-v2r1c4-task-anchor
aios-v2r1c4-approval-observer
aios-v2r1c4-task-writer
aios-v2r1c4-task-controller
aios-v2r1c4-task-publisher
root # root action broker only
```
All non-root roles use group `aios-v2r1c4-release`; the root action broker uses
`root:root`. The Writer unit hosts both its AF_UNIX operation socket and the
loopback metadata Writer at `127.0.0.1:19892`. Only that unit receives the
metadata API bearer and Gitea publication credentials. The root action broker
socket is `/run/aios-v2r1c4-release-v5/root-action-broker.sock`; action wrappers
are thin AF_UNIX clients and do not provide a second production implementation.
@@ -0,0 +1,22 @@
939495d29782d1f7c063131dcd134c31df0ad07079ab15df99c5886efb3705a6 deploy/actions/action-config.schema.json
413313a03547372988ec871ff30d3fabe767d1c6af13f7f1392c71e7251d8196 deploy/actions/aios-v2r1c4-root-action-runner
162d87f32aa21aed794f89a582a67532415980eed9161781bb6618c5cf88b178 deploy/actions/deploy-candidate
70aaf4febf1c94674c64cef534b15ff0d314e0eb988c1bb7604038c8619a71fb deploy/actions/migrate-owner-identity
232fa6e7737e2d505afe8ed066f6dac6098c40cd6c3092dc56c8374c8f771f1f deploy/actions/promote-production
97b51f4daf26e07380b0f4f57d8cf8e449da1ec5bcbf1f134d52d53b3aa4c7f0 deploy/actions/revoke-task-credentials
8d26b43a886477a130d249825a0dba21ad29d0708332caf2ce1e68605fa20352 deploy/actions/scan-core-metadata
1baa7571b2ff22c60a2ca8b7174e7f22615c048d753793b28c0ebdd93da903ba deploy/actions/write-production-baseline
a239b785a9ddd5975ae10d9820b6d690d161b37e67c291d908f3ee9646db4983 deploy/actions/write-release-registry
c5d20a1c90a713b5d17f95638cfec55b84dbeb05122d5269485d8f70fbc598d5 deploy/bin/aios-task-release
437f8826bf84ba8e3876bd12f2ccc274d1f498424c08b6a44b1e2e0963a1ece7 deploy/bin/aios-task-release-anchor
5f4f83c850240acf8bea951408911dd032b201c8ba60cbc912eaf54ba7d52f5c deploy/bin/aios-task-release-finalizer
5a5ec858035ce59b519b12018f881301d4ff59d281bab840413f4f88b0a4e435 deploy/bin/aios-task-release-operation
dc99c98da6ed5cd4af5a5a2c5a64daf96eefeda39497fd3bd2beba2c76b5846c deploy/bin/aios-task-release-revoker
ca76dd130f0969fcbb5418c4276d4fbbe0671b340ffb2c615098a9989064a8fd deploy/systemd/aios-exact-two-parent-merge-broker@.service
8f564cf7658b1f27666216e57de133677251c9fec298c04444b4b2764a4c2d49 deploy/systemd/aios-v2r1c4-release-anchor-v5.service
e9cf179a5cc75d1dfa644698abad7991acec582fd988ac73f01ba47b37595325 deploy/systemd/aios-v2r1c4-release-approval-observer-v5.service
d1f42014f73a64aa4662d4071a0ccc5523131bbac2b72267548d548d12aba1d8 deploy/systemd/aios-v2r1c4-release-controller-v5.service
fdee4f640bac52d4e85806ad9681c7ec5b7ab695326232308d156c65b5e078be deploy/systemd/aios-v2r1c4-release-publisher-v5.service
138f811d5f4694cb9603718fadfcf6ce8041c348905812f0b0d48cfdae905f51 deploy/systemd/aios-v2r1c4-release-writer-v5.service
5dc58ac4a4f724c276be9f914e76f5ff17ab0eed13086e1c594e2237bfc8c859 deploy/systemd/aios-v2r1c4-root-action-broker.service
440ee7ccac9da3861c04cfaa22768a11c4905f2874d2d776adbdd499de29ef22 deploy/tmpfiles.d/aios-v2r1c4-task-release-v5.conf
@@ -0,0 +1,138 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AIOS V2R1C4 descriptor-pinned root action broker configuration",
"type": "object",
"additionalProperties": false,
"required": ["manifest_sha256", "interpreter", "action_program", "anchor_socket", "anchor_timeout_seconds", "actions"],
"properties": {
"manifest_sha256": {
"description": "SHA-256 of AIOS_CANONICAL_JSON_V1 bytes for the pinned release manifest.",
"type": "string",
"pattern": "^[0-9a-f]{64}$"
},
"interpreter": {
"type": "object",
"additionalProperties": false,
"required": ["path", "sha256"],
"properties": {
"path": {"const": "/usr/bin/python3.12"},
"sha256": {"const": "e1efa562c2cc2e35521a5c9c9b9939921001ff8ca9708a13ef15ace68cc2ccd7"}
}
},
"action_program": {
"type": "object",
"additionalProperties": false,
"required": ["path", "sha256"],
"properties": {
"path": {
"const": "/opt/aios/v2r1c4-release-v5/libexec/action-program.pyz"
},
"sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
}
},
"anchor_socket": {
"description": "Fixed Anchor AF_UNIX endpoint used by the root broker through a caller-UID-dropped snapshot child.",
"const": "/run/aios-v2r1c4-release-v5/anchor.sock"
},
"anchor_timeout_seconds": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 30
},
"request_timeout_seconds": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 30
},
"socket_gid": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"socket_parent_uid": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"environment": {
"type": "object",
"additionalProperties": false,
"properties": {
"LANG": {"type": "string", "minLength": 1},
"LC_ALL": {"type": "string", "minLength": 1},
"PATH": {"type": "string", "minLength": 1},
"TZ": {"type": "string", "minLength": 1}
}
},
"actions": {
"type": "object",
"additionalProperties": false,
"required": [
"record_main_reconciliation",
"deploy_candidate",
"migrate_owner_identity",
"promote_production",
"scan_core_metadata",
"write_release_registry",
"write_production_baseline",
"revoke_task_credentials"
],
"properties": {
"record_main_reconciliation": {"$ref": "#/$defs/action"},
"deploy_candidate": {"$ref": "#/$defs/action"},
"migrate_owner_identity": {"$ref": "#/$defs/action"},
"promote_production": {"$ref": "#/$defs/action"},
"scan_core_metadata": {"$ref": "#/$defs/action"},
"write_release_registry": {"$ref": "#/$defs/action"},
"write_production_baseline": {"$ref": "#/$defs/action"},
"revoke_task_credentials": {"$ref": "#/$defs/action"}
}
}
},
"$defs": {
"action": {
"type": "object",
"additionalProperties": false,
"required": [
"plan_sha256",
"caller_uid",
"caller_gid",
"exec_uid",
"exec_gid",
"timeout_seconds",
"stdout_limit_bytes",
"stderr_limit_bytes"
],
"properties": {
"plan_sha256": {
"description": "SHA-256 of the canonical approved plan embedded in the release manifest; the plan object itself must not contain this digest.",
"type": "string",
"pattern": "^[0-9a-f]{64}$"
},
"caller_uid": {"type": "integer", "minimum": 0, "maximum": 2147483647},
"caller_gid": {"type": "integer", "minimum": 0, "maximum": 2147483647},
"exec_uid": {"type": "integer", "minimum": 0, "maximum": 2147483647},
"exec_gid": {"type": "integer", "minimum": 0, "maximum": 2147483647},
"timeout_seconds": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 300
},
"stdout_limit_bytes": {
"type": "integer",
"minimum": 1,
"maximum": 1048576
},
"stderr_limit_bytes": {
"type": "integer",
"minimum": 1,
"maximum": 1048576
},
"anchored_predecessor_evidence_required": {
"description": "Must be true for promote_production and scan_core_metadata; the broker injects Anchor-owned evidence through a protected descriptor, never caller JSON.",
"type": "boolean"
}
}
}
}
}
@@ -0,0 +1,8 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 /opt/aios/v2r1c4-release-v5/libexec/action-broker.pyz \
--config /etc/aios/v2r1c4-release-v5/root-action-config.json \
--manifest /etc/aios/v2r1c4-release-v5/release-manifest.json \
--python /usr/bin/python3.12 \
--program /opt/aios/v2r1c4-release-v5/libexec/action-program.pyz \
--socket /run/aios-v2r1c4-release-v5/root-action-broker.sock
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action deploy_candidate "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action migrate_owner_identity "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action promote_production "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action revoke_task_credentials "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action scan_core_metadata "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action write_production_baseline "$@"
@@ -0,0 +1,3 @@
#!/bin/sh
set -eu
exec /usr/bin/python3.12 -m aios_task_scoped_release.broker_passthrough --action write_release_registry "$@"
@@ -0,0 +1,3 @@
#!/usr/bin/env python3
from aios_task_scoped_release.cli import main
raise SystemExit(main())
@@ -0,0 +1,3 @@
#!/usr/bin/env python3
from aios_task_scoped_release.anchor_service import main
raise SystemExit(main())

Some files were not shown because too many files have changed in this diff Show More