820 lines
35 KiB
Python
820 lines
35 KiB
Python
import hashlib
|
|
import json
|
|
from datetime import UTC, datetime
|
|
from pathlib import Path
|
|
|
|
from ops.restore_gcp_generated_postgres_snapshot import DEFAULT_RESTORE_SERVICE_ACCOUNT
|
|
from ops.verify_gcp_canonical_lifecycle import EXPECTED_BLIND_ROW_IDS
|
|
from ops.verify_gcp_canonical_lifecycle import verify_lifecycle as _verify_lifecycle
|
|
from ops.verify_postgres_parity_manifest import REVIEWED_MANIFEST_SQL_SHA256
|
|
|
|
VERIFY_NOW = datetime(2026, 7, 15, 1, 3, tzinfo=UTC)
|
|
|
|
|
|
def verify_lifecycle(**kwargs):
|
|
return _verify_lifecycle(**kwargs, now=VERIFY_NOW)
|
|
|
|
|
|
def write_json(path: Path, payload: dict) -> Path:
|
|
path.write_text(json.dumps(payload, sort_keys=True) + "\n", encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def sha256(path: Path) -> str:
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def lifecycle_receipts(tmp_path: Path) -> dict[str, Path]:
|
|
target_db = "teleo_clone_current_test"
|
|
run_id = "gcp-restore-current-test123"
|
|
healthy_service = {
|
|
"ActiveState": "active",
|
|
"SubState": "running",
|
|
"MainPID": "148735",
|
|
"NRestarts": "0",
|
|
}
|
|
structural_hashes = {
|
|
kind: {"source": format(index, "x") * 64, "target": format(index, "x") * 64}
|
|
for index, kind in enumerate(
|
|
(
|
|
"schemas",
|
|
"columns",
|
|
"constraints",
|
|
"indexes",
|
|
"sequences",
|
|
"views",
|
|
"functions",
|
|
"triggers",
|
|
"types",
|
|
"policies",
|
|
"role_memberships",
|
|
"object_ownership",
|
|
"object_acl",
|
|
),
|
|
1,
|
|
)
|
|
}
|
|
exact_parity_details = {
|
|
"source_database": "teleo",
|
|
"target_database": target_db,
|
|
"source_table_count": 39,
|
|
"target_table_count": 39,
|
|
"source_total_rows": 52167,
|
|
"target_total_rows": 52167,
|
|
"table_mismatches": [],
|
|
"table_hash_problems": [],
|
|
"structural_hashes": structural_hashes,
|
|
"required_extension_mismatches": {},
|
|
"target_extra_extensions": [],
|
|
"application_role_mismatches": {},
|
|
"target_extra_application_roles": [],
|
|
"performance": [{"query": "count_claims", "source_ms": 1.0, "target_ms": 2.0, "source_ratio": 0.4}],
|
|
"performance_problems": [],
|
|
}
|
|
source = {
|
|
"artifact": "vps_canonical_postgres_exported_snapshot",
|
|
"schema": "livingip.sourceSnapshotReceipt.v2",
|
|
"receipt_version": 2,
|
|
"status": "pass",
|
|
"run_id": "canonical-current-test",
|
|
"capture_authorization_ref": "codex-delegation:test1234",
|
|
"source": {
|
|
"ssh_target": "root@77.42.65.182",
|
|
"container": "teleo-pg",
|
|
"database": "teleo",
|
|
"service": "leoclean-gateway.service",
|
|
},
|
|
"snapshot_exported": True,
|
|
"snapshot": {
|
|
"captured_at_utc": "2026-07-15T00:59:00+00:00",
|
|
"exported_snapshot_id": "00000003-000001A2-1",
|
|
"txid_snapshot": "100:120:",
|
|
"wal_lsn": "0/16B6C50",
|
|
"system_identifier": "7649789040005668902",
|
|
},
|
|
"service_unchanged": True,
|
|
"source_service": {"before": healthy_service, "after": healthy_service, "unchanged": True},
|
|
"production_db_mutated": False,
|
|
"telegram_send_attempted": False,
|
|
"dump": {"sha256": "a" * 64},
|
|
"manifest": {
|
|
"sha256": "b" * 64,
|
|
"manifest_sql_sha256": REVIEWED_MANIFEST_SQL_SHA256,
|
|
"table_count": 39,
|
|
"total_rows": 52167,
|
|
},
|
|
"provenance_binding": {"algorithm": "sha256", "payload": {"bound": True}, "sha256": "c" * 64},
|
|
}
|
|
source_path = write_json(tmp_path / "source.json", source)
|
|
restore = {
|
|
"artifact": "gcp_generated_postgres_snapshot_restore",
|
|
"status": "pass",
|
|
"generated_at_utc": "2026-07-15T00:59:10+00:00",
|
|
"completed_at_utc": "2026-07-15T00:59:30+00:00",
|
|
"run_id": run_id,
|
|
"target_database": target_db,
|
|
"source": {
|
|
"capture_receipt": {
|
|
"sha256": sha256(source_path),
|
|
"capture_authorization_ref": "codex-delegation:test1234",
|
|
"provenance_binding_sha256": "c" * 64,
|
|
"dump_sha256": "a" * 64,
|
|
"manifest_sha256": "b" * 64,
|
|
"manifest_sql_sha256": REVIEWED_MANIFEST_SQL_SHA256,
|
|
"checks": {
|
|
name: True
|
|
for name in (
|
|
"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",
|
|
)
|
|
},
|
|
}
|
|
},
|
|
"execution_contract": {
|
|
"project": "teleo-501523",
|
|
"cloudsql_instance": "teleo-pgvector-standby",
|
|
"host": "10.61.0.3",
|
|
"private_network": "projects/teleo-501523/global/networks/teleo-staging-net",
|
|
"compute_instance": "teleo-prod-1",
|
|
"compute_zone": "europe-west6-a",
|
|
"restore_service_account": DEFAULT_RESTORE_SERVICE_ACCOUNT,
|
|
"ssl_server_name": "teleo-pgvector-standby.private.teleo.internal",
|
|
"ssl_root_cert_sha256": "9" * 64,
|
|
"source": source["source"],
|
|
"password_secret": "gcp-teleo-pgvector-standby-postgres-password",
|
|
"service": "leoclean-gcp-prod-parallel.service",
|
|
},
|
|
"target": {
|
|
"manifest_sha256": "d" * 64,
|
|
"connectivity": {
|
|
"private_connectivity": True,
|
|
"ssl": True,
|
|
"sslmode": "verify-full",
|
|
"ssl_server_name": "teleo-pgvector-standby.private.teleo.internal",
|
|
"ssl_root_cert_sha256": "9" * 64,
|
|
"server_identity_verified": True,
|
|
"server_address": "10.61.0.3",
|
|
"source_compute": "teleo-prod-1",
|
|
},
|
|
"cloudsql": {
|
|
"project": "teleo-501523",
|
|
"instance": "teleo-pgvector-standby",
|
|
"expected_private_host": "10.61.0.3",
|
|
"private_network": "projects/teleo-501523/global/networks/teleo-staging-net",
|
|
"expected_private_network": "projects/teleo-501523/global/networks/teleo-staging-net",
|
|
"public_ip_disabled": True,
|
|
"checks": {
|
|
"instance": True,
|
|
"state": True,
|
|
"postgres_16": True,
|
|
"public_ip_disabled": True,
|
|
"private_network": True,
|
|
"expected_private_host": True,
|
|
"no_non_private_address": True,
|
|
},
|
|
},
|
|
"compute": {
|
|
"project": "teleo-501523",
|
|
"project_number": "785938879453",
|
|
"instance": "teleo-prod-1",
|
|
"instance_id": "123456789",
|
|
"zone": "europe-west6-a",
|
|
"expected_private_network": "projects/teleo-501523/global/networks/teleo-staging-net",
|
|
"network_resource": "projects/123456789/networks/teleo-staging-net",
|
|
"private_ip": "10.61.0.2",
|
|
"service_account": DEFAULT_RESTORE_SERVICE_ACCOUNT,
|
|
"checks": {
|
|
"project": True,
|
|
"project_number": True,
|
|
"expected_network_project": True,
|
|
"instance": True,
|
|
"instance_id": True,
|
|
"zone": True,
|
|
"network": True,
|
|
"private_ip": True,
|
|
"service_account": True,
|
|
},
|
|
},
|
|
"connectivity_proof": {
|
|
"sha256": "f" * 64,
|
|
"schema": "livingip.gcpPrivatePostgresConnectivity.v2",
|
|
},
|
|
},
|
|
"parity": {"status": "pass", "problems": [], "details": exact_parity_details},
|
|
"live_service": {"before": healthy_service, "after": healthy_service, "unchanged": True},
|
|
}
|
|
restore_path = write_json(tmp_path / "restore.json", restore)
|
|
parity = {
|
|
"artifact": "canonical_postgres_parity_verification",
|
|
"status": "pass",
|
|
"completed_at_utc": "2026-07-15T00:59:45+00:00",
|
|
"scope": "gcp_staging",
|
|
"problems": [],
|
|
"source_manifest_sha256": "b" * 64,
|
|
"target_manifest_sha256": "d" * 64,
|
|
"connectivity_proof_sha256": "f" * 64,
|
|
"details": exact_parity_details,
|
|
"private_connectivity": {
|
|
"required": True,
|
|
"proof": {
|
|
"artifact": "gcp_private_postgres_connectivity",
|
|
"schema": "livingip.gcpPrivatePostgresConnectivity.v2",
|
|
"status": "pass",
|
|
"restore_run_id": run_id,
|
|
"private_connectivity": True,
|
|
"public_ip_disabled": True,
|
|
"target_database": target_db,
|
|
"source_compute": "teleo-prod-1",
|
|
"source_compute_instance_id": "123456789",
|
|
"source_compute_zone": "europe-west6-a",
|
|
"source_compute_private_ip": "10.61.0.2",
|
|
"server_address": "10.61.0.3",
|
|
"sslmode": "verify-full",
|
|
"ssl_server_name": "teleo-pgvector-standby.private.teleo.internal",
|
|
"ssl_root_cert_sha256": "9" * 64,
|
|
"server_identity_verified": True,
|
|
"project": "teleo-501523",
|
|
"cloudsql_instance": "teleo-pgvector-standby",
|
|
"private_network": "projects/teleo-501523/global/networks/teleo-staging-net",
|
|
"cloudsql_control_plane_checks": restore["target"]["cloudsql"]["checks"],
|
|
"compute_identity_checks": restore["target"]["compute"]["checks"],
|
|
},
|
|
},
|
|
}
|
|
parity_path = write_json(tmp_path / "parity.json", parity)
|
|
required_checks = {
|
|
name: True
|
|
for name in (
|
|
"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",
|
|
)
|
|
}
|
|
reasoning = {
|
|
"schema": "livingip.gcpGeneratedDbBlindClaimCanary.v1",
|
|
"status": "pass",
|
|
"generated_at_utc": "2026-07-15T01:00:00+00:00",
|
|
"completed_at_utc": "2026-07-15T01:01:00+00:00",
|
|
"mode": "gcp_generated_db_gatewayrunner_blind_claim_no_send",
|
|
"source_compute": "teleo-prod-1",
|
|
"prompt": "Inspect the live claim without me giving you an ID. Do not change the database.",
|
|
"errors": [],
|
|
"target_database": target_db,
|
|
"posted_to_telegram": False,
|
|
"database_write_attempted": False,
|
|
"parity_receipt": {"sha256": sha256(parity_path)},
|
|
"checks": required_checks,
|
|
"database_fingerprint_before": {"sha256": "e" * 64},
|
|
"database_fingerprint_after": {"sha256": "e" * 64},
|
|
"canonical_status_before": {"claims": 1},
|
|
"canonical_status_after": {"claims": 1},
|
|
"database_identity_before": {"database": target_db},
|
|
"database_identity_after": {"database": target_db},
|
|
"service_before": healthy_service,
|
|
"service_after": healthy_service,
|
|
"temp_profile_absent": True,
|
|
"temp_profile_removed": True,
|
|
"outcomes": {
|
|
"asks_for_user_iteration_before_live": True,
|
|
"challenges_weak_support": True,
|
|
"decomposes_the_bundled_legal_claim": True,
|
|
"does_not_claim_a_database_change": True,
|
|
"proposes_candidate_claims": True,
|
|
"uses_only_m3taversal_handle": True,
|
|
},
|
|
"result": {
|
|
"reply": "The claim is weak; here are grounded, review-first alternatives.",
|
|
"database_tool_trace": {
|
|
"schema": "livingip.leoKbToolTrace.v1",
|
|
"database_tool_call_proven": True,
|
|
"database_retrieval_receipt_proven": True,
|
|
"database_tool_calls_read_only": True,
|
|
"database_tool_call_count": 3,
|
|
"database_tool_completed_count": 3,
|
|
"calls": [
|
|
{
|
|
"database_invocations": [{"access_mode": "read_only", "subcommand": subcommand}],
|
|
"result": {
|
|
"nonempty": True,
|
|
"error_detected": False,
|
|
"row_ids": sorted(EXPECTED_BLIND_ROW_IDS),
|
|
"row_id_count": len(EXPECTED_BLIND_ROW_IDS),
|
|
"retrieval_receipt": {
|
|
"schema": "livingip.teleoKbRetrievalReceipt.v1",
|
|
"semantic_context_sha256": "1" * 64,
|
|
"artifact_state_sha256": "2" * 64,
|
|
"read_consistency_status": "stable_wal_marker",
|
|
},
|
|
},
|
|
}
|
|
for subcommand in ("search", "show", "evidence")
|
|
],
|
|
},
|
|
"gateway": {
|
|
"authorized": True,
|
|
"handler_invoked": True,
|
|
"model_free_fallback_used": False,
|
|
"posted_to_telegram": False,
|
|
"child_process": {
|
|
"exitcode": 0,
|
|
"alive_after_readback": False,
|
|
"process_group_alive_after_readback": False,
|
|
"timed_out": False,
|
|
},
|
|
"tool_surface": {"send_message_tool_enabled": False},
|
|
},
|
|
},
|
|
"wrapper_tool_proof": {
|
|
"all_bound_to_supplied_target": True,
|
|
"all_completed_successfully": True,
|
|
"complete_start_end_pairing": True,
|
|
"database_read_only_required": True,
|
|
"default_read_only_required": True,
|
|
"invocations": [
|
|
{
|
|
"database": target_db,
|
|
"returncode": 0,
|
|
"subcommand": subcommand,
|
|
"database_identity": {
|
|
"transaction_read_only": "on",
|
|
"default_transaction_read_only": "on",
|
|
"ssl": True,
|
|
"sslmode": "verify-full",
|
|
"ssl_server_name": "teleo-pgvector-standby.private.teleo.internal",
|
|
"ssl_root_cert_sha256": "9" * 64,
|
|
"server_identity_verified": True,
|
|
"server_address": "10.61.0.3",
|
|
},
|
|
}
|
|
for subcommand in ("search", "show", "evidence")
|
|
],
|
|
},
|
|
}
|
|
reasoning_path = write_json(tmp_path / "reasoning.json", reasoning)
|
|
reasoning_compute = {
|
|
"artifact": "gcp_reasoning_compute_attestation",
|
|
"schema": "livingip.gcpReasoningComputeAttestation.v1",
|
|
"status": "pass",
|
|
"generated_at_utc": "2026-07-15T01:01:05+00:00",
|
|
"restore_run_id": run_id,
|
|
"target_database": target_db,
|
|
"reasoning_receipt": {
|
|
"sha256": sha256(reasoning_path),
|
|
"schema": reasoning["schema"],
|
|
"generated_at_utc": reasoning["generated_at_utc"],
|
|
"completed_at_utc": reasoning["completed_at_utc"],
|
|
"claimed_source_compute": reasoning["source_compute"],
|
|
},
|
|
"compute": restore["target"]["compute"],
|
|
"checks": {
|
|
"schema": True,
|
|
"status": True,
|
|
"target_database": True,
|
|
"source_compute": True,
|
|
"chronology": True,
|
|
"no_telegram_send": True,
|
|
"no_database_write": True,
|
|
"gce_metadata_identity": True,
|
|
},
|
|
"method": "gce_metadata_server_v1",
|
|
"mutation": {
|
|
"cloudsql_changed": False,
|
|
"compute_changed": False,
|
|
"database_changed": False,
|
|
"telegram_message_sent": False,
|
|
},
|
|
}
|
|
reasoning_compute_path = write_json(tmp_path / "reasoning-compute.json", reasoning_compute)
|
|
current_source = json.loads(json.dumps(source))
|
|
current_source["run_id"] = "canonical-current-postflight"
|
|
current_source["capture_authorization_ref"] = "codex-delegation:postflight1234"
|
|
current_source["snapshot"]["captured_at_utc"] = "2026-07-15T01:02:00+00:00"
|
|
current_source["snapshot"]["exported_snapshot_id"] = "00000003-000001B2-1"
|
|
current_source_path = write_json(tmp_path / "current-source.json", current_source)
|
|
source_delta = {
|
|
"artifact": "vps_canonical_snapshot_postflight_delta",
|
|
"schema": "livingip.vpsCanonicalSnapshotDelta.v1",
|
|
"status": "pass",
|
|
"baseline": {
|
|
"run_id": "canonical-current-test",
|
|
"capture_receipt_sha256": sha256(source_path),
|
|
"manifest_sha256": "b" * 64,
|
|
"manifest_sql_sha256": REVIEWED_MANIFEST_SQL_SHA256,
|
|
"capture_authorization_ref": "codex-delegation:test1234",
|
|
"captured_at_utc": "2026-07-15T00:59:00+00:00",
|
|
"table_count": 39,
|
|
"total_rows": 52167,
|
|
"table_fingerprint_sha256": "d" * 64,
|
|
"structure_fingerprint_sha256": "e" * 64,
|
|
},
|
|
"current": {
|
|
"run_id": "canonical-current-postflight",
|
|
"capture_receipt_sha256": sha256(current_source_path),
|
|
"manifest_sha256": "b" * 64,
|
|
"manifest_sql_sha256": REVIEWED_MANIFEST_SQL_SHA256,
|
|
"capture_authorization_ref": "codex-delegation:postflight1234",
|
|
"captured_at_utc": "2026-07-15T01:02:00+00:00",
|
|
"table_count": 39,
|
|
"total_rows": 52167,
|
|
"table_fingerprint_sha256": "d" * 64,
|
|
"structure_fingerprint_sha256": "e" * 64,
|
|
},
|
|
"delta": {
|
|
"delta_detected": False,
|
|
"added_tables": [],
|
|
"removed_tables": [],
|
|
"changed_tables": [],
|
|
"changed_structures": [],
|
|
"total_row_delta": 0,
|
|
},
|
|
}
|
|
source_delta_path = write_json(tmp_path / "source-delta.json", source_delta)
|
|
cleanup = {
|
|
"artifact": "gcp_generated_postgres_snapshot_cleanup",
|
|
"status": "pass",
|
|
"generated_at_utc": "2026-07-15T01:01:10+00:00",
|
|
"completed_at_utc": "2026-07-15T01:01:30+00:00",
|
|
"run_id": run_id,
|
|
"target_database": target_db,
|
|
"database": {"existed_before": True, "clone_database_remaining": 0},
|
|
"live_service": {"before": healthy_service, "after": healthy_service, "unchanged": True},
|
|
"restore_receipt": {"sha256": sha256(restore_path)},
|
|
"execution_contract": restore["execution_contract"],
|
|
"target": {
|
|
"cloudsql": restore["target"]["cloudsql"],
|
|
"compute": restore["target"]["compute"],
|
|
},
|
|
}
|
|
cleanup_path = write_json(tmp_path / "cleanup.json", cleanup)
|
|
return {
|
|
"source_path": source_path,
|
|
"current_source_path": current_source_path,
|
|
"source_delta_path": source_delta_path,
|
|
"restore_path": restore_path,
|
|
"parity_path": parity_path,
|
|
"reasoning_path": reasoning_path,
|
|
"reasoning_compute_path": reasoning_compute_path,
|
|
"cleanup_path": cleanup_path,
|
|
}
|
|
|
|
|
|
def test_caller_authored_bundle_is_preparation_only_even_when_all_checks_pass(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "prepared_external_attestation_required"
|
|
assert result["failed_checks"] == []
|
|
assert result["checks"]["clone_absent"] is True
|
|
assert result["current_tier"] == "T2_structural_receipt_bundle"
|
|
assert result["required_tier"] == "T3_live_private_gcp_staging"
|
|
assert result["t3_receipt_ready"] is False
|
|
assert result["accepted_by_this_api"] is False
|
|
assert "current private GCP staging" not in result["strongest_claim_allowed"]
|
|
|
|
|
|
def test_rebound_unreviewed_manifest_sql_digest_fails_closed(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
unreviewed_digest = "f" * 64
|
|
|
|
source = json.loads(paths["source_path"].read_text())
|
|
source["manifest"]["manifest_sql_sha256"] = unreviewed_digest
|
|
write_json(paths["source_path"], source)
|
|
current_source = json.loads(paths["current_source_path"].read_text())
|
|
current_source["manifest"]["manifest_sql_sha256"] = unreviewed_digest
|
|
write_json(paths["current_source_path"], current_source)
|
|
|
|
restore = json.loads(paths["restore_path"].read_text())
|
|
restore["source"]["capture_receipt"]["sha256"] = sha256(paths["source_path"])
|
|
restore["source"]["capture_receipt"]["manifest_sql_sha256"] = unreviewed_digest
|
|
write_json(paths["restore_path"], restore)
|
|
|
|
delta = json.loads(paths["source_delta_path"].read_text())
|
|
delta["baseline"]["capture_receipt_sha256"] = sha256(paths["source_path"])
|
|
delta["baseline"]["manifest_sql_sha256"] = unreviewed_digest
|
|
delta["current"]["capture_receipt_sha256"] = sha256(paths["current_source_path"])
|
|
delta["current"]["manifest_sql_sha256"] = unreviewed_digest
|
|
write_json(paths["source_delta_path"], delta)
|
|
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["restore_receipt"]["sha256"] = sha256(paths["restore_path"])
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "source_delta_manifest_sql_reviewed" in result["failed_checks"]
|
|
|
|
|
|
def test_local_parity_or_missing_cleanup_fails_closed(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
parity = json.loads(paths["parity_path"].read_text())
|
|
parity["scope"] = "local_restore"
|
|
write_json(paths["parity_path"], parity)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
reasoning["parity_receipt"]["sha256"] = sha256(paths["parity_path"])
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["database"]["clone_database_remaining"] = 1
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert {"parity_pass", "clone_absent"} <= set(result["failed_checks"])
|
|
|
|
|
|
def test_cleanup_cannot_pass_when_the_named_clone_never_existed(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["database"]["existed_before"] = False
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "clone_absent" in result["failed_checks"]
|
|
|
|
|
|
def test_mismatched_source_or_reasoning_receipt_fails_closed(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
restore = json.loads(paths["restore_path"].read_text())
|
|
restore["source"]["capture_receipt"]["sha256"] = "0" * 64
|
|
write_json(paths["restore_path"], restore)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
reasoning["checks"]["claim_and_sources_retrieved"] = False
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert {"source_receipt_hash_bound", "reasoning_required_checks"} <= set(result["failed_checks"])
|
|
|
|
|
|
def test_hand_authored_reasoning_boole_without_producer_evidence_fail(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
reasoning.pop("result")
|
|
reasoning.pop("wrapper_tool_proof")
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "reasoning_producer_evidence" in result["failed_checks"]
|
|
assert result["reasoning_producer_checks"]["tool_trace"] is False
|
|
|
|
|
|
def test_reasoning_compute_attestation_must_bind_live_metadata(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
attestation = json.loads(paths["reasoning_compute_path"].read_text())
|
|
attestation["compute"]["instance_id"] = "999999999"
|
|
write_json(paths["reasoning_compute_path"], attestation)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "reasoning_compute_identity_bound" in result["failed_checks"]
|
|
|
|
|
|
def test_project_owner_shaped_service_account_cannot_pass_preparation(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
project_owner = "project-owner@teleo-501523.iam.gserviceaccount.com"
|
|
restore = json.loads(paths["restore_path"].read_text())
|
|
restore["target"]["compute"]["service_account"] = project_owner
|
|
restore["execution_contract"]["restore_service_account"] = project_owner
|
|
write_json(paths["restore_path"], restore)
|
|
attestation = json.loads(paths["reasoning_compute_path"].read_text())
|
|
attestation["compute"]["service_account"] = project_owner
|
|
write_json(paths["reasoning_compute_path"], attestation)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["target"]["compute"]["service_account"] = project_owner
|
|
cleanup["execution_contract"]["restore_service_account"] = project_owner
|
|
cleanup["restore_receipt"]["sha256"] = sha256(paths["restore_path"])
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "restore_compute_contract" in result["failed_checks"]
|
|
|
|
|
|
def test_source_postflight_must_be_newer_than_cleanup_completion(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["completed_at_utc"] = "2026-07-15T02:00:00+00:00"
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "source_postflight_after_lifecycle" in result["failed_checks"]
|
|
|
|
|
|
def test_parity_must_retain_exact_structure_roles_rows_and_performance(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
parity = json.loads(paths["parity_path"].read_text())
|
|
parity["details"]["structural_hashes"].pop("constraints")
|
|
parity["details"]["application_role_mismatches"] = {"kb_apply": {"missing": True}}
|
|
parity["details"]["performance"] = []
|
|
write_json(paths["parity_path"], parity)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
reasoning["parity_receipt"]["sha256"] = sha256(paths["parity_path"])
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "parity_exact_evidence" in result["failed_checks"]
|
|
assert result["parity_evidence_checks"]["structural_hashes"] is False
|
|
assert result["parity_evidence_checks"]["roles"] is False
|
|
assert result["parity_evidence_checks"]["performance"] is False
|
|
|
|
|
|
def test_reasoning_must_retrieve_expected_claim_sources_and_preserve_handle(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
for call in reasoning["result"]["database_tool_trace"]["calls"]:
|
|
call["result"]["row_ids"] = []
|
|
call["result"]["row_id_count"] = 0
|
|
reasoning["result"]["reply"] = "Cory found a weak claim and two sources."
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "reasoning_producer_evidence" in result["failed_checks"]
|
|
assert result["reasoning_producer_checks"]["expected_claim_and_sources_retrieved"] is False
|
|
assert result["reasoning_producer_checks"]["reply_uses_only_m3taversal_handle"] is False
|
|
|
|
|
|
def test_reasoning_wrapper_must_authenticate_the_cloudsql_server(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
for invocation in reasoning["wrapper_tool_proof"]["invocations"]:
|
|
invocation["database_identity"]["sslmode"] = "require"
|
|
invocation["database_identity"]["server_identity_verified"] = False
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "reasoning_producer_evidence" in result["failed_checks"]
|
|
assert result["reasoning_producer_checks"]["wrapper_invocations"] is False
|
|
|
|
|
|
def test_lifecycle_requires_restore_parity_reasoning_cleanup_chronology(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["generated_at_utc"] = "2026-07-15T00:58:00+00:00"
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "lifecycle_chronology" in result["failed_checks"]
|
|
|
|
|
|
def test_source_delta_requires_real_fingerprints_and_consistent_no_delta(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
delta = json.loads(paths["source_delta_path"].read_text())
|
|
delta["baseline"].pop("table_fingerprint_sha256")
|
|
delta["current"]["total_rows"] += 1
|
|
write_json(paths["source_delta_path"], delta)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert {"source_delta_baseline_shape", "source_delta_current_shape", "source_delta_consistent"} <= set(
|
|
result["failed_checks"]
|
|
)
|
|
|
|
|
|
def test_detected_source_delta_requires_exact_row_arithmetic(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
delta = json.loads(paths["source_delta_path"].read_text())
|
|
delta["delta"]["delta_detected"] = True
|
|
delta["delta"]["changed_tables"] = [{"table": "public.claims"}]
|
|
delta["delta"]["total_row_delta"] = 99
|
|
write_json(paths["source_delta_path"], delta)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "source_delta_consistent" in result["failed_checks"]
|
|
|
|
|
|
def test_postflight_source_requires_structured_healthy_service(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
current = json.loads(paths["current_source_path"].read_text())
|
|
current["source_service"]["before"]["ActiveState"] = "failed"
|
|
current["source_service"]["after"]["ActiveState"] = "failed"
|
|
write_json(paths["current_source_path"], current)
|
|
delta = json.loads(paths["source_delta_path"].read_text())
|
|
delta["current"]["capture_receipt_sha256"] = sha256(paths["current_source_path"])
|
|
write_json(paths["source_delta_path"], delta)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "current_source_pass" in result["failed_checks"]
|
|
|
|
|
|
def test_unchanged_but_inactive_service_cannot_pass_t3(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
restore = json.loads(paths["restore_path"].read_text())
|
|
restore["live_service"]["before"]["ActiveState"] = "failed"
|
|
restore["live_service"]["after"]["ActiveState"] = "failed"
|
|
write_json(paths["restore_path"], restore)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["restore_receipt"]["sha256"] = sha256(paths["restore_path"])
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["status"] == "fail"
|
|
assert "restore_service_healthy_unchanged" in result["failed_checks"]
|
|
|
|
|
|
def test_historical_but_monotonic_receipts_cannot_claim_current_t3(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
|
|
result = _verify_lifecycle(**paths, now=datetime(2026, 7, 15, 3, 0, tzinfo=UTC))
|
|
|
|
assert result["status"] == "fail"
|
|
assert "source_postflight_fresh" in result["failed_checks"]
|
|
assert result["postflight_age_seconds"] > result["max_postflight_age_seconds"]
|
|
|
|
|
|
def test_fresh_postflight_cannot_mask_historical_gcp_lifecycle(tmp_path: Path) -> None:
|
|
paths = lifecycle_receipts(tmp_path)
|
|
source = json.loads(paths["source_path"].read_text())
|
|
source["snapshot"]["captured_at_utc"] = "2026-07-12T00:59:00+00:00"
|
|
write_json(paths["source_path"], source)
|
|
restore = json.loads(paths["restore_path"].read_text())
|
|
restore["generated_at_utc"] = "2026-07-12T00:59:10+00:00"
|
|
restore["completed_at_utc"] = "2026-07-12T00:59:30+00:00"
|
|
restore["source"]["capture_receipt"]["sha256"] = sha256(paths["source_path"])
|
|
write_json(paths["restore_path"], restore)
|
|
parity = json.loads(paths["parity_path"].read_text())
|
|
parity["completed_at_utc"] = "2026-07-12T00:59:45+00:00"
|
|
write_json(paths["parity_path"], parity)
|
|
reasoning = json.loads(paths["reasoning_path"].read_text())
|
|
reasoning["generated_at_utc"] = "2026-07-12T01:00:00+00:00"
|
|
reasoning["completed_at_utc"] = "2026-07-12T01:01:00+00:00"
|
|
reasoning["parity_receipt"]["sha256"] = sha256(paths["parity_path"])
|
|
write_json(paths["reasoning_path"], reasoning)
|
|
attestation = json.loads(paths["reasoning_compute_path"].read_text())
|
|
attestation["generated_at_utc"] = "2026-07-12T01:01:05+00:00"
|
|
attestation["reasoning_receipt"]["sha256"] = sha256(paths["reasoning_path"])
|
|
attestation["reasoning_receipt"]["generated_at_utc"] = reasoning["generated_at_utc"]
|
|
attestation["reasoning_receipt"]["completed_at_utc"] = reasoning["completed_at_utc"]
|
|
write_json(paths["reasoning_compute_path"], attestation)
|
|
cleanup = json.loads(paths["cleanup_path"].read_text())
|
|
cleanup["generated_at_utc"] = "2026-07-12T01:01:10+00:00"
|
|
cleanup["completed_at_utc"] = "2026-07-12T01:01:30+00:00"
|
|
cleanup["restore_receipt"]["sha256"] = sha256(paths["restore_path"])
|
|
write_json(paths["cleanup_path"], cleanup)
|
|
delta = json.loads(paths["source_delta_path"].read_text())
|
|
delta["baseline"]["captured_at_utc"] = "2026-07-12T00:59:00+00:00"
|
|
delta["baseline"]["capture_receipt_sha256"] = sha256(paths["source_path"])
|
|
write_json(paths["source_delta_path"], delta)
|
|
|
|
result = verify_lifecycle(**paths)
|
|
|
|
assert result["checks"]["source_postflight_fresh"] is True
|
|
assert result["checks"]["lifecycle_chronology"] is True
|
|
assert result["status"] == "fail"
|
|
assert {"gcp_lifecycle_fresh", "lifecycle_span_bounded"} <= set(result["failed_checks"])
|