1424 lines
50 KiB
Python
1424 lines
50 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import copy
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import uuid
|
|
from collections.abc import Iterator
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from ops import run_local_genesis_ledger_rebuild as rebuild
|
|
|
|
CLAIM_A = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"
|
|
CLAIM_B = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"
|
|
REVIEWER_ID = "11111111-1111-4111-8111-111111111111"
|
|
SERVICE_ID = "44444444-4444-4444-4444-444444444444"
|
|
PROPOSAL_ID = "99999999-9999-4999-8999-999999999999"
|
|
EDGE_ID = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee"
|
|
OTHER_AGENT_ID = "22222222-2222-4222-8222-222222222222"
|
|
REVISE_PROPOSAL_ID = "88888888-8888-4888-8888-888888888888"
|
|
PRIOR_STRATEGY_ID = "33333333-3333-4333-8333-333333333333"
|
|
PRIOR_ACTIVE_NODE_ID = "55555555-5555-4555-8555-555555555555"
|
|
PRIOR_RETIRED_NODE_ID = "66666666-6666-4666-8666-666666666666"
|
|
OTHER_STRATEGY_ID = "77777777-7777-4777-8777-777777777777"
|
|
OTHER_ACTIVE_NODE_ID = "12121212-1212-4212-8212-121212121212"
|
|
NULL_AGENT_NODE_ID = "13131313-1313-4313-8313-131313131313"
|
|
PRIOR_NODE_ANCHOR_ID = "19191919-1919-4919-8919-191919191919"
|
|
RECEIPT_STRATEGY_ID = "14141414-1414-4414-8414-141414141414"
|
|
RECEIPT_NODE_A_ID = "15151515-1515-4515-8515-151515151515"
|
|
RECEIPT_NODE_B_ID = "16161616-1616-4616-8616-161616161616"
|
|
PRIVATE_MARKER = "PRIVATE-REPLAY-MATERIAL-MUST-NOT-LEAK"
|
|
|
|
|
|
def sha256_file(path: Path) -> str:
|
|
digest = hashlib.sha256()
|
|
digest.update(path.read_bytes())
|
|
return digest.hexdigest()
|
|
|
|
|
|
def write_json(path: Path, value: object) -> Path:
|
|
path.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def manifest_rows(database: str = "teleo_fixture") -> list[dict]:
|
|
role = {
|
|
"name": "kb_apply",
|
|
"can_login": True,
|
|
"superuser": False,
|
|
"create_db": False,
|
|
"create_role": False,
|
|
"inherit": False,
|
|
"replication": False,
|
|
"bypass_rls": False,
|
|
}
|
|
rows = [
|
|
{
|
|
"kind": "identity",
|
|
"database": database,
|
|
"server_version_num": 160010,
|
|
"transaction_read_only": "on",
|
|
"server_address": None,
|
|
"server_port": None,
|
|
"ssl": False,
|
|
"ssl_version": None,
|
|
"database_collation": "C",
|
|
"database_ctype": "C",
|
|
},
|
|
{"kind": "schemas", "items": ["kb_stage", "public"]},
|
|
{"kind": "extensions", "items": []},
|
|
{"kind": "application_roles", "items": [role]},
|
|
{"kind": "role_memberships", "items": []},
|
|
{"kind": "object_ownership", "items": []},
|
|
{"kind": "object_acl", "items": []},
|
|
]
|
|
rows.extend(
|
|
{"kind": kind, "items": []}
|
|
for kind in (
|
|
"columns",
|
|
"constraints",
|
|
"indexes",
|
|
"sequences",
|
|
"views",
|
|
"functions",
|
|
"triggers",
|
|
"types",
|
|
"policies",
|
|
)
|
|
)
|
|
rows.extend(
|
|
[
|
|
{
|
|
"kind": "table",
|
|
"schema": "public",
|
|
"table": "claims",
|
|
"row_count": 2,
|
|
"rowset_md5": "fixture",
|
|
},
|
|
{
|
|
"kind": "performance",
|
|
"query": "count_claims",
|
|
"elapsed_ms": 1.0,
|
|
"observed_rows": 2,
|
|
},
|
|
]
|
|
)
|
|
return rows
|
|
|
|
|
|
def write_manifest(path: Path) -> Path:
|
|
path.write_text("".join(json.dumps(row) + "\n" for row in manifest_rows()), encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def proposal_rows() -> tuple[dict, dict, dict]:
|
|
payload = {
|
|
"apply_payload": {
|
|
"from_claim": CLAIM_A,
|
|
"to_claim": CLAIM_B,
|
|
"edge_type": "supports",
|
|
"weight": 0.8,
|
|
},
|
|
"private_title": PRIVATE_MARKER,
|
|
}
|
|
approved = {
|
|
"id": PROPOSAL_ID,
|
|
"proposal_type": "add_edge",
|
|
"status": "approved",
|
|
"proposed_by_handle": "fixture-agent",
|
|
"proposed_by_agent_id": REVIEWER_ID,
|
|
"channel": "reconstruction_fixture",
|
|
"source_ref": "private://fixture/source",
|
|
"rationale": PRIVATE_MARKER,
|
|
"payload": payload,
|
|
"reviewed_by_handle": "m3ta",
|
|
"reviewed_by_agent_id": REVIEWER_ID,
|
|
"reviewed_at": "2026-07-14T01:00:00+00:00",
|
|
"review_note": "Reviewed exact strict fixture payload.",
|
|
"applied_by_handle": None,
|
|
"applied_by_agent_id": None,
|
|
"applied_at": None,
|
|
"created_at": "2026-07-14T00:59:00+00:00",
|
|
"updated_at": "2026-07-14T01:00:00+00:00",
|
|
}
|
|
applied = {
|
|
**approved,
|
|
"status": "applied",
|
|
"applied_by_handle": "kb-apply",
|
|
"applied_by_agent_id": SERVICE_ID,
|
|
"applied_at": "2026-07-14T01:01:00+00:00",
|
|
"updated_at": "2026-07-14T01:01: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-14T01:00:00+00:00",
|
|
"review_note": "Reviewed exact strict fixture payload.",
|
|
}
|
|
return approved, applied, approval
|
|
|
|
|
|
def revise_strategy_proposal_rows() -> tuple[dict, dict, dict]:
|
|
approved, _, approval = proposal_rows()
|
|
payload = {
|
|
"apply_payload": {
|
|
"agent_id": REVIEWER_ID,
|
|
"strategy": {
|
|
"diagnosis": "Deterministic reconstruction needs exact mutation deltas.",
|
|
"guiding_policy": "Replay every guarded transition and fail closed on drift.",
|
|
"proximate_objectives": ["exact parity", "zero orphan containers"],
|
|
},
|
|
"strategy_nodes": [
|
|
{
|
|
"node_type": "policy",
|
|
"title": "Replay exactly",
|
|
"body": "Bind the guarded transition to its canonical receipt.",
|
|
"rank": 1,
|
|
},
|
|
{
|
|
"node_type": "policy",
|
|
"title": "Replay exactly",
|
|
"body": "Bind the guarded transition to its canonical receipt.",
|
|
"rank": 1,
|
|
},
|
|
],
|
|
},
|
|
"private_title": PRIVATE_MARKER,
|
|
}
|
|
approved = {
|
|
**approved,
|
|
"id": REVISE_PROPOSAL_ID,
|
|
"proposal_type": "revise_strategy",
|
|
"payload": payload,
|
|
"created_at": "2026-07-14T00:58:00+00:00",
|
|
"updated_at": "2026-07-14T01:00:00+00:00",
|
|
}
|
|
applied = {
|
|
**approved,
|
|
"status": "applied",
|
|
"applied_by_handle": "kb-apply",
|
|
"applied_by_agent_id": SERVICE_ID,
|
|
"applied_at": "2026-07-14T01:01:00+00:00",
|
|
"updated_at": "2026-07-14T01:01:00.000001+00:00",
|
|
}
|
|
approval = {
|
|
**approval,
|
|
"proposal_id": REVISE_PROPOSAL_ID,
|
|
"proposal_type": "revise_strategy",
|
|
"payload": payload,
|
|
}
|
|
return approved, applied, approval
|
|
|
|
|
|
def applied_envelope(applied: dict) -> dict:
|
|
fields = (
|
|
"id",
|
|
"proposal_type",
|
|
"status",
|
|
"payload",
|
|
"reviewed_by_handle",
|
|
"reviewed_by_agent_id",
|
|
"reviewed_at",
|
|
"review_note",
|
|
"applied_by_handle",
|
|
"applied_by_agent_id",
|
|
"applied_at",
|
|
)
|
|
return {field: applied[field] for field in fields}
|
|
|
|
|
|
def replay_material() -> dict:
|
|
approved, applied, approval = proposal_rows()
|
|
proposal = applied_envelope(applied)
|
|
edge = {
|
|
"id": EDGE_ID,
|
|
"from_claim": CLAIM_A,
|
|
"to_claim": CLAIM_B,
|
|
"edge_type": "supports",
|
|
"weight": 0.8,
|
|
"created_by": None,
|
|
"created_at": "2026-07-14T01:00:30+00:00",
|
|
}
|
|
receipt = rebuild.replay_receipt.build_replay_receipt(
|
|
proposal,
|
|
{"claim_edges": [edge]},
|
|
apply_sql_sha256=rebuild.replay_receipt.sha256_text("fixture original guarded apply SQL"),
|
|
apply_sql_source="exact_executed_sql",
|
|
exported_at_utc="2026-07-14T01:02:00+00:00",
|
|
)
|
|
return {
|
|
"artifact": rebuild.MATERIAL_ARTIFACT,
|
|
"contract_version": rebuild.MATERIAL_CONTRACT_VERSION,
|
|
"sequence": 1,
|
|
"approved_proposal": approved,
|
|
"approval_snapshot": approval,
|
|
"applied_proposal": applied,
|
|
"replay_receipt": receipt,
|
|
}
|
|
|
|
|
|
def revise_strategy_replay_material(*, apply_sql_source: str = "exact_executed_sql", version: int = 2) -> dict:
|
|
approved, applied, approval = revise_strategy_proposal_rows()
|
|
proposal = applied_envelope(applied)
|
|
transaction_timestamp = "2026-07-14T01:00:30+00:00"
|
|
canonical_rows = {
|
|
"strategies": [
|
|
{
|
|
"id": RECEIPT_STRATEGY_ID,
|
|
"agent_id": REVIEWER_ID,
|
|
**proposal["payload"]["apply_payload"]["strategy"],
|
|
"version": version,
|
|
"active": True,
|
|
"created_at": transaction_timestamp,
|
|
}
|
|
],
|
|
"strategy_nodes": [
|
|
{
|
|
"id": node_id,
|
|
"agent_id": REVIEWER_ID,
|
|
**node,
|
|
"status": "active",
|
|
"horizon": None,
|
|
"measure": None,
|
|
"source_ref": None,
|
|
"metadata": {},
|
|
"created_at": transaction_timestamp,
|
|
"updated_at": transaction_timestamp,
|
|
}
|
|
for node_id, node in zip(
|
|
(RECEIPT_NODE_A_ID, RECEIPT_NODE_B_ID),
|
|
proposal["payload"]["apply_payload"]["strategy_nodes"],
|
|
strict=True,
|
|
)
|
|
],
|
|
}
|
|
apply_sql = rebuild.apply_engine.build_apply_sql(proposal, applied["applied_by_handle"])
|
|
receipt = rebuild.replay_receipt.build_replay_receipt(
|
|
proposal,
|
|
canonical_rows,
|
|
apply_sql_sha256=rebuild.replay_receipt.sha256_text(apply_sql),
|
|
apply_sql_source=apply_sql_source,
|
|
exported_at_utc="2026-07-14T01:02:00+00:00",
|
|
)
|
|
return {
|
|
"artifact": rebuild.MATERIAL_ARTIFACT,
|
|
"contract_version": rebuild.MATERIAL_CONTRACT_VERSION,
|
|
"sequence": 1,
|
|
"approved_proposal": approved,
|
|
"approval_snapshot": approval,
|
|
"applied_proposal": applied,
|
|
"replay_receipt": receipt,
|
|
}
|
|
|
|
|
|
def rehash_revise_strategy_receipt(material: dict) -> None:
|
|
prior_receipt = material["replay_receipt"]
|
|
proposal = applied_envelope(material["applied_proposal"])
|
|
apply_sql = rebuild.apply_engine.build_apply_sql(proposal, material["applied_proposal"]["applied_by_handle"])
|
|
material["replay_receipt"] = rebuild.replay_receipt.build_replay_receipt(
|
|
proposal,
|
|
prior_receipt["canonical_rows"],
|
|
apply_sql_sha256=rebuild.replay_receipt.sha256_text(apply_sql),
|
|
apply_sql_source=prior_receipt["apply_engine"]["source"],
|
|
exported_at_utc=prior_receipt["exported_at_utc"],
|
|
)
|
|
|
|
|
|
def write_bundle(tmp_path: Path, *, material: dict | None = None) -> argparse.Namespace:
|
|
dump = tmp_path / "genesis.dump"
|
|
dump.write_bytes(b"PGDMPfixture")
|
|
genesis_manifest = write_manifest(tmp_path / "genesis-manifest.jsonl")
|
|
final_manifest = write_manifest(tmp_path / "final-manifest.jsonl")
|
|
material = copy.deepcopy(material or replay_material())
|
|
material_path = write_json(tmp_path / "entry-0001.json", material)
|
|
receipt_hash = material["replay_receipt"]["hashes"]["replay_material_sha256"]
|
|
ledger = {
|
|
"artifact": rebuild.LEDGER_ARTIFACT,
|
|
"contract_version": rebuild.LEDGER_CONTRACT_VERSION,
|
|
"engine": rebuild._engine_hashes(),
|
|
"genesis": {
|
|
"dump_sha256": sha256_file(dump),
|
|
"parity_manifest_sha256": sha256_file(genesis_manifest),
|
|
},
|
|
"entries": [
|
|
{
|
|
"sequence": 1,
|
|
"material": material_path.name,
|
|
"sha256": sha256_file(material_path),
|
|
"replay_material_sha256": receipt_hash,
|
|
}
|
|
],
|
|
"final_parity": {
|
|
"manifest": final_manifest.name,
|
|
"sha256": sha256_file(final_manifest),
|
|
},
|
|
}
|
|
ledger_path = write_json(tmp_path / "ledger.json", ledger)
|
|
return argparse.Namespace(
|
|
genesis_dump=dump,
|
|
genesis_manifest=genesis_manifest,
|
|
ledger=ledger_path,
|
|
ledger_sha256=sha256_file(ledger_path),
|
|
database="teleo",
|
|
image=rebuild.DEFAULT_REBUILD_IMAGE,
|
|
container_prefix="teleo-genesis-ledger-test",
|
|
tmpfs_mb=256,
|
|
startup_timeout=30.0,
|
|
restore_timeout=60.0,
|
|
apply_timeout=60.0,
|
|
manifest_timeout=60.0,
|
|
command_timeout=20.0,
|
|
poll_interval=0.05,
|
|
max_target_query_ms=5000.0,
|
|
max_target_source_ratio=100.0,
|
|
docker_bin="docker",
|
|
output=tmp_path / "receipt.json",
|
|
)
|
|
|
|
|
|
def rewrite_material_and_ledger(args: argparse.Namespace, material: dict) -> None:
|
|
material_path = args.ledger.parent / "entry-0001.json"
|
|
write_json(material_path, material)
|
|
ledger = json.loads(args.ledger.read_text(encoding="utf-8"))
|
|
ledger["entries"][0]["sha256"] = sha256_file(material_path)
|
|
write_json(args.ledger, ledger)
|
|
args.ledger_sha256 = sha256_file(args.ledger)
|
|
|
|
|
|
def test_load_bundle_validates_every_pin_and_current_apply_engine(tmp_path: Path) -> None:
|
|
args = write_bundle(tmp_path)
|
|
|
|
bundle = rebuild.load_bundle(args)
|
|
|
|
assert bundle.genesis_dump_sha256 == sha256_file(args.genesis_dump)
|
|
assert bundle.genesis_manifest_sha256 == sha256_file(args.genesis_manifest)
|
|
assert bundle.final_manifest_sha256 == sha256_file(tmp_path / "final-manifest.jsonl")
|
|
assert bundle.engine_hashes == rebuild._engine_hashes()
|
|
assert len(bundle.entries) == 1
|
|
entry = bundle.entries[0]
|
|
assert entry.applied_proposal["proposal_type"] == "add_edge"
|
|
assert entry.current_apply_sql_sha256 == hashlib.sha256(entry.current_apply_sql.encode("utf-8")).hexdigest()
|
|
assert "kb_stage.assert_approved_proposal" in entry.current_apply_sql
|
|
|
|
|
|
def test_dump_hash_mismatch_fails_before_container_start(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
args = write_bundle(tmp_path)
|
|
args.genesis_dump.write_bytes(b"PGDMPtampered")
|
|
commands: list[list[str]] = []
|
|
|
|
def absent_docker(command: list[str], *, timeout: float):
|
|
commands.append(command)
|
|
if command[1:3] == ["rm", "--force"]:
|
|
return subprocess.CompletedProcess(command, 1, "", "No such container")
|
|
if command[1:3] == ["container", "inspect"]:
|
|
return subprocess.CompletedProcess(command, 1, "", "No such object")
|
|
raise AssertionError(f"unexpected command after failed preflight: {command}")
|
|
|
|
monkeypatch.setattr(rebuild.canonical_rebuild, "_run", absent_docker)
|
|
|
|
receipt = rebuild.run_reconstruction(args)
|
|
|
|
assert receipt["status"] == "fail"
|
|
assert receipt["error"]["code"] == "hash_pin_mismatch"
|
|
assert receipt["cleanup"]["container_absent"] is True
|
|
assert not any(len(command) > 1 and command[1] == "run" for command in commands)
|
|
|
|
|
|
def test_revise_strategy_material_validates_exact_engine_and_canonicalizes_row_order(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
material = revise_strategy_replay_material()
|
|
material["replay_receipt"]["canonical_rows"]["strategy_nodes"].reverse()
|
|
args = write_bundle(tmp_path, material=material)
|
|
|
|
entry = rebuild.load_bundle(args).entries[0]
|
|
|
|
assert entry.applied_proposal["proposal_type"] == "revise_strategy"
|
|
assert entry.receipt["apply_engine"]["source"] == "exact_executed_sql"
|
|
assert entry.receipt["apply_engine"]["apply_sql_sha256"] == entry.current_apply_sql_sha256
|
|
assert entry.receipt["canonical_rows"]["strategy_nodes"] == sorted(
|
|
entry.receipt["canonical_rows"]["strategy_nodes"], key=rebuild._canonical_json
|
|
)
|
|
|
|
|
|
def test_revise_strategy_material_rejects_reconstructed_apply_engine(tmp_path: Path) -> None:
|
|
args = write_bundle(
|
|
tmp_path,
|
|
material=revise_strategy_replay_material(apply_sql_source="reconstructed_current_engine"),
|
|
)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "mutating_apply_engine_mismatch"
|
|
|
|
|
|
def test_revise_strategy_rejects_fully_rehashed_transaction_before_approval(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
material = revise_strategy_replay_material()
|
|
original_receipt = material["replay_receipt"]
|
|
forged_timestamp = "2026-07-13T01:00:30+00:00"
|
|
canonical_rows = copy.deepcopy(original_receipt["canonical_rows"])
|
|
canonical_rows["strategies"][0]["created_at"] = forged_timestamp
|
|
for row in canonical_rows["strategy_nodes"]:
|
|
row["created_at"] = forged_timestamp
|
|
row["updated_at"] = forged_timestamp
|
|
material["replay_receipt"]["canonical_rows"] = canonical_rows
|
|
rehash_revise_strategy_receipt(material)
|
|
args = write_bundle(tmp_path, material=material)
|
|
ledger = json.loads(args.ledger.read_text(encoding="utf-8"))
|
|
material_path = args.ledger.parent / ledger["entries"][0]["material"]
|
|
|
|
assert material["replay_receipt"]["hashes"] != original_receipt["hashes"]
|
|
assert ledger["entries"][0]["sha256"] == sha256_file(material_path)
|
|
assert (
|
|
ledger["entries"][0]["replay_material_sha256"] == material["replay_receipt"]["hashes"]["replay_material_sha256"]
|
|
)
|
|
assert args.ledger_sha256 == sha256_file(args.ledger)
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "invalid_mutating_receipt"
|
|
assert "before proposal approval" in exc_info.value.safe_message
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("reviewed_at", "transaction_timestamp", "applied_at"),
|
|
(
|
|
(
|
|
"2026-07-14T03:00:00+02:00",
|
|
"2026-07-14T01:00:00+00:00",
|
|
"2026-07-14T01:01:00+00:00",
|
|
),
|
|
(
|
|
"2026-07-14T01:00:00+00:00",
|
|
"2026-07-14T01:01:00+00:00",
|
|
"2026-07-14T03:01:00+02:00",
|
|
),
|
|
),
|
|
)
|
|
def test_revise_strategy_accepts_timezone_aware_closed_timestamp_boundaries(
|
|
tmp_path: Path,
|
|
reviewed_at: str,
|
|
transaction_timestamp: str,
|
|
applied_at: str,
|
|
) -> None:
|
|
material = revise_strategy_replay_material()
|
|
for proposal_row in (material["approved_proposal"], material["applied_proposal"]):
|
|
proposal_row["reviewed_at"] = reviewed_at
|
|
material["approval_snapshot"]["reviewed_at"] = reviewed_at
|
|
material["applied_proposal"]["applied_at"] = applied_at
|
|
rows = material["replay_receipt"]["canonical_rows"]
|
|
rows["strategies"][0]["created_at"] = transaction_timestamp
|
|
for row in rows["strategy_nodes"]:
|
|
row["created_at"] = transaction_timestamp
|
|
row["updated_at"] = transaction_timestamp
|
|
rehash_revise_strategy_receipt(material)
|
|
|
|
entry = rebuild.load_bundle(write_bundle(tmp_path, material=material)).entries[0]
|
|
|
|
assert entry.receipt["canonical_rows"]["strategies"][0]["created_at"] == transaction_timestamp
|
|
|
|
|
|
def test_revise_strategy_rejects_reviewed_at_without_timezone(tmp_path: Path) -> None:
|
|
material = revise_strategy_replay_material()
|
|
reviewed_at = "2026-07-14T01:00:00"
|
|
for proposal_row in (material["approved_proposal"], material["applied_proposal"]):
|
|
proposal_row["reviewed_at"] = reviewed_at
|
|
material["approval_snapshot"]["reviewed_at"] = reviewed_at
|
|
rehash_revise_strategy_receipt(material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(write_bundle(tmp_path, material=material))
|
|
|
|
assert exc_info.value.code == "invalid_mutating_receipt"
|
|
assert "reviewed_at must include a timezone" in exc_info.value.safe_message
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"invalid_case",
|
|
("extra_strategy_field", "duplicate_node_id", "node_timestamp_drift", "transaction_after_apply"),
|
|
)
|
|
def test_revise_strategy_receipt_rejects_impossible_poststate(tmp_path: Path, invalid_case: str) -> None:
|
|
material = revise_strategy_replay_material()
|
|
rows = material["replay_receipt"]["canonical_rows"]
|
|
if invalid_case == "extra_strategy_field":
|
|
rows["strategies"][0]["unexpected"] = "ignored by jsonb_populate_record"
|
|
elif invalid_case == "duplicate_node_id":
|
|
rows["strategy_nodes"][1]["id"] = rows["strategy_nodes"][0]["id"]
|
|
elif invalid_case == "node_timestamp_drift":
|
|
rows["strategy_nodes"][0]["updated_at"] = "2026-07-14T01:00:31+00:00"
|
|
else:
|
|
rows["strategies"][0]["created_at"] = "2026-07-14T01:01:01+00:00"
|
|
for row in rows["strategy_nodes"]:
|
|
row["created_at"] = "2026-07-14T01:01:01+00:00"
|
|
row["updated_at"] = "2026-07-14T01:01:01+00:00"
|
|
args = write_bundle(tmp_path, material=material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "invalid_mutating_receipt"
|
|
|
|
|
|
def test_revise_strategy_transition_builders_preserve_historical_prestate(tmp_path: Path) -> None:
|
|
entry = rebuild.load_bundle(write_bundle(tmp_path, material=revise_strategy_replay_material())).entries[0]
|
|
prestate = {
|
|
"strategy_ids": [PRIOR_STRATEGY_ID],
|
|
"active_strategy_ids": [PRIOR_STRATEGY_ID],
|
|
"max_strategy_version": 1,
|
|
"strategy_node_ids": [PRIOR_ACTIVE_NODE_ID, PRIOR_RETIRED_NODE_ID],
|
|
"non_retired_strategy_node_ids": [PRIOR_ACTIVE_NODE_ID],
|
|
}
|
|
generated_rows = copy.deepcopy(entry.receipt["canonical_rows"])
|
|
generated_rows["strategies"][0]["id"] = "17171717-1717-4717-8717-171717171717"
|
|
generated_rows["strategies"][0]["created_at"] = "2026-07-15T01:00:30+00:00"
|
|
for index, row in enumerate(generated_rows["strategy_nodes"], start=1):
|
|
row["id"] = f"18181818-1818-4818-8818-18181818181{index}"
|
|
row["created_at"] = "2026-07-15T01:00:30+00:00"
|
|
row["updated_at"] = "2026-07-15T01:00:30+00:00"
|
|
|
|
sql = rebuild.build_revise_strategy_normalization_sql(entry, prestate, generated_rows)
|
|
|
|
assert PRIOR_ACTIVE_NODE_ID in sql
|
|
assert PRIOR_RETIRED_NODE_ID not in sql
|
|
assert PRIOR_STRATEGY_ID in sql
|
|
assert RECEIPT_STRATEGY_ID in sql
|
|
assert "updated_at = E'2026-07-14T01:00:30+00:00'::timestamptz" in sql
|
|
|
|
|
|
def test_revise_strategy_transition_builders_allow_empty_prestate(tmp_path: Path) -> None:
|
|
entry = rebuild.load_bundle(write_bundle(tmp_path, material=revise_strategy_replay_material(version=1))).entries[0]
|
|
prestate = {
|
|
"strategy_ids": [],
|
|
"active_strategy_ids": [],
|
|
"max_strategy_version": 0,
|
|
"strategy_node_ids": [],
|
|
"non_retired_strategy_node_ids": [],
|
|
}
|
|
generated_rows = copy.deepcopy(entry.receipt["canonical_rows"])
|
|
generated_rows["strategies"][0]["id"] = "17171717-1717-4717-8717-171717171717"
|
|
generated_rows["strategies"][0]["created_at"] = "2026-07-15T01:00:30+00:00"
|
|
for index, row in enumerate(generated_rows["strategy_nodes"], start=1):
|
|
row["id"] = f"18181818-1818-4818-8818-18181818181{index}"
|
|
row["created_at"] = "2026-07-15T01:00:30+00:00"
|
|
row["updated_at"] = "2026-07-15T01:00:30+00:00"
|
|
|
|
sql = rebuild.build_revise_strategy_normalization_sql(entry, prestate, generated_rows)
|
|
|
|
assert "prior active strategy transition mismatch" not in sql
|
|
assert "prior node normalization mismatch" not in sql
|
|
assert RECEIPT_STRATEGY_ID in sql
|
|
|
|
|
|
def test_legacy_freeform_receipt_fails_closed(tmp_path: Path) -> None:
|
|
material = replay_material()
|
|
material["replay_receipt"]["proposal"]["payload"] = {"legacy": PRIVATE_MARKER}
|
|
material["approved_proposal"]["payload"] = {"legacy": PRIVATE_MARKER}
|
|
material["applied_proposal"]["payload"] = {"legacy": PRIVATE_MARKER}
|
|
material["approval_snapshot"]["payload"] = {"legacy": PRIVATE_MARKER}
|
|
args = write_bundle(tmp_path, material=material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "invalid_replay_receipt"
|
|
assert PRIVATE_MARKER not in exc_info.value.safe_message
|
|
|
|
|
|
def test_unknown_proposal_operation_fails_closed_before_replay(tmp_path: Path) -> None:
|
|
material = replay_material()
|
|
material["replay_receipt"]["proposal"]["proposal_type"] = "delete_claim"
|
|
args = write_bundle(tmp_path, material=material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "unsupported_proposal_type"
|
|
|
|
|
|
def test_proposal_metadata_outside_apply_transition_is_rejected(tmp_path: Path) -> None:
|
|
material = replay_material()
|
|
material["applied_proposal"]["rationale"] = "silently changed after review"
|
|
args = write_bundle(tmp_path)
|
|
rewrite_material_and_ledger(args, material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "material_mismatch"
|
|
assert "rationale" in exc_info.value.safe_message
|
|
|
|
|
|
def test_output_cannot_overwrite_a_fixed_guard_or_engine_file(tmp_path: Path) -> None:
|
|
args = write_bundle(tmp_path)
|
|
args.output = rebuild.GUARD_PREREQUISITES_PATH
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "unsafe_output_path"
|
|
|
|
|
|
def test_cli_defaults_to_pinned_image_and_rejects_moving_tag(tmp_path: Path) -> None:
|
|
bundle = write_bundle(tmp_path)
|
|
argv = [
|
|
"--genesis-dump",
|
|
str(bundle.genesis_dump),
|
|
"--genesis-manifest",
|
|
str(bundle.genesis_manifest),
|
|
"--ledger",
|
|
str(bundle.ledger),
|
|
"--ledger-sha256",
|
|
bundle.ledger_sha256,
|
|
"--output",
|
|
str(tmp_path / "receipt.json"),
|
|
]
|
|
|
|
assert rebuild.parse_args(argv).image == rebuild.DEFAULT_REBUILD_IMAGE
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
rebuild.parse_args([*argv, "--image", "postgres:16-alpine"])
|
|
|
|
assert exc_info.value.code == 2
|
|
|
|
|
|
def test_unknown_private_field_name_is_not_echoed_in_public_error(tmp_path: Path) -> None:
|
|
material = replay_material()
|
|
material[PRIVATE_MARKER] = "private value"
|
|
args = write_bundle(tmp_path, material=material)
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild.load_bundle(args)
|
|
|
|
assert exc_info.value.code == "invalid_contract"
|
|
assert PRIVATE_MARKER not in exc_info.value.safe_message
|
|
|
|
|
|
def test_seed_sql_preserves_exact_rows_and_uses_only_fixed_tables(tmp_path: Path) -> None:
|
|
entry = rebuild.load_bundle(write_bundle(tmp_path)).entries[0]
|
|
|
|
sql = rebuild.build_seed_sql(entry)
|
|
|
|
assert "jsonb_populate_record" in sql
|
|
assert "kb_stage.kb_proposals" in sql
|
|
assert "kb_stage.kb_proposal_approvals" in sql
|
|
assert "public.claim_edges" in sql
|
|
assert "on conflict do nothing" in sql
|
|
assert PRIVATE_MARKER in sql
|
|
assert "public.strategies" not in sql
|
|
|
|
|
|
def test_private_psql_failure_output_is_replaced_with_a_fingerprint(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
captured: dict[str, object] = {}
|
|
|
|
def fail(command: list[str], *, stdin: str, timeout: float):
|
|
captured.update(command=command, stdin=stdin, timeout=timeout)
|
|
return subprocess.CompletedProcess(command, 1, "", f"ERROR: {PRIVATE_MARKER}")
|
|
|
|
monkeypatch.setattr(rebuild, "_run_stdin", fail)
|
|
args = argparse.Namespace(docker_bin="docker", database="teleo")
|
|
|
|
with pytest.raises(rebuild.ReconstructionError) as exc_info:
|
|
rebuild._psql(
|
|
args,
|
|
"fixture-container",
|
|
f"select '{PRIVATE_MARKER}';",
|
|
role="postgres",
|
|
timeout=3.0,
|
|
code="fixture_failure",
|
|
action="private fixture SQL",
|
|
)
|
|
|
|
assert PRIVATE_MARKER not in exc_info.value.safe_message
|
|
assert "diagnostic_sha256=" in exc_info.value.safe_message
|
|
assert PRIVATE_MARKER not in " ".join(captured["command"])
|
|
assert PRIVATE_MARKER in captured["stdin"]
|
|
|
|
|
|
def test_entry_summary_is_secret_safe(tmp_path: Path) -> None:
|
|
entry = rebuild.load_bundle(write_bundle(tmp_path)).entries[0]
|
|
|
|
encoded = json.dumps(rebuild._entry_summary(entry), sort_keys=True)
|
|
|
|
assert PRIVATE_MARKER not in encoded
|
|
assert entry.applied_proposal["id"] in encoded
|
|
assert entry.replay_material_sha256 in encoded
|
|
|
|
|
|
BOOTSTRAP_SQL = f"""
|
|
create role kb_apply login noinherit;
|
|
create role kb_review login noinherit;
|
|
create schema kb_stage;
|
|
create type evidence_role as enum ('grounds', 'illustrates', 'contradicts');
|
|
create type edge_type as enum (
|
|
'supports', 'challenges', 'requires', 'relates', 'contradicts', 'supersedes',
|
|
'derives_from', 'cites', 'causes', 'constrains', 'accelerates'
|
|
);
|
|
|
|
create table public.agents (
|
|
id uuid primary key,
|
|
handle text not null unique,
|
|
kind text not null
|
|
);
|
|
create table public.claims (
|
|
id uuid primary key,
|
|
type text not null,
|
|
text text not null,
|
|
status text not null,
|
|
confidence numeric,
|
|
tags text[] not null default '{{}}',
|
|
created_by uuid references public.agents(id),
|
|
superseded_by uuid references public.claims(id),
|
|
created_at timestamptz not null default now(),
|
|
updated_at timestamptz not null default now()
|
|
);
|
|
create table public.sources (
|
|
id uuid primary key,
|
|
source_type text not null,
|
|
url text,
|
|
storage_path text,
|
|
excerpt text,
|
|
hash text not null,
|
|
created_by uuid references public.agents(id),
|
|
captured_at timestamptz,
|
|
created_at timestamptz not null default now()
|
|
);
|
|
create table public.claim_evidence (
|
|
id uuid primary key,
|
|
claim_id uuid not null references public.claims(id),
|
|
source_id uuid not null references public.sources(id),
|
|
role evidence_role not null,
|
|
weight numeric,
|
|
created_by uuid references public.agents(id),
|
|
created_at timestamptz not null default now()
|
|
);
|
|
create table public.claim_edges (
|
|
id uuid primary key,
|
|
from_claim uuid not null references public.claims(id),
|
|
to_claim uuid not null references public.claims(id),
|
|
edge_type edge_type not null,
|
|
weight numeric,
|
|
created_by uuid references public.agents(id),
|
|
created_at timestamptz not null default now()
|
|
);
|
|
create table public.reasoning_tools (
|
|
id uuid primary key,
|
|
agent_id uuid references public.agents(id),
|
|
name text not null,
|
|
description text not null,
|
|
category text,
|
|
created_at timestamptz not null default now()
|
|
);
|
|
create table public.strategies (
|
|
id uuid primary key default gen_random_uuid(),
|
|
agent_id uuid not null references public.agents(id),
|
|
diagnosis text,
|
|
guiding_policy text,
|
|
proximate_objectives jsonb,
|
|
version integer not null default 1,
|
|
active boolean not null default true,
|
|
created_at timestamptz not null default now(),
|
|
unique (agent_id, version)
|
|
);
|
|
create table public.strategy_nodes (
|
|
id uuid primary key default gen_random_uuid(),
|
|
agent_id uuid references public.agents(id),
|
|
node_type text,
|
|
title text,
|
|
body text,
|
|
rank integer,
|
|
status text not null default 'active',
|
|
horizon text,
|
|
measure text,
|
|
source_ref text,
|
|
metadata jsonb not null default '{{}}',
|
|
created_at timestamptz not null default now(),
|
|
updated_at timestamptz not null default now()
|
|
);
|
|
create table public.strategy_node_anchors (
|
|
id uuid primary key default gen_random_uuid(),
|
|
from_node_id uuid not null references public.strategy_nodes(id) on delete cascade,
|
|
anchor_role text not null,
|
|
to_node_id uuid references public.strategy_nodes(id) on delete cascade,
|
|
to_shared_root_id uuid,
|
|
belief_id uuid,
|
|
claim_id uuid,
|
|
source_id uuid,
|
|
weight numeric,
|
|
note text,
|
|
created_at timestamptz not null default now(),
|
|
check (num_nonnulls(to_node_id, to_shared_root_id, belief_id, claim_id, source_id) = 1)
|
|
);
|
|
create table kb_stage.kb_proposals (
|
|
id uuid primary key,
|
|
proposal_type text not null,
|
|
status text not null,
|
|
proposed_by_handle text,
|
|
proposed_by_agent_id uuid references public.agents(id),
|
|
channel text,
|
|
source_ref text,
|
|
rationale text,
|
|
payload jsonb not null,
|
|
reviewed_by_handle text,
|
|
reviewed_by_agent_id uuid references public.agents(id),
|
|
reviewed_at timestamptz,
|
|
review_note text,
|
|
applied_by_handle text,
|
|
applied_by_agent_id uuid references public.agents(id),
|
|
applied_at timestamptz,
|
|
created_at timestamptz not null default now(),
|
|
updated_at timestamptz not null default now()
|
|
);
|
|
|
|
insert into public.agents (id, handle, kind) values
|
|
('{REVIEWER_ID}', 'm3ta', 'human'),
|
|
('{OTHER_AGENT_ID}', 'other-agent', 'system');
|
|
insert into public.claims (id, type, text, status, confidence, tags, created_by) values
|
|
('{CLAIM_A}', 'structural', 'Fixture claim A', 'open', 0.8, array['fixture'], '{REVIEWER_ID}'),
|
|
('{CLAIM_B}', 'structural', 'Fixture claim B', 'open', 0.8, array['fixture'], '{REVIEWER_ID}');
|
|
insert into public.strategies
|
|
(id, agent_id, diagnosis, guiding_policy, proximate_objectives, version, active, created_at)
|
|
values
|
|
('{PRIOR_STRATEGY_ID}', '{REVIEWER_ID}', 'Prior diagnosis', 'Prior policy', '["prior"]', 1, true,
|
|
'2026-07-01T00:00:00+00:00'),
|
|
('{OTHER_STRATEGY_ID}', '{OTHER_AGENT_ID}', 'Other diagnosis', 'Other policy', '["other"]', 1, true,
|
|
'2026-07-01T00:00:00+00:00');
|
|
insert into public.strategy_nodes
|
|
(id, agent_id, node_type, title, body, rank, status, created_at, updated_at)
|
|
values
|
|
('{PRIOR_ACTIVE_NODE_ID}', '{REVIEWER_ID}', 'policy', 'Prior active', 'Retire exactly once', 1,
|
|
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00'),
|
|
('{PRIOR_RETIRED_NODE_ID}', '{REVIEWER_ID}', 'policy', 'Prior retired', 'Leave timestamp unchanged', 2,
|
|
'retired', '2026-06-01T00:00:00+00:00', '2026-06-02T00:00:00+00:00'),
|
|
('{OTHER_ACTIVE_NODE_ID}', '{OTHER_AGENT_ID}', 'policy', 'Other active', 'Leave other agent unchanged', 1,
|
|
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00'),
|
|
('{NULL_AGENT_NODE_ID}', null, 'policy', 'Shared active', 'Leave shared node unchanged', 1,
|
|
'active', '2026-07-01T00:00:00+00:00', '2026-07-01T00:00:00+00:00');
|
|
insert into public.strategy_node_anchors
|
|
(id, from_node_id, anchor_role, to_node_id, weight, note, created_at)
|
|
values
|
|
('{PRIOR_NODE_ANCHOR_ID}', '{PRIOR_ACTIVE_NODE_ID}', 'serves', '{PRIOR_RETIRED_NODE_ID}', 1.0,
|
|
'Existing anchor must survive strategy revision replay', '2026-07-01T00:00:00+00:00');
|
|
"""
|
|
|
|
|
|
def docker_psql(
|
|
container: str,
|
|
database: str,
|
|
sql: str,
|
|
*,
|
|
role: str = "postgres",
|
|
check: bool = True,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
completed = subprocess.run(
|
|
[
|
|
"docker",
|
|
"exec",
|
|
"-i",
|
|
container,
|
|
"psql",
|
|
"-X",
|
|
"-U",
|
|
role,
|
|
"-h",
|
|
"127.0.0.1",
|
|
"-d",
|
|
database,
|
|
"-Atq",
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
],
|
|
input=sql,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if check and completed.returncode != 0:
|
|
pytest.fail(
|
|
f"fixture psql failed ({completed.returncode})\nstdout:\n{completed.stdout}\nstderr:\n{completed.stderr}"
|
|
)
|
|
return completed
|
|
|
|
|
|
def wait_for_postgres(container: str, database: str) -> None:
|
|
for _ in range(120):
|
|
completed = docker_psql(container, database, "select 1;", check=False)
|
|
if completed.returncode == 0:
|
|
return
|
|
time.sleep(0.25)
|
|
pytest.fail("fixture PostgreSQL did not become ready")
|
|
|
|
|
|
def capture_manifest(container: str, database: str, destination: Path) -> None:
|
|
copy_result = subprocess.run(
|
|
["docker", "cp", str(rebuild.PARITY_SQL_PATH), f"{container}:/tmp/parity.sql"],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if copy_result.returncode != 0:
|
|
pytest.fail(f"could not copy parity SQL: {copy_result.stderr}")
|
|
completed = subprocess.run(
|
|
[
|
|
"docker",
|
|
"exec",
|
|
container,
|
|
"psql",
|
|
"-X",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
database,
|
|
"-Atq",
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
"-f",
|
|
"/tmp/parity.sql",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if completed.returncode != 0:
|
|
pytest.fail(f"could not capture parity manifest: {completed.stderr}")
|
|
destination.write_text(completed.stdout, encoding="utf-8")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def source_postgres() -> Iterator[tuple[str, str]]:
|
|
if shutil.which("docker") is None:
|
|
pytest.skip("Docker is required for the genesis-plus-ledger lifecycle test")
|
|
container = f"genesis-ledger-source-{uuid.uuid4().hex[:12]}"
|
|
database = "teleo_fixture"
|
|
started = subprocess.run(
|
|
[
|
|
"docker",
|
|
"run",
|
|
"--rm",
|
|
"--detach",
|
|
"--network",
|
|
"none",
|
|
"--name",
|
|
container,
|
|
"--label",
|
|
f"{rebuild.canonical_rebuild.CANARY_LABEL}={container}",
|
|
"--env",
|
|
f"POSTGRES_DB={database}",
|
|
"--env",
|
|
"POSTGRES_HOST_AUTH_METHOD=trust",
|
|
rebuild.DEFAULT_REBUILD_IMAGE,
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if started.returncode != 0:
|
|
pytest.fail(f"could not start fixture PostgreSQL: {started.stderr}")
|
|
try:
|
|
wait_for_postgres(container, database)
|
|
docker_psql(container, database, BOOTSTRAP_SQL)
|
|
copy_result = subprocess.run(
|
|
[
|
|
"docker",
|
|
"cp",
|
|
str(rebuild.GUARD_PREREQUISITES_PATH),
|
|
f"{container}:/tmp/kb-apply-prereqs.sql",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if copy_result.returncode != 0:
|
|
pytest.fail(f"could not copy apply prerequisites: {copy_result.stderr}")
|
|
migration = subprocess.run(
|
|
[
|
|
"docker",
|
|
"exec",
|
|
container,
|
|
"psql",
|
|
"-X",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
database,
|
|
"-Atq",
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
"-f",
|
|
"/tmp/kb-apply-prereqs.sql",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if migration.returncode != 0:
|
|
pytest.fail(f"could not apply guarded prerequisites: {migration.stderr}")
|
|
yield container, database
|
|
finally:
|
|
subprocess.run(
|
|
["docker", "rm", "--force", container],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
inspected = subprocess.run(
|
|
["docker", "container", "inspect", container],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if inspected.returncode == 0:
|
|
pytest.fail(f"fixture PostgreSQL container was not removed: {container}")
|
|
|
|
|
|
def capture_source_snapshot(
|
|
source_container: str,
|
|
database: str,
|
|
tmp_path: Path,
|
|
*,
|
|
stem: str,
|
|
) -> tuple[Path, Path]:
|
|
dump = tmp_path / f"{stem}.dump"
|
|
dump_result = subprocess.run(
|
|
[
|
|
"docker",
|
|
"exec",
|
|
source_container,
|
|
"pg_dump",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
database,
|
|
"--format=custom",
|
|
f"--file=/tmp/{stem}.dump",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert dump_result.returncode == 0, dump_result.stderr
|
|
copy_result = subprocess.run(
|
|
["docker", "cp", f"{source_container}:/tmp/{stem}.dump", str(dump)],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert copy_result.returncode == 0, copy_result.stderr
|
|
manifest = tmp_path / f"{stem}-manifest.jsonl"
|
|
capture_manifest(source_container, database, manifest)
|
|
return dump, manifest
|
|
|
|
|
|
def seed_proposal_and_approval(
|
|
source_container: str,
|
|
database: str,
|
|
approved: dict,
|
|
approval: dict,
|
|
) -> dict:
|
|
sql = f"""begin;
|
|
set local standard_conforming_strings = on;
|
|
insert into kb_stage.kb_proposals
|
|
select seeded.* from jsonb_populate_record(
|
|
null::kb_stage.kb_proposals, {rebuild._jsonb_literal(approved)}
|
|
) seeded;
|
|
insert into kb_stage.kb_proposal_approvals
|
|
select seeded.* from jsonb_populate_record(
|
|
null::kb_stage.kb_proposal_approvals, {rebuild._jsonb_literal(approval)}
|
|
) seeded;
|
|
commit;
|
|
"""
|
|
docker_psql(source_container, database, sql)
|
|
raw = docker_psql(
|
|
source_container,
|
|
database,
|
|
rebuild.build_proposal_readback_sql(approved["id"]),
|
|
).stdout.strip()
|
|
return json.loads(raw)
|
|
|
|
|
|
def run_genesis_ledger_command(
|
|
*,
|
|
tmp_path: Path,
|
|
database: str,
|
|
genesis_dump: Path,
|
|
genesis_manifest: Path,
|
|
material_path: Path,
|
|
final_manifest: Path,
|
|
artifact_stem: str,
|
|
container_prefix: str,
|
|
run_number: int,
|
|
) -> tuple[subprocess.CompletedProcess[str], dict, Path]:
|
|
ledger = {
|
|
"artifact": rebuild.LEDGER_ARTIFACT,
|
|
"contract_version": rebuild.LEDGER_CONTRACT_VERSION,
|
|
"engine": rebuild._engine_hashes(),
|
|
"genesis": {
|
|
"dump_sha256": sha256_file(genesis_dump),
|
|
"parity_manifest_sha256": sha256_file(genesis_manifest),
|
|
},
|
|
"entries": [
|
|
{
|
|
"sequence": 1,
|
|
"material": material_path.name,
|
|
"sha256": sha256_file(material_path),
|
|
"replay_material_sha256": json.loads(material_path.read_text(encoding="utf-8"))["replay_receipt"][
|
|
"hashes"
|
|
]["replay_material_sha256"],
|
|
}
|
|
],
|
|
"final_parity": {
|
|
"manifest": final_manifest.name,
|
|
"sha256": sha256_file(final_manifest),
|
|
},
|
|
}
|
|
ledger_path = write_json(tmp_path / f"{artifact_stem}-ledger-run-{run_number}.json", ledger)
|
|
output = tmp_path / f"{artifact_stem}-reconstruction-receipt-run-{run_number}.json"
|
|
command = [
|
|
sys.executable,
|
|
str(Path(rebuild.__file__).resolve()),
|
|
"--genesis-dump",
|
|
str(genesis_dump),
|
|
"--genesis-manifest",
|
|
str(genesis_manifest),
|
|
"--ledger",
|
|
str(ledger_path),
|
|
"--ledger-sha256",
|
|
sha256_file(ledger_path),
|
|
"--database",
|
|
database,
|
|
"--container-prefix",
|
|
container_prefix,
|
|
"--tmpfs-mb",
|
|
"256",
|
|
"--max-target-query-ms",
|
|
"5000",
|
|
"--max-target-source-ratio",
|
|
"100",
|
|
"--output",
|
|
str(output),
|
|
]
|
|
completed = subprocess.run(
|
|
command,
|
|
cwd=rebuild.REPO_ROOT,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
timeout=180,
|
|
)
|
|
assert completed.returncode == 0, completed.stderr + completed.stdout
|
|
assert output.is_file(), "rebuild command succeeded without writing its receipt"
|
|
receipt = json.loads(output.read_text(encoding="utf-8"))
|
|
return completed, receipt, output
|
|
|
|
|
|
def test_live_genesis_plus_ledger_command_rebuilds_exactly_and_proves_cleanup(
|
|
tmp_path: Path,
|
|
source_postgres: tuple[str, str],
|
|
) -> None:
|
|
source_container, database = source_postgres
|
|
genesis_dump, genesis_manifest = capture_source_snapshot(
|
|
source_container,
|
|
database,
|
|
tmp_path,
|
|
stem="insert-only-genesis",
|
|
)
|
|
|
|
material = replay_material()
|
|
material_path = write_json(tmp_path / "entry-0001.json", material)
|
|
entry = rebuild._validate_entry_material(
|
|
material,
|
|
expected_sequence=1,
|
|
expected_replay_hash=material["replay_receipt"]["hashes"]["replay_material_sha256"],
|
|
material_path=material_path,
|
|
material_sha256=sha256_file(material_path),
|
|
)
|
|
docker_psql(source_container, database, rebuild.build_seed_sql(entry))
|
|
docker_psql(
|
|
source_container,
|
|
database,
|
|
entry.current_apply_sql,
|
|
role="kb_apply",
|
|
)
|
|
docker_psql(
|
|
source_container,
|
|
database,
|
|
rebuild.build_applied_timestamp_normalization_sql(entry),
|
|
)
|
|
|
|
final_manifest = tmp_path / "final-manifest.jsonl"
|
|
capture_manifest(source_container, database, final_manifest)
|
|
completed, receipt, output = run_genesis_ledger_command(
|
|
tmp_path=tmp_path,
|
|
database=database,
|
|
genesis_dump=genesis_dump,
|
|
genesis_manifest=genesis_manifest,
|
|
material_path=material_path,
|
|
final_manifest=final_manifest,
|
|
artifact_stem="insert-only",
|
|
container_prefix="teleo-genesis-ledger-live-test",
|
|
run_number=1,
|
|
)
|
|
|
|
assert receipt["status"] == "pass"
|
|
assert receipt["genesis_parity"]["status"] == "pass"
|
|
assert receipt["ledger"]["entries"][0]["status"] == "pass"
|
|
assert receipt["ledger"]["entries"][0]["guarded_apply_executed"] is True
|
|
assert receipt["ledger"]["entries"][0]["canonical_rows_exact"] is True
|
|
assert receipt["final_parity"]["status"] == "pass"
|
|
assert receipt["cleanup"]["container_absent"] is True
|
|
assert receipt["safety"]["network_access_available_to_container"] is False
|
|
assert receipt["safety"]["private_replay_material_emitted"] is False
|
|
assert PRIVATE_MARKER not in completed.stdout
|
|
assert PRIVATE_MARKER not in output.read_text(encoding="utf-8")
|
|
assert stat.S_IMODE(output.stat().st_mode) == 0o600
|
|
|
|
inspect = subprocess.run(
|
|
["docker", "container", "inspect", receipt["container"]["name"]],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert inspect.returncode != 0
|
|
|
|
|
|
def test_live_revise_strategy_rebuild_is_exact_repeatable_and_leaves_no_container(
|
|
tmp_path: Path,
|
|
source_postgres: tuple[str, str],
|
|
) -> None:
|
|
source_container, database = source_postgres
|
|
genesis_dump, genesis_manifest = capture_source_snapshot(
|
|
source_container,
|
|
database,
|
|
tmp_path,
|
|
stem="revise-strategy-genesis",
|
|
)
|
|
|
|
approved, _, approval = revise_strategy_proposal_rows()
|
|
pre_apply = seed_proposal_and_approval(
|
|
source_container,
|
|
database,
|
|
approved,
|
|
approval,
|
|
)
|
|
apply_sql = rebuild.apply_engine.build_apply_sql(pre_apply["proposal"], "kb-apply")
|
|
docker_psql(source_container, database, apply_sql, role="kb_apply")
|
|
post_apply = json.loads(
|
|
docker_psql(
|
|
source_container,
|
|
database,
|
|
rebuild.build_proposal_readback_sql(REVISE_PROPOSAL_ID),
|
|
).stdout.strip()
|
|
)
|
|
applied_proposal = post_apply["proposal"]
|
|
proposal_envelope = applied_envelope(applied_proposal)
|
|
source_receipt_path, receipt = rebuild.apply_engine.capture_replay_receipt(
|
|
argparse.Namespace(
|
|
container=source_container,
|
|
role="kb_apply",
|
|
host="127.0.0.1",
|
|
db=database,
|
|
receipt_out=str(tmp_path / "source-revise-strategy-private-receipt.json"),
|
|
receipt_dir=None,
|
|
),
|
|
proposal_envelope,
|
|
"",
|
|
apply_sql=apply_sql,
|
|
)
|
|
assert source_receipt_path.is_file()
|
|
assert stat.S_IMODE(source_receipt_path.stat().st_mode) == 0o600
|
|
material = {
|
|
"artifact": rebuild.MATERIAL_ARTIFACT,
|
|
"contract_version": rebuild.MATERIAL_CONTRACT_VERSION,
|
|
"sequence": 1,
|
|
"approved_proposal": pre_apply["proposal"],
|
|
"approval_snapshot": pre_apply["approval_snapshot"],
|
|
"applied_proposal": applied_proposal,
|
|
"replay_receipt": receipt,
|
|
}
|
|
material_path = write_json(tmp_path / "revise-strategy-entry-0001.json", material)
|
|
final_manifest = tmp_path / "revise-strategy-final-manifest.jsonl"
|
|
capture_manifest(source_container, database, final_manifest)
|
|
|
|
runs = [
|
|
run_genesis_ledger_command(
|
|
tmp_path=tmp_path,
|
|
database=database,
|
|
genesis_dump=genesis_dump,
|
|
genesis_manifest=genesis_manifest,
|
|
material_path=material_path,
|
|
final_manifest=final_manifest,
|
|
artifact_stem="revise-strategy",
|
|
container_prefix="teleo-genesis-ledger-revise",
|
|
run_number=run_number,
|
|
)
|
|
for run_number in (1, 2)
|
|
]
|
|
|
|
for completed, reconstruction, output in runs:
|
|
assert reconstruction["status"] == "pass"
|
|
assert reconstruction["genesis_parity"]["status"] == "pass"
|
|
assert reconstruction["final_parity"]["status"] == "pass"
|
|
entry_summary = reconstruction["ledger"]["entries"][0]
|
|
assert entry_summary["proposal_type"] == "revise_strategy"
|
|
assert entry_summary["proposal_seed_exact"] is True
|
|
assert entry_summary["canonical_seed_exact"] is False
|
|
assert entry_summary["seed_exact"] is False
|
|
assert entry_summary["guarded_apply_executed"] is True
|
|
assert entry_summary["mutating_prestate_captured"] is True
|
|
assert entry_summary["mutating_delta_validated"] is True
|
|
assert entry_summary["mutating_poststate_normalized"] is True
|
|
assert entry_summary["proposal_exact"] is True
|
|
assert entry_summary["canonical_rows_exact"] is True
|
|
assert reconstruction["cleanup"]["container_absent"] is True
|
|
assert reconstruction["safety"]["network_access_available_to_container"] is False
|
|
assert reconstruction["safety"]["private_replay_material_emitted"] is False
|
|
assert PRIVATE_MARKER not in completed.stdout
|
|
assert PRIVATE_MARKER not in output.read_text(encoding="utf-8")
|
|
assert stat.S_IMODE(output.stat().st_mode) == 0o600
|
|
|
|
container_name = reconstruction["container"]["name"]
|
|
inspect = subprocess.run(
|
|
["docker", "container", "inspect", container_name],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert inspect.returncode != 0
|
|
labeled = subprocess.run(
|
|
[
|
|
"docker",
|
|
"ps",
|
|
"-aq",
|
|
"--filter",
|
|
f"label={rebuild.canonical_rebuild.CANARY_LABEL}={container_name}",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert labeled.returncode == 0
|
|
assert labeled.stdout.strip() == ""
|
|
|
|
first = runs[0][1]
|
|
second = runs[1][1]
|
|
assert first["inputs"] == second["inputs"]
|
|
assert first["ledger"]["entries"][0]["material_sha256"] == second["ledger"]["entries"][0]["material_sha256"]
|
|
assert (
|
|
first["ledger"]["entries"][0]["replay_material_sha256"]
|
|
== second["ledger"]["entries"][0]["replay_material_sha256"]
|
|
)
|