diff --git a/active-runtime/app/aios_trusted_candidate_builder.py b/active-runtime/app/aios_trusted_candidate_builder.py index b4c3d45..9b0acd0 100644 --- a/active-runtime/app/aios_trusted_candidate_builder.py +++ b/active-runtime/app/aios_trusted_candidate_builder.py @@ -640,7 +640,7 @@ class TrustedCandidateBuilder: "builder_key_id": self.signer.key_id, "builder_key_generation": self.signer.key_generation, "signature_algorithm": "Ed25519", - "signature_purpose": "builder_attestation", + "signature_purpose": "AIOS_TRUSTED_RELEASE_BUILDER", "policy_sha256": self.config.policy_sha256, "collector_ready": True, "signer_ready": True, @@ -659,7 +659,7 @@ class TrustedCandidateBuilder: "builder_key_id": self.signer.key_id, "builder_key_generation": self.signer.key_generation, "signature_algorithm": "Ed25519", - "signature_purpose": "builder_attestation", + "signature_purpose": "AIOS_TRUSTED_RELEASE_BUILDER", "source_commit": candidate["source_commit"], "tree_oid": candidate["tree_oid"], "artifact_sha256": candidate["artifact_sha256"], "manifest_sha256": candidate["manifest_sha256"], "package_closure_sha256": release_plan["deployment"]["package_closure_sha256"], @@ -673,7 +673,7 @@ class TrustedCandidateBuilder: } canonical_attestation = _canonical_json(attestation) fingerprint = hashlib.sha256(canonical_attestation).hexdigest() - signature = base64.b64encode(self.signer.sign_for_purpose("builder_attestation", canonical_attestation)).decode("ascii") + signature = base64.b64encode(self.signer.sign_for_purpose("AIOS_TRUSTED_RELEASE_BUILDER", canonical_attestation)).decode("ascii") result = { "schema": self.config.response_schema, "status": "BUILT", "recipe": recipe_name, "repository": self.config.repository, "task_id": recipe["task_id"], "base_oid": recipe["base_oid"], @@ -780,7 +780,7 @@ def _main() -> None: keyring.signing_private_key_path, key_id=os.environ["AIOS_TRUSTED_BUILDER_KEY_ID"], key_generation=int(os.environ["AIOS_TRUSTED_BUILDER_KEY_GENERATION"]), - allowed_purpose="builder_attestation", + allowed_purpose="AIOS_TRUSTED_RELEASE_BUILDER", ) listener = socket.fromfd(arguments.socket_fd, socket.AF_UNIX, socket.SOCK_STREAM) collector = DeterministicEvidenceCollector( diff --git a/active-runtime/app/silent_release_hardening.py b/active-runtime/app/silent_release_hardening.py index c555b25..d906771 100644 --- a/active-runtime/app/silent_release_hardening.py +++ b/active-runtime/app/silent_release_hardening.py @@ -42,7 +42,7 @@ from silent_release_controller import ( IDENTIFIER_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.:-]{2,255}$") NONCE_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.:-]{15,255}$") BUILDER_ATTESTATION_TRUST_DOMAIN = "aios.trusted-builder.attestation.v1" -BUILDER_ATTESTATION_PURPOSE = "builder_attestation" +BUILDER_ATTESTATION_PURPOSE = "AIOS_TRUSTED_RELEASE_BUILDER" ALLOWED_CAPABILITIES = frozenset( { "runtime_switch", diff --git a/config/gitops/trusted-candidate-builder-policy.json b/config/gitops/trusted-candidate-builder-policy.json index eb69e98..52b9bf2 100644 --- a/config/gitops/trusted-candidate-builder-policy.json +++ b/config/gitops/trusted-candidate-builder-policy.json @@ -26,7 +26,7 @@ "base_oid": "d2b5a8339a34a8f958a177f8a3b9e8296a57a7a6", "candidate_id": "rc-v2r2c2-d2b5a8339a34", "mode": "fixed", - "purpose": "release:candidate:trusted-build", + "purpose": "AIOS_TRUSTED_RELEASE_BUILDER", "source_commit": "d2b5a8339a34a8f958a177f8a3b9e8296a57a7a6", "task_id": "v12-durable-trusted-release-controller-activation-20260829", "version": "V2R2C2" @@ -34,7 +34,7 @@ "V2R2C3": { "derives_from": "V2R2C2", "mode": "governed-derived-only", - "purpose": "release:candidate:trusted-build", + "purpose": "AIOS_TRUSTED_RELEASE_BUILDER", "version": "V2R2C3" } }, diff --git a/tests/test_model_api_trusted_candidate_builder.py b/tests/test_model_api_trusted_candidate_builder.py index b61cdca..1016392 100644 --- a/tests/test_model_api_trusted_candidate_builder.py +++ b/tests/test_model_api_trusted_candidate_builder.py @@ -81,7 +81,7 @@ def _keyring_payload(private: Ed25519PrivateKey, *, purpose: str) -> dict: } payload = { "algorithm": "Ed25519", - "purpose": "builder_attestation", + "purpose": "AIOS_TRUSTED_RELEASE_BUILDER", "keys": [record], } payload["keyring_sha256"] = hashlib.sha256( @@ -117,7 +117,7 @@ def _attestation(private: Ed25519PrivateKey) -> BuilderAttestation: signature="", builder_key_generation=1, signature_algorithm="Ed25519", - signature_purpose="builder_attestation", + signature_purpose="AIOS_TRUSTED_RELEASE_BUILDER", gitea_evidence_sha256=_canonical_digest(GITEA), rollback_evidence_sha256=_canonical_digest({ "ready": True, @@ -151,7 +151,7 @@ def test_builder_verifier_checks_domain_key_window_digest_and_signature(tmp_path private = Ed25519PrivateKey.generate() path = tmp_path / "builder-keyring.json" path.write_text( - json.dumps(_keyring_payload(private, purpose="builder_attestation")), + json.dumps(_keyring_payload(private, purpose="AIOS_TRUSTED_RELEASE_BUILDER")), encoding="utf-8", ) verifier = BuilderAttestationVerifier( @@ -178,7 +178,7 @@ def test_builder_verifier_checks_domain_key_window_digest_and_signature(tmp_path @pytest.mark.parametrize("state", ["REVOKED", "EXPIRED", "FUTURE"]) def test_builder_verifier_rejects_unavailable_key_lifecycle_states(tmp_path, state): private = Ed25519PrivateKey.generate() - payload = _keyring_payload(private, purpose="builder_attestation") + payload = _keyring_payload(private, purpose="AIOS_TRUSTED_RELEASE_BUILDER") record = payload["keys"][0] if state == "REVOKED": record["status"] = "REVOKED" @@ -203,7 +203,7 @@ def test_builder_verifier_rejects_unavailable_key_lifecycle_states(tmp_path, sta def test_builder_verifier_rejects_unknown_key_invalid_signature_and_keyring_digest(tmp_path): private = Ed25519PrivateKey.generate() - payload = _keyring_payload(private, purpose="builder_attestation") + payload = _keyring_payload(private, purpose="AIOS_TRUSTED_RELEASE_BUILDER") path = tmp_path / "builder-keyring.json" path.write_text(json.dumps(payload), encoding="utf-8") verifier = BuilderAttestationVerifier(BuilderAttestationKeyRing.from_file(path)) @@ -252,7 +252,7 @@ def test_builder_keyring_rejects_attestation_metadata_mismatch(tmp_path, field, private = Ed25519PrivateKey.generate() path = tmp_path / "builder-keyring.json" path.write_text( - json.dumps(_keyring_payload(private, purpose="builder_attestation")), + json.dumps(_keyring_payload(private, purpose="AIOS_TRUSTED_RELEASE_BUILDER")), encoding="utf-8", ) verifier = BuilderAttestationVerifier( diff --git a/tests/test_trusted_candidate_builder.py b/tests/test_trusted_candidate_builder.py index 283fe91..00fdd1e 100644 --- a/tests/test_trusted_candidate_builder.py +++ b/tests/test_trusted_candidate_builder.py @@ -173,7 +173,7 @@ def test_public_build_seam_accepts_only_the_fixed_v2r2c2_recipe_and_returns_serv assert set(result["checks"]) == set(server.config.required_checks) assert all(result["checks"].values()) assert result["attestation"]["trust_domain"] == "aios.trusted-builder.attestation.v1" - assert signer.calls and signer.calls[0][0] == "builder_attestation" + assert signer.calls and signer.calls[0][0] == "AIOS_TRUSTED_RELEASE_BUILDER" assert result["attestation"]["fingerprint"] == hashlib.sha256(signer.calls[0][1]).hexdigest() assert BuilderAttestation.from_dict(result["attestation"]).canonical_bytes() == signer.calls[0][1] silent_bundle = result["silent_release_bundle"] @@ -357,7 +357,7 @@ def test_backend_attestation_round_trip_verifies_with_production_keyring() -> No key_generation = 1 def sign_for_purpose(self, purpose, payload): - assert purpose == "builder_attestation" + assert purpose == "AIOS_TRUSTED_RELEASE_BUILDER" return private.sign(payload) server, client, _ = make_seam(signer_override=Ed25519Signer()) @@ -380,7 +380,7 @@ def test_backend_attestation_round_trip_verifies_with_production_keyring() -> No key_id="builder-key-001", public_key=public_key, algorithm="Ed25519", - purpose="builder_attestation", + purpose="AIOS_TRUSTED_RELEASE_BUILDER", generation=1, not_before="2020-01-01T00:00:00Z", expires_at="2099-01-01T00:00:00Z",