"""Pure state and evidence rules for the fixed RepoPulse legacy adoption. This module deliberately has no Portainer, filesystem, Docker, database, or controller client. The integrated operator runner uses these rules only after the fixed managed profile and controller-owned durable intent are verified. """ from __future__ import annotations import hashlib import json import re from copy import deepcopy from typing import Any from backend.app.services.enrollment_profiles import PROFILE_VERSION PROTOCOL_VERSION = "itworx.repopulse-legacy-adoption/v1" INTENT_VERSION = "itworx.repopulse-legacy-adoption-intent/v1" CONTROLLER_RECEIPT_VERSION = "itworx.repopulse-legacy-adoption-receipt/v1" REPOSITORY = "jens/repopulse" APPLICATION_ID = "repopulse" LEGACY_VOLUME = "repopulse_data" EXECUTION_ENABLED = True _SHA256 = re.compile(r"^[0-9a-f]{64}$") _SHA1 = re.compile(r"^[0-9a-f]{40}$") _IDEMPOTENCY_KEY = re.compile(r"^[A-Za-z0-9._:-]{8,128}$") _PROFILE_ID = "repopulse-authenticated" _ENROLLMENT_ID = re.compile(r"^enr-[0-9a-f]{20}$") _INTENT_ID = re.compile(r"^rpa-[0-9a-f]{20}$") _LEGACY_CHECKS = { "legacy_registry", "controller_state", "gitea_ancestry", "runtime_identity_and_health", "legacy_storage_topology", "legacy_appdata", "product_api", "database_health", "queue_quiescence", "database_baseline", } _PHASES = ( "reserved", "target_gates_ready", "quiesced", "snapshot_verified", "target_registered", "appops_owned", "completed", ) _STEP_CONTRACTS: dict[str, tuple[str, str]] = { "target_gates": ("reserved", "target_gates_ready"), "quiescence": ("target_gates_ready", "quiesced"), "snapshot": ("quiesced", "snapshot_verified"), "controller_registration": ("snapshot_verified", "target_registered"), "appops_ownership": ("target_registered", "appops_owned"), } _RECOVERY_REASONS = { "controller_unavailable", "database_backup_failed", "registry_receipt_uncertain", "target_health_failed", "appops_commit_uncertain", "preflight_drift", "operator_interruption", "unknown_external_effect", } _STEP_EVIDENCE_KEYS = { "target_gates": "targetGates", "quiescence": "quiescence", "snapshot": "snapshot", "controller_registration": "controllerRegistration", "appops_ownership": "appopsOwnership", "completion": "completion", } class AdoptionProtocolError(ValueError): """A fail-closed protocol or evidence validation error.""" def __init__(self, code: str): super().__init__(code) self.code = code def _canonical(value: object) -> bytes: try: return json.dumps( value, sort_keys=True, separators=(",", ":"), ensure_ascii=True, allow_nan=False, ).encode("ascii") except (TypeError, ValueError, UnicodeEncodeError) as exc: raise AdoptionProtocolError("invalid_evidence_encoding") from exc def _digest(value: object) -> str: return hashlib.sha256(_canonical(value)).hexdigest() def _is_count(value: object) -> bool: return isinstance(value, int) and not isinstance(value, bool) and value >= 0 def _validate_preflight_projection(value: object) -> dict[str, Any]: required = { "repository", "main_revision", "live_revision", "container_id_sha256", "container_image_sha256", "queue", "database", "container_state", "container_health", } _need(isinstance(value, dict) and set(value) == required, "intent_preflight_invalid") projection = value _need( projection.get("repository") == REPOSITORY and isinstance(projection.get("main_revision"), str) and _SHA1.fullmatch(projection["main_revision"]) is not None and isinstance(projection.get("live_revision"), str) and _SHA1.fullmatch(projection["live_revision"]) is not None and isinstance(projection.get("container_id_sha256"), str) and _SHA256.fullmatch(projection["container_id_sha256"]) is not None and isinstance(projection.get("container_image_sha256"), str) and _SHA256.fullmatch(projection["container_image_sha256"]) is not None and projection.get("container_state") == "running" and projection.get("container_health") == "healthy", "intent_preflight_invalid", ) queue = projection.get("queue") database = projection.get("database") _need( isinstance(queue, dict) and set(queue) == {"queued", "active", "completed", "failed"} and all(_is_count(queue.get(key)) for key in queue) and queue.get("queued") == 0 and queue.get("active") == 0, "intent_preflight_queue_invalid", ) _need( isinstance(database, dict) and set(database) == {"database_bytes", "journal_bytes", "scan_count", "compacted_scan_count"} and all(_is_count(database.get(key)) for key in database) and database.get("database_bytes", 0) > 0 and database.get("scan_count", -1) >= database.get("compacted_scan_count", 0), "intent_preflight_database_invalid", ) return projection def _need(condition: bool, code: str) -> None: if not condition: raise AdoptionProtocolError(code) def _safe_preflight_projection(report: object) -> dict[str, Any]: """Accept only the existing read-only preflight's allowlisted identity facts.""" _need(isinstance(report, dict), "legacy_preflight_missing") source = report _need( source.get("apiVersion") == "itworx.repopulse-legacy-adoption-preflight/v1" and source.get("repository") == REPOSITORY and source.get("status") == "preflight_passed" and source.get("readOnly") is True and source.get("adoptionAuthorized") is False, "legacy_preflight_not_compatible", ) compatibility = source.get("legacyCompatibility") _need( isinstance(compatibility, dict) and compatibility.get("status") == "passed", "legacy_preflight_not_compatible", ) checks = compatibility.get("checks") _need(isinstance(checks, list), "legacy_preflight_checks_missing") observed: dict[str, str] = {} for check in checks: _need(isinstance(check, dict), "legacy_preflight_check_invalid") code = check.get("code") _need( isinstance(code, str) and code in _LEGACY_CHECKS and check.get("gate") == "legacy_compatibility" and check.get("status") == "passed" and code not in observed, "legacy_preflight_check_failed", ) observed[code] = "passed" _need(set(observed) == _LEGACY_CHECKS, "legacy_preflight_check_incomplete") evidence = source.get("evidence") _need(isinstance(evidence, dict), "legacy_preflight_evidence_missing") main_revision = evidence.get("main_revision") live_revision = evidence.get("live_revision") queue = evidence.get("queue") database = evidence.get("database") _need( isinstance(main_revision, str) and _SHA1.fullmatch(main_revision) is not None and isinstance(live_revision, str) and _SHA1.fullmatch(live_revision) is not None, "legacy_preflight_revision_invalid", ) _need( isinstance(queue, dict) and set(queue) == {"queued", "active", "completed", "failed"} and all(_is_count(queue.get(key)) for key in queue) and queue.get("queued") == 0 and queue.get("active") == 0, "legacy_preflight_queue_not_quiescent", ) _need( isinstance(database, dict) and all( _is_count(database.get(key)) for key in ( "database_bytes", "journal_bytes", "scan_count", "compacted_scan_count", ) ) and database.get("database_bytes", 0) > 0 and database.get("scan_count", -1) >= database.get("compacted_scan_count", 0), "legacy_preflight_database_facts_invalid", ) _need( evidence.get("container_state") == "running" and evidence.get("container_health") == "healthy", "legacy_preflight_runtime_invalid", ) return { "repository": REPOSITORY, "main_revision": main_revision, "live_revision": live_revision, "container_id_sha256": evidence.get("container_id_sha256"), "container_image_sha256": evidence.get("container_image_sha256"), "queue": { key: queue[key] for key in ("queued", "active", "completed", "failed") }, "database": { key: database[key] for key in ( "database_bytes", "journal_bytes", "scan_count", "compacted_scan_count", ) }, "container_state": "running", "container_health": "healthy", } def create_intent(report: object, idempotency_key: str) -> dict[str, Any]: """Create deterministic fixed-identity intent data from a passing preflight. Persistence is deliberately left to the future AppOps/controller adapters; this pure constructor never writes a database or controller state file. """ _need( isinstance(idempotency_key, str) and _IDEMPOTENCY_KEY.fullmatch(idempotency_key) is not None, "idempotency_key_invalid", ) projection = _safe_preflight_projection(report) idempotency_sha256 = hashlib.sha256( f"{PROTOCOL_VERSION}:{REPOSITORY}:{idempotency_key}".encode("ascii") ).hexdigest() intent_id = f"rpa-{idempotency_sha256[:20]}" intent = { "apiVersion": INTENT_VERSION, "protocolVersion": PROTOCOL_VERSION, "intentId": intent_id, "idempotencySha256": idempotency_sha256, "repository": REPOSITORY, "applicationId": APPLICATION_ID, "phase": "reserved", "status": "in_progress", "preflightSha256": _digest(projection), "legacyVolume": LEGACY_VOLUME, "legacyVolumePreserved": True, "evidence": {"preflight": projection}, "receipts": {}, "recovery": None, } return _validate_intent(intent) def reserve_or_replay( existing_intent: object | None, report: object, idempotency_key: str ) -> dict[str, Any]: """Enforce the single fixed adoption slot and exact retry identity.""" candidate = create_intent(report, idempotency_key) if existing_intent is None: return candidate existing = _validate_intent(existing_intent) _need( existing["idempotencySha256"] == candidate["idempotencySha256"], "one_time_adoption_already_reserved", ) _need( existing["preflightSha256"] == candidate["preflightSha256"], "idempotency_conflict", ) return deepcopy(existing) def _validate_intent(intent: object) -> dict[str, Any]: required = { "apiVersion", "protocolVersion", "intentId", "idempotencySha256", "repository", "applicationId", "phase", "status", "preflightSha256", "legacyVolume", "legacyVolumePreserved", "evidence", "receipts", "recovery", } _need(isinstance(intent, dict) and set(intent) == required, "intent_shape_invalid") value = intent _need( value.get("apiVersion") == INTENT_VERSION and value.get("protocolVersion") == PROTOCOL_VERSION and value.get("repository") == REPOSITORY and value.get("applicationId") == APPLICATION_ID and value.get("legacyVolume") == LEGACY_VOLUME and value.get("legacyVolumePreserved") is True and isinstance(value.get("intentId"), str) and _INTENT_ID.fullmatch(value["intentId"]) is not None and isinstance(value.get("idempotencySha256"), str) and _SHA256.fullmatch(value["idempotencySha256"]) is not None and value["intentId"] == f"rpa-{value['idempotencySha256'][:20]}" and isinstance(value.get("preflightSha256"), str) and _SHA256.fullmatch(value["preflightSha256"]) is not None and value.get("phase") in _PHASES and value.get("status") in {"in_progress", "recovery_required", "completed"} and isinstance(value.get("evidence"), dict) and isinstance(value.get("receipts"), dict), "intent_identity_invalid", ) _need( value.get("status") != "completed" or value.get("phase") == "completed", "intent_terminal_state_invalid", ) evidence = value["evidence"] _need( set(evidence) <= {"preflight", *_STEP_EVIDENCE_KEYS.values()} and isinstance(evidence.get("preflight"), dict) and _digest(evidence["preflight"]) == value["preflightSha256"], "intent_evidence_invalid", ) _validate_preflight_projection(evidence["preflight"]) receipts = value["receipts"] phase = value["phase"] expected_steps = { "reserved": (), "target_gates_ready": ("target_gates",), "quiesced": ("target_gates", "quiescence"), "snapshot_verified": ("target_gates", "quiescence", "snapshot"), "target_registered": ("target_gates", "quiescence", "snapshot", "controller_registration"), "appops_owned": tuple(key for key in _STEP_EVIDENCE_KEYS if key != "completion"), "completed": tuple(_STEP_EVIDENCE_KEYS), }[phase] _need(set(receipts) == set(expected_steps), "intent_receipts_incomplete") for step, record in receipts.items(): _need( isinstance(record, dict) and set(record) == {"evidenceSha256"} and isinstance(record.get("evidenceSha256"), str) and _SHA256.fullmatch(record["evidenceSha256"]) is not None, "intent_receipt_invalid", ) evidence_key = _STEP_EVIDENCE_KEYS[step] _need( evidence_key in evidence and _digest(evidence[evidence_key]) == record["evidenceSha256"], "intent_receipt_evidence_mismatch", ) if value["status"] == "recovery_required": recovery = value.get("recovery") _need( isinstance(recovery, dict) and set(recovery) == { "reason", "afterPhase", "failureEvidenceSha256", "controllerReconciliationRequired", "legacyVolumePreserved", } and recovery.get("reason") in _RECOVERY_REASONS and recovery.get("afterPhase") == phase and isinstance(recovery.get("failureEvidenceSha256"), str) and _SHA256.fullmatch(recovery["failureEvidenceSha256"]) is not None and recovery.get("controllerReconciliationRequired") is True and recovery.get("legacyVolumePreserved") is True, "intent_recovery_marker_invalid", ) else: _need(value.get("recovery") is None, "intent_recovery_marker_unexpected") return value def _intent_binding(intent: dict[str, Any]) -> str: return _digest( { "intentId": intent["intentId"], "repository": REPOSITORY, "applicationId": APPLICATION_ID, "preflightSha256": intent["preflightSha256"], "idempotencySha256": intent["idempotencySha256"], } ) def _target_gates(evidence: object) -> dict[str, Any]: required = { "profileId", "profileVersion", "planSha256", "profileReady", "controllerTrustReady", "controllerBootstrapSecretImported", "typedEnrollmentTrustReady", "targetSecretReady", "exactPolicyReady", "authenticatedRouteReady", "accessListReady", "mutationBoundaryReady", "managedRuntimeReady", "scanSourceMatches", "scanMountReadOnly", "scanPermissionPolicyPersistent", "scanAccessForRuntimeIdentityReady", "ownedDataTargetReady", "managedEnvironmentReady", "legacyEnvironmentRetained", "maintenanceAuthReady", "controllerAdoptionCapabilityReady", "controllerRegistryWriterReady", "controllerSecretWriterReady", } _need(isinstance(evidence, dict) and set(evidence) == required, "target_gates_invalid") value = evidence _need( value.get("profileId") == _PROFILE_ID and value.get("profileVersion") == PROFILE_VERSION and isinstance(value.get("planSha256"), str) and _SHA256.fullmatch(value["planSha256"]) is not None and all(value.get(key) is True for key in required - {"profileId", "profileVersion", "planSha256"}), "target_gates_not_ready", ) return {key: value[key] for key in sorted(required)} def _quiescence_evidence(evidence: object, intent: dict[str, Any]) -> dict[str, Any]: required = { "intentId", "globalDeployLockHeld", "projectLockHeld", "maintenanceModeActive", "queueFrozen", "queuedJobs", "activeJobs", "maintenanceModeAuthenticated", "containerName", "containerIdSha256", "containerImageSha256", "containerState", "legacyVolume", "controllerIntentDurable", "controllerIntentBindingSha256", } _need(isinstance(evidence, dict) and set(evidence) == required, "quiescence_evidence_invalid") value = evidence _need( value.get("intentId") == intent["intentId"] and value.get("globalDeployLockHeld") is True and value.get("projectLockHeld") is True and value.get("maintenanceModeActive") is True and value.get("queueFrozen") is True and value.get("maintenanceModeAuthenticated") is True and _is_count(value.get("queuedJobs")) and value.get("queuedJobs") == 0 and _is_count(value.get("activeJobs")) and value.get("activeJobs") == 0 and value.get("containerName") == "repopulse" and isinstance(value.get("containerIdSha256"), str) and _SHA256.fullmatch(value["containerIdSha256"]) is not None and value.get("containerIdSha256") == intent["evidence"]["preflight"]["container_id_sha256"] and isinstance(value.get("containerImageSha256"), str) and _SHA256.fullmatch(value["containerImageSha256"]) is not None and value.get("containerImageSha256") == intent["evidence"]["preflight"]["container_image_sha256"] and value.get("containerState") == "exited" and value.get("legacyVolume") == LEGACY_VOLUME and value.get("controllerIntentDurable") is True, "quiescence_not_proven", ) _need( isinstance(value.get("controllerIntentBindingSha256"), str) and _SHA256.fullmatch(value["controllerIntentBindingSha256"]) is not None and value["controllerIntentBindingSha256"] == _intent_binding(intent), "controller_intent_binding_mismatch", ) return {key: value[key] for key in sorted(required)} def _snapshot_evidence(evidence: object, intent: dict[str, Any]) -> dict[str, Any]: required = { "intentId", "globalDeployLockHeld", "projectLockHeld", "legacyContainerStopped", "legacyVolume", "legacyVolumeRetained", "sqliteBackupMethod", "quickCheck", "integrityCheck", "sourceLogicalSha256", "snapshotLogicalSha256", "snapshotFileSha256", "sourceScanCount", "snapshotScanCount", "sourceCompactedScanCount", "snapshotCompactedScanCount", "sourceQueueSha256", "snapshotQueueSha256", "sourceAuxiliaryTreeSha256", "sourceAuxiliaryFileCount", "targetDataPathWasAbsent", "snapshotReceiptDurable", "legacyEnvironmentRetained", "managedEnvironmentFilePrivate", "controllerIntentBindingSha256", } _need(isinstance(evidence, dict) and set(evidence) == required, "snapshot_evidence_invalid") value = evidence _need( value.get("intentId") == intent["intentId"] and value.get("globalDeployLockHeld") is True and value.get("projectLockHeld") is True and value.get("legacyContainerStopped") is True and value.get("legacyVolume") == LEGACY_VOLUME and value.get("legacyVolumeRetained") is True and value.get("sqliteBackupMethod") == "sqlite_online_backup" and value.get("quickCheck") == "ok" and value.get("integrityCheck") == "ok" and isinstance(value.get("sourceLogicalSha256"), str) and _SHA256.fullmatch(value["sourceLogicalSha256"]) is not None and value.get("sourceLogicalSha256") == value.get("snapshotLogicalSha256") and isinstance(value.get("snapshotFileSha256"), str) and _SHA256.fullmatch(value["snapshotFileSha256"]) is not None and _is_count(value.get("sourceScanCount")) and value.get("sourceScanCount") == value.get("snapshotScanCount") and _is_count(value.get("sourceCompactedScanCount")) and value.get("sourceCompactedScanCount") == value.get("snapshotCompactedScanCount") and isinstance(value.get("sourceQueueSha256"), str) and _SHA256.fullmatch(value["sourceQueueSha256"]) is not None and value.get("sourceQueueSha256") == value.get("snapshotQueueSha256") and isinstance(value.get("sourceAuxiliaryTreeSha256"), str) and _SHA256.fullmatch(value["sourceAuxiliaryTreeSha256"]) is not None and _is_count(value.get("sourceAuxiliaryFileCount")) and value.get("targetDataPathWasAbsent") is True and value.get("snapshotReceiptDurable") is True and value.get("legacyEnvironmentRetained") is True and value.get("managedEnvironmentFilePrivate") is True, "sqlite_snapshot_not_verified", ) _need( isinstance(value.get("controllerIntentBindingSha256"), str) and _SHA256.fullmatch(value["controllerIntentBindingSha256"]) is not None and value["controllerIntentBindingSha256"] == _intent_binding(intent), "controller_intent_binding_mismatch", ) return {key: value[key] for key in sorted(required)} def _controller_registration_evidence( evidence: object, intent: dict[str, Any] ) -> dict[str, Any]: required = { "receiptVersion", "intentId", "receiptSha256", "repository", "applicationId", "enrollmentId", "profileId", "planSha256", "snapshotFileSha256", "targetLogicalSha256", "targetScanCount", "targetCompactedScanCount", "targetQueueSha256", "targetAuxiliaryTreeSha256", "targetAuxiliaryFileCount", "targetQueuedJobs", "targetActiveJobs", "targetQuickCheck", "targetIntegrityCheck", "targetRecoveryStatus", "targetDataUid", "targetDataGid", "managedDataMountMatches", "copySourceIsVerifiedSnapshot", "registryTargetMatches", "controllerStateReceiptVerified", "deploymentReceiptSchema", "deploymentReceiptSha256", "deploymentReceiptVerified", "runtimeHealthy", "publishedHostPorts", "globalDeployLockHeld", "projectLockHeld", "legacyVolume", "legacyVolumeRetained", "legacyEnvironmentRetained", "managedEnvironmentFilePrivate", "scanSourceMatches", "scanMountReadOnly", "scanPermissionPolicyPersistent", "scanAccessForRuntimeIdentityReady", "controllerIntentDurable", "controllerIntentBindingSha256", } _need( isinstance(evidence, dict) and set(evidence) == required, "controller_receipt_evidence_invalid", ) value = evidence gates = intent["evidence"].get("targetGates") snapshot = intent["evidence"].get("snapshot") _need(isinstance(gates, dict) and isinstance(snapshot, dict), "adoption_prerequisite_missing") _need( value.get("receiptVersion") == CONTROLLER_RECEIPT_VERSION and value.get("intentId") == intent["intentId"] and isinstance(value.get("receiptSha256"), str) and _SHA256.fullmatch(value["receiptSha256"]) is not None and value.get("repository") == REPOSITORY and value.get("applicationId") == APPLICATION_ID and isinstance(value.get("enrollmentId"), str) and _ENROLLMENT_ID.fullmatch(value["enrollmentId"]) is not None and value.get("profileId") == gates["profileId"] and value.get("planSha256") == gates["planSha256"] and value.get("snapshotFileSha256") == snapshot["snapshotFileSha256"] and isinstance(value.get("targetLogicalSha256"), str) and value.get("targetLogicalSha256") == snapshot["snapshotLogicalSha256"] and _is_count(value.get("targetScanCount")) and value.get("targetScanCount") == snapshot["snapshotScanCount"] and _is_count(value.get("targetCompactedScanCount")) and value.get("targetCompactedScanCount") == snapshot["snapshotCompactedScanCount"] and value.get("targetQueueSha256") == snapshot["snapshotQueueSha256"] and value.get("targetAuxiliaryTreeSha256") == snapshot["sourceAuxiliaryTreeSha256"] and value.get("targetAuxiliaryFileCount") == snapshot["sourceAuxiliaryFileCount"] and _is_count(value.get("targetQueuedJobs")) and value.get("targetQueuedJobs") == 0 and _is_count(value.get("targetActiveJobs")) and value.get("targetActiveJobs") == 0 and value.get("targetQuickCheck") == "ok" and value.get("targetIntegrityCheck") == "ok" and value.get("targetRecoveryStatus") in {"healthy", "acknowledged"} and value.get("targetDataUid") == 10001 and value.get("targetDataGid") == 10001 and value.get("managedDataMountMatches") is True and value.get("copySourceIsVerifiedSnapshot") is True and value.get("registryTargetMatches") is True and value.get("controllerStateReceiptVerified") is True and value.get("deploymentReceiptSchema") == "gitea-deploy-receipt.v1" and isinstance(value.get("deploymentReceiptSha256"), str) and _SHA256.fullmatch(value["deploymentReceiptSha256"]) is not None and value.get("deploymentReceiptVerified") is True and value.get("runtimeHealthy") is True and value.get("publishedHostPorts") == [] and value.get("globalDeployLockHeld") is True and value.get("projectLockHeld") is True and value.get("legacyVolume") == LEGACY_VOLUME and value.get("legacyVolumeRetained") is True and value.get("legacyEnvironmentRetained") is True and value.get("managedEnvironmentFilePrivate") is True and value.get("scanSourceMatches") is True and value.get("scanMountReadOnly") is True and value.get("scanPermissionPolicyPersistent") is True and value.get("scanAccessForRuntimeIdentityReady") is True and value.get("controllerIntentDurable") is True and value.get("controllerIntentBindingSha256") == _intent_binding(intent), "controller_adoption_receipt_not_verified", ) return {key: value[key] for key in sorted(required)} def validate_controller_registration_evidence( intent: object, evidence: object ) -> dict[str, Any]: """Validate fresh controller registration evidence against the intent. This pure projection can validate receipt replays after AppOps reaches its terminal `completed` phase. Controller response authentication remains the caller's responsibility. """ current = _validate_intent(intent) return _controller_registration_evidence(evidence, current) def _appops_ownership_evidence( evidence: object, intent: dict[str, Any] ) -> dict[str, Any]: required = { "repository", "applicationId", "enrollmentId", "profileId", "planSha256", "controllerReceiptSha256", "enrollmentPersisted", "exactApplyPolicyPersisted", "exactRollbackPolicyPersisted", "secretReferenceReady", } _need(isinstance(evidence, dict) and set(evidence) == required, "appops_ownership_evidence_invalid") value = evidence registration = intent["evidence"].get("controllerRegistration") _need(isinstance(registration, dict), "controller_registration_missing") gates = intent["evidence"].get("targetGates") _need(isinstance(gates, dict), "target_gates_missing") _need( value.get("repository") == REPOSITORY and value.get("applicationId") == APPLICATION_ID and value.get("enrollmentId") == registration["enrollmentId"] and value.get("profileId") == registration["profileId"] and value.get("planSha256") == gates["planSha256"] and value.get("controllerReceiptSha256") == registration["receiptSha256"] and all( value.get(key) is True for key in ( "enrollmentPersisted", "exactApplyPolicyPersisted", "exactRollbackPolicyPersisted", "secretReferenceReady", ) ), "appops_ownership_not_verified", ) return {key: value[key] for key in sorted(required)} def validate_appops_ownership_evidence( intent: object, evidence: object ) -> dict[str, Any]: """Validate fixed ownership evidence for an idempotent completed replay.""" current = _validate_intent(intent) return _appops_ownership_evidence(evidence, current) def advance_intent( intent: object, step: str, evidence: object ) -> dict[str, Any]: """Purely validate and record one forward protocol checkpoint. The exact evidence digest makes retries idempotent. Replaying a step with different evidence is a conflict and must enter recovery review. """ current = _validate_intent(intent) _need(current.get("status") == "in_progress", "intent_requires_recovery") _need(step in _STEP_CONTRACTS, "adoption_step_unknown") source_phase, destination_phase = _STEP_CONTRACTS[step] checked = { "target_gates": _target_gates, "quiescence": lambda value: _quiescence_evidence(value, current), "snapshot": lambda value: _snapshot_evidence(value, current), "controller_registration": lambda value: _controller_registration_evidence(value, current), "appops_ownership": lambda value: _appops_ownership_evidence(value, current), }[step](evidence) digest = _digest(checked) receipts = current["receipts"] previous = receipts.get(step) if previous is not None: _need( current.get("phase") in _PHASES[_PHASES.index(destination_phase):] and isinstance(previous, dict) and previous.get("evidenceSha256") == digest, "idempotency_conflict", ) return deepcopy(current) _need(current.get("phase") == source_phase, "adoption_step_out_of_order") updated = deepcopy(current) updated["phase"] = destination_phase updated["recovery"] = None updated["receipts"][step] = {"evidenceSha256": digest} evidence_key = _STEP_EVIDENCE_KEYS[step] updated["evidence"][evidence_key] = checked _validate_intent(updated) return updated def complete_intent(intent: object, evidence: object) -> dict[str, Any]: """Finalize only after re-reading both AppOps ownership and controller receipt.""" current = _validate_intent(intent) _need( current.get("status") == "in_progress" and current.get("phase") == "appops_owned", "adoption_not_ready_to_complete", ) required = { "intentId", "repository", "applicationId", "enrollmentId", "controllerReceiptSha256", "enrollmentStillPersisted", "exactApplyPolicyStillPersisted", "exactRollbackPolicyStillPersisted", "controllerReceiptStillMatches", "legacyVolumeRetained", } _need(isinstance(evidence, dict) and set(evidence) == required, "completion_evidence_invalid") value = evidence ownership = current["evidence"].get("appopsOwnership") registration = current["evidence"].get("controllerRegistration") _need(isinstance(ownership, dict) and isinstance(registration, dict), "adoption_prerequisite_missing") _need( value.get("intentId") == current["intentId"] and value.get("repository") == REPOSITORY and value.get("applicationId") == APPLICATION_ID and value.get("enrollmentId") == registration["enrollmentId"] and value.get("controllerReceiptSha256") == registration["receiptSha256"] and value.get("controllerReceiptSha256") == ownership["controllerReceiptSha256"] and all( value.get(key) is True for key in ( "enrollmentStillPersisted", "exactApplyPolicyStillPersisted", "exactRollbackPolicyStillPersisted", "controllerReceiptStillMatches", "legacyVolumeRetained", ) ), "completion_not_verified", ) checked = {key: value[key] for key in sorted(required)} updated = deepcopy(current) updated["phase"] = "completed" updated["status"] = "completed" updated["evidence"]["completion"] = checked updated["receipts"]["completion"] = {"evidenceSha256": _digest(checked)} return _validate_intent(updated) def mark_recovery_required( intent: object, reason: str, failure_evidence: object ) -> dict[str, Any]: """Persist a sanitized recovery marker without compensating external state.""" current = _validate_intent(intent) _need(current.get("status") != "completed", "intent_already_completed") _need(reason in _RECOVERY_REASONS, "recovery_reason_invalid") _need(isinstance(failure_evidence, dict), "recovery_evidence_invalid") # Only bind the evidence; arbitrary external messages/paths/secret values # are never copied into the journal by this pure protocol helper. updated = deepcopy(current) updated["status"] = "recovery_required" updated["recovery"] = { "reason": reason, "afterPhase": current["phase"], "failureEvidenceSha256": _digest(failure_evidence), "controllerReconciliationRequired": True, "legacyVolumePreserved": True, } return updated def resume_intent(intent: object, controller_receipt: object) -> dict[str, Any]: """Resume only from an authenticated controller receipt bound to this intent. The adapter that calls this function must authenticate the controller response. This pure helper validates its exact content and only reconciles the single ambiguous boundary: controller registration committed while the AppOps intent checkpoint was interrupted. """ current = _validate_intent(intent) _need(current.get("status") == "recovery_required", "intent_not_in_recovery") required = { "apiVersion", "intentId", "phase", "receiptSha256", "repository", "applicationId", "legacyVolumeRetained", "intentDurable", "intentBindingSha256", "registrationEvidence", } _need( isinstance(controller_receipt, dict) and set(controller_receipt) == required, "controller_recovery_receipt_invalid", ) receipt = controller_receipt _need( receipt.get("apiVersion") == CONTROLLER_RECEIPT_VERSION and receipt.get("intentId") == current["intentId"] and receipt.get("repository") == REPOSITORY and receipt.get("applicationId") == APPLICATION_ID and receipt.get("legacyVolumeRetained") is True and receipt.get("intentDurable") is True and receipt.get("intentBindingSha256") == _intent_binding(current) and isinstance(receipt.get("receiptSha256"), str) and _SHA256.fullmatch(receipt["receiptSha256"]) is not None, "controller_recovery_receipt_unbound", ) phase = receipt.get("phase") if phase == current["phase"]: _need( current["phase"] in {"reserved", "target_gates_ready", "quiesced", "snapshot_verified", "target_registered", "appops_owned"}, "controller_recovery_phase_invalid", ) if phase in {"target_registered", "appops_owned"}: registration = _controller_registration_evidence( receipt.get("registrationEvidence"), current ) _need( receipt.get("receiptSha256") == registration["receiptSha256"] and registration == current["evidence"].get("controllerRegistration"), "controller_recovery_receipt_conflict", ) else: _need( receipt.get("registrationEvidence") is None, "controller_recovery_receipt_conflict", ) updated = deepcopy(current) updated["status"] = "in_progress" updated["recovery"] = None return updated _need( current.get("phase") == "snapshot_verified" and phase == "target_registered", "controller_recovery_phase_conflict", ) registration = _controller_registration_evidence(receipt.get("registrationEvidence"), current) registration_digest = _digest(registration) _need(receipt.get("receiptSha256") == registration["receiptSha256"], "controller_recovery_receipt_digest_mismatch") updated = deepcopy(current) updated["phase"] = "target_registered" updated["status"] = "in_progress" updated["recovery"] = None updated["receipts"]["controller_registration"] = {"evidenceSha256": registration_digest} updated["evidence"]["controllerRegistration"] = registration _validate_intent(updated) return updated def intent_binding_sha256(intent: object) -> str: """Return the immutable root-controller journal binding for an intent.""" current = _validate_intent(intent) return _intent_binding(current) def execution_status() -> dict[str, Any]: """Report the code gate without claiming live target readiness.""" return { "apiVersion": PROTOCOL_VERSION, "repository": REPOSITORY, "status": "enabled" if EXECUTION_ENABLED is True else "disabled", "reason": None if EXECUTION_ENABLED is True else "controller_adoption_execution_disabled", "executionEnabled": EXECUTION_ENABLED, }