from __future__ import annotations import argparse import copy import hashlib import json import os import stat import sys from pathlib import Path import pytest from ops import run_local_genesis_ledger_rebuild as genesis_rebuild REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "scripts")) import export_kb_transition_replay_material as exporter # noqa: E402 import kb_apply_replay_receipt as replay_receipt # noqa: E402 PROPOSAL_ID = "70000000-0000-4000-8000-000000000001" REVIEWER_ID = "70000000-0000-4000-8000-000000000002" SERVICE_ID = "70000000-0000-4000-8000-000000000003" CLAIM_A = "70000000-0000-4000-8000-000000000004" CLAIM_B = "70000000-0000-4000-8000-000000000005" def _material() -> dict: payload = { "apply_payload": { "from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports", "weight": 0.75, }, "title": "Private exact transition packet", } approved = { "id": PROPOSAL_ID, "proposal_type": "add_edge", "status": "approved", "proposed_by_handle": "leo", "proposed_by_agent_id": REVIEWER_ID, "channel": "private_export_test", "source_ref": "private://transition/source", "rationale": "Retain the exact approved row for deterministic reconstruction.", "payload": payload, "reviewed_by_handle": "m3ta", "reviewed_by_agent_id": REVIEWER_ID, "reviewed_at": "2026-07-18T10:01:00+00:00", "review_note": "Approved the exact strict packet.", "applied_by_handle": None, "applied_by_agent_id": None, "applied_at": None, "created_at": "2026-07-18T10:00:00+00:00", "updated_at": "2026-07-18T10:01:00.000001+00:00", } applied = { **approved, "status": "applied", "applied_by_handle": "kb-apply", "applied_by_agent_id": SERVICE_ID, "applied_at": "2026-07-18T10:02:00+00:00", "updated_at": "2026-07-18T10:02:00.000001+00:00", } approval = { "proposal_id": PROPOSAL_ID, "proposal_type": "add_edge", "payload": payload, "reviewed_by_handle": "m3ta", "reviewed_by_agent_id": REVIEWER_ID, "reviewed_by_db_role": "kb_review", "reviewed_at": "2026-07-18T10:01:00+00:00", "review_note": "Approved the exact strict packet.", } receipt_proposal = {field: applied[field] for field in exporter.RECEIPT_PROPOSAL_FIELDS} receipt = replay_receipt.build_replay_receipt( receipt_proposal, { "claim_edges": [ { "id": "70000000-0000-4000-8000-000000000006", "from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports", "weight": 0.75, "created_by": None, "created_at": "2026-07-18T10:01:30+00:00", } ] }, apply_sql_sha256=replay_receipt.sha256_text("exact guarded apply SQL"), apply_sql_source="exact_executed_sql", exported_at_utc="2026-07-18T10:03:00+00:00", ) return { "artifact": exporter.MATERIAL_ARTIFACT, "contract_version": exporter.MATERIAL_CONTRACT_VERSION, "sequence": 1, "approved_proposal": approved, "approval_snapshot": approval, "applied_proposal": applied, "replay_receipt": receipt, } def _rehash_worker_receipt(material: dict) -> dict: receipt = material["replay_receipt"] def sha256_json(value) -> str: encoded = json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True).encode("utf-8") return hashlib.sha256(encoded).hexdigest() rows = receipt["canonical_rows"] replay_material = { "receipt_contract_version": receipt["receipt_contract_version"], "apply_engine": receipt["apply_engine"], "proposal": receipt["proposal"], "canonical_rows": rows, } receipt["hashes"] = { "apply_payload_sha256": sha256_json(receipt["proposal"]["payload"]["apply_payload"]), "proposal_payload_sha256": sha256_json(receipt["proposal"]["payload"]), "canonical_rows_sha256": sha256_json(rows), "row_sha256": {table: [sha256_json(row) for row in table_rows] for table, table_rows in rows.items()}, "table_sha256": {table: sha256_json(table_rows) for table, table_rows in rows.items()}, "replay_material_sha256": sha256_json(replay_material), } return material def _legacy_space_timestamp_material() -> dict: material = copy.deepcopy(_material()) receipt = material["replay_receipt"] receipt["proposal"]["reviewed_at"] = "2026-07-18 10:01:00+00" receipt["proposal"]["applied_at"] = "2026-07-18 10:02:00+00" receipt["canonical_rows"]["claim_edges"][0]["created_at"] = "2026-07-18 10:01:30+00" receipt["exported_at_utc"] = "2026-07-18T10:03:00+00:00" return _rehash_worker_receipt(material) def test_material_matches_genesis_replay_row_contract() -> None: material = exporter.validate_material( _material(), expected_proposal_id=PROPOSAL_ID, expected_sequence=1, ) assert exporter.MATERIAL_ARTIFACT == genesis_rebuild.MATERIAL_ARTIFACT assert exporter.MATERIAL_CONTRACT_VERSION == genesis_rebuild.MATERIAL_CONTRACT_VERSION assert exporter.PROPOSAL_FIELDS == genesis_rebuild.PROPOSAL_FIELDS assert exporter.APPROVAL_FIELDS == genesis_rebuild.APPROVAL_FIELDS genesis_rebuild._validate_proposal_rows( material["approved_proposal"], material["applied_proposal"], material["approval_snapshot"], material["replay_receipt"]["proposal"], ) def test_legacy_postgres_worker_receipt_exports_and_reconstructs_without_rehashing( tmp_path: Path, ) -> None: material = _legacy_space_timestamp_material() legacy_hash = material["replay_receipt"]["hashes"]["replay_material_sha256"] validated = exporter.validate_material( material, expected_proposal_id=PROPOSAL_ID, expected_sequence=1, ) assert validated["replay_receipt"]["proposal"]["reviewed_at"] == "2026-07-18 10:01:00+00" assert validated["replay_receipt"]["hashes"]["replay_material_sha256"] == legacy_hash material_path = tmp_path / "legacy-transition.json" material_path.write_text(json.dumps(validated), encoding="utf-8") entry = genesis_rebuild._validate_entry_material( validated, expected_sequence=1, expected_replay_hash=legacy_hash, material_path=material_path, material_sha256=hashlib.sha256(material_path.read_bytes()).hexdigest(), ) assert entry.replay_material_sha256 == legacy_hash assert entry.receipt["proposal"]["reviewed_at"] == "2026-07-18T10:01:00.000000Z" assert entry.receipt["canonical_rows"]["claim_edges"][0]["created_at"] == ("2026-07-18T10:01:30.000000Z") tampered = copy.deepcopy(material) tampered["replay_receipt"]["hashes"]["replay_material_sha256"] = "0" * 64 with pytest.raises(exporter.ExportError, match="worker replay receipt"): exporter.validate_material(tampered, expected_proposal_id=PROPOSAL_ID) @pytest.mark.parametrize( "separator", ["X", "_", "\U0001f642"], ids=["x", "underscore", "emoji"], ) def test_current_material_rejects_noncanonical_timestamp_separators(separator: str) -> None: material = _material() invalid = material["approved_proposal"]["reviewed_at"].replace("T", separator, 1) material["approved_proposal"]["reviewed_at"] = invalid material["applied_proposal"]["reviewed_at"] = invalid material["approval_snapshot"]["reviewed_at"] = invalid with pytest.raises(exporter.ExportError, match="timezone-aware timestamp"): exporter.validate_material(material, expected_proposal_id=PROPOSAL_ID) @pytest.mark.parametrize( "separator", ["X", "_", "\U0001f642"], ids=["x", "underscore", "emoji"], ) @pytest.mark.parametrize("target", ["proposal", "canonical_row"]) def test_rehashed_legacy_receipt_rejects_hybrid_timestamp_separators( separator: str, target: str, ) -> None: material = _legacy_space_timestamp_material() receipt = material["replay_receipt"] if target == "proposal": receipt["proposal"]["applied_at"] = receipt["proposal"]["applied_at"].replace(" ", separator, 1) else: row = receipt["canonical_rows"]["claim_edges"][0] row["created_at"] = row["created_at"].replace(" ", separator, 1) _rehash_worker_receipt(material) with pytest.raises(exporter.ExportError, match="worker replay receipt"): exporter.validate_material(material, expected_proposal_id=PROPOSAL_ID) @pytest.mark.parametrize( ("mutation", "message"), [ (lambda value: value["approved_proposal"].__setitem__("unexpected", True), "invalid fields"), ( lambda value: value["applied_proposal"].__setitem__("rationale", "post-approval drift"), "exact guarded apply transition", ), ( lambda value: value["approval_snapshot"].__setitem__("review_note", "different review"), "does not match approved proposal", ), ( lambda value: value["replay_receipt"]["proposal"].__setitem__("id", CLAIM_A), "worker replay receipt", ), (lambda value: value.__setitem__("sequence", 0), "positive integer"), ], ) def test_material_validation_fails_closed_on_drift(mutation, message: str) -> None: material = copy.deepcopy(_material()) mutation(material) with pytest.raises(exporter.ExportError, match=message): exporter.validate_material(material, expected_proposal_id=PROPOSAL_ID) def test_json_parser_rejects_duplicate_and_nonfinite_fields() -> None: with pytest.raises(exporter.ExportError, match="duplicate"): exporter._parse_json_object('{"artifact":"a","artifact":"b"}', label="fixture") with pytest.raises(exporter.ExportError, match="invalid numeric"): exporter._parse_json_object('{"sequence":NaN}', label="fixture") def test_private_writer_is_atomic_idempotent_and_refuses_alias_or_rerun_drift(tmp_path: Path) -> None: material = exporter.validate_material(_material(), expected_proposal_id=PROPOSAL_ID) protected = tmp_path / "worker-receipt.json" protected.write_text("private worker receipt", encoding="utf-8") protected.chmod(0o600) output = tmp_path / "material.json" written, disposition = exporter.write_private_material(output, material, protected_paths=(protected,)) assert written == output assert disposition == "created" assert stat.S_IMODE(output.stat().st_mode) == 0o600 assert output.stat().st_nlink == 1 assert json.loads(output.read_text(encoding="utf-8")) == material _, rerun_disposition = exporter.write_private_material(output, material, protected_paths=(protected,)) assert rerun_disposition == "unchanged" drifted = copy.deepcopy(material) drifted["sequence"] = 2 with pytest.raises(exporter.ExportError, match="different replay material"): exporter.write_private_material(output, drifted, protected_paths=(protected,)) with pytest.raises(exporter.ExportError, match="aliases a protected"): exporter.write_private_material(protected, material, protected_paths=(protected,)) dangling = tmp_path / "dangling-output.json" dangling.symlink_to(tmp_path / "missing-target.json") with pytest.raises(exporter.ExportError, match="non-symlink"): exporter.write_private_material(dangling, material, protected_paths=(protected,)) hardlink = tmp_path / "hardlink.json" os.link(output, hardlink) with pytest.raises(exporter.ExportError, match="hard-link"): exporter.write_private_material(output, material, protected_paths=(protected,)) def test_private_receipt_loader_requires_exact_mode_and_rejects_symlinks(tmp_path: Path) -> None: receipt = _material()["replay_receipt"] receipt_path = tmp_path / "receipt.json" receipt_path.write_text(json.dumps(receipt), encoding="utf-8") receipt_path.chmod(0o600) assert exporter._load_private_receipt(receipt_path) == receipt receipt_path.chmod(0o640) with pytest.raises(exporter.ExportError, match="exactly 0600"): exporter._load_private_receipt(receipt_path) receipt_path.chmod(0o600) receipt_link = tmp_path / "receipt-link.json" receipt_link.symlink_to(receipt_path) with pytest.raises(exporter.ExportError, match="non-symlink"): exporter._load_private_receipt(receipt_link) def test_transition_fetch_uses_only_read_only_narrow_function(monkeypatch: pytest.MonkeyPatch) -> None: calls: list[tuple[str, bool]] = [] rows = {key: _material()[key] for key in ("approved_proposal", "approval_snapshot", "applied_proposal")} def fake_run_psql(args, sql: str, password: str, *, redact_output_on_error: bool = False) -> str: assert args.role == "kb_apply" assert password == "private-password" calls.append((sql, redact_output_on_error)) return json.dumps(rows) monkeypatch.setattr(exporter.apply_engine, "run_psql", fake_run_psql) args = argparse.Namespace(container="disposable", db="teleo", host="127.0.0.1", role="kb_apply") assert exporter.fetch_transition_rows(args, "private-password", PROPOSAL_ID) == rows assert len(calls) == 1 sql, redacted = calls[0] assert "transaction isolation level repeatable read read only" in sql assert "kb_stage.export_applied_proposal_replay_rows" in sql assert not any(keyword in sql.lower() for keyword in ("insert ", "update ", "delete ", "truncate ")) assert redacted is True