autonomy-smoke-tests Exact governed tree; evidence 7dbba7ff168e72af
autonomy-unit-tests Exact governed tree; evidence 7dbba7ff168e72af
campaign-approval-gate Exact governed tree; evidence 7dbba7ff168e72af
git-diff-check Exact governed tree; evidence 7dbba7ff168e72af
py-compile Exact governed tree; evidence 7dbba7ff168e72af
reconciliation-contract Exact governed tree; evidence 7dbba7ff168e72af
release-state-machine Exact governed tree; evidence 7dbba7ff168e72af
secret-scan Exact governed tree; evidence 7029b3eafb209066
signer-validator-contract Exact governed tree; evidence 7dbba7ff168e72af
428 lines
16 KiB
Python
428 lines
16 KiB
Python
from __future__ import annotations
|
|
|
|
import base64
|
|
import dataclasses
|
|
from datetime import datetime, timedelta, timezone
|
|
import hashlib
|
|
import hmac
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
import pytest
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
|
|
import c5_exact_deployment_adapter as c5
|
|
import release_source_admission
|
|
from release_source_admission import ReleaseSourceAdmissionStore
|
|
from silent_release_controller import ReleaseCandidate
|
|
from silent_release_hardening import (
|
|
ApprovalKeyRing,
|
|
ApprovalRevocationStore,
|
|
CapabilityLedger,
|
|
DeploymentPlan,
|
|
FinalizationPlan,
|
|
ReleasePlan,
|
|
SignedApprovalVerifier,
|
|
SignedReleasePlanApproval,
|
|
TagPlan,
|
|
)
|
|
|
|
|
|
SOURCE = "1" * 40
|
|
TREE = "2" * 40
|
|
MANIFEST = "3" * 64
|
|
POLICY = "4" * 64
|
|
TAG_OID = "5" * 40
|
|
EVIDENCE = "6" * 40
|
|
OWNER_RECORD = "7" * 40
|
|
BASELINE = "8" * 64
|
|
REGISTRY = "9" * 64
|
|
TAG_REFSET = "a" * 64
|
|
PACKAGE = "b" * 64
|
|
SYSTEMD = "c" * 64
|
|
ABSENT = "d" * 64
|
|
CANDIDATE_ID = "c5-candidate-final-publication-001"
|
|
APPROVAL_PLAN_ID = "c5-owner-plan-final-publication-001"
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _windows_has_no_posix_mode_model(monkeypatch):
|
|
if os.name == "nt":
|
|
monkeypatch.setattr(
|
|
release_source_admission,
|
|
"_secure_stat",
|
|
lambda *args, **kwargs: None,
|
|
)
|
|
|
|
|
|
def _sha(path: Path) -> str:
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def _plan(source: str, tree: str, artifact_sha256: str) -> ReleasePlan:
|
|
deployment = DeploymentPlan(
|
|
service=c5.C5_PRODUCTION_SERVICE,
|
|
release_path=f"/data/aios-gitops/runtime/releases/{source}",
|
|
release_root="/data/aios-gitops/runtime/releases",
|
|
cutover_link=(
|
|
"/etc/systemd/system/aios-gitops-model-api.service.d/production.conf"
|
|
),
|
|
dropin_path=(
|
|
f"/data/aios-gitops/runtime/releases/{source}/deployment/production.conf"
|
|
),
|
|
dropin_sha256=SYSTEMD,
|
|
systemd_unit_sha256=SYSTEMD,
|
|
rollback_path="/usr/libexec/aios-gitops-runtime-anchor",
|
|
rollback_sha256="e" * 64,
|
|
source_commit=source,
|
|
tree_oid=tree,
|
|
artifact_sha256=artifact_sha256,
|
|
manifest_sha256=MANIFEST,
|
|
package_closure_sha256=PACKAGE,
|
|
authoritative_git_dir="/data/aios-gitops/repo.git",
|
|
repository_identity="aios/aios",
|
|
writer_expected=False,
|
|
baseline_before_sha256=BASELINE,
|
|
registry_before_sha256=REGISTRY,
|
|
production_tag_refset_before_sha256=TAG_REFSET,
|
|
health_contract_version="silent-release-health/v1",
|
|
timeout_policy={"health_seconds": 30},
|
|
retry_policy={"health_attempts": 3},
|
|
policy_sha256=POLICY,
|
|
health_contract={
|
|
"runtime_commit": source,
|
|
"writer": False,
|
|
"repository_identity": "aios/aios",
|
|
},
|
|
rollback_target=dict(c5.C4_ROLLBACK_TARGET),
|
|
)
|
|
return ReleasePlan(
|
|
deployment=deployment,
|
|
tag=TagPlan(
|
|
version=c5.C5_VERSION,
|
|
tag_type="annotated",
|
|
expected_tag_oid=TAG_OID,
|
|
expected_target_oid=source,
|
|
evidence_closure_oid=EVIDENCE,
|
|
approval_plan_id=APPROVAL_PLAN_ID,
|
|
repository_identity="aios/aios",
|
|
gitea_owner="aios",
|
|
gitea_repository="aios",
|
|
current_remote_tag_oid=None,
|
|
remote_absent_evidence_sha256=ABSENT,
|
|
verification_contract="git+api+listing/v1",
|
|
),
|
|
finalization=FinalizationPlan(
|
|
version=c5.C5_VERSION,
|
|
expected_tag_oid=TAG_OID,
|
|
expected_target_oid=source,
|
|
expected_previous_baseline_sha256=BASELINE,
|
|
registry_expected_record={"version": c5.C5_VERSION, "target_oid": source},
|
|
baseline_expected_record={"version": c5.C5_VERSION, "target_oid": source},
|
|
final_consistency_contract="registry=baseline=tag=v1",
|
|
),
|
|
policy_sha256=POLICY,
|
|
)
|
|
|
|
|
|
def _approval(
|
|
candidate: ReleaseCandidate,
|
|
plan: ReleasePlan,
|
|
private: Ed25519PrivateKey,
|
|
) -> SignedReleasePlanApproval:
|
|
now = datetime.now(timezone.utc)
|
|
value = SignedReleasePlanApproval(
|
|
release_plan_id="c5-release-plan-final-publication-001",
|
|
candidate_id=candidate.candidate_id,
|
|
source_commit=candidate.source_commit,
|
|
tree_oid=candidate.tree_oid,
|
|
artifact_sha256=candidate.artifact_sha256,
|
|
manifest_sha256=candidate.manifest_sha256,
|
|
deployment_plan_sha256=plan.deployment.sha256,
|
|
policy_sha256=plan.policy_sha256,
|
|
approval_plan_id=APPROVAL_PLAN_ID,
|
|
evidence_closure_oid=EVIDENCE,
|
|
owner_approval_record_oid=OWNER_RECORD,
|
|
capabilities=("runtime_switch",),
|
|
issued_at=(now - timedelta(minutes=1)).isoformat().replace("+00:00", "Z"),
|
|
not_before=(now - timedelta(minutes=1)).isoformat().replace("+00:00", "Z"),
|
|
expires_at=(now + timedelta(minutes=30)).isoformat().replace("+00:00", "Z"),
|
|
nonce="c5-exact-deployment-nonce-0001",
|
|
key_id="c5-owner-key-001",
|
|
signature="",
|
|
owner_identity="owner:imruyi",
|
|
trust_domain="aios.production",
|
|
release_plan_sha256=plan.sha256,
|
|
)
|
|
return dataclasses.replace(
|
|
value,
|
|
signature=base64.b64encode(private.sign(value.canonical_bytes())).decode(),
|
|
)
|
|
|
|
|
|
def _admission_store(
|
|
root: Path,
|
|
candidate: ReleaseCandidate,
|
|
) -> ReleaseSourceAdmissionStore:
|
|
root.mkdir(mode=0o700)
|
|
root.chmod(0o700)
|
|
key = b"c5-source-admission-test-key-000000000000"
|
|
record = {
|
|
"schema": "aios.release-source-admission.v1",
|
|
"admission_id": "c5-final-source-admission-001",
|
|
"repository": "aios/aios",
|
|
"task_id": "TASK-V2R2C5-FINAL-PUBLICATION-001",
|
|
"version": c5.C5_VERSION,
|
|
"candidate_id": candidate.candidate_id,
|
|
"base_oid": c5.C4_ROLLBACK_TARGET["target_oid"],
|
|
"source_ref": "refs/heads/agent/v2r2c5-final-publication",
|
|
"source_commit": candidate.source_commit,
|
|
"remote_ref_oid": candidate.source_commit,
|
|
"tree_oid": candidate.tree_oid,
|
|
"purpose": "AIOS_TRUSTED_RELEASE_BUILDER",
|
|
"policy_sha256": POLICY,
|
|
"admitted_at": "2026-09-30T00:00:00Z",
|
|
}
|
|
record["mac"] = hmac.new(
|
|
key,
|
|
release_source_admission._canonical(record),
|
|
hashlib.sha256,
|
|
).hexdigest()
|
|
path = root / f"{candidate.source_commit}.json"
|
|
path.write_text(json.dumps(record, sort_keys=True) + "\n", encoding="utf-8")
|
|
path.chmod(0o600)
|
|
return ReleaseSourceAdmissionStore(
|
|
root,
|
|
repository="aios/aios",
|
|
policy_sha256=POLICY,
|
|
hmac_key=key,
|
|
writable=False,
|
|
)
|
|
|
|
|
|
def _adapter_script(path: Path, state: Path, calls: Path, mode: str) -> None:
|
|
path.write_text(
|
|
"import json, pathlib, sys\n"
|
|
f"state=pathlib.Path({str(state)!r})\n"
|
|
f"calls=pathlib.Path({str(calls)!r})\n"
|
|
f"mode={mode!r}\n"
|
|
"request=json.loads(sys.stdin.buffer.read())\n"
|
|
"with calls.open('a', encoding='utf-8') as out: out.write(request['operation']+'\\n')\n"
|
|
"binding={k:v for k,v in request.items() if k not in {'schema','operation'}}\n"
|
|
"result={**binding,'writer_disabled':True,'deployment_receipt':{'adapter':'registered-c5','operation':request['operation']}}\n"
|
|
"if mode == 'bad-receipt': result.pop('tree_oid')\n"
|
|
"if request['operation']=='probe':\n"
|
|
" if mode == 'unknown':\n"
|
|
" result['status']='NOT_APPLIED' if len(calls.read_text(encoding='utf-8').splitlines()) == 1 else 'INDETERMINATE'\n"
|
|
" elif state.exists(): result.update(status='ACTIVE_VERIFIED',verified=True,deployment_state='ACTIVE',production_deployed=True)\n"
|
|
" else: result['status']='NOT_APPLIED'\n"
|
|
"elif request['operation']=='apply':\n"
|
|
" if mode == 'unknown': result['status']='EXECUTION_OUTCOME_UNKNOWN'\n"
|
|
" else:\n"
|
|
" state.write_text(request['release_plan_sha256'], encoding='utf-8')\n"
|
|
" result['status']='APPLIED'\n"
|
|
"elif request['operation']=='rollback':\n"
|
|
" result.update(status='ROLLED_BACK_VERIFIED',verified=True,rollback_verified=True,rollback_version='V2R2C4',rollback_target_oid='e5f8209f57b43fc39e55c4555776e6362ce326eb',rollback_artifact_sha256='0dfc0461f7f9aa25cfbfc37008dcbd2d48d5341383574163b7bba102852062c4')\n"
|
|
"else: raise SystemExit(2)\n"
|
|
"print(json.dumps(result, sort_keys=True))\n",
|
|
encoding="utf-8",
|
|
)
|
|
path.chmod(0o600)
|
|
|
|
|
|
def _fixture(tmp_path: Path, *, mode: str = "success", source: str = SOURCE):
|
|
artifact = tmp_path / "c5-release.tar.zst"
|
|
artifact.write_bytes(b"exact-c5-final-governed-artifact")
|
|
artifact.chmod(0o600)
|
|
artifact_sha256 = _sha(artifact)
|
|
candidate = ReleaseCandidate(
|
|
candidate_id=CANDIDATE_ID,
|
|
source_commit=source,
|
|
tree_oid=TREE,
|
|
artifact_sha256=artifact_sha256,
|
|
manifest_sha256=MANIFEST,
|
|
)
|
|
plan = _plan(source, TREE, artifact_sha256)
|
|
private = Ed25519PrivateKey.generate()
|
|
public = private.public_key().public_bytes(
|
|
serialization.Encoding.Raw,
|
|
serialization.PublicFormat.Raw,
|
|
)
|
|
approval = _approval(candidate, plan, private)
|
|
verifier = SignedApprovalVerifier(
|
|
ApprovalKeyRing({"c5-owner-key-001": public}),
|
|
ApprovalRevocationStore(tmp_path / "revocations"),
|
|
allowed_trust_domains={"aios.production"},
|
|
)
|
|
admissions = _admission_store(tmp_path / "admissions", candidate)
|
|
script = tmp_path / "registered_c5_adapter.py"
|
|
state = tmp_path / "runtime-state"
|
|
calls = tmp_path / "calls.log"
|
|
_adapter_script(script, state, calls, mode)
|
|
executable = Path(sys.executable).resolve()
|
|
executor = c5.RegisteredC5DeploymentExecutor(
|
|
executor_id="registered-c5-production-adapter-001",
|
|
executable=executable,
|
|
executable_sha256=_sha(executable),
|
|
adapter_path=script.resolve(),
|
|
adapter_sha256=_sha(script),
|
|
artifact_path=artifact.resolve(),
|
|
rollback_artifact_path=c5.C4_ROLLBACK_ARTIFACT_PATH,
|
|
production_environment_file=c5.C5_PRODUCTION_ENVIRONMENT_FILE,
|
|
require_root_owner=False,
|
|
)
|
|
return candidate, plan, approval, verifier, admissions, executor, calls
|
|
|
|
|
|
def _build_adapter(parts) -> c5.C5ExactDeploymentAdapter:
|
|
candidate, plan, approval, verifier, admissions, executor, _calls = parts
|
|
return c5.C5ExactDeploymentAdapter(
|
|
candidate=candidate,
|
|
release_plan=plan,
|
|
approval=approval,
|
|
approval_verifier=verifier,
|
|
source_admissions=admissions,
|
|
executor=executor,
|
|
)
|
|
|
|
|
|
def test_runtime_switch_executes_only_registered_exact_deployment_and_is_idempotent(
|
|
tmp_path,
|
|
):
|
|
parts = _fixture(tmp_path)
|
|
candidate, plan, *_rest, calls = parts
|
|
adapter = _build_adapter(parts)
|
|
controller = adapter.controller(CapabilityLedger(tmp_path / "ledger"))
|
|
|
|
first = controller.execute(
|
|
adapter.approval,
|
|
operation=f"runtime:{plan.sha256}",
|
|
candidate=candidate,
|
|
plan=plan,
|
|
)
|
|
second = controller.execute(
|
|
adapter.approval,
|
|
operation=f"runtime:{plan.sha256}",
|
|
candidate=candidate,
|
|
plan=plan,
|
|
)
|
|
|
|
assert first["status"] == "EXECUTED"
|
|
assert first["result"]["verified"] is True
|
|
assert first["result"]["rollback_target"] == c5.C4_ROLLBACK_TARGET
|
|
assert first["result"]["global_legacy_writes_enabled"] is False
|
|
assert second["status"] == "IDEMPOTENT"
|
|
assert calls.read_text(encoding="utf-8").splitlines() == ["probe", "apply", "probe"]
|
|
|
|
|
|
def test_unknown_effect_reconciles_and_never_reapplies(tmp_path):
|
|
parts = _fixture(tmp_path, mode="unknown")
|
|
candidate, plan, *_rest, calls = parts
|
|
adapter = _build_adapter(parts)
|
|
controller = adapter.controller(CapabilityLedger(tmp_path / "ledger"))
|
|
operation = f"runtime:{plan.sha256}"
|
|
|
|
with pytest.raises(c5.C5DeploymentOutcomeUnknown, match="OUTCOME_UNKNOWN"):
|
|
controller.execute(
|
|
adapter.approval,
|
|
operation=operation,
|
|
candidate=candidate,
|
|
plan=plan,
|
|
)
|
|
reconciled = controller.execute(
|
|
adapter.approval,
|
|
operation=operation,
|
|
candidate=candidate,
|
|
plan=plan,
|
|
)
|
|
|
|
assert reconciled["status"] == "RECONCILIATION_REQUIRED"
|
|
assert calls.read_text(encoding="utf-8").splitlines() == ["probe", "apply", "probe"]
|
|
|
|
|
|
def test_wrong_rollback_target_fails_before_registered_executor(tmp_path):
|
|
parts = list(_fixture(tmp_path))
|
|
plan = parts[1]
|
|
parts[1] = dataclasses.replace(
|
|
plan,
|
|
deployment=dataclasses.replace(
|
|
plan.deployment,
|
|
rollback_target={
|
|
**c5.C4_ROLLBACK_TARGET,
|
|
"target_oid": "f" * 40,
|
|
},
|
|
),
|
|
)
|
|
with pytest.raises(c5.C5DeploymentBindingError, match="ROLLBACK_TARGET_INVALID"):
|
|
_build_adapter(tuple(parts))
|
|
assert not parts[-1].exists()
|
|
|
|
|
|
def test_rehearsal_executor_rejects_bindings_outside_exact_isolation_root(tmp_path):
|
|
parts = _fixture(tmp_path)
|
|
_candidate, _plan, _approval, _verifier, _admissions, executor, _calls = parts
|
|
rehearsal_root = (tmp_path / "isolated-rehearsal" / "instance-001").resolve()
|
|
rehearsal_root.mkdir(parents=True)
|
|
with pytest.raises(c5.C5DeploymentBindingError, match="C5_REHEARSAL_BINDING_INVALID"):
|
|
dataclasses.replace(
|
|
executor,
|
|
execution_scope="ISOLATED_REHEARSAL",
|
|
isolation_root=rehearsal_root,
|
|
rollback_artifact_path=tmp_path / "outside-c4.tar.gz",
|
|
production_environment_file=rehearsal_root / "v2r2c2.env",
|
|
rollback_target={**c5.C4_ROLLBACK_TARGET, "artifact_sha256": "f" * 64},
|
|
)
|
|
|
|
|
|
def test_prepublication_installer_source_cannot_become_final_c5_binding(tmp_path):
|
|
parts = _fixture(tmp_path, source=c5.C5_PREPUBLICATION_SOURCE_COMMIT)
|
|
with pytest.raises(c5.C5DeploymentBindingError, match="PREPUBLICATION_SOURCE_FORBIDDEN"):
|
|
_build_adapter(parts)
|
|
assert not parts[-1].exists()
|
|
|
|
|
|
def test_receipt_must_echo_tree_plan_approval_and_rollback_binding(tmp_path):
|
|
parts = _fixture(tmp_path, mode="bad-receipt")
|
|
candidate, plan, *_rest, calls = parts
|
|
adapter = _build_adapter(parts)
|
|
controller = adapter.controller(CapabilityLedger(tmp_path / "ledger"))
|
|
with pytest.raises(c5.C5DeploymentBindingError, match="RECEIPT_MISMATCH:tree_oid"):
|
|
controller.execute(
|
|
adapter.approval,
|
|
operation=f"runtime:{plan.sha256}",
|
|
candidate=candidate,
|
|
plan=plan,
|
|
)
|
|
assert calls.read_text(encoding="utf-8").splitlines() == ["probe"]
|
|
|
|
|
|
def test_global_legacy_writes_true_blocks_before_executor(tmp_path, monkeypatch):
|
|
parts = _fixture(tmp_path)
|
|
monkeypatch.setenv("AIOS_GITOPS_WRITES_ENABLED", "true")
|
|
with pytest.raises(c5.C5DeploymentBindingError, match="LEGACY_WRITES"):
|
|
_build_adapter(parts)
|
|
assert not parts[-1].exists()
|
|
|
|
|
|
def test_explicit_saga_rollback_requires_exact_c4_verified_receipt(tmp_path):
|
|
parts = _fixture(tmp_path)
|
|
candidate, plan, *_rest, calls = parts
|
|
adapter = _build_adapter(parts)
|
|
|
|
result = adapter.rollback(candidate=candidate, plan=plan)
|
|
|
|
assert result == {
|
|
"verified": True,
|
|
"rollback_verified": True,
|
|
"rollback_version": "V2R2C4",
|
|
"rollback_target_oid": c5.C4_ROLLBACK_TARGET["target_oid"],
|
|
"rollback_artifact_sha256": c5.C4_ROLLBACK_TARGET[
|
|
"artifact_sha256"
|
|
],
|
|
"writer_disabled": True,
|
|
}
|
|
assert calls.read_text(encoding="utf-8").splitlines() == ["rollback"]
|