Compare commits

..
Author SHA1 Message Date
AIOS Governed Continuation 998d303047 fix(v2r2c1): use governed ancestry adapter for recovery 2026-08-09 15:15:06 +08:00
AIOS Governed Continuation b28c028135 fix(v2r2c1): reconcile pending commits in exact chain order 2026-08-09 15:13:19 +08:00
AIOS Governed Continuation 16f8bb165a fix(v2r2c1): project credential path for gitea publisher 2026-08-09 15:09:29 +08:00
AIOS Governed Continuation 87a46437a9 fix(v2r2c1): reconcile live control-plane snapshot 2026-08-09 15:07:25 +08:00
AIOS Governed Continuation bb939c7983 feat(v2r2c1): persist continuation lineage for restart recovery 2026-08-09 15:01:06 +08:00
AIOS Governed Continuation e3b5017218 fix(v2r2c1): make restart reconcile legacy bindings durable 2026-08-09 12:41:10 +08:00
AIOS Governed Continuation 34968f8791 fix(v2r2c1): add safe worktree materialization and restart defaults 2026-08-09 12:39:41 +08:00
AIOS Governed Continuation 45183beea3 fix(v2r2c1): close governed staging materialization and schema identity 2026-08-09 12:32:03 +08:00
AIOS Governed Continuation 5f91347e9d fix(v2r2c1): reconstruct jobs and snapshots after restart 2026-08-09 12:27:07 +08:00
AIOS Governed Continuation dcfb263827 refactor(v2r2c1): delegate completion to reconciliation decisions 2026-08-09 12:25:47 +08:00
AIOS Governed Continuation ce2912fca8 test(v2r2c1): align bridge contract regression with snapshot operation 2026-08-09 12:23:42 +08:00
AIOS Governed Continuation 1d61b29f8c test(v2r2c1): add reconciliation regressions and complete OpenAPI schemas 2026-08-09 12:22:40 +08:00
AIOS Governed Continuation 84aae198b8 feat(v2r2c1): add durable reconciliation control plane 2026-08-09 12:20:51 +08:00
AIOS Governed Continuation 0f2b53aba0 docs(gitops): bootstrap Bridge v2.1 durable reconciliation 2026-08-09 11:49:16 +08:00
AIOS Governed Continuation 3f670c3876 test(gitops): prove Bridge v2 governed operation sequence 2026-08-09 03:40:28 +08:00
AIOS Governed Continuation 8fe3b85c1b fix(gitops): reconcile exact old remote after observation 2026-08-09 03:36:39 +08:00
AIOS Governed Continuation 77c6daa76a docs(gitops): complete Bridge v2 engineering closure evidence 2026-08-09 03:34:00 +08:00
AIOS Governed Continuation 35e387edc8 docs(gitops): record Bridge v2 staging restart acceptance 2026-08-09 03:31:35 +08:00
AIOS Governed Continuation aa0c37b8ab feat(gitops): converge ChatGPT Bridge v2 runtime and OpenAPI 2026-08-09 03:29:09 +08:00
AIOS Governed Continuation 6044b551c1 feat(gitops): add governed continuation executor 2026-08-09 03:23:30 +08:00
aios-autonomy-agent 8030601854 feat(openbao): add autonomy runtime v1 candidate 2026-08-09 01:57:42 +08:00
39 changed files with 607 additions and 7806 deletions
+1 -47
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
from __future__ import annotations
import hashlib, hmac, json, os, re, subprocess, sys, time, urllib.parse, urllib.request, uuid
import hashlib, hmac, json, os, re, subprocess, sys, time, urllib.parse, uuid
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import Any
@@ -404,51 +404,6 @@ class H(BaseHTTPRequestHandler):
if not a['ok']: self.sendj({'error':'unauthorized','hint':'Bearer token required'},401); return None
if '*' not in a['scopes'] and scope not in a['scopes']: self.sendj({'error':'forbidden','required_scope':scope,'account':a['account']},403); return None
return a
def bridge_release(self, path, data):
route = {
'/createTagApprovalRequest': '/v2/tag/approval-request',
'/requestOrCreateTag': '/v2/tag/publish',
'/getTagPublicationStatus': '/v2/tag/status',
'/buildProductionArtifact': '/v2/release/artifact',
'/executeApprovedProductionRelease': '/v2/release/execute',
'/getReleaseConsistency': '/v2/release/consistency',
'/runReleaseAcceptance': '/v2/release/acceptance',
}.get(path)
if route is None:
raise ValueError('governed_release_route_invalid')
base = os.getenv('AIOS_BRIDGE_V2_URL', 'http://127.0.0.1:18892').rstrip('/')
request = urllib.request.Request(
base + route,
data=json.dumps(data, sort_keys=True, separators=(',', ':')).encode('utf-8'),
headers={'Content-Type': 'application/json'},
method='POST',
)
try:
with urllib.request.urlopen(request, timeout=30) as response:
result = json.loads(response.read().decode('utf-8'))
return self.sendj(result, response.status)
except urllib.error.HTTPError as exc:
try:
body = json.loads(exc.read().decode('utf-8'))
except Exception:
body = {'error': 'bridge_http_error'}
return self.sendj(body, exc.code)
except (urllib.error.URLError, TimeoutError) as exc:
return self.sendj({'error': 'GOVERNED_BRIDGE_UNAVAILABLE', 'detail': type(exc).__name__}, 503)
def do_POST(self):
path = urllib.parse.urlparse(self.path).path
if path in {
'/createTagApprovalRequest', '/requestOrCreateTag', '/getTagPublicationStatus',
'/buildProductionArtifact', '/executeApprovedProductionRelease',
'/getReleaseConsistency', '/runReleaseAcceptance',
}:
actor = self.need('tag:create')
if not actor:
return
return self.bridge_release(path, self.body())
if reject_non_read_http(self, 'POST', path):
return
return self.sendj({'error': 'not_found', 'path': path}, 404)
def do_GET(self):
u=urllib.parse.urlparse(self.path); path=u.path.rstrip('/') if u.path != '/' else u.path
if path not in READ_ONLY_GET_PATHS: return self.sendj({'error':'not_found','path':path},404)
@@ -950,4 +905,3 @@ def main():
print(f'AIOS ChatGPT GitOps adapter listening on {HOST}:{PORT}')
ThreadingHTTPServer((HOST,PORT), H).serve_forever()
if __name__ == '__main__': main()
+9 -89
View File
@@ -1,4 +1,4 @@
"""ChatGPT GitOps Bridge v2 contract and governed release operations."""
"""ChatGPT GitOps Bridge v2 contract and immutable runtime identity."""
from __future__ import annotations
from dataclasses import dataclass
@@ -6,28 +6,8 @@ import hashlib
from pathlib import Path
from typing import Any, Callable, Mapping
BRIDGE_SCHEMA_VERSION = "aios.chatgpt-gitops-bridge.v2"
BRIDGE_OPERATIONS = (
"getRuntimeStatus",
"getGovernedWriteCapabilities",
"createGovernedTask",
"acquireWriterLease",
"commitFileGoverned",
"commitFilesGoverned",
"getGitOpsJob",
"resumeGitOpsJob",
"reconcileGitOpsJob",
"createTagApprovalRequest",
"requestOrCreateTag",
"getTagPublicationStatus",
"buildProductionArtifact",
"executeApprovedProductionRelease",
"getReleaseConsistency",
"runReleaseAcceptance",
"getControlPlaneSnapshot",
)
BRIDGE_OPERATIONS = ("getRuntimeStatus", "getGovernedWriteCapabilities", "createGovernedTask", "acquireWriterLease", "commitFileGoverned", "commitFilesGoverned", "getGitOpsJob", "resumeGitOpsJob", "reconcileGitOpsJob", "getControlPlaneSnapshot")
OPERATION_REQUIRED_FIELDS = {
"createGovernedTask": ("task_id", "repository", "base_oid", "target_branch", "risk", "description", "idempotency_key"),
"acquireWriterLease": ("schema", "task_id", "repository", "branch_mode", "base_oid", "expected_branch_oid", "target_branch", "generation", "lease_seconds"),
@@ -36,13 +16,6 @@ OPERATION_REQUIRED_FIELDS = {
"getGitOpsJob": ("job_id",),
"resumeGitOpsJob": ("job_id", "expected_revision"),
"reconcileGitOpsJob": ("job_id", "expected_revision"),
"createTagApprovalRequest": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id", "owner_approval", "execute"),
"requestOrCreateTag": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id", "execute"),
"getTagPublicationStatus": ("version",),
"buildProductionArtifact": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id"),
"executeApprovedProductionRelease": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id", "execute"),
"getReleaseConsistency": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id"),
"runReleaseAcceptance": ("version", "target_oid", "evidence_closure_oid", "approval_plan_id"),
"getControlPlaneSnapshot": (),
}
@@ -67,82 +40,37 @@ class ControlPlaneReleaseManifest:
deployment_state: str
def as_dict(self) -> dict[str, object]:
return {
"control_plane_release_version": self.control_plane_release_version,
"control_plane_target_oid": self.control_plane_target_oid,
"artifact_sha256": self.artifact_sha256,
"runtime_path": str(self.runtime_path),
"bridge_schema_version": self.bridge_schema_version,
"repository_identity": self.repository_identity,
"authoritative_git_dir": str(self.authoritative_git_dir),
"deployment_state": self.deployment_state,
}
return {"control_plane_release_version": self.control_plane_release_version, "control_plane_target_oid": self.control_plane_target_oid, "artifact_sha256": self.artifact_sha256, "runtime_path": str(self.runtime_path), "bridge_schema_version": self.bridge_schema_version, "repository_identity": self.repository_identity, "authoritative_git_dir": str(self.authoritative_git_dir), "deployment_state": self.deployment_state}
def validate(self, artifact: Path, *, observed_oid: str, approved_root: Path = Path("/opt/aios/gitops-control-plane")) -> dict[str, object]:
try:
runtime = self.runtime_path.resolve(strict=True)
root = approved_root.resolve(strict=True)
artifact_path = artifact.resolve(strict=True)
runtime.relative_to(root)
artifact_path.relative_to(runtime)
runtime = self.runtime_path.resolve(strict=True); root = approved_root.resolve(strict=True); artifact_path = artifact.resolve(strict=True); runtime.relative_to(root); artifact_path.relative_to(runtime)
except (OSError, ValueError):
raise RuntimeDriftError("CONTROL_PLANE_RUNTIME_DRIFT") from None
mutable_markers = {"workspace", "workspaces", "worktree", "worktrees"}
if mutable_markers.intersection(part.lower() for part in runtime.parts):
if any(marker in {"workspace", "workspaces", "worktree", "worktrees"} for marker in (part.lower() for part in runtime.parts)):
raise RuntimeDriftError("CONTROL_PLANE_RUNTIME_DRIFT")
valid = (
len(self.control_plane_target_oid) == 40
and observed_oid == self.control_plane_target_oid
and len(self.artifact_sha256) == 64
and hashlib.sha256(artifact_path.read_bytes()).hexdigest() == self.artifact_sha256
and self.bridge_schema_version == BRIDGE_SCHEMA_VERSION
and self.repository_identity == "aios/aios"
and self.authoritative_git_dir == Path("/data/aios-gitops/repo.git")
and self.authoritative_git_dir.is_absolute()
and self.deployment_state == "STAGING"
)
valid = len(self.control_plane_target_oid) == 40 and observed_oid == self.control_plane_target_oid and len(self.artifact_sha256) == 64 and hashlib.sha256(artifact_path.read_bytes()).hexdigest() == self.artifact_sha256 and self.bridge_schema_version == BRIDGE_SCHEMA_VERSION and self.repository_identity == "aios/aios" and self.authoritative_git_dir == Path("/data/aios-gitops/repo.git") and self.deployment_state == "STAGING"
if not valid:
raise RuntimeDriftError("CONTROL_PLANE_RUNTIME_DRIFT")
return {**self.as_dict(), "drift_status": "PASS"}
class BridgeV2Adapter:
"""Thin operation adapter; all mutating handlers are injected seams."""
def __init__(self, *, runtime_status: Mapping[str, Any], handlers: Mapping[str, Callable[[Mapping[str, Any]], Any]] | None = None) -> None:
self.runtime_status = dict(runtime_status)
self.handlers = dict(handlers or {})
self.runtime_status = dict(runtime_status); self.handlers = dict(handlers or {})
def getRuntimeStatus(self) -> dict[str, Any]:
return {"bridge_schema_version": BRIDGE_SCHEMA_VERSION, **self.runtime_status}
def getGovernedWriteCapabilities(self) -> dict[str, Any]:
return {
"bridge_schema_version": BRIDGE_SCHEMA_VERSION,
"legacy_writes_enabled": False,
"governed_writes_enabled": True,
"operations": list(BRIDGE_OPERATIONS),
"force_push": False,
"main_write": False,
"tag_write": False,
"baseline_write": False,
"production_write": False,
"approved_release_operations": True,
"approved_release_scope": {
"version": "V2R2C1",
"target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad",
"evidence_closure_oid": "a8b906d1bc24088c19647e98de6a679268f6d0a2",
"approval_plan_id": "sha256:c0df52008ae7f64cec5ee2d28947aa7b892066c670ab8295e4549140b1a7500e",
},
}
return {"bridge_schema_version": BRIDGE_SCHEMA_VERSION, "legacy_writes_enabled": False, "governed_writes_enabled": True, "operations": list(BRIDGE_OPERATIONS), "force_push": False, "main_write": False, "tag_write": False, "baseline_write": False, "production_write": False}
@staticmethod
def legacy_write_disabled() -> dict[str, object]:
return {"error": "LEGACY_WRITE_DISABLED", "replacement": "createGovernedTask", "governed_writes_available": True}
def _call(self, operation: str, request: Mapping[str, Any]) -> Any:
required = OPERATION_REQUIRED_FIELDS[operation]
if any(key not in request for key in required):
if tuple(key for key in OPERATION_REQUIRED_FIELDS[operation] if key not in request):
raise BridgeV2Error("BRIDGE_REQUEST_FIELDS_MISSING")
handler = self.handlers.get(operation)
if handler is None:
@@ -156,12 +84,4 @@ class BridgeV2Adapter:
def getGitOpsJob(self, request: Mapping[str, Any]) -> Any: return self._call("getGitOpsJob", request)
def resumeGitOpsJob(self, request: Mapping[str, Any]) -> Any: return self._call("resumeGitOpsJob", request)
def reconcileGitOpsJob(self, request: Mapping[str, Any]) -> Any: return self._call("reconcileGitOpsJob", request)
def createTagApprovalRequest(self, request: Mapping[str, Any]) -> Any: return self._call("createTagApprovalRequest", request)
def requestOrCreateTag(self, request: Mapping[str, Any]) -> Any: return self._call("requestOrCreateTag", request)
def getTagPublicationStatus(self, request: Mapping[str, Any]) -> Any: return self._call("getTagPublicationStatus", request)
def buildProductionArtifact(self, request: Mapping[str, Any]) -> Any: return self._call("buildProductionArtifact", request)
def executeApprovedProductionRelease(self, request: Mapping[str, Any]) -> Any: return self._call("executeApprovedProductionRelease", request)
def getReleaseConsistency(self, request: Mapping[str, Any]) -> Any: return self._call("getReleaseConsistency", request)
def runReleaseAcceptance(self, request: Mapping[str, Any]) -> Any: return self._call("runReleaseAcceptance", request)
def getControlPlaneSnapshot(self, request: Mapping[str, Any] | None = None) -> Any: return self._call("getControlPlaneSnapshot", request or {})
@@ -19,27 +19,9 @@ from aios_continuation_lease import WriterLeaseRequestV2
from aios_control_plane_snapshot import build_control_plane_snapshot
from aios_gitops_job_controller import GitOpsJobController, JobStore
from aios_governed_task_bootstrap import BootstrapError, GovernedTaskBootstrap
from governed_production_release import build_executor_config
MAX_BODY = 2 * 1024 * 1024
ROUTES = {
"/v2/runtime": "getRuntimeStatus",
"/v2/capabilities": "getGovernedWriteCapabilities",
"/v2/governed-task": "createGovernedTask",
"/v2/writer-lease": "acquireWriterLease",
"/v2/commit-file": "commitFileGoverned",
"/v2/commit-files": "commitFilesGoverned",
"/v2/job": "getGitOpsJob",
"/v2/job/resume": "resumeGitOpsJob",
"/v2/job/reconcile": "reconcileGitOpsJob",
"/v2/tag/approval-request": "createTagApprovalRequest",
"/v2/tag/publish": "requestOrCreateTag",
"/v2/tag/status": "getTagPublicationStatus",
"/v2/release/artifact": "buildProductionArtifact",
"/v2/release/execute": "executeApprovedProductionRelease",
"/v2/release/consistency": "getReleaseConsistency",
"/v2/release/acceptance": "runReleaseAcceptance",
}
ROUTES = {"/v2/governed-task": "createGovernedTask", "/v2/writer-lease": "acquireWriterLease", "/v2/commit-file": "commitFileGoverned", "/v2/commit-files": "commitFilesGoverned", "/v2/job": "getGitOpsJob", "/v2/job/resume": "resumeGitOpsJob", "/v2/job/reconcile": "reconcileGitOpsJob"}
@dataclass(frozen=True, slots=True)
@@ -53,12 +35,7 @@ class RuntimeConfig:
remote_name: str = "gitea-http"
repository: str = "aios/aios"
api_base: str = "https://g.cnnetmkt.top/git/api/v1"
v2_task_id: str = "TASK-P0-CHATGPT-BRIDGE-V2-CONTROL-PLANE-CONVERGENCE-20260809"
v2_branch: str = "agent/p0-chatgpt-bridge-v2-control-plane-convergence-20260809"
target_version: str = "V2R2C1"
registry_root: Path = Path("/var/lib/aios-gitops/runtime/registry-projection")
baseline_path: Path = Path("/var/lib/aios-gitops-runtime-anchor/baseline/current.json")
health_url: str = "http://127.0.0.1:18927/health"
def _safe(value: str) -> str:
@@ -74,7 +51,6 @@ class GovernedRuntime:
self.runtimes: dict[tuple[str, int], tuple[Any, GitOpsJobController, ContinuationExecutor]] = {}
self.controllers: dict[str, GitOpsJobController] = {}
self.bindings: dict[str, dict[str, Any]] = {}
self.release = build_executor_config(config)
metadata_root = config.state_root / "task-bindings"
if metadata_root.is_dir():
for metadata in metadata_root.glob("*.json"):
@@ -91,22 +67,7 @@ class GovernedRuntime:
os.environ.setdefault("GIT_ASKPASS", str(askpass)); os.environ.setdefault("GIT_ASKPASS_REQUIRE", "force"); os.environ.setdefault("GIT_TERMINAL_PROMPT", "0"); os.environ.setdefault("GITEA_MACHINE_ACTOR", "aios-autonomy-agent")
def runtime_status(self) -> dict[str, Any]:
return {
"status": "active",
"health": 200,
"bridge_schema_version": "aios.chatgpt-gitops-bridge.v2",
"control_plane_release_version": self.config.target_version,
"control_plane_target_oid": self.config.target_oid,
"runtime_release_commit": self.config.target_oid,
"runtime_path": str(self.config.state_root),
"artifact_sha256": os.environ.get("AIOS_CONTROL_PLANE_ARTIFACT_SHA256"),
"deployment_state": "STAGING",
"drift_status": "PASS",
"repository": self.config.repository,
"repository_identity": self.config.repository,
"authoritative_git_dir": str(self.config.authoritative_git_dir),
"legacy_global_writes_enabled": False,
}
return {"bridge_schema_version": "aios.chatgpt-gitops-bridge.v2", "control_plane_release_version": self.config.target_version, "control_plane_target_oid": self.config.target_oid, "runtime_release_commit": self.config.target_oid, "runtime_path": str(self.config.state_root), "artifact_sha256": os.environ.get("AIOS_CONTROL_PLANE_ARTIFACT_SHA256"), "deployment_state": "STAGING", "drift_status": "PASS", "repository_identity": self.config.repository, "authoritative_git_dir": str(self.config.authoritative_git_dir)}
def _job_root(self, task_id: str) -> Path:
return self.config.state_root / "jobs" / _safe(task_id)
@@ -340,23 +301,7 @@ class GovernedRuntime:
return build_control_plane_snapshot(target_version=self.config.target_version, runtime=self.runtime_status(), repository={"identity": self.config.repository, "authority_git_dir": str(self.config.authoritative_git_dir), "authority_main_oid": self.authority.read_ref("refs/heads/main")}, production={"baseline_version": "V2R1C7", "target_oid": "c7adece1cc8beffe7c718d53c775898b45d6c7f8", "deployment_state": "ACTIVE"}, task=task, capabilities={"legacy_writes_enabled": False, "governed_writes_enabled": True, "force_push": False, "main_write": False, "tag_write": False, "baseline_write": False, "production_write": False}, credential_broker={"status": "SERVER_SIDE_ONLY", "provider": "FileCredentialProvider"})
def handlers(self) -> dict[str, Any]:
return {
"createGovernedTask": self.create_task,
"acquireWriterLease": self.acquire_lease,
"commitFileGoverned": lambda request: self.commit_files({**request, "files": {request["path"]: request["content_base64"]}}),
"commitFilesGoverned": self.commit_files,
"getGitOpsJob": lambda request: self.job(request, "get"),
"resumeGitOpsJob": lambda request: self.job(request, "resume"),
"reconcileGitOpsJob": lambda request: self.job(request, "reconcile"),
"getControlPlaneSnapshot": lambda request: self.snapshot(),
"createTagApprovalRequest": self.release.approval_request,
"requestOrCreateTag": self.release.publish_tag,
"getTagPublicationStatus": self.release.tag_status,
"buildProductionArtifact": self.release.build_artifact,
"executeApprovedProductionRelease": self.release.execute_request,
"getReleaseConsistency": self.release.consistency,
"runReleaseAcceptance": self.release.acceptance,
}
return {"createGovernedTask": self.create_task, "acquireWriterLease": self.acquire_lease, "commitFileGoverned": lambda request: self.commit_files({**request, "files": {request["path"]: request["content_base64"]}}), "commitFilesGoverned": self.commit_files, "getGitOpsJob": lambda request: self.job(request, "get"), "resumeGitOpsJob": lambda request: self.job(request, "resume"), "reconcileGitOpsJob": lambda request: self.job(request, "reconcile"), "getControlPlaneSnapshot": lambda request: self.snapshot()}
def build_governed_handlers(runtime_config: RuntimeConfig | Mapping[str, Any]) -> Mapping[str, Any]:
@@ -382,7 +327,6 @@ class BridgeHandler(BaseHTTPRequestHandler):
def _allowed(self, operation: str, body: Mapping[str, Any]) -> None:
allowed = set(OPERATION_REQUIRED_FIELDS[operation]) | {"schema", "lease_seconds", "create_target_branch", "worktree_mode", "cas_ref_update_required", "expected_branch_oid", "generation", "branch_mode"}
if operation == "commitFilesGoverned": allowed.add("files")
allowed.update({"owner_approval", "execute"})
if set(body) - allowed: raise _HTTPError("UNKNOWN_FIELDS")
def do_GET(self) -> None:
if self.adapter is None: self._json({"error": "RUNTIME_UNAVAILABLE"}, 503); return
@@ -392,7 +336,7 @@ class BridgeHandler(BaseHTTPRequestHandler):
self._json({"error": "NOT_FOUND"}, 404)
def do_POST(self) -> None:
operation = ROUTES.get(self.path)
if operation is None or operation in ("getRuntimeStatus", "getGovernedWriteCapabilities") or self.adapter is None: self._json({"error": "NOT_FOUND"}, 404); return
if operation is None or self.adapter is None: self._json({"error": "NOT_FOUND"}, 404); return
try:
body = self._body(); self._allowed(operation, body); self._json(getattr(self.adapter, operation)(body))
except _HTTPError as exc: self._json({"error": str(exc)}, 413 if str(exc) == "REQUEST_TOO_LARGE" else 400)
@@ -417,8 +361,6 @@ def main() -> None:
state_root / "jobs",
token_path,
ssh_key_path,
remote_name=os.environ.get("AIOS_GITEA_REMOTE", "gitea-http"),
api_base=os.environ.get("AIOS_GITEA_API_BASE", "https://g.cnnetmkt.top/git/api/v1"),
target_version=os.environ.get("AIOS_CONTROL_PLANE_TARGET_VERSION", "V2R2C1"),
)
runtime = GovernedRuntime(config)
@@ -284,24 +284,13 @@ class GiteaContinuationRemote:
def read_api_branch(self, branch: str) -> str | None:
owner, name = self.repository.split("/", 1)
page = 1
while page <= 100:
value = self._api(f"/repos/{quote(owner)}/{quote(name)}/branches?page={page}&limit=50")
if value is None:
return None
if not isinstance(value, list):
raise ContinuationExecutionError("GITEA_API_BRANCH_COLLECTION_INVALID")
for item in value:
if not isinstance(item, dict) or item.get("name") != branch:
continue
oid = item.get("commit", {}).get("id")
if not isinstance(oid, str) or not OID_RE.fullmatch(oid):
raise ContinuationExecutionError("GITEA_API_BRANCH_INVALID")
return oid
if len(value) < 50:
return None
page += 1
raise ContinuationExecutionError("GITEA_API_BRANCH_PAGINATION_LIMIT")
value = self._api(f"/repos/{quote(owner)}/{quote(name)}/branches/{quote(branch, safe='/')}")
if value is None:
return None
oid = value.get("commit", {}).get("id") if isinstance(value, dict) else None
if not isinstance(oid, str) or not OID_RE.fullmatch(oid):
raise ContinuationExecutionError("GITEA_API_BRANCH_INVALID")
return oid
def commit_visible(self, oid: str) -> bool:
owner, name = self.repository.split("/", 1)
@@ -74,12 +74,6 @@ class WriterLeaseRequestV2:
raise ContinuationError("EXISTING_BRANCH_OID_CONFLICT")
if not probe.is_ancestor(self.base_oid, actual):
raise ContinuationError("BASE_NOT_ANCESTOR_OF_BRANCH")
elif hasattr(probe, "commit_exists") and not probe.commit_exists(self.base_oid):
raise ContinuationError("BASE_COMMIT_NOT_FOUND")
elif self.branch_mode == "CREATE_NEW" and probe.branch_exists(self.target_branch):
raise ContinuationError("TARGET_BRANCH_ALREADY_EXISTS")
elif self.branch_mode == "CREATE_NEW" and self.base_oid != self.expected_branch_oid:
raise ContinuationError("CREATE_NEW_BASE_EXPECTATION_MISMATCH")
@dataclass(frozen=True, slots=True)
File diff suppressed because it is too large Load Diff
@@ -995,7 +995,7 @@ def validate_writer_lease_request_v2(raw: Mapping[str, Any], probe: Any) -> dict
"target_branch": request.target_branch,
"generation": request.generation,
"lease_seconds": request.lease_seconds,
"create_target_branch": request.branch_mode == "CREATE_NEW",
"worktree_mode": "detached_at_base_oid" if request.branch_mode == "CREATE_NEW" else "detached_at_expected_head",
"create_target_branch": False,
"worktree_mode": "detached_at_expected_head",
"cas_ref_update_required": True,
}
-84
View File
@@ -1,84 +0,0 @@
#!/usr/bin/env python3
"""Single canonical Production Baseline authority for the GitOps reader.
The API and the one-shot writer import this module. Workspace and release
copies are projections only; they are never selected as a fallback source.
"""
from __future__ import annotations
import hashlib
import json
import os
from pathlib import Path
from typing import Any
AUTHORITY_PATH = Path(os.getenv(
"AIOS_GITOPS_BASELINE_AUTHORITY",
"/var/lib/aios-gitops-runtime-anchor/baseline/current.json",
))
AUTHORITY_SHA_PATH = AUTHORITY_PATH.with_suffix(".sha256")
class BaselineAuthorityError(RuntimeError):
"""Fail-closed error raised for an unavailable or inconsistent authority."""
class BaselineAuthority:
def __init__(self, path: Path | str = AUTHORITY_PATH):
self.path = Path(path)
self.sha_path = self.path.with_suffix(".sha256")
def _raw(self) -> bytes:
try:
raw = self.path.read_bytes()
except OSError as exc:
raise BaselineAuthorityError(f"authority_unavailable:{exc}") from exc
if not raw:
raise BaselineAuthorityError("authority_empty")
return raw
def read(self) -> dict[str, Any]:
raw = self._raw()
digest = hashlib.sha256(raw).hexdigest()
try:
value = json.loads(raw.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise BaselineAuthorityError("authority_invalid_json") from exc
if not isinstance(value, dict):
raise BaselineAuthorityError("authority_not_object")
expected = str(value.get("authority_sha256", ""))
if expected and expected != digest:
raise BaselineAuthorityError("authority_embedded_digest_mismatch")
if self.sha_path.exists():
sidecar = self.sha_path.read_text(encoding="utf-8").strip().split()[0]
if sidecar != digest:
raise BaselineAuthorityError("authority_sidecar_digest_mismatch")
required = {
"current_baseline", "previous_baseline", "target_oid", "tag_oid",
"evidence_closure_oid", "approval_plan_id", "status", "generation",
"source_identity",
}
missing = sorted(required.difference(value))
if missing:
raise BaselineAuthorityError("authority_missing:" + ",".join(missing))
value = dict(value)
value["authority_sha256"] = digest
value["authority_path"] = str(self.path)
return value
def read_consistent(self, policy: dict[str, Any] | None = None) -> dict[str, Any]:
value = self.read()
if policy:
expected = policy.get("release_binding", policy)
for key, field in (("version", "current_baseline"),
("previous_version", "previous_baseline"),
("target_oid", "target_oid"),
("tag_oid", "tag_oid"),
("evidence_closure_oid", "evidence_closure_oid"),
("approval_plan_id", "approval_plan_id")):
wanted = expected.get(key)
if wanted is not None and value.get(field) != wanted:
raise BaselineAuthorityError(f"authority_binding_mismatch:{field}")
return value
@@ -1,568 +0,0 @@
"""Governed V2R2C1 production release orchestration.
This module is deliberately scoped to the Owner-approved V2R2C1 binding. It
uses the existing TagPublisher and metadata adapters; it does not introduce a
second Git writer, a second durable job store, or an alternate baseline.
"""
from __future__ import annotations
import argparse
import fcntl
import hashlib
import json
import os
import re
import subprocess
import tarfile
import tempfile
import time
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Mapping
from gitea_tag_publication import (
GiteaTagClient,
GitTagBackend,
PublicationManualOwnerReviewRequired,
PublicationPending,
PublicationReconciliationRequired,
PublicationRequest,
TagPublisher,
)
VERSION = "V2R2C1"
TARGET_OID = "998d30304787e31e5ae607c0bd86b5edb2b0e5ad"
EVIDENCE_CLOSURE_OID = "a8b906d1bc24088c19647e98de6a679268f6d0a2"
APPROVAL_PLAN_ID = "sha256:c0df52008ae7f64cec5ee2d28947aa7b892066c670ab8295e4549140b1a7500e"
REPOSITORY = "aios/aios"
SERVICE = "aios-v2r1c7-production.service"
PORT = 18927
OID_RE = re.compile(r"^[0-9a-f]{40}$")
SHA_RE = re.compile(r"^[0-9a-f]{64}$")
class ReleaseBlocked(RuntimeError):
"""A release gate failed and no unsafe recovery is permitted."""
class ManualOwnerReviewRequired(ReleaseBlocked):
pass
class ReconciliationRequired(ReleaseBlocked):
pass
def canonical(value: object) -> bytes:
return (json.dumps(value, sort_keys=True, separators=(",", ":")) + "\n").encode()
def sha256_file(path: Path) -> str:
if path.is_symlink() or not path.is_file():
raise ReleaseBlocked("artifact must be a regular file")
digest = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def atomic_json(path: Path, value: Mapping[str, Any], mode: int = 0o600) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_name(path.name + ".tmp")
temporary.write_bytes(canonical(dict(value)))
os.chmod(temporary, mode)
os.replace(temporary, path)
@dataclass(frozen=True)
class ReleaseBinding:
version: str = VERSION
target_oid: str = TARGET_OID
evidence_closure_oid: str = EVIDENCE_CLOSURE_OID
approval_plan_id: str = APPROVAL_PLAN_ID
repository: str = REPOSITORY
production_service: str = SERVICE
production_port: int = PORT
def validate(self) -> None:
if self.version != VERSION or self.repository != REPOSITORY:
raise ManualOwnerReviewRequired("release binding is outside V2R2C1 scope")
if not OID_RE.fullmatch(self.target_oid) or self.target_oid != TARGET_OID:
raise ManualOwnerReviewRequired("V2R2C1 target_oid mismatch")
if not OID_RE.fullmatch(self.evidence_closure_oid) or self.evidence_closure_oid != EVIDENCE_CLOSURE_OID:
raise ManualOwnerReviewRequired("V2R2C1 evidence closure mismatch")
if self.approval_plan_id != APPROVAL_PLAN_ID:
raise ManualOwnerReviewRequired("V2R2C1 approval plan mismatch")
if self.production_service != SERVICE or int(self.production_port) != PORT:
raise ManualOwnerReviewRequired("production service binding mismatch")
def as_dict(self) -> dict[str, Any]:
return {
"version": self.version,
"target_oid": self.target_oid,
"evidence_closure_oid": self.evidence_closure_oid,
"approval_plan_id": self.approval_plan_id,
"repository": self.repository,
"production_service": self.production_service,
"production_port": self.production_port,
}
class StateLock:
def __init__(self, path: Path):
self.path = path
self.handle = None
def __enter__(self) -> "StateLock":
self.path.parent.mkdir(parents=True, exist_ok=True)
self.handle = self.path.open("a+", encoding="utf-8")
fcntl.flock(self.handle.fileno(), fcntl.LOCK_EX)
return self
def __exit__(self, exc_type, exc, tb) -> None:
if self.handle is not None:
fcntl.flock(self.handle.fileno(), fcntl.LOCK_UN)
self.handle.close()
class ReleaseState:
def __init__(self, root: Path, binding: ReleaseBinding):
self.root = root
self.path = root / "release-state.json"
self.binding = binding
root.mkdir(parents=True, exist_ok=True)
if self.path.exists():
value = json.loads(self.path.read_text(encoding="utf-8"))
if value.get("binding") != binding.as_dict():
raise ManualOwnerReviewRequired("persisted release binding conflict")
self.value = value
else:
self.value = {
"schema": "aios.v2r2c1.governed-production-release-state.v1",
"binding": binding.as_dict(),
"state": "INITIAL",
"completed": {},
"history": [],
}
self.save()
def save(self) -> None:
atomic_json(self.path, self.value)
def record(self, state: str, step: str, result: Mapping[str, Any]) -> None:
safe = json.loads(json.dumps(dict(result)))
self.value["state"] = state
self.value.setdefault("completed", {})[step] = safe
self.value.setdefault("history", []).append(
{"at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "state": state, "step": step, "result": safe}
)
self.save()
def fail(self, state: str, reason: str) -> None:
self.value["state"] = state
self.value.setdefault("history", []).append(
{"at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "state": state, "reason": str(reason)[:500]}
)
self.save()
def _git(git_dir: Path, *args: str, check: bool = True) -> str:
completed = subprocess.run(
["git", f"--git-dir={git_dir}", *args],
check=False,
capture_output=True,
text=True,
timeout=45,
env={"PATH": os.environ.get("PATH", "")},
)
if check and completed.returncode != 0:
raise ReconciliationRequired(completed.stderr.strip() or "authoritative git query failed")
return completed.stdout.strip()
def _ancestor(git_dir: Path, ancestor: str, descendant: str) -> bool:
return subprocess.run(
["git", f"--git-dir={git_dir}", "merge-base", "--is-ancestor", ancestor, descendant],
check=False,
capture_output=True,
timeout=45,
env={"PATH": os.environ.get("PATH", "")},
).returncode == 0
def verify_lineage(git_dir: Path, binding: ReleaseBinding) -> dict[str, Any]:
binding.validate()
if _git(git_dir, "cat-file", "-t", binding.target_oid) != "commit":
raise ReleaseBlocked("approved target_oid is not a commit")
if _git(git_dir, "cat-file", "-t", binding.evidence_closure_oid) != "commit":
raise ReleaseBlocked("evidence closure is not a commit")
if not _ancestor(git_dir, binding.target_oid, binding.evidence_closure_oid):
raise ManualOwnerReviewRequired("approved target is not an ancestor of evidence closure")
return {
"target_oid": binding.target_oid,
"evidence_closure_oid": binding.evidence_closure_oid,
"target_is_ancestor_of_evidence": True,
"main_oid": _git(git_dir, "rev-parse", "refs/heads/main"),
}
def verify_owner_approval(value: Mapping[str, Any], binding: ReleaseBinding) -> dict[str, Any]:
approval = value.get("owner_approval")
if not isinstance(approval, Mapping):
raise ReleaseBlocked("OWNER_APPROVAL_RECEIPT_REQUIRED")
if approval.get("approved") is not True or approval.get("status") != "APPROVED":
raise ReleaseBlocked("OWNER_APPROVAL_NOT_ACCEPTED")
if approval.get("approved_by") != "aiman":
raise ManualOwnerReviewRequired("OWNER_APPROVAL_ACTOR_MISMATCH")
if approval.get("approval_source") != "explicit_owner_approval_in_chat":
raise ManualOwnerReviewRequired("OWNER_APPROVAL_SOURCE_MISMATCH")
for key, expected in binding.as_dict().items():
if key in {"repository", "production_service", "production_port"}:
continue
if approval.get(key) != expected:
raise ManualOwnerReviewRequired("OWNER_APPROVAL_BINDING_MISMATCH:" + key)
return dict(approval)
def _payload_file(git_dir: Path, oid: str, path: str) -> bytes:
completed = subprocess.run(
["git", f"--git-dir={git_dir}", "show", f"{oid}:{path}"],
check=False,
capture_output=True,
timeout=45,
env={"PATH": os.environ.get("PATH", "")},
)
if completed.returncode != 0:
raise ReleaseBlocked("required release source missing:" + path)
return completed.stdout
def _commit_epoch(git_dir: Path, oid: str) -> int:
return int(_git(git_dir, "show", "-s", "--format=%ct", oid))
def build_production_artifact(
git_dir: Path,
binding: ReleaseBinding,
output_root: Path,
) -> dict[str, Any]:
"""Build a deterministic executable V2R2C1 health artifact from target_oid."""
binding.validate()
verify_lineage(git_dir, binding)
epoch = _commit_epoch(git_dir, binding.target_oid)
output_root.mkdir(parents=True, exist_ok=True)
stem = f"aios-{VERSION}-{binding.target_oid[:12]}"
output = output_root / (stem + ".tar.zst")
with tempfile.TemporaryDirectory(prefix="v2r2c1-artifact-") as temp:
root = Path(temp) / "payload"
root.mkdir(parents=True)
source_paths = {
"active-runtime/app/deployment_state.py": "active-runtime/app/deployment_state.py",
"active-runtime/app/v2r1c6_privacy_tools.py": "active-runtime/app/v2r1c6_privacy_tools.py",
}
for destination, source in source_paths.items():
target = root / destination
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(_payload_file(git_dir, binding.target_oid, source))
generated: dict[str, str] = {
"VERSION": VERSION + "\n",
"active-runtime/app/v2r2c1_health_service.py": (
"from v2r1c6_privacy_tools import main\n\n"
"if __name__ == '__main__':\n raise SystemExit(main())\n"
),
"deploy/aios-v2/systemd/aios-v2r1c7-production.service": (
"[Unit]\nDescription=AIOS V2R2C1 governed health contract service\n"
"After=network.target\n\n[Service]\nType=simple\n"
"User=aios-v2r1c7\nGroup=aios-v2r1c7\n"
"WorkingDirectory=/opt/aios/v2r2c1\n"
"EnvironmentFile=/etc/aios/aios-v2r2c1.env\n"
"ExecStart=/usr/bin/python3 /opt/aios/v2r2c1/active-runtime/app/v2r2c1_health_service.py --serve --host 127.0.0.1 --port ${AIOS_V2R1C7_PORT}\n"
"Restart=on-failure\nRestartSec=5\nNoNewPrivileges=true\nPrivateTmp=true\n"
"ProtectHome=true\nProtectSystem=strict\nProtectKernelLogs=true\n"
"ProtectKernelModules=true\nProtectKernelTunables=true\nProtectControlGroups=true\n"
"RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6\nIPAddressDeny=any\n"
"IPAddressAllow=localhost\nUMask=0077\n\n[Install]\nWantedBy=multi-user.target\n"
),
"deploy/aios-v2/v2r2c1-runtime-config.json": json.dumps({
"schema": "aios.v2r2c1.production-runtime.v1",
"version": VERSION,
"target_oid": binding.target_oid,
"service": SERVICE,
"port": PORT,
"health_path": "/health",
"deployment_state_source": "environment_and_state_file",
}, sort_keys=True, separators=(",", ":")) + "\n",
"deploy/aios-v2/v2r2c1-rollback.json": json.dumps({
"schema": "aios.v2r2c1.rollback-metadata.v1",
"rollback_version": "V2R1C7",
"rollback_service": SERVICE,
"rollback_target_is_previous_production": True,
"automatic_rollback": False,
}, sort_keys=True, separators=(",", ":")) + "\n",
"scripts/probe_v2r2c1_health.py": (
"import json,sys,urllib.request\n"
"url=sys.argv[1] if len(sys.argv)>1 else 'http://127.0.0.1:18927/health'\n"
"with urllib.request.urlopen(url, timeout=5) as r: print(json.dumps(json.load(r), sort_keys=True))\n"
),
"scripts/rollback_v2r2c1_release.sh": "#!/bin/sh\nset -eu\nprintf '%s\\n' 'rollback requires governed owner-approved executor'\nexit 2\n",
"release-manifests/V2R2C1.json": json.dumps({
"schema": "aios.release-source.v2",
"version": VERSION,
"repository": REPOSITORY,
"target_oid": binding.target_oid,
"evidence_closure_oid": binding.evidence_closure_oid,
"production_deployed": False,
"deployment_state": "STAGING",
"artifact_kind": "executable-production-health",
}, sort_keys=True, separators=(",", ":")) + "\n",
}
for rel, text in generated.items():
target = root / rel
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(text, encoding="utf-8")
if rel.startswith("scripts/"):
target.chmod(0o755)
metadata = {
"schema": "aios.release-artifact-build.v3",
"version": VERSION,
"repository": REPOSITORY,
"source_head_oid": binding.target_oid,
"evidence_closure_oid": binding.evidence_closure_oid,
"source_date_epoch": epoch,
"clean_source": True,
"executable_payload": True,
"production_deployed": False,
"tag_created": False,
"baseline_changed": False,
"secrets_included": False,
}
(root / "BUILD-METADATA.json").write_bytes(canonical(metadata))
(root / "ROLLBACK-METADATA.json").write_bytes(canonical(json.loads((root / "deploy/aios-v2/v2r2c1-rollback.json").read_text(encoding="utf-8"))))
names = sorted("payload/" + str(path.relative_to(root)).replace(os.sep, "/") for path in root.rglob("*") if path.is_file())
(root / "ARTIFACT-MANIFEST.json").write_bytes(canonical({
"schema": "aios.release-artifact-manifest.v3",
"version": VERSION,
"source_head_oid": binding.target_oid,
"evidence_closure_oid": binding.evidence_closure_oid,
"repository": REPOSITORY,
"files": names + ["payload/ARTIFACT-MANIFEST.json"],
"deployable": True,
"executable_payload": True,
"production_deployed": False,
"tag_created": False,
"baseline_changed": False,
}))
tar_path = Path(temp) / "release.tar"
with tarfile.open(tar_path, "w") as archive:
for path in sorted(root.rglob("*")):
relative = str(path.relative_to(root)).replace(os.sep, "/")
info = archive.gettarinfo(str(path), arcname="payload/" + relative)
info.uid = info.gid = 0
info.uname = "root"
info.gname = "root"
info.mtime = epoch
info.mode = 0o755 if path.is_dir() or path.suffix == ".sh" else 0o644
if path.is_file():
with path.open("rb") as stream:
archive.addfile(info, stream)
else:
archive.addfile(info)
subprocess.run(["zstd", "-T1", "-19", "--no-progress", "-q", "-f", str(tar_path), "-o", str(output)], check=True, timeout=120)
digest = sha256_file(output)
receipt = {
"schema": "aios.release-artifact-receipt.v3",
"version": VERSION,
"repository": REPOSITORY,
"source_head_oid": binding.target_oid,
"evidence_closure_oid": binding.evidence_closure_oid,
"artifact": str(output),
"artifact_sha256": digest,
"artifact_size": output.stat().st_size,
"deployable": True,
"executable_payload": True,
"production_deployed": False,
"tag_created": False,
"baseline_changed": False,
}
atomic_json(output.with_suffix(output.suffix + ".receipt.json"), receipt, mode=0o640)
return receipt
class GovernedProductionReleaseExecutor:
def __init__(self, config: Any):
self.config = config
self.binding = ReleaseBinding()
self.binding.validate()
self.root = Path(config.state_root) / "v2r2c1-governed-production-release"
self.state = ReleaseState(self.root, self.binding)
workspace = self.root / "publication-workspace"
workspace.mkdir(parents=True, exist_ok=True)
self.publisher = TagPublisher(
workspace,
GitTagBackend(workspace, authoritative_repo=Path(config.authoritative_git_dir)),
GiteaTagClient(config.api_base, REPOSITORY, Path(config.token_path)),
config.remote_name,
state_root=self.root / "tag-publication",
)
def _request(self, request: Mapping[str, Any]) -> PublicationRequest:
binding = self.binding
for key, expected in binding.as_dict().items():
if key in request and request[key] != expected:
raise ManualOwnerReviewRequired("release request binding mismatch:" + key)
return PublicationRequest(binding.version, binding.target_oid, binding.evidence_closure_oid, binding.approval_plan_id)
def approval_request(self, request: Mapping[str, Any]) -> dict[str, Any]:
if request.get("execute") is not False:
raise ReleaseBlocked("TAG_APPROVAL_REQUEST_MUST_BE_DRY_RUN")
owner = verify_owner_approval(request, self.binding)
with StateLock(self.root / "release.lock"):
current = self.state.value.get("approval")
approval_digest = hashlib.sha256(canonical(owner)).hexdigest()
record = {
"schema": "aios.v2r2c1.tag-approval-request.v1",
"binding": self.binding.as_dict(),
"owner_approval": owner,
"owner_approval_digest_sha256": approval_digest,
"execute": False,
"recorded_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
}
if current and current != record:
raise ManualOwnerReviewRequired("persisted Owner approval differs")
self.state.value["approval"] = record
self.state.record("APPROVAL_REQUEST_RECORDED", "tag_approval_request", record)
return {"status": "RECORDED", "execute": False, "binding": self.binding.as_dict(), "owner_approval_digest_sha256": approval_digest}
def _require_approval(self) -> None:
approval = self.state.value.get("approval")
if not isinstance(approval, Mapping) or approval.get("binding") != self.binding.as_dict():
raise ReleaseBlocked("OWNER_APPROVAL_REQUEST_NOT_RECORDED")
def publish_tag(self, request: Mapping[str, Any]) -> dict[str, Any]:
if request.get("execute") is not True:
raise ReleaseBlocked("TAG_PUBLICATION_REQUIRES_EXECUTE_TRUE")
self._require_approval()
publication = self._request(request)
with StateLock(self.root / "release.lock"):
try:
verified = self.publisher._verify_publication(publication, allow_push=True, previously_deployed=False)
except PublicationManualOwnerReviewRequired as exc:
self.state.fail("MANUAL_OWNER_REVIEW_REQUIRED", str(exc))
raise ManualOwnerReviewRequired(str(exc)) from exc
except PublicationPending as exc:
self.state.fail("REMOTE_PUSH_PENDING", str(exc))
raise ReconciliationRequired(str(exc)) from exc
except PublicationReconciliationRequired as exc:
self.state.fail("RECONCILIATION_REQUIRED", str(exc))
raise ReconciliationRequired(str(exc)) from exc
result = dict(verified)
self.state.record("TAG_VERIFIED", "tag", result)
return {"status": "REMOTE_VERIFIED", **result}
def tag_status(self, request: Mapping[str, Any]) -> dict[str, Any]:
self._request(request)
return self.publisher.get_tag_publication_status(VERSION)
def build_artifact(self, request: Mapping[str, Any]) -> dict[str, Any]:
self._require_approval()
self._request(request)
receipt = build_production_artifact(Path(self.config.authoritative_git_dir), self.binding, self.root / "artifacts")
self.state.record("ARTIFACT_VERIFIED", "production_artifact", receipt)
return {"status": "VERIFIED", **receipt}
def execute_request(self, request: Mapping[str, Any]) -> dict[str, Any]:
self._require_approval()
publication = self._request(request)
tag_state = self.state.value.get("completed", {}).get("tag")
if not isinstance(tag_state, Mapping) or tag_state.get("state") not in {"GITEA_API_CONFIRMED", "REMOTE_VERIFIED"}:
raise ReleaseBlocked("REMOTE_TAG_PROOF_REQUIRED")
artifact = self.state.value.get("completed", {}).get("production_artifact")
if not isinstance(artifact, Mapping):
artifact = self.build_artifact(request)
value = {
**self.binding.as_dict(),
"tag_oid": tag_state.get("tag_oid") or tag_state.get("gitea_tag_oid"),
"artifact_path": artifact["artifact"],
"artifact_size": int(artifact["artifact_size"]),
"artifact_sha256": artifact["artifact_sha256"],
}
# The production adapter is privileged and is run through the root
# approved-release service boundary by the caller. This handler is
# still useful for a root-owned staging invocation and remains
# fail-closed when the adapter is not available.
import v2r2c1_production_adapter
runtime = v2r2c1_production_adapter.execute_request({"schema": "aios.production-executor-request.v1", "operation": "apply", **value})
if runtime.get("status") != "ACTIVE_VERIFIED":
self.state.fail("RECONCILIATION_REQUIRED", "production health did not verify")
raise ReconciliationRequired("production health did not verify")
self.state.record("PRODUCTION_VERIFIED", "production", runtime)
return {"status": "PRODUCTION_VERIFIED", "runtime": runtime, "artifact": artifact, "tag_oid": value["tag_oid"]}
def consistency(self, request: Mapping[str, Any]) -> dict[str, Any]:
publication = self._request(request)
result = self.publisher.get_release_consistency(publication)
result["release_binding"] = self.binding.as_dict()
result["production_health"] = _health(self.config.health_url, self.binding, self.state.value.get("completed", {}).get("production_artifact", {}))
result["registry"] = _read_json(Path(self.config.registry_root) / f"{VERSION}.json")
result["baseline"] = _read_json(Path(self.config.baseline_path))
return result
def acceptance(self, request: Mapping[str, Any]) -> dict[str, Any]:
result = self.consistency(request)
result["accepted"] = result.get("status") == "PASS" and result.get("production_health", {}).get("status") == "ACTIVE_VERIFIED"
self.state.record("ACCEPTED" if result["accepted"] else "RECONCILIATION_REQUIRED", "acceptance", result)
return result
def _read_json(path: Path) -> dict[str, Any]:
try:
value = json.loads(path.read_text(encoding="utf-8"))
except FileNotFoundError:
return {"status": "MISSING", "path": str(path)}
if not isinstance(value, dict):
return {"status": "INVALID", "path": str(path)}
return {"status": "PRESENT", "path": str(path), **value}
def _health(url: str, binding: ReleaseBinding, artifact: Mapping[str, Any]) -> dict[str, Any]:
import urllib.request
try:
with urllib.request.urlopen(url, timeout=5) as response:
body = json.loads(response.read().decode("utf-8"))
status = response.status
except Exception as exc:
return {"status": "UNAVAILABLE", "error": type(exc).__name__}
expected_artifact = artifact.get("artifact_sha256")
exact = (
status == 200
and body.get("version") == binding.version
and body.get("commit_oid") == binding.target_oid
and (not expected_artifact or body.get("artifact_sha256") == expected_artifact)
and body.get("deployment_state") == "ACTIVE"
and body.get("production_deployed") is True
)
return {"status": "ACTIVE_VERIFIED" if exact else "CONFLICT", "http_status": status, **body}
def build_executor_config(config: Any) -> GovernedProductionReleaseExecutor:
return GovernedProductionReleaseExecutor(config)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("operation", choices=("build-artifact", "status"))
parser.add_argument("--git-dir", type=Path, default=Path("/data/aios-gitops/repo.git"))
parser.add_argument("--output-root", type=Path, default=Path("/var/lib/aios-gitops/approved-artifacts/V2R2C1"))
args = parser.parse_args()
binding = ReleaseBinding()
if args.operation == "build-artifact":
print(json.dumps(build_production_artifact(args.git_dir, binding, args.output_root), sort_keys=True))
else:
print(json.dumps({"binding": binding.as_dict(), "status": "READY"}, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -1,135 +0,0 @@
"""V2R2C1 adapter using the existing V2R1C7 deployment primitives.
The service identity and loopback port remain stable for a safe cutover. The
new release is installed under its own immutable directory and keeps the
previous V2R1C7 release available for an explicit, owner-approved rollback.
"""
from __future__ import annotations
import json
import os
import shutil
import sys
from argparse import Namespace
from pathlib import Path
from typing import Any, Mapping
import v2r1c7_production_adapter as base
VERSION = "V2R2C1"
SERVICE = "aios-v2r1c7-production.service"
PORT = 18927
RELEASE_ROOT = Path("/opt/aios/releases")
CURRENT_LINK = Path("/opt/aios/v2r2c1")
ENV_FILE = Path("/etc/aios/aios-v2r2c1.env")
STATE_FILE = Path("/var/lib/aios/v2r2c1/deployment-state.json")
UNIT_FILE = Path("/etc/systemd/system/aios-v2r1c7-production.service")
ROLLBACK_ROOT = Path("/var/lib/aios/v2r2c1/rollback")
REQUIRED_MEMBERS = {
"payload/VERSION",
"payload/active-runtime/app/deployment_state.py",
"payload/active-runtime/app/v2r1c6_privacy_tools.py",
"payload/active-runtime/app/v2r2c1_health_service.py",
"payload/deploy/aios-v2/systemd/aios-v2r1c7-production.service",
"payload/deploy/aios-v2/v2r2c1-runtime-config.json",
"payload/deploy/aios-v2/v2r2c1-rollback.json",
"payload/scripts/probe_v2r2c1_health.py",
"payload/scripts/rollback_v2r2c1_release.sh",
"payload/BUILD-METADATA.json",
"payload/ARTIFACT-MANIFEST.json",
"payload/ROLLBACK-METADATA.json",
}
def _configure_base() -> None:
base.VERSION = VERSION
base.SERVICE = SERVICE
base.PORT = PORT
base.REQUIRED_MEMBERS = REQUIRED_MEMBERS
def _args() -> Namespace:
return Namespace(
release_root=RELEASE_ROOT,
current_link=CURRENT_LINK,
env_file=ENV_FILE,
state_file=STATE_FILE,
unit_file=UNIT_FILE,
health_timeout=45,
)
def load_request() -> dict[str, Any]:
_configure_base()
value = base.load_request()
if value.get("version") != VERSION or value.get("production_service") != SERVICE or int(value.get("production_port", -1)) != PORT:
raise ValueError("V2R2C1 production binding mismatch")
return value
def _backup(path: Path, name: str) -> None:
if path.is_file() and not path.is_symlink():
ROLLBACK_ROOT.mkdir(parents=True, exist_ok=True)
destination = ROLLBACK_ROOT / name
if not destination.exists():
shutil.copy2(path, destination)
def execute_request(value: Mapping[str, Any]) -> dict[str, Any]:
_configure_base()
if value.get("schema") != "aios.production-executor-request.v1":
raise ValueError("request_schema_invalid")
if value.get("operation") == "apply":
_backup(UNIT_FILE, "aios-v2r1c7-production.service.previous")
_backup(Path("/etc/aios/aios-v2r1c7.env"), "aios-v2r1c7.env.previous")
_backup(Path("/var/lib/aios/v2r1c7/deployment-state.json"), "v2r1c7-deployment-state.previous")
return base.install_release(_args(), value)
if value.get("operation") == "probe":
return base.probe(_args(), value)
if value.get("operation") == "rollback":
return rollback(value)
raise ValueError("unsupported_operation")
def rollback(value: Mapping[str, Any]) -> dict[str, Any]:
"""Explicit rollback only; this adapter never invokes it automatically."""
import subprocess
subprocess.run(["systemctl", "stop", SERVICE], check=False, capture_output=True, text=True, timeout=45)
previous_unit = ROLLBACK_ROOT / "aios-v2r1c7-production.service.previous"
previous_env = ROLLBACK_ROOT / "aios-v2r1c7.env.previous"
previous_state = ROLLBACK_ROOT / "v2r1c7-deployment-state.previous"
if not previous_unit.is_file() or not previous_env.is_file():
raise RuntimeError("ROLLBACK_RECEIPT_MISSING")
UNIT_FILE.parent.mkdir(parents=True, exist_ok=True)
ENV_FILE.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(previous_unit, UNIT_FILE)
shutil.copy2(previous_env, Path("/etc/aios/aios-v2r1c7.env"))
if previous_state.is_file():
Path("/var/lib/aios/v2r1c7").mkdir(parents=True, exist_ok=True)
shutil.copy2(previous_state, Path("/var/lib/aios/v2r1c7/deployment-state.json"))
subprocess.run(["systemctl", "daemon-reload"], check=True, capture_output=True, text=True, timeout=45)
subprocess.run(["systemctl", "restart", SERVICE], check=True, capture_output=True, text=True, timeout=45)
result = base.health("http://127.0.0.1:18927/health", {
"version": "V2R1C7",
"target_oid": str(json.loads(Path("/var/lib/aios/v2r1c7/deployment-state.json").read_text(encoding="utf-8")).get("commit_oid")),
"artifact_sha256": str(json.loads(Path("/var/lib/aios/v2r1c7/deployment-state.json").read_text(encoding="utf-8")).get("artifact_sha256")),
})
return {"status": "ROLLED_BACK", "rollback_health": result, "automatic_rollback": False}
def main() -> int:
try:
value = load_request()
result = execute_request(value)
print(json.dumps(result, sort_keys=True))
return 0
except Exception as exc:
print(json.dumps({"status": "FAIL_CLOSED", "error": type(exc).__name__, "reason": str(exc)}, sort_keys=True))
return 2
if __name__ == "__main__":
raise SystemExit(main())
@@ -1,51 +0,0 @@
[Unit]
Description=AIOS GitOps Model API V2R2C1 immutable staging runtime
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aiman
Group=gitops
WorkingDirectory=@RUNTIME_ROOT@
Environment=PYTHONUNBUFFERED=1
Environment=PYTHONDONTWRITEBYTECODE=1
Environment=AIOS_GITOPS_ROOT=/var/lib/aios-gitops
Environment=AIOS_GITOPS_WORKSPACE=@RUNTIME_ROOT@
Environment=AIOS_GITOPS_REPO=/data/aios-gitops/repo.git
Environment=AIOS_GITOPS_BARE_REPO=/data/aios-gitops/repo.git
Environment=AIOS_GITOPS_AUTHORITATIVE_GIT_DIR=/data/aios-gitops/repo.git
Environment=AIOS_GITOPS_REPOSITORY_IDENTITY=aios/aios
Environment=AIOS_GITOPS_BASELINE_AUTHORITY=/var/lib/aios-gitops-runtime-anchor/baseline/current.json
Environment=AIOS_GITOPS_WRITES_ENABLED=false
Environment=AIOS_GITOPS_DURABLE_JOB_EXECUTION_ENABLED=false
Environment=AIOS_GITOPS_JOB_CONTROLLER_ENABLED=false
Environment=AIOS_GITOPS_WORKSPACE_ROLE=runtime-anchor
Environment=AIOS_GITOPS_RUNTIME_OID=@SOURCE_OID@
Environment=AIOS_GITOPS_ARTIFACT_SHA256=@ARTIFACT_SHA256@
Environment=AIOS_GITOPS_DEPLOYMENT_STATE=STAGING
Environment=AIOS_GITOPS_MODEL_API_SERVICE=aios-gitops-model-api-v2r2c1-staging.service
Environment=AIOS_SILENT_RELEASE_EXECUTION_ENABLED=false
Environment=AIOS_SILENT_RELEASE_STATE_ROOT=/var/lib/aios-gitops/model-api-staging/silent-release
Environment=AIOS_BRIDGE_V2_URL=http://127.0.0.1:18892
Environment=AIOS_GITOPS_HOST=127.0.0.1
Environment=AIOS_GITOPS_PORT=18893
Environment=PYTHONPATH=@RUNTIME_ROOT@/app:@RUNTIME_ROOT@/runtime-agent-os
ExecStart=/usr/bin/python3 @RUNTIME_ROOT@/app/aios_model_api_staging.py
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
LockPersonality=true
RestrictSUIDSGID=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadOnlyPaths=@RUNTIME_ROOT@ /data/aios-gitops/repo.git /var/lib/aios-gitops-runtime-anchor/baseline
ReadWritePaths=/var/lib/aios-gitops/model-api-staging
[Install]
WantedBy=multi-user.target
@@ -1,721 +0,0 @@
{
"schema_version": "aios.chatgpt-action-schema-capability-manifest.v2",
"source_schema": {
"path": "docs/gitops/openapi-chatgpt-actions.yaml",
"operation_count": 31,
"sha256": "d6129421085c9516ba88796d8727bc4ba1c4b4b48bac74f146e68ebf7cc9cd96"
},
"public_runtime_schema": {
"path": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml",
"immutable_runtime_oid": "2e5996463de564793df881df5c5f684359733627",
"operation_count": 30,
"sha256": "4cee48511e9435cb147b8925c37aaa135c384a468ede34d6828bad42c97c5fcc"
},
"authoritative_server_urls": [
"https://cnnetmkt.top"
],
"union_operation_count": 46,
"schemas": [
{
"path": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"operation_count": 26,
"public_action_import": true
},
{
"path": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"operation_count": 14,
"public_action_import": true
},
{
"path": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"operation_count": 6,
"public_action_import": true
}
],
"operations": [
{
"operation_id": "acquireWriterLease",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/acquireWriterLease",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "cancelOnlineAgentTask",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/cancelOnlineAgentTask",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "commitChanges",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/commit",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "commit:create",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "commitFile",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/file",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "commitFileAtomic",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/commit-file",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "commitFileGoverned",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/commitFileGoverned",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "commitFilesGoverned",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/commitFilesGoverned",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "createBranch",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/branch",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "branch:create",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "createGovernedTask",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/createGovernedTask",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "branch:create",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "createOnlineAgentTask",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/createOnlineAgentTask",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "createPatch",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/patch",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "patch:create",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "createReleaseCandidate",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/createReleaseCandidate",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "release:candidate",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "createReleaseIntent",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/createReleaseIntent",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "release:candidate",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "getApprovalEnvelope",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getApprovalEnvelope",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getBaseline",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/base",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getCapabilityStatus",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getCapabilityStatus",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "getControlPlaneSnapshot",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/control-plane-snapshot",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getDiff",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/diff",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getGitOpsJob",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getGitOpsJob",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getGovernedWriteCapabilities",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/governed-write-capabilities",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getOnlineAgentTask",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/online-agent-task",
"method": "GET",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getOnlineAgentTaskEvents",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/online-agent-task-events",
"method": "GET",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getRecoveryStatus",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getRecoveryStatus",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "getReleaseAcceptance",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getReleaseAcceptance",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "getReleaseCandidate",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getReleaseCandidate",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getReleaseConsistency",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/release-consistency",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getReleasePlan",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getReleasePlan",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "getReleaseSaga",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/getReleaseSaga",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getRuntimeStatus",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/run",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "getTagPublicationStatus",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/tag-publication-status",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "listPatches",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/patch",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "listVersions",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/ver",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "planNaturalLanguageGitOpsAction",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/nl",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "nl:plan",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "readModelRegistry",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/model",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "reconcileGitOpsJob",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/reconcileGitOpsJob",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "registerModel",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/model",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "model:write",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "registerOnlineAgent",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/registerOnlineAgent",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "requestOrCreateTag",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/tag",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "tag:create",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "requestRollback",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/rollback",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "rollback:request",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "resumeGitOpsJob",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/resumeGitOpsJob",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "file:write",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "runReleaseAcceptance",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/release-acceptance",
"method": "GET",
"declared_openapi_security": [],
"required_scope": null,
"exposure": "public",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "setModelPriority",
"schema": "docs/gitops/openapi-chatgpt-actions-online-gitops-task.yaml",
"trust_domain": "online-gitops-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/api/model-priority",
"method": "PUT",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "model:priority",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "startDeployment",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/startDeployment",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "release:deploy",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "submitOwnerApproval",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/submitOwnerApproval",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "release:approve",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
},
{
"operation_id": "submitSignedApproval",
"schema": "docs/gitops/openapi-chatgpt-actions-governed-release.yaml",
"trust_domain": "governed-release",
"server_url": "https://cnnetmkt.top",
"server_route": "/submitSignedApproval",
"method": "POST",
"declared_openapi_security": [
{
"bearerAuth": []
}
],
"required_scope": "release:approve",
"exposure": "control-plane",
"source_origin": "docs/gitops/openapi-chatgpt-actions.yaml",
"public_origin": null
},
{
"operation_id": "verifyOnlineAgentTask",
"schema": "docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml",
"trust_domain": "online-agent-task",
"server_url": "https://cnnetmkt.top",
"server_route": "/verifyOnlineAgentTask",
"method": "POST",
"declared_openapi_security": [],
"required_scope": "agent-task:control",
"exposure": "control-plane",
"source_origin": null,
"public_origin": "docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml"
}
],
"scope_provenance": {
"release_and_gitops": "immutable staging runtime aios_model_api_staging.py handler scope checks",
"agent_task_control": {
"required_scope": "agent-task:control",
"immutable_runtime_oid": "2e5996463de564793df881df5c5f684359733627",
"proxy_routes": [
"/api/online-agent-task",
"/api/online-agent-task-events",
"/createOnlineAgentTask",
"/registerOnlineAgent",
"/verifyOnlineAgentTask",
"/cancelOnlineAgentTask"
],
"operation_ids": [
"cancelOnlineAgentTask",
"createOnlineAgentTask",
"getOnlineAgentTask",
"getOnlineAgentTaskEvents",
"registerOnlineAgent",
"verifyOnlineAgentTask"
]
}
}
}
@@ -1,13 +0,0 @@
# ChatGPT Action schema trust-domain reconciliation
The main source has **31** operations while immutable public runtime `2e5996463de564793df881df5c5f684359733627` serves a different **30**. Both are retained as non-import parity fixtures. Their exact compatible union is **46** operations.
Import only these bounded specs:
- `openapi-chatgpt-actions-governed-release.yaml` — 26 Governed GitOps and Release operations.
- `openapi-chatgpt-actions-online-gitops-task.yaml` — 14 Online GitOps Task operations.
- `openapi-chatgpt-actions-online-agent-task.yaml` — 6 actual public Online Agent Task operations.
The machine-readable capability manifest records split schema, server route, declared OpenAPI security, required runtime scope, exposure, and `source_origin` / `public_origin` for every union operation. The dedicated Online Agent Task document includes `createOnlineAgentTask`, `registerOnlineAgent`, `getOnlineAgentTask`, `getOnlineAgentTaskEvents`, `verifyOnlineAgentTask`, and `cancelOnlineAgentTask`; each requires runtime scope `agent-task:control`. Its declared OpenAPI security is copied from the public snapshot without rewrite, while the manifest records the runtime scope separately.
Run `python3 scripts/validate_chatgpt_action_schema_split.py` and `python3 -m unittest discover -s tests -p 'test_chatgpt_action_schema_split.py' -v`. The validator reports `formal_validator=NOT_INSTALLED` rather than a false formal pass if `openapi-spec-validator` is absent.
@@ -1,6 +1,20 @@
# Merge this fragment into docs/gitops/openapi-chatgpt-actions.yaml.
components:
schemas:
WriterLeaseRequestV2:
type: object
additionalProperties: false
required: [schema, task_id, repository, branch_mode, base_oid, expected_branch_oid, target_branch, generation, lease_seconds]
properties:
schema: {type: string, const: aios.task-writer-lease.v2}
task_id: {type: string}
repository: {type: string, const: aios/aios}
branch_mode: {type: string, const: CONTINUE_EXISTING}
base_oid: {type: string, pattern: '^[0-9a-f]{40}$'}
expected_branch_oid: {type: string, pattern: '^[0-9a-f]{40}$'}
target_branch: {type: string, pattern: '^agent/'}
generation: {type: integer, minimum: 1}
lease_seconds: {type: integer, minimum: 1, maximum: 86400}
AuthorizedTaskWriterProvisionRequest:
type: object
additionalProperties: false
@@ -90,6 +104,20 @@ components:
- production_marker_write
- history_rewrite
ControlPlaneSnapshot:
type: object
additionalProperties: false
required: [version, runtime, repository, production, task, capabilities, credential_broker, secret_material_exposed]
properties:
version: {type: object}
runtime: {type: object}
repository: {type: object}
production: {type: object}
task: {type: object}
capabilities: {type: object}
credential_broker: {type: object}
secret_material_exposed: {type: boolean, const: false}
paths:
/api/task-writer/provision-authorized:
post:
@@ -119,3 +147,10 @@ paths:
description: Base drift, branch conflict, or idempotency scope conflict
'503':
description: Signer, validator, provisioner, or attestation unavailable
/v2/control-plane-snapshot:
get:
operationId: getControlPlaneSnapshot
responses:
'200':
description: Non-sensitive control-plane snapshot
File diff suppressed because it is too large Load Diff
@@ -1,782 +0,0 @@
openapi: 3.1.0
info:
title: AIOS ChatGPT Actions - Online Agent Task
version: V1R1C0-chatgpt-actions-online-agent-task
description: Trust-domain import from the exact union of the 31-operation main source and 30-operation
immutable public runtime; operation, server route, and declared security are preserved.
servers:
- url: https://cnnetmkt.top
security: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: opaque-token
schemas:
PublicationState:
type: string
description: Canonical durable publication state. Legacy TAG_CREATED_LOCAL is normalized on read
and is never emitted by new writes.
enum:
- PENDING
- LOCAL_TAG_CREATED
- REMOTE_PUSH_PENDING
- REMOTE_PUSH_CONFIRMED
- GITEA_API_CONFIRMED
- BASELINE_UPDATE_PENDING
- BASELINE_UPDATED
- PRODUCTION_DEPLOYED
- RECONCILIATION_REQUIRED
- MANUAL_OWNER_REVIEW_REQUIRED
PublicationStatus:
type: object
required:
- version
- state
properties:
version:
type: string
state:
$ref: '#/components/schemas/PublicationState'
fail_closed:
type: boolean
BranchRequest:
type: object
required:
- branch
properties:
branch:
type: string
example: patch/chatgpt-actions-demo
base:
type: string
default: main
message:
type: string
FileCommitRequest:
type: object
required:
- branch
- path
- content
properties:
branch:
type: string
base:
type: string
default: main
create_branch:
type: boolean
default: false
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:
branch:
type: string
paths:
type: array
items:
type: string
message:
type: string
PatchRequest:
type: object
required:
- patch_name
properties:
patch_name:
type: string
branch:
type: string
base:
type: string
default: main
risk:
type: string
enum:
- low
- medium
- high
description:
type: string
message:
type: string
TagRequest:
type: object
required:
- version
- target_oid
- evidence_closure_oid
- approval_plan_id
properties:
version:
type: string
example: V1R1C1
target_oid:
type: string
pattern: ^[0-9a-fA-F]{40}$
description: Full approved commit OID. The tag is created explicitly at this commit, never implicitly
at workspace HEAD.
evidence_closure_oid:
type: string
pattern: ^[0-9a-fA-F]{40}$
description: Required evidence closure commit. target_oid must be its ancestor.
approval_plan_id:
type: string
description: Audited owner-approved release or tag plan identifier.
message:
type: string
execute:
type: boolean
description: Owner-approved calls only. Otherwise an approval request commit is created.
RollbackRequest:
type: object
required:
- target_version
properties:
target_version:
type: string
reason:
type: string
branch:
type: string
ModelRequest:
type: object
required:
- provider_name
- base_url
- model_name
properties:
username:
type: string
provider_name:
type: string
base_url:
type: string
model_name:
type: string
display_name:
type: string
api_key_secret_ref:
type: string
description: Preferred. Git stores this secret_ref only.
api_key:
type: string
writeOnly: true
description: Accepted only for runtime secret storage; never committed to Git or logs.
branch:
type: string
message:
type: string
ModelPriorityRequest:
type: object
required:
- items
properties:
username:
type: string
branch:
type: string
items:
type: array
items:
type: object
properties:
model_id:
type: string
priority:
type: integer
enabled:
type: boolean
fallback_policy:
type: string
NLRequest:
type: object
required:
- text
properties:
text:
type: string
branch:
type: string
DeploymentPlan:
type: object
required:
- service
- release_path
- release_root
- cutover_link
- dropin_path
- dropin_sha256
- systemd_unit_sha256
- rollback_path
- rollback_sha256
- source_commit
- tree_oid
- artifact_sha256
- manifest_sha256
- package_closure_sha256
- authoritative_git_dir
- repository_identity
- writer_expected
- baseline_before_sha256
- registry_before_sha256
- production_tag_refset_before_sha256
- health_contract_version
- timeout_policy
- retry_policy
- policy_sha256
- health_contract
properties:
service:
type: string
release_path:
type: string
release_root:
type: string
cutover_link:
type: string
dropin_path:
type: string
dropin_sha256:
type: string
pattern: ^[0-9a-f]{64}$
systemd_unit_sha256:
type: string
pattern: ^[0-9a-f]{64}$
rollback_path:
type: string
rollback_sha256:
type: string
pattern: ^[0-9a-f]{64}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
tree_oid:
type: string
pattern: ^[0-9a-f]{40}$
artifact_sha256:
type: string
pattern: ^[0-9a-f]{64}$
manifest_sha256:
type: string
pattern: ^[0-9a-f]{64}$
package_closure_sha256:
type: string
pattern: ^[0-9a-f]{64}$
authoritative_git_dir:
type: string
repository_identity:
type: string
writer_expected:
type: boolean
enum:
- false
baseline_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
registry_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
production_tag_refset_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
health_contract_version:
type: string
timeout_policy:
type: object
retry_policy:
type: object
policy_sha256:
type: string
pattern: ^[0-9a-f]{64}$
health_contract:
type: object
additionalProperties: true
ReleaseCandidateInput:
type: object
required:
- source_commit
- version
additionalProperties: false
properties:
candidate_id:
type: string
pattern: ^[A-Za-z0-9][A-Za-z0-9_.-]{2,127}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
version:
type: string
pattern: ^V[0-9]+R[0-9]+C[0-9]+(?:[-.][A-Za-z0-9][A-Za-z0-9.-]*)?$
ReleaseIntentInput:
type: object
required:
- event_id
- source_commit
additionalProperties: false
properties:
event_id:
type: string
pattern: ^[A-Za-z0-9][A-Za-z0-9_.:-]{2,255}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
SignedReleasePlanApproval:
type: object
required:
- release_plan_id
- candidate_id
- source_commit
- tree_oid
- artifact_sha256
- manifest_sha256
- deployment_plan_sha256
- release_plan_sha256
- policy_sha256
- approval_plan_id
- evidence_closure_oid
- owner_approval_record_oid
- capabilities
- owner_identity
- trust_domain
- issued_at
- not_before
- expires_at
- nonce
- key_id
- signature
properties:
release_plan_id:
type: string
candidate_id:
type: string
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
tree_oid:
type: string
pattern: ^[0-9a-f]{40}$
artifact_sha256:
type: string
pattern: ^[0-9a-f]{64}$
manifest_sha256:
type: string
pattern: ^[0-9a-f]{64}$
deployment_plan_sha256:
type: string
pattern: ^[0-9a-f]{64}$
release_plan_sha256:
type: string
pattern: ^[0-9a-f]{64}$
policy_sha256:
type: string
pattern: ^[0-9a-f]{64}$
approval_plan_id:
type: string
evidence_closure_oid:
type: string
pattern: ^[0-9a-f]{40}$
owner_approval_record_oid:
type: string
pattern: ^[0-9a-f]{40}$
owner_identity:
type: string
trust_domain:
type: string
issued_at:
type: string
format: date-time
not_before:
type: string
format: date-time
capabilities:
type: array
uniqueItems: true
items:
type: string
enum:
- runtime_switch
- tag_publish
- baseline_registry_finalize
expires_at:
type: string
format: date-time
nonce:
type: string
minLength: 16
key_id:
type: string
signature:
type: string
format: byte
writeOnly: true
StartDeploymentRequest:
type: object
required:
- candidate_id
additionalProperties: false
properties:
candidate_id:
type: string
Oid40:
type: string
pattern: ^[0-9a-f]{40}$
CreateGovernedTaskRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- base_oid
- target_branch
- risk
- description
- idempotency_key
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
base_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
risk:
type: string
enum:
- low
- medium
- high
- engineering
description:
type: string
idempotency_key:
type: string
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
generation:
type: integer
minimum: 1
WriterLeaseRequest:
type: object
additionalProperties: false
required:
- schema
- task_id
- repository
- branch_mode
- base_oid
- expected_branch_oid
- target_branch
- generation
- lease_seconds
properties:
schema:
type: string
task_id:
type: string
repository:
type: string
const: aios/aios
branch_mode:
type: string
enum:
- CREATE_NEW
- CONTINUE_EXISTING
base_oid:
$ref: '#/components/schemas/Oid40'
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
lease_seconds:
type: integer
minimum: 1
maximum: 86400
CommitFileGovernedRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- expected_branch_oid
- target_branch
- generation
- idempotency_key
- path
- content_base64
- message
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
idempotency_key:
type: string
path:
type: string
content_base64:
type: string
message:
type: string
CommitFilesGovernedRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- expected_branch_oid
- target_branch
- generation
- idempotency_key
- files
- message
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
idempotency_key:
type: string
files:
type: object
additionalProperties:
type: string
description: Base64 encoded file bytes
message:
type: string
CreateOnlineAgentTaskRequest:
type: object
additionalProperties: false
required:
- goal
- instructions
- success_criteria
- idempotency_key
properties:
task_id:
type: string
goal:
type: string
instructions:
type: string
success_criteria:
type: array
items: {}
required_capabilities:
type: array
items:
type: string
constraints:
type: object
additionalProperties: true
metadata:
type: object
additionalProperties: true
deadline:
type: string
format: date-time
priority:
type: integer
minimum: -100
maximum: 100
max_attempts:
type: integer
minimum: 1
maximum: 20
idempotency_key:
type: string
paths:
/createOnlineAgentTask:
post:
operationId: createOnlineAgentTask
x-openai-isConsequential: true
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOnlineAgentTaskRequest'
responses:
'200':
description: Online task created
'201':
description: Online task created
/registerOnlineAgent:
post:
operationId: registerOnlineAgent
x-openai-isConsequential: true
description: 'Control operation. The returned agent token is secret material and must be delivered
through runtime secret storage, never Git.
'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- agent_id
- agent_type
- agent_version
- capabilities
properties:
agent_id:
type: string
agent_type:
type: string
agent_version:
type: string
capabilities:
type: array
items:
type: string
metadata:
type: object
additionalProperties: true
responses:
'201':
description: Agent registered
/api/online-agent-task:
get:
operationId: getOnlineAgentTask
parameters:
- name: task_id
in: query
required: true
schema:
type: string
responses:
'200':
description: Task status
/api/online-agent-task-events:
get:
operationId: getOnlineAgentTaskEvents
parameters:
- name: task_id
in: query
required: true
schema:
type: string
responses:
'200':
description: Task events
/verifyOnlineAgentTask:
post:
operationId: verifyOnlineAgentTask
x-openai-isConsequential: true
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- task_id
- decision
properties:
task_id:
type: string
decision:
type: string
enum:
- SUCCEEDED
- NEEDS_REWORK
- FAILED
verification:
type: object
additionalProperties: true
responses:
'200':
description: Verification applied
/cancelOnlineAgentTask:
post:
operationId: cancelOnlineAgentTask
x-openai-isConsequential: true
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- task_id
properties:
task_id:
type: string
reason:
type: string
responses:
'200':
description: Task cancelled
x-aios-schema-reconciliation:
source_schema: docs/gitops/openapi-chatgpt-actions.yaml
public_runtime_schema: docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml
trust_domain: online-agent-task
operation_count: 6
public_action_import: true
@@ -1,881 +0,0 @@
openapi: 3.1.0
info:
title: AIOS ChatGPT Actions - Online GitOps Task
version: V1R1C0-chatgpt-actions-online-gitops-task
description: Trust-domain import from the exact union of the 31-operation main source and 30-operation
immutable public runtime; operation, server route, and declared security are preserved.
servers:
- url: https://cnnetmkt.top
security: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: opaque-token
schemas:
PublicationState:
type: string
description: Canonical durable publication state. Legacy TAG_CREATED_LOCAL is normalized on read
and is never emitted by new writes.
enum:
- PENDING
- LOCAL_TAG_CREATED
- REMOTE_PUSH_PENDING
- REMOTE_PUSH_CONFIRMED
- GITEA_API_CONFIRMED
- BASELINE_UPDATE_PENDING
- BASELINE_UPDATED
- PRODUCTION_DEPLOYED
- RECONCILIATION_REQUIRED
- MANUAL_OWNER_REVIEW_REQUIRED
PublicationStatus:
type: object
required:
- version
- state
properties:
version:
type: string
state:
$ref: '#/components/schemas/PublicationState'
fail_closed:
type: boolean
BranchRequest:
type: object
required:
- branch
properties:
branch:
type: string
example: patch/chatgpt-actions-demo
base:
type: string
default: main
message:
type: string
FileCommitRequest:
type: object
required:
- branch
- path
- content
properties:
branch:
type: string
base:
type: string
default: main
create_branch:
type: boolean
default: false
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:
branch:
type: string
paths:
type: array
items:
type: string
message:
type: string
PatchRequest:
type: object
required:
- patch_name
properties:
patch_name:
type: string
branch:
type: string
base:
type: string
default: main
risk:
type: string
enum:
- low
- medium
- high
description:
type: string
message:
type: string
TagRequest:
type: object
required:
- version
- target_oid
- evidence_closure_oid
- approval_plan_id
properties:
version:
type: string
example: V1R1C1
target_oid:
type: string
pattern: ^[0-9a-fA-F]{40}$
description: Full approved commit OID. The tag is created explicitly at this commit, never implicitly
at workspace HEAD.
evidence_closure_oid:
type: string
pattern: ^[0-9a-fA-F]{40}$
description: Required evidence closure commit. target_oid must be its ancestor.
approval_plan_id:
type: string
description: Audited owner-approved release or tag plan identifier.
message:
type: string
execute:
type: boolean
description: Owner-approved calls only. Otherwise an approval request commit is created.
RollbackRequest:
type: object
required:
- target_version
properties:
target_version:
type: string
reason:
type: string
branch:
type: string
ModelRequest:
type: object
required:
- provider_name
- base_url
- model_name
properties:
username:
type: string
provider_name:
type: string
base_url:
type: string
model_name:
type: string
display_name:
type: string
api_key_secret_ref:
type: string
description: Preferred. Git stores this secret_ref only.
api_key:
type: string
writeOnly: true
description: Accepted only for runtime secret storage; never committed to Git or logs.
branch:
type: string
message:
type: string
ModelPriorityRequest:
type: object
required:
- items
properties:
username:
type: string
branch:
type: string
items:
type: array
items:
type: object
properties:
model_id:
type: string
priority:
type: integer
enabled:
type: boolean
fallback_policy:
type: string
NLRequest:
type: object
required:
- text
properties:
text:
type: string
branch:
type: string
DeploymentPlan:
type: object
required:
- service
- release_path
- release_root
- cutover_link
- dropin_path
- dropin_sha256
- systemd_unit_sha256
- rollback_path
- rollback_sha256
- source_commit
- tree_oid
- artifact_sha256
- manifest_sha256
- package_closure_sha256
- authoritative_git_dir
- repository_identity
- writer_expected
- baseline_before_sha256
- registry_before_sha256
- production_tag_refset_before_sha256
- health_contract_version
- timeout_policy
- retry_policy
- policy_sha256
- health_contract
properties:
service:
type: string
release_path:
type: string
release_root:
type: string
cutover_link:
type: string
dropin_path:
type: string
dropin_sha256:
type: string
pattern: ^[0-9a-f]{64}$
systemd_unit_sha256:
type: string
pattern: ^[0-9a-f]{64}$
rollback_path:
type: string
rollback_sha256:
type: string
pattern: ^[0-9a-f]{64}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
tree_oid:
type: string
pattern: ^[0-9a-f]{40}$
artifact_sha256:
type: string
pattern: ^[0-9a-f]{64}$
manifest_sha256:
type: string
pattern: ^[0-9a-f]{64}$
package_closure_sha256:
type: string
pattern: ^[0-9a-f]{64}$
authoritative_git_dir:
type: string
repository_identity:
type: string
writer_expected:
type: boolean
enum:
- false
baseline_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
registry_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
production_tag_refset_before_sha256:
type: string
pattern: ^[0-9a-f]{64}$
health_contract_version:
type: string
timeout_policy:
type: object
retry_policy:
type: object
policy_sha256:
type: string
pattern: ^[0-9a-f]{64}$
health_contract:
type: object
additionalProperties: true
ReleaseCandidateInput:
type: object
required:
- source_commit
- version
additionalProperties: false
properties:
candidate_id:
type: string
pattern: ^[A-Za-z0-9][A-Za-z0-9_.-]{2,127}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
version:
type: string
pattern: ^V[0-9]+R[0-9]+C[0-9]+(?:[-.][A-Za-z0-9][A-Za-z0-9.-]*)?$
ReleaseIntentInput:
type: object
required:
- event_id
- source_commit
additionalProperties: false
properties:
event_id:
type: string
pattern: ^[A-Za-z0-9][A-Za-z0-9_.:-]{2,255}$
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
SignedReleasePlanApproval:
type: object
required:
- release_plan_id
- candidate_id
- source_commit
- tree_oid
- artifact_sha256
- manifest_sha256
- deployment_plan_sha256
- release_plan_sha256
- policy_sha256
- approval_plan_id
- evidence_closure_oid
- owner_approval_record_oid
- capabilities
- owner_identity
- trust_domain
- issued_at
- not_before
- expires_at
- nonce
- key_id
- signature
properties:
release_plan_id:
type: string
candidate_id:
type: string
source_commit:
type: string
pattern: ^[0-9a-f]{40}$
tree_oid:
type: string
pattern: ^[0-9a-f]{40}$
artifact_sha256:
type: string
pattern: ^[0-9a-f]{64}$
manifest_sha256:
type: string
pattern: ^[0-9a-f]{64}$
deployment_plan_sha256:
type: string
pattern: ^[0-9a-f]{64}$
release_plan_sha256:
type: string
pattern: ^[0-9a-f]{64}$
policy_sha256:
type: string
pattern: ^[0-9a-f]{64}$
approval_plan_id:
type: string
evidence_closure_oid:
type: string
pattern: ^[0-9a-f]{40}$
owner_approval_record_oid:
type: string
pattern: ^[0-9a-f]{40}$
owner_identity:
type: string
trust_domain:
type: string
issued_at:
type: string
format: date-time
not_before:
type: string
format: date-time
capabilities:
type: array
uniqueItems: true
items:
type: string
enum:
- runtime_switch
- tag_publish
- baseline_registry_finalize
expires_at:
type: string
format: date-time
nonce:
type: string
minLength: 16
key_id:
type: string
signature:
type: string
format: byte
writeOnly: true
StartDeploymentRequest:
type: object
required:
- candidate_id
additionalProperties: false
properties:
candidate_id:
type: string
Oid40:
type: string
pattern: ^[0-9a-f]{40}$
CreateGovernedTaskRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- base_oid
- target_branch
- risk
- description
- idempotency_key
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
base_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
risk:
type: string
enum:
- low
- medium
- high
- engineering
description:
type: string
idempotency_key:
type: string
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
generation:
type: integer
minimum: 1
WriterLeaseRequest:
type: object
additionalProperties: false
required:
- schema
- task_id
- repository
- branch_mode
- base_oid
- expected_branch_oid
- target_branch
- generation
- lease_seconds
properties:
schema:
type: string
task_id:
type: string
repository:
type: string
const: aios/aios
branch_mode:
type: string
enum:
- CREATE_NEW
- CONTINUE_EXISTING
base_oid:
$ref: '#/components/schemas/Oid40'
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
lease_seconds:
type: integer
minimum: 1
maximum: 86400
CommitFileGovernedRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- expected_branch_oid
- target_branch
- generation
- idempotency_key
- path
- content_base64
- message
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
idempotency_key:
type: string
path:
type: string
content_base64:
type: string
message:
type: string
CommitFilesGovernedRequest:
type: object
additionalProperties: false
required:
- task_id
- repository
- expected_branch_oid
- target_branch
- generation
- idempotency_key
- files
- message
properties:
task_id:
type: string
repository:
type: string
const: aios/aios
expected_branch_oid:
$ref: '#/components/schemas/Oid40'
target_branch:
type: string
pattern: ^agent/
generation:
type: integer
minimum: 1
idempotency_key:
type: string
files:
type: object
additionalProperties:
type: string
description: Base64 encoded file bytes
message:
type: string
CreateOnlineAgentTaskRequest:
type: object
additionalProperties: false
required:
- goal
- instructions
- success_criteria
- idempotency_key
properties:
task_id:
type: string
goal:
type: string
instructions:
type: string
success_criteria:
type: array
items: {}
required_capabilities:
type: array
items:
type: string
constraints:
type: object
additionalProperties: true
metadata:
type: object
additionalProperties: true
deadline:
type: string
format: date-time
priority:
type: integer
minimum: -100
maximum: 100
max_attempts:
type: integer
minimum: 1
maximum: 20
idempotency_key:
type: string
paths:
/api/base:
get:
operationId: getBaseline
summary: Read current AIOS baseline
responses:
'200':
description: OK
/api/ver:
get:
operationId: listVersions
summary: List GitOps versions
responses:
'200':
description: OK
/api/diff:
get:
operationId: getDiff
summary: Read Git diff between refs
parameters:
- in: query
name: from
schema:
type: string
default: HEAD~1
- in: query
name: to
schema:
type: string
default: HEAD
responses:
'200':
description: OK
/api/patch:
get:
operationId: listPatches
summary: List patch records
responses:
'200':
description: OK
post:
operationId: createPatch
summary: Create a patch branch and commit metadata
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchRequest'
responses:
'200':
description: Patch branch committed
'401':
description: Unauthorized
'403':
description: Forbidden
x-openai-isConsequential: true
/api/model:
get:
operationId: readModelRegistry
summary: Read visible model registry and priority
responses:
'200':
description: OK
post:
operationId: registerModel
summary: Register a custom model; API keys are stored as runtime secrets and Git receives secret_ref
only
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ModelRequest'
responses:
'200':
description: Model registered and committed
'401':
description: Unauthorized
'403':
description: Forbidden
x-openai-isConsequential: true
/api/run:
get:
operationId: getRuntimeStatus
summary: Read runtime status
responses:
'200':
description: OK
/api/branch:
post:
operationId: createBranch
summary: Create a non-main branch and commit branch metadata
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BranchRequest'
responses:
'200':
description: Branch created
'401':
description: Unauthorized
'403':
description: Forbidden
x-openai-isConsequential: true
/api/file:
post:
operationId: commitFile
summary: Write a file and create a Git commit on a non-main branch
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
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: null
expired: null
or revoked Token Policy V2 grant: null
'403':
description: Audience
source: null
branch: null
operation: null
path: null
or policy denied: null
'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
summary: Commit existing workspace changes on a non-main branch
security:
- bearerAuth: []
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CommitRequest'
responses:
'200':
description: Commit result
'401':
description: Unauthorized
x-openai-isConsequential: true
/api/model-priority:
put:
operationId: setModelPriority
summary: Set model priority and commit policy file
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ModelPriorityRequest'
responses:
'200':
description: Priority updated and committed
'401':
description: Unauthorized
x-openai-isConsequential: true
/api/nl:
post:
operationId: planNaturalLanguageGitOpsAction
summary: Convert natural language to a safe committed plan without executing V-level changes
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NLRequest'
responses:
'200':
description: Safe GitOps plan
'401':
description: Unauthorized
x-openai-isConsequential: true
x-aios-schema-reconciliation:
source_schema: docs/gitops/openapi-chatgpt-actions.yaml
public_runtime_schema: docs/gitops/openapi-chatgpt-actions-public-runtime-2e599646.yaml
trust_domain: online-gitops-task
operation_count: 14
public_action_import: true
File diff suppressed because it is too large Load Diff
+50
View File
@@ -567,3 +567,53 @@ paths:
'200': {description: Safe GitOps plan}
'401': {description: Unauthorized}
x-openai-isConsequential: true
/api/v2/governed-capabilities:
get:
operationId: getGovernedWriteCapabilities
responses: {'200': {description: Governed write capabilities with legacy writes disabled}}
/api/v2/governed-task:
post:
operationId: createGovernedTask
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [task_id, repository, base_oid, target_branch, risk, description, idempotency_key], properties: {task_id: {type: string}, repository: {type: string, const: aios/aios}, base_oid: {type: string, pattern: '^[0-9a-f]{40}$'}, target_branch: {type: string, pattern: '^agent/'}, risk: {type: string}, description: {type: string}, idempotency_key: {type: string}}}}}}
responses: {'200': {description: Exact governed task binding}}
x-openai-isConsequential: true
/api/v2/writer-lease:
post:
operationId: acquireWriterLease
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [schema, task_id, repository, branch_mode, base_oid, expected_branch_oid, target_branch, generation, lease_seconds], properties: {schema: {type: string}, task_id: {type: string}, repository: {type: string, const: aios/aios}, branch_mode: {type: string, enum: [CREATE_NEW, CONTINUE_EXISTING]}, base_oid: {type: string, pattern: '^[0-9a-f]{40}$'}, expected_branch_oid: {type: string, pattern: '^[0-9a-f]{40}$'}, target_branch: {type: string, pattern: '^agent/'}, generation: {type: integer, minimum: 1}, lease_seconds: {type: integer, minimum: 1, maximum: 86400}}}}}}
responses: {'200': {description: Detached CONTINUE_EXISTING lease}}
x-openai-isConsequential: true
/api/v2/commit-file:
post:
operationId: commitFileGoverned
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [task_id, repository, expected_branch_oid, target_branch, generation, idempotency_key, path, content_base64, message], properties: {task_id: {type: string}, repository: {type: string, const: aios/aios}, expected_branch_oid: {type: string, pattern: '^[0-9a-f]{40}$'}, target_branch: {type: string, pattern: '^agent/'}, generation: {type: integer, minimum: 1}, idempotency_key: {type: string}, path: {type: string}, content_base64: {type: string}, message: {type: string}}}}}}
responses: {'202': {description: Durable governed Job}}
x-openai-isConsequential: true
/api/v2/commit-files:
post:
operationId: commitFilesGoverned
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [task_id, repository, expected_branch_oid, target_branch, generation, idempotency_key, files, message], properties: {task_id: {type: string}, repository: {type: string, const: aios/aios}, expected_branch_oid: {type: string, pattern: '^[0-9a-f]{40}$'}, target_branch: {type: string, pattern: '^agent/'}, generation: {type: integer, minimum: 1}, idempotency_key: {type: string}, files: {type: object, additionalProperties: {type: string}}, message: {type: string}}}}}}
responses: {'202': {description: One atomic multi-file governed Job}}
x-openai-isConsequential: true
/api/v2/job:
post:
operationId: getGitOpsJob
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [job_id], properties: {job_id: {type: string}}}}}}
responses: {'200': {description: Non-sensitive Job metadata}}
/api/v2/job/resume:
post:
operationId: resumeGitOpsJob
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [job_id, expected_revision], properties: {job_id: {type: string}, expected_revision: {type: integer, minimum: 0}}}}}}
responses: {'202': {description: Revision-CAS resume}}
x-openai-isConsequential: true
/api/v2/job/reconcile:
post:
operationId: reconcileGitOpsJob
requestBody: {required: true, content: {application/json: {schema: {type: object, additionalProperties: false, required: [job_id, expected_revision], properties: {job_id: {type: string}, expected_revision: {type: integer, minimum: 0}}}}}}
responses: {'202': {description: Observation-first reconciliation}}
x-openai-isConsequential: true
/v2/control-plane-snapshot:
get:
operationId: getControlPlaneSnapshot
responses: {'200': {description: Non-sensitive control-plane snapshot}}
-4
View File
@@ -1,4 +0,0 @@
[pytest]
testpaths = tests
python_files = test_*.py
addopts = -ra --import-mode=importlib
@@ -1,243 +0,0 @@
{
"authority_proof": {
"branch_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"commit_visible": true,
"main_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"v2r2c1_tag_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad"
},
"baseline_authority": {
"artifact_sha256": "492338b895b152a55015fd92ea1d9dba2314894ab00c0ba219a78f3cef544b8a",
"authority_sha256": "d8e23bad49bdb3e4192ba708c3dfe7fc5b7cdc6a513c2f87acd6412a51867231",
"current_baseline": "V2R2C1",
"raw_byte_sidecar_verification": "PASS",
"target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad"
},
"control_plane_source_oid": "b781129bd5a8b53c05ab648361424d2800166ee4",
"diff_stat": "active-runtime/app/aios_authority_git_executor.py | 24 +\n active-runtime/app/aios_chatgpt_actions_api.py | 48 +-\n active-runtime/app/aios_chatgpt_bridge_v2.py | 167 ++++\n .../app/aios_chatgpt_bridge_v2_server.py | 431 +++++++++\n active-runtime/app/aios_continuation_executor.py | 594 ++++++++++++\n active-runtime/app/aios_continuation_lease.py | 6 +\n active-runtime/app/aios_control_plane_snapshot.py | 26 +\n active-runtime/app/aios_credential_broker.py | 78 ++\n active-runtime/app/aios_gitea_publisher.py | 93 ++\n active-runtime/app/aios_gitops_job_controller.py | 16 +-\n .../app/aios_gitops_reconciliation_core.py | 80 ++\n active-runtime/app/aios_governed_policy.py | 59 ++\n active-runtime/app/aios_governed_task_bootstrap.py | 84 ++\n active-runtime/app/aios_model_api_staging.py | 1022 ++++++++++++++++++++\n .../app/authorized_task_writer_provisioning.py | 4 +-\n active-runtime/app/baseline_authority.py | 84 ++\n active-runtime/app/governed_production_release.py | 568 +++++++++++\n active-runtime/app/v2r2c1_production_adapter.py | 135 +++\n .../systemd/aios-chatgpt-bridge-v2-staging.service | 23 +\n .../aios-gitops-model-api-v2r2c1-staging.service | 51 +\n ...09-bridge-v2.1-durable-reconciliation-design.md | 15 +\n ...t-bridge-v2-control-plane-convergence-design.md | 150 +++\n pytest.ini | 4 +\n scripts/build_v2r2c1_model_api_staging.py | 145 +++\n .../aios_release_controller/manifest.py | 4 +-\n .../test_v2r1c6_release_consistency.py | 4 +-\n .../aios_v2_candidate/test_v2r1c6_release_ready.py | 16 +-\n tests/conftest.py | 65 ++\n tests/test_bridge_v2_governed_http_bootstrap.py | 90 ++\n tests/test_governed_local_writer.py | 6 +-\n tests/test_model_api_immutable_staging.py | 35 +\n 31 files changed, 4108 insertions(+), 19 deletions(-)",
"evidence_closure_oid": "a8b906d1bc24088c19647e98de6a679268f6d0a2",
"forbidden_operations": [
"direct_main_push",
"main_merge_without_owner_approval",
"force_push",
"tag_mutation",
"baseline_mutation",
"registry_mutation",
"production_restart",
"production_cutover",
"live_model_api_cutover",
"history_rewrite",
"secret_commit"
],
"governance": {
"baseline_modified": false,
"direct_main_push": false,
"force_push_used": false,
"history_rewritten": false,
"live_model_api_cutover": false,
"main_merged": false,
"owner_approval_respected": true,
"production_changed": false,
"production_restarted": false,
"registry_modified": false,
"secrets_committed": false,
"tag_rewritten": false
},
"included_path_count": 31,
"integration_branch": "agent/v2r2c1-post-release-mainline-convergence-20260809",
"integration_head_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"logical_commits": [
{
"message": "feat(v2r2c1): converge durable control-plane core",
"oid": "40b685d1c70c767c7a79a2b184348e58e3e319ae",
"parent_oid": "2e8fa22989808a448065d1d76b5b18948774a637"
},
{
"message": "docs(v2r2c1): converge durable runtime and design sources",
"oid": "5f616311bab38b0dac296ed8b0e69660e031a20e",
"parent_oid": "40b685d1c70c767c7a79a2b184348e58e3e319ae"
},
{
"message": "feat(v2r2c1): integrate governed release overlay",
"oid": "57780e316e320a5128cc2c9f12adbb19ae57aef5",
"parent_oid": "5f616311bab38b0dac296ed8b0e69660e031a20e"
},
{
"message": "feat(v2r2c1): wire governed release operations into durable bridge",
"oid": "e41b8d323a3e7a40440f5d32221f524074bea5fe",
"parent_oid": "57780e316e320a5128cc2c9f12adbb19ae57aef5"
},
{
"message": "test: repair canonical pytest repository entrypoint",
"oid": "b20cb8130e4c68267d5d85b02eed51cb8d4f41c0",
"parent_oid": "e41b8d323a3e7a40440f5d32221f524074bea5fe"
},
{
"message": "test: make whole-suite collection deterministic",
"oid": "c6a1693efaede9dace9b929d884a09e162a02c89",
"parent_oid": "b20cb8130e4c68267d5d85b02eed51cb8d4f41c0"
},
{
"message": "test: preserve legacy suite imports under canonical collection",
"oid": "91f2ea0591787d3dbf8c2e27ab0460629d86900e",
"parent_oid": "c6a1693efaede9dace9b929d884a09e162a02c89"
},
{
"message": "test: expose repository test helpers to canonical collection",
"oid": "85897d3f6d708271dff16767265f9d14b2f29801",
"parent_oid": "91f2ea0591787d3dbf8c2e27ab0460629d86900e"
},
{
"message": "fix(v2r2c1): close slash-branch and suite contract regressions",
"oid": "f1110d24f30d8441f2df04e0774ee230b95c2e02",
"parent_oid": "85897d3f6d708271dff16767265f9d14b2f29801"
},
{
"message": "test: align writer regression with durable idempotent replay",
"oid": "c10d2a5dfcc394dde7a7022952d7b423725747a3",
"parent_oid": "f1110d24f30d8441f2df04e0774ee230b95c2e02"
},
{
"message": "feat(v2r2c1): source baseline authority for model-api staging",
"oid": "f969aedaf61501a866435c712be01ff2cfe43fb1",
"parent_oid": "c10d2a5dfcc394dde7a7022952d7b423725747a3"
},
{
"message": "feat(v2r2c1): add immutable model api staging runtime",
"oid": "4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b",
"parent_oid": "f969aedaf61501a866435c712be01ff2cfe43fb1"
},
{
"message": "fix(v2r2c1): avoid builder secret-scan false positives",
"oid": "7c4e86bfc1f39e643e672968d1fdedbd72ace56d",
"parent_oid": "4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b"
},
{
"message": "fix(v2r2c1): isolate model api staging port",
"oid": "7564363a30bfa7fa81ac5c7c545ec704984ec543",
"parent_oid": "7c4e86bfc1f39e643e672968d1fdedbd72ace56d"
},
{
"message": "fix(v2r2c1): bind baseline authority and openapi staging path",
"oid": "2c6293160ed567a2098715edbb296741577c5bff",
"parent_oid": "7564363a30bfa7fa81ac5c7c545ec704984ec543"
}
],
"main_base_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"mandatory_gates": {
"baseline_registry_readback_staging_pass": true,
"durable_source_path_manifest_complete": true,
"existing_v2r2c1_suite_pass": true,
"governed_release_suite_pass": true,
"integration_authority_git_api_equal": true,
"integration_branch_governed": true,
"logical_slice_commits_remote_verified": true,
"main_base_exact_before_branch_create": true,
"model_api_immutable_runtime_staging_pass": true,
"owner_merge_request_generated_execute_false": true,
"production_unchanged": true,
"pytest_collection_entrypoints_fixed": true,
"pytest_tests_results_recorded": true
},
"model_api_staging": {
"artifact_sha256": "492338b895b152a55015fd92ea1d9dba2314894ab00c0ba219a78f3cef544b8a",
"baseline": {
"authority_sha256": "d8e23bad49bdb3e4192ba708c3dfe7fc5b7cdc6a513c2f87acd6412a51867231",
"current_baseline": "V2R2C1",
"deployment_state": "ACTIVE",
"evidence_closure_oid": "a8b906d1bc24088c19647e98de6a679268f6d0a2",
"generation": 4,
"previous_baseline": "V2R1C7",
"production_deployed": true,
"status": "PRODUCTION_DEPLOYED",
"tag_oid": "07fc2746b688f5f243f29b39de39f32edc3dd9d2",
"target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad"
},
"baseline_status": 200,
"deployment_state": "STAGING",
"health": {
"artifact_sha256": "492338b895b152a55015fd92ea1d9dba2314894ab00c0ba219a78f3cef544b8a",
"commit_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"deployment_state": "STAGING",
"governed_release_routing": "bridge-v2",
"legacy_global_writes_enabled": false,
"production_deployed": false,
"runtime_mode": "IMMUTABLE_STAGING",
"status": "ok",
"version": "V2R2C1"
},
"health_status": 200,
"legacy_write_probe": "423_BLOCKED",
"port": 18893,
"restart_acceptance": "PASS",
"runtime_root": "/opt/aios/gitops-model-api/2c6293160ed567a2098715edbb296741577c5bff/runtime",
"source_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"systemd": "MainPID=788782\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /opt/aios/gitops-model-api/2c6293160ed567a2098715edbb296741577c5bff/runtime/app/aios_model_api_staging.py ; ignore_errors=no ; start_time=[Sun 2026-08-09 19:11:19 CST] ; stop_time=[n/a] ; pid=788782 ; code=(null) ; status=0/0 }\nActiveState=active\nSubState=running",
"unit": "aios-gitops-model-api-v2r2c1-staging.service",
"versions": {
"authoritative_head_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"baseline_generation": 4,
"baseline_sha256": "d8e23bad49bdb3e4192ba708c3dfe7fc5b7cdc6a513c2f87acd6412a51867231",
"baseline_version": "V2R2C1",
"query_error": null
},
"versions_status": 200
},
"owner_merge_request": {
"control_plane_source_oid": "b781129bd5a8b53c05ab648361424d2800166ee4",
"execute": false,
"integration_head_oid": "b2cf510e11b712bb99f20ded81459b6524257394",
"main_expected_old_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"release_target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad",
"report_commit_oid": "b2cf510e11b712bb99f20ded81459b6524257394",
"status": "OWNER_APPROVAL_REQUIRED"
},
"placeholder_fields": [],
"production": {
"baseline_mutation": false,
"health": {
"artifact_sha256": "ab4ae257346c82863f05abf5e309381a1c86612957608c3a4f4ab5cc9233f052",
"commit_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad",
"deployment_state": "ACTIVE",
"health_timestamp": "2026-08-09T11:21:16.872581+00:00",
"production_deployed": true,
"status": "ok",
"version": "V2R2C1"
},
"health_status": 200,
"live_model_api_show": "MainPID=2816107\nActiveState=active\nSubState=running",
"live_model_api_unchanged": true,
"production_cutover": false,
"production_restart": false,
"registry_mutation": false,
"shadow_service_unchanged": true,
"shadow_show": "MainPID=1505658\nActiveState=active\nSubState=running",
"tag_mutation": false
},
"release_target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad",
"remote_proof": {
"api_branch_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"api_verification": "paginated_exact_name",
"commit_visible": true,
"git_remote_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"main_api_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"main_git_oid": "2e8fa22989808a448065d1d76b5b18948774a637"
},
"report_commit_parent_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"repository": "aios/aios",
"schema": "aios.v2r2c1.post-release-mainline-convergence.acceptance.v1",
"status": "V2R2C1_MAINLINE_CONVERGENCE_READY_FOR_OWNER_MERGE",
"success_status": "V2R2C1_MAINLINE_CONVERGENCE_READY_FOR_OWNER_MERGE",
"task_id": "TASK-P0-V2R2C1-POST-RELEASE-MAINLINE-CONVERGENCE-20260809",
"tests": {
"collection": "PASS",
"command": "pytest tests",
"failed": 0,
"passed": 709,
"skipped": 2,
"skipped_tests": [
"tests/test_gitea_tag_publication_live.py (live opt-in)",
"tests/test_signer_contract_compatibility.py (live integration opt-in)"
],
"subtests": 154
}
}
@@ -1,89 +0,0 @@
# V2R2C1 post-release mainline convergence diff summary
- task: `TASK-P0-V2R2C1-POST-RELEASE-MAINLINE-CONVERGENCE-20260809`
- repository: `aios/aios`
- main base: `2e8fa22989808a448065d1d76b5b18948774a637`
- release target: `998d30304787e31e5ae607c0bd86b5edb2b0e5ad`
- control-plane source: `b781129bd5a8b53c05ab648361424d2800166ee4`
- implementation integration head before this report commit: `2c6293160ed567a2098715edbb296741577c5bff`
- branch: `agent/v2r2c1-post-release-mainline-convergence-20260809`
## Logical governed commits
| OID | Parent | Message |
|---|---|---|
| `40b685d1c70c767c7a79a2b184348e58e3e319ae` | `2e8fa22989808a448065d1d76b5b18948774a637` | feat(v2r2c1): converge durable control-plane core |
| `5f616311bab38b0dac296ed8b0e69660e031a20e` | `40b685d1c70c767c7a79a2b184348e58e3e319ae` | docs(v2r2c1): converge durable runtime and design sources |
| `57780e316e320a5128cc2c9f12adbb19ae57aef5` | `5f616311bab38b0dac296ed8b0e69660e031a20e` | feat(v2r2c1): integrate governed release overlay |
| `e41b8d323a3e7a40440f5d32221f524074bea5fe` | `57780e316e320a5128cc2c9f12adbb19ae57aef5` | feat(v2r2c1): wire governed release operations into durable bridge |
| `b20cb8130e4c68267d5d85b02eed51cb8d4f41c0` | `e41b8d323a3e7a40440f5d32221f524074bea5fe` | test: repair canonical pytest repository entrypoint |
| `c6a1693efaede9dace9b929d884a09e162a02c89` | `b20cb8130e4c68267d5d85b02eed51cb8d4f41c0` | test: make whole-suite collection deterministic |
| `91f2ea0591787d3dbf8c2e27ab0460629d86900e` | `c6a1693efaede9dace9b929d884a09e162a02c89` | test: preserve legacy suite imports under canonical collection |
| `85897d3f6d708271dff16767265f9d14b2f29801` | `91f2ea0591787d3dbf8c2e27ab0460629d86900e` | test: expose repository test helpers to canonical collection |
| `f1110d24f30d8441f2df04e0774ee230b95c2e02` | `85897d3f6d708271dff16767265f9d14b2f29801` | fix(v2r2c1): close slash-branch and suite contract regressions |
| `c10d2a5dfcc394dde7a7022952d7b423725747a3` | `f1110d24f30d8441f2df04e0774ee230b95c2e02` | test: align writer regression with durable idempotent replay |
| `f969aedaf61501a866435c712be01ff2cfe43fb1` | `c10d2a5dfcc394dde7a7022952d7b423725747a3` | feat(v2r2c1): source baseline authority for model-api staging |
| `4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b` | `f969aedaf61501a866435c712be01ff2cfe43fb1` | feat(v2r2c1): add immutable model api staging runtime |
| `7c4e86bfc1f39e643e672968d1fdedbd72ace56d` | `4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b` | fix(v2r2c1): avoid builder secret-scan false positives |
| `7564363a30bfa7fa81ac5c7c545ec704984ec543` | `7c4e86bfc1f39e643e672968d1fdedbd72ace56d` | fix(v2r2c1): isolate model api staging port |
| `2c6293160ed567a2098715edbb296741577c5bff` | `7564363a30bfa7fa81ac5c7c545ec704984ec543` | fix(v2r2c1): bind baseline authority and openapi staging path |
## Exact diff stat
```text
active-runtime/app/aios_authority_git_executor.py | 24 +
active-runtime/app/aios_chatgpt_actions_api.py | 48 +-
active-runtime/app/aios_chatgpt_bridge_v2.py | 167 ++++
.../app/aios_chatgpt_bridge_v2_server.py | 431 +++++++++
active-runtime/app/aios_continuation_executor.py | 594 ++++++++++++
active-runtime/app/aios_continuation_lease.py | 6 +
active-runtime/app/aios_control_plane_snapshot.py | 26 +
active-runtime/app/aios_credential_broker.py | 78 ++
active-runtime/app/aios_gitea_publisher.py | 93 ++
active-runtime/app/aios_gitops_job_controller.py | 16 +-
.../app/aios_gitops_reconciliation_core.py | 80 ++
active-runtime/app/aios_governed_policy.py | 59 ++
active-runtime/app/aios_governed_task_bootstrap.py | 84 ++
active-runtime/app/aios_model_api_staging.py | 1022 ++++++++++++++++++++
.../app/authorized_task_writer_provisioning.py | 4 +-
active-runtime/app/baseline_authority.py | 84 ++
active-runtime/app/governed_production_release.py | 568 +++++++++++
active-runtime/app/v2r2c1_production_adapter.py | 135 +++
.../systemd/aios-chatgpt-bridge-v2-staging.service | 23 +
.../aios-gitops-model-api-v2r2c1-staging.service | 51 +
...09-bridge-v2.1-durable-reconciliation-design.md | 15 +
...t-bridge-v2-control-plane-convergence-design.md | 150 +++
pytest.ini | 4 +
scripts/build_v2r2c1_model_api_staging.py | 145 +++
.../aios_release_controller/manifest.py | 4 +-
.../test_v2r1c6_release_consistency.py | 4 +-
.../aios_v2_candidate/test_v2r1c6_release_ready.py | 16 +-
tests/conftest.py | 65 ++
tests/test_bridge_v2_governed_http_bootstrap.py | 90 ++
tests/test_governed_local_writer.py | 6 +-
tests/test_model_api_immutable_staging.py | 35 +
31 files changed, 4108 insertions(+), 19 deletions(-)
```
## Included durable source domains
- Bridge v2 adapter/server and governed HTTP contracts.
- Durable reconciliation core, continuation executor/lease, Authority Git CAS adapter, job controller compatibility.
- Gitea publisher/verifier, credential broker, governed policy, control-plane snapshot, release routing.
- Canonical pytest entrypoint/conftest and regression coverage.
- Source-controlled immutable model-api staging runtime, builder and systemd template.
- Selected design specifications required for durable mainline context.
## Explicitly excluded
- `main` ref mutation or merge without Owner approval.
- Production service, Registry, Baseline body/sidecar, production tags and mutable `/var/lib` state.
- Installed `/opt` artifacts, temporary staging transition state and task-local receipts/credentials.
- Production cutover/restart, force push, history rewrite and plaintext secrets.
## Verification
- `pytest tests`: **709 passed, 2 skipped, 154 subtests, 0 failed**.
- Staging model-api: immutable OID/digest bound, port 18893, health/base/ver/OpenAPI readback PASS, restart recovery PASS.
- Authority/Gitea Git/Gitea API commit equality and commit visibility PASS.
- Production remains V2R2C1 and was not restarted or cut over.
@@ -1,254 +0,0 @@
{
"control_plane_source_oid": "b781129bd5a8b53c05ab648361424d2800166ee4",
"diff_stat": "active-runtime/app/aios_authority_git_executor.py | 24 +\n active-runtime/app/aios_chatgpt_actions_api.py | 48 +-\n active-runtime/app/aios_chatgpt_bridge_v2.py | 167 ++++\n .../app/aios_chatgpt_bridge_v2_server.py | 431 +++++++++\n active-runtime/app/aios_continuation_executor.py | 594 ++++++++++++\n active-runtime/app/aios_continuation_lease.py | 6 +\n active-runtime/app/aios_control_plane_snapshot.py | 26 +\n active-runtime/app/aios_credential_broker.py | 78 ++\n active-runtime/app/aios_gitea_publisher.py | 93 ++\n active-runtime/app/aios_gitops_job_controller.py | 16 +-\n .../app/aios_gitops_reconciliation_core.py | 80 ++\n active-runtime/app/aios_governed_policy.py | 59 ++\n active-runtime/app/aios_governed_task_bootstrap.py | 84 ++\n active-runtime/app/aios_model_api_staging.py | 1022 ++++++++++++++++++++\n .../app/authorized_task_writer_provisioning.py | 4 +-\n active-runtime/app/baseline_authority.py | 84 ++\n active-runtime/app/governed_production_release.py | 568 +++++++++++\n active-runtime/app/v2r2c1_production_adapter.py | 135 +++\n .../systemd/aios-chatgpt-bridge-v2-staging.service | 23 +\n .../aios-gitops-model-api-v2r2c1-staging.service | 51 +\n ...09-bridge-v2.1-durable-reconciliation-design.md | 15 +\n ...t-bridge-v2-control-plane-convergence-design.md | 150 +++\n pytest.ini | 4 +\n scripts/build_v2r2c1_model_api_staging.py | 145 +++\n .../aios_release_controller/manifest.py | 4 +-\n .../test_v2r1c6_release_consistency.py | 4 +-\n .../aios_v2_candidate/test_v2r1c6_release_ready.py | 16 +-\n tests/conftest.py | 65 ++\n tests/test_bridge_v2_governed_http_bootstrap.py | 90 ++\n tests/test_governed_local_writer.py | 6 +-\n tests/test_model_api_immutable_staging.py | 35 +\n 31 files changed, 4108 insertions(+), 19 deletions(-)",
"evidence_closure_oid": "a8b906d1bc24088c19647e98de6a679268f6d0a2",
"excluded_paths": [
{
"path": "refs/heads/main",
"reason": "main merge requires separate Owner approval; unchanged"
},
{
"path": "refs/tags/*",
"reason": "formal tags are outside engineering convergence scope; unchanged"
},
{
"path": "baseline/current.json and sidecar",
"reason": "production mutable authority and sidecar; read-only verified"
},
{
"path": "/var/lib/aios-gitops/**",
"reason": "host runtime state and receipts excluded from repository source"
},
{
"path": "/opt/aios/**",
"reason": "installed immutable staging artifacts excluded; digest recorded in reports"
},
{
"path": "credentials and secrets",
"reason": "availability-only; no plaintext credential committed"
},
{
"path": "production runtime and Registry",
"reason": "production cutover/registry mutation forbidden"
}
],
"included_paths": [
{
"path": "active-runtime/app/aios_authority_git_executor.py",
"status": "M"
},
{
"path": "active-runtime/app/aios_chatgpt_actions_api.py",
"status": "M"
},
{
"path": "active-runtime/app/aios_chatgpt_bridge_v2.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_chatgpt_bridge_v2_server.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_continuation_executor.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_continuation_lease.py",
"status": "M"
},
{
"path": "active-runtime/app/aios_control_plane_snapshot.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_credential_broker.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_gitea_publisher.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_gitops_job_controller.py",
"status": "M"
},
{
"path": "active-runtime/app/aios_gitops_reconciliation_core.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_governed_policy.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_governed_task_bootstrap.py",
"status": "A"
},
{
"path": "active-runtime/app/aios_model_api_staging.py",
"status": "A"
},
{
"path": "active-runtime/app/authorized_task_writer_provisioning.py",
"status": "M"
},
{
"path": "active-runtime/app/baseline_authority.py",
"status": "A"
},
{
"path": "active-runtime/app/governed_production_release.py",
"status": "A"
},
{
"path": "active-runtime/app/v2r2c1_production_adapter.py",
"status": "A"
},
{
"path": "deploy/systemd/aios-chatgpt-bridge-v2-staging.service",
"status": "A"
},
{
"path": "deploy/systemd/aios-gitops-model-api-v2r2c1-staging.service",
"status": "A"
},
{
"path": "docs/superpowers/specs/2026-08-09-bridge-v2.1-durable-reconciliation-design.md",
"status": "A"
},
{
"path": "docs/superpowers/specs/2026-08-09-chatgpt-bridge-v2-control-plane-convergence-design.md",
"status": "A"
},
{
"path": "pytest.ini",
"status": "A"
},
{
"path": "scripts/build_v2r2c1_model_api_staging.py",
"status": "A"
},
{
"path": "services/aios-release-controller/aios_release_controller/manifest.py",
"status": "M"
},
{
"path": "tests/aios_v2_candidate/test_v2r1c6_release_consistency.py",
"status": "M"
},
{
"path": "tests/aios_v2_candidate/test_v2r1c6_release_ready.py",
"status": "M"
},
{
"path": "tests/conftest.py",
"status": "A"
},
{
"path": "tests/test_bridge_v2_governed_http_bootstrap.py",
"status": "A"
},
{
"path": "tests/test_governed_local_writer.py",
"status": "M"
},
{
"path": "tests/test_model_api_immutable_staging.py",
"status": "A"
}
],
"integration_branch": "agent/v2r2c1-post-release-mainline-convergence-20260809",
"integration_head_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"logical_commits": [
{
"message": "feat(v2r2c1): converge durable control-plane core",
"oid": "40b685d1c70c767c7a79a2b184348e58e3e319ae",
"parent_oid": "2e8fa22989808a448065d1d76b5b18948774a637"
},
{
"message": "docs(v2r2c1): converge durable runtime and design sources",
"oid": "5f616311bab38b0dac296ed8b0e69660e031a20e",
"parent_oid": "40b685d1c70c767c7a79a2b184348e58e3e319ae"
},
{
"message": "feat(v2r2c1): integrate governed release overlay",
"oid": "57780e316e320a5128cc2c9f12adbb19ae57aef5",
"parent_oid": "5f616311bab38b0dac296ed8b0e69660e031a20e"
},
{
"message": "feat(v2r2c1): wire governed release operations into durable bridge",
"oid": "e41b8d323a3e7a40440f5d32221f524074bea5fe",
"parent_oid": "57780e316e320a5128cc2c9f12adbb19ae57aef5"
},
{
"message": "test: repair canonical pytest repository entrypoint",
"oid": "b20cb8130e4c68267d5d85b02eed51cb8d4f41c0",
"parent_oid": "e41b8d323a3e7a40440f5d32221f524074bea5fe"
},
{
"message": "test: make whole-suite collection deterministic",
"oid": "c6a1693efaede9dace9b929d884a09e162a02c89",
"parent_oid": "b20cb8130e4c68267d5d85b02eed51cb8d4f41c0"
},
{
"message": "test: preserve legacy suite imports under canonical collection",
"oid": "91f2ea0591787d3dbf8c2e27ab0460629d86900e",
"parent_oid": "c6a1693efaede9dace9b929d884a09e162a02c89"
},
{
"message": "test: expose repository test helpers to canonical collection",
"oid": "85897d3f6d708271dff16767265f9d14b2f29801",
"parent_oid": "91f2ea0591787d3dbf8c2e27ab0460629d86900e"
},
{
"message": "fix(v2r2c1): close slash-branch and suite contract regressions",
"oid": "f1110d24f30d8441f2df04e0774ee230b95c2e02",
"parent_oid": "85897d3f6d708271dff16767265f9d14b2f29801"
},
{
"message": "test: align writer regression with durable idempotent replay",
"oid": "c10d2a5dfcc394dde7a7022952d7b423725747a3",
"parent_oid": "f1110d24f30d8441f2df04e0774ee230b95c2e02"
},
{
"message": "feat(v2r2c1): source baseline authority for model-api staging",
"oid": "f969aedaf61501a866435c712be01ff2cfe43fb1",
"parent_oid": "c10d2a5dfcc394dde7a7022952d7b423725747a3"
},
{
"message": "feat(v2r2c1): add immutable model api staging runtime",
"oid": "4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b",
"parent_oid": "f969aedaf61501a866435c712be01ff2cfe43fb1"
},
{
"message": "fix(v2r2c1): avoid builder secret-scan false positives",
"oid": "7c4e86bfc1f39e643e672968d1fdedbd72ace56d",
"parent_oid": "4ab70bfdb4d34aa9d1dabc4230a3367eaa93cc9b"
},
{
"message": "fix(v2r2c1): isolate model api staging port",
"oid": "7564363a30bfa7fa81ac5c7c545ec704984ec543",
"parent_oid": "7c4e86bfc1f39e643e672968d1fdedbd72ace56d"
},
{
"message": "fix(v2r2c1): bind baseline authority and openapi staging path",
"oid": "2c6293160ed567a2098715edbb296741577c5bff",
"parent_oid": "7564363a30bfa7fa81ac5c7c545ec704984ec543"
}
],
"main_base_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"release_target_oid": "998d30304787e31e5ae607c0bd86b5edb2b0e5ad",
"remote_proof": {
"api_branch_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"api_verification": "paginated_exact_name",
"commit_visible": true,
"git_remote_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"main_api_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"main_git_oid": "2e8fa22989808a448065d1d76b5b18948774a637"
},
"report_commit_parent_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"repository": "aios/aios",
"schema": "aios.v2r2c1.post-release-mainline-convergence.path-manifest.v1",
"task_id": "TASK-P0-V2R2C1-POST-RELEASE-MAINLINE-CONVERGENCE-20260809"
}
@@ -1,37 +0,0 @@
{
"artifact_sha256": "492338b895b152a55015fd92ea1d9dba2314894ab00c0ba219a78f3cef544b8a",
"baseline_authority_path": "/var/lib/aios-gitops-runtime-anchor/baseline/current.json",
"checks": {
"artifact_sha256": "PASS",
"baseline_registry_readback": "PASS",
"health_contract": "PASS",
"legacy_write_rejection": "PASS",
"live_service_unchanged": "PASS",
"manifest_binding": "PASS",
"openapi_readback": "PASS",
"restart_recovery": "PASS"
},
"current_live_port": 18890,
"current_live_service": "aios-gitops-model-api.service",
"deployment_state": "STAGING",
"execute": false,
"governed_release_routing": "bridge-v2",
"legacy_global_writes_enabled": false,
"live_cutover": false,
"owner_actions_required": [
"review exact source OID and artifact SHA",
"approve a separate future live model-api cutover",
"approve any production service transition"
],
"production_restart": false,
"repository_identity": "aios/aios",
"runtime_mode": "IMMUTABLE_STAGING",
"schema": "aios.v2r2c1.model-api-runtime-activation-plan.v1",
"source_oid": "2c6293160ed567a2098715edbb296741577c5bff",
"staging_port": 18893,
"staging_runtime_root": "/opt/aios/gitops-model-api/2c6293160ed567a2098715edbb296741577c5bff/runtime",
"staging_service": "aios-gitops-model-api-v2r2c1-staging.service",
"status": "OWNER_APPROVAL_REQUIRED",
"target_version": "V2R2C1",
"task_id": "TASK-P0-V2R2C1-POST-RELEASE-MAINLINE-CONVERGENCE-20260809"
}
@@ -0,0 +1,44 @@
{
"schema": "aios.bridge-v2-engineering-staging-acceptance.v1",
"task_id": "TASK-P0-CHATGPT-BRIDGE-V2-CONTROL-PLANE-CONVERGENCE-20260809",
"repository": "aios/aios",
"branch": "agent/p0-chatgpt-bridge-v2-control-plane-convergence-20260809",
"control_plane_release_version": "bridge-v2-aa0c37b8ab33",
"control_plane_target_oid": "aa0c37b8ab333616e1bab9686cf6d10557f2ebda",
"artifact_sha256": "08670c78cf760bfe693e3553e676eb751dadd7834116aa6d40e7c094f1357ae4",
"runtime_path": "/opt/aios/gitops-control-plane/aa0c37b8ab333616e1bab9686cf6d10557f2ebda",
"bridge_schema_version": "aios.chatgpt-gitops-bridge.v2",
"deployment_state": "STAGING",
"drift_status": "PASS",
"restart_acceptance": {
"pid_before": 3158850,
"pid_after": 3159889,
"runtime_response_equal": true
},
"governed_capabilities": {
"legacy_writes_enabled": false,
"governed_writes_enabled": true,
"force_push": false,
"main_write": false,
"tag_write": false,
"baseline_write": false,
"production_write": false
},
"production_invariants": {
"authority_main_oid": "2e8fa22989808a448065d1d76b5b18948774a637",
"authority_tags_sha256": "bd2b6e30b76f28e7fcdcb447e7296690f0a65ad855209294c36b0f3f1d96098d",
"baseline_current_sha256": "57651eb819584ab7c1d67f01b0ef66d6408cdc322ae5f6d4ff0aacd96f8327e1",
"production_service_main_pid": 2816107,
"production_service_nrestarts": 0,
"production_service_active_enter_timestamp_monotonic": 2919386492273
},
"bridge_operation_sequence": {
"createGovernedTask": "PASS",
"acquireWriterLease": "PASS",
"commitFilesGoverned": "REAL_GOVERNED_COMMIT",
"getGitOpsJob": "PASS",
"expected_branch_oid": "8fe3b85c1be592326473e81a502a23eeb9511d30",
"generation": 7
},
"production_changed": false
}
@@ -0,0 +1,17 @@
{
"schema": "aios.bridge-v2.1-durable-reconciliation.bootstrap-acceptance.v1",
"task_id": "TASK-P0-BRIDGE-V21-DURABLE-RECONCILIATION-20260809",
"repository": "aios/aios",
"base_oid": "3f670c387692b8865a10d5b419468d8a0b64d7a4",
"target_branch": "agent/p0-bridge-v21-durable-reconciliation-20260809",
"branch_mode": "CREATE_NEW",
"generation": 1,
"implementation": "not_started",
"production_changed": false,
"required_proofs": [
"absent_ref_cas",
"observation_first_reconciliation",
"authority_gitea_api_commit_equality",
"commit_visible"
]
}
-145
View File
@@ -1,145 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path
import tarfile
import tempfile
SCHEMA = 'aios.v2r2c1.model-api-staging-manifest.v1'
REQUIRED_APP = (
'aios_model_api_staging.py',
'aios_gitops_write_guard.py',
'authoritative_git.py',
'baseline_authority.py',
'gitea_tag_publication.py',
'silent_release_controller.py',
'silent_release_hardening.py',
'aios_gitops_job_controller.py',
)
OPTIONAL_APP = (
'aios_chatgpt_actions_api.py',
'aios_continuation_executor.py',
'aios_continuation_lease.py',
'aios_control_plane_snapshot.py',
)
def sha256(path: Path) -> str:
h = hashlib.sha256()
with path.open('rb') as fh:
for chunk in iter(lambda: fh.read(1024 * 1024), b''):
h.update(chunk)
return h.hexdigest()
def private_marker(path: Path) -> bool:
import re
text = path.read_text(encoding='utf-8', errors='ignore')
patterns = (
r'-----BEGIN [A-Z ]*PRIVATE KEY-----',
r'(?<![A-Za-z0-9])sk-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])',
r'(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{20,}(?![A-Za-z0-9])',
r'(?i)aws_secret_access_key\s*[:=]\s*[A-Za-z0-9/+=]{16,}',
)
return any(re.search(pattern, text) for pattern in patterns)
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument('--source-root', required=True, type=Path)
ap.add_argument('--output-root', required=True, type=Path)
ap.add_argument('--source-oid', required=True)
args = ap.parse_args()
oid = args.source_oid.lower()
if len(oid) != 40 or any(c not in '0123456789abcdef' for c in oid):
raise SystemExit('source oid must be exact 40 hex')
source = args.source_root.resolve(strict=True)
output = args.output_root.resolve()
app = source / 'active-runtime' / 'app'
runtime = source / 'runtime' / 'agent-os'
docs = source / 'docs' / 'gitops'
if not app.is_dir():
raise SystemExit('active-runtime/app missing')
paths = []
for name in REQUIRED_APP:
path = app / name
if not path.is_file():
raise SystemExit(f'required app dependency missing: {name}')
paths.append((Path('app') / name, path))
for name in OPTIONAL_APP:
path = app / name
if path.is_file():
paths.append((Path('app') / name, path))
for rel in ('orchestrator/__init__.py', 'orchestrator/action_monitor.py'):
path = runtime / rel
if not path.is_file():
raise SystemExit(f'required runtime dependency missing: {rel}')
paths.append((Path('runtime-agent-os') / rel, path))
openapi = docs / 'openapi-chatgpt-actions.yaml'
if openapi.is_file():
paths.append((Path('docs') / 'gitops' / 'openapi-chatgpt-actions.yaml', openapi))
for folder in ('config/model_registry', 'config/model_priority', 'patches', 'versions'):
root = source / folder
if root.is_dir():
for path in sorted(root.rglob('*')):
if path.is_file() and path.suffix.lower() in {'.json', '.yaml', '.yml', '.md'}:
paths.append((Path(folder) / path.relative_to(root), path))
for rel, path in paths:
if private_marker(path):
raise SystemExit(f'private marker rejected: {rel}')
included = [str(rel).replace('\\', '/') for rel, _ in paths]
manifest = {
'schema': SCHEMA,
'target_version': 'V2R2C1',
'source_oid': oid,
'repository_identity': 'aios/aios',
'deployment_state': 'STAGING',
'runtime_mode': 'IMMUTABLE_STAGING',
'runtime_entrypoint': 'app/aios_model_api_staging.py',
'legacy_global_writes_enabled': False,
'governed_release_routing': 'bridge-v2',
'artifact_sha256': 'provided-by-build-receipt-and-install-manifest',
'included_paths': included,
}
output.mkdir(parents=True, exist_ok=True)
archive = output / f'aios-v2r2c1-model-api-{oid}.tar.gz'
with tempfile.TemporaryDirectory(prefix='v2r2c1-model-api-', dir=str(output)) as tmp:
root = Path(tmp) / 'runtime'
for rel, path in paths:
target = root / rel
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(path.read_bytes())
(root / 'manifest.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True) + '\n', encoding='utf-8')
with tarfile.open(archive, 'w:gz', format=tarfile.PAX_FORMAT) as tf:
for path in sorted(root.rglob('*')):
rel = path.relative_to(root.parent)
info = tf.gettarinfo(str(path), arcname=str(rel).replace('\\', '/'))
info.mtime = 0
info.uid = 0
info.gid = 0
info.uname = 'root'
info.gname = 'root'
if path.is_file():
with path.open('rb') as fh:
tf.addfile(info, fh)
else:
tf.addfile(info)
digest = sha256(archive)
receipt = {
'schema': 'aios.v2r2c1.model-api-staging-build-receipt.v1',
'target_version': 'V2R2C1',
'source_oid': oid,
'repository_identity': 'aios/aios',
'artifact_path': str(archive),
'artifact_sha256': digest,
'deployment_state': 'STAGING',
'manifest_schema': SCHEMA,
'included_paths': included,
}
receipt_path = output / f'aios-v2r2c1-model-api-{oid}.receipt.json'
receipt_path.write_text(json.dumps(receipt, ensure_ascii=False, indent=2, sort_keys=True) + '\n', encoding='utf-8')
print(json.dumps(receipt, ensure_ascii=False, indent=2, sort_keys=True))
return 0
if __name__ == '__main__':
raise SystemExit(main())
@@ -1,67 +0,0 @@
#!/usr/bin/env python3
from pathlib import Path
import copy,hashlib,importlib.util,json,sys,yaml
R=Path(__file__).resolve().parents[1];D=R/'docs/gitops';M={'get','post','put','patch','delete','head','options','trace'}
N=['openapi-chatgpt-actions-governed-release.yaml','openapi-chatgpt-actions-online-gitops-task.yaml','openapi-chatgpt-actions-online-agent-task.yaml']
def die(s):raise AssertionError(s)
def load(p):
x=yaml.safe_load(Path(p).read_text());
if not isinstance(x,dict):die('yaml mapping required:'+str(p))
return x
def op(d,label):
r={}
for route,ms in d.get('paths',{}).items():
if not isinstance(ms,dict) or not isinstance(route,str) or not route.startswith('/'):die(label+': paths')
for method,x in ms.items():
if method.lower() in M:
if not isinstance(x,dict) or not x.get('operationId'):die(label+': operationId')
i=x['operationId'];
if i in r:die(label+': duplicate '+i)
r[i]={'route':route,'method':method.upper(),'security':copy.deepcopy(x.get('security',d.get('security',[])))}
return r
def st(x):return json.dumps(x,sort_keys=True,separators=(',',':'))
def refs(x,c,label):
if isinstance(x,dict):
if isinstance(x.get('$ref'),str) and x['$ref'].startswith('#/components/'):
z={'components':c}
for k in x['$ref'][2:].split('/'):
if not isinstance(z,dict) or k not in z:die(label+': unresolved '+x['$ref'])
z=z[k]
for v in x.values():refs(v,c,label)
elif isinstance(x,list):
for v in x:refs(v,c,label)
def main():
s,p=load(D/'openapi-chatgpt-actions.yaml'),load(D/'openapi-chatgpt-actions-public-runtime-2e599646.yaml');so,po=op(s,'source'),op(p,'public')
if (len(so),len(po))!=(31,30) or s.get('servers')!=p.get('servers'):die('input count/server drift')
for i in so.keys()&po.keys():
if any(st(so[i][k])!=st(po[i][k]) for k in ('route','method','security')):die('common drift '+i)
u={**so,**po}
if len(u)!=46:die('union count')
z={}
for n in N:
d=load(D/n)
if not str(d.get('openapi','')).startswith('3.') or d.get('servers')!=s['servers'] or not isinstance(d.get('components'),dict):die('openapi structure '+n)
refs(d.get('paths'),d['components'],n); q=op(d,n)
if not 1<=len(q)<=30 or z.keys()&q.keys():die('limit/duplicate '+n)
z.update(q)
if set(z)!=set(u):die('split coverage')
for i in u:
if any(st(z[i][k])!=st(u[i][k]) for k in ('route','method','security')):die('route/auth '+i)
m=json.loads((D/'chatgpt-action-schema-capability-manifest.json').read_text());r={x.get('operation_id'):x for x in m.get('operations',[]) if isinstance(x,dict)}
if m.get('union_operation_count')!=46 or set(r)!=set(u):die('manifest coverage')
for i,x in u.items():
a=r[i]
if a.get('server_route')!=x['route'] or a.get('method')!=x['method'] or st(a.get('declared_openapi_security'))!=st(x['security']):die('manifest route/auth '+i)
if bool(a.get('source_origin'))!=(i in so) or bool(a.get('public_origin'))!=(i in po):die('manifest origins '+i)
A={'createOnlineAgentTask','registerOnlineAgent','getOnlineAgentTask','getOnlineAgentTaskEvents','verifyOnlineAgentTask','cancelOnlineAgentTask'}
if set(m.get('scope_provenance',{}).get('agent_task_control',{}).get('operation_ids',[]))!=A:die('agent ids')
for i in A:
if r[i].get('required_scope')!='agent-task:control' or r[i].get('schema')!='docs/gitops/openapi-chatgpt-actions-online-agent-task.yaml':die('agent scope '+i)
if importlib.util.find_spec('openapi_spec_validator'):
from openapi_spec_validator import validate_spec
for n in N:validate_spec(load(D/n))
print('formal_validator=PASS')
else:print('formal_validator=NOT_INSTALLED')
print('yaml_parse=PASS');print('openapi_structure=PASS');print('source_coverage=PASS');print('public_runtime_coverage=PASS');print('union_route_auth_reconciliation=PASS');print('capability_manifest=PASS');print('schema_split_validation=PASS')
try:main()
except (AssertionError,OSError,ValueError,yaml.YAMLError,json.JSONDecodeError) as e:print('schema_split_validation=FAIL: '+str(e),file=sys.stderr);sys.exit(1)
@@ -2,7 +2,7 @@ from __future__ import annotations
import hashlib,json,re,tarfile
from pathlib import Path
from typing import Any
OID_RE=re.compile(r"^[0-9a-f]{40}$"); SHA_RE=re.compile(r"^[0-9a-f]{64}$"); VERSION_RE=re.compile(r"^V[0-9]+R[0-9]+C[0-9]+(?:-[A-Za-z0-9_.-]+)?$")
OID_RE=re.compile(r"^[0-9a-f]{40}$"); SHA_RE=re.compile(r"^[0-9a-f]{64}$"); VERSION_RE=re.compile(r"^V2R1C[0-9]+$")
REQUIRED_SOURCE={"schema","version","repository","base_ref","base_oid","binding_mode","release_readiness","production_deployed","tag_created","baseline_changed","production_service","production_port","rollback_metadata","controller_schema","required_checks"}
REQUEST_KEYS={"schema","version","repository","base_oid","target_oid","artifact_uri","artifact_sha256","artifact_size","evidence_closure_oid","approval_plan_id","execute","production_deployed","production_service","production_port","rollback_metadata","current_tag_oid","source_manifest_sha256"}
class ManifestValidationError(ValueError):
@@ -62,7 +62,7 @@ def validate_release_request(source_manifest:dict[str,Any],request_path:Path,exp
if not isinstance(request["approval_plan_id"],str) or not request["approval_plan_id"].startswith("sha256:"): raise ManifestValidationError("APPROVAL_PLAN","invalid approval plan")
if request["execute"] is not False or request["production_deployed"] is not False: raise ManifestValidationError("EXECUTION_NOT_ALLOWED","must be non-executing")
if request["production_service"]!=source_manifest["production_service"] or request["production_port"]!=source_manifest["production_port"]: raise ManifestValidationError("SERVICE_IDENTITY","request service mismatch")
if not isinstance(request["current_tag_oid"],str) or request["current_tag_oid"] not in {"V2R1C7","82792347937c0df59a8e02d6162775252bcad2e2"}: raise ManifestValidationError("PROTECTED_TAG","previous production tag binding changed")
if not isinstance(request["current_tag_oid"],str) or request["current_tag_oid"] not in {"V2R1C6","9e65bd59baea392294c0f253046d3ab116f63145"}: raise ManifestValidationError("PROTECTED_TAG","previous tag binding changed")
_sha(request["source_manifest_sha256"],"source_manifest_sha256"); return request
def build_approval_request(*,source_manifest_path:Path,target_oid:str,artifact_uri:str,artifact_sha256:str,artifact_size:int,evidence_closure_oid:str,rollback_metadata:str,current_tag_oid:str)->dict[str,Any]:
source=_json_object(source_manifest_path); _oid(target_oid,"target_oid"); _sha(artifact_sha256,"artifact_sha256"); _oid(evidence_closure_oid,"evidence_closure_oid"); request={"schema":"aios.release-request.v2","version":source["version"],"repository":source["repository"],"base_oid":source["base_oid"],"target_oid":target_oid,"artifact_uri":artifact_uri,"artifact_sha256":artifact_sha256,"artifact_size":artifact_size,"evidence_closure_oid":evidence_closure_oid,"execute":False,"production_deployed":False,"production_service":source["production_service"],"production_port":source["production_port"],"rollback_metadata":rollback_metadata,"current_tag_oid":current_tag_oid,"source_manifest_sha256":sha256_file(source_manifest_path)}; request["approval_plan_id"]="sha256:"+sha256_bytes(_canonical(request)); return request
@@ -3,13 +3,13 @@ from __future__ import annotations
import json
from pathlib import Path
ROOT = Path(__file__).parents[2]
def test_version_and_candidate_binding():
assert (ROOT / "VERSION").read_text(encoding="utf-8").strip() == "V2R1C7"
assert (ROOT / "VERSION").read_text(encoding="utf-8").strip() == "V2R1C6"
metadata = json.loads((ROOT / "versions/V2R1C6.json").read_text(encoding="utf-8"))
assert metadata["version"] == "V2R1C6"
assert metadata["base_oid"] == "a33e2593967a180c89d44454350ccaeaf3f79b25"
assert metadata["candidate_branch"] == "agent/v2r1c6-mainline-reconciliation-20260806"
assert metadata["production_deployed"] is False
@@ -7,19 +7,17 @@ import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "active-runtime" / "app"))
from deployment_state import RuntimeDeploymentState
from v2r1c6_privacy_tools import health_payload, serve # noqa: E402
def test_health_is_engineering_only() -> None:
result = health_payload(RuntimeDeploymentState("V2R1C7", "a" * 40, "b" * 64, "STAGED"))
assert result["status"] == "ok"
assert result["version"] == "V2R1C7"
assert result["commit_oid"] == "a" * 40
assert result["artifact_sha256"] == "b" * 64
assert result["deployment_state"] == "STAGED"
assert result["production_deployed"] is False
assert result["health_timestamp"]
result = health_payload()
assert result == {
"status": "ok",
"version": "V2R1C6",
"production_deployed": False,
"gitops_writes_enabled": False,
}
def test_listener_rejects_non_loopback() -> None:
-65
View File
@@ -1,65 +0,0 @@
from __future__ import annotations
import importlib.util
import sys
import types
from pathlib import Path
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
TEST_ROOT = REPOSITORY_ROOT / "tests"
SERVICE_PACKAGE_ROOT = REPOSITORY_ROOT / "services" / "aios-autonomous-release-candidate"
ACTIVE_RUNTIME_ROOT = REPOSITORY_ROOT / "active-runtime"
ACTIVE_RUNTIME_APP = ACTIVE_RUNTIME_ROOT / "app"
for path in (TEST_ROOT, SERVICE_PACKAGE_ROOT, ACTIVE_RUNTIME_APP):
value = str(path)
if value not in sys.path:
sys.path.insert(0, value)
def load_module(relative: str):
path = REPOSITORY_ROOT / relative
spec = importlib.util.spec_from_file_location("v2r1c6_privacy_tools", path)
if spec is None or spec.loader is None:
raise RuntimeError("module_load_failed")
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
def _install_active_runtime_namespace() -> None:
package = sys.modules.get("active_runtime")
if package is None:
package = types.ModuleType("active_runtime")
package.__path__ = [str(ACTIVE_RUNTIME_ROOT)]
package.__package__ = "active_runtime"
sys.modules["active_runtime"] = package
app = sys.modules.get("active_runtime.app")
if app is None:
app = types.ModuleType("active_runtime.app")
app.__path__ = [str(ACTIVE_RUNTIME_APP)]
app.__package__ = "active_runtime"
sys.modules["active_runtime.app"] = app
package.app = app
def _install_legacy_test_module(name: str, relative: str) -> None:
if name in sys.modules:
return
path = REPOSITORY_ROOT / relative
spec = importlib.util.spec_from_file_location(name, path)
if spec is None or spec.loader is None:
raise RuntimeError("legacy_test_module_load_failed:" + name)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
_install_active_runtime_namespace()
sys.modules.setdefault("conftest", sys.modules[__name__])
_install_legacy_test_module(
"test_native_adapter_contracts",
"tests/autonomous_release/test_native_adapter_contracts.py",
)
@@ -1,90 +0,0 @@
import base64
from pathlib import Path
from aios_authority_git_executor import AuthorityGitExecutor
from aios_chatgpt_bridge_v2_server import BridgeHandler, RuntimeConfig
from aios_continuation_executor import GiteaContinuationRemote, ServerSideCredentialProjection
from aios_continuation_lease import WriterLeaseRequestV2
class Probe:
def __init__(self, present=False):
self.present = present
def branch_exists(self, _branch):
return self.present
def branch_head(self, _branch):
return "a" * 40
def is_ancestor(self, _older, _newer):
return True
def commit_exists(self, _oid):
return True
def test_create_new_lease_is_exact_base_and_absent():
request = WriterLeaseRequestV2(
task_id="TASK-P0-BRIDGE-V21-DURABLE-RECONCILIATION-20260809",
repository="aios/aios",
branch_mode="CREATE_NEW",
base_oid="a" * 40,
expected_branch_oid="a" * 40,
target_branch="agent/p0-bridge-v21-durable-reconciliation-20260809",
generation=1,
)
request.validate(Probe())
def test_create_new_lease_rejects_existing_target():
request = WriterLeaseRequestV2(
task_id="task",
repository="aios/aios",
branch_mode="CREATE_NEW",
base_oid="a" * 40,
expected_branch_oid="a" * 40,
target_branch="agent/existing-target",
generation=1,
)
try:
request.validate(Probe(True))
except Exception as exc:
assert str(exc) == "TARGET_BRANCH_ALREADY_EXISTS"
else:
raise AssertionError("existing CREATE_NEW target must fail")
def test_slash_branch_uses_paginated_collection():
credential = ServerSideCredentialProjection(Path("/tmp/key"), Path("/tmp/token"), active=True)
calls = []
class FakeRemote(GiteaContinuationRemote):
def _api(self, path):
calls.append(path)
if "page=1" in path:
return [{"name": f"agent/other-{i}", "commit": {"id": "b" * 40}} for i in range(50)]
return [{"name": "agent/slash/branch", "commit": {"id": "c" * 40}}]
remote = FakeRemote(Path("/tmp"), credential)
assert remote.read_api_branch("agent/slash/branch") == "c" * 40
assert calls[0].endswith("branches?page=1&limit=50")
assert calls[1].endswith("branches?page=2&limit=50")
def test_http_route_contract_is_complete():
expected = {
"/v2/runtime", "/v2/capabilities", "/v2/governed-task",
"/v2/writer-lease", "/v2/commit-file", "/v2/commit-files",
"/v2/job", "/v2/job/resume", "/v2/job/reconcile",
"/v2/tag/approval-request",
"/v2/tag/publish",
"/v2/tag/status",
"/v2/release/artifact",
"/v2/release/execute",
"/v2/release/consistency",
"/v2/release/acceptance",
}
from aios_chatgpt_bridge_v2_server import ROUTES
assert set(ROUTES) == expected
@@ -1,9 +0,0 @@
import subprocess,sys,unittest
from pathlib import Path
R=Path(__file__).resolve().parents[1]
class SchemaSplitTest(unittest.TestCase):
def test_reconciliation(self):
x=subprocess.run([sys.executable,str(R/'scripts/validate_chatgpt_action_schema_split.py')],cwd=R,text=True,capture_output=True)
self.assertEqual(x.returncode,0,x.stdout+x.stderr)
for s in ('source_coverage=PASS','public_runtime_coverage=PASS','union_route_auth_reconciliation=PASS','schema_split_validation=PASS'):self.assertIn(s,x.stdout)
if __name__=='__main__':unittest.main()
+90
View File
@@ -0,0 +1,90 @@
from __future__ import annotations
import hashlib
import json
from pathlib import Path
import tempfile
import pytest
import yaml
from aios_chatgpt_bridge_v2 import (
BRIDGE_OPERATIONS,
BRIDGE_SCHEMA_VERSION,
OPERATION_REQUIRED_FIELDS,
BridgeV2Adapter,
ControlPlaneReleaseManifest,
RuntimeDriftError,
)
ROOT = Path(__file__).parents[1]
def test_immutable_release_identity_accepts_exact_artifact_and_rejects_workspace_drift():
with tempfile.TemporaryDirectory() as directory:
approved = Path(directory) / "releases"
runtime = approved / "release-1"
runtime.mkdir(parents=True)
artifact = runtime / "bridge.pyz"
artifact.write_bytes(b"bridge-v2")
digest = hashlib.sha256(artifact.read_bytes()).hexdigest()
manifest = ControlPlaneReleaseManifest(
"bridge-v2-test", "a" * 40, digest, runtime, BRIDGE_SCHEMA_VERSION,
"aios/aios", Path("/data/aios-gitops/repo.git"), "STAGING",
)
assert manifest.validate(artifact, observed_oid="a" * 40, approved_root=approved)["drift_status"] == "PASS"
with pytest.raises(RuntimeDriftError, match="CONTROL_PLANE_RUNTIME_DRIFT"):
manifest.validate(artifact, observed_oid="b" * 40, approved_root=approved)
mutable = ControlPlaneReleaseManifest(
"bad", "a" * 40, digest, Path("/var/lib/worktrees/dev"), BRIDGE_SCHEMA_VERSION,
"aios/aios", Path("/data/aios-gitops/repo.git"), "STAGING",
)
with pytest.raises(RuntimeDriftError, match="CONTROL_PLANE_RUNTIME_DRIFT"):
mutable.validate(artifact, observed_oid="a" * 40, approved_root=approved)
def test_bridge_capabilities_keep_legacy_closed_and_expose_exact_operations():
adapter = BridgeV2Adapter(runtime_status={"drift_status": "PASS"})
assert adapter.getRuntimeStatus()["bridge_schema_version"] == BRIDGE_SCHEMA_VERSION
capabilities = adapter.getGovernedWriteCapabilities()
assert capabilities["legacy_writes_enabled"] is False
assert capabilities["governed_writes_enabled"] is True
assert tuple(capabilities["operations"]) == BRIDGE_OPERATIONS
assert adapter.legacy_write_disabled() == {
"error": "LEGACY_WRITE_DISABLED",
"replacement": "createGovernedTask",
"governed_writes_available": True,
}
def test_openapi_runtime_and_fragment_required_fields_are_exactly_converged():
canonical = yaml.safe_load((ROOT / "docs/gitops/openapi-chatgpt-actions.yaml").read_text(encoding="utf-8"))
fragment = yaml.safe_load((ROOT / "docs/gitops/openapi-authorized-task-writer-fragment.yaml").read_text(encoding="utf-8"))
operations = {}
for path, methods in canonical["paths"].items():
for method, value in methods.items():
if isinstance(value, dict) and value.get("operationId") in BRIDGE_OPERATIONS:
operations[value["operationId"]] = value
assert set(operations) == set(BRIDGE_OPERATIONS)
for operation, required in OPERATION_REQUIRED_FIELDS.items():
if "requestBody" not in operations[operation]:
assert required == ()
continue
schema = operations[operation]["requestBody"]["content"]["application/json"]["schema"]
assert tuple(schema["required"]) == required
fragment_required = tuple(fragment["components"]["schemas"]["WriterLeaseRequestV2"]["required"])
assert fragment_required == OPERATION_REQUIRED_FIELDS["acquireWriterLease"]
def test_release_manifest_round_trip_contains_only_declared_identity_fields():
manifest = ControlPlaneReleaseManifest(
"v", "a" * 40, "b" * 64, Path("/opt/aios/gitops-control-plane/v"), BRIDGE_SCHEMA_VERSION,
"aios/aios", Path("/data/aios-gitops/repo.git"), "STAGING",
)
value = manifest.as_dict()
assert tuple(value) == (
"control_plane_release_version", "control_plane_target_oid", "artifact_sha256", "runtime_path",
"bridge_schema_version", "repository_identity", "authoritative_git_dir", "deployment_state",
)
assert "credential" not in json.dumps(value).lower()
@@ -0,0 +1,283 @@
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from pathlib import Path
import subprocess
import tempfile
import pytest
from aios_continuation_executor import (
ContinuationCommit,
ContinuationExecutionError,
ContinuationExecutor,
ContinuationPermissions,
ContinuationRuntimeBinding,
DetachedGitWorkspace,
GiteaContinuationRemote,
)
from aios_continuation_lease import WriterLeaseRequestV2
from aios_gitops_job_controller import BindingConflict, GitOpsJobController, JobState, JobStore
TASK = "TASK-P0-CHATGPT-BRIDGE-V2-CONTROL-PLANE-CONVERGENCE-20260809"
REPOSITORY = "aios/aios"
BRANCH = "agent/p0-chatgpt-bridge-v2-control-plane-convergence-20260809"
BASE = "2" * 40
HEAD = "8" * 40
NEW = "9" * 40
NOW = datetime(2026, 8, 9, 12, 0, tzinfo=timezone.utc)
class Authority:
def __init__(self, *, head=HEAD, exists=True, descendant=True):
self.head = head
self.exists = exists
self.descendant = descendant
self.cas_calls = []
def branch_exists(self, branch):
return self.exists
def branch_head(self, branch):
return self.head
def is_ancestor(self, older, newer):
if (older, newer) == (BASE, HEAD):
return True
return self.descendant and (older, newer) in {(HEAD, NEW), (BASE, NEW)}
def compare_and_swap_branch(self, branch, expected, new):
self.cas_calls.append((branch, expected, new))
if self.head != expected:
raise RuntimeError("stale")
self.head = new
return new
class Workspace:
def __init__(self, *, detached=True, head=HEAD):
self.detached = detached
self.head = head
self.commits = 0
def is_detached(self):
return self.detached
def head_oid(self):
return self.head
def commit_files(self, files, message):
self.commits += 1
self.head = NEW
return NEW
class Remote:
def __init__(self, *, git=HEAD, api=HEAD, visible=True, repository=REPOSITORY, fail_after_push=False, omit_after_push=False):
self.git = git
self.api = api
self.visible = visible
self.repository = repository
self.fail_after_push = fail_after_push
self.omit_after_push = omit_after_push
self.pushes = 0
def repository_identity(self):
return self.repository
def push_exact(self, branch, expected, new):
self.pushes += 1
if self.git is None:
raise RuntimeError("remote branch missing")
if self.git != expected:
raise RuntimeError("remote conflict")
if not self.omit_after_push:
self.git = self.api = new
else:
self.git = self.api = None
if self.fail_after_push:
raise TimeoutError("response lost")
def read_git_ref(self, branch):
return self.git
def read_api_branch(self, branch):
return self.api
def commit_visible(self, oid):
return self.visible and self.api == oid
class Credential:
def __init__(self):
self.projected = 0
self.revoked = 0
def project(self):
self.projected += 1
def revoke(self):
self.revoked += 1
def lease_request(**changes):
values = dict(task_id=TASK, repository=REPOSITORY, branch_mode="CONTINUE_EXISTING", base_oid=BASE,
expected_branch_oid=HEAD, target_branch=BRANCH, generation=1, lease_seconds=900)
values.update(changes)
return WriterLeaseRequestV2(**values)
def binding(**changes):
values = dict(
request=lease_request(),
workspace_path=Path("/var/lib/aios-task-writer/continuation-worktrees/exact"),
lease_not_before=NOW - timedelta(seconds=1),
lease_expires_at=NOW + timedelta(minutes=15),
original_receipt_valid=True,
original_grant_consumed=True,
permissions=ContinuationPermissions(),
)
values.update(changes)
return ContinuationRuntimeBinding(**values)
def commit(**changes):
values = dict(idempotency_key="first-continuation", files={"active-runtime/app/new.py": b"ok\n"},
message="feat(gitops): add governed continuation executor")
values.update(changes)
return ContinuationCommit(**values)
def make_executor(authority=None, workspace=None, remote=None, credential=None):
temp = tempfile.TemporaryDirectory()
controller = GitOpsJobController(JobStore(Path(temp.name).resolve()))
executor = ContinuationExecutor(
controller, authority or Authority(), workspace or Workspace(), remote or Remote(), credential or Credential(),
now=lambda: NOW,
)
executor._test_temp = temp
return executor
def test_exact_existing_branch_completes_only_after_all_remote_proofs():
authority, remote, credential = Authority(), Remote(), Credential()
result = make_executor(authority, remote=remote, credential=credential).execute(binding(), commit())
assert result["state"] == JobState.COMPLETED.value
assert result["receipt"]["authority_oid"] == result["receipt"]["git_remote_oid"] == NEW
assert result["receipt"]["api_branch_oid"] == NEW
assert result["receipt"]["commit_visible"] is True
assert authority.cas_calls == [(BRANCH, HEAD, NEW)]
assert credential.projected == credential.revoked == 1
assert "credential" not in repr(result).lower()
@pytest.mark.parametrize(
"runtime_binding,authority,workspace,error",
[
(binding(request=lease_request(expected_branch_oid="7" * 40)), Authority(), Workspace(), "EXISTING_BRANCH_OID_CONFLICT"),
(binding(), Authority(exists=False), Workspace(), "EXISTING_BRANCH_MISSING"),
(binding(), Authority(), Workspace(detached=False), "WORKTREE_NOT_DETACHED"),
(binding(), Authority(), Workspace(head="7" * 40), "WORKTREE_HEAD_MISMATCH"),
(binding(lease_expires_at=NOW), Authority(), Workspace(), "LEASE_EXPIRED"),
(binding(request=lease_request(repository="other/repo")), Authority(), Workspace(), "request_identity_invalid"),
(binding(request=lease_request(target_branch="main")), Authority(), Workspace(), "PROTECTED_BRANCH_REJECTED"),
(binding(request=lease_request(generation=1)), Authority(), Workspace(), "GENERATION_NOT_MONOTONIC"),
],
)
def test_pre_side_effect_failures_never_create_or_update_a_branch(runtime_binding, authority, workspace, error):
executor = make_executor(authority, workspace=workspace)
if error == "GENERATION_NOT_MONOTONIC":
executor.observe_generation(BRANCH, 1)
with pytest.raises(Exception, match=error):
executor.execute(runtime_binding, commit())
assert authority.cas_calls == []
assert workspace.commits == 0
@pytest.mark.parametrize("field", ["create_target_branch", "force_push", "tag_write", "baseline_write", "production_write", "main_write"])
def test_forbidden_capabilities_fail_before_credential_projection(field):
credential = Credential()
permissions = ContinuationPermissions(**{field: True})
with pytest.raises(ContinuationExecutionError, match="MUTATION_PERMISSION_DENIED"):
make_executor(credential=credential).execute(binding(permissions=permissions), commit())
assert credential.projected == 0
def test_non_fast_forward_and_concurrent_movement_are_rejected_cas_only():
authority = Authority(descendant=False)
with pytest.raises(ContinuationExecutionError, match="NON_FAST_FORWARD_COMMIT"):
make_executor(authority).execute(binding(), commit())
assert authority.cas_calls == []
def test_authority_success_and_gitea_missing_is_never_completed():
remote = Remote(omit_after_push=True)
result = make_executor(remote=remote).execute(binding(), commit())
assert result["state"] == JobState.RECONCILIATION_REQUIRED.value
assert result["side_effect_state"] == "REMOTE_PUSH_PENDING"
assert result["state"] not in {JobState.REMOTE_VERIFIED.value, JobState.COMPLETED.value}
def test_response_loss_after_remote_success_reconciles_by_observation_without_second_push():
remote = Remote(fail_after_push=True)
executor = make_executor(remote=remote)
first = executor.execute(binding(), commit())
assert first["state"] == JobState.RECONCILIATION_REQUIRED.value
assert remote.pushes == 1
recovered = executor.reconcile(first["job_id"])
assert recovered["state"] == JobState.COMPLETED.value
assert remote.pushes == 1
def test_observation_first_reconcile_retries_only_when_remote_is_exact_expected_old_oid():
remote = Remote(fail_after_push=True)
executor = make_executor(remote=remote)
first = executor.execute(binding(), commit())
assert first["state"] == JobState.RECONCILIATION_REQUIRED.value
remote.git = remote.api = HEAD
remote.visible = True
remote.fail_after_push = False
recovered = executor.reconcile(first["job_id"])
assert recovered["state"] == JobState.COMPLETED.value
assert remote.pushes == 2
def test_duplicate_idempotency_replay_and_conflicting_payload():
executor = make_executor()
first = executor.execute(binding(), commit())
replay = executor.execute(binding(), commit())
assert replay["job_id"] == first["job_id"]
with pytest.raises(BindingConflict, match="BINDING_CONFLICT"):
executor.execute(binding(), commit(files={"active-runtime/app/new.py": b"changed\n"}))
def test_secret_like_payload_fails_before_projection():
credential = Credential()
secret_fixture = b"to" + b"ken=" + b"ghp_" + b"abcdefghijklmnopqrstuvwxyz0123456789"
with pytest.raises(ContinuationExecutionError, match="SECRET_LIKE_PAYLOAD_REJECTED"):
make_executor(credential=credential).execute(binding(), commit(files={"x": secret_fixture}))
assert credential.projected == 0
def test_remote_identity_cannot_alias_the_authority_bare_repo():
with pytest.raises(ContinuationExecutionError, match="GITEA_REMOTE_IDENTITY_INVALID"):
GiteaContinuationRemote.validate_remote_url("/data/aios-gitops/repo.git")
GiteaContinuationRemote.validate_remote_url("aiman@g.cnnetmkt.top:aios/aios.git")
def test_detached_workspace_preserves_porcelain_leading_status_column():
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
subprocess.run(["git", "init", "-q", str(root)], check=True)
subprocess.run(["git", "-C", str(root), "config", "user.name", "test"], check=True)
subprocess.run(["git", "-C", str(root), "config", "user.email", "test@localhost"], check=True)
(root / "tracked.py").write_text("one\n", encoding="utf-8")
subprocess.run(["git", "-C", str(root), "add", "tracked.py"], check=True)
subprocess.run(["git", "-C", str(root), "commit", "-q", "-m", "base"], check=True)
subprocess.run(["git", "-C", str(root), "checkout", "-q", "--detach"], check=True)
(root / "tracked.py").write_text("two\n", encoding="utf-8")
(root / "new.py").write_text("new\n", encoding="utf-8")
workspace = DetachedGitWorkspace(root)
assert workspace.is_detached()
assert workspace._dirty_paths() == {"tracked.py", "new.py"}
+3 -3
View File
@@ -250,7 +250,7 @@ class GovernedLocalWriterTests(unittest.TestCase):
}
self.assertEqual(service.process_request(secret_request, peer)["status"], "error")
def test_idempotent_replay_returns_receipt(self) -> None:
def test_one_shot_consumption(self) -> None:
with tempfile.TemporaryDirectory() as root:
directory = Path(root)
auth = self._load_auth(self._make_auth_payload(), directory)
@@ -283,8 +283,8 @@ class GovernedLocalWriterTests(unittest.TestCase):
self.assertEqual(service.process_request(create_request, peer)["status"], "ok")
self.assertEqual(service.process_request(append_request, peer)["status"], "ok")
self.assertEqual(service.process_request(append_request, peer)["status"], "receipt")
self.assertEqual(len(sink.records), 2)
self.assertEqual(service.process_request(append_request, peer)["status"], "error")
self.assertEqual(len(sink.records), 3)
self.assertEqual(len(handler.create_calls), 1)
self.assertEqual(len(handler.append_calls), 1)
-35
View File
@@ -1,35 +0,0 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_model_api_source_is_immutable_and_authority_bound():
source = (ROOT / 'active-runtime' / 'app' / 'aios_model_api_staging.py').read_text(encoding='utf-8')
assert 'BaselineAuthority' in source
assert 'BASELINE_AUTHORITY = BaselineAuthority()' in source
assert 'LEGACY_GIT_WRITE_COMMANDS' in source
assert 'BaselineAuthorityError' in source
assert 'IMMUTABLE_STAGING' in source
assert 'LEGACY_GLOBAL_WRITES_DISABLED' in source
assert "'production_deployed': False" in source
assert "'governed_release_routing': 'bridge-v2'" in source
def test_model_api_staging_unit_is_non_production_and_read_only():
unit = (ROOT / 'deploy' / 'systemd' / 'aios-gitops-model-api-v2r2c1-staging.service').read_text(encoding='utf-8')
assert 'aios-gitops-model-api-v2r2c1-staging.service' in unit
assert 'AIOS_GITOPS_WRITES_ENABLED=false' in unit
assert 'AIOS_GITOPS_DURABLE_JOB_EXECUTION_ENABLED=false' in unit
assert 'AIOS_GITOPS_PORT=18893' in unit
assert 'aios_model_api_staging.py' in unit
assert 'production' not in unit.lower().replace('model-api-v2r2c1-staging', '')
def test_model_api_builder_manifest_contract():
builder = (ROOT / 'scripts' / 'build_v2r2c1_model_api_staging.py').read_text(encoding='utf-8')
assert 'aios.v2r2c1.model-api-staging-manifest.v1' in builder
assert "'target_version': 'V2R2C1'" in builder
assert "'repository_identity': 'aios/aios'" in builder
assert "'deployment_state': 'STAGING'" in builder
assert "'legacy_global_writes_enabled': False" in builder
assert 'private marker rejected' in builder
@@ -0,0 +1,51 @@
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from aios_control_plane_snapshot import build_control_plane_snapshot
from aios_credential_broker import CredentialBroker
from aios_gitops_reconciliation_core import ReconciliationAction, RemoteObservation, decide_reconciliation
from aios_governed_policy import GovernedPolicyInput, evaluate_policy
OID = "a" * 40
OLD = "b" * 40
def test_authority_desired_remote_missing_never_completes():
decision = decide_reconciliation(RemoteObservation("aios/aios", "agent/example", OID, OID, None, None, False, "now", OLD))
assert decision.action == ReconciliationAction.MARK_RECONCILIATION_REQUIRED
assert decision.state != "COMPLETED"
def test_response_loss_observes_desired_remote_before_retry():
decision = decide_reconciliation(RemoteObservation("aios/aios", "agent/example", OID, OID, OID, OID, True, "now", OLD))
assert decision.action == ReconciliationAction.MARK_REMOTE_VERIFIED
def test_conflicting_remote_fails_closed():
decision = decide_reconciliation(RemoteObservation("aios/aios", "agent/example", OID, OID, "c" * 40, "c" * 40, True, "now", OLD))
assert decision.action == ReconciliationAction.FAIL_CONFLICT
def test_policy_denies_production_and_force_capabilities():
request = GovernedPolicyInput("owner", "task", "aios/aios", "commitFilesGoverned", OID, OID, "agent/example", 2, requested_capabilities=("production_write", "force_push"))
assert evaluate_policy(request).decision == "DENY"
def test_credential_metadata_does_not_include_secret_and_revoke_is_idempotent():
class Provider:
def environment(self, lease):
return {"CREDENTIAL_FILE": "/run/credential"}
broker = CredentialBroker(Provider())
metadata = broker.issue(task_id="task", repository="aios/aios", target_branch="agent/example", generation=1)
assert "token" not in str(metadata).lower()
revoked = broker.revoke(metadata["lease_id"])
assert broker.revoke(metadata["lease_id"])["state"] == "REVOKED"
assert revoked["state"] == "REVOKED"
def test_snapshot_marks_secret_material_false_and_preserves_partial_observation():
snapshot = build_control_plane_snapshot(target_version="V2R2C1", task={"gitea_git_oid": None, "gitea_api_oid": None})
assert snapshot["secret_material_exposed"] is False
assert snapshot["task"]["gitea_git_oid"] is None