teleo-infrastructure/ops/verify_gcp_canonical_lifecycle.py

792 lines
42 KiB
Python

#!/usr/bin/env python3
"""Verify one bound source-to-GCP restore, reasoning, and cleanup lifecycle."""
from __future__ import annotations
import argparse
import hashlib
import ipaddress
import json
import re
from datetime import UTC, datetime
from itertools import pairwise
from pathlib import Path
from typing import Any
try:
from .private_receipt_io import print_private_receipt_summary
from .restore_gcp_generated_postgres_snapshot import DEFAULT_RESTORE_SERVICE_ACCOUNT
from .verify_postgres_parity_manifest import REVIEWED_MANIFEST_SQL_SHA256
from .verify_vps_canonical_snapshot_delta import DELTA_SCHEMA, parse_timestamp, write_private_json
except ImportError: # pragma: no cover - direct script execution
from private_receipt_io import print_private_receipt_summary
from restore_gcp_generated_postgres_snapshot import DEFAULT_RESTORE_SERVICE_ACCOUNT
from verify_postgres_parity_manifest import REVIEWED_MANIFEST_SQL_SHA256
from verify_vps_canonical_snapshot_delta import DELTA_SCHEMA, parse_timestamp, write_private_json
SOURCE_SCHEMA = "livingip.sourceSnapshotReceipt.v2"
BLIND_REASONING_SCHEMA = "livingip.gcpGeneratedDbBlindClaimCanary.v1"
REASONING_COMPUTE_SCHEMA = "livingip.gcpReasoningComputeAttestation.v1"
RETRIEVAL_RECEIPT_SCHEMA = "livingip.teleoKbRetrievalReceipt.v1"
UUID_RE = re.compile(r"\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b", re.I)
SHA256_RE = re.compile(r"[0-9a-f]{64}\Z")
FORBIDDEN_HANDLE_RE = re.compile(r"\b(?:cory|m3ta)\b", re.I)
EXPECTED_BLIND_ROW_IDS = {
"2a7ae257-d01d-46f4-b813-63f81bb9c7c7",
"261c3532-fa32-47d8-a5b5-6cc45035c267",
"15740795-ecc6-40fa-9a01-3d6bc7c54f79",
}
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def load_receipt(path: Path, label: str) -> dict[str, Any]:
try:
payload = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise ValueError(f"{label} is unreadable or invalid JSON") from exc
if not isinstance(payload, dict):
raise ValueError(f"{label} must be a JSON object")
return payload
def is_rfc1918(value: Any) -> bool:
try:
address = ipaddress.ip_address(str(value))
except ValueError:
return False
return any(
address in network
for network in (
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
)
)
def nonempty_all_true(value: Any) -> bool:
return isinstance(value, dict) and bool(value) and all(item is True for item in value.values())
def required_true_checks(value: Any, required: set[str]) -> bool:
return nonempty_all_true(value) and required <= set(value)
def service_healthy(value: Any) -> bool:
if not isinstance(value, dict):
return False
try:
main_pid = int(value.get("MainPID") or 0)
restarts = int(value.get("NRestarts") or 0)
except (TypeError, ValueError):
return False
return (
value.get("ActiveState") == "active" and value.get("SubState") == "running" and main_pid > 0 and restarts >= 0
)
def parity_evidence(details: dict[str, Any]) -> dict[str, bool]:
structural = details.get("structural_hashes") or {}
required_structures = {
"schemas",
"columns",
"constraints",
"indexes",
"sequences",
"views",
"functions",
"triggers",
"types",
"policies",
"role_memberships",
"object_ownership",
"object_acl",
}
structural_valid = required_structures <= set(structural) and all(
bool(SHA256_RE.fullmatch(str((structural.get(kind) or {}).get("source") or "")))
and (structural.get(kind) or {}).get("source") == (structural.get(kind) or {}).get("target")
for kind in required_structures
)
performance = details.get("performance") or []
performance_valid = bool(performance) and all(
bool(row.get("query"))
and isinstance(row.get("source_ms"), (int, float))
and isinstance(row.get("target_ms"), (int, float))
and isinstance(row.get("source_ratio"), (int, float))
for row in performance
)
source_table_count = details.get("source_table_count")
target_table_count = details.get("target_table_count")
source_total_rows = details.get("source_total_rows")
target_total_rows = details.get("target_total_rows")
return {
"table_counts": isinstance(source_table_count, int)
and source_table_count > 0
and source_table_count == target_table_count,
"row_counts": isinstance(source_total_rows, int)
and source_total_rows > 0
and source_total_rows == target_total_rows,
"table_hashes": details.get("table_mismatches") == [] and details.get("table_hash_problems") == [],
"structural_hashes": structural_valid,
"roles": details.get("application_role_mismatches") == {}
and details.get("target_extra_application_roles") == [],
"extensions": details.get("required_extension_mismatches") == {}
and details.get("target_extra_extensions") == [],
"performance": performance_valid and details.get("performance_problems") == [],
}
def blind_reasoning_evidence(reasoning: dict[str, Any], target_db: Any) -> dict[str, bool]:
result = reasoning.get("result") or {}
gateway = result.get("gateway") or {}
child = gateway.get("child_process") or {}
tool_surface = gateway.get("tool_surface") or {}
tool_trace = result.get("database_tool_trace") or {}
calls = tool_trace.get("calls") or []
wrapper = reasoning.get("wrapper_tool_proof") or {}
invocations = wrapper.get("invocations") or []
prompt = str(reasoning.get("prompt") or "")
reply = str(result.get("reply") or "")
outcomes = reasoning.get("outcomes") or {}
required_outcomes = (
"asks_for_user_iteration_before_live",
"challenges_weak_support",
"decomposes_the_bundled_legal_claim",
"does_not_claim_a_database_change",
"proposes_candidate_claims",
"uses_only_m3taversal_handle",
)
required_subcommands = {"show", "evidence"}
discovery_subcommands = {"search", "context"}
traced_subcommands = {
str(invocation.get("subcommand")) for call in calls for invocation in (call.get("database_invocations") or [])
}
wrapper_subcommands = {str(invocation.get("subcommand")) for invocation in invocations}
retrieved_row_ids = {str(row_id) for call in calls for row_id in ((call.get("result") or {}).get("row_ids") or [])}
call_row_ids_valid = bool(calls) and all(
isinstance((call.get("result") or {}).get("row_ids"), list)
and isinstance((call.get("result") or {}).get("row_id_count"), int)
and (call.get("result") or {}).get("row_id_count") >= 0
and (call.get("result") or {}).get("row_id_count") >= len((call.get("result") or {}).get("row_ids") or [])
for call in calls
)
call_receipts_valid = bool(calls) and all(
(call.get("result") or {}).get("nonempty") is True
and (call.get("result") or {}).get("error_detected") is False
and ((call.get("result") or {}).get("retrieval_receipt") or {}).get("schema") == RETRIEVAL_RECEIPT_SCHEMA
and bool(
SHA256_RE.fullmatch(
str(((call.get("result") or {}).get("retrieval_receipt") or {}).get("semantic_context_sha256") or "")
)
)
and bool(
SHA256_RE.fullmatch(
str(((call.get("result") or {}).get("retrieval_receipt") or {}).get("artifact_state_sha256") or "")
)
)
and str(
((call.get("result") or {}).get("retrieval_receipt") or {}).get("read_consistency_status") or ""
).startswith("stable")
for call in calls
)
wrapper_invocations_valid = bool(invocations) and all(
invocation.get("database") == target_db
and invocation.get("returncode") == 0
and ((invocation.get("database_identity") or {}).get("transaction_read_only") == "on")
and ((invocation.get("database_identity") or {}).get("default_transaction_read_only") == "on")
and ((invocation.get("database_identity") or {}).get("ssl") is True)
and ((invocation.get("database_identity") or {}).get("sslmode") == "verify-full")
and ((invocation.get("database_identity") or {}).get("server_identity_verified") is True)
and bool((invocation.get("database_identity") or {}).get("ssl_server_name"))
and bool(
SHA256_RE.fullmatch(str((invocation.get("database_identity") or {}).get("ssl_root_cert_sha256") or ""))
)
and is_rfc1918((invocation.get("database_identity") or {}).get("server_address"))
for invocation in invocations
)
return {
"mode": reasoning.get("mode") == "gcp_generated_db_gatewayrunner_blind_claim_no_send",
"timestamps": bool(reasoning.get("generated_at_utc")) and bool(reasoning.get("completed_at_utc")),
"source_compute": bool(reasoning.get("source_compute")),
"blind_prompt": bool(prompt) and UUID_RE.search(prompt) is None,
"reply_nonempty": bool(reply.strip()),
"reply_uses_only_m3taversal_handle": FORBIDDEN_HANDLE_RE.search(reply) is None,
"outcomes": all(outcomes.get(name) is True for name in required_outcomes),
"gateway": gateway.get("authorized") is True
and gateway.get("handler_invoked") is True
and gateway.get("model_free_fallback_used") is False
and gateway.get("posted_to_telegram") is False,
"gateway_cleanup": child.get("exitcode") == 0
and child.get("alive_after_readback") is False
and child.get("process_group_alive_after_readback") is False
and child.get("timed_out") is False,
"send_tool_absent": tool_surface.get("send_message_tool_enabled") is False,
"tool_trace": tool_trace.get("schema") == "livingip.leoKbToolTrace.v1"
and tool_trace.get("database_tool_call_proven") is True
and tool_trace.get("database_retrieval_receipt_proven") is True
and tool_trace.get("database_tool_calls_read_only") is True
and tool_trace.get("database_tool_call_count") == len(calls)
and tool_trace.get("database_tool_completed_count") == len(calls),
"tool_receipts": call_receipts_valid,
"expected_claim_and_sources_retrieved": call_row_ids_valid and retrieved_row_ids >= EXPECTED_BLIND_ROW_IDS,
"required_tool_sequence": required_subcommands <= traced_subcommands
and bool(discovery_subcommands & traced_subcommands),
"wrapper": wrapper.get("all_bound_to_supplied_target") is True
and wrapper.get("all_completed_successfully") is True
and wrapper.get("complete_start_end_pairing") is True
and wrapper.get("database_read_only_required") is True
and wrapper.get("default_read_only_required") is True,
"wrapper_invocations": wrapper_invocations_valid
and required_subcommands <= wrapper_subcommands
and bool(discovery_subcommands & wrapper_subcommands),
"canonical_status_unchanged": bool(reasoning.get("canonical_status_before"))
and reasoning.get("canonical_status_before") == reasoning.get("canonical_status_after"),
"database_identity_unchanged": bool(reasoning.get("database_identity_before"))
and reasoning.get("database_identity_before") == reasoning.get("database_identity_after"),
"service_unchanged": service_healthy(reasoning.get("service_before"))
and reasoning.get("service_before") == reasoning.get("service_after"),
"temporary_profile_removed": reasoning.get("temp_profile_absent") is True
and reasoning.get("temp_profile_removed") is True,
}
def verify_lifecycle(
*,
source_path: Path,
current_source_path: Path,
source_delta_path: Path,
restore_path: Path,
parity_path: Path,
reasoning_path: Path,
reasoning_compute_path: Path,
cleanup_path: Path,
max_postflight_age_seconds: float = 900.0,
max_lifecycle_age_seconds: float = 3600.0,
now: datetime | None = None,
) -> dict[str, Any]:
if max_postflight_age_seconds <= 0:
raise ValueError("max postflight age must be positive")
if max_lifecycle_age_seconds <= 0:
raise ValueError("max lifecycle age must be positive")
verification_time = (now or datetime.now(UTC)).astimezone(UTC)
source = load_receipt(source_path, "source receipt")
current_source = load_receipt(current_source_path, "current source receipt")
source_delta = load_receipt(source_delta_path, "source delta receipt")
restore = load_receipt(restore_path, "restore receipt")
parity = load_receipt(parity_path, "parity receipt")
reasoning = load_receipt(reasoning_path, "reasoning receipt")
reasoning_compute_attestation = load_receipt(reasoning_compute_path, "reasoning compute attestation")
cleanup = load_receipt(cleanup_path, "cleanup receipt")
target_db = restore.get("target_database")
run_id = restore.get("run_id")
restore_source = restore.get("source") or {}
capture_binding = restore_source.get("capture_receipt") or {}
restore_target = restore.get("target") or {}
restore_connectivity = restore_target.get("connectivity") or {}
restore_connectivity_proof = restore_target.get("connectivity_proof") or {}
restore_cloudsql = restore_target.get("cloudsql") or {}
restore_compute = restore_target.get("compute") or {}
restore_parity = restore.get("parity") or {}
restore_service = restore.get("live_service") or {}
parity_details = parity.get("details") or {}
parity_evidence_checks = parity_evidence(parity_details)
restore_inline_parity_checks = parity_evidence(restore_parity.get("details") or {})
parity_connectivity = parity.get("private_connectivity") or {}
parity_connectivity_proof = parity_connectivity.get("proof") or {}
reasoning_checks = reasoning.get("checks") or {}
reasoning_parity = reasoning.get("parity_receipt") or {}
before_fingerprint = reasoning.get("database_fingerprint_before") or {}
after_fingerprint = reasoning.get("database_fingerprint_after") or {}
cleanup_database = cleanup.get("database") or {}
cleanup_service = cleanup.get("live_service") or {}
cleanup_cloudsql = (cleanup.get("target") or {}).get("cloudsql") or {}
cleanup_compute = (cleanup.get("target") or {}).get("compute") or {}
restore_contract = restore.get("execution_contract") or {}
cleanup_contract = cleanup.get("execution_contract") or {}
producer_reasoning_checks = blind_reasoning_evidence(reasoning, target_db)
reasoning_compute = reasoning_compute_attestation.get("compute") or {}
reasoning_compute_checks = reasoning_compute_attestation.get("checks") or {}
reasoning_compute_mutation = reasoning_compute_attestation.get("mutation") or {}
delta_baseline = source_delta.get("baseline") or {}
delta_current = source_delta.get("current") or {}
delta_details = source_delta.get("delta") or {}
source_snapshot = source.get("snapshot") or {}
current_source_snapshot = current_source.get("snapshot") or {}
timeline_values = {
"source_snapshot": source_snapshot.get("captured_at_utc"),
"restore_started": restore.get("generated_at_utc"),
"restore_completed": restore.get("completed_at_utc"),
"parity_completed": parity.get("completed_at_utc"),
"reasoning_started": reasoning.get("generated_at_utc"),
"reasoning_completed": reasoning.get("completed_at_utc"),
"reasoning_compute_attested": reasoning_compute_attestation.get("generated_at_utc"),
"cleanup_started": cleanup.get("generated_at_utc"),
"cleanup_completed": cleanup.get("completed_at_utc"),
"current_source_snapshot": current_source_snapshot.get("captured_at_utc"),
}
timeline = [parse_timestamp(value, name) for name, value in timeline_values.items()]
lifecycle_chronology = all(earlier <= later for earlier, later in pairwise(timeline))
delta_detected = delta_details.get("delta_detected")
delta_change_present = bool(
delta_details.get("added_tables")
or delta_details.get("removed_tables")
or delta_details.get("changed_tables")
or delta_details.get("changed_structures")
or delta_details.get("total_row_delta")
)
current_source_time = parse_timestamp(
current_source_snapshot.get("captured_at_utc"), "current source snapshot time"
)
restore_started_time = parse_timestamp(restore.get("generated_at_utc"), "restore start time")
cleanup_completed_time = parse_timestamp(cleanup.get("completed_at_utc"), "cleanup completion time")
postflight_age_seconds = (verification_time - current_source_time).total_seconds()
lifecycle_age_seconds = (verification_time - cleanup_completed_time).total_seconds()
lifecycle_span_seconds = (current_source_time - restore_started_time).total_seconds()
postflight_after_lifecycle = current_source_time >= max(
parse_timestamp(reasoning.get("completed_at_utc"), "reasoning completion time"),
parse_timestamp(cleanup.get("completed_at_utc"), "cleanup completion time"),
)
required_reasoning_checks = (
"exact_blind_prompt_without_ids",
"claim_and_sources_retrieved",
"discovery_show_evidence_completed",
"retrieval_receipts_proven",
"private_tls_read_only_target",
"generated_database_unchanged",
"canonical_counts_unchanged",
"database_calls_read_only",
"no_database_write",
"no_telegram_send",
"live_service_unchanged",
"live_profile_unchanged",
"temporary_profile_removed",
)
checks = {
"source_schema_v2": source.get("schema") == SOURCE_SCHEMA and source.get("receipt_version") == 2,
"source_pass": source.get("status") == "pass"
and source.get("snapshot_exported") is True
and (source.get("source_service") or {}).get("unchanged") is True
and service_healthy((source.get("source_service") or {}).get("before"))
and (source.get("source_service") or {}).get("before") == (source.get("source_service") or {}).get("after"),
"source_authorized": bool(source.get("capture_authorization_ref")),
"source_authorization_bound": capture_binding.get("capture_authorization_ref")
== source.get("capture_authorization_ref"),
"source_service_unchanged": source.get("service_unchanged") is True,
"source_not_mutated": source.get("production_db_mutated") is False,
"current_source_schema_v2": current_source.get("schema") == SOURCE_SCHEMA
and current_source.get("receipt_version") == 2,
"current_source_pass": current_source.get("status") == "pass"
and current_source.get("snapshot_exported") is True
and current_source.get("service_unchanged") is True
and (current_source.get("source_service") or {}).get("unchanged") is True
and service_healthy((current_source.get("source_service") or {}).get("before"))
and (current_source.get("source_service") or {}).get("before")
== (current_source.get("source_service") or {}).get("after")
and current_source.get("production_db_mutated") is False,
"current_source_identity": current_source.get("source") == source.get("source")
and current_source_snapshot.get("system_identifier") == source_snapshot.get("system_identifier"),
"source_delta_pass": source_delta.get("artifact") == "vps_canonical_snapshot_postflight_delta"
and source_delta.get("schema") == DELTA_SCHEMA
and source_delta.get("status") == "pass",
"source_delta_receipts_bound": delta_baseline.get("capture_receipt_sha256") == sha256_file(source_path)
and delta_current.get("capture_receipt_sha256") == sha256_file(current_source_path),
"source_delta_manifests_bound": delta_baseline.get("manifest_sha256")
== (source.get("manifest") or {}).get("sha256")
and delta_current.get("manifest_sha256") == (current_source.get("manifest") or {}).get("sha256"),
"source_delta_manifest_sql_bound": delta_baseline.get("manifest_sql_sha256")
== (source.get("manifest") or {}).get("manifest_sql_sha256")
and delta_current.get("manifest_sql_sha256")
== (current_source.get("manifest") or {}).get("manifest_sql_sha256")
and delta_baseline.get("manifest_sql_sha256") == delta_current.get("manifest_sql_sha256"),
"source_delta_manifest_sql_reviewed": delta_baseline.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
and delta_current.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
and (source.get("manifest") or {}).get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
and (current_source.get("manifest") or {}).get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256
and capture_binding.get("manifest_sql_sha256") == REVIEWED_MANIFEST_SQL_SHA256,
"source_delta_authorizations_bound": delta_baseline.get("capture_authorization_ref")
== source.get("capture_authorization_ref")
and delta_current.get("capture_authorization_ref") == current_source.get("capture_authorization_ref"),
"source_delta_explicit": isinstance(delta_details.get("delta_detected"), bool)
and isinstance(delta_details.get("added_tables"), list)
and isinstance(delta_details.get("removed_tables"), list)
and isinstance(delta_details.get("changed_tables"), list)
and isinstance(delta_details.get("changed_structures"), list)
and isinstance(delta_details.get("total_row_delta"), int),
"source_delta_baseline_shape": delta_baseline.get("run_id") == source.get("run_id")
and delta_baseline.get("captured_at_utc") == source_snapshot.get("captured_at_utc")
and delta_baseline.get("table_count") == (source.get("manifest") or {}).get("table_count")
and delta_baseline.get("total_rows") == (source.get("manifest") or {}).get("total_rows")
and bool(SHA256_RE.fullmatch(str(delta_baseline.get("table_fingerprint_sha256") or "")))
and bool(SHA256_RE.fullmatch(str(delta_baseline.get("structure_fingerprint_sha256") or ""))),
"source_delta_current_shape": delta_current.get("run_id") == current_source.get("run_id")
and delta_current.get("captured_at_utc") == current_source_snapshot.get("captured_at_utc")
and delta_current.get("table_count") == (current_source.get("manifest") or {}).get("table_count")
and delta_current.get("total_rows") == (current_source.get("manifest") or {}).get("total_rows")
and bool(SHA256_RE.fullmatch(str(delta_current.get("table_fingerprint_sha256") or "")))
and bool(SHA256_RE.fullmatch(str(delta_current.get("structure_fingerprint_sha256") or ""))),
"source_delta_consistent": delta_detected is delta_change_present
and delta_details.get("total_row_delta")
== (delta_current.get("total_rows") or 0) - (delta_baseline.get("total_rows") or 0)
and (
delta_detected is True
or (
delta_baseline.get("table_count") == delta_current.get("table_count")
and delta_baseline.get("total_rows") == delta_current.get("total_rows")
and delta_baseline.get("table_fingerprint_sha256") == delta_current.get("table_fingerprint_sha256")
and delta_baseline.get("structure_fingerprint_sha256")
== delta_current.get("structure_fingerprint_sha256")
)
),
"source_postflight_after_lifecycle": postflight_after_lifecycle,
"source_postflight_fresh": 0 <= postflight_age_seconds <= max_postflight_age_seconds,
"gcp_lifecycle_fresh": 0 <= lifecycle_age_seconds <= max_lifecycle_age_seconds,
"lifecycle_span_bounded": 0 <= lifecycle_span_seconds <= max_lifecycle_age_seconds,
"lifecycle_chronology": lifecycle_chronology,
"restore_pass": restore.get("artifact") == "gcp_generated_postgres_snapshot_restore"
and restore.get("status") == "pass",
"restore_target_is_disposable": isinstance(target_db, str) and target_db.startswith("teleo_clone_"),
"restore_run_id": isinstance(run_id, str) and run_id.startswith("gcp-restore-"),
"source_receipt_hash_bound": capture_binding.get("sha256") == sha256_file(source_path),
"source_provenance_bound": capture_binding.get("provenance_binding_sha256")
== (source.get("provenance_binding") or {}).get("sha256"),
"source_capture_checks": required_true_checks(
capture_binding.get("checks"),
{
"artifact",
"schema",
"receipt_version",
"status",
"snapshot_exported",
"service_unchanged",
"source_service_healthy",
"source_not_mutated",
"telegram_not_sent",
"run_id",
"capture_authorization_ref",
"source_identity",
"source_database",
"snapshot_identity",
"dump_sha256",
"dump_bytes",
"source_manifest_sha256",
"manifest_sql_sha256",
"source_context_sha256",
"table_count",
"total_rows",
"binding_algorithm",
"binding_payload",
"binding_sha256",
},
),
"source_dump_bound": capture_binding.get("dump_sha256") == (source.get("dump") or {}).get("sha256"),
"source_execution_contract_bound": restore_contract.get("source") == source.get("source"),
"source_manifest_bound": capture_binding.get("manifest_sha256") == (source.get("manifest") or {}).get("sha256"),
"restore_manifest_matches_parity_source": capture_binding.get("manifest_sha256")
== parity.get("source_manifest_sha256"),
"restore_target_manifest_matches_parity": restore_target.get("manifest_sha256")
== parity.get("target_manifest_sha256"),
"restore_private_tls": restore_connectivity.get("private_connectivity") is True
and restore_connectivity.get("ssl") is True
and restore_connectivity.get("sslmode") == "verify-full"
and restore_connectivity.get("server_identity_verified") is True
and restore_connectivity.get("ssl_server_name") == restore_contract.get("ssl_server_name")
and restore_connectivity.get("ssl_root_cert_sha256") == restore_contract.get("ssl_root_cert_sha256")
and is_rfc1918(restore_connectivity.get("server_address")),
"restore_public_ip_disabled": restore_cloudsql.get("public_ip_disabled") is True,
"restore_cloudsql_checks": required_true_checks(
restore_cloudsql.get("checks"),
{
"instance",
"state",
"postgres_16",
"public_ip_disabled",
"private_network",
"expected_private_host",
"no_non_private_address",
},
),
"restore_compute_checks": required_true_checks(
restore_compute.get("checks"),
{
"project",
"project_number",
"expected_network_project",
"instance",
"instance_id",
"zone",
"network",
"private_ip",
"service_account",
},
),
"restore_compute_contract": restore_compute.get("project") == restore_contract.get("project")
and restore_compute.get("instance") == restore_contract.get("compute_instance")
and restore_compute.get("zone") == restore_contract.get("compute_zone")
and restore_compute.get("expected_private_network") == restore_contract.get("private_network")
and bool(restore_compute.get("network_resource"))
and is_rfc1918(restore_compute.get("private_ip"))
and restore_contract.get("restore_service_account") == DEFAULT_RESTORE_SERVICE_ACCOUNT
and restore_compute.get("service_account") == DEFAULT_RESTORE_SERVICE_ACCOUNT,
"restore_tls_identity_contract": bool(restore_contract.get("ssl_server_name"))
and bool(SHA256_RE.fullmatch(str(restore_contract.get("ssl_root_cert_sha256") or ""))),
"restore_connectivity_compute_bound": restore_connectivity.get("source_compute")
== restore_compute.get("instance"),
"restore_inline_parity": restore_parity.get("status") == "pass" and restore_parity.get("problems") == [],
"restore_inline_parity_evidence": all(restore_inline_parity_checks.values()),
"restore_service_healthy_unchanged": restore_service.get("unchanged") is True
and service_healthy(restore_service.get("before"))
and restore_service.get("before") == restore_service.get("after"),
"parity_pass": parity.get("artifact") == "canonical_postgres_parity_verification"
and parity.get("status") == "pass"
and parity.get("scope") == "gcp_staging"
and parity.get("problems") == [],
"parity_target_bound": parity_details.get("target_database") == target_db,
"parity_exact_evidence": all(parity_evidence_checks.values()),
"parity_connectivity_hash_bound": restore_connectivity_proof.get("sha256")
== parity.get("connectivity_proof_sha256"),
"parity_private_proof": parity_connectivity.get("required") is True
and parity_connectivity_proof.get("artifact") == "gcp_private_postgres_connectivity"
and parity_connectivity_proof.get("status") == "pass"
and parity_connectivity_proof.get("schema") == "livingip.gcpPrivatePostgresConnectivity.v2"
and parity_connectivity_proof.get("restore_run_id") == run_id
and parity_connectivity_proof.get("private_connectivity") is True
and parity_connectivity_proof.get("public_ip_disabled") is True
and parity_connectivity_proof.get("target_database") == target_db
and parity_connectivity_proof.get("project") == restore_cloudsql.get("project")
and parity_connectivity_proof.get("cloudsql_instance") == restore_cloudsql.get("instance")
and parity_connectivity_proof.get("private_network") == restore_cloudsql.get("private_network")
and parity_connectivity_proof.get("source_compute") == reasoning.get("source_compute")
and parity_connectivity_proof.get("source_compute_instance_id") == restore_compute.get("instance_id")
and parity_connectivity_proof.get("source_compute_zone") == restore_compute.get("zone")
and is_rfc1918(parity_connectivity_proof.get("source_compute_private_ip"))
and parity_connectivity_proof.get("server_address") == restore_connectivity.get("server_address")
and parity_connectivity_proof.get("sslmode") == "verify-full"
and parity_connectivity_proof.get("server_identity_verified") is True
and parity_connectivity_proof.get("ssl_server_name") == restore_contract.get("ssl_server_name")
and parity_connectivity_proof.get("ssl_root_cert_sha256") == restore_contract.get("ssl_root_cert_sha256")
and required_true_checks(
parity_connectivity_proof.get("cloudsql_control_plane_checks"),
{
"instance",
"state",
"postgres_16",
"public_ip_disabled",
"private_network",
"expected_private_host",
"no_non_private_address",
},
)
and required_true_checks(
parity_connectivity_proof.get("compute_identity_checks"),
{
"project",
"project_number",
"expected_network_project",
"instance",
"instance_id",
"zone",
"network",
"private_ip",
"service_account",
},
),
"reasoning_schema": reasoning.get("schema") == BLIND_REASONING_SCHEMA,
"reasoning_pass": reasoning.get("status") == "pass" and not reasoning.get("errors"),
"reasoning_target_bound": reasoning.get("target_database") == target_db,
"reasoning_compute_bound": reasoning.get("source_compute") == restore_compute.get("instance"),
"reasoning_parity_hash_bound": reasoning_parity.get("sha256") == sha256_file(parity_path),
"reasoning_required_checks": all(reasoning_checks.get(name) is True for name in required_reasoning_checks),
"reasoning_producer_evidence": all(producer_reasoning_checks.values()),
"reasoning_compute_attestation": reasoning_compute_attestation.get("artifact")
== "gcp_reasoning_compute_attestation"
and reasoning_compute_attestation.get("schema") == REASONING_COMPUTE_SCHEMA
and reasoning_compute_attestation.get("status") == "pass"
and reasoning_compute_attestation.get("method") == "gce_metadata_server_v1"
and nonempty_all_true(reasoning_compute_checks)
and reasoning_compute_attestation.get("restore_run_id") == run_id
and reasoning_compute_attestation.get("target_database") == target_db
and all(value is False for value in reasoning_compute_mutation.values())
and {
"cloudsql_changed",
"compute_changed",
"database_changed",
"telegram_message_sent",
}
<= set(reasoning_compute_mutation),
"reasoning_compute_receipt_bound": (reasoning_compute_attestation.get("reasoning_receipt") or {}).get("sha256")
== sha256_file(reasoning_path),
"reasoning_compute_identity_bound": reasoning_compute.get("project") == restore_compute.get("project")
and reasoning_compute.get("project_number") == restore_compute.get("project_number")
and reasoning_compute.get("instance") == restore_compute.get("instance")
and reasoning_compute.get("instance_id") == restore_compute.get("instance_id")
and reasoning_compute.get("zone") == restore_compute.get("zone")
and reasoning_compute.get("expected_private_network") == restore_compute.get("expected_private_network")
and reasoning_compute.get("network_resource") == restore_compute.get("network_resource")
and reasoning_compute.get("private_ip") == restore_compute.get("private_ip")
and reasoning_compute.get("service_account") == restore_compute.get("service_account")
and required_true_checks(
reasoning_compute.get("checks"),
{
"project",
"project_number",
"expected_network_project",
"instance",
"instance_id",
"zone",
"network",
"private_ip",
"service_account",
},
),
"reasoning_no_send_no_write": reasoning.get("posted_to_telegram") is False
and reasoning.get("database_write_attempted") is False,
"reasoning_fingerprint_unchanged": bool(before_fingerprint.get("sha256"))
and before_fingerprint.get("sha256") == after_fingerprint.get("sha256"),
"cleanup_pass": cleanup.get("artifact") == "gcp_generated_postgres_snapshot_cleanup"
and cleanup.get("status") == "pass",
"cleanup_run_bound": cleanup.get("run_id") == run_id and cleanup.get("target_database") == target_db,
"cleanup_restore_receipt_bound": (cleanup.get("restore_receipt") or {}).get("sha256")
== sha256_file(restore_path),
"cleanup_execution_contract_bound": bool(restore_contract) and cleanup_contract == restore_contract,
"cleanup_cloudsql_bound": cleanup_cloudsql.get("project") == restore_cloudsql.get("project")
and cleanup_cloudsql.get("instance") == restore_cloudsql.get("instance")
and cleanup_cloudsql.get("expected_private_host") == restore_cloudsql.get("expected_private_host")
and cleanup_cloudsql.get("expected_private_network") == restore_cloudsql.get("expected_private_network")
and cleanup_cloudsql.get("public_ip_disabled") is True
and required_true_checks(
cleanup_cloudsql.get("checks"),
{
"instance",
"state",
"postgres_16",
"public_ip_disabled",
"private_network",
"expected_private_host",
"no_non_private_address",
},
),
"cleanup_compute_bound": cleanup_compute.get("instance_id") == restore_compute.get("instance_id")
and cleanup_compute.get("project") == restore_compute.get("project")
and cleanup_compute.get("project_number") == restore_compute.get("project_number")
and cleanup_compute.get("instance") == restore_compute.get("instance")
and cleanup_compute.get("zone") == restore_compute.get("zone")
and cleanup_compute.get("expected_private_network") == restore_compute.get("expected_private_network")
and cleanup_compute.get("network_resource") == restore_compute.get("network_resource")
and cleanup_compute.get("private_ip") == restore_compute.get("private_ip")
and cleanup_compute.get("service_account") == restore_compute.get("service_account")
and required_true_checks(
cleanup_compute.get("checks"),
{
"project",
"project_number",
"expected_network_project",
"instance",
"instance_id",
"zone",
"network",
"private_ip",
"service_account",
},
),
"clone_absent": cleanup_database.get("existed_before") is True
and cleanup_database.get("clone_database_remaining") == 0,
"cleanup_service_unchanged": cleanup_service.get("unchanged") is True
and service_healthy(cleanup_service.get("before"))
and cleanup_service.get("before") == cleanup_service.get("after"),
}
failed = sorted(name for name, passed in checks.items() if not passed)
structurally_valid = not failed
return {
"artifact": "gcp_canonical_snapshot_lifecycle_verification",
"generated_at_utc": verification_time.isoformat(),
"status": "prepared_external_attestation_required" if structurally_valid else "fail",
"current_tier": "T2_structural_receipt_bundle",
"required_tier": "T3_live_private_gcp_staging",
"t3_receipt_ready": False,
"accepted_by_this_api": False,
"target_database": target_db,
"run_id": run_id,
"checks": checks,
"reasoning_producer_checks": producer_reasoning_checks,
"restore_inline_parity_checks": restore_inline_parity_checks,
"parity_evidence_checks": parity_evidence_checks,
"post_snapshot_source_delta": delta_details,
"timeline": timeline_values,
"postflight_age_seconds": postflight_age_seconds,
"max_postflight_age_seconds": max_postflight_age_seconds,
"lifecycle_age_seconds": lifecycle_age_seconds,
"lifecycle_span_seconds": lifecycle_span_seconds,
"max_lifecycle_age_seconds": max_lifecycle_age_seconds,
"failed_checks": failed,
"receipt_sha256": {
"source": sha256_file(source_path),
"current_source": sha256_file(current_source_path),
"source_delta": sha256_file(source_delta_path),
"restore": sha256_file(restore_path),
"parity": sha256_file(parity_path),
"reasoning": sha256_file(reasoning_path),
"reasoning_compute": sha256_file(reasoning_compute_path),
"cleanup": sha256_file(cleanup_path),
},
"strongest_claim_allowed": (
"caller-supplied lifecycle receipts are internally consistent; an independently authenticated platform receipt is still required"
if structurally_valid
else "lifecycle preparation is incomplete; failed checks must be repaired"
),
"not_proven": ["production cutover", "ongoing replication", "Telegram delivery"],
}
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--source-receipt", required=True, type=Path)
parser.add_argument("--current-source-receipt", required=True, type=Path)
parser.add_argument("--source-delta-receipt", required=True, type=Path)
parser.add_argument("--restore-receipt", required=True, type=Path)
parser.add_argument("--parity-receipt", required=True, type=Path)
parser.add_argument("--reasoning-receipt", required=True, type=Path)
parser.add_argument("--reasoning-compute-receipt", required=True, type=Path)
parser.add_argument("--cleanup-receipt", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
parser.add_argument("--max-postflight-age-seconds", default=900.0, type=float)
parser.add_argument("--max-lifecycle-age-seconds", default=3600.0, type=float)
args = parser.parse_args()
try:
payload = verify_lifecycle(
source_path=args.source_receipt,
current_source_path=args.current_source_receipt,
source_delta_path=args.source_delta_receipt,
restore_path=args.restore_receipt,
parity_path=args.parity_receipt,
reasoning_path=args.reasoning_receipt,
reasoning_compute_path=args.reasoning_compute_receipt,
cleanup_path=args.cleanup_receipt,
max_postflight_age_seconds=args.max_postflight_age_seconds,
max_lifecycle_age_seconds=args.max_lifecycle_age_seconds,
)
except (OSError, ValueError, KeyError, TypeError) as exc:
payload = {
"artifact": "gcp_canonical_snapshot_lifecycle_verification",
"generated_at_utc": datetime.now(UTC).isoformat(),
"status": "fail",
"required_tier": "T3_live_private_gcp_staging",
"failed_checks": ["receipt_load_or_validation_error"],
"error": str(exc),
"strongest_claim_allowed": "lifecycle incomplete; receipts could not be validated",
}
write_private_json(args.output, payload)
print_private_receipt_summary(args.output, payload)
return 0 if payload.get("status") == "prepared_external_attestation_required" else 1
if __name__ == "__main__":
raise SystemExit(main())