Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57697d81cf | ||
|
|
39c97d4f7f | ||
|
|
649e25a668 | ||
|
|
fcfd841a2d | ||
|
|
1a7d62c755 | ||
|
|
61c8cf3ca7 | ||
|
|
8814dff202 | ||
|
|
ff6743e851 | ||
|
|
ebd7439874 | ||
|
|
c41e278c59 | ||
|
|
1071979079 | ||
|
|
9a158fcab9 | ||
|
|
8b7f9d9028 | ||
|
|
3aa1872084 | ||
|
|
f6bef90633 | ||
|
|
c2eed5b379 | ||
|
|
6e8212608e | ||
|
|
e6a53888fe | ||
|
|
2bef44f6bc | ||
|
|
a96f36bf72 | ||
|
|
4e6ef70029 | ||
|
|
80feef309f | ||
|
|
a5489f1b67 | ||
|
|
312d3b4830 | ||
|
|
ac2dc5c30e | ||
|
|
5ef261b265 | ||
|
|
3a22c3c7d8 | ||
|
|
1c9f28a613 | ||
|
|
9514062cf3 | ||
|
|
a701a32cb4 | ||
|
|
45f3226662 | ||
|
|
975d239d40 | ||
|
|
3bc44accb5 | ||
|
|
3304d87872 |
+83
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"approval_request_branch": "governance/request/integration-refresh-control-plane-deployment-20260728T093428Z",
|
||||
"approval_type": "CONTROL_PLANE_DEPLOYMENT_APPROVAL_REQUEST",
|
||||
"authorization_lineage": {
|
||||
"execution_renewal_merge_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
|
||||
"grant_id": "grant-11354281aafdd074df5899a3925dd2a0370cffa9edb06f5c7d7227ce8de00d91",
|
||||
"source_mapping_approval_merge_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6"
|
||||
},
|
||||
"deployment_status": "NOT_EXECUTED",
|
||||
"evidence": {
|
||||
"control_plane_artifact": {
|
||||
"path": "/var/lib/aios-integration-refresh-source-writer-v2/artifacts/control-plane-patch-112d995545e3e79126a062b2643a9f0c17ae7bd4.tar",
|
||||
"sha256": "bf101ade1aaf956f40c0bba74ed4b347f5f38d0de6a0c1b7694ae107c4b43c14",
|
||||
"size_bytes": 13363200
|
||||
},
|
||||
"rendered_systemd_config_sha256": "182a3cba48e752798cf24323a8c0249c53d7386371388a8db0435a29c43dc969",
|
||||
"rollback_artifact": {
|
||||
"path": "/var/lib/aios-gitops/runtime/tasks/AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726/implementation/rollback-to-85426f4f570e4d40b212318d47e52e4aed5cb06a.tar",
|
||||
"sha256": "f12a2a95e475da5d02eaff99e93615cb0186019ca30edae013ab054a2c6418ce"
|
||||
},
|
||||
"source_map": {
|
||||
"path": "docs/autonomous-release/INTEGRATION_REFRESH_SOURCE_MAP_20260728.json",
|
||||
"sha256": "01ddd56cfa2a525559e2d174cf7df117a9465ffce44ef25bc7a15b8e74d06bf5"
|
||||
},
|
||||
"test_evidence": {
|
||||
"collection_errors": 0,
|
||||
"path": "/var/lib/aios-gitops/runtime/tasks/AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726/implementation/test-evidence.json",
|
||||
"sha256": "d8933553f56462a3f1b3040dec989ff0adf717a17728d55ba0fe9e127d93c206",
|
||||
"tests_failed": 0,
|
||||
"tests_passed": 41
|
||||
}
|
||||
},
|
||||
"execution_conditions": {
|
||||
"candidate_only": true,
|
||||
"integration_unchanged": true,
|
||||
"main_unchanged": true,
|
||||
"no_credentials_or_secrets_in_request": true,
|
||||
"production_baseline_unchanged": true,
|
||||
"registry_unchanged": true
|
||||
},
|
||||
"expected_governance_base_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
|
||||
"expires_at": "2026-07-28T21:34:28Z",
|
||||
"implementation": {
|
||||
"commit_oid": "112d995545e3e79126a062b2643a9f0c17ae7bd4",
|
||||
"tree_oid": "4ed88399fb8e7e4c235413ebbd783c9b6ad3c624"
|
||||
},
|
||||
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
|
||||
"issued_at": "2026-07-28T09:34:28Z",
|
||||
"prohibited_operations": [
|
||||
"production-baseline.write",
|
||||
"production-tag.write",
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"registry.write",
|
||||
"force-push",
|
||||
"direct-main-push",
|
||||
"direct-tag-write"
|
||||
],
|
||||
"repository": "aios/aios",
|
||||
"request_status": "PENDING_HUMAN_APPROVAL",
|
||||
"requested_operations": [
|
||||
"control-plane.candidate.deploy",
|
||||
"control-plane.candidate.verify",
|
||||
"control-plane.candidate.rollback"
|
||||
],
|
||||
"required_controls": [
|
||||
"Two distinct human approvals, one Codex and one GPT, both APPROVED against the same current approval-request PR head.",
|
||||
"Re-verify artifact, test evidence, source map, rendered systemd configuration, and rollback artifact paths and SHA-256 digests immediately before execution.",
|
||||
"AIOS_GITOPS_WRITES_ENABLED=false throughout candidate deployment, verification, and rollback.",
|
||||
"No force push, direct main write, or direct tag write."
|
||||
],
|
||||
"required_reviewers": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"schema": "aios.control-plane-deployment-approval-request/v1",
|
||||
"target_governance": {
|
||||
"approved_base_oid": "3a22c3c7d86930efd4bd93ac05d80ad322050cb9",
|
||||
"binding_rule": "Human approvals must bind to the same approval-request PR head; its first parent must equal the active governance base."
|
||||
},
|
||||
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
|
||||
"validity_hours": 12
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"schema": "aios.governance-approval/v1",
|
||||
"approval_type": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP_POLICY_ACTIVATION",
|
||||
"approval_plan_id": "AIOS-TSG-BS-PHASE-A-RENEWAL-20260731T081147Z",
|
||||
"task_id": "AIOS-V2R1C4-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-RENEWAL",
|
||||
"repository": "aios/aios",
|
||||
"issued_at": "2026-07-31T08:11:47Z",
|
||||
"expires_at": "2026-07-31T20:11:47Z",
|
||||
"expected_governance_base_oid": "ebd74398743e36523b593fcc395b73945d4924c5",
|
||||
"expected_governance_base_tree_oid": "ad1255a1127204fad1d1208d8f31dc94fa64e6e1",
|
||||
"approval_request_branch": "governance/request/two-stage-owner-campaign-v2-phase-a-renewal-20260731T081147Z",
|
||||
"request_head_binding": "GITEA_EXACT_HEAD_REVIEW_POST_COMMIT",
|
||||
"human_authorizer": "owner",
|
||||
"authorization_mode": "GITEA_EXACT_HEAD_REVIEW",
|
||||
"required_human_approvals": 1,
|
||||
"allowed_human_approvers": [
|
||||
"owner"
|
||||
],
|
||||
"require_latest_head_approval": true,
|
||||
"dismiss_stale_approvals": true,
|
||||
"auto_merge_after_machine_gates": true,
|
||||
"phase_a_scope": {
|
||||
"schema_id": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP",
|
||||
"schema_version": 1,
|
||||
"activate_schema_and_validator_only": true,
|
||||
"phase_b_release_authorized": false,
|
||||
"publisher_authorized": false,
|
||||
"writer_authorized": false,
|
||||
"credential_projection_authorized": false,
|
||||
"tag_authorized": false,
|
||||
"registry_authorized": false,
|
||||
"baseline_authorized": false,
|
||||
"production_deployment_authorized": false
|
||||
},
|
||||
"content_bindings": {
|
||||
"schema_document": {
|
||||
"path": "services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json",
|
||||
"blob_oid": "9b117667c0d98f995ac059b0e1b5ffed06ca6444",
|
||||
"sha256": "6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd"
|
||||
},
|
||||
"validator_policy": {
|
||||
"path": "services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py",
|
||||
"blob_oid": "c18d15f31340f19fc5da87944901bdfb867ab6dc",
|
||||
"sha256": "de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac"
|
||||
},
|
||||
"evidence_manifest": {
|
||||
"path": "evidence/governance-policy/AIOS-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-20260730T023551Z.json",
|
||||
"blob_oid": "c3d215b3ea525a25de514c32c5aad91d47e140b4",
|
||||
"sha256": "1b0a993940b41a4b16724b557f6abd8b6cebb56dc64cc8f813bd605b6a3399c2"
|
||||
},
|
||||
"checksums_manifest": {
|
||||
"path": "evidence/governance-policy/AIOS-TWO-STAGE-OWNER-CAMPAIGN-V2-PHASE-A-20260730T023551Z.sha256",
|
||||
"blob_oid": "45ed084234dae6a00e69a41cd4f716f46a97d9fb",
|
||||
"sha256": "51c4b029c0792dc98d41f754e484ba3861cf7604443d9c5f289b3b0af768a41a"
|
||||
}
|
||||
},
|
||||
"offline_candidate_bindings": {
|
||||
"schema_seed_commit_oid": "8da47545a507cb798d3d6ab30ff8552a2d0a5ecf",
|
||||
"schema_seed_tree_oid": "991e68577a469657c1c4996814b6634ce5ed752f",
|
||||
"implementation_commit_oid": "a637a9dbb6e0021cb7dcf0d6b0ca00dfe10dce38",
|
||||
"implementation_tree_oid": "bf6e0c16fcad7515465bec4aefdd2e77b1e9bef0",
|
||||
"evidence_closure_commit_oid": "1e4885197f508f7921b148d71e545b3de0029b0a",
|
||||
"evidence_closure_tree_oid": "e55cf9ef19d1c6804f161de54fd3395a06149807",
|
||||
"source_diff_sha256": "c06d002db06da6cbf16f9c8321f1acbfd431f009b5127a13fd2cb5d63b278867",
|
||||
"source_pathset_sha256": "5061402d516c0e9413208ce64e2b52f77d224e6eec1f7b07c5b3a10b58df5eaf",
|
||||
"implementation_bundle_sha256": "15711b225b9ef41cca0588d21b2b95d7a95ac155efc27fcb8772c435fcdab147",
|
||||
"evidence_bundle_sha256": "ec97b8460151fc0e7e7ea9ae044ca13a1543c4b79c41a437ef087d3b1c271857"
|
||||
},
|
||||
"runtime_dependency_bindings": {
|
||||
"handoff_zip_sha256": "668239a549b4a2b2094fe9b5104b84703fe8ed75011fd8ed71ed3958a6dc0706",
|
||||
"installed_wheel_sha256": "abbf616366eb3467d4e651bb5306e22ae5e931b613df5362a0892935c4a1c0c7",
|
||||
"anchor_service": "aios-campaign-anchor.service",
|
||||
"anchor_uid": 988,
|
||||
"runner_uid": 986,
|
||||
"anchor_database": "/var/lib/aios-campaign-anchor/anchor.sqlite3",
|
||||
"anchor_socket": "/run/aios-campaign-anchor/anchor.sock",
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false
|
||||
},
|
||||
"required_machine_status_contexts": [
|
||||
"governance/schema-contract",
|
||||
"governance/validator-security",
|
||||
"governance/fault-injection",
|
||||
"governance/runtime-isolation",
|
||||
"governance/authority-mirror"
|
||||
],
|
||||
"allowed_operations_after_exact_head_owner_approval": [
|
||||
"observe_governance_pr",
|
||||
"wait_governance_gates",
|
||||
"observe_governance_merge",
|
||||
"observe_validator_activation",
|
||||
"complete_policy_activation"
|
||||
],
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"registry.write",
|
||||
"baseline.write",
|
||||
"production.deploy",
|
||||
"force_push",
|
||||
"history_rewrite",
|
||||
"governance.direct_push",
|
||||
"approval.impersonate",
|
||||
"publisher.create",
|
||||
"writer.create",
|
||||
"credential.project",
|
||||
"phase_b.execute"
|
||||
],
|
||||
"merge_constraints": {
|
||||
"allowed_modes": [
|
||||
"FAST_FORWARD_TO_APPROVED_HEAD",
|
||||
"EXACT_TWO_PARENT_MERGE_WITH_APPROVED_TREE"
|
||||
],
|
||||
"force": false,
|
||||
"plus_refspec": false,
|
||||
"tags": false,
|
||||
"prune": false
|
||||
},
|
||||
"governance_declarations": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"force_push_used": false,
|
||||
"tag_rewritten": false,
|
||||
"direct_main_push": false,
|
||||
"secrets_committed": false,
|
||||
"owner_approval_respected": true
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"approval_type": "TASK_STATUS_MERGE_BROKER_BOOTSTRAP",
|
||||
"schema_version": 1,
|
||||
"repository": "aios/aios",
|
||||
"expected_governance_base_oid": "8814dff20222625b60454c613b61ccf15fa20e51",
|
||||
"request_branch": "governance/bootstrap/task-status-merge-broker-20260801t0036z",
|
||||
"issued_at": "2026-08-01T00:46:50Z",
|
||||
"expires_at": "2026-08-01T12:46:50Z",
|
||||
"required_human_approvals": 1,
|
||||
"allowed_human_approvers": ["owner"],
|
||||
"require_latest_head_approval": true,
|
||||
"purpose": "Activate a task-scoped credential, status, and fast-forward-only merge broker so a new V2R1C4 Phase B renewal can satisfy existing branch protection without impersonation or long-lived credentials.",
|
||||
"phase_b_transition": {
|
||||
"old_pr_number": 36,
|
||||
"old_head_oid": "a8644fc172bd8ebbba17a16e6bf586c93fd1e793",
|
||||
"reuse_after_governance_base_change": false,
|
||||
"renewal_required_after_bootstrap_merge": true
|
||||
},
|
||||
"allowed_status_contexts": [
|
||||
"aios/branch-protection",
|
||||
"aios/evidence-closure",
|
||||
"aios/secret-scan",
|
||||
"aios/state-machine",
|
||||
"aios/validator"
|
||||
],
|
||||
"allowed_identities": ["codex", "gpt"],
|
||||
"allowed_operations": [
|
||||
"issue_task_status_credential",
|
||||
"issue_task_merge_credential",
|
||||
"sign_task_grant_after_owner_exact_head_review",
|
||||
"publish_exact_five_statuses",
|
||||
"fast_forward_only_merge",
|
||||
"readback_status_and_ref",
|
||||
"revoke_task_credentials",
|
||||
"remove_credential_projection"
|
||||
,"sweep_completed_or_expired_task_credentials"
|
||||
],
|
||||
"operation_limits": {
|
||||
"maximum_status_writes_per_grant": 5,
|
||||
"maximum_merges_per_grant": 1,
|
||||
"maximum_grant_lifetime_seconds": 43200,
|
||||
"automatic_revocation_required": true
|
||||
},
|
||||
"denied_operations": [
|
||||
"branch_push",
|
||||
"main_push",
|
||||
"tag_write",
|
||||
"registry_write",
|
||||
"baseline_write",
|
||||
"production_write",
|
||||
"branch_protection_change",
|
||||
"force_push",
|
||||
"squash",
|
||||
"rebase",
|
||||
"merge_commit",
|
||||
"approval_impersonation",
|
||||
"plaintext_secret_persistence"
|
||||
,"sign_unapproved_grant"
|
||||
,"reuse_superseded_pr"
|
||||
,"grant_signing_private_key_projection_to_broker"
|
||||
,"commit_status_database_write"
|
||||
,"database_write_outside_exact_access_token_revocation"
|
||||
],
|
||||
"runtime_controls": {
|
||||
"global_gitops_writes_enabled": false,
|
||||
"runtime_secret_only": true,
|
||||
"systemd_encrypted_credentials_required": true,
|
||||
"token_in_argv_allowed": false,
|
||||
"token_in_log_allowed": false,
|
||||
"separate_non_root_status_identity": true,
|
||||
"separate_non_root_merge_identity": true,
|
||||
"root_credential_broker_only": true,
|
||||
"sqlite_quota_and_hash_chain_audit": true,
|
||||
"hmac_audit_signature": true,
|
||||
"detached_ssh_grant_signature_required": true,
|
||||
"broker_receives_public_verification_key_only": true,
|
||||
"grant_signing_requires_live_owner_exact_head_review": true,
|
||||
"grant_signing_requires_open_pr_exact_head_base_tree_manifest": true,
|
||||
"status_evidence_digest_bound_in_signed_grant": true,
|
||||
"credential_issue_rechecks_local_pr_review_ref_tree_manifest": true,
|
||||
"gitea_write_repository_scope_compensated_by_locked_broker_sandbox": true,
|
||||
"token_revocation_exact_row_and_http_401_required": true,
|
||||
"gitea_1_22_token_delete_requires_basic_auth": true,
|
||||
"exact_access_token_row_revocation_exception": true,
|
||||
"access_token_revocation_binding_fields": ["id", "uid", "name", "scope"],
|
||||
"commit_status_database_write_allowed": false,
|
||||
"credential_completion_and_expiry_sweep_interval_seconds": 60,
|
||||
"sweeper_uses_same_per_task_audit_credential_as_issuer": true,
|
||||
"gitea_api_origin": "http://127.0.0.1:3000/api/v1",
|
||||
"merge_method": "fast-forward-only"
|
||||
},
|
||||
"approved_files": {
|
||||
"services/aios-single-owner-governance/aios_single_owner_governance/task_status_merge_broker.py": "79a7b6807dc9e6c167c94adbd3bb4a1b9ae17e54d2d6fd19bd6a38ce2f8b8e3f",
|
||||
"services/aios-single-owner-governance/aios_single_owner_governance/task_credential_broker.py": "678fccd8e61fa1806d44fbb81fe7f6e2a7b63bbd99d1323516073100b6e48ab5",
|
||||
"services/aios-single-owner-governance/aios_single_owner_governance/task_credential_expiry_sweeper.py": "8d383768eb0322c84a35282c126bee26a3e6419b125780424ffc7793a504efdf",
|
||||
"services/aios-single-owner-governance/task-status-merge-grant-v1.schema.json": "4528aa6dfeaa151deadb54bf1c462e1ff3e9526e0da3eb20144e6c01c19998f0",
|
||||
"tests/single_owner_governance/test_task_status_merge_broker.py": "65a285b29798b72d13e30562ce97529780643f3739e5d07c283dfa5995035dc4",
|
||||
"deploy/systemd/aios-task-status-broker@.service": "378a2e8f658cb56cac5dcc151772ec6a00d86f6c1ce3106509b9aa87549dc9da",
|
||||
"deploy/systemd/aios-task-merge-broker@.service": "4e6b8fcf541f225e58ea080107fc30deb0c4ac9eac70217ff9e57081245c106a",
|
||||
"deploy/systemd/aios-task-credential-broker@.service": "ec5dd2be87f3e02af89a40a615ccbd76a277f46aa29cc1a92fee5496d750cbce",
|
||||
"deploy/systemd/aios-task-credential-expiry-sweeper.service": "39726537a3b4f57614eba678309fd3009c8fa25448458827aef7ece0015be10d",
|
||||
"deploy/systemd/aios-task-credential-expiry-sweeper.timer": "49ff9c80cbd0b44fd584dc7d29f4db0d042e33f325b1ed7af81a5be42f1cd011"
|
||||
},
|
||||
"machine_gate_requirements": {
|
||||
"compileall": "PASS",
|
||||
"unit_tests": "PASS",
|
||||
"json_schema": "PASS",
|
||||
"systemd_validation": "PASS",
|
||||
"secret_scan": "PASS",
|
||||
"fault_injection": "PASS",
|
||||
"scope_boundary_tests": "PASS"
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"acknowledges_pr30_owner_approval_was_missing": true,
|
||||
"activation_prerequisites_artifact_sha256": "729077800c6510bf8930c97a78781218d1bce9ec40157aa99fc2bd205466e895",
|
||||
"activation_prerequisites_commit_oid": "fa038d17b29001e26f1ac88019a407a4b3ebaa7e",
|
||||
"activation_prerequisites_rollback_artifact_sha256": "00e40eace10a0aae1731eb98851fec71a0c13c48e1e6e5a113e30a4356c2086f",
|
||||
"activation_prerequisites_tree_oid": "d5ff67f848807ef2c7a695c05cdd0bb5f2644fc2",
|
||||
"approval_request_branch": "governance/request/single-owner-atomic-activation-owner-ratification-20260729T014918Z-e503d96665ee",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_ATOMIC_ACTIVATION_OWNER_RATIFICATION",
|
||||
"branch_protection_adapter_sha256": "2706dc6095ff639838f72c91a66c1f80711893c8c0498555b388feaacf2db569",
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"registry.write",
|
||||
"baseline.write",
|
||||
"production.deploy",
|
||||
"force_push",
|
||||
"history_rewrite",
|
||||
"governance.direct_push",
|
||||
"approval.impersonate"
|
||||
],
|
||||
"direct_protected_branch_push_allowed": false,
|
||||
"dismiss_stale_approvals": true,
|
||||
"dormant_deployment_evidence_sha256": "c4c326784a3d66d62e32c46be3506c801585c06a34e62c9a1f210492a6c1bc06",
|
||||
"evidence_closure_oid": "5f45139ca5f7f7f3da244141c5115d12f5af58ae",
|
||||
"evidence_closure_sha256": "53e5f2fdc01a6225048dfdf6eac973e99743f0295f17f3a42f01dce7e7050ab8",
|
||||
"expected_governance_base_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
|
||||
"expires_at": "2026-07-29T13:49:18Z",
|
||||
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
|
||||
"approval_validator.activate",
|
||||
"governance_state_machine.activate",
|
||||
"gitea_branch_protection.atomic_update",
|
||||
"rollback_configuration.install",
|
||||
"single_owner_policy.activate",
|
||||
"break_glass.expire",
|
||||
"post_activation_tests.execute"
|
||||
],
|
||||
"force_push_allowed": false,
|
||||
"human_authorizer": "owner",
|
||||
"issued_at": "2026-07-29T01:49:18Z",
|
||||
"legacy_mechanical_approvals": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"merge_mode": "CREATE_MERGE_COMMIT",
|
||||
"pr30_codex_approval_review_id": 45,
|
||||
"pr30_codex_reviewed_at": "2026-07-29T01:24:38Z",
|
||||
"pr30_codex_reviewed_head_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
|
||||
"pr30_gpt_approval_review_id": 46,
|
||||
"pr30_gpt_reviewed_at": "2026-07-29T01:25:02Z",
|
||||
"pr30_gpt_reviewed_head_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
|
||||
"pr30_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-ATOMIC-ACTIVATION-20260728T204808Z-4cab1d5829d6.json",
|
||||
"pr30_merge_tree_oid": "219974f085efe473fcc6ad2170f67312d8e57c54",
|
||||
"pr30_merged_at": "2026-07-29T01:25:08Z",
|
||||
"pr30_owner_review_id": 42,
|
||||
"pr30_owner_review_state_observed": "REQUESTED_NOT_APPROVED",
|
||||
"pr30_owner_reviewed_head_oid": null,
|
||||
"pr30_premerge_base_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
|
||||
"production_deployment_allowed": false,
|
||||
"ratifies_pr30_manifest_blob_oid": "38c95dde2d3831f8e3c80b342369f1c3e1cbf34c",
|
||||
"ratifies_pr30_manifest_sha256": "bc19ada0e8eeb47d421a6360cf1d66b6d1129eb6056a447d9ff70ebd5ada1718",
|
||||
"ratifies_pr30_merge_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
|
||||
"ratifies_pr30_request_oid": "c2eed5b37983a6461783361efb6de43a28f909bb",
|
||||
"ratifies_pr_number": 30,
|
||||
"require_latest_head_approval": true,
|
||||
"required_reviewers": [
|
||||
"owner",
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"rollback_configuration_sha256": "eb44fc5f655f8c30c4b687185055ba3a2725189e19538e3a9a46a2c0cf141b8c",
|
||||
"schema": "aios.governance-approval/v1",
|
||||
"state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
|
||||
"task_id": "AIOS-PR30-SINGLE-OWNER-ATOMIC-ACTIVATION-OWNER-RATIFICATION-20260729",
|
||||
"test_evidence_sha256": "42168da7437028440bece3432d8aa38a8722b4db18244423d9daaa380675c45a",
|
||||
"validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
|
||||
"wip_blocks_merge": true
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"approval_request_branch": "governance/request/single-owner-governance-activation-prerequisites-20260728T183025127107Z",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_ACTIVATION_PREREQUISITES",
|
||||
"binds_final_ratification_manifest_blob_oid": "2865fbec766901eb61fc8aed0542970e951e0d1d",
|
||||
"binds_final_ratification_manifest_sha256": "216e54503d8e6a3f4c908084e19ce1e6242d3ba15f7b8011a9a9d9f7975e63e7",
|
||||
"binds_final_ratification_merge_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
|
||||
"binds_mirror_receipt_sha256": "6873133f7233bfed0d3b78b01847ad4251b8b67f3b6db7011efd07664f8d088f",
|
||||
"expected_governance_base_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
|
||||
"expires_at": "2026-07-29T06:30:25Z",
|
||||
"explicitly_allowed_after_owner_approval_and_legacy_merge": [
|
||||
"task_bound_activation_writer_grant.create",
|
||||
"gitea_owner_review_adapter.create_and_dormant_deploy",
|
||||
"machine_status_producer.create_and_dormant_deploy",
|
||||
"machine_status_producer.credential_rotation_and_revocation",
|
||||
"maintenance_lock.create",
|
||||
"branch_protection_compensation_saga.create",
|
||||
"targeted_online_rollback_executor.create",
|
||||
"disposable_gitea_fixture.create_test_destroy",
|
||||
"single_owner_activation_prerequisite_tests.execute",
|
||||
"activation_prerequisite_evidence.create"
|
||||
],
|
||||
"implementation_branch": "patch/single-owner-governance-activation-prerequisites-20260729",
|
||||
"implementation_paths": [
|
||||
"services/aios-single-owner-governance/**",
|
||||
"tests/single_owner_governance/**",
|
||||
"deploy/systemd/aios-governance-*.service",
|
||||
"deploy/systemd/aios-governance-*.timer"
|
||||
],
|
||||
"issued_at": "2026-07-28T18:30:25Z",
|
||||
"machine_status_contexts": [
|
||||
"aios/machine-gates",
|
||||
"aios/secret-scan",
|
||||
"aios/evidence-closure"
|
||||
],
|
||||
"observed_blockers": {
|
||||
"commit_status_row_count": 0,
|
||||
"disposable_governance_fixture_present": false,
|
||||
"gitea_owner_review_validator_present": false,
|
||||
"gitea_version": "1.22.6",
|
||||
"native_branch_protection_etag_cas_present": false,
|
||||
"required_status_context_producers_present": false,
|
||||
"targeted_online_rollback_executor_present": false
|
||||
},
|
||||
"owner_approval_contract": {
|
||||
"agent_must_not_submit_review": true,
|
||||
"dismissed": false,
|
||||
"head_change_invalidates_approval": true,
|
||||
"only_human_approver": "owner",
|
||||
"owner_user_id": 2,
|
||||
"review_state": "APPROVED",
|
||||
"reviewed_before_expires_at": true,
|
||||
"reviewed_head_oid_must_equal_current_head_oid": true,
|
||||
"stale": false
|
||||
},
|
||||
"permanent_constraints": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"direct_main_push": false,
|
||||
"force_push": false,
|
||||
"history_rewrite": false,
|
||||
"secret_commit": false,
|
||||
"tag_rewrite": false
|
||||
},
|
||||
"pre_approval_non_authorizations": {
|
||||
"activation_allowed": false,
|
||||
"baseline_write_allowed": false,
|
||||
"branch_protection_change_allowed": false,
|
||||
"fixture_deployment_allowed": false,
|
||||
"integration_write_allowed": false,
|
||||
"main_write_allowed": false,
|
||||
"merge_allowed": false,
|
||||
"production_write_allowed": false,
|
||||
"registry_write_allowed": false,
|
||||
"tag_write_allowed": false,
|
||||
"writer_grant_allowed": false
|
||||
},
|
||||
"reason": "safe-atomic-activation-prerequisites-absent",
|
||||
"repository": "aios/aios",
|
||||
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
|
||||
"schema": "aios.single-owner-governance-activation-prerequisites/v1",
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-PREREQUISITES-20260729",
|
||||
"wip": true,
|
||||
"wip_transition_contract": {
|
||||
"codex_and_gpt_not_requested_before_owner_approval": true,
|
||||
"remove_wip_without_head_change_only_after_owner_approval": true,
|
||||
"then_request_legacy_mechanical_reviews": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"wip_must_remain_until_owner_exact_head_approval": true
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"activation_prerequisites_artifact_sha256": "729077800c6510bf8930c97a78781218d1bce9ec40157aa99fc2bd205466e895",
|
||||
"activation_prerequisites_commit_oid": "fa038d17b29001e26f1ac88019a407a4b3ebaa7e",
|
||||
"activation_prerequisites_rollback_artifact_sha256": "00e40eace10a0aae1731eb98851fec71a0c13c48e1e6e5a113e30a4356c2086f",
|
||||
"activation_prerequisites_tree_oid": "d5ff67f848807ef2c7a695c05cdd0bb5f2644fc2",
|
||||
"approval_request_branch": "governance/request/single-owner-governance-atomic-activation-20260728T204808Z-4cab1d5829d6",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_ATOMIC_ACTIVATION",
|
||||
"branch_protection_adapter_sha256": "2706dc6095ff639838f72c91a66c1f80711893c8c0498555b388feaacf2db569",
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"registry.write",
|
||||
"baseline.write",
|
||||
"production.deploy",
|
||||
"force_push",
|
||||
"history_rewrite",
|
||||
"governance.direct_push",
|
||||
"approval.impersonate"
|
||||
],
|
||||
"deployment_mode_before_execution": "DORMANT_SHADOW_ONLY",
|
||||
"direct_protected_branch_push_allowed": false,
|
||||
"dismiss_stale_approvals": true,
|
||||
"dormant_deployment_evidence_sha256": "c4c326784a3d66d62e32c46be3506c801585c06a34e62c9a1f210492a6c1bc06",
|
||||
"evidence_closure_oid": "5f45139ca5f7f7f3da244141c5115d12f5af58ae",
|
||||
"evidence_closure_sha256": "53e5f2fdc01a6225048dfdf6eac973e99743f0295f17f3a42f01dce7e7050ab8",
|
||||
"expected_governance_base_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
|
||||
"expires_at": "2026-07-29T08:48:08Z",
|
||||
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
|
||||
"approval_validator.activate",
|
||||
"governance_state_machine.activate",
|
||||
"gitea_branch_protection.atomic_update",
|
||||
"rollback_configuration.install",
|
||||
"single_owner_policy.activate",
|
||||
"break_glass.expire",
|
||||
"post_activation_tests.execute"
|
||||
],
|
||||
"force_push_allowed": false,
|
||||
"issued_at": "2026-07-28T20:48:08Z",
|
||||
"legacy_mechanical_approvals": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"machine_gates_required": true,
|
||||
"merge_mode": "CREATE_MERGE_COMMIT",
|
||||
"pr26_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"pr27_merge_oid": "4e6ef70029b1d94626e432892f7d3beb8e3e5627",
|
||||
"pr28_merge_oid": "2bef44f6bc8cf7bc04c959ab629ac95561fa609f",
|
||||
"pr29_merge_oid": "6e8212608ee310e2fb45f1e802359f4db2e9077b",
|
||||
"production_deployment_allowed": false,
|
||||
"require_latest_head_approval": true,
|
||||
"required_human_authorizer": "owner",
|
||||
"required_reviewers": [
|
||||
"owner",
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"rollback_configuration_sha256": "eb44fc5f655f8c30c4b687185055ba3a2725189e19538e3a9a46a2c0cf141b8c",
|
||||
"rollback_required_on_any_activation_failure": true,
|
||||
"schema": "aios.governance-approval/v1",
|
||||
"single_owner_policy_active_before_execution": false,
|
||||
"state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ATOMIC-ACTIVATION-20260729",
|
||||
"test_evidence_sha256": "42168da7437028440bece3432d8aa38a8722b4db18244423d9daaa380675c45a",
|
||||
"validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
|
||||
"wip_blocks_merge": true
|
||||
}
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
{
|
||||
"acknowledges_pr26_owner_approval_was_missing": true,
|
||||
"approval_request_branch": "governance/request/single-owner-control-plane-deployment-20260728T170740Z-ea7a102dac417c23",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_CONTROL_PLANE_DEPLOYMENT",
|
||||
"control_plane_targets": {
|
||||
"allowed_human_approvers": [
|
||||
"owner"
|
||||
],
|
||||
"branch_deletion": false,
|
||||
"direct_protected_branch_push": false,
|
||||
"dismiss_stale_approvals": true,
|
||||
"executor_must_not_approve": true,
|
||||
"force_push": false,
|
||||
"governance_model": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
|
||||
"historical_records_immutable": true,
|
||||
"machine_gates_required": true,
|
||||
"policy_effective_at_set_only_after_activation_tests_pass": true,
|
||||
"protected_branches": [
|
||||
"governance/approvals",
|
||||
"main",
|
||||
"release/**",
|
||||
"integration/**"
|
||||
],
|
||||
"requester_must_not_approve": true,
|
||||
"require_approval_for_latest_commit": true,
|
||||
"required_human_approvals": 1,
|
||||
"required_owner_approvals": 1,
|
||||
"required_status_contexts": [
|
||||
"aios/machine-gates",
|
||||
"aios/secret-scan",
|
||||
"aios/evidence-closure"
|
||||
],
|
||||
"tag_rewrite": false,
|
||||
"wip_blocks_merge": true
|
||||
},
|
||||
"does_not_claim_pr26_met_old_two_natural_person_policy": true,
|
||||
"expected_authoritative_governance_base_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
|
||||
"expected_gitea_governance_base_oid": "a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"expires_at": "2026-07-29T05:07:40Z",
|
||||
"explicitly_allowed_operations_after_exact_head_approvals_and_merge": [
|
||||
"approval_mirror.fast_forward_governance_only",
|
||||
"approval_validator.update",
|
||||
"state_machine.update",
|
||||
"gitea_branch_protection.update_via_authenticated_api_compare_and_swap",
|
||||
"governance_policy.activate",
|
||||
"rollback_configuration.install",
|
||||
"governance_acceptance_tests.execute",
|
||||
"single_owner_governance_activation_receipt.create"
|
||||
],
|
||||
"explicitly_denied_operations": [
|
||||
"force_push",
|
||||
"plus_refspec",
|
||||
"tag_fetch",
|
||||
"prune",
|
||||
"direct_git_database_write",
|
||||
"direct_protected_ref_push",
|
||||
"main_write",
|
||||
"integration_write",
|
||||
"tag_write",
|
||||
"registry_write",
|
||||
"baseline_write",
|
||||
"production_write",
|
||||
"history_rewrite",
|
||||
"branch_delete",
|
||||
"secret_read",
|
||||
"approval_impersonation"
|
||||
],
|
||||
"global_constraints": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"direct_main_push": false,
|
||||
"force_push_used": false,
|
||||
"owner_approval_respected": true,
|
||||
"secrets_committed": false,
|
||||
"tag_rewritten": false
|
||||
},
|
||||
"implementation_surface": {
|
||||
"approval_validator": [
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py",
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py",
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py"
|
||||
],
|
||||
"runtime": [
|
||||
"active-runtime/app/silent_release_controller.py",
|
||||
"active-runtime/app/silent_release_hardening.py"
|
||||
],
|
||||
"state_machine": [
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py",
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py",
|
||||
"services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py"
|
||||
],
|
||||
"systemd": [
|
||||
"deploy/systemd/aios-autonomous-release-candidate.service",
|
||||
"deploy/systemd/aios-silent-release-controller.service"
|
||||
]
|
||||
},
|
||||
"issued_at": "2026-07-28T17:07:40Z",
|
||||
"legacy_gitea_protection_gate": {
|
||||
"account_reviews_do_not_prove_distinct_natural_persons": true,
|
||||
"both_must_approve_this_exact_head": true,
|
||||
"current_approval_whitelist": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"current_required_approvals": 2
|
||||
},
|
||||
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET_RATIFICATION",
|
||||
"mirror_contract": {
|
||||
"expected_chain_contains_policy_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"expected_pre_sync_authoritative_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
|
||||
"fast_forward_only": true,
|
||||
"force": false,
|
||||
"fsck_connectivity_only_required": true,
|
||||
"only_ref": "refs/heads/governance/approvals",
|
||||
"plus_refspec": false,
|
||||
"prune": false,
|
||||
"quarantine_required": true,
|
||||
"source": "gitea_repository_file_url_only",
|
||||
"tags": false
|
||||
},
|
||||
"owner_break_glass_ratification": {
|
||||
"attests_reason": "single-maintainer-system",
|
||||
"attests_scope": "governance-policy-migration-only",
|
||||
"created_before_expires_at": true,
|
||||
"dismissed": false,
|
||||
"required": true,
|
||||
"review_state": "APPROVED",
|
||||
"reviewed_head_oid_must_equal_current_pr_head_oid": true,
|
||||
"reviewer_user_id": 2,
|
||||
"reviewer_username": "owner",
|
||||
"stale": false
|
||||
},
|
||||
"pre_approval_non_authorizations": {
|
||||
"approval_validator_update_allowed": false,
|
||||
"development_allowed": false,
|
||||
"gitea_branch_protection_update_allowed": false,
|
||||
"governance_policy_activation_allowed": false,
|
||||
"merge_allowed": false,
|
||||
"mirror_allowed": false,
|
||||
"production_change_allowed": false,
|
||||
"rollback_install_allowed": false,
|
||||
"standing_writer_policy_allowed": false,
|
||||
"state_machine_update_allowed": false
|
||||
},
|
||||
"pre_cutover_protection_snapshot": {
|
||||
"protected_branch": [
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "governance/approvals",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 1,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 3,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "main",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 2,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
}
|
||||
],
|
||||
"protected_tag": []
|
||||
},
|
||||
"pre_cutover_protection_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
|
||||
"ratifies_policy_manifest_blob_oid": "65f44007b10fc2a912d69e3f9081c0cfff77dfad",
|
||||
"ratifies_policy_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-MIGRATION-20260728T162246Z.json",
|
||||
"ratifies_policy_manifest_sha256": "c097475afbe3074e6482f125b635981f8c0284f3d763c926e2a63e1a3ee1c6c3",
|
||||
"ratifies_policy_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"ratifies_policy_pr_number": 26,
|
||||
"ratifies_policy_request_oid": "312d3b483049a748675e887a516ec739c81ff474",
|
||||
"ratifies_policy_tree_oid": "5c6974c058bba6210dcc1bdd0968fb7e6c84a844",
|
||||
"repository": "aios/aios",
|
||||
"request_status": "HUMAN_OWNER_AND_LEGACY_PROTECTION_APPROVAL_PENDING",
|
||||
"required_machine_gates": [
|
||||
"owner_exact_head_review_valid",
|
||||
"legacy_protection_reviews_valid",
|
||||
"ordinary_merge_commit",
|
||||
"parent_order_verified",
|
||||
"manifest_add_only",
|
||||
"quarantine_verification",
|
||||
"approval_mirror_fast_forward",
|
||||
"validator_tests",
|
||||
"state_machine_tests",
|
||||
"protection_compare_and_swap",
|
||||
"positive_governance_tests",
|
||||
"negative_governance_tests",
|
||||
"secret_scan",
|
||||
"rollback_integrity",
|
||||
"production_write_false"
|
||||
],
|
||||
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
|
||||
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
|
||||
"schema": "aios.single-owner-governance-control-plane-deployment/v1",
|
||||
"scope": "pr26-ratification-mirror-and-single-owner-control-plane-deployment-only",
|
||||
"task_id": "AIOS-SINGLE-OWNER-CONTROL-PLANE-DEPLOYMENT-20260729"
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
{
|
||||
"acknowledges_pr26_and_pr27_owner_approval_was_missing": true,
|
||||
"approval_request_branch": "governance/request/single-owner-governance-final-owner-ratification-20260728T173634412838Z",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_FINAL_OWNER_RATIFICATION",
|
||||
"backup_checksums_sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
|
||||
"backup_root": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/pre-migration-backup",
|
||||
"break_glass_expires_immediately_after_activation": true,
|
||||
"does_not_claim_old_two_natural_person_compliance": true,
|
||||
"expires_at": "2026-07-29T05:36:34Z",
|
||||
"inherits_only_pr27_control_plane_allowlist": [
|
||||
"approval_mirror.fast_forward_governance_only",
|
||||
"approval_validator.update",
|
||||
"state_machine.update",
|
||||
"gitea_branch_protection.update_via_authenticated_api_compare_and_swap",
|
||||
"governance_policy.activate",
|
||||
"rollback_configuration.install",
|
||||
"governance_acceptance_tests.execute",
|
||||
"single_owner_governance_activation_receipt.create"
|
||||
],
|
||||
"issued_at": "2026-07-28T17:36:34Z",
|
||||
"legacy_mechanical_protection_gate": {
|
||||
"account_reviews_do_not_count_as_owner_ratification": true,
|
||||
"account_reviews_do_not_prove_distinct_natural_persons": true,
|
||||
"approval_and_merge_whitelist_user_ids": [
|
||||
42,
|
||||
43
|
||||
],
|
||||
"both_reviews_must_bind_current_request_head": true,
|
||||
"required_approvals": 2,
|
||||
"reviewers": [
|
||||
"codex",
|
||||
"gpt"
|
||||
]
|
||||
},
|
||||
"merge_contract": {
|
||||
"first_parent_must_equal_premerge_governance_oid": true,
|
||||
"force": false,
|
||||
"merge_mode": "CREATE_MERGE_COMMIT",
|
||||
"parent_count": 2,
|
||||
"rebase": false,
|
||||
"second_parent_must_equal_final_ratification_request_oid": true,
|
||||
"single_file_add_only": true,
|
||||
"squash": false
|
||||
},
|
||||
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET",
|
||||
"mirror_contract": {
|
||||
"expected_authoritative_pre_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
|
||||
"fast_forward_only": true,
|
||||
"force": false,
|
||||
"fsck_connectivity_only_required": true,
|
||||
"only_ref": "refs/heads/governance/approvals",
|
||||
"plus_refspec": false,
|
||||
"prune": false,
|
||||
"quarantine_required": true,
|
||||
"required_chain": [
|
||||
"ac2dc5c30eb35748ef11c98297812729d0fd5828",
|
||||
"a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"4e6ef70029b1d94626e432892f7d3beb8e3e5627",
|
||||
"FINAL_RATIFICATION_MERGE_OID"
|
||||
],
|
||||
"source": "gitea_repository_file_url_only",
|
||||
"tags": false
|
||||
},
|
||||
"owner_ratification_contract": {
|
||||
"agent_must_not_submit_review": true,
|
||||
"dismissed": false,
|
||||
"only_valid_human_approver": "owner",
|
||||
"owner_user_id": 2,
|
||||
"review_state": "APPROVED",
|
||||
"review_type_must_be_approved_not_requested": true,
|
||||
"reviewed_before_expires_at": true,
|
||||
"reviewed_before_merge": true,
|
||||
"reviewed_head_oid_must_equal_current_request_head_oid": true,
|
||||
"stale": false
|
||||
},
|
||||
"permanent_constraints": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"direct_main_push": false,
|
||||
"force_push_used": false,
|
||||
"owner_approval_respected": true,
|
||||
"secrets_committed": false,
|
||||
"tag_rewritten": false
|
||||
},
|
||||
"post_merge_activation_preconditions": [
|
||||
"owner_exact_head_approval_valid",
|
||||
"legacy_mechanical_reviews_valid",
|
||||
"ordinary_merge_commit",
|
||||
"one_file_add_only",
|
||||
"quarantine_chain_verified",
|
||||
"approval_mirror_fast_forward_closed",
|
||||
"rollback_integrity_pass",
|
||||
"validator_and_state_machine_tests_pass",
|
||||
"protection_compare_and_swap_pass",
|
||||
"positive_and_negative_governance_tests_pass",
|
||||
"production_write_false"
|
||||
],
|
||||
"pre_activation_protection_snapshot": {
|
||||
"protected_branch": [
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "governance/approvals",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 1,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 3,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "main",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 2,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
}
|
||||
],
|
||||
"protected_tag": []
|
||||
},
|
||||
"pre_activation_protection_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
|
||||
"pre_approval_non_authorizations": {
|
||||
"baseline_write_allowed": false,
|
||||
"branch_protection_update_allowed": false,
|
||||
"control_plane_activation_allowed": false,
|
||||
"development_allowed": false,
|
||||
"integration_write_allowed": false,
|
||||
"main_write_allowed": false,
|
||||
"merge_allowed": false,
|
||||
"mirror_allowed": false,
|
||||
"production_write_allowed": false,
|
||||
"registry_write_allowed": false,
|
||||
"rollback_install_allowed": false,
|
||||
"standing_writer_allowed": false,
|
||||
"state_machine_update_allowed": false,
|
||||
"tag_write_allowed": false,
|
||||
"validator_update_allowed": false
|
||||
},
|
||||
"ratification_scope": "GOVERNANCE_MIGRATION_AND_CONTROL_PLANE_ACTIVATION_ONLY",
|
||||
"ratifies_pr26_manifest_blob_oid": "65f44007b10fc2a912d69e3f9081c0cfff77dfad",
|
||||
"ratifies_pr26_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-MIGRATION-20260728T162246Z.json",
|
||||
"ratifies_pr26_manifest_sha256": "c097475afbe3074e6482f125b635981f8c0284f3d763c926e2a63e1a3ee1c6c3",
|
||||
"ratifies_pr26_merge_oid": "a5489f1b67870622162b2daa781bd0237735831a",
|
||||
"ratifies_pr26_request_oid": "312d3b483049a748675e887a516ec739c81ff474",
|
||||
"ratifies_pr26_tree_oid": "5c6974c058bba6210dcc1bdd0968fb7e6c84a844",
|
||||
"ratifies_pr27_manifest_blob_oid": "77f3c2ab85cba2c30c8c0aa36e591232d0f4c396",
|
||||
"ratifies_pr27_manifest_path": "approvals/governance-policy/SINGLE-OWNER-GOVERNANCE-CONTROL-PLANE-DEPLOYMENT-20260728T170740Z-ea7a102dac417c23.json",
|
||||
"ratifies_pr27_manifest_sha256": "2ed09180c0aeadbef2e5d6310efe7c2d0de15e0e87b6135e7a8494cb4f0967c7",
|
||||
"ratifies_pr27_merge_oid": "4e6ef70029b1d94626e432892f7d3beb8e3e5627",
|
||||
"ratifies_pr27_request_oid": "80feef309fd8e1db7795f68d5bf0f15ce805b365",
|
||||
"ratifies_pr27_tree_oid": "85af0d1e88e8484a9c3a0562a81cbc1de09250ae",
|
||||
"ratifies_pr_numbers": [
|
||||
26,
|
||||
27
|
||||
],
|
||||
"repository": "aios/aios",
|
||||
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
|
||||
"retroactive_authorization_for_other_operations": false,
|
||||
"rollback_archive_member_hashes": {
|
||||
"pre-migration-backup/app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
|
||||
"pre-migration-backup/authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
|
||||
"pre-migration-backup/authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
|
||||
"pre-migration-backup/backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
|
||||
"pre-migration-backup/checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
|
||||
"pre-migration-backup/gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
|
||||
"pre-migration-backup/gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
|
||||
"pre-migration-backup/gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
|
||||
"pre-migration-backup/governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
|
||||
"pre-migration-backup/protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
|
||||
"pre-migration-backup/protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"pre-migration-backup/repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
|
||||
"pre-migration-backup/repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
|
||||
"pre-migration-backup/repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
|
||||
"pre-migration-backup/repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
|
||||
"pre-migration-backup/repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
|
||||
},
|
||||
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
|
||||
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
|
||||
"schema": "aios.single-owner-governance-final-owner-ratification/v1",
|
||||
"single_owner_policy_effective_at": "FINAL_RATIFICATION_MERGE_OID",
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-FINAL-RATIFICATION-20260729"
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
{
|
||||
"allowed_human_approvers": [
|
||||
"owner"
|
||||
],
|
||||
"approval_expires_at": "2026-07-29T16:22:46Z",
|
||||
"approval_request_branch": "governance/request/single-owner-governance-migration-20260728T162246Z",
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_POLICY",
|
||||
"approval_types_migrated_after_policy_effective_at": [
|
||||
"SOURCE_MAPPING_AND_IMPORT_EXECUTION_RENEWAL",
|
||||
"CONTROL_PLANE_DEPLOYMENT_APPROVAL",
|
||||
"DEVELOPMENT_MERGE_APPROVAL",
|
||||
"RELEASE_CANDIDATE_APPROVAL",
|
||||
"PRODUCTION_RELEASE_APPROVAL",
|
||||
"TAG_APPROVAL",
|
||||
"REGISTRY_BASELINE_PROMOTION_APPROVAL",
|
||||
"PRODUCTION_DEPLOYMENT_APPROVAL",
|
||||
"ROLLBACK_APPROVAL"
|
||||
],
|
||||
"atomic_migration": {
|
||||
"backup_checksums_sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
|
||||
"backup_root": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/pre-migration-backup",
|
||||
"direct_database_update": false,
|
||||
"direct_ref_update": false,
|
||||
"dual_capable_validator_shadow_required": true,
|
||||
"identity_snapshot_sha256": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
|
||||
"live_protection_canonical_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
|
||||
"maintenance_lock_required": true,
|
||||
"old_rules_remain_active_until_owner_approval_and_machine_gates_pass": true,
|
||||
"protected_branch_snapshot_sha256": "2bc353f34689242cabebf89856d3faab0e1c496b5d33761dfb7cbd47904516f7",
|
||||
"protection_update_method": "authenticated_admin_API_compare_and_swap",
|
||||
"reviewable_backup_file_hashes": {
|
||||
"app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
|
||||
"authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
|
||||
"authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
|
||||
"backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
|
||||
"checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
|
||||
"gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
|
||||
"gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
|
||||
"gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
|
||||
"governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
|
||||
"protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
|
||||
"protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
|
||||
"repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
|
||||
"repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
|
||||
"repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
|
||||
"repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
|
||||
"repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
|
||||
"repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
|
||||
"repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
|
||||
"repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
|
||||
"repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
|
||||
},
|
||||
"reviewable_pre_migration_governance_identity_snapshot": [
|
||||
{
|
||||
"created_unix": 1783321252,
|
||||
"id": 1,
|
||||
"is_active": 1,
|
||||
"is_admin": 0,
|
||||
"last_login_unix": 0,
|
||||
"lower_name": "aios",
|
||||
"prohibit_login": 1,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"created_unix": 1783335380,
|
||||
"id": 2,
|
||||
"is_active": 1,
|
||||
"is_admin": 1,
|
||||
"last_login_unix": 1785086126,
|
||||
"lower_name": "owner",
|
||||
"prohibit_login": 0,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"created_unix": 1783411566,
|
||||
"id": 3,
|
||||
"is_active": 1,
|
||||
"is_admin": 1,
|
||||
"last_login_unix": 0,
|
||||
"lower_name": "gito",
|
||||
"prohibit_login": 0,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"created_unix": 1785078826,
|
||||
"id": 42,
|
||||
"is_active": 1,
|
||||
"is_admin": 0,
|
||||
"last_login_unix": 1785206253,
|
||||
"lower_name": "codex",
|
||||
"prohibit_login": 0,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"created_unix": 1785078882,
|
||||
"id": 43,
|
||||
"is_active": 1,
|
||||
"is_admin": 0,
|
||||
"last_login_unix": 1785206380,
|
||||
"lower_name": "gpt",
|
||||
"prohibit_login": 0,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"reviewable_pre_migration_protection_snapshot": {
|
||||
"protected_branch": [
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "governance/approvals",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 1,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "integration/chatgpt-autonomous-completion-20260726",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 3,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
{
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[42,43]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "main",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 0,
|
||||
"enable_whitelist": 0,
|
||||
"id": 2,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 2,
|
||||
"status_check_contexts": "[]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785093422,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
}
|
||||
],
|
||||
"protected_tag": []
|
||||
},
|
||||
"rollback_archive_members": {
|
||||
"pre-migration-backup/app.ini": "0693e4fa8296a22533429339faeee2ac1856b6c966c6c1009bb139ab4784f687",
|
||||
"pre-migration-backup/authoritative-aios.bundle": "4fb4ccc979c3061065cde451af0e733326cb56fa6f860124bb73f153a60907c9",
|
||||
"pre-migration-backup/authoritative-refs.txt": "85cb664c8edf3902bebfc6c2253a3ee16cff8534f86561ba771a73df160186c6",
|
||||
"pre-migration-backup/backup-metadata.json": "a38ef6dacb52ae61c4332bf8d087f479fb0d5f51d5f636a132a711bddd6e7732",
|
||||
"pre-migration-backup/checksums.sha256": "72e2fe0b03d1011c872bb39a6cff489f08398ac7d52092f720cbbc63bcf6f753",
|
||||
"pre-migration-backup/gitea-aios.bundle": "a343c7437f3a1a2aa842dd9d986a1d3cf80691058faae978565224320ff5ed90",
|
||||
"pre-migration-backup/gitea-refs.txt": "1792b2c4f1cf1f232704601ee968e16425f926a6eaab1bdcddf273525d046e4d",
|
||||
"pre-migration-backup/gitea.db": "aadcc1587a05827ed3b2c4ffc2403f26139020cd0328afaa03f7afbf6083a2f1",
|
||||
"pre-migration-backup/governance-identities.json": "2d7b4e72d1fdf187425092089589547e0d76784c611d00f915a8c212f17d3b15",
|
||||
"pre-migration-backup/protected-branch.json": "5cc4ae4fe5614baa3d4bb83d71872a4ad1ce3c5e39061e02b336be40d5b5b75d",
|
||||
"pre-migration-backup/protected-tag.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"pre-migration-backup/repository/active-runtime/app/aios_isolated_writer_policy.py": "d86ec23fd5d8b7e9844c0895c50385b6f8f3071c3dac3c0f26c70768ae00a188",
|
||||
"pre-migration-backup/repository/active-runtime/app/isolated_writer_authz.py": "cfae1cdf70c1dabbe013e9365c308a45f11acf20035881a3bb6143774682bbf0",
|
||||
"pre-migration-backup/repository/active-runtime/app/isolated_writer_path_policy.py": "c6c9ea8e45dfc03c4703503f4dc9c92f887bbacdbf1c7779a487567eee6c257c",
|
||||
"pre-migration-backup/repository/active-runtime/app/silent_release_controller.py": "524a0a9961b15c2a35b669d1b89b2142377c13ddd3c721780f374331b7d2b6eb",
|
||||
"pre-migration-backup/repository/active-runtime/app/silent_release_hardening.py": "524aba7034f2cd89d897fe01e9799c835bae9f11ca738182ce469aa59e05cc1a",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/approval.py": "cc937a81aef881206cb1d6fd2ad1feb1a1c2e0ad91c908095d56fd96402c3373",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/models.py": "aa3b3dd41c03c17e4e116ce444d9f4f779694a9cde684e8329cf892bd319069a",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/policy.py": "24b3f3326e6dcd1a4c376d892c53ad20c68e0dd6f861a3a34e11c9a2bba4c756",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/release.py": "db535e5006f8e4a3ab80c2f689213045c120b01cda9b43ef461a3022096c9d19",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/store.py": "31e1f3b904b0bfc8822d21bfd166a45388f122398d1ec76b803e90ee06dc92f0",
|
||||
"pre-migration-backup/repository/services/aios-autonomous-release-candidate/aios_autonomous_release_candidate/workflow.py": "5f6a8e3a4d66f47717e95842f2eaa443e3cfa321cb08026cc82d74c4ad353bcf",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_core_contracts.py": "71852070db50a04901c141213cadc987ae17ec678fe27a901fee165b6d1c3e2a",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_external_gates.py": "91cca37eb1d40f0cf9fc38b12e2123045ffebd794a34d6cdef3f1dec470fffd2",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_release_gates.py": "d82b23ac00f5389f1a0de628bda9dff898d33f80d375cf6ff74f1531fd138134",
|
||||
"pre-migration-backup/repository/tests/autonomous_release/test_state_and_workflow.py": "c0395a901732adb0b2f1402e6a1cf5202d54aa597bcaec9584a7ea7589c53917"
|
||||
},
|
||||
"rollback_configuration_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729/rollback-configuration.tar",
|
||||
"rollback_configuration_sha256": "fc8dcf68aaf53edb0cda45833ee45ba5b8b205791af9073258ca617c8b8187d6",
|
||||
"rollback_restores_protection_before_validator": true
|
||||
},
|
||||
"auto_merge_after_owner_approval": false,
|
||||
"auto_merge_machine_conditions": [
|
||||
"owner_approval_valid",
|
||||
"head_oid_unchanged",
|
||||
"required_checks_pass",
|
||||
"secret_scan_pass",
|
||||
"evidence_closure_pass",
|
||||
"approval_not_expired",
|
||||
"protected_branch_rules_pass"
|
||||
],
|
||||
"automatic_renewal_policy": {
|
||||
"approval_ref_fast_forward_descendant_required": true,
|
||||
"changed_condition_fallback": "HUMAN_OWNER_APPROVAL_PENDING",
|
||||
"secret_scan": "PASS_REQUIRED",
|
||||
"single_renewal_max_hours": 12,
|
||||
"status": "PROPOSED_AFTER_MIGRATION",
|
||||
"total_window_max_days": 7,
|
||||
"unchanged_fields_required": [
|
||||
"original_policy_sha256",
|
||||
"allowed_paths",
|
||||
"allowed_operations",
|
||||
"denied_operations",
|
||||
"source_sha256",
|
||||
"source_blob_oid"
|
||||
]
|
||||
},
|
||||
"break_glass_executor_may_merge_only_after_owner_approval_machine_gates_and_atomic_cutover_preconditions": true,
|
||||
"break_glass_expires_at": "2026-07-29T16:22:46Z",
|
||||
"desired_branch_protection": {
|
||||
"approval_whitelist_user_ids": [
|
||||
2
|
||||
],
|
||||
"approval_whitelist_usernames": [
|
||||
"owner"
|
||||
],
|
||||
"block_on_official_review_requests": true,
|
||||
"block_on_outdated_branch": true,
|
||||
"block_on_rejected_reviews": true,
|
||||
"branch_deletion": false,
|
||||
"branch_patterns": [
|
||||
"governance/approvals",
|
||||
"main",
|
||||
"release/**",
|
||||
"integration/**"
|
||||
],
|
||||
"direct_push": false,
|
||||
"dismiss_stale_approvals": true,
|
||||
"force_push": false,
|
||||
"require_status_checks": true,
|
||||
"required_approvals": 1,
|
||||
"required_status_contexts": [
|
||||
"aios/machine-gates",
|
||||
"aios/secret-scan",
|
||||
"aios/evidence-closure"
|
||||
],
|
||||
"wip_blocks_merge": true
|
||||
},
|
||||
"executor_must_not_approve": true,
|
||||
"expected_governance_base_oid": "ac2dc5c30eb35748ef11c98297812729d0fd5828",
|
||||
"expires_at": "2026-07-29T16:22:46Z",
|
||||
"global_constraints": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"approval_impersonation": false,
|
||||
"direct_main_push": false,
|
||||
"fake_review": false,
|
||||
"force_push": false,
|
||||
"production_change_without_owner_approval": false,
|
||||
"secret_commit": false,
|
||||
"tag_rewrite": false
|
||||
},
|
||||
"governance_model": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
|
||||
"historical_policy": {
|
||||
"historical_manifests_modified": false,
|
||||
"old_policy_decoder_retained_read_only": true,
|
||||
"requests_created_before_policy_effective_at_use_old_policy": true
|
||||
},
|
||||
"issued_at": "2026-07-28T16:22:46Z",
|
||||
"machine_gates": {
|
||||
"development_branch": [
|
||||
"allowed_branch",
|
||||
"allowed_paths",
|
||||
"compileall",
|
||||
"targeted_tests",
|
||||
"secret_scan",
|
||||
"git_diff_check"
|
||||
],
|
||||
"production": [
|
||||
"owner_approval",
|
||||
"tag_consistency",
|
||||
"registry_consistency",
|
||||
"deployment_plan",
|
||||
"rollback_plan",
|
||||
"artifact_integrity",
|
||||
"production_preflight"
|
||||
],
|
||||
"protected_branch_merge": [
|
||||
"expected_base_oid",
|
||||
"current_head_oid",
|
||||
"ordinary_merge_commit",
|
||||
"parent_order_verified",
|
||||
"artifact_binding",
|
||||
"audit_chain_valid"
|
||||
],
|
||||
"release": [
|
||||
"version_manifest",
|
||||
"explicit_release_target_oid",
|
||||
"artifact_sha256",
|
||||
"rollback_artifact_sha256",
|
||||
"sbom",
|
||||
"test_evidence",
|
||||
"evidence_closure"
|
||||
]
|
||||
},
|
||||
"merge_mode": "CREATE_MERGE_COMMIT",
|
||||
"migration_acceptance_tests": [
|
||||
"agent_request_pass",
|
||||
"owner_current_head_approval_pass",
|
||||
"machine_gates_then_merge_commit_pass",
|
||||
"agent_self_approval_denied",
|
||||
"non_owner_approval_denied",
|
||||
"stale_head_approval_denied",
|
||||
"wip_merge_denied",
|
||||
"machine_test_failure_merge_denied",
|
||||
"secret_scan_failure_merge_denied",
|
||||
"main_direct_write_denied",
|
||||
"tag_direct_write_denied",
|
||||
"force_push_denied",
|
||||
"missing_tag_target_oid_denied",
|
||||
"missing_evidence_closure_oid_denied",
|
||||
"production_without_owner_denied",
|
||||
"dormant_only_production_activation_denied"
|
||||
],
|
||||
"migration_mode": "OWNER_BREAK_GLASS_GOVERNANCE_RESET",
|
||||
"new_policy": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
|
||||
"old_policy": "DUAL_HUMAN_APPROVAL",
|
||||
"owner_approval_contract": {
|
||||
"dismissed": false,
|
||||
"does_not_claim_old_dual_approval_compliance": true,
|
||||
"head_change_invalidates_owner_approval": true,
|
||||
"owner_review_is_break_glass_signature": true,
|
||||
"review_created_before_approval_expires_at": true,
|
||||
"review_state": "APPROVED",
|
||||
"reviewed_head_oid_must_equal_current_pr_head_oid": true,
|
||||
"reviewer_must_equal": "owner",
|
||||
"stale": false
|
||||
},
|
||||
"owner_break_glass_declaration_to_be_attested_by_review": {
|
||||
"attestation_status": "PENDING_OWNER_REVIEW",
|
||||
"expires_at": "2026-07-29T16:22:46Z",
|
||||
"new_policy": "SINGLE_OWNER_WITH_MACHINE_GATES_V1",
|
||||
"old_policy": "DUAL_HUMAN_APPROVAL",
|
||||
"owner_acknowledges_old_policy_exception": true,
|
||||
"reason": "single-maintainer-system",
|
||||
"scope": "governance-policy-migration-only"
|
||||
},
|
||||
"owner_is_only_human_approver": true,
|
||||
"policy_effective_at": null,
|
||||
"pre_approval_non_authorizations": {
|
||||
"approval_validator_update_allowed": false,
|
||||
"gitea_branch_protection_update_allowed": false,
|
||||
"merge_allowed": false,
|
||||
"old_dual_rule_disable_allowed": false,
|
||||
"production_change_allowed": false,
|
||||
"state_machine_update_allowed": false,
|
||||
"writer_credential_issue_allowed": false
|
||||
},
|
||||
"prohibited_merge_modes": [
|
||||
"squash",
|
||||
"rebase",
|
||||
"force",
|
||||
"fast_forward_policy_bypass"
|
||||
],
|
||||
"reason": "single-maintainer-system",
|
||||
"repository": "aios/aios",
|
||||
"request_status": "HUMAN_OWNER_APPROVAL_PENDING",
|
||||
"requester_must_not_approve": true,
|
||||
"requesters": [
|
||||
"codex-chartgpt-bridge",
|
||||
"aios-governance-agent",
|
||||
"aios-release-agent",
|
||||
"aios-governed-development-writer"
|
||||
],
|
||||
"required_distinct_human_approvers": 1,
|
||||
"required_human_approvals": 1,
|
||||
"required_owner_approvals": 1,
|
||||
"resolved_owner": {
|
||||
"confidence_before_review": "MEDIUM",
|
||||
"confirmation_rule": "valid APPROVED review by owner on this exact immutable head",
|
||||
"email_sha256": "f5dc2928f6202c24fa4db8bb33db84e1b77c6eff30d1b95abdadeaae209bc4c9",
|
||||
"identity_source": [
|
||||
"gitea_repository_owner_account_aios_is_login_prohibited",
|
||||
"all_login_enabled_site_admins_enumerated_owner_and_never_logged_in_service_gito",
|
||||
"only_interactive_site_admin_named_owner",
|
||||
"gitea_owner_last_login_present",
|
||||
"historical_governance_records_use_approved_by_role_owner",
|
||||
"user_declared_single_natural_person_maintainer"
|
||||
],
|
||||
"login_enabled_site_admins": [
|
||||
{
|
||||
"observed_prior_login": true,
|
||||
"user_id": 2,
|
||||
"username": "owner"
|
||||
},
|
||||
{
|
||||
"classification": "service_admin_not_human_approver",
|
||||
"observed_prior_login": false,
|
||||
"user_id": 3,
|
||||
"username": "gito"
|
||||
}
|
||||
],
|
||||
"user_id": 2,
|
||||
"username": "owner"
|
||||
},
|
||||
"schema": "aios.single-owner-governance-policy/v1",
|
||||
"scope": "governance-policy-migration-only",
|
||||
"standing_autonomous_development_policy": {
|
||||
"allowed_without_repeated_owner_approval": [
|
||||
"patch_branch_create",
|
||||
"allowlisted_development_write",
|
||||
"patch_branch_commit_and_push",
|
||||
"test_execute",
|
||||
"artifact_build",
|
||||
"approval_pr_create",
|
||||
"read_only_evidence",
|
||||
"task_writer_renewal"
|
||||
],
|
||||
"owner_approval_still_required": [
|
||||
"protected_branch_merge",
|
||||
"tag",
|
||||
"registry_update",
|
||||
"production_baseline_update",
|
||||
"production_deploy",
|
||||
"production_rollback",
|
||||
"governance_policy_change"
|
||||
],
|
||||
"status": "PROPOSED_AFTER_MIGRATION"
|
||||
},
|
||||
"standing_single_owner_governance_migration_authorization": true,
|
||||
"state_machine": {
|
||||
"auto_merge_ready_state": "AUTO_MERGE_READY",
|
||||
"execution_ready_state": "OWNER_APPROVED_EXECUTION_READY",
|
||||
"machine_verified_state": "MACHINE_GATES_VERIFIED",
|
||||
"owner_approval_alone_is_not_execution_ready": true,
|
||||
"owner_verified_state": "OWNER_APPROVAL_VERIFIED",
|
||||
"pending_state": "HUMAN_OWNER_APPROVAL_PENDING"
|
||||
},
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-MIGRATION-20260729",
|
||||
"this_manifest_authorizes_only_governance_policy_migration": true,
|
||||
"this_manifest_grants_standing_development_authorization": false
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"schema": "aios.gitea-native-approval/v1",
|
||||
"approval_type": "IMPLEMENTATION",
|
||||
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
|
||||
"repository": "aios/aios",
|
||||
"branch": "patch/integration-refresh-grant-provisioner-20260726",
|
||||
"base_oid": "875d41c3101093149414292067fd700dc214d4d3",
|
||||
"actor_identity": "chatgpt-gitops-bot",
|
||||
"writer_audience": "aios-integration-refresh-provisioner-development-writer",
|
||||
"risk": "high",
|
||||
"allowed_paths": [
|
||||
"active-runtime/app/**",
|
||||
"tests/test_integration_refresh_provisioner.py",
|
||||
"tests/test_isolated_writer_integration_merge.py",
|
||||
"tests/test_gitea_branch_read_projection.py",
|
||||
"tests/test_isolated_writer_token_policy_v2.py",
|
||||
"deploy/systemd/aios-integration-refresh-*.service",
|
||||
"docs/autonomous-release/**"
|
||||
],
|
||||
"allowed_operations": [
|
||||
"repository.source_map.read",
|
||||
"runtime.unit_metadata.read",
|
||||
"git.ref.read",
|
||||
"git.diff.read",
|
||||
"git.branch.patch.create",
|
||||
"commit_file.atomic",
|
||||
"git.push.patch_branch",
|
||||
"test.execute.allowlisted",
|
||||
"artifact.build.control_plane_patch",
|
||||
"evidence.write.task_runtime"
|
||||
],
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"main.merge",
|
||||
"tag.write",
|
||||
"tag.delete",
|
||||
"tag.rewrite",
|
||||
"force_push",
|
||||
"history.rewrite",
|
||||
"baseline.write",
|
||||
"registry.write",
|
||||
"production.deploy",
|
||||
"production.rollback",
|
||||
"secret.read",
|
||||
"secret.export",
|
||||
"bare_ref_direct_write"
|
||||
],
|
||||
"expires_at": "2026-07-27T03:35:55Z"
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"schema": "aios.gitea-native-approval/v1",
|
||||
"approval_type": "IMPLEMENTATION",
|
||||
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
|
||||
"repository": "aios/aios",
|
||||
"branch": "patch/integration-refresh-grant-provisioner-20260726",
|
||||
"base_oid": "875d41c3101093149414292067fd700dc214d4d3",
|
||||
"actor_identity": "chatgpt-gitops-bot",
|
||||
"writer_audience": "aios-integration-refresh-provisioner-development-writer",
|
||||
"risk": "high",
|
||||
"allowed_paths": [
|
||||
"active-runtime/app/**",
|
||||
"tests/test_integration_refresh_provisioner.py",
|
||||
"tests/test_isolated_writer_integration_merge.py",
|
||||
"tests/test_gitea_branch_read_projection.py",
|
||||
"tests/test_isolated_writer_token_policy_v2.py",
|
||||
"deploy/systemd/aios-integration-refresh-*.service",
|
||||
"docs/autonomous-release/**"
|
||||
],
|
||||
"allowed_operations": [
|
||||
"repository.source_map.read",
|
||||
"runtime.unit_metadata.read",
|
||||
"git.ref.read",
|
||||
"git.diff.read",
|
||||
"git.branch.patch.create",
|
||||
"commit_file.atomic",
|
||||
"git.push.patch_branch",
|
||||
"test.execute.allowlisted",
|
||||
"artifact.build.control_plane_patch",
|
||||
"evidence.write.task_runtime"
|
||||
],
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"main.merge",
|
||||
"tag.write",
|
||||
"tag.delete",
|
||||
"tag.rewrite",
|
||||
"force_push",
|
||||
"history.rewrite",
|
||||
"baseline.write",
|
||||
"registry.write",
|
||||
"production.deploy",
|
||||
"production.rollback",
|
||||
"secret.read",
|
||||
"secret.export",
|
||||
"bare_ref_direct_write"
|
||||
],
|
||||
"expires_at": "2026-07-27T13:00:11Z"
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_LIVE_ACTIVATION_IMPLEMENTATION_AND_EXECUTION",
|
||||
"artifact_sha256": "01e0226f0302bb8e2f8d81299393075bf0332c6e22e00877469fb297c51f3802",
|
||||
"authorization_scope": [
|
||||
"deploy_live_activation_implementation",
|
||||
"execute_one_atomic_governance_activation",
|
||||
"execute_acceptance_tests",
|
||||
"control_plane_rollback_on_failure",
|
||||
"write_activation_receipt"
|
||||
],
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"registry.write",
|
||||
"baseline.write",
|
||||
"production.deploy",
|
||||
"force_push",
|
||||
"history_rewrite"
|
||||
],
|
||||
"evidence_closure_oid": "c6316943d2485f06f97242df6338ded21de1ee38",
|
||||
"evidence_closure_sha256": "bd521103c907d6194acbbbd42a947c5af2ccbda91797e5dc75e81887a042becd",
|
||||
"execution_binding": {
|
||||
"backend": "sqlite",
|
||||
"branch": "governance/approvals",
|
||||
"evidence_closure_oid": "c6316943d2485f06f97242df6338ded21de1ee38",
|
||||
"executor": "aios-governance-single-owner-activation",
|
||||
"expected_branch_protection_sha256": "f27992c8024426708d93bce072d231707bae47a927aa2393d566aae64d5ed079",
|
||||
"expected_gitea_schema_sha256": "3524f4912165939cb746c2c65d70583a909f5abbd00c4e07ae76f7206d49aa54",
|
||||
"expected_state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
|
||||
"expected_validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
|
||||
"forbidden_operations": {
|
||||
"baseline": false,
|
||||
"force_push": false,
|
||||
"governance_direct": false,
|
||||
"history_rewrite": false,
|
||||
"integration": false,
|
||||
"main": false,
|
||||
"production": false,
|
||||
"registry": false,
|
||||
"tags": false
|
||||
},
|
||||
"operation_id": "single-owner-live-activation-20260729T033228Z",
|
||||
"repo_id": 1,
|
||||
"requester": "codex-agent",
|
||||
"target_branch_protection_sha256": "61b424b0c495eed71c73171c5c4434ac66d074de36886a73ec4c445fd1905db8",
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729"
|
||||
},
|
||||
"execution_binding_sha256": "6b2ed671a94fa83704383728fd2bb2df3b67523b4273100fa371777d984be102",
|
||||
"expected_governance_base_oid": "8b7f9d9028f6ff9beb225bf85f53dbeaac6830e7",
|
||||
"expires_at": "2026-07-29T15:32:28Z",
|
||||
"human_authorizer": "owner",
|
||||
"implementation_commit_oid": "e1e438564ce8b987a36df0947e6eaa324dfede74",
|
||||
"implementation_tree_oid": "dd93dc1df10cb8b8fe59b09d3214a9ae6fee671e",
|
||||
"issued_at": "2026-07-29T03:32:28Z",
|
||||
"legacy_mechanical_approvals": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"machine_gate_contexts": [
|
||||
"aios/branch-protection",
|
||||
"aios/evidence-closure",
|
||||
"aios/secret-scan",
|
||||
"aios/state-machine",
|
||||
"aios/validator"
|
||||
],
|
||||
"pr30_merge_oid": "f6bef90633f428454e85721f353cd82cdf04caf0",
|
||||
"pr31_merge_oid": "8b7f9d9028f6ff9beb225bf85f53dbeaac6830e7",
|
||||
"rollback_artifact_sha256": "ed9307cc2f07767b75866fcb370fa3f98b76c5147e4b7fc49ecf04cf21cf7c31",
|
||||
"signed_merge_requirement_effective": false,
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
|
||||
"test_evidence_sha256": "172a7cf812c6b901524138fb72851a9b7d2e895dedc98893407d0bab9b52c6c1"
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
{
|
||||
"approval_type": "SINGLE_OWNER_GOVERNANCE_LIVE_ACTIVATION_IMPLEMENTATION_AND_EXECUTION",
|
||||
"artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
|
||||
"artifact_sha256": "32bc49c207ec454b6fd81b0484f5b257bb789481b37175995029a2ec78cc62fa",
|
||||
"authorization_scope": [
|
||||
"deploy_exact_approved_artifact",
|
||||
"publish_exact_head_machine_statuses",
|
||||
"execute_one_atomic_governance_activation",
|
||||
"verify_and_rollback_exact_transaction"
|
||||
],
|
||||
"denied_operations": [
|
||||
"main.write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"registry.write",
|
||||
"baseline.write",
|
||||
"production.deploy",
|
||||
"force_push",
|
||||
"history_rewrite"
|
||||
],
|
||||
"evidence_closure_blob_oid": "6af6d017f22c4e0c512b0cd62644cdc6ab2135d5",
|
||||
"evidence_closure_oid": "310ab2af902a9fde9108d227077f433cc743ce7c",
|
||||
"evidence_closure_path": "evidence/single-owner-governance/AIOS-SINGLE-OWNER-LIVE-ACTIVATION-HARDENING-20260729T043010Z.json",
|
||||
"evidence_closure_sha256": "e482fe52c8381f765ee508d2de1fe2e77dff52e6e342f01be4ca481ff2f76820",
|
||||
"execution_binding": {
|
||||
"artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
|
||||
"artifact_sha256": "32bc49c207ec454b6fd81b0484f5b257bb789481b37175995029a2ec78cc62fa",
|
||||
"backend": "sqlite",
|
||||
"branch": "governance/approvals",
|
||||
"evidence_closure_oid": "310ab2af902a9fde9108d227077f433cc743ce7c",
|
||||
"evidence_closure_path": "evidence/single-owner-governance/AIOS-SINGLE-OWNER-LIVE-ACTIVATION-HARDENING-20260729T043010Z.json",
|
||||
"evidence_closure_sha256": "e482fe52c8381f765ee508d2de1fe2e77dff52e6e342f01be4ca481ff2f76820",
|
||||
"executor": "aios-governance-single-owner-activation",
|
||||
"expected_branch_protection_sha256": "f27992c8024426708d93bce072d231707bae47a927aa2393d566aae64d5ed079",
|
||||
"expected_gitea_schema_sha256": "3524f4912165939cb746c2c65d70583a909f5abbd00c4e07ae76f7206d49aa54",
|
||||
"expected_state_machine_sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e",
|
||||
"expected_validator_sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1",
|
||||
"forbidden_operations": {
|
||||
"baseline": false,
|
||||
"force_push": false,
|
||||
"governance_direct": false,
|
||||
"history_rewrite": false,
|
||||
"integration": false,
|
||||
"main": false,
|
||||
"production": false,
|
||||
"registry": false,
|
||||
"tags": false
|
||||
},
|
||||
"implementation_commit_oid": "71def340e7cc34f4f19918dcf8d3c847abbe4fbf",
|
||||
"implementation_tree_oid": "3cc61bfbf69cbe0a24d54a0e53a6c50bcc130066",
|
||||
"machine_status_producer_id": 13,
|
||||
"machine_status_producer_name": "gitops-bot",
|
||||
"operation_id": "single-owner-live-activation-hardening-20260729T043149Z",
|
||||
"repo_id": 1,
|
||||
"requester": "codex-agent",
|
||||
"rollback_artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-rollback-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
|
||||
"rollback_artifact_sha256": "4efe1ea73d4fd72e5364fc91a16ad5e9d1e6ebe78d8aa466f7b11c4915b08403",
|
||||
"runtime_sources": [
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
|
||||
"sha256": "48846a58fa3afb2b7c8ffe6e88504a9333863932df867f33ba0321ad3bac6003"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
|
||||
"sha256": "00775efe3f3d631d88379eff4ed2dcfaf386a2fa43111abe961e75109e80d768"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
|
||||
"sha256": "a8f121245e04487d99c99fb03ada83f0c907723f8eb18552872ff46dcf5a7873"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
|
||||
"sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
|
||||
"sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1"
|
||||
}
|
||||
],
|
||||
"target_branch_protection_sha256": "4713f0494b79103668fbe5bd8fd7da5d60a43e56fb545aa6e7c773f43dc07c10",
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
|
||||
"test_evidence_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/test-evidence-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.json",
|
||||
"test_evidence_sha256": "c1633732767f3f051ffb01404d12d05a6168a4b01b91efdb34a64988d6dee684"
|
||||
},
|
||||
"execution_binding_sha256": "63705dd0f5cc25debde132179f96819a844a9703b33c092db4ac48d5680d536a",
|
||||
"expected_governance_base_oid": "1071979079deab8a4028473d967c2a205c3b111e",
|
||||
"expires_at": "2026-07-29T16:31:49Z",
|
||||
"human_authorizer": "owner",
|
||||
"implementation_commit_oid": "71def340e7cc34f4f19918dcf8d3c847abbe4fbf",
|
||||
"implementation_tree_oid": "3cc61bfbf69cbe0a24d54a0e53a6c50bcc130066",
|
||||
"issued_at": "2026-07-29T04:31:49Z",
|
||||
"legacy_mechanical_approvals": [
|
||||
"codex",
|
||||
"gpt"
|
||||
],
|
||||
"machine_gate_contexts": [
|
||||
"aios/branch-protection",
|
||||
"aios/evidence-closure",
|
||||
"aios/secret-scan",
|
||||
"aios/state-machine",
|
||||
"aios/validator"
|
||||
],
|
||||
"machine_status_producer_id": 13,
|
||||
"machine_status_producer_name": "gitops-bot",
|
||||
"rollback_artifact_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/live-activation-rollback-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.tar.gz",
|
||||
"rollback_artifact_sha256": "4efe1ea73d4fd72e5364fc91a16ad5e9d1e6ebe78d8aa466f7b11c4915b08403",
|
||||
"runtime_sources": [
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/activation.py",
|
||||
"sha256": "48846a58fa3afb2b7c8ffe6e88504a9333863932df867f33ba0321ad3bac6003"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/gitea_protected_branch.py",
|
||||
"sha256": "00775efe3f3d631d88379eff4ed2dcfaf386a2fa43111abe961e75109e80d768"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/journal.py",
|
||||
"sha256": "a8f121245e04487d99c99fb03ada83f0c907723f8eb18552872ff46dcf5a7873"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/state_machine.py",
|
||||
"sha256": "0b08a2c378d143cb9031a25132afc7b7d825bdc03d11efe10610341d4b70167e"
|
||||
},
|
||||
{
|
||||
"git_path": "services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
|
||||
"runtime_path": "/opt/aios/single-owner-governance/releases/71def340e7cc34f4f19918dcf8d3c847abbe4fbf/services/aios-single-owner-governance/aios_single_owner_governance/validator.py",
|
||||
"sha256": "754639846cb15cb997d612a1fe0ceb0224ddef5bbc3ccac9802a3747f122dac1"
|
||||
}
|
||||
],
|
||||
"target_branch_protection": {
|
||||
"approvals_whitelist_team_i_ds": "null",
|
||||
"approvals_whitelist_user_i_ds": "[2]",
|
||||
"block_on_official_review_requests": 1,
|
||||
"block_on_outdated_branch": 1,
|
||||
"block_on_rejected_reviews": 1,
|
||||
"branch_name": "governance/approvals",
|
||||
"can_push": 0,
|
||||
"created_unix": 1785093201,
|
||||
"dismiss_stale_approvals": 1,
|
||||
"enable_approvals_whitelist": 1,
|
||||
"enable_merge_whitelist": 1,
|
||||
"enable_status_check": 1,
|
||||
"enable_whitelist": 0,
|
||||
"id": 1,
|
||||
"ignore_stale_approvals": 0,
|
||||
"merge_whitelist_team_i_ds": "null",
|
||||
"merge_whitelist_user_i_ds": "[42,43]",
|
||||
"protected_file_patterns": "",
|
||||
"repo_id": 1,
|
||||
"require_signed_commits": 0,
|
||||
"required_approvals": 1,
|
||||
"status_check_contexts": "[\"aios/branch-protection\",\"aios/evidence-closure\",\"aios/secret-scan\",\"aios/state-machine\",\"aios/validator\"]",
|
||||
"unprotected_file_patterns": "",
|
||||
"updated_unix": 1785299509,
|
||||
"whitelist_deploy_keys": 0,
|
||||
"whitelist_team_i_ds": "null",
|
||||
"whitelist_user_i_ds": "null"
|
||||
},
|
||||
"task_id": "AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729",
|
||||
"test_evidence_path": "/var/lib/aios-gitops/runtime/tasks/AIOS-SINGLE-OWNER-GOVERNANCE-ACTIVATION-20260729/artifacts/hardening-71def340e7cc34f4f19918dcf8d3c847abbe4fbf/test-evidence-71def340e7cc34f4f19918dcf8d3c847abbe4fbf.json",
|
||||
"test_evidence_sha256": "c1633732767f3f051ffb01404d12d05a6168a4b01b91efdb34a64988d6dee684"
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"actor_identity": "chatgpt-gitops-bot",
|
||||
"allowed_operations": [
|
||||
"runtime.source.read.exact",
|
||||
"runtime.source.hash",
|
||||
"runtime.unit_metadata.read",
|
||||
"package.ownership.read",
|
||||
"git.object.lookup.by_blob_oid",
|
||||
"secret.scan.local_source",
|
||||
"repository.source_import.byte_exact",
|
||||
"repository.module.create",
|
||||
"source_map.evidence.write",
|
||||
"git.branch.patch.create",
|
||||
"commit_file.atomic",
|
||||
"git.push.patch_branch",
|
||||
"test.execute.allowlisted",
|
||||
"artifact.build.control_plane_patch",
|
||||
"evidence.write.task_runtime"
|
||||
],
|
||||
"allowed_paths": [
|
||||
"active-runtime/app/aios_autonomous_release_authorization/**",
|
||||
"active-runtime/app/aios_chatgpt_action_task_router/**",
|
||||
"active-runtime/app/aios_isolated_writer_api/**",
|
||||
"tests/test_integration_refresh_provisioner.py",
|
||||
"tests/test_isolated_writer_integration_merge.py",
|
||||
"tests/test_gitea_branch_read_projection.py",
|
||||
"tests/test_isolated_writer_token_policy_v2.py",
|
||||
"deploy/systemd/aios-integration-refresh-*.service",
|
||||
"docs/autonomous-release/**"
|
||||
],
|
||||
"allowed_runtime_reads": [
|
||||
"/usr/libexec/aios-autonomous-release-authorization/controller.py",
|
||||
"/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py"
|
||||
],
|
||||
"approval_type": "SOURCE_MAPPING_AND_IMPORT",
|
||||
"canonical_paths": {
|
||||
"controller": "active-runtime/app/aios_autonomous_release_authorization/controller.py",
|
||||
"isolated_writer_api": "active-runtime/app/aios_isolated_writer_api/**",
|
||||
"router": "active-runtime/app/aios_chatgpt_action_task_router/action_task_router.py"
|
||||
},
|
||||
"denied_operations": [
|
||||
"secret.value.return",
|
||||
"secret.matching_line.return",
|
||||
"secret.context.return",
|
||||
"runtime.source.modify",
|
||||
"runtime.unit.modify",
|
||||
"arbitrary_path.read",
|
||||
"secret.read.by_agent",
|
||||
"secret.export",
|
||||
"main.write",
|
||||
"main.merge",
|
||||
"governance.approvals.direct_write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"tag.delete",
|
||||
"tag.rewrite",
|
||||
"force_push",
|
||||
"history.rewrite",
|
||||
"bare_ref_direct_write",
|
||||
"baseline.write",
|
||||
"registry.write",
|
||||
"production.deploy",
|
||||
"production.rollback"
|
||||
],
|
||||
"expires_at": "2026-07-27T22:36:27Z",
|
||||
"extends_approval_merge_oid": "45f3226662965c8d41ec1775e8c8857f2b986397",
|
||||
"finding_policy": {
|
||||
"controller_byte_exact_import_allowed": true,
|
||||
"controller_finding_status": "PASS",
|
||||
"controller_sanitized_source_creation_allowed": false,
|
||||
"finding_classification_by_automation": "PROHIBITED",
|
||||
"isolated_writer_api_module_create_allowed": true,
|
||||
"matching_source_lines_disclosed": false,
|
||||
"router_byte_exact_import_allowed": true,
|
||||
"router_finding_status": "PASS",
|
||||
"router_sanitized_source_creation_allowed": false,
|
||||
"scan_decision": "MAPPING_IMPORT_ONLY",
|
||||
"secret_content_disclosed": false
|
||||
},
|
||||
"implementation_base_oid": "875d41c3101093149414292067fd700dc214d4d3",
|
||||
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
|
||||
"issued_at": "2026-07-27T10:36:27Z",
|
||||
"repository": "aios/aios",
|
||||
"required_controls": {
|
||||
"controller_finding_must_be_resolved": false,
|
||||
"controller_import_blob_must_equal_runtime_blob": true,
|
||||
"controller_import_must_be_byte_exact": true,
|
||||
"controller_import_sha256_must_equal_runtime_sha256": true,
|
||||
"dual_human_approval_required": true,
|
||||
"global_gitops_writes_must_remain_disabled": true,
|
||||
"new_task_bound_grant_required": true,
|
||||
"old_implementation_token_auth_status": 401,
|
||||
"old_implementation_writer_revoked": true,
|
||||
"old_secret_revocation_must_be_verified": false,
|
||||
"router_finding_must_be_resolved": false,
|
||||
"router_import_blob_must_equal_runtime_blob": true,
|
||||
"router_import_must_be_byte_exact": true,
|
||||
"router_import_sha256_must_equal_runtime_sha256": true,
|
||||
"sanitized_source_behavioral_equivalence_required": false,
|
||||
"sanitized_source_secret_scan_must_pass": false,
|
||||
"true_positive_requires_rotation": false
|
||||
},
|
||||
"risk": "high",
|
||||
"runtime_source_evidence": {
|
||||
"controller": {
|
||||
"finding_count": 0,
|
||||
"findings": [],
|
||||
"git_blob_oid": "9c68be36e0b6a18260e3099e3d7b0dcab6d814aa",
|
||||
"group_gid": 0,
|
||||
"mode": "0o700",
|
||||
"mtime_ns": 1785043975531298047,
|
||||
"owner_uid": 0,
|
||||
"package_owner": "UNPACKAGED",
|
||||
"referencing_systemd_units": [
|
||||
"aios-autonomous-release-authorization-controller.service"
|
||||
],
|
||||
"resolved_path": "/usr/libexec/aios-autonomous-release-authorization/controller.py",
|
||||
"secret_content_returned": false,
|
||||
"secret_scan": "PASS",
|
||||
"sha256": "39b532c3058c4ae49ed691d7c66c3b7745a25111fa61039f388c8335fd262c50",
|
||||
"size": 24204,
|
||||
"utf8_python": true
|
||||
},
|
||||
"isolated_writer_api": {
|
||||
"canonical_source_path": "NOT_ESTABLISHED",
|
||||
"runtime_module_status": "ABSENT"
|
||||
},
|
||||
"router": {
|
||||
"finding_count": 0,
|
||||
"findings": [],
|
||||
"git_blob_oid": "ee0595ca61a0598f8cb3dc10865a255e21679b2a",
|
||||
"group_gid": 0,
|
||||
"mode": "0o644",
|
||||
"mtime_ns": 1785042222580725999,
|
||||
"owner_uid": 0,
|
||||
"package_owner": "UNPACKAGED",
|
||||
"referencing_systemd_units": [
|
||||
"aios-chatgpt-autonomous-release-route.service"
|
||||
],
|
||||
"resolved_path": "/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py",
|
||||
"secret_content_returned": false,
|
||||
"secret_scan": "PASS",
|
||||
"sha256": "738fb7035a6b792115d6467b4d1e4ffd47a8c5d5646f7032ebc68ea587cbd554",
|
||||
"size": 25952,
|
||||
"utf8_python": true
|
||||
}
|
||||
},
|
||||
"schema": "aios.gitea-native-approval/v1",
|
||||
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
|
||||
"writer_audience": "aios-integration-refresh-provisioner-development-writer"
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"actor_identity": "chatgpt-gitops-bot",
|
||||
"allowed_operations": [
|
||||
"runtime.source.read.exact",
|
||||
"runtime.source.hash",
|
||||
"runtime.unit_metadata.read",
|
||||
"package.ownership.read",
|
||||
"git.object.lookup.by_blob_oid",
|
||||
"secret.scan.local_source",
|
||||
"repository.source_import.byte_exact",
|
||||
"repository.module.create",
|
||||
"source_map.evidence.write",
|
||||
"git.branch.patch.create",
|
||||
"commit_file.atomic",
|
||||
"git.push.patch_branch",
|
||||
"test.execute.allowlisted",
|
||||
"artifact.build.control_plane_patch",
|
||||
"evidence.write.task_runtime"
|
||||
],
|
||||
"allowed_paths": [
|
||||
"active-runtime/app/aios_autonomous_release_authorization/**",
|
||||
"active-runtime/app/aios_chatgpt_action_task_router/**",
|
||||
"active-runtime/app/aios_isolated_writer_api/**",
|
||||
"tests/test_integration_refresh_provisioner.py",
|
||||
"tests/test_isolated_writer_integration_merge.py",
|
||||
"tests/test_gitea_branch_read_projection.py",
|
||||
"tests/test_isolated_writer_token_policy_v2.py",
|
||||
"deploy/systemd/aios-integration-refresh-*.service",
|
||||
"docs/autonomous-release/**"
|
||||
],
|
||||
"allowed_runtime_reads": [
|
||||
"/usr/libexec/aios-autonomous-release-authorization/controller.py",
|
||||
"/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py"
|
||||
],
|
||||
"approval_type": "SOURCE_MAPPING_AND_IMPORT_EXECUTION_RENEWAL",
|
||||
"canonical_paths": {
|
||||
"controller": "active-runtime/app/aios_autonomous_release_authorization/controller.py",
|
||||
"isolated_writer_api": "active-runtime/app/aios_isolated_writer_api/**",
|
||||
"router": "active-runtime/app/aios_chatgpt_action_task_router/action_task_router.py"
|
||||
},
|
||||
"denied_operations": [
|
||||
"secret.value.return",
|
||||
"secret.matching_line.return",
|
||||
"secret.context.return",
|
||||
"runtime.source.modify",
|
||||
"runtime.unit.modify",
|
||||
"arbitrary_path.read",
|
||||
"secret.read.by_agent",
|
||||
"secret.export",
|
||||
"main.write",
|
||||
"main.merge",
|
||||
"governance.approvals.direct_write",
|
||||
"integration.write",
|
||||
"tag.write",
|
||||
"tag.delete",
|
||||
"tag.rewrite",
|
||||
"force_push",
|
||||
"history.rewrite",
|
||||
"bare_ref_direct_write",
|
||||
"baseline.write",
|
||||
"registry.write",
|
||||
"production.deploy",
|
||||
"production.rollback"
|
||||
],
|
||||
"expected_governance_base_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6",
|
||||
"expires_at": "2026-07-28T18:10:44Z",
|
||||
"extends_approval_merge_oid": "45f3226662965c8d41ec1775e8c8857f2b986397",
|
||||
"finding_policy": {
|
||||
"controller_byte_exact_import_allowed": true,
|
||||
"controller_finding_status": "PASS",
|
||||
"controller_sanitized_source_creation_allowed": false,
|
||||
"finding_classification_by_automation": "PROHIBITED",
|
||||
"isolated_writer_api_module_create_allowed": true,
|
||||
"matching_source_lines_disclosed": false,
|
||||
"router_byte_exact_import_allowed": true,
|
||||
"router_finding_status": "PASS",
|
||||
"router_sanitized_source_creation_allowed": false,
|
||||
"scan_decision": "MAPPING_IMPORT_ONLY",
|
||||
"secret_content_disclosed": false
|
||||
},
|
||||
"implementation_base_oid": "875d41c3101093149414292067fd700dc214d4d3",
|
||||
"implementation_branch": "patch/integration-refresh-grant-provisioner-20260726",
|
||||
"issued_at": "2026-07-28T06:10:44Z",
|
||||
"renews_source_mapping_approval_merge_oid": "9514062cf33e45941abe4a8c98377e0713b0b3f6",
|
||||
"renews_source_mapping_manifest_blob_oid": "00c5e90e529cb98c7750a5761b0a0d6ccf507174",
|
||||
"renews_source_mapping_manifest_sha256": "17af8ebc43673c0e46bb9ab1bf44497e8c147f1b4a9d7a8a404edd5c0abd6f21",
|
||||
"repository": "aios/aios",
|
||||
"required_controls": {
|
||||
"controller_finding_must_be_resolved": false,
|
||||
"controller_import_blob_must_equal_runtime_blob": true,
|
||||
"controller_import_must_be_byte_exact": true,
|
||||
"controller_import_sha256_must_equal_runtime_sha256": true,
|
||||
"dual_human_approval_required": true,
|
||||
"global_gitops_writes_must_remain_disabled": true,
|
||||
"new_task_bound_grant_required": true,
|
||||
"old_implementation_token_auth_status": 401,
|
||||
"old_implementation_writer_revoked": true,
|
||||
"old_secret_revocation_must_be_verified": false,
|
||||
"router_finding_must_be_resolved": false,
|
||||
"router_import_blob_must_equal_runtime_blob": true,
|
||||
"router_import_must_be_byte_exact": true,
|
||||
"router_import_sha256_must_equal_runtime_sha256": true,
|
||||
"sanitized_source_behavioral_equivalence_required": false,
|
||||
"sanitized_source_secret_scan_must_pass": false,
|
||||
"true_positive_requires_rotation": false
|
||||
},
|
||||
"risk": "high",
|
||||
"runtime_source_evidence": {
|
||||
"controller": {
|
||||
"finding_count": 0,
|
||||
"findings": [],
|
||||
"git_blob_oid": "9c68be36e0b6a18260e3099e3d7b0dcab6d814aa",
|
||||
"group_gid": 0,
|
||||
"mode": "0o700",
|
||||
"mtime_ns": 1785043975531298047,
|
||||
"owner_uid": 0,
|
||||
"package_owner": "UNPACKAGED",
|
||||
"referencing_systemd_units": [
|
||||
"aios-autonomous-release-authorization-controller.service"
|
||||
],
|
||||
"resolved_path": "/usr/libexec/aios-autonomous-release-authorization/controller.py",
|
||||
"secret_content_returned": false,
|
||||
"secret_scan": "PASS",
|
||||
"sha256": "39b532c3058c4ae49ed691d7c66c3b7745a25111fa61039f388c8335fd262c50",
|
||||
"size": 24204,
|
||||
"utf8_python": true
|
||||
},
|
||||
"isolated_writer_api": {
|
||||
"canonical_source_path": "NOT_ESTABLISHED",
|
||||
"runtime_module_status": "ABSENT"
|
||||
},
|
||||
"observed_at": "2026-07-28T05:53:01.253909Z",
|
||||
"router": {
|
||||
"finding_count": 0,
|
||||
"findings": [],
|
||||
"git_blob_oid": "ee0595ca61a0598f8cb3dc10865a255e21679b2a",
|
||||
"group_gid": 0,
|
||||
"mode": "0o644",
|
||||
"mtime_ns": 1785042222580725999,
|
||||
"owner_uid": 0,
|
||||
"package_owner": "UNPACKAGED",
|
||||
"referencing_systemd_units": [
|
||||
"aios-chatgpt-autonomous-release-route.service"
|
||||
],
|
||||
"resolved_path": "/usr/libexec/aios-chatgpt-action-task-router-continuous-20260726/action_task_router.py",
|
||||
"secret_content_returned": false,
|
||||
"secret_scan": "PASS",
|
||||
"sha256": "738fb7035a6b792115d6467b4d1e4ffd47a8c5d5646f7032ebc68ea587cbd554",
|
||||
"size": 25952,
|
||||
"utf8_python": true
|
||||
}
|
||||
},
|
||||
"runtime_source_read_projection_evidence_sha256": "23f03d9c6abe6f11e1acda5210b8708696e3b77caa0083b6bfaef30a44b2a35f",
|
||||
"schema": "aios.gitea-native-approval/v1",
|
||||
"task_id": "AIOS-INTEGRATION-REFRESH-PROVISIONER-IMPLEMENTATION-20260726",
|
||||
"writer_audience": "aios-integration-refresh-provisioner-development-writer"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
[Unit]
|
||||
Description=AIOS root task credential broker (%i)
|
||||
ConditionPathExists=/var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
Group=root
|
||||
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
|
||||
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_credential_broker --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --audit-key %d/audit-key --audit-dir /var/lib/aios-gitops/runtime/task-status-merge/%i/audit --request /var/lib/aios-gitops/runtime/task-status-merge/%i/credential-request.json
|
||||
Environment=AIOS_GITOPS_WRITES_ENABLED=false
|
||||
NoNewPrivileges=false
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadOnlyPaths=/data/aios-gitops/runtime/bin/gitea /data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig /var/lib/aios-gitops/runtime/task-status-merge/%i/credential-request.json /etc/aios-gitops/task-status-merge/allowed_signers
|
||||
ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data/gitea.db /run/aios-task-credential-broker /var/lib/aios-gitops/runtime/task-status-merge/%i/audit
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET
|
||||
IPAddressDeny=any
|
||||
IPAddressAllow=localhost
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictSUIDSGID=true
|
||||
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=AIOS task credential expiry and completion sweeper
|
||||
After=aios-gitea.service
|
||||
Requires=aios-gitea.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
Group=root
|
||||
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_credential_expiry_sweeper --runtime-root /var/lib/aios-gitops/runtime/task-status-merge --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers
|
||||
Environment=AIOS_GITOPS_WRITES_ENABLED=false
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadOnlyPaths=/var/lib/aios-gitops/runtime/task-status-merge /etc/aios-gitops/task-status-merge/allowed_signers
|
||||
ReadWritePaths=/data/aios-gitops/runtime/gitea-bin/data/gitea.db /run/aios-task-credential-broker /var/lib/aios-gitops/runtime/task-status-merge
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET
|
||||
IPAddressDeny=any
|
||||
IPAddressAllow=localhost
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictSUIDSGID=true
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Run AIOS task credential expiry sweeper every minute
|
||||
|
||||
[Timer]
|
||||
OnBootSec=1min
|
||||
OnUnitActiveSec=1min
|
||||
AccuracySec=5s
|
||||
Persistent=true
|
||||
Unit=aios-task-credential-expiry-sweeper.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=AIOS task-scoped Gitea fast-forward-only merge broker (%i)
|
||||
After=network.target aios-gitea.service aios-task-status-broker@%i.service
|
||||
Requires=aios-gitea.service aios-task-status-broker@%i.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=aios-task-merge-bot
|
||||
Group=aios-task-merge-bot
|
||||
LoadCredentialEncrypted=gitea-token:/run/aios-task-credential-broker/%i-merge.cred
|
||||
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
|
||||
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_status_merge_broker --mode merge --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --token %d/gitea-token --audit-key %d/audit-key --journal /var/lib/aios-gitops/runtime/task-status-merge/%i/merge-journal/journal.sqlite3
|
||||
Environment=AIOS_GITOPS_WRITES_ENABLED=false
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET
|
||||
ReadOnlyPaths=/var/lib/aios-gitops/runtime/task-status-merge/%i /etc/aios-gitops/task-status-merge/allowed_signers
|
||||
ReadWritePaths=/var/lib/aios-gitops/runtime/task-status-merge/%i/merge-journal
|
||||
IPAddressDeny=any
|
||||
IPAddressAllow=localhost
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictSUIDSGID=true
|
||||
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=AIOS task-scoped Gitea status broker (%i)
|
||||
After=network.target aios-gitea.service
|
||||
Requires=aios-gitea.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=aios-task-status-bot
|
||||
Group=aios-task-status-bot
|
||||
LoadCredentialEncrypted=gitea-token:/run/aios-task-credential-broker/%i-status.cred
|
||||
LoadCredentialEncrypted=audit-key:/run/aios-task-credential-broker/%i-audit.cred
|
||||
ExecStart=/usr/bin/python3 -m aios_single_owner_governance.task_status_merge_broker --mode status --grant /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.json --grant-signature /var/lib/aios-gitops/runtime/task-status-merge/%i/grant.sig --allowed-signers /etc/aios-gitops/task-status-merge/allowed_signers --evidence /var/lib/aios-gitops/runtime/task-status-merge/%i/status-evidence.json --token %d/gitea-token --audit-key %d/audit-key --journal /var/lib/aios-gitops/runtime/task-status-merge/%i/status-journal/journal.sqlite3
|
||||
Environment=AIOS_GITOPS_WRITES_ENABLED=false
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET
|
||||
ReadOnlyPaths=/var/lib/aios-gitops/runtime/task-status-merge/%i /etc/aios-gitops/task-status-merge/allowed_signers
|
||||
ReadWritePaths=/var/lib/aios-gitops/runtime/task-status-merge/%i/status-journal
|
||||
IPAddressDeny=any
|
||||
IPAddressAllow=localhost
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictSUIDSGID=true
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"evidence_type": "TWO_STAGE_OWNER_CAMPAIGN_V2_PHASE_A_CANDIDATE",
|
||||
"generated_at": "2026-07-30T02:35:51Z",
|
||||
"execution_status": "PARTIALLY_COMPLETED",
|
||||
"blocking_layer": "PHASE_A_OWNER_EXACT_HEAD_APPROVAL",
|
||||
"repository": "aios/aios",
|
||||
"governance_base_oid": "ebd74398743e36523b593fcc395b73945d4924c5",
|
||||
"governance_tree_oid": "ad1255a1127204fad1d1208d8f31dc94fa64e6e1",
|
||||
"authority_main_oid": "875d41c3101093149414292067fd700dc214d4d3",
|
||||
"schema_seed_commit_oid": "8da47545a507cb798d3d6ab30ff8552a2d0a5ecf",
|
||||
"schema_seed_tree_oid": "991e68577a469657c1c4996814b6634ce5ed752f",
|
||||
"candidate_source_commit_oid": "a637a9dbb6e0021cb7dcf0d6b0ca00dfe10dce38",
|
||||
"candidate_source_tree_oid": "bf6e0c16fcad7515465bec4aefdd2e77b1e9bef0",
|
||||
"candidate_diff_sha256": "c06d002db06da6cbf16f9c8321f1acbfd431f009b5127a13fd2cb5d63b278867",
|
||||
"candidate_files_sha256": "5061402d516c0e9413208ce64e2b52f77d224e6eec1f7b07c5b3a10b58df5eaf",
|
||||
"candidate_file_count": 44,
|
||||
"schema_document_path": "services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json",
|
||||
"schema_document_sha256": "6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd",
|
||||
"validator_policy_path": "services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py",
|
||||
"validator_policy_sha256": "de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac",
|
||||
"two_stage_policy_schema_sha256": "6b4def7c1eef19c01ef73c43252eb0cd1a87c103e1047249a3cfcc75c7922bf6",
|
||||
"two_stage_release_schema_sha256": "82ee589dc87db6998ddf0779ce264194cadea0deca66088b0797378f6ce89ad3",
|
||||
"runtime_observer_sha256": "181e632192f1417a98c1efb35631cf80246759080b2e04243576abcdc7da22af",
|
||||
"journal_anchor_sha256": "18feb0792b95f1060aa696cc60943379695a246984aecf76098838f9ed37426e",
|
||||
"package_zip_sha256": "668239a549b4a2b2094fe9b5104b84703fe8ed75011fd8ed71ed3958a6dc0706",
|
||||
"candidate_bundle_sha256": "15711b225b9ef41cca0588d21b2b95d7a95ac155efc27fcb8772c435fcdab147",
|
||||
"anchor_install_wheel_sha256": "abbf616366eb3467d4e651bb5306e22ae5e931b613df5362a0892935c4a1c0c7",
|
||||
"tests": {
|
||||
"two_stage_campaign": {"passed": 67, "failed": 0, "skipped": 0, "collection_errors": 0},
|
||||
"single_owner_governance": {"passed": 105, "failed": 0, "subtests_passed": 17, "collection_errors": 0},
|
||||
"task_scoped_bootstrap": {"passed": 15, "failed": 0, "collection_errors": 0},
|
||||
"compileall": "PASS",
|
||||
"quarantine_fsck": "PASS",
|
||||
"systemd_verify": "PASS_WITH_UNRELATED_HOST_WARNINGS"
|
||||
},
|
||||
"anchor": {
|
||||
"service_status": "active",
|
||||
"anchor_uid": 988,
|
||||
"runner_uid": 986,
|
||||
"uids_distinct": true,
|
||||
"runner_database_write": "DENIED",
|
||||
"unauthorized_socket_peer": "DENIED",
|
||||
"runner_registration_action": "ANCHOR_REQUEST_INVALID",
|
||||
"journal_mode": "WAL",
|
||||
"synchronous": "FULL",
|
||||
"foreign_keys": "ON",
|
||||
"restart_open_reservation": "PASS",
|
||||
"selftest_open_reservation_cleanup": "ABORTED"
|
||||
},
|
||||
"phase_separation": {
|
||||
"required_owner_decisions": 2,
|
||||
"phase_a_authorization": "GITEA_EXACT_HEAD_REVIEW",
|
||||
"phase_b_authorization": "DETACHED_SSH_SIGNATURE",
|
||||
"phase_a_release_authority": false,
|
||||
"one_shot_authority": false
|
||||
},
|
||||
"isolation": {
|
||||
"AIOS_GITOPS_WRITES_ENABLED": false,
|
||||
"publisher_created": false,
|
||||
"writer_created": false,
|
||||
"credential_projection_created": false,
|
||||
"target_branch_created": false,
|
||||
"tag_created": false,
|
||||
"registry_modified": false,
|
||||
"baseline_modified": false,
|
||||
"production_modified": false
|
||||
},
|
||||
"governance": {
|
||||
"force_push_used": false,
|
||||
"tag_rewritten": false,
|
||||
"direct_main_push": false,
|
||||
"secrets_committed": false,
|
||||
"owner_approval_respected": true
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
1f4a83cf91e9aacb6f50bc4fb24d4f745a7a31fd1dd7f2d3d3ed0de05e38234f deploy/systemd/aios-campaign-anchor.service
|
||||
6b2525d31b8544488bce1544deb39a087cc2d830fb1b16fda26cde6ce430dbd2 deploy/systemd/aios-policy-activation-verification@.service
|
||||
fad52587775ff5f1c5cc16862c5fb1d910bb097c6b3330c00d75db4f7bef0bbd deploy/systemd/aios-policy-campaign-register@.service
|
||||
de11123b5cd9ccdad4961f1d5d084a8c4a1b2270ce793652ab9c50bb95694eac services/aios-single-owner-governance/aios_single_owner_governance/task_scoped_bootstrap.py
|
||||
6ec912a96c8bac5c0d3c0a017abc078cb9567ed54dcb20bb0eadb5926ac54fdd services/aios-single-owner-governance/task-scoped-governance-bootstrap-v1.schema.json
|
||||
5b6d65ae34b2c3bebc1bde8f38c6b0bb73269336d7d4ee5e3416f79c323134d6 services/aios-two-stage-owner-campaign/ANCHOR_REGISTRATION_CONTRACT.md
|
||||
8ba5278f96447bf4308813b49fcc433d0cc7a5019cd9e78aeb0d8ada5f00d53b services/aios-two-stage-owner-campaign/README.md
|
||||
7285527358bc8da1d4bc7ff70162dfc3a734086851b734daac89d6f9b330798d services/aios-two-stage-owner-campaign/SECURITY_DELTA_V2.md
|
||||
89f03fdf156d35807bf39f2f1dbf304c01e7e9ad64399276fb72c68d795eda65 services/aios-two-stage-owner-campaign/STEP_EXECUTOR_CONTRACT.md
|
||||
7453177223b62509e4854051a75d53f24d8d1f737986f309cc6ae7a2e721459f services/aios-two-stage-owner-campaign/TWO_STAGE_OWNER_INTERACTION_SPEC.md
|
||||
9308ee245a28a0f0ff623fbfc8e3961204b8e67194bffe536a9c3485ca126ac7 services/aios-two-stage-owner-campaign/examples/allowed_signers.example
|
||||
9ac7b7fdeb73a99d4f41bf3410ef16f67091d85f9082075287d388e6e5e37eed services/aios-two-stage-owner-campaign/examples/campaign-anchor.env.example
|
||||
926f0c0cfb7bd6db0ebab6bcb5a0530057b8d38ae1e0b436a69a12b44039462b services/aios-two-stage-owner-campaign/examples/executor-release.example.json
|
||||
8d46ec9279eb58c03337d41b63de2abdd9eb0d03f98f0806768dcd309d481ee9 services/aios-two-stage-owner-campaign/examples/policy-activation-verification.example.json
|
||||
b34d8895fe872ef27c62c759449757def698eb05157daff8badd0c86f64ee18c services/aios-two-stage-owner-campaign/examples/release-campaign-manifest.example.json
|
||||
a2992f493cf0547e1f4acd3fcd9b20e03c912d8b255e196f640d47e291ec9d8e services/aios-two-stage-owner-campaign/examples/runtime-observer-policy.example.json
|
||||
150c9a8debdcaa4dbb9fd51817ca8710ef805a32f2f96dc5490d0c4f77f2cb6f services/aios-two-stage-owner-campaign/examples/runtime-observer-release.example.json
|
||||
675b39d13223ad281a4d14a04e739639e470e4e2a2591b85264ba37f840f2b49 services/aios-two-stage-owner-campaign/payload/scripts/generate_diff_chunks.py
|
||||
5751764275e626c787dad17c2561edd86b2710ae0b3cfeafeec44d98126d9015 services/aios-two-stage-owner-campaign/payload/services/aios-autonomous-control-plane/aios_autonomous_control_plane/lineage_audit.py
|
||||
2b501bf32a22e1b10c7254d2268d11aa2424aac5756c52441557c25dbaaaa8d5 services/aios-two-stage-owner-campaign/payload/tests/autonomous_control_plane/test_lineage_audit_v3.py
|
||||
3f118bc7a4f2bdfdd47e2c86112e87f95162dba4d88c1579337bd1d442ec9832 services/aios-two-stage-owner-campaign/pyproject.toml
|
||||
6b4def7c1eef19c01ef73c43252eb0cd1a87c103e1047249a3cfcc75c7922bf6 services/aios-two-stage-owner-campaign/schemas/governance-policy-activation-verification-v1.schema.json
|
||||
82ee589dc87db6998ddf0779ce264194cadea0deca66088b0797378f6ce89ad3 services/aios-two-stage-owner-campaign/schemas/task-scoped-release-campaign-v1.schema.json
|
||||
d04543b5407dcefc0a41af1b8a65ebc2e62f779582ae959449f1ac37b305eecf services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/__init__.py
|
||||
935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/__main__.py
|
||||
4e317e2fbf912662bfbf57d2f7fe1a9f7fd3d8c00f7ad09602d9e885ee4ef3cc services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/canonical.py
|
||||
863be28723553e5bf5df90eda49e96edf8417e765da7b41579f050b04336d480 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/cli.py
|
||||
dae1e0ed0f841d928a1dd5094c64b1f39b3213301c1da747f45d032a18833c1e services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/errors.py
|
||||
baf8931566d2c2fb2985d1814b5ded89719bb4b0eba01e94cca9f3690baadeb2 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/executor.py
|
||||
18feb0792b95f1060aa696cc60943379695a246984aecf76098838f9ed37426e services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/journal_anchor.py
|
||||
e24765d3c62f9934a921f099e43a002d349a6c9934438da82040e40238070c58 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/orchestrator.py
|
||||
181e632192f1417a98c1efb35631cf80246759080b2e04243576abcdc7da22af services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/runtime_observer.py
|
||||
3f3ce81490b6f0893665ba296fc23be904ae0e5dcbcd3b602e25feb2571262b0 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/signature.py
|
||||
c71d85d5df2ed0e5367de9aacd230f586e77f3b4c11cf52960c84bbdeec43eb7 services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/state_machine.py
|
||||
75ea8ed1c9b49b1ca3ce452fe229524ebd0ccd802945d3362dd668602ce1f98c services/aios-two-stage-owner-campaign/src/aios_two_stage_campaign/validator.py
|
||||
b1be7e1ed0fa0e16e041f77200d651cf46f6bb029c89d31f0b286d32c026cb66 services/aios-two-stage-owner-campaign/tests/test_canonical_snapshot.py
|
||||
0bb956135c90cf71fcb655c4d700c1f71c3442b9e9fddc376959890cdad823de services/aios-two-stage-owner-campaign/tests/test_executor_v2.py
|
||||
9bb8a9f1c3bd9aaf44db3dd2f5b810eb0cb650da0e5a5f5e2ea50be46f12664d services/aios-two-stage-owner-campaign/tests/test_lineage_payload.py
|
||||
681c14ddc0be90f94fd3c3d8a6768fe602ec8acd130ed00a8668505d2db57aa2 services/aios-two-stage-owner-campaign/tests/test_orchestrator_v2.py
|
||||
9edf44fe0129098c31d66f6b6f7ab252879b425e2844969d09e22c3c88e6b77d services/aios-two-stage-owner-campaign/tests/test_runtime_observer.py
|
||||
204e77c760380f8e29d10fc0afa4227497109d27493245c55a851de6ff69ac86 services/aios-two-stage-owner-campaign/tests/test_signature.py
|
||||
9bc5dfa237e6bf37ccc90bbc618a807892d323cdd41345717b296838b44cd22a services/aios-two-stage-owner-campaign/tests/test_state_machine.py
|
||||
a9ef9c11120f480e0cde3ccbf8a816705621506657d8ac10faf7e38fb54bf367 services/aios-two-stage-owner-campaign/tests/test_validator.py
|
||||
4ec67865474c6c7ebaa7d125490486e8644618b1666cbde597420e4e6fe8f1d4 tests/single_owner_governance/test_task_scoped_bootstrap.py
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
from .task_status_merge_broker import ContractDenied, TaskGrant, canonical, load_signed_task_grant, read_runtime_secret
|
||||
|
||||
|
||||
GITEA_BIN = Path("/data/aios-gitops/runtime/bin/gitea")
|
||||
GITEA_CONFIG = Path("/data/aios-gitops/runtime/gitea-bin/custom/conf/app.ini")
|
||||
GITEA_DB = Path("/data/aios-gitops/runtime/gitea-bin/data/gitea.db")
|
||||
RUNUSER = Path("/usr/sbin/runuser")
|
||||
SYSTEMD_CREDS = Path("/usr/bin/systemd-creds")
|
||||
GIT = Path("/usr/bin/git")
|
||||
GITEA_REPOSITORY = Path("/data/aios-gitops/runtime/gitea-bin/data/repositories/aios/aios.git")
|
||||
|
||||
|
||||
def _git(*arguments: str, input_bytes: bytes | None = None) -> bytes:
|
||||
return subprocess.run(
|
||||
[str(GIT), f"--git-dir={GITEA_REPOSITORY}", *arguments], input=input_bytes,
|
||||
check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
).stdout
|
||||
|
||||
|
||||
def _verify_local_governance_binding(grant: TaskGrant) -> None:
|
||||
"""Verify the exact open PR and latest Owner review without issuing a token."""
|
||||
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
|
||||
connection.row_factory = sqlite3.Row
|
||||
try:
|
||||
pr = connection.execute(
|
||||
"SELECT pr.head_branch,pr.base_branch,pr.merge_base,pr.has_merged,i.is_closed "
|
||||
"FROM pull_request pr JOIN issue i ON i.id=pr.issue_id JOIN repository repo ON repo.id=i.repo_id "
|
||||
"WHERE repo.owner_name='aios' AND repo.lower_name='aios' AND pr.[index]=?",
|
||||
(grant.raw["pr_number"],),
|
||||
).fetchone()
|
||||
review = connection.execute(
|
||||
"SELECT r.type,r.commit_id,r.official,r.stale,r.dismissed,r.created_unix,u.id,u.lower_name "
|
||||
"FROM review r JOIN user u ON u.id=r.reviewer_id JOIN issue i ON i.id=r.issue_id "
|
||||
"JOIN repository repo ON repo.id=i.repo_id "
|
||||
"WHERE repo.owner_name='aios' AND repo.lower_name='aios' AND i.[index]=? "
|
||||
"AND u.id=2 AND u.lower_name='owner' ORDER BY r.id DESC LIMIT 1",
|
||||
(grant.raw["pr_number"],),
|
||||
).fetchone()
|
||||
finally:
|
||||
connection.close()
|
||||
if pr is None or pr["base_branch"] != "governance/approvals" or pr["merge_base"] != grant.raw["base_oid"] or pr["has_merged"] != 0 or pr["is_closed"] != 0:
|
||||
raise ContractDenied("LOCAL_PR_BINDING_INVALID")
|
||||
head = _git("rev-parse", f"refs/heads/{pr['head_branch']}").decode().strip()
|
||||
base = _git("rev-parse", "refs/heads/governance/approvals").decode().strip()
|
||||
if head != grant.raw["target_commit"] or base != grant.raw["base_oid"]:
|
||||
raise ContractDenied("LOCAL_REF_BINDING_INVALID")
|
||||
if review is None or review["type"] != 1 or review["commit_id"] != head or review["official"] != 1 or review["stale"] != 0 or review["dismissed"] != 0:
|
||||
raise ContractDenied("LOCAL_OWNER_APPROVAL_MISSING")
|
||||
submitted = datetime.fromtimestamp(review["created_unix"], tz=timezone.utc)
|
||||
if submitted < grant.issued_at or submitted >= grant.expires_at:
|
||||
raise ContractDenied("LOCAL_OWNER_APPROVAL_EXPIRED")
|
||||
tree = _git("show", "-s", "--format=%T", head).decode().strip()
|
||||
if tree != grant.raw["approved_tree_oid"]:
|
||||
raise ContractDenied("APPROVED_TREE_MISMATCH")
|
||||
entry = _git("ls-tree", head, "--", grant.raw["manifest_path"]).decode().strip().split()
|
||||
if len(entry) < 3 or entry[1] != "blob" or entry[2] != grant.raw["manifest_blob_oid"]:
|
||||
raise ContractDenied("MANIFEST_BLOB_BINDING_INVALID")
|
||||
manifest = _git("cat-file", "blob", grant.raw["manifest_blob_oid"])
|
||||
if hashlib.sha256(manifest).hexdigest() != grant.raw["manifest_sha256"]:
|
||||
raise ContractDenied("MANIFEST_SHA256_MISMATCH")
|
||||
|
||||
|
||||
def _safe_absolute(path: Path, expected_parent: Path) -> None:
|
||||
if not path.is_absolute() or path.is_symlink() or path.parent != expected_parent:
|
||||
raise ContractDenied("CREDENTIAL_PATH_UNSAFE")
|
||||
|
||||
|
||||
class TaskCredentialBroker:
|
||||
def __init__(self, grant: TaskGrant, audit_dir: Path, audit_key: bytes):
|
||||
self.grant = grant
|
||||
self.audit_key = bytes(audit_key)
|
||||
if not self.audit_key:
|
||||
raise ContractDenied("CREDENTIAL_AUDIT_KEY_EMPTY")
|
||||
self.audit_dir = Path(audit_dir)
|
||||
if not self.audit_dir.is_absolute() or self.audit_dir.is_symlink():
|
||||
raise ContractDenied("AUDIT_DIR_UNSAFE")
|
||||
|
||||
def provision(self, *, identity: str, token_name: str, encrypted_path: Path) -> dict:
|
||||
if os.geteuid() != 0:
|
||||
raise ContractDenied("ROOT_BROKER_REQUIRED")
|
||||
expected = self.grant.raw["status_identity"] if token_name.endswith("-status") else self.grant.raw["merge_identity"]
|
||||
if identity != expected or identity not in {"codex", "gpt"}:
|
||||
raise ContractDenied("IDENTITY_BINDING_INVALID")
|
||||
prefix = f"pr{self.grant.raw['pr_number']}-{self.grant.raw['target_commit'][:12]}"
|
||||
if token_name not in {f"{prefix}-status", f"{prefix}-merge"}:
|
||||
raise ContractDenied("TOKEN_NAME_INVALID")
|
||||
_safe_absolute(encrypted_path, Path("/run/aios-task-credential-broker"))
|
||||
if encrypted_path.exists():
|
||||
raise ContractDenied("CREDENTIAL_PATH_EXISTS")
|
||||
_verify_local_governance_binding(self.grant)
|
||||
command = [str(RUNUSER), "-u", "aiman", "--", str(GITEA_BIN), "admin", "user", "generate-access-token", "--config", str(GITEA_CONFIG), "--username", identity, "--token-name", token_name, "--scopes", "write:repository", "--raw"]
|
||||
issued = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
|
||||
if len(issued) < 32 or b"\n" in issued or b"\x00" in issued:
|
||||
raise ContractDenied("ISSUED_TOKEN_INVALID")
|
||||
subprocess.run([str(SYSTEMD_CREDS), "encrypt", "-", str(encrypted_path)], input=issued, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
|
||||
os.chmod(encrypted_path, 0o400)
|
||||
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
|
||||
try:
|
||||
row = connection.execute("SELECT t.id,u.id FROM access_token t JOIN user u ON u.id=t.uid WHERE u.lower_name=? AND t.name=? AND t.scope='write:repository'", (identity, token_name)).fetchone()
|
||||
finally:
|
||||
connection.close()
|
||||
if row is None:
|
||||
raise ContractDenied("TOKEN_DATABASE_BINDING_MISSING")
|
||||
receipt = {"status": "PASS", "operation": "credential_provision", "identity": identity, "token_name": token_name, "token_id": int(row[0]), "token_uid": int(row[1]), "grant_sha256": self.grant.digest, "credential_ref": f"systemd-credential-encrypted://{encrypted_path.name}"}
|
||||
return self._audit(receipt)
|
||||
|
||||
def revoke(self, *, receipt: dict, encrypted_path: Path) -> dict:
|
||||
if os.geteuid() != 0:
|
||||
raise ContractDenied("ROOT_BROKER_REQUIRED")
|
||||
_safe_absolute(encrypted_path, Path("/run/aios-task-credential-broker"))
|
||||
self.validate_provision_receipt(receipt, encrypted_path)
|
||||
decrypted = subprocess.run([str(SYSTEMD_CREDS), "decrypt", str(encrypted_path), "-"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
|
||||
if len(decrypted) < 32 or b"\n" in decrypted or b"\x00" in decrypted:
|
||||
raise ContractDenied("PROJECTED_TOKEN_INVALID")
|
||||
token_header = {"Authorization": "token " + decrypted.decode("utf-8")}
|
||||
preflight = urllib.request.Request("http://127.0.0.1:3000/api/v1/repos/aios/aios", headers=token_header)
|
||||
try:
|
||||
with urllib.request.urlopen(preflight, timeout=10) as response:
|
||||
if response.status != 200:
|
||||
raise ContractDenied("TOKEN_PREFLIGHT_STATUS_INVALID")
|
||||
except urllib.error.HTTPError as exc:
|
||||
raise ContractDenied(f"TOKEN_PREFLIGHT_FAILED:{exc.code}") from exc
|
||||
connection = sqlite3.connect(GITEA_DB)
|
||||
try:
|
||||
connection.execute("BEGIN IMMEDIATE")
|
||||
cursor = connection.execute(
|
||||
"DELETE FROM access_token WHERE id=? AND uid=? AND name=? AND scope='write:repository'",
|
||||
(receipt["token_id"], receipt["token_uid"], receipt["token_name"]),
|
||||
)
|
||||
if cursor.rowcount != 1:
|
||||
raise ContractDenied("TOKEN_REVOCATION_MISMATCH")
|
||||
connection.commit()
|
||||
except Exception:
|
||||
connection.rollback()
|
||||
raise
|
||||
finally:
|
||||
connection.close()
|
||||
connection = sqlite3.connect(f"file:{GITEA_DB}?mode=ro", uri=True)
|
||||
try:
|
||||
remaining = connection.execute("SELECT COUNT(*) FROM access_token WHERE id=?", (receipt["token_id"],)).fetchone()[0]
|
||||
finally:
|
||||
connection.close()
|
||||
if remaining != 0:
|
||||
raise ContractDenied("TOKEN_REVOCATION_READBACK_MISMATCH")
|
||||
request = urllib.request.Request("http://127.0.0.1:3000/api/v1/repos/aios/aios", headers=token_header)
|
||||
try:
|
||||
urllib.request.urlopen(request, timeout=10)
|
||||
raise ContractDenied("REVOKED_TOKEN_STILL_ACCEPTED")
|
||||
except urllib.error.HTTPError as exc:
|
||||
if exc.code != 401:
|
||||
raise ContractDenied("REVOCATION_HTTP_STATUS_INVALID") from exc
|
||||
encrypted_path.unlink(missing_ok=True)
|
||||
result = {"status": "PASS", "operation": "credential_revoke", "identity": receipt["identity"], "token_name": receipt["token_name"], "token_id": receipt["token_id"], "grant_sha256": self.grant.digest, "token_rows_remaining": 0, "credential_projection_remaining": False, "old_token_http_status": 401}
|
||||
return self._audit(result)
|
||||
|
||||
def validate_provision_receipt(self, receipt: dict, encrypted_path: Path) -> None:
|
||||
required = {"status", "operation", "identity", "token_name", "token_id", "token_uid", "grant_sha256", "credential_ref", "audit_sha256", "audit_hmac_signature"}
|
||||
expected_credential_ref = f"systemd-credential-encrypted://{encrypted_path.name}"
|
||||
unsigned_receipt = {key: value for key, value in receipt.items() if key not in {"audit_sha256", "audit_hmac_signature"}}
|
||||
expected_name_prefix = f"pr{self.grant.raw['pr_number']}-{self.grant.raw['target_commit'][:12]}"
|
||||
if (set(receipt) != required or receipt["status"] != "PASS" or receipt["operation"] != "credential_provision"
|
||||
or receipt["grant_sha256"] != self.grant.digest or receipt["identity"] not in {self.grant.raw["status_identity"], self.grant.raw["merge_identity"]}
|
||||
or receipt["token_name"] not in {f"{expected_name_prefix}-status", f"{expected_name_prefix}-merge"}
|
||||
or receipt["credential_ref"] != expected_credential_ref
|
||||
or hashlib.sha256(canonical(unsigned_receipt)).hexdigest() != receipt["audit_sha256"]
|
||||
or not hmac.compare_digest(receipt["audit_hmac_signature"], hmac.new(self.audit_key, canonical(unsigned_receipt), hashlib.sha256).hexdigest())):
|
||||
raise ContractDenied("PROVISION_RECEIPT_INVALID")
|
||||
|
||||
def _audit(self, value: dict) -> dict:
|
||||
raw = canonical(value)
|
||||
result = dict(value)
|
||||
result["audit_sha256"] = hashlib.sha256(raw).hexdigest()
|
||||
result["audit_hmac_signature"] = hmac.new(self.audit_key, raw, hashlib.sha256).hexdigest()
|
||||
self.audit_dir.mkdir(mode=0o750, parents=True, exist_ok=True)
|
||||
destination = self.audit_dir / f"{value['operation']}-{value['token_name']}.json"
|
||||
descriptor = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0), 0o640)
|
||||
try:
|
||||
os.write(descriptor, canonical(result) + b"\n")
|
||||
os.fsync(descriptor)
|
||||
finally:
|
||||
os.close(descriptor)
|
||||
return result
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(prog="aios-task-credential-broker")
|
||||
parser.add_argument("--grant", required=True, type=Path)
|
||||
parser.add_argument("--audit-dir", required=True, type=Path)
|
||||
parser.add_argument("--operation", choices=("provision", "revoke"))
|
||||
parser.add_argument("--identity")
|
||||
parser.add_argument("--token-name")
|
||||
parser.add_argument("--encrypted-path", type=Path)
|
||||
parser.add_argument("--receipt", type=Path)
|
||||
parser.add_argument("--request", type=Path)
|
||||
parser.add_argument("--grant-signature", required=True, type=Path)
|
||||
parser.add_argument("--allowed-signers", required=True, type=Path)
|
||||
parser.add_argument("--audit-key", required=True, type=Path)
|
||||
args = parser.parse_args(argv)
|
||||
grant = load_signed_task_grant(args.grant, args.grant_signature, args.allowed_signers)
|
||||
broker = TaskCredentialBroker(grant, args.audit_dir, read_runtime_secret(args.audit_key))
|
||||
if args.request is not None:
|
||||
request = json.loads(args.request.read_text(encoding="utf-8"))
|
||||
if not isinstance(request, dict) or set(request) not in ({"operation", "identity", "token_name", "encrypted_path"}, {"operation", "identity", "token_name", "encrypted_path", "receipt"}):
|
||||
raise ContractDenied("CREDENTIAL_REQUEST_INVALID")
|
||||
args.operation = request["operation"]
|
||||
args.identity = request["identity"]
|
||||
args.token_name = request["token_name"]
|
||||
args.encrypted_path = Path(request["encrypted_path"])
|
||||
args.receipt = Path(request["receipt"]) if "receipt" in request else None
|
||||
if args.operation is None or args.identity is None or args.token_name is None or args.encrypted_path is None:
|
||||
raise ContractDenied("CREDENTIAL_REQUEST_INCOMPLETE")
|
||||
if args.operation == "provision":
|
||||
result = broker.provision(identity=args.identity, token_name=args.token_name, encrypted_path=args.encrypted_path)
|
||||
else:
|
||||
if args.receipt is None:
|
||||
raise ContractDenied("RECEIPT_REQUIRED")
|
||||
result = broker.revoke(receipt=json.loads(args.receipt.read_text(encoding="utf-8")), encrypted_path=args.encrypted_path)
|
||||
print(json.dumps(result, sort_keys=True, separators=(",", ":")))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
import subprocess
|
||||
|
||||
from .task_credential_broker import SYSTEMD_CREDS, TaskCredentialBroker
|
||||
from .task_status_merge_broker import ContractDenied, load_signed_task_grant
|
||||
|
||||
|
||||
RUNTIME_ROOT = Path("/var/lib/aios-gitops/runtime/task-status-merge")
|
||||
CREDENTIAL_ROOT = Path("/run/aios-task-credential-broker")
|
||||
|
||||
|
||||
def _operation_complete(task_dir: Path, token_name: str) -> bool:
|
||||
if token_name.endswith("-status"):
|
||||
journal, operation = task_dir / "status-journal" / "journal.sqlite3", "statuses"
|
||||
elif token_name.endswith("-merge"):
|
||||
journal, operation = task_dir / "merge-journal" / "journal.sqlite3", "merge"
|
||||
else:
|
||||
raise ContractDenied("SWEEPER_TOKEN_NAME_INVALID")
|
||||
if not journal.is_file() or journal.is_symlink():
|
||||
return False
|
||||
connection = sqlite3.connect(f"file:{journal}?mode=ro", uri=True)
|
||||
try:
|
||||
row = connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
|
||||
finally:
|
||||
connection.close()
|
||||
return row == ("COMMITTED",)
|
||||
|
||||
|
||||
def sweep(runtime_root: Path, allowed_signers: Path, *, now: datetime | None = None) -> list[dict]:
|
||||
if os.geteuid() != 0:
|
||||
raise ContractDenied("ROOT_SWEEPER_REQUIRED")
|
||||
if runtime_root != RUNTIME_ROOT or runtime_root.is_symlink():
|
||||
raise ContractDenied("SWEEPER_ROOT_INVALID")
|
||||
current = now or datetime.now(timezone.utc)
|
||||
results: list[dict] = []
|
||||
for task_dir in sorted(runtime_root.iterdir() if runtime_root.exists() else []):
|
||||
if not task_dir.is_dir() or task_dir.is_symlink():
|
||||
raise ContractDenied("SWEEPER_TASK_DIR_INVALID")
|
||||
grant_path, signature_path = task_dir / "grant.json", task_dir / "grant.sig"
|
||||
if not grant_path.is_file() or not signature_path.is_file():
|
||||
raise ContractDenied("SWEEPER_GRANT_INCOMPLETE")
|
||||
grant = load_signed_task_grant(grant_path, signature_path, allowed_signers, now=current, allow_expired=True)
|
||||
audit_credential = CREDENTIAL_ROOT / f"{task_dir.name}-audit.cred"
|
||||
if not audit_credential.is_file() or audit_credential.is_symlink():
|
||||
raise ContractDenied("SWEEPER_TASK_AUDIT_CREDENTIAL_MISSING")
|
||||
audit_key = subprocess.run(
|
||||
[str(SYSTEMD_CREDS), "decrypt", str(audit_credential), "-"], check=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
).stdout.strip()
|
||||
if not audit_key or b"\n" in audit_key or b"\x00" in audit_key:
|
||||
raise ContractDenied("SWEEPER_TASK_AUDIT_KEY_INVALID")
|
||||
broker = TaskCredentialBroker(grant, task_dir / "audit", audit_key)
|
||||
for receipt_path in sorted((task_dir / "audit").glob("credential_provision-*.json")):
|
||||
if receipt_path.is_symlink():
|
||||
raise ContractDenied("SWEEPER_RECEIPT_UNSAFE")
|
||||
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
||||
token_name = str(receipt.get("token_name") or "")
|
||||
credential_ref = str(receipt.get("credential_ref") or "")
|
||||
prefix = "systemd-credential-encrypted://"
|
||||
if not credential_ref.startswith(prefix):
|
||||
raise ContractDenied("SWEEPER_CREDENTIAL_REF_INVALID")
|
||||
encrypted_path = CREDENTIAL_ROOT / credential_ref.removeprefix(prefix)
|
||||
revoked_receipt = task_dir / "audit" / f"credential_revoke-{token_name}.json"
|
||||
if revoked_receipt.exists():
|
||||
if encrypted_path.exists():
|
||||
raise ContractDenied("SWEEPER_REVOKED_PROJECTION_REAPPEARED")
|
||||
continue
|
||||
if current < grant.expires_at and not _operation_complete(task_dir, token_name):
|
||||
continue
|
||||
if not encrypted_path.is_file() or encrypted_path.is_symlink():
|
||||
raise ContractDenied("SWEEPER_CREDENTIAL_PROJECTION_MISSING")
|
||||
results.append(broker.revoke(receipt=receipt, encrypted_path=encrypted_path))
|
||||
return results
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(prog="aios-task-credential-expiry-sweeper")
|
||||
parser.add_argument("--runtime-root", required=True, type=Path)
|
||||
parser.add_argument("--allowed-signers", required=True, type=Path)
|
||||
args = parser.parse_args(argv)
|
||||
result = sweep(args.runtime_root, args.allowed_signers)
|
||||
print(json.dumps({"status": "PASS", "revoked": result}, sort_keys=True, separators=(",", ":")))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
+1090
File diff suppressed because it is too large
Load Diff
+436
@@ -0,0 +1,436 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sqlite3
|
||||
import stat
|
||||
import subprocess
|
||||
from typing import Any, Protocol
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
|
||||
ALLOWED_CONTEXTS = frozenset({
|
||||
"aios/branch-protection",
|
||||
"aios/evidence-closure",
|
||||
"aios/secret-scan",
|
||||
"aios/state-machine",
|
||||
"aios/validator",
|
||||
})
|
||||
ALLOWED_IDENTITIES = frozenset({"codex", "gpt"})
|
||||
OID = re.compile(r"^[0-9a-f]{40}$")
|
||||
SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
||||
SECRET_REF = re.compile(r"^systemd-credential://[A-Za-z0-9_.-]+$")
|
||||
SUPERSEDED_PR_NUMBER = 36
|
||||
SUPERSEDED_HEAD_OID = "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"
|
||||
FIELDS = frozenset({
|
||||
"schema_id", "schema_version", "repository", "pr_number", "base_oid",
|
||||
"target_commit", "approved_tree_oid", "manifest_path", "manifest_blob_oid", "manifest_sha256",
|
||||
"payload_sha256", "status_identity", "merge_identity", "status_contexts",
|
||||
"status_write_quota", "merge_quota", "merge_method", "branch_push_allowed",
|
||||
"tag_write_allowed", "main_write_allowed", "registry_write_allowed",
|
||||
"baseline_write_allowed", "production_write_allowed", "issued_at", "expires_at",
|
||||
"audit_key_ref", "grant_signer_identity", "grant_signature_namespace",
|
||||
"status_evidence_sha256", "supersedes_pr_number", "supersedes_head_oid",
|
||||
"renewal_required",
|
||||
})
|
||||
|
||||
|
||||
class ContractDenied(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def canonical(value: Any) -> bytes:
|
||||
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
|
||||
|
||||
|
||||
def _time(value: str) -> datetime:
|
||||
if not isinstance(value, str) or not value.endswith("Z"):
|
||||
raise ContractDenied("TIMESTAMP_INVALID")
|
||||
try:
|
||||
return datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||
except ValueError as exc:
|
||||
raise ContractDenied("TIMESTAMP_INVALID") from exc
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TaskGrant:
|
||||
raw: dict[str, Any]
|
||||
issued_at: datetime
|
||||
expires_at: datetime
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, value: dict[str, Any], *, now: datetime | None = None,
|
||||
allow_expired: bool = False) -> "TaskGrant":
|
||||
if not isinstance(value, dict) or set(value) != FIELDS:
|
||||
raise ContractDenied("GRANT_FIELDS_INVALID")
|
||||
if value["schema_id"] != "AIOS_TASK_STATUS_MERGE_GRANT" or value["schema_version"] != 1:
|
||||
raise ContractDenied("GRANT_SCHEMA_INVALID")
|
||||
if value["repository"] != "aios/aios" or type(value["pr_number"]) is not int or value["pr_number"] <= 0:
|
||||
raise ContractDenied("REPOSITORY_OR_PR_MISMATCH")
|
||||
for field in ("base_oid", "target_commit", "approved_tree_oid", "manifest_blob_oid"):
|
||||
if not isinstance(value[field], str) or not OID.fullmatch(value[field]):
|
||||
raise ContractDenied("OID_INVALID")
|
||||
if not isinstance(value["manifest_path"], str) or not re.fullmatch(r"approvals/[A-Za-z0-9._/-]+\.json", value["manifest_path"]) or ".." in value["manifest_path"].split("/"):
|
||||
raise ContractDenied("MANIFEST_PATH_INVALID")
|
||||
for field in ("manifest_sha256", "payload_sha256"):
|
||||
if not isinstance(value[field], str) or not SHA256.fullmatch(value[field]):
|
||||
raise ContractDenied("SHA256_INVALID")
|
||||
evidence = value["status_evidence_sha256"]
|
||||
if not isinstance(evidence, dict) or set(evidence) != ALLOWED_CONTEXTS or any(not isinstance(item, str) or not SHA256.fullmatch(item) for item in evidence.values()):
|
||||
raise ContractDenied("STATUS_EVIDENCE_BINDING_INVALID")
|
||||
if value["supersedes_pr_number"] != SUPERSEDED_PR_NUMBER or value["pr_number"] == SUPERSEDED_PR_NUMBER:
|
||||
raise ContractDenied("RENEWAL_PR_INVALID")
|
||||
if value["supersedes_head_oid"] != SUPERSEDED_HEAD_OID or value["supersedes_head_oid"] == value["target_commit"] or value["renewal_required"] is not True:
|
||||
raise ContractDenied("RENEWAL_BINDING_INVALID")
|
||||
if value["status_identity"] not in ALLOWED_IDENTITIES or value["merge_identity"] not in ALLOWED_IDENTITIES:
|
||||
raise ContractDenied("IDENTITY_NOT_ALLOWED")
|
||||
if set(value["status_contexts"]) != ALLOWED_CONTEXTS or len(value["status_contexts"]) != 5:
|
||||
raise ContractDenied("STATUS_CONTEXTS_INVALID")
|
||||
if value["status_write_quota"] != 5 or value["merge_quota"] != 1:
|
||||
raise ContractDenied("QUOTA_INVALID")
|
||||
if value["merge_method"] != "fast-forward-only":
|
||||
raise ContractDenied("MERGE_METHOD_INVALID")
|
||||
denied = (
|
||||
"branch_push_allowed", "tag_write_allowed", "main_write_allowed",
|
||||
"registry_write_allowed", "baseline_write_allowed", "production_write_allowed",
|
||||
)
|
||||
if any(value[field] is not False for field in denied):
|
||||
raise ContractDenied("WRITE_SCOPE_EXPANDED")
|
||||
if not isinstance(value["audit_key_ref"], str) or not SECRET_REF.fullmatch(value["audit_key_ref"]):
|
||||
raise ContractDenied("AUDIT_KEY_REFERENCE_INVALID")
|
||||
if value["grant_signer_identity"] != "aios-task-grant-signer" or value["grant_signature_namespace"] != "aios-task-status-merge-grant-v1":
|
||||
raise ContractDenied("GRANT_SIGNATURE_POLICY_INVALID")
|
||||
issued, expires = _time(value["issued_at"]), _time(value["expires_at"])
|
||||
current = now or datetime.now(timezone.utc)
|
||||
lifetime = (expires - issued).total_seconds()
|
||||
if lifetime <= 0 or lifetime > 12 * 3600 or (not allow_expired and current >= expires):
|
||||
raise ContractDenied("GRANT_EXPIRED_OR_LIFETIME_INVALID")
|
||||
return cls(dict(value), issued, expires)
|
||||
|
||||
@property
|
||||
def digest(self) -> str:
|
||||
return hashlib.sha256(canonical(self.raw)).hexdigest()
|
||||
|
||||
|
||||
def load_signed_task_grant(grant_path: Path, signature_path: Path, allowed_signers: Path,
|
||||
*, now: datetime | None = None, allow_expired: bool = False) -> TaskGrant:
|
||||
for path in (grant_path, signature_path, allowed_signers):
|
||||
if not path.is_absolute() or path.is_symlink():
|
||||
raise ContractDenied("GRANT_SIGNATURE_PATH_UNSAFE")
|
||||
raw = grant_path.read_bytes()
|
||||
if len(raw) > 1024 * 1024:
|
||||
raise ContractDenied("GRANT_TOO_LARGE")
|
||||
try:
|
||||
value = json.loads(raw)
|
||||
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
||||
raise ContractDenied("GRANT_JSON_INVALID") from exc
|
||||
if raw != canonical(value) + b"\n":
|
||||
raise ContractDenied("GRANT_NOT_CANONICAL")
|
||||
grant = TaskGrant.from_dict(value, now=now, allow_expired=allow_expired)
|
||||
command = [
|
||||
"/usr/bin/ssh-keygen", "-Y", "verify", "-f", str(allowed_signers),
|
||||
"-I", "aios-task-grant-signer", "-n", "aios-task-status-merge-grant-v1",
|
||||
"-s", str(signature_path),
|
||||
]
|
||||
try:
|
||||
subprocess.run(command, input=raw, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
|
||||
except (OSError, subprocess.CalledProcessError) as exc:
|
||||
raise ContractDenied("GRANT_SIGNATURE_INVALID") from exc
|
||||
return grant
|
||||
|
||||
|
||||
class API(Protocol):
|
||||
def get(self, path: str) -> Any: ...
|
||||
def post(self, path: str, payload: dict[str, Any]) -> Any: ...
|
||||
|
||||
|
||||
def read_runtime_secret(path: Path) -> bytes:
|
||||
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
|
||||
descriptor = os.open(path, flags)
|
||||
try:
|
||||
metadata = os.fstat(descriptor)
|
||||
if not stat.S_ISREG(metadata.st_mode) or stat.S_IMODE(metadata.st_mode) & 0o077:
|
||||
raise ContractDenied("CREDENTIAL_FILE_UNSAFE")
|
||||
value = os.read(descriptor, 16 * 1024 + 1)
|
||||
finally:
|
||||
os.close(descriptor)
|
||||
if not value or len(value) > 16 * 1024 or b"\x00" in value or b"\n" in value.strip():
|
||||
raise ContractDenied("CREDENTIAL_CONTENT_INVALID")
|
||||
return value.strip()
|
||||
|
||||
|
||||
class _NoRedirect(urllib.request.HTTPRedirectHandler):
|
||||
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||
return None
|
||||
|
||||
|
||||
class GiteaClient:
|
||||
def __init__(self, token_path: Path, api_base: str = "http://127.0.0.1:3000/api/v1"):
|
||||
parsed = urllib.parse.urlparse(api_base)
|
||||
if parsed.scheme != "http" or parsed.hostname != "127.0.0.1" or parsed.path.rstrip("/") != "/api/v1" or parsed.username or parsed.password or parsed.query or parsed.fragment:
|
||||
raise ContractDenied("GITEA_API_ORIGIN_INVALID")
|
||||
self.token_path = Path(token_path)
|
||||
self.api_base = api_base.rstrip("/")
|
||||
self.opener = urllib.request.build_opener(_NoRedirect)
|
||||
|
||||
def _request(self, method: str, path: str, payload: dict[str, Any] | None = None) -> Any:
|
||||
if not path.startswith("/") or ".." in path.split("/"):
|
||||
raise ContractDenied("GITEA_API_PATH_INVALID")
|
||||
token = read_runtime_secret(self.token_path).decode("utf-8")
|
||||
body = canonical(payload) if payload is not None else None
|
||||
request = urllib.request.Request(self.api_base + path, data=body, method=method, headers={"Authorization": f"token {token}", "Content-Type": "application/json", "Accept": "application/json"})
|
||||
try:
|
||||
with self.opener.open(request, timeout=20) as response:
|
||||
raw = response.read(2 * 1024 * 1024 + 1)
|
||||
except (urllib.error.URLError, OSError) as exc:
|
||||
raise ContractDenied(f"GITEA_API_FAILED:{type(exc).__name__}") from exc
|
||||
if len(raw) > 2 * 1024 * 1024:
|
||||
raise ContractDenied("GITEA_API_RESPONSE_TOO_LARGE")
|
||||
return json.loads(raw.decode("utf-8")) if raw else None
|
||||
|
||||
def get(self, path: str) -> Any:
|
||||
return self._request("GET", path)
|
||||
|
||||
def post(self, path: str, payload: dict[str, Any]) -> Any:
|
||||
return self._request("POST", path, payload)
|
||||
|
||||
|
||||
class QuotaJournal:
|
||||
def __init__(self, path: Path, grant: TaskGrant):
|
||||
self.path = Path(path)
|
||||
self.grant = grant
|
||||
self.connection = sqlite3.connect(self.path, isolation_level=None)
|
||||
self.connection.execute("PRAGMA journal_mode=WAL")
|
||||
self.connection.execute("PRAGMA synchronous=FULL")
|
||||
self.connection.execute("CREATE TABLE IF NOT EXISTS quota(operation TEXT PRIMARY KEY, state TEXT NOT NULL, effect_sha256 TEXT)")
|
||||
self.connection.execute("CREATE TABLE IF NOT EXISTS audit(seq INTEGER PRIMARY KEY AUTOINCREMENT, event BLOB NOT NULL, previous_hash TEXT NOT NULL, event_hash TEXT NOT NULL UNIQUE)")
|
||||
|
||||
def close(self) -> None:
|
||||
self.connection.close()
|
||||
|
||||
def reserve(self, operation: str) -> str:
|
||||
limit = {"statuses": 1, "merge": 1}.get(operation)
|
||||
if limit is None:
|
||||
raise ContractDenied("OPERATION_INVALID")
|
||||
self.connection.execute("BEGIN IMMEDIATE")
|
||||
try:
|
||||
row = self.connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
|
||||
if row and row[0] == "COMMITTED":
|
||||
raise ContractDenied("STATUS_QUOTA_EXHAUSTED" if operation == "statuses" else "MERGE_QUOTA_EXHAUSTED")
|
||||
if row and row[0] != "RESERVED":
|
||||
raise ContractDenied("JOURNAL_STATE_INVALID")
|
||||
if not row:
|
||||
self.connection.execute("INSERT INTO quota(operation,state,effect_sha256) VALUES(?,'RESERVED',NULL)", (operation,))
|
||||
self.connection.execute("COMMIT")
|
||||
return "RESERVED"
|
||||
except Exception:
|
||||
self.connection.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
def state(self, operation: str) -> str | None:
|
||||
row = self.connection.execute("SELECT state FROM quota WHERE operation=?", (operation,)).fetchone()
|
||||
return str(row[0]) if row else None
|
||||
|
||||
def commit(self, operation: str, effect: dict[str, Any]) -> None:
|
||||
digest = hashlib.sha256(canonical(effect)).hexdigest()
|
||||
self.connection.execute("BEGIN IMMEDIATE")
|
||||
try:
|
||||
row = self.connection.execute("SELECT state,effect_sha256 FROM quota WHERE operation=?", (operation,)).fetchone()
|
||||
if row is None or row[0] not in {"RESERVED", "COMMITTED"}:
|
||||
raise ContractDenied("RESERVATION_MISSING")
|
||||
if row[0] == "COMMITTED" and row[1] != digest:
|
||||
raise ContractDenied("COMMITTED_EFFECT_MISMATCH")
|
||||
self.connection.execute("UPDATE quota SET state='COMMITTED',effect_sha256=? WHERE operation=?", (digest, operation))
|
||||
self.connection.execute("COMMIT")
|
||||
except Exception:
|
||||
self.connection.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
def append(self, event: dict[str, Any]) -> str:
|
||||
row = self.connection.execute("SELECT event_hash FROM audit ORDER BY seq DESC LIMIT 1").fetchone()
|
||||
previous = row[0] if row else "0" * 64
|
||||
raw = canonical(event)
|
||||
digest = hashlib.sha256(previous.encode() + raw).hexdigest()
|
||||
self.connection.execute("INSERT INTO audit(event,previous_hash,event_hash) VALUES(?,?,?)", (raw, previous, digest))
|
||||
return digest
|
||||
|
||||
def verify_chain(self) -> bool:
|
||||
previous = "0" * 64
|
||||
for raw, observed_previous, observed_hash in self.connection.execute("SELECT event,previous_hash,event_hash FROM audit ORDER BY seq"):
|
||||
if observed_previous != previous or hashlib.sha256(previous.encode() + raw).hexdigest() != observed_hash:
|
||||
return False
|
||||
previous = observed_hash
|
||||
return True
|
||||
|
||||
|
||||
def _latest_statuses(values: Any) -> dict[str, dict[str, Any]]:
|
||||
if not isinstance(values, list):
|
||||
raise ContractDenied("STATUS_RESPONSE_INVALID")
|
||||
latest: dict[str, tuple[tuple[str, int], dict[str, Any]]] = {}
|
||||
for item in values:
|
||||
if not isinstance(item, dict) or item.get("context") not in ALLOWED_CONTEXTS:
|
||||
continue
|
||||
key = (str(item.get("created_at") or ""), int(item.get("id") or 0))
|
||||
context = item["context"]
|
||||
if context not in latest or key > latest[context][0]:
|
||||
latest[context] = (key, item)
|
||||
return {context: item for context, (_, item) in latest.items()}
|
||||
|
||||
|
||||
def _verify_owner_binding(api: API, grant: TaskGrant) -> tuple[dict[str, Any], dict[str, Any]]:
|
||||
pr_number = grant.raw["pr_number"]
|
||||
head, base = grant.raw["target_commit"], grant.raw["base_oid"]
|
||||
pr = api.get(f"/repos/aios/aios/pulls/{pr_number}")
|
||||
reviews = api.get(f"/repos/aios/aios/pulls/{pr_number}/reviews")
|
||||
if not isinstance(pr, dict) or pr.get("state") != "open" or pr.get("mergeable") is not True or (pr.get("head") or {}).get("sha") != head or (pr.get("base") or {}).get("sha") != base or (pr.get("base") or {}).get("ref") != "governance/approvals":
|
||||
raise ContractDenied("PR_BINDING_INVALID")
|
||||
if not isinstance(reviews, list):
|
||||
raise ContractDenied("REVIEW_RESPONSE_INVALID")
|
||||
owners = [item for item in reviews if isinstance(item, dict) and (item.get("user") or {}).get("login") == "owner" and (item.get("user") or {}).get("id") == 2]
|
||||
if not owners:
|
||||
raise ContractDenied("OWNER_EXACT_HEAD_APPROVAL_MISSING")
|
||||
latest = max(owners, key=lambda item: int(item.get("id") or -1))
|
||||
if latest.get("state") != "APPROVED" or latest.get("commit_id") != head or latest.get("official") is not True or latest.get("stale") is not False or latest.get("dismissed") is not False:
|
||||
raise ContractDenied("OWNER_EXACT_HEAD_APPROVAL_MISSING")
|
||||
submitted = _time(str(latest.get("submitted_at") or ""))
|
||||
if submitted < grant.issued_at or submitted >= grant.expires_at:
|
||||
raise ContractDenied("OWNER_APPROVAL_EXPIRED")
|
||||
return pr, latest
|
||||
|
||||
|
||||
def _signed_receipt(value: dict[str, Any], key: bytes) -> dict[str, Any]:
|
||||
if not key:
|
||||
raise ContractDenied("AUDIT_KEY_EMPTY")
|
||||
result = dict(value)
|
||||
result["audit_signature"] = hmac.new(key, canonical(value), hashlib.sha256).hexdigest()
|
||||
return result
|
||||
|
||||
|
||||
class StatusBroker:
|
||||
def __init__(self, grant: TaskGrant, journal: QuotaJournal, api: API, audit_key: bytes):
|
||||
self.grant, self.journal, self.api, self.audit_key = grant, journal, api, audit_key
|
||||
|
||||
def publish(self, evidence: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
if not isinstance(evidence, list) or len(evidence) != 5:
|
||||
raise ContractDenied("EVIDENCE_SET_INVALID")
|
||||
mapped = {item.get("context"): item for item in evidence if isinstance(item, dict)}
|
||||
if set(mapped) != ALLOWED_CONTEXTS or any(set(item) != {"context", "evidence_sha256"} or not SHA256.fullmatch(str(item["evidence_sha256"])) or item["evidence_sha256"] != self.grant.raw["status_evidence_sha256"].get(context) for context, item in mapped.items()):
|
||||
raise ContractDenied("EVIDENCE_SET_INVALID")
|
||||
_verify_owner_binding(self.api, self.grant)
|
||||
self.journal.reserve("statuses")
|
||||
published = []
|
||||
head = self.grant.raw["target_commit"]
|
||||
pr_number = self.grant.raw["pr_number"]
|
||||
observed_before = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
|
||||
already = _latest_statuses(observed_before)
|
||||
already = {context: item for context, item in already.items()
|
||||
if item.get("status", item.get("state")) == "success"
|
||||
and item.get("sha", head) == head
|
||||
and (item.get("creator") or {}).get("login") == self.grant.raw["status_identity"]
|
||||
and str(item.get("description") or "").endswith(mapped[context]["evidence_sha256"])}
|
||||
for context in sorted(ALLOWED_CONTEXTS):
|
||||
digest = mapped[context]["evidence_sha256"]
|
||||
if context in already:
|
||||
published.append({"context": context, "evidence_sha256": digest, "status_id": already[context].get("id"), "reconciled": True})
|
||||
continue
|
||||
response = self.api.post(f"/repos/aios/aios/statuses/{head}", {
|
||||
"state": "success", "context": context,
|
||||
"description": f"task-scoped PASS evidence_sha256={digest}",
|
||||
"target_url": f"https://g.cnnetmkt.top/git/aios/aios/pulls/{pr_number}",
|
||||
})
|
||||
if not isinstance(response, dict) or response.get("context") != context or response.get("status", response.get("state")) != "success":
|
||||
raise ContractDenied("STATUS_PUBLICATION_FAILED")
|
||||
published.append({"context": context, "evidence_sha256": digest, "status_id": response.get("id")})
|
||||
observed = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
|
||||
latest = _latest_statuses(observed)
|
||||
if set(latest) != ALLOWED_CONTEXTS or any(
|
||||
item.get("status", item.get("state")) != "success"
|
||||
or item.get("sha", head) != head
|
||||
or (item.get("creator") or {}).get("login") != self.grant.raw["status_identity"]
|
||||
or not str(item.get("description") or "").endswith(mapped[context]["evidence_sha256"])
|
||||
for context, item in latest.items()
|
||||
):
|
||||
raise ContractDenied("STATUS_READBACK_INVALID")
|
||||
receipt = {"status": "PASS", "operation": "publish_statuses", "grant_sha256": self.grant.digest, "target_commit": head, "published_count": 5, "published": published}
|
||||
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
|
||||
receipt["audit_chain_hash"] = self.journal.append(receipt)
|
||||
self.journal.commit("statuses", receipt)
|
||||
return receipt
|
||||
|
||||
|
||||
class MergeBroker:
|
||||
def __init__(self, grant: TaskGrant, journal: QuotaJournal, api: API, audit_key: bytes):
|
||||
self.grant, self.journal, self.api, self.audit_key = grant, journal, api, audit_key
|
||||
|
||||
def merge(self) -> dict[str, Any]:
|
||||
head, base = self.grant.raw["target_commit"], self.grant.raw["base_oid"]
|
||||
pr_number = self.grant.raw["pr_number"]
|
||||
pr = self.api.get(f"/repos/aios/aios/pulls/{pr_number}")
|
||||
if isinstance(pr, dict) and pr.get("merged") is True:
|
||||
observed_branch = self.api.get("/repos/aios/aios/branches/governance%2Fapprovals")
|
||||
if pr.get("merge_commit_sha") != head or (observed_branch.get("commit") or {}).get("id") != head or self.journal.state("merge") != "RESERVED":
|
||||
raise ContractDenied("FAST_FORWARD_RESULT_MISMATCH")
|
||||
receipt = {"status": "PASS", "operation": "fast_forward_merge", "grant_sha256": self.grant.digest, "pr_number": pr_number, "governance_oid": head, "merge_method": "fast-forward-only", "reconciled": True}
|
||||
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
|
||||
receipt["audit_chain_hash"] = self.journal.append(receipt)
|
||||
self.journal.commit("merge", receipt)
|
||||
return receipt
|
||||
pr, _ = _verify_owner_binding(self.api, self.grant)
|
||||
statuses = self.api.get(f"/repos/aios/aios/commits/{head}/statuses")
|
||||
latest = _latest_statuses(statuses)
|
||||
if set(latest) != ALLOWED_CONTEXTS or any(item.get("status", item.get("state")) != "success" or item.get("sha", head) != head or (item.get("creator") or {}).get("login") != self.grant.raw["status_identity"] or not str(item.get("description") or "").endswith(self.grant.raw["status_evidence_sha256"][context]) for context, item in latest.items()):
|
||||
raise ContractDenied("MACHINE_STATUS_INVALID")
|
||||
self.journal.reserve("merge")
|
||||
self.api.post(f"/repos/aios/aios/pulls/{pr_number}/merge", {"Do": "fast-forward-only", "head_commit_id": head, "force_merge": False, "delete_branch_after_merge": False})
|
||||
observed_pr = self.api.get(f"/repos/aios/aios/pulls/{pr_number}")
|
||||
observed_branch = self.api.get("/repos/aios/aios/branches/governance%2Fapprovals")
|
||||
if observed_pr.get("merged") is not True or observed_pr.get("merge_commit_sha") != head or (observed_branch.get("commit") or {}).get("id") != head:
|
||||
raise ContractDenied("FAST_FORWARD_RESULT_MISMATCH")
|
||||
receipt = {"status": "PASS", "operation": "fast_forward_merge", "grant_sha256": self.grant.digest, "pr_number": pr_number, "governance_oid": head, "merge_method": "fast-forward-only"}
|
||||
receipt["audit_signature"] = hmac.new(self.audit_key, canonical(receipt), hashlib.sha256).hexdigest()
|
||||
receipt["audit_chain_hash"] = self.journal.append(receipt)
|
||||
self.journal.commit("merge", receipt)
|
||||
return receipt
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(prog="aios-task-status-merge-broker")
|
||||
parser.add_argument("--mode", required=True, choices=("status", "merge"))
|
||||
parser.add_argument("--grant", required=True, type=Path)
|
||||
parser.add_argument("--token", required=True, type=Path)
|
||||
parser.add_argument("--audit-key", required=True, type=Path)
|
||||
parser.add_argument("--grant-signature", required=True, type=Path)
|
||||
parser.add_argument("--allowed-signers", required=True, type=Path)
|
||||
parser.add_argument("--journal", required=True, type=Path)
|
||||
parser.add_argument("--evidence", type=Path)
|
||||
args = parser.parse_args(argv)
|
||||
grant = load_signed_task_grant(args.grant, args.grant_signature, args.allowed_signers)
|
||||
journal = QuotaJournal(args.journal, grant)
|
||||
try:
|
||||
client = GiteaClient(args.token)
|
||||
key = read_runtime_secret(args.audit_key)
|
||||
if args.mode == "status":
|
||||
if args.evidence is None:
|
||||
raise ContractDenied("EVIDENCE_REQUIRED")
|
||||
result = StatusBroker(grant, journal, client, key).publish(json.loads(args.evidence.read_text(encoding="utf-8")))
|
||||
else:
|
||||
if args.evidence is not None:
|
||||
raise ContractDenied("EVIDENCE_FORBIDDEN")
|
||||
result = MergeBroker(grant, journal, client, key).merge()
|
||||
print(json.dumps(result, sort_keys=True, separators=(",", ":")))
|
||||
return 0
|
||||
finally:
|
||||
journal.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP",
|
||||
"title": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP observed approval envelope",
|
||||
"description": "Versioned fail-closed validation envelope assembled from an immutable request plus observed Owner, Git, machine-gate, runtime, and mirror evidence.",
|
||||
"x-schema-version": 1,
|
||||
"x-schema-status": "CANDIDATE",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"document_kind",
|
||||
"request_id",
|
||||
"schema_id",
|
||||
"schema_version",
|
||||
"request_created_at",
|
||||
"request_expires_at",
|
||||
"requester_identity",
|
||||
"repository_identity",
|
||||
"approval_plan_path",
|
||||
"approval_plan_blob_oid",
|
||||
"approval_plan_sha256",
|
||||
"schema_document_sha256",
|
||||
"validator_policy_sha256",
|
||||
"required_machine_contexts",
|
||||
"governance_base_ref",
|
||||
"governance_base_oid",
|
||||
"request_head_ref",
|
||||
"request_head_oid",
|
||||
"code_base_ref",
|
||||
"code_base_oid",
|
||||
"candidate_commit_oid",
|
||||
"candidate_parent_oid",
|
||||
"candidate_tree_oid",
|
||||
"candidate_diff_sha256",
|
||||
"candidate_files_sha256",
|
||||
"target_ref",
|
||||
"target_initial_state",
|
||||
"provision_publisher",
|
||||
"provision_writer",
|
||||
"provision_credential_projection",
|
||||
"publisher_identity",
|
||||
"writer_identity",
|
||||
"credential_secret_ref",
|
||||
"publisher_scope",
|
||||
"writer_scope",
|
||||
"credential_scope",
|
||||
"observed_preapproval_operations",
|
||||
"allowed_operations",
|
||||
"allowed_operations_sha256",
|
||||
"denied_operations",
|
||||
"maximum_operation_count",
|
||||
"maximum_pr_count",
|
||||
"maximum_branch_count",
|
||||
"maximum_commit_count",
|
||||
"allowed_paths",
|
||||
"allowed_paths_sha256",
|
||||
"approved_at",
|
||||
"expires_at",
|
||||
"maximum_lifetime_seconds",
|
||||
"auto_revoke",
|
||||
"required_human_approvals",
|
||||
"allowed_human_approvers",
|
||||
"approved_by",
|
||||
"owner_review_id",
|
||||
"owner_review_commit_oid",
|
||||
"approval_plan_id",
|
||||
"approval_audit_event_id",
|
||||
"production_runtime_anchor_change",
|
||||
"production_writes_enabled",
|
||||
"tag_operations",
|
||||
"registry_operations",
|
||||
"baseline_operations",
|
||||
"deployment_operations",
|
||||
"force_push_allowed",
|
||||
"tag_rewrite_allowed",
|
||||
"direct_main_push_allowed"
|
||||
],
|
||||
"properties": {
|
||||
"document_kind": {"const": "ENVELOPE"},
|
||||
"request_id": {"type": "string", "minLength": 3, "maxLength": 192, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]+$"},
|
||||
"schema_id": {"const": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP"},
|
||||
"schema_version": {"const": 1},
|
||||
"request_created_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
|
||||
"request_expires_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
|
||||
"requester_identity": {"$ref": "#/$defs/identity"},
|
||||
"repository_identity": {"const": "aios/aios"},
|
||||
"approval_plan_path": {"type": "string", "pattern": "^approvals/governance-bootstrap/[A-Za-z0-9._-]+\\.json$"},
|
||||
"approval_plan_blob_oid": {"$ref": "#/$defs/oid"},
|
||||
"approval_plan_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"schema_document_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"validator_policy_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"required_machine_contexts": {
|
||||
"type": "array",
|
||||
"minItems": 5,
|
||||
"maxItems": 5,
|
||||
"uniqueItems": true,
|
||||
"items": {"enum": [
|
||||
"governance/authority-mirror",
|
||||
"governance/fault-injection",
|
||||
"governance/runtime-isolation",
|
||||
"governance/schema-contract",
|
||||
"governance/validator-security"
|
||||
]}
|
||||
},
|
||||
"governance_base_ref": {"const": "refs/heads/governance/approvals"},
|
||||
"governance_base_oid": {"$ref": "#/$defs/oid"},
|
||||
"request_head_ref": {"type": "string", "pattern": "^refs/heads/governance/request/[A-Za-z0-9._/-]+$"},
|
||||
"request_head_oid": {"$ref": "#/$defs/oid"},
|
||||
"code_base_ref": {"type": "string", "pattern": "^refs/heads/patch/[A-Za-z0-9._/-]+$"},
|
||||
"code_base_oid": {"$ref": "#/$defs/oid"},
|
||||
"candidate_commit_oid": {"$ref": "#/$defs/oid"},
|
||||
"candidate_parent_oid": {"$ref": "#/$defs/oid"},
|
||||
"candidate_tree_oid": {"$ref": "#/$defs/oid"},
|
||||
"candidate_diff_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"candidate_files_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"target_ref": {"type": "string", "pattern": "^refs/heads/patch/[A-Za-z0-9._/-]+$"},
|
||||
"target_initial_state": {"const": "ABSENT"},
|
||||
"provision_publisher": {"const": true},
|
||||
"provision_writer": {"const": true},
|
||||
"provision_credential_projection": {"const": true},
|
||||
"publisher_identity": {"$ref": "#/$defs/identity"},
|
||||
"writer_identity": {"$ref": "#/$defs/identity"},
|
||||
"credential_secret_ref": {"type": "string", "pattern": "^(systemd-credential|secret-ref)://[A-Za-z0-9_.-]+$"},
|
||||
"publisher_scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repository", "local_code_write", "administrator"],
|
||||
"properties": {
|
||||
"repository": {"const": "aios/aios"},
|
||||
"local_code_write": {"const": false},
|
||||
"administrator": {"const": false}
|
||||
}
|
||||
},
|
||||
"writer_scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["repository", "remote_credentials", "remote_push", "run_as_root"],
|
||||
"properties": {
|
||||
"repository": {"const": "aios/aios"},
|
||||
"remote_credentials": {"const": false},
|
||||
"remote_push": {"const": false},
|
||||
"run_as_root": {"const": false}
|
||||
}
|
||||
},
|
||||
"credential_scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider", "projection", "audience", "writer_visible",
|
||||
"runtime_anchor_visible", "expires_with_request", "revocation_required",
|
||||
"post_revoke_http_status"
|
||||
],
|
||||
"properties": {
|
||||
"provider": {"const": "systemd"},
|
||||
"projection": {"const": "LoadCredential"},
|
||||
"audience": {"$ref": "#/$defs/identity"},
|
||||
"writer_visible": {"const": false},
|
||||
"runtime_anchor_visible": {"const": false},
|
||||
"expires_with_request": {"const": true},
|
||||
"revocation_required": {"const": true},
|
||||
"post_revoke_http_status": {"const": 401}
|
||||
}
|
||||
},
|
||||
"observed_preapproval_operations": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"uniqueItems": true,
|
||||
"items": {"enum": [
|
||||
"create_governance_request_branch",
|
||||
"create_governance_approval_pr"
|
||||
]}
|
||||
},
|
||||
"allowed_operations": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {"enum": [
|
||||
"provision_task_publisher",
|
||||
"provision_task_writer",
|
||||
"provision_task_credential_projection",
|
||||
"create_approved_code_branch",
|
||||
"push_approved_code_branch",
|
||||
"read_remote_refs",
|
||||
"revoke_task_credentials",
|
||||
"remove_task_identities"
|
||||
]}
|
||||
},
|
||||
"allowed_operations_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"denied_operations": {"type": "array", "minItems": 12, "uniqueItems": true, "items": {"type": "string"}},
|
||||
"maximum_operation_count": {"type": "integer", "minimum": 1, "maximum": 10},
|
||||
"maximum_pr_count": {"const": 1},
|
||||
"maximum_branch_count": {"const": 1},
|
||||
"maximum_commit_count": {"const": 1},
|
||||
"allowed_paths": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
|
||||
"allowed_paths_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"approved_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
|
||||
"expires_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
|
||||
"maximum_lifetime_seconds": {"type": "integer", "minimum": 1, "maximum": 43200},
|
||||
"auto_revoke": {"const": true},
|
||||
"required_human_approvals": {"const": 1},
|
||||
"allowed_human_approvers": {"const": ["owner"]},
|
||||
"approved_by": {"const": "owner"},
|
||||
"owner_review_id": {"type": "integer", "minimum": 1},
|
||||
"owner_review_commit_oid": {"$ref": "#/$defs/oid"},
|
||||
"approval_plan_id": {"type": "string", "minLength": 3, "maxLength": 192},
|
||||
"approval_audit_event_id": {"type": "string", "minLength": 3, "maxLength": 192},
|
||||
"production_runtime_anchor_change": {"const": false},
|
||||
"production_writes_enabled": {"const": false},
|
||||
"tag_operations": {"const": false},
|
||||
"registry_operations": {"const": false},
|
||||
"baseline_operations": {"const": false},
|
||||
"deployment_operations": {"const": false},
|
||||
"force_push_allowed": {"const": false},
|
||||
"tag_rewrite_allowed": {"const": false},
|
||||
"direct_main_push_allowed": {"const": false}
|
||||
},
|
||||
"$defs": {
|
||||
"plan": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"document_kind", "schema_id", "schema_version", "payload_sha256",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"document_kind": {"const": "PLAN"},
|
||||
"schema_id": {"const": "TASK_SCOPED_GOVERNANCE_BOOTSTRAP_PLAN"},
|
||||
"schema_version": {"const": 1},
|
||||
"payload_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"payload": {"$ref": "#/$defs/planPayload"}
|
||||
}
|
||||
},
|
||||
"planPayload": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"allowed_human_approvers", "allowed_operations", "allowed_operations_sha256",
|
||||
"allowed_paths", "allowed_paths_sha256", "approval_plan_id", "approval_plan_path",
|
||||
"approved_by", "auto_revoke", "baseline_operations", "candidate_commit_oid",
|
||||
"candidate_diff_sha256", "candidate_files_sha256", "candidate_parent_oid",
|
||||
"candidate_tree_oid", "code_base_oid", "code_base_ref", "credential_scope",
|
||||
"credential_secret_ref", "denied_operations", "deployment_operations",
|
||||
"direct_main_push_allowed", "expires_at", "force_push_allowed",
|
||||
"governance_base_oid", "governance_base_ref", "maximum_branch_count",
|
||||
"maximum_commit_count", "maximum_lifetime_seconds", "maximum_operation_count",
|
||||
"maximum_pr_count", "observed_preapproval_operations",
|
||||
"production_runtime_anchor_change", "production_writes_enabled",
|
||||
"provision_credential_projection", "provision_publisher", "provision_writer",
|
||||
"publisher_identity", "publisher_scope", "registry_operations",
|
||||
"repository_identity", "request_created_at", "request_expires_at",
|
||||
"request_head_ref", "request_id", "requester_identity",
|
||||
"required_human_approvals", "required_machine_contexts",
|
||||
"schema_document_sha256", "schema_id", "schema_version", "tag_operations",
|
||||
"tag_rewrite_allowed", "target_initial_state", "target_ref",
|
||||
"validator_policy_sha256", "writer_identity", "writer_scope"
|
||||
],
|
||||
"properties": {
|
||||
"allowed_human_approvers": {"$ref": "#/properties/allowed_human_approvers"},
|
||||
"allowed_operations": {"$ref": "#/properties/allowed_operations"},
|
||||
"allowed_operations_sha256": {"$ref": "#/properties/allowed_operations_sha256"},
|
||||
"allowed_paths": {"$ref": "#/properties/allowed_paths"},
|
||||
"allowed_paths_sha256": {"$ref": "#/properties/allowed_paths_sha256"},
|
||||
"approval_plan_id": {"$ref": "#/properties/approval_plan_id"},
|
||||
"approval_plan_path": {"$ref": "#/properties/approval_plan_path"},
|
||||
"approved_by": {"$ref": "#/properties/approved_by"},
|
||||
"auto_revoke": {"$ref": "#/properties/auto_revoke"},
|
||||
"baseline_operations": {"$ref": "#/properties/baseline_operations"},
|
||||
"candidate_commit_oid": {"$ref": "#/properties/candidate_commit_oid"},
|
||||
"candidate_diff_sha256": {"$ref": "#/properties/candidate_diff_sha256"},
|
||||
"candidate_files_sha256": {"$ref": "#/properties/candidate_files_sha256"},
|
||||
"candidate_parent_oid": {"$ref": "#/properties/candidate_parent_oid"},
|
||||
"candidate_tree_oid": {"$ref": "#/properties/candidate_tree_oid"},
|
||||
"code_base_oid": {"$ref": "#/properties/code_base_oid"},
|
||||
"code_base_ref": {"$ref": "#/properties/code_base_ref"},
|
||||
"credential_scope": {"$ref": "#/properties/credential_scope"},
|
||||
"credential_secret_ref": {"$ref": "#/properties/credential_secret_ref"},
|
||||
"denied_operations": {"$ref": "#/properties/denied_operations"},
|
||||
"deployment_operations": {"$ref": "#/properties/deployment_operations"},
|
||||
"direct_main_push_allowed": {"$ref": "#/properties/direct_main_push_allowed"},
|
||||
"expires_at": {"$ref": "#/properties/expires_at"},
|
||||
"force_push_allowed": {"$ref": "#/properties/force_push_allowed"},
|
||||
"governance_base_oid": {"$ref": "#/properties/governance_base_oid"},
|
||||
"governance_base_ref": {"$ref": "#/properties/governance_base_ref"},
|
||||
"maximum_branch_count": {"$ref": "#/properties/maximum_branch_count"},
|
||||
"maximum_commit_count": {"$ref": "#/properties/maximum_commit_count"},
|
||||
"maximum_lifetime_seconds": {"$ref": "#/properties/maximum_lifetime_seconds"},
|
||||
"maximum_operation_count": {"$ref": "#/properties/maximum_operation_count"},
|
||||
"maximum_pr_count": {"$ref": "#/properties/maximum_pr_count"},
|
||||
"observed_preapproval_operations": {"$ref": "#/properties/observed_preapproval_operations"},
|
||||
"production_runtime_anchor_change": {"$ref": "#/properties/production_runtime_anchor_change"},
|
||||
"production_writes_enabled": {"$ref": "#/properties/production_writes_enabled"},
|
||||
"provision_credential_projection": {"$ref": "#/properties/provision_credential_projection"},
|
||||
"provision_publisher": {"$ref": "#/properties/provision_publisher"},
|
||||
"provision_writer": {"$ref": "#/properties/provision_writer"},
|
||||
"publisher_identity": {"$ref": "#/properties/publisher_identity"},
|
||||
"publisher_scope": {"$ref": "#/properties/publisher_scope"},
|
||||
"registry_operations": {"$ref": "#/properties/registry_operations"},
|
||||
"repository_identity": {"$ref": "#/properties/repository_identity"},
|
||||
"request_created_at": {"$ref": "#/properties/request_created_at"},
|
||||
"request_expires_at": {"$ref": "#/properties/request_expires_at"},
|
||||
"request_head_ref": {"$ref": "#/properties/request_head_ref"},
|
||||
"request_id": {"$ref": "#/properties/request_id"},
|
||||
"requester_identity": {"$ref": "#/properties/requester_identity"},
|
||||
"required_human_approvals": {"$ref": "#/properties/required_human_approvals"},
|
||||
"required_machine_contexts": {"$ref": "#/properties/required_machine_contexts"},
|
||||
"schema_document_sha256": {"$ref": "#/properties/schema_document_sha256"},
|
||||
"schema_id": {"$ref": "#/properties/schema_id"},
|
||||
"schema_version": {"$ref": "#/properties/schema_version"},
|
||||
"tag_operations": {"$ref": "#/properties/tag_operations"},
|
||||
"tag_rewrite_allowed": {"$ref": "#/properties/tag_rewrite_allowed"},
|
||||
"target_initial_state": {"$ref": "#/properties/target_initial_state"},
|
||||
"target_ref": {"$ref": "#/properties/target_ref"},
|
||||
"validator_policy_sha256": {"$ref": "#/properties/validator_policy_sha256"},
|
||||
"writer_identity": {"$ref": "#/properties/writer_identity"},
|
||||
"writer_scope": {"$ref": "#/properties/writer_scope"}
|
||||
}
|
||||
},
|
||||
"oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||||
"sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"identity": {"type": "string", "minLength": 3, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]+$"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "AIOS_TASK_STATUS_MERGE_GRANT_V1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_id", "schema_version", "repository", "pr_number", "base_oid",
|
||||
"target_commit", "approved_tree_oid", "manifest_path", "manifest_blob_oid", "manifest_sha256",
|
||||
"payload_sha256", "status_identity", "merge_identity", "status_contexts",
|
||||
"status_write_quota", "merge_quota", "merge_method", "branch_push_allowed",
|
||||
"tag_write_allowed", "main_write_allowed", "registry_write_allowed",
|
||||
"baseline_write_allowed", "production_write_allowed", "issued_at", "expires_at",
|
||||
"audit_key_ref", "grant_signer_identity", "grant_signature_namespace",
|
||||
"status_evidence_sha256", "supersedes_pr_number", "supersedes_head_oid",
|
||||
"renewal_required"
|
||||
],
|
||||
"properties": {
|
||||
"schema_id": {"const": "AIOS_TASK_STATUS_MERGE_GRANT"},
|
||||
"schema_version": {"const": 1},
|
||||
"repository": {"const": "aios/aios"},
|
||||
"pr_number": {"type": "integer", "minimum": 1},
|
||||
"base_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||||
"target_commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||||
"approved_tree_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||||
"manifest_path": {"type": "string", "pattern": "^approvals/[A-Za-z0-9._/-]+\\.json$"},
|
||||
"manifest_blob_oid": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||||
"manifest_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"payload_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"status_evidence_sha256": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["aios/branch-protection", "aios/evidence-closure", "aios/secret-scan", "aios/state-machine", "aios/validator"],
|
||||
"properties": {
|
||||
"aios/branch-protection": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"aios/evidence-closure": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"aios/secret-scan": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"aios/state-machine": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
||||
"aios/validator": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
|
||||
}
|
||||
},
|
||||
"supersedes_pr_number": {"const": 36},
|
||||
"supersedes_head_oid": {"const": "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"},
|
||||
"renewal_required": {"const": true},
|
||||
"status_identity": {"enum": ["codex", "gpt"]},
|
||||
"merge_identity": {"enum": ["codex", "gpt"]},
|
||||
"status_contexts": {
|
||||
"type": "array", "minItems": 5, "maxItems": 5, "uniqueItems": true,
|
||||
"items": {"enum": ["aios/branch-protection", "aios/evidence-closure", "aios/secret-scan", "aios/state-machine", "aios/validator"]}
|
||||
},
|
||||
"status_write_quota": {"const": 5},
|
||||
"merge_quota": {"const": 1},
|
||||
"merge_method": {"const": "fast-forward-only"},
|
||||
"branch_push_allowed": {"const": false},
|
||||
"tag_write_allowed": {"const": false},
|
||||
"main_write_allowed": {"const": false},
|
||||
"registry_write_allowed": {"const": false},
|
||||
"baseline_write_allowed": {"const": false},
|
||||
"production_write_allowed": {"const": false},
|
||||
"issued_at": {"type": "string", "format": "date-time"},
|
||||
"expires_at": {"type": "string", "format": "date-time"},
|
||||
"audit_key_ref": {"type": "string", "pattern": "^systemd-credential://[A-Za-z0-9_.-]+$"},
|
||||
"grant_signer_identity": {"const": "aios-task-grant-signer"},
|
||||
"grant_signature_namespace": {"const": "aios-task-status-merge-grant-v1"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
import urllib.error
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT / "services" / "aios-single-owner-governance"))
|
||||
|
||||
from aios_single_owner_governance.task_status_merge_broker import ( # noqa: E402
|
||||
ALLOWED_CONTEXTS,
|
||||
ContractDenied,
|
||||
MergeBroker,
|
||||
QuotaJournal,
|
||||
StatusBroker,
|
||||
TaskGrant,
|
||||
canonical,
|
||||
load_signed_task_grant,
|
||||
)
|
||||
from aios_single_owner_governance.task_credential_broker import TaskCredentialBroker # noqa: E402
|
||||
from aios_single_owner_governance import task_credential_expiry_sweeper as sweeper # noqa: E402
|
||||
|
||||
|
||||
HEAD = "d" * 40
|
||||
OLD_HEAD = "a8644fc172bd8ebbba17a16e6bf586c93fd1e793"
|
||||
BASE = "8814dff20222625b60454c613b61ccf15fa20e51"
|
||||
|
||||
|
||||
def grant() -> dict:
|
||||
now = datetime.now(timezone.utc).replace(microsecond=0)
|
||||
value = {
|
||||
"schema_id": "AIOS_TASK_STATUS_MERGE_GRANT",
|
||||
"schema_version": 1,
|
||||
"repository": "aios/aios",
|
||||
"pr_number": 36,
|
||||
"base_oid": BASE,
|
||||
"target_commit": HEAD,
|
||||
"approved_tree_oid": "3649be2dac8fcea3a79cb1604b2cfb63f6cc0307",
|
||||
"manifest_path": "approvals/release-campaign/AIOS-V2R1C4-PHASE-B-RENEWAL.json",
|
||||
"manifest_blob_oid": "d6e4431992e4315799c7f0487f2b12a20d0e2890",
|
||||
"manifest_sha256": "2555c5e37f77f1d0aac51864733b55ee3e91169ae76bf67e8817de6d1874eea4",
|
||||
"payload_sha256": "4db7d3fd5aaa00a65eabfce7501f275b5f6c8a2587b6153fa8066ec0dafa5d6d",
|
||||
"status_evidence_sha256": {context: "1" * 64 for context in ALLOWED_CONTEXTS},
|
||||
"supersedes_pr_number": 36,
|
||||
"supersedes_head_oid": OLD_HEAD,
|
||||
"renewal_required": True,
|
||||
"status_identity": "codex",
|
||||
"merge_identity": "codex",
|
||||
"status_contexts": sorted(ALLOWED_CONTEXTS),
|
||||
"status_write_quota": 5,
|
||||
"merge_quota": 1,
|
||||
"merge_method": "fast-forward-only",
|
||||
"branch_push_allowed": False,
|
||||
"tag_write_allowed": False,
|
||||
"main_write_allowed": False,
|
||||
"registry_write_allowed": False,
|
||||
"baseline_write_allowed": False,
|
||||
"production_write_allowed": False,
|
||||
"issued_at": now.isoformat().replace("+00:00", "Z"),
|
||||
"expires_at": (now + timedelta(hours=1)).isoformat().replace("+00:00", "Z"),
|
||||
"audit_key_ref": "systemd-credential://task-audit-hmac",
|
||||
"grant_signer_identity": "aios-task-grant-signer",
|
||||
"grant_signature_namespace": "aios-task-status-merge-grant-v1",
|
||||
}
|
||||
value["pr_number"] = 37
|
||||
return value
|
||||
|
||||
|
||||
class FakeAPI:
|
||||
def __init__(self, *, with_statuses: bool = False, fail_status_after: int | None = None,
|
||||
fail_after_merge: bool = False):
|
||||
self.posts: list[tuple[str, dict]] = []
|
||||
self.merged = False
|
||||
self.status_rows = [{"id": index + 1, "context": value, "status": "success", "sha": HEAD,
|
||||
"description": "task-scoped PASS evidence_sha256=" + "1" * 64,
|
||||
"creator": {"login": "codex"}} for index, value in enumerate(ALLOWED_CONTEXTS)] if with_statuses else []
|
||||
self.fail_status_after = fail_status_after
|
||||
self.fail_after_merge = fail_after_merge
|
||||
self.base = BASE
|
||||
|
||||
def get(self, path: str):
|
||||
if path.endswith("/reviews"):
|
||||
return [{
|
||||
"id": 76,
|
||||
"state": "APPROVED",
|
||||
"commit_id": HEAD,
|
||||
"official": True,
|
||||
"stale": False,
|
||||
"dismissed": False,
|
||||
"submitted_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
||||
"user": {"id": 2, "login": "owner"},
|
||||
}]
|
||||
if path.endswith("/statuses"):
|
||||
return list(self.status_rows)
|
||||
if path.endswith("/branches/governance%2Fapprovals"):
|
||||
return {"name": "governance/approvals", "commit": {"id": HEAD if self.merged else BASE}}
|
||||
if path.endswith("/pulls/37"):
|
||||
return {
|
||||
"number": 37,
|
||||
"state": "closed" if self.merged else "open",
|
||||
"merged": self.merged,
|
||||
"mergeable": True,
|
||||
"head": {"sha": HEAD},
|
||||
"base": {"sha": self.base, "ref": "governance/approvals"},
|
||||
"merge_commit_sha": HEAD if self.merged else None,
|
||||
}
|
||||
raise AssertionError(path)
|
||||
|
||||
def post(self, path: str, payload: dict):
|
||||
self.posts.append((path, payload))
|
||||
if path.endswith("/merge"):
|
||||
assert payload == {
|
||||
"Do": "fast-forward-only",
|
||||
"head_commit_id": HEAD,
|
||||
"force_merge": False,
|
||||
"delete_branch_after_merge": False,
|
||||
}
|
||||
self.merged = True
|
||||
if self.fail_after_merge:
|
||||
raise ContractDenied("SIMULATED_POST_MERGE_LOSS")
|
||||
return {"merged": True}
|
||||
if self.fail_status_after is not None and len(self.status_rows) >= self.fail_status_after:
|
||||
raise ContractDenied("SIMULATED_STATUS_FAILURE")
|
||||
row = {"id": len(self.posts), "context": payload["context"], "status": "success", "sha": HEAD,
|
||||
"description": payload["description"],
|
||||
"creator": {"login": "codex"}}
|
||||
self.status_rows.append(row)
|
||||
return row
|
||||
|
||||
|
||||
def evidence() -> list[dict]:
|
||||
return [{"context": value, "evidence_sha256": "1" * 64} for value in sorted(ALLOWED_CONTEXTS)]
|
||||
|
||||
|
||||
class TaskStatusMergeBrokerTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temporary = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self.temporary.name)
|
||||
self.journals: list[QuotaJournal] = []
|
||||
|
||||
def tearDown(self):
|
||||
for journal in self.journals:
|
||||
journal.close()
|
||||
self.temporary.cleanup()
|
||||
|
||||
def journal(self, item: TaskGrant) -> QuotaJournal:
|
||||
value = QuotaJournal(self.root / "journal.sqlite3", item)
|
||||
self.journals.append(value)
|
||||
return value
|
||||
|
||||
def test_status_broker_publishes_exact_five_and_quota_is_single_use(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
api = FakeAPI()
|
||||
journal = self.journal(item)
|
||||
receipt = StatusBroker(item, journal, api, b"audit-key").publish(evidence())
|
||||
self.assertEqual(receipt["status"], "PASS")
|
||||
self.assertEqual(receipt["published_count"], 5)
|
||||
self.assertEqual({entry[1]["context"] for entry in api.posts}, ALLOWED_CONTEXTS)
|
||||
with self.assertRaisesRegex(ContractDenied, "STATUS_QUOTA_EXHAUSTED"):
|
||||
StatusBroker(item, journal, api, b"audit-key").publish(evidence())
|
||||
|
||||
def test_merge_broker_uses_fast_forward_only_and_binds_exact_head(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
api = FakeAPI(with_statuses=True)
|
||||
journal = self.journal(item)
|
||||
receipt = MergeBroker(item, journal, api, b"audit-key").merge()
|
||||
self.assertEqual(receipt["status"], "PASS")
|
||||
self.assertEqual(receipt["governance_oid"], HEAD)
|
||||
self.assertTrue(api.merged)
|
||||
with self.assertRaisesRegex(ContractDenied, "MERGE_QUOTA_EXHAUSTED"):
|
||||
MergeBroker(item, journal, FakeAPI(with_statuses=True), b"audit-key").merge()
|
||||
|
||||
def test_contract_rejects_scope_expansion_secret_and_wrong_identity(self):
|
||||
value = grant()
|
||||
value["main_write_allowed"] = True
|
||||
with self.assertRaisesRegex(ContractDenied, "WRITE_SCOPE_EXPANDED"):
|
||||
TaskGrant.from_dict(value)
|
||||
|
||||
def test_unbound_evidence_fails_closed(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
changed = evidence()
|
||||
changed[0]["evidence_sha256"] = "2" * 64
|
||||
with self.assertRaisesRegex(ContractDenied, "EVIDENCE_SET_INVALID"):
|
||||
StatusBroker(item, self.journal(item), FakeAPI(), b"audit-key").publish(changed)
|
||||
|
||||
def test_grant_requires_detached_asymmetric_signature(self):
|
||||
grant_path = self.root / "grant.json"
|
||||
signature_path = self.root / "grant.sig"
|
||||
allowed_signers = self.root / "allowed_signers"
|
||||
raw = canonical(grant()) + b"\n"
|
||||
grant_path.write_bytes(raw)
|
||||
signature_path.write_text("ssh-signature", encoding="utf-8")
|
||||
allowed_signers.write_text("aios-task-grant-signer ssh-ed25519 AAAA", encoding="utf-8")
|
||||
with mock.patch("aios_single_owner_governance.task_status_merge_broker.subprocess.run") as runner:
|
||||
item = load_signed_task_grant(grant_path, signature_path, allowed_signers)
|
||||
self.assertEqual(item.raw["pr_number"], 37)
|
||||
self.assertEqual(runner.call_args.kwargs["input"], raw)
|
||||
with mock.patch(
|
||||
"aios_single_owner_governance.task_status_merge_broker.subprocess.run",
|
||||
side_effect=subprocess.CalledProcessError(255, ["ssh-keygen"]),
|
||||
):
|
||||
with self.assertRaisesRegex(ContractDenied, "GRANT_SIGNATURE_INVALID"):
|
||||
load_signed_task_grant(grant_path, signature_path, allowed_signers)
|
||||
|
||||
def test_base_movement_blocks_status_publication_before_side_effect(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
api = FakeAPI()
|
||||
api.base = "c" * 40
|
||||
with self.assertRaisesRegex(ContractDenied, "PR_BINDING_INVALID"):
|
||||
StatusBroker(item, self.journal(item), api, b"audit-key").publish(evidence())
|
||||
self.assertEqual(api.posts, [])
|
||||
|
||||
def test_credential_provision_rechecks_local_owner_and_refs_before_issuance(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
broker = TaskCredentialBroker(item, self.root / "audit", b"audit-key")
|
||||
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=0, create=True), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker._safe_absolute"), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker._verify_local_governance_binding", side_effect=ContractDenied("LOCAL_OWNER_APPROVAL_MISSING")), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker.subprocess.run") as runner:
|
||||
with self.assertRaisesRegex(ContractDenied, "LOCAL_OWNER_APPROVAL_MISSING"):
|
||||
broker.provision(
|
||||
identity="codex",
|
||||
token_name="pr37-dddddddddddd-status",
|
||||
encrypted_path=Path("/run/aios-task-credential-broker/status.cred"),
|
||||
)
|
||||
runner.assert_not_called()
|
||||
value = grant()
|
||||
value["status_identity"] = "gitops-bot"
|
||||
with self.assertRaisesRegex(ContractDenied, "IDENTITY_NOT_ALLOWED"):
|
||||
TaskGrant.from_dict(value)
|
||||
|
||||
def test_expiry_sweeper_revokes_projected_token_after_grant_expiry(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
runtime_root = self.root / "runtime"
|
||||
credential_root = self.root / "credentials"
|
||||
task_dir = runtime_root / "task-37"
|
||||
audit_dir = task_dir / "audit"
|
||||
audit_dir.mkdir(parents=True)
|
||||
credential_root.mkdir()
|
||||
(task_dir / "grant.json").write_text("{}", encoding="utf-8")
|
||||
(task_dir / "grant.sig").write_text("signature", encoding="utf-8")
|
||||
token_name = "pr37-dddddddddddd-status"
|
||||
encrypted_path = credential_root / "status.cred"
|
||||
encrypted_path.write_text("encrypted", encoding="utf-8")
|
||||
(credential_root / "task-37-audit.cred").write_text("encrypted-audit-key", encoding="utf-8")
|
||||
real_broker = TaskCredentialBroker(item, audit_dir, b"audit-key")
|
||||
receipt = real_broker._audit({
|
||||
"status": "PASS", "operation": "credential_provision", "identity": "codex",
|
||||
"token_name": token_name, "token_id": 101, "token_uid": 7,
|
||||
"grant_sha256": item.digest,
|
||||
"credential_ref": "systemd-credential-encrypted://status.cred",
|
||||
})
|
||||
real_broker.validate_provision_receipt(receipt, encrypted_path)
|
||||
tampered = dict(receipt)
|
||||
tampered["token_id"] = 102
|
||||
with self.assertRaisesRegex(ContractDenied, "PROVISION_RECEIPT_INVALID"):
|
||||
real_broker.validate_provision_receipt(tampered, encrypted_path)
|
||||
fake_broker = mock.Mock()
|
||||
fake_broker.revoke.return_value = {"status": "PASS", "old_token_http_status": 401}
|
||||
with mock.patch.object(sweeper, "RUNTIME_ROOT", runtime_root), \
|
||||
mock.patch.object(sweeper, "CREDENTIAL_ROOT", credential_root), \
|
||||
mock.patch.object(sweeper.os, "geteuid", return_value=0, create=True), \
|
||||
mock.patch.object(sweeper, "load_signed_task_grant", return_value=item), \
|
||||
mock.patch.object(sweeper.subprocess, "run", return_value=mock.Mock(stdout=b"audit-key")), \
|
||||
mock.patch.object(sweeper, "TaskCredentialBroker", return_value=fake_broker) as broker_type:
|
||||
results = sweeper.sweep(runtime_root, self.root / "allowed_signers", now=item.expires_at)
|
||||
self.assertEqual(results, [{"status": "PASS", "old_token_http_status": 401}])
|
||||
broker_type.assert_called_once_with(item, audit_dir, b"audit-key")
|
||||
fake_broker.revoke.assert_called_once()
|
||||
|
||||
def test_revocation_is_exact_access_token_row_only_and_proves_http_401(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
broker = TaskCredentialBroker(item, self.root / "revoke-audit", b"audit-key")
|
||||
token_name = "pr37-dddddddddddd-status"
|
||||
receipt = broker._audit({
|
||||
"status": "PASS", "operation": "credential_provision", "identity": "codex",
|
||||
"token_name": token_name, "token_id": 101, "token_uid": 7,
|
||||
"grant_sha256": item.digest,
|
||||
"credential_ref": "systemd-credential-encrypted://status.cred",
|
||||
})
|
||||
response = mock.MagicMock()
|
||||
response.__enter__.return_value.status = 200
|
||||
unauthorized = urllib.error.HTTPError("http://127.0.0.1:3000/api/v1/repos/aios/aios", 401, "Unauthorized", {}, None)
|
||||
write_connection = mock.MagicMock()
|
||||
write_connection.execute.return_value.rowcount = 1
|
||||
read_connection = mock.MagicMock()
|
||||
read_connection.execute.return_value.fetchone.return_value = (0,)
|
||||
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=0, create=True), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker._safe_absolute"), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker.subprocess.run", return_value=mock.Mock(stdout=b"x" * 40)), \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker.sqlite3.connect", side_effect=[write_connection, read_connection]) as connect, \
|
||||
mock.patch("aios_single_owner_governance.task_credential_broker.urllib.request.urlopen", side_effect=[response, unauthorized]) as urlopen:
|
||||
result = broker.revoke(receipt=receipt, encrypted_path=Path("/run/aios-task-credential-broker/status.cred"))
|
||||
self.assertEqual(result["old_token_http_status"], 401)
|
||||
self.assertIn("/repos/aios/aios", urlopen.call_args_list[0].args[0].full_url)
|
||||
delete_sql = write_connection.execute.call_args_list[1].args[0]
|
||||
self.assertIn("DELETE FROM access_token", delete_sql)
|
||||
self.assertNotIn("commit_status", delete_sql)
|
||||
self.assertIn("mode=ro", connect.call_args_list[1].args[0])
|
||||
value = grant()
|
||||
value["token"] = "plaintext"
|
||||
with self.assertRaisesRegex(ContractDenied, "GRANT_FIELDS_INVALID"):
|
||||
TaskGrant.from_dict(value)
|
||||
|
||||
def test_audit_chain_is_content_addressed_and_contains_no_secret(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
journal = self.journal(item)
|
||||
receipt = StatusBroker(item, journal, FakeAPI(), b"audit-key").publish(evidence())
|
||||
serialized = json.dumps(receipt, sort_keys=True)
|
||||
self.assertNotIn("audit-key", serialized)
|
||||
self.assertEqual(len(receipt["audit_signature"]), 64)
|
||||
self.assertTrue(journal.verify_chain())
|
||||
|
||||
def test_credential_broker_is_root_only_and_never_returns_a_token(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
broker = TaskCredentialBroker(item, self.root / "audit", b"audit-key")
|
||||
with mock.patch("aios_single_owner_governance.task_credential_broker.os.geteuid", return_value=1000, create=True):
|
||||
with self.assertRaisesRegex(ContractDenied, "ROOT_BROKER_REQUIRED"):
|
||||
broker.provision(
|
||||
identity="codex",
|
||||
token_name="pr36-a8644fc172bd-status",
|
||||
encrypted_path=Path("/run/aios-task-credential-broker/status.cred"),
|
||||
)
|
||||
|
||||
def test_partial_status_side_effects_are_reconciled_without_duplicate_writes(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
api = FakeAPI(fail_status_after=2)
|
||||
journal = self.journal(item)
|
||||
with self.assertRaisesRegex(ContractDenied, "SIMULATED_STATUS_FAILURE"):
|
||||
StatusBroker(item, journal, api, b"audit-key").publish(evidence())
|
||||
self.assertEqual(len(api.status_rows), 2)
|
||||
api.fail_status_after = None
|
||||
receipt = StatusBroker(item, journal, api, b"audit-key").publish(evidence())
|
||||
self.assertEqual(receipt["published_count"], 5)
|
||||
self.assertEqual(len(api.status_rows), 5)
|
||||
|
||||
def test_post_merge_response_loss_is_reconciled_from_exact_remote_ref(self):
|
||||
item = TaskGrant.from_dict(grant())
|
||||
api = FakeAPI(with_statuses=True, fail_after_merge=True)
|
||||
journal = self.journal(item)
|
||||
with self.assertRaisesRegex(ContractDenied, "SIMULATED_POST_MERGE_LOSS"):
|
||||
MergeBroker(item, journal, api, b"audit-key").merge()
|
||||
api.fail_after_merge = False
|
||||
receipt = MergeBroker(item, journal, api, b"audit-key").merge()
|
||||
self.assertTrue(receipt["reconciled"])
|
||||
self.assertEqual(receipt["governance_oid"], HEAD)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user