2423 lines
107 KiB
Python
2423 lines
107 KiB
Python
#!/usr/bin/env python3
|
|
"""Run a real source -> review -> apply -> recompile lifecycle in disposable Postgres.
|
|
|
|
The harness composes the repository's existing source compiler, normalized
|
|
proposal staging, review packet, guarded approval, guarded apply, and replay
|
|
receipt surfaces. It starts its own networkless tmpfs Postgres container and
|
|
never accepts an existing database target, so the explicit review/apply actions
|
|
cannot reach VPS, GCP, or another persistent database.
|
|
|
|
The source packet must contain:
|
|
|
|
* ``prepared/extracted-text.txt``
|
|
* ``prepared/source-manifest.json``
|
|
* ``proposal-packet.json``
|
|
|
|
The extracted text is used as both the hash-bound source artifact and its strict
|
|
UTF-8 extraction. ``proposal-packet.json`` is an independently retained
|
|
compiler expectation: the harness refuses to continue unless a fresh compile
|
|
matches it byte-for-byte under canonical JSON.
|
|
|
|
When every ``--genesis-*`` input is supplied, the harness copies every input
|
|
and execution engine into one private read-only staging directory. Before
|
|
Docker it validates the genesis against a repository-pinned trusted exporter
|
|
receipt/source identity and binds the executing commit and engine hashes. It
|
|
then restores and manifest-proves the real genesis without synthetic canonical
|
|
bootstrap or preseed and runs the gated apply worker lifecycle twice. The
|
|
detailed receipt is private mode 0600; stdout is sanitized.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
import secrets
|
|
import shutil
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
import uuid
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
REPO_ROOT = HERE.parent
|
|
OPS_DIR = REPO_ROOT / "ops"
|
|
sys.path.insert(0, str(HERE))
|
|
sys.path.insert(0, str(OPS_DIR))
|
|
|
|
import apply_proposal as ap # noqa: E402
|
|
import capture_vps_canonical_postgres_snapshot as snapshot_capture # noqa: E402
|
|
import compile_kb_source_packet as compiler # noqa: E402
|
|
import kb_proposal_review_packet as review_packets # noqa: E402
|
|
import proposal_apply_lifecycle as apply_lifecycle # noqa: E402
|
|
import run_local_canonical_postgres_rebuild as canonical_rebuild # noqa: E402
|
|
import stage_normalized_proposal as stage # noqa: E402
|
|
from private_receipt_io import print_private_receipt_summary, write_private_json # noqa: E402
|
|
from verify_postgres_parity_manifest import load_manifest # noqa: E402
|
|
|
|
RECEIPT_SCHEMA = "livingip.leoIntegratedLearningLifecycleReceipt.v1"
|
|
GENESIS_RECEIPT_SCHEMA = "livingip.leoGenesisIntegratedLearningLifecycleReceipt.v1"
|
|
GENESIS_RECEIPT_ARTIFACT = "leo_genesis_integrated_learning_lifecycle"
|
|
CONTAINER_LABEL = "livingip.canary=leo-integrated-learning-lifecycle"
|
|
DATABASE = "teleo"
|
|
REVIEWER_HANDLE = "m3taversal"
|
|
REVIEWER_ID = "11111111-1111-4111-8111-111111111111"
|
|
DEFAULT_REVIEW_NOTE = (
|
|
"Approved the exact hash-bound candidate rows for this disposable integrated-learning lifecycle only."
|
|
)
|
|
POSTGRES_IMAGE = os.environ.get("LEOCLEAN_RUNTIME_POSTGRES_IMAGE", "postgres:16-alpine")
|
|
DEFAULT_GENESIS_IMAGE = (
|
|
"docker.io/library/postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777"
|
|
)
|
|
SHA256_RE = re.compile(r"[0-9a-f]{64}\Z")
|
|
IMAGE_DIGEST_RE = re.compile(r"\S+@sha256:[0-9a-f]{64}\Z")
|
|
PARITY_SQL_PATH = OPS_DIR / "postgres_parity_manifest.sql"
|
|
GUARD_PREREQUISITES_PATH = HERE / "kb_apply_prereqs.sql"
|
|
GUARD_PREREQUISITES_DESTINATION = "/tmp/kb-apply-prereqs.sql"
|
|
GENESIS_REPEAT_COUNT = 2
|
|
TRUSTED_EXPORTER_ARTIFACT = "vps_canonical_postgres_exported_snapshot"
|
|
TRUSTED_EXPORTER_RECEIPTS: dict[str, dict[str, Any]] = {
|
|
"5e0030179d1ae9568e5619588ec1f10f573893eb036a15ce6a98e232a30de92b": {
|
|
"run_id": "canonical-20260715t204305z-final",
|
|
"capture_authorization_ref": "codex-delegation:019f47af-f2cc-7c10-b928-a9283afa2621",
|
|
"source": {
|
|
"ssh_target": "root@77.42.65.182",
|
|
"container": "teleo-pg",
|
|
"database": "teleo",
|
|
"service": "leoclean-gateway.service",
|
|
},
|
|
"dump_sha256": "64eea334a3515a83d405e27b08c65891080afc7f2d051bbd198f07f2ccfabf3b",
|
|
"manifest_sha256": "ef04591b295d1a49e6baf6ee71a6b98f854916add9a2d3869c6ddbed1c8cef9b",
|
|
"manifest_sql_sha256": "67c287169394758df58fcab15103f5a9f9b185d266af82c35a3c2bc87aa79095",
|
|
"provenance_binding_sha256": "2442ea51b4048aedd5b370d840ee04745c21742525a6b2b950e58468d1d5bd08",
|
|
}
|
|
}
|
|
ENGINE_INPUT_PATHS = {
|
|
"engine.runner": HERE / "run_leo_integrated_learning_lifecycle.py",
|
|
"engine.apply_worker": HERE / "apply_worker.py",
|
|
"engine.apply_proposal": HERE / "apply_proposal.py",
|
|
"engine.approve_proposal": HERE / "approve_proposal.py",
|
|
"engine.apply_lifecycle": HERE / "proposal_apply_lifecycle.py",
|
|
"engine.apply_receipt": HERE / "kb_apply_replay_receipt.py",
|
|
"engine.compiler": HERE / "compile_kb_source_packet.py",
|
|
"engine.stage": HERE / "stage_normalized_proposal.py",
|
|
"engine.proposal_normalizer": HERE / "kb_proposal_normalize.py",
|
|
"engine.rich_proposal_plan": HERE / "kb_rich_proposal_creation_plan.py",
|
|
"engine.clone_checkpoint": HERE / "run_leo_clone_bound_handler_checkpoint.py",
|
|
"engine.review_packet": HERE / "kb_proposal_review_packet.py",
|
|
"engine.guard_sql": GUARD_PREREQUISITES_PATH,
|
|
"engine.canonical_rebuild": OPS_DIR / "run_local_canonical_postgres_rebuild.py",
|
|
"engine.parity_verifier": OPS_DIR / "verify_postgres_parity_manifest.py",
|
|
"engine.parity_sql": PARITY_SQL_PATH,
|
|
"engine.private_receipt": OPS_DIR / "private_receipt_io.py",
|
|
"engine.snapshot_exporter": OPS_DIR / "capture_vps_canonical_postgres_snapshot.py",
|
|
}
|
|
STAGED_ENGINE_DESTINATIONS = {
|
|
"engine.apply_worker": Path("engine/scripts/apply_worker.py"),
|
|
"engine.apply_proposal": Path("engine/scripts/apply_proposal.py"),
|
|
"engine.approve_proposal": Path("engine/scripts/approve_proposal.py"),
|
|
"engine.apply_lifecycle": Path("engine/scripts/proposal_apply_lifecycle.py"),
|
|
"engine.apply_receipt": Path("engine/scripts/kb_apply_replay_receipt.py"),
|
|
"engine.guard_sql": Path("engine/scripts/kb_apply_prereqs.sql"),
|
|
"engine.parity_sql": Path("engine/ops/postgres_parity_manifest.sql"),
|
|
}
|
|
PAYLOAD_CONTROLLED_FIELDS: dict[str, tuple[str, ...]] = {
|
|
"claims": ("id", "type", "text", "status", "confidence", "tags", "created_by", "superseded_by"),
|
|
"sources": ("id", "source_type", "url", "storage_path", "excerpt", "hash", "created_by"),
|
|
"claim_evidence": ("claim_id", "source_id", "role", "weight", "created_by"),
|
|
"claim_edges": ("from_claim", "to_claim", "edge_type", "weight", "created_by"),
|
|
"reasoning_tools": ("id", "agent_id", "name", "description", "category"),
|
|
}
|
|
|
|
|
|
class LifecycleError(RuntimeError):
|
|
"""Raised when the isolated lifecycle cannot prove an exact transition."""
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GenesisInputs:
|
|
"""Fully validated, immutable inputs for one direct genesis restore."""
|
|
|
|
dump: Path
|
|
dump_sha256: str
|
|
dump_bytes: int
|
|
manifest_path: Path
|
|
manifest_sha256: str
|
|
manifest_bytes: int
|
|
manifest: dict[str, Any]
|
|
image: str
|
|
exporter_receipt_path: Path
|
|
exporter_receipt_sha256: str
|
|
exporter_receipt: dict[str, Any]
|
|
source_identity: dict[str, str]
|
|
capture_authorization_ref: str
|
|
provenance_binding_sha256: str
|
|
trust_root_receipt_sha256: str
|
|
role_settings_capture_complete: bool
|
|
parity_sql_path: Path
|
|
guard_prerequisites_path: Path
|
|
approve_script_path: Path
|
|
apply_worker_script_path: Path
|
|
apply_script_path: Path
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class StagedLifecycleInputs:
|
|
"""Private read-only byte set consumed by both genesis-backed runs."""
|
|
|
|
root: Path
|
|
source_packet: Path
|
|
genesis_dump: Path
|
|
genesis_manifest: Path
|
|
exporter_receipt: Path
|
|
files: dict[str, dict[str, Any]]
|
|
manifest_sha256: str
|
|
execution: dict[str, Any]
|
|
|
|
|
|
def canonical_json_bytes(value: Any) -> bytes:
|
|
return json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True).encode("utf-8")
|
|
|
|
|
|
def canonical_sha256(value: Any) -> str:
|
|
return hashlib.sha256(canonical_json_bytes(value)).hexdigest()
|
|
|
|
|
|
def sha256_text(value: str) -> str:
|
|
return hashlib.sha256(value.encode("utf-8")).hexdigest()
|
|
|
|
|
|
def sha256_file(path: Path) -> str:
|
|
digest = hashlib.sha256()
|
|
with path.open("rb") as handle:
|
|
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
|
digest.update(chunk)
|
|
return digest.hexdigest()
|
|
|
|
|
|
def absolute_path_value_pointers(value: Any, pointer: str = "$") -> list[str]:
|
|
"""Return receipt locations that expose host-specific absolute paths."""
|
|
if isinstance(value, dict):
|
|
paths: list[str] = []
|
|
for key, child in value.items():
|
|
paths.extend(absolute_path_value_pointers(child, f"{pointer}.{key}"))
|
|
return paths
|
|
if isinstance(value, list):
|
|
paths = []
|
|
for index, child in enumerate(value):
|
|
paths.extend(absolute_path_value_pointers(child, f"{pointer}[{index}]"))
|
|
return paths
|
|
if isinstance(value, str) and value.startswith("/"):
|
|
return [pointer]
|
|
return []
|
|
|
|
|
|
def manifest_for_role_replay(manifest: dict[str, Any]) -> dict[str, Any]:
|
|
"""Project legacy role fields for replay without upgrading their parity claim."""
|
|
normalized = json.loads(json.dumps(manifest))
|
|
try:
|
|
role_items = normalized["singleton"]["application_roles"]["items"]
|
|
except (KeyError, TypeError) as exc:
|
|
raise LifecycleError("genesis manifest is missing application role inventory") from exc
|
|
if not isinstance(role_items, list):
|
|
raise LifecycleError("genesis manifest application role inventory is malformed")
|
|
for item in role_items:
|
|
if not isinstance(item, dict):
|
|
raise LifecycleError("genesis manifest application role entry is malformed")
|
|
if "settings" not in item:
|
|
read_only = item.get("default_transaction_read_only")
|
|
item["settings"] = (
|
|
[{"name": "default_transaction_read_only", "value": read_only}] if read_only is not None else []
|
|
)
|
|
item.setdefault("database_settings", [])
|
|
return normalized
|
|
|
|
|
|
def role_settings_capture_complete(manifest: dict[str, Any]) -> bool:
|
|
try:
|
|
items = manifest["singleton"]["application_roles"]["items"]
|
|
except (KeyError, TypeError):
|
|
return False
|
|
return isinstance(items, list) and all(
|
|
isinstance(item, dict)
|
|
and isinstance(item.get("settings"), list)
|
|
and isinstance(item.get("database_settings"), list)
|
|
for item in items
|
|
)
|
|
|
|
|
|
def _regular_non_symlink(path: Path, label: str) -> os.stat_result:
|
|
try:
|
|
result = path.lstat()
|
|
except OSError as exc:
|
|
raise LifecycleError(f"{label} is unavailable: {exc}") from exc
|
|
if not stat.S_ISREG(result.st_mode) or path.is_symlink():
|
|
raise LifecycleError(f"{label} must be a regular non-symlink file")
|
|
return result
|
|
|
|
|
|
def _copy_private_input(source: Path, destination: Path, label: str) -> dict[str, Any]:
|
|
"""Copy one regular file through no-follow descriptors and hash copied bytes."""
|
|
destination.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
|
try:
|
|
source_fd = os.open(source, flags)
|
|
except OSError as exc:
|
|
raise LifecycleError(f"{label} could not be opened safely: {exc}") from exc
|
|
digest = hashlib.sha256()
|
|
byte_count = 0
|
|
try:
|
|
source_stat = os.fstat(source_fd)
|
|
if not stat.S_ISREG(source_stat.st_mode):
|
|
raise LifecycleError(f"{label} must remain a regular file while staging")
|
|
destination_fd = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
|
try:
|
|
while True:
|
|
chunk = os.read(source_fd, 1024 * 1024)
|
|
if not chunk:
|
|
break
|
|
digest.update(chunk)
|
|
byte_count += len(chunk)
|
|
view = memoryview(chunk)
|
|
while view:
|
|
written = os.write(destination_fd, view)
|
|
view = view[written:]
|
|
os.fsync(destination_fd)
|
|
finally:
|
|
os.close(destination_fd)
|
|
finally:
|
|
os.close(source_fd)
|
|
destination.chmod(0o400)
|
|
return {
|
|
"relative_path": str(destination),
|
|
"bytes": byte_count,
|
|
"sha256": digest.hexdigest(),
|
|
"mode": "0400",
|
|
}
|
|
|
|
|
|
def execution_identity() -> dict[str, Any]:
|
|
engine_relpaths = {
|
|
logical_name: str(path.relative_to(REPO_ROOT)) for logical_name, path in sorted(ENGINE_INPUT_PATHS.items())
|
|
}
|
|
head = run_tool(
|
|
["git", "-C", str(REPO_ROOT), "rev-parse", "HEAD"],
|
|
action="executing Git commit readback",
|
|
).stdout.strip()
|
|
if not re.fullmatch(r"[0-9a-f]{40}", head):
|
|
raise LifecycleError("executing Git commit readback was malformed")
|
|
|
|
head_sha256: dict[str, str] = {}
|
|
for logical_name, relative_path in engine_relpaths.items():
|
|
source = ENGINE_INPUT_PATHS[logical_name]
|
|
_regular_non_symlink(source, logical_name)
|
|
committed = subprocess.run(
|
|
["git", "-C", str(REPO_ROOT), "show", f"{head}:{relative_path}"],
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if committed.returncode != 0:
|
|
raise LifecycleError(f"executing engine dependency is not tracked at {head}: {relative_path}")
|
|
current_bytes = source.read_bytes()
|
|
if current_bytes != committed.stdout:
|
|
raise LifecycleError(f"executing engine dependency does not match {head}: {relative_path}")
|
|
head_sha256[logical_name] = hashlib.sha256(committed.stdout).hexdigest()
|
|
|
|
return {
|
|
"git_head": head,
|
|
"engine_paths_match_head": True,
|
|
"engine_relpaths": sorted(engine_relpaths.values()),
|
|
"engine_head_sha256": head_sha256,
|
|
}
|
|
|
|
|
|
def stage_lifecycle_inputs(
|
|
source_packet: Path,
|
|
genesis_dump: Path,
|
|
genesis_manifest: Path,
|
|
genesis_exporter_receipt: Path,
|
|
) -> StagedLifecycleInputs:
|
|
"""Copy every external input and subprocess engine into one private byte set."""
|
|
source_packet = source_packet.expanduser().resolve()
|
|
sources: dict[str, tuple[Path, Path]] = {
|
|
"genesis.dump": (genesis_dump.expanduser().resolve(), Path("inputs/genesis/teleo-canonical.dump")),
|
|
"genesis.manifest": (
|
|
genesis_manifest.expanduser().resolve(),
|
|
Path("inputs/genesis/source-manifest.jsonl"),
|
|
),
|
|
"genesis.exporter_receipt": (
|
|
genesis_exporter_receipt.expanduser().resolve(),
|
|
Path("inputs/genesis/exporter-receipt.json"),
|
|
),
|
|
"source.extracted_text": (
|
|
source_packet / "prepared" / "extracted-text.txt",
|
|
Path("inputs/source-packet/prepared/extracted-text.txt"),
|
|
),
|
|
"source.manifest": (
|
|
source_packet / "prepared" / "source-manifest.json",
|
|
Path("inputs/source-packet/prepared/source-manifest.json"),
|
|
),
|
|
"source.proposal_packet": (
|
|
source_packet / "proposal-packet.json",
|
|
Path("inputs/source-packet/proposal-packet.json"),
|
|
),
|
|
}
|
|
for logical_name, source in ENGINE_INPUT_PATHS.items():
|
|
destination = STAGED_ENGINE_DESTINATIONS.get(
|
|
logical_name,
|
|
Path("engine/bound") / f"{logical_name.replace('.', '__')}--{source.name}",
|
|
)
|
|
sources[logical_name] = (source, destination)
|
|
|
|
for logical_name, (source, _destination) in sources.items():
|
|
_regular_non_symlink(source, logical_name)
|
|
|
|
root = Path(tempfile.mkdtemp(prefix="leo-genesis-immutable-stage-"))
|
|
root.chmod(0o700)
|
|
files: dict[str, dict[str, Any]] = {}
|
|
try:
|
|
for logical_name, (source, relative_destination) in sorted(sources.items()):
|
|
destination = root / relative_destination
|
|
evidence = _copy_private_input(source, destination, logical_name)
|
|
evidence["relative_path"] = str(relative_destination)
|
|
files[logical_name] = evidence
|
|
execution = execution_identity()
|
|
staged_engine_sha256 = {
|
|
logical_name: files[logical_name]["sha256"] for logical_name in sorted(ENGINE_INPUT_PATHS)
|
|
}
|
|
if staged_engine_sha256 != execution["engine_head_sha256"]:
|
|
raise LifecycleError("staged engine dependency bytes do not match the executing Git commit")
|
|
manifest_payload = {
|
|
"schema": "livingip.leoImmutableLifecycleInputs.v1",
|
|
"execution": execution,
|
|
"files": files,
|
|
}
|
|
manifest_sha256 = canonical_sha256(manifest_payload)
|
|
for directory in sorted((path for path in root.rglob("*") if path.is_dir()), reverse=True):
|
|
directory.chmod(0o500)
|
|
root.chmod(0o500)
|
|
staged = StagedLifecycleInputs(
|
|
root=root,
|
|
source_packet=root / "inputs/source-packet",
|
|
genesis_dump=root / "inputs/genesis/teleo-canonical.dump",
|
|
genesis_manifest=root / "inputs/genesis/source-manifest.jsonl",
|
|
exporter_receipt=root / "inputs/genesis/exporter-receipt.json",
|
|
files=files,
|
|
manifest_sha256=manifest_sha256,
|
|
execution=execution,
|
|
)
|
|
verify_staged_inputs(staged)
|
|
return staged
|
|
except Exception:
|
|
cleanup_staged_inputs(root)
|
|
raise
|
|
|
|
|
|
def verify_staged_inputs(staged: StagedLifecycleInputs) -> dict[str, Any]:
|
|
expected_paths = {str(item["relative_path"]) for item in staged.files.values()}
|
|
actual_paths = {
|
|
str(path.relative_to(staged.root)) for path in staged.root.rglob("*") if path.is_file() or path.is_symlink()
|
|
}
|
|
if actual_paths != expected_paths:
|
|
raise LifecycleError("private immutable staging file set drifted")
|
|
observed: dict[str, dict[str, Any]] = {}
|
|
for logical_name, expected in sorted(staged.files.items()):
|
|
path = staged.root / str(expected["relative_path"])
|
|
path_stat = _regular_non_symlink(path, logical_name)
|
|
if stat.S_IMODE(path_stat.st_mode) != 0o400:
|
|
raise LifecycleError(f"private immutable staging mode drifted for {logical_name}")
|
|
observed[logical_name] = {
|
|
"relative_path": str(expected["relative_path"]),
|
|
"bytes": path_stat.st_size,
|
|
"sha256": sha256_file(path),
|
|
"mode": "0400",
|
|
}
|
|
manifest_payload = {
|
|
"schema": "livingip.leoImmutableLifecycleInputs.v1",
|
|
"execution": staged.execution,
|
|
"files": observed,
|
|
}
|
|
observed_manifest_sha256 = canonical_sha256(manifest_payload)
|
|
if observed != staged.files or observed_manifest_sha256 != staged.manifest_sha256:
|
|
raise LifecycleError("private immutable staging bytes drifted from preflight")
|
|
return {
|
|
"manifest_sha256": observed_manifest_sha256,
|
|
"files_sha256": canonical_sha256({name: row["sha256"] for name, row in observed.items()}),
|
|
"file_count": len(observed),
|
|
"all_files_match_preflight": True,
|
|
}
|
|
|
|
|
|
def cleanup_staged_inputs(root: Path | None) -> dict[str, Any]:
|
|
if root is None:
|
|
return {"attempted": False, "root_absent": True}
|
|
if root.exists():
|
|
for path in root.rglob("*"):
|
|
try:
|
|
path.chmod(0o700 if path.is_dir() else 0o600)
|
|
except OSError:
|
|
pass
|
|
try:
|
|
root.chmod(0o700)
|
|
except OSError:
|
|
pass
|
|
shutil.rmtree(root, ignore_errors=True)
|
|
return {"attempted": True, "root_absent": not root.exists()}
|
|
|
|
|
|
def _service_state_healthy(value: Any) -> bool:
|
|
if not isinstance(value, dict):
|
|
return False
|
|
try:
|
|
main_pid = int(value.get("MainPID") or 0)
|
|
restarts = int(value.get("NRestarts") or 0)
|
|
except (TypeError, ValueError):
|
|
return False
|
|
return (
|
|
value.get("ActiveState") == "active" and value.get("SubState") == "running" and main_pid > 0 and restarts >= 0
|
|
)
|
|
|
|
|
|
def validate_genesis_inputs(
|
|
genesis_dump: Path,
|
|
genesis_manifest: Path,
|
|
genesis_exporter_receipt: Path,
|
|
image: str,
|
|
*,
|
|
parity_sql_path: Path = PARITY_SQL_PATH,
|
|
guard_prerequisites_path: Path = GUARD_PREREQUISITES_PATH,
|
|
approve_script_path: Path = HERE / "approve_proposal.py",
|
|
apply_worker_script_path: Path = HERE / "apply_worker.py",
|
|
apply_script_path: Path = HERE / "apply_proposal.py",
|
|
) -> GenesisInputs:
|
|
"""Validate staged genesis bytes against the exporter receipt, without Docker."""
|
|
if not IMAGE_DIGEST_RE.fullmatch(image):
|
|
raise LifecycleError("--image must be pinned by a lowercase sha256 digest")
|
|
dump = genesis_dump.expanduser().resolve()
|
|
manifest_path = genesis_manifest.expanduser().resolve()
|
|
receipt_path = genesis_exporter_receipt.expanduser().resolve()
|
|
if len({dump, manifest_path, receipt_path}) != 3:
|
|
raise LifecycleError("genesis dump, manifest, and exporter receipt must be distinct files")
|
|
_regular_non_symlink(receipt_path, "genesis exporter receipt")
|
|
if receipt_path.stat().st_mode & 0o077:
|
|
raise LifecycleError("genesis exporter receipt permissions must be private")
|
|
try:
|
|
canonical_rebuild.validate_custom_dump(dump)
|
|
except (OSError, ValueError) as exc:
|
|
raise LifecycleError(f"invalid genesis dump: {exc}") from exc
|
|
try:
|
|
exporter_receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
|
if not isinstance(exporter_receipt, dict):
|
|
raise LifecycleError("genesis exporter receipt must contain one JSON object")
|
|
manifest = load_manifest(manifest_path)
|
|
role_manifest = manifest_for_role_replay(manifest)
|
|
canonical_rebuild.application_role_sql(role_manifest, DATABASE)
|
|
except (OSError, UnicodeError, ValueError, KeyError, TypeError, json.JSONDecodeError) as exc:
|
|
raise LifecycleError("genesis exporter receipt or manifest is invalid") from exc
|
|
|
|
dump_sha256 = sha256_file(dump)
|
|
manifest_sha256 = sha256_file(manifest_path)
|
|
exporter_receipt_sha256 = sha256_file(receipt_path)
|
|
trust_root = TRUSTED_EXPORTER_RECEIPTS.get(exporter_receipt_sha256)
|
|
receipt_dump = exporter_receipt.get("dump") or {}
|
|
receipt_manifest = exporter_receipt.get("manifest") or {}
|
|
source = exporter_receipt.get("source") or {}
|
|
snapshot = exporter_receipt.get("snapshot") or {}
|
|
source_context = exporter_receipt.get("source_context") or {}
|
|
source_service = exporter_receipt.get("source_service") or {}
|
|
binding = exporter_receipt.get("provenance_binding") or {}
|
|
authorization_ref = str(exporter_receipt.get("capture_authorization_ref") or "")
|
|
manifest_sql_sha256 = str(receipt_manifest.get("manifest_sql_sha256") or "")
|
|
source_context_sha256 = str(source_context.get("sha256") or "")
|
|
source_identity_valid = (
|
|
isinstance(source, dict)
|
|
and set(source) == {"ssh_target", "container", "database", "service"}
|
|
and all(
|
|
isinstance(value, str) and value and not any(char in value for char in "\r\n\x00")
|
|
for value in source.values()
|
|
)
|
|
)
|
|
expected_binding = snapshot_capture.build_provenance_binding(
|
|
run_id=str(exporter_receipt.get("run_id") or ""),
|
|
authorization_ref=authorization_ref,
|
|
source=source,
|
|
snapshot=snapshot,
|
|
dump_sha256=dump_sha256,
|
|
manifest_sql_sha256=manifest_sql_sha256,
|
|
source_manifest_sha256=manifest_sha256,
|
|
source_context_sha256=source_context_sha256,
|
|
)
|
|
application_roles = manifest["singleton"]["application_roles"].get("items", [])
|
|
table_count = len(manifest["tables"])
|
|
total_rows = sum(int(row["row_count"]) for row in manifest["tables"].values())
|
|
before = source_service.get("before")
|
|
after = source_service.get("after")
|
|
checks = {
|
|
"trusted_exporter_receipt_hash": trust_root is not None,
|
|
"trusted_exporter_run_id": trust_root is not None and exporter_receipt.get("run_id") == trust_root["run_id"],
|
|
"trusted_capture_authorization": trust_root is not None
|
|
and authorization_ref == trust_root["capture_authorization_ref"],
|
|
"trusted_source_identity": trust_root is not None and source == trust_root["source"],
|
|
"trusted_dump_identity": trust_root is not None and dump_sha256 == trust_root["dump_sha256"],
|
|
"trusted_manifest_identity": trust_root is not None and manifest_sha256 == trust_root["manifest_sha256"],
|
|
"trusted_manifest_engine": trust_root is not None and manifest_sql_sha256 == trust_root["manifest_sql_sha256"],
|
|
"trusted_provenance_binding": trust_root is not None
|
|
and binding.get("sha256") == trust_root["provenance_binding_sha256"],
|
|
"artifact": exporter_receipt.get("artifact") == TRUSTED_EXPORTER_ARTIFACT,
|
|
"schema": exporter_receipt.get("schema") == snapshot_capture.SOURCE_SNAPSHOT_RECEIPT_SCHEMA,
|
|
"receipt_version": exporter_receipt.get("receipt_version") == 2,
|
|
"status": exporter_receipt.get("status") == "pass",
|
|
"run_id": bool(exporter_receipt.get("run_id")),
|
|
"capture_authorization_bound": bool(authorization_ref),
|
|
"source_identity_bound": source_identity_valid,
|
|
"snapshot_exported": exporter_receipt.get("snapshot_exported") is True,
|
|
"snapshot_identity_bound": all(
|
|
bool(snapshot.get(field))
|
|
for field in ("captured_at_utc", "exported_snapshot_id", "txid_snapshot", "wal_lsn", "system_identifier")
|
|
),
|
|
"source_service_unchanged": exporter_receipt.get("service_unchanged") is True
|
|
and source_service.get("unchanged") is True
|
|
and before == after
|
|
and _service_state_healthy(before),
|
|
"source_not_mutated": exporter_receipt.get("production_db_mutated") is False,
|
|
"telegram_not_sent": exporter_receipt.get("telegram_send_attempted") is False,
|
|
"dump_hash_from_exporter_receipt": receipt_dump.get("sha256") == dump_sha256,
|
|
"dump_bytes_from_exporter_receipt": receipt_dump.get("bytes") == dump.stat().st_size,
|
|
"manifest_hash_from_exporter_receipt": receipt_manifest.get("sha256") == manifest_sha256,
|
|
"manifest_sql_hash_bound": bool(SHA256_RE.fullmatch(manifest_sql_sha256)),
|
|
"manifest_table_count_bound": receipt_manifest.get("table_count") == table_count,
|
|
"manifest_total_rows_bound": receipt_manifest.get("total_rows") == total_rows,
|
|
"manifest_application_roles_bound": receipt_manifest.get("application_roles") == application_roles,
|
|
"manifest_database_bound": source_identity_valid
|
|
and source.get("database") == manifest["singleton"]["identity"].get("database"),
|
|
"manifest_captured_read_only": manifest["singleton"]["identity"].get("transaction_read_only") == "on",
|
|
"source_context_hash_bound": bool(SHA256_RE.fullmatch(source_context_sha256)),
|
|
"provenance_binding_payload": binding.get("payload") == expected_binding["payload"],
|
|
"provenance_binding_sha256": binding.get("sha256") == expected_binding["sha256"],
|
|
"provenance_binding_algorithm": binding.get("algorithm") == "sha256",
|
|
}
|
|
failed = sorted(name for name, passed in checks.items() if not passed)
|
|
if failed:
|
|
raise LifecycleError("genesis exporter receipt failed validation: " + ", ".join(failed))
|
|
return GenesisInputs(
|
|
dump=dump,
|
|
dump_sha256=dump_sha256,
|
|
dump_bytes=dump.stat().st_size,
|
|
manifest_path=manifest_path,
|
|
manifest_sha256=manifest_sha256,
|
|
manifest_bytes=manifest_path.stat().st_size,
|
|
manifest=manifest,
|
|
image=image,
|
|
exporter_receipt_path=receipt_path,
|
|
exporter_receipt_sha256=exporter_receipt_sha256,
|
|
exporter_receipt=exporter_receipt,
|
|
source_identity={key: str(value) for key, value in source.items()},
|
|
capture_authorization_ref=authorization_ref,
|
|
provenance_binding_sha256=str(binding["sha256"]),
|
|
trust_root_receipt_sha256=exporter_receipt_sha256,
|
|
role_settings_capture_complete=role_settings_capture_complete(manifest),
|
|
parity_sql_path=parity_sql_path,
|
|
guard_prerequisites_path=guard_prerequisites_path,
|
|
approve_script_path=approve_script_path,
|
|
apply_worker_script_path=apply_worker_script_path,
|
|
apply_script_path=apply_script_path,
|
|
)
|
|
|
|
|
|
def payload_controlled_fingerprint(rows: dict[str, list[dict[str, Any]]]) -> dict[str, Any]:
|
|
"""Hash only immutable payload-controlled fields, excluding generated IDs/times."""
|
|
if set(rows) != set(PAYLOAD_CONTROLLED_FIELDS):
|
|
raise LifecycleError("canonical target rows do not contain the exact approve-claim table set")
|
|
projected: dict[str, list[dict[str, Any]]] = {}
|
|
for family, fields in PAYLOAD_CONTROLLED_FIELDS.items():
|
|
family_rows = rows[family]
|
|
if not isinstance(family_rows, list) or any(not isinstance(row, dict) for row in family_rows):
|
|
raise LifecycleError(f"canonical target rows for {family} are malformed")
|
|
projected[family] = sorted(
|
|
({field: row.get(field) for field in fields} for row in family_rows),
|
|
key=canonical_json_bytes,
|
|
)
|
|
return {
|
|
"schema": "livingip.leoPayloadControlledRowsFingerprint.v1",
|
|
"sha256": canonical_sha256(projected),
|
|
"table_sha256": {family: canonical_sha256(family_rows) for family, family_rows in projected.items()},
|
|
"row_counts": _row_counts(projected),
|
|
"rows": projected,
|
|
}
|
|
|
|
|
|
def parse_last_json_line(output: str) -> Any:
|
|
for line in reversed(output.splitlines()):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
try:
|
|
return json.loads(line)
|
|
except json.JSONDecodeError:
|
|
continue
|
|
return None
|
|
|
|
|
|
def _safe_error_text(value: str, *, limit: int = 1200) -> str:
|
|
compact = " ".join(value.split())
|
|
return compact[-limit:]
|
|
|
|
|
|
def command_receipt(result: subprocess.CompletedProcess[str], *, expected_marker: str | None = None) -> dict[str, Any]:
|
|
parsed = parse_last_json_line(result.stdout)
|
|
if isinstance(parsed, dict):
|
|
parsed = {key: value for key, value in parsed.items() if key not in {"receipt_path"}}
|
|
return {
|
|
"returncode": result.returncode,
|
|
"stdout_sha256": sha256_text(result.stdout),
|
|
"stderr_sha256": sha256_text(result.stderr),
|
|
"stdout_json": parsed if isinstance(parsed, dict) else None,
|
|
"expected_marker": expected_marker,
|
|
"expected_marker_present": expected_marker in result.stdout if expected_marker else None,
|
|
}
|
|
|
|
|
|
def run_tool(arguments: list[str], *, action: str) -> subprocess.CompletedProcess[str]:
|
|
result = subprocess.run(arguments, text=True, capture_output=True, check=False)
|
|
if result.returncode != 0:
|
|
detail = _safe_error_text(result.stderr or result.stdout)
|
|
raise LifecycleError(f"{action} failed ({result.returncode}): {detail}")
|
|
return result
|
|
|
|
|
|
class DisposablePostgres:
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
admin_password: str,
|
|
*,
|
|
image: str = POSTGRES_IMAGE,
|
|
genesis_backed: bool = False,
|
|
run_group: str | None = None,
|
|
) -> None:
|
|
self.name = name
|
|
self.admin_password = admin_password
|
|
self.image = image
|
|
self.genesis_backed = genesis_backed
|
|
self.run_group = run_group or uuid.uuid4().hex
|
|
self.docker = shutil.which("docker")
|
|
if not self.docker:
|
|
raise LifecycleError("docker executable is unavailable")
|
|
self.started = False
|
|
self.environment: dict[str, Any] = {}
|
|
|
|
def _run(
|
|
self,
|
|
arguments: list[str],
|
|
*,
|
|
input_text: str | None = None,
|
|
check: bool = True,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
result = subprocess.run(
|
|
[self.docker, *arguments],
|
|
input=input_text,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if check and result.returncode != 0:
|
|
detail = _safe_error_text(result.stderr or result.stdout)
|
|
raise LifecycleError(f"docker {arguments[0]} failed ({result.returncode}): {detail}")
|
|
return result
|
|
|
|
def start(self) -> dict[str, Any]:
|
|
auth_environment = ["-e", f"POSTGRES_PASSWORD={self.admin_password}"]
|
|
result = self._run(
|
|
[
|
|
"run",
|
|
"--rm",
|
|
"-d",
|
|
"--name",
|
|
self.name,
|
|
"--network",
|
|
"none",
|
|
"--label",
|
|
CONTAINER_LABEL,
|
|
"--label",
|
|
f"livingip.canary.instance={self.name}",
|
|
"--label",
|
|
f"livingip.canary.run_group={self.run_group}",
|
|
"--tmpfs",
|
|
"/var/lib/postgresql/data:rw,nosuid,size=384m",
|
|
"-e",
|
|
f"POSTGRES_DB={DATABASE}",
|
|
*auth_environment,
|
|
self.image,
|
|
]
|
|
)
|
|
self.started = True
|
|
deadline = time.monotonic() + 45
|
|
ready_streak = 0
|
|
while time.monotonic() < deadline:
|
|
ready = self._run(
|
|
["exec", self.name, "pg_isready", "-U", "postgres", "-d", DATABASE],
|
|
check=False,
|
|
)
|
|
if ready.returncode == 0:
|
|
ready_streak += 1
|
|
if ready_streak >= 2:
|
|
break
|
|
else:
|
|
ready_streak = 0
|
|
time.sleep(0.25)
|
|
else:
|
|
raise LifecycleError("disposable Postgres did not become stably ready")
|
|
|
|
inspect = json.loads(self._run(["inspect", self.name]).stdout)[0]
|
|
mounts = [
|
|
{
|
|
"type": mount.get("Type"),
|
|
"name": mount.get("Name"),
|
|
"destination": mount.get("Destination"),
|
|
}
|
|
for mount in inspect.get("Mounts", [])
|
|
]
|
|
labels = inspect.get("Config", {}).get("Labels", {})
|
|
self.environment = {
|
|
"container_id": result.stdout.strip(),
|
|
"container_name": self.name,
|
|
"image": inspect.get("Config", {}).get("Image"),
|
|
"image_reference_exact": inspect.get("Config", {}).get("Image") == self.image,
|
|
"image_digest_pinned": bool(IMAGE_DIGEST_RE.fullmatch(self.image)) if self.genesis_backed else None,
|
|
"host_auth_trust_requested": False,
|
|
"network_mode": inspect.get("HostConfig", {}).get("NetworkMode"),
|
|
"tmpfs_data_dir": "/var/lib/postgresql/data" in inspect.get("HostConfig", {}).get("Tmpfs", {}),
|
|
"mounts": mounts,
|
|
"canary_label": labels.get("livingip.canary"),
|
|
"instance_label": labels.get("livingip.canary.instance"),
|
|
"run_group_label": labels.get("livingip.canary.run_group"),
|
|
}
|
|
if self.environment["network_mode"] != "none":
|
|
raise LifecycleError("disposable Postgres is not networkless")
|
|
if not self.environment["tmpfs_data_dir"] or mounts:
|
|
raise LifecycleError("disposable Postgres must use tmpfs without Docker volumes")
|
|
if self.environment["canary_label"] != "leo-integrated-learning-lifecycle":
|
|
raise LifecycleError("disposable Postgres canary label is missing")
|
|
if self.environment["instance_label"] != self.name:
|
|
raise LifecycleError("disposable Postgres instance label is missing")
|
|
if self.environment["run_group_label"] != self.run_group:
|
|
raise LifecycleError("disposable Postgres run-group label is missing")
|
|
if not self.environment["image_reference_exact"]:
|
|
raise LifecycleError("disposable Postgres did not use the exact requested image reference")
|
|
if self.genesis_backed and not self.environment["image_digest_pinned"]:
|
|
raise LifecycleError("genesis-backed Postgres image is not digest pinned")
|
|
return self.environment
|
|
|
|
def psql(self, sql: str) -> str:
|
|
result = self._run(
|
|
[
|
|
"exec",
|
|
"-i",
|
|
self.name,
|
|
"psql",
|
|
"-X",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
DATABASE,
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
"-Atq",
|
|
],
|
|
input_text="set timezone = 'UTC';\n" + sql,
|
|
)
|
|
return result.stdout.strip()
|
|
|
|
def psql_json(self, sql: str) -> Any:
|
|
output = self.psql(sql)
|
|
parsed = parse_last_json_line(output)
|
|
if parsed is None:
|
|
raise LifecycleError("Postgres readback did not contain JSON")
|
|
return parsed
|
|
|
|
def restore_genesis(self, inputs: GenesisInputs) -> dict[str, Any]:
|
|
"""Restore one validated genesis directly and prove its parity manifest."""
|
|
if not self.genesis_backed:
|
|
raise LifecycleError("genesis restore requires a genesis-backed disposable database")
|
|
role_manifest = manifest_for_role_replay(inputs.manifest)
|
|
role_capture_complete = inputs.role_settings_capture_complete
|
|
try:
|
|
application_roles = canonical_rebuild.execute_application_role_bootstrap(
|
|
self.docker,
|
|
self.name,
|
|
DATABASE,
|
|
role_manifest,
|
|
timeout=30.0,
|
|
)
|
|
role_memberships = canonical_rebuild.execute_role_membership_replay(
|
|
self.docker,
|
|
self.name,
|
|
DATABASE,
|
|
role_manifest,
|
|
timeout=30.0,
|
|
)
|
|
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired) as exc:
|
|
raise LifecycleError("manifest-declared application role bootstrap failed") from exc
|
|
|
|
copy_dump = self._run(
|
|
["cp", str(inputs.dump), f"{self.name}:{canonical_rebuild.DUMP_DESTINATION}"],
|
|
)
|
|
restore = self._run(
|
|
[
|
|
"exec",
|
|
self.name,
|
|
"pg_restore",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
DATABASE,
|
|
"--no-owner",
|
|
"--exit-on-error",
|
|
canonical_rebuild.DUMP_DESTINATION,
|
|
]
|
|
)
|
|
try:
|
|
database_acl_statements = canonical_rebuild.execute_database_acl_replay(
|
|
self.docker,
|
|
self.name,
|
|
DATABASE,
|
|
role_manifest,
|
|
timeout=30.0,
|
|
)
|
|
parity = canonical_rebuild.run_parity_check(
|
|
self.docker,
|
|
self.name,
|
|
DATABASE,
|
|
source_manifest_path=inputs.manifest_path,
|
|
source_manifest=role_manifest,
|
|
manifest_sql=inputs.parity_sql_path,
|
|
command_timeout=180.0,
|
|
max_target_query_ms=2000.0,
|
|
max_target_source_ratio=20.0,
|
|
)
|
|
key_counts, schema_table_count = canonical_rebuild.collect_key_counts(
|
|
self.docker,
|
|
self.name,
|
|
DATABASE,
|
|
timeout=30.0,
|
|
)
|
|
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired, json.JSONDecodeError) as exc:
|
|
raise LifecycleError("restored genesis manifest proof could not complete") from exc
|
|
if parity.get("status") != "pass":
|
|
problems = _safe_error_text(json.dumps(parity.get("problems", []), sort_keys=True))
|
|
raise LifecycleError(f"restored genesis does not match the supplied parity manifest: {problems}")
|
|
copy_guards = self._run(
|
|
["cp", str(inputs.guard_prerequisites_path), f"{self.name}:{GUARD_PREREQUISITES_DESTINATION}"],
|
|
)
|
|
install_guards = self._run(
|
|
[
|
|
"exec",
|
|
self.name,
|
|
"psql",
|
|
"-X",
|
|
"-U",
|
|
"postgres",
|
|
"-d",
|
|
DATABASE,
|
|
"-Atq",
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
"-f",
|
|
GUARD_PREREQUISITES_DESTINATION,
|
|
]
|
|
)
|
|
source_manifest = dict(parity["source_manifest"])
|
|
source_manifest.pop("path", None)
|
|
return {
|
|
"dump": {
|
|
"bytes": inputs.dump_bytes,
|
|
"sha256": inputs.dump_sha256,
|
|
"exporter_receipt_binding_verified_before_docker": True,
|
|
"copy_command_stdout_sha256": sha256_text(copy_dump.stdout),
|
|
},
|
|
"manifest": {
|
|
"bytes": inputs.manifest_bytes,
|
|
"sha256": inputs.manifest_sha256,
|
|
"exporter_receipt_binding_verified_before_docker": True,
|
|
"compatibility_projection": {
|
|
"raw_bytes_unchanged": True,
|
|
"role_settings_capture_complete": role_capture_complete,
|
|
"derived_fields": (
|
|
[]
|
|
if role_capture_complete
|
|
else [
|
|
"application_roles[].settings",
|
|
"application_roles[].database_settings",
|
|
]
|
|
),
|
|
"derivation": (
|
|
None
|
|
if role_capture_complete
|
|
else "settings mirrors captured default_transaction_read_only; database_settings defaults empty"
|
|
),
|
|
},
|
|
},
|
|
"exporter_receipt": {
|
|
"sha256": inputs.exporter_receipt_sha256,
|
|
"trust_root_receipt_sha256": inputs.trust_root_receipt_sha256,
|
|
"schema": inputs.exporter_receipt["schema"],
|
|
"artifact": inputs.exporter_receipt["artifact"],
|
|
"run_id": inputs.exporter_receipt["run_id"],
|
|
"capture_authorization_ref": inputs.capture_authorization_ref,
|
|
"source_identity": inputs.source_identity,
|
|
"provenance_binding_sha256": inputs.provenance_binding_sha256,
|
|
"trusted_contract_validated_before_docker": True,
|
|
},
|
|
"image": {
|
|
"reference": inputs.image,
|
|
"digest_pinned": True,
|
|
"runtime_reference_exact": self.environment.get("image_reference_exact") is True,
|
|
},
|
|
"restore": {
|
|
"direct_custom_format_pg_restore": True,
|
|
"snapshot_repackaged": False,
|
|
"synthetic_schema_bootstrap_skipped": True,
|
|
"canonical_payload_preseed_performed": False,
|
|
"application_roles_from_manifest": application_roles,
|
|
"role_membership_statement_count": role_memberships,
|
|
"database_acl_statement_count": database_acl_statements,
|
|
"pg_restore_stdout_sha256": sha256_text(restore.stdout),
|
|
"pg_restore_stderr_sha256": sha256_text(restore.stderr),
|
|
"guard_prerequisites_sha256": sha256_file(inputs.guard_prerequisites_path),
|
|
"manifest_parity_proven_before_guard_install": True,
|
|
"guard_copy_stdout_sha256": sha256_text(copy_guards.stdout),
|
|
"guard_install_stdout_sha256": sha256_text(install_guards.stdout),
|
|
},
|
|
"parity": {
|
|
"status": parity["status"],
|
|
"verifier": parity["verifier"],
|
|
"source_manifest": source_manifest,
|
|
"target_manifest": parity["target_manifest"],
|
|
"problems": parity["problems"],
|
|
"claim_scope": (
|
|
"full_captured_manifest_including_role_and_database_settings"
|
|
if role_capture_complete
|
|
else "data_schema_and_captured_role_attributes_only"
|
|
),
|
|
"role_global_parity": {
|
|
"status": "proven" if role_capture_complete else "not_proven",
|
|
"captured_source_settings_present": role_capture_complete,
|
|
"reason": (
|
|
None
|
|
if role_capture_complete
|
|
else "source manifest omitted role settings/database settings; replay used a compatibility projection"
|
|
),
|
|
},
|
|
"details": parity["details"],
|
|
},
|
|
"key_counts": key_counts,
|
|
"canonical_schema_table_count": schema_table_count,
|
|
}
|
|
|
|
def cleanup(self) -> dict[str, Any]:
|
|
remove = self._run(["rm", "-f", self.name], check=False) if self.started else None
|
|
inspect = self._run(["inspect", self.name], check=False)
|
|
names = self._run(
|
|
["container", "ls", "-a", "--filter", f"name=^/{self.name}$", "--format", "{{.Names}}"],
|
|
check=False,
|
|
)
|
|
labels = self._run(
|
|
[
|
|
"container",
|
|
"ls",
|
|
"-a",
|
|
"--filter",
|
|
"label=livingip.canary=leo-integrated-learning-lifecycle",
|
|
"--filter",
|
|
f"label=livingip.canary.instance={self.name}",
|
|
"--format",
|
|
"{{.Names}}",
|
|
],
|
|
check=False,
|
|
)
|
|
run_group = self._run(
|
|
[
|
|
"container",
|
|
"ls",
|
|
"-a",
|
|
"--filter",
|
|
f"label=livingip.canary.run_group={self.run_group}",
|
|
"--filter",
|
|
f"label=livingip.canary.instance={self.name}",
|
|
"--format",
|
|
"{{.Names}}",
|
|
],
|
|
check=False,
|
|
)
|
|
return {
|
|
"remove_attempted": self.started,
|
|
"remove_returncode": remove.returncode if remove else None,
|
|
"container_absent": inspect.returncode != 0,
|
|
"name_readback_clear": names.returncode == 0 and not names.stdout.strip(),
|
|
"instance_label_readback_clear": labels.returncode == 0 and not labels.stdout.strip(),
|
|
"run_group_readback_clear": run_group.returncode == 0 and not run_group.stdout.strip(),
|
|
"network_mode_was_none": self.environment.get("network_mode") == "none",
|
|
"tmpfs_data_dir_was_present": self.environment.get("tmpfs_data_dir") is True,
|
|
"docker_volume_mounts_observed": self.environment.get("mounts", []),
|
|
}
|
|
|
|
|
|
def bootstrap_sql(review_password: str, apply_password: str) -> str:
|
|
return f"""\\set ON_ERROR_STOP on
|
|
create role kb_apply login noinherit password {ap.sql_literal(apply_password)};
|
|
create role kb_review login noinherit password {ap.sql_literal(review_password)};
|
|
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 default gen_random_uuid(),
|
|
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(),
|
|
updated_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 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 ({ap.sql_literal(REVIEWER_ID)}::uuid, {ap.sql_literal(REVIEWER_HANDLE)}, 'human');
|
|
"""
|
|
|
|
|
|
def initialize_database(
|
|
postgres: DisposablePostgres,
|
|
*,
|
|
genesis: GenesisInputs | None,
|
|
review_password: str,
|
|
apply_password: str,
|
|
) -> dict[str, Any]:
|
|
"""Initialize exactly one allowed database mode."""
|
|
if genesis is not None:
|
|
restored = postgres.restore_genesis(genesis)
|
|
postgres.psql(
|
|
f"alter role kb_review password {ap.sql_literal(review_password)};\n"
|
|
f"alter role kb_apply password {ap.sql_literal(apply_password)};"
|
|
)
|
|
return {
|
|
"mode": "exporter_receipt_bound_genesis_restore",
|
|
"synthetic_schema_bootstrap_skipped": True,
|
|
"canonical_payload_preseed_performed": False,
|
|
"worker_credentials_configured_for_password_auth": True,
|
|
"genesis": restored,
|
|
}
|
|
postgres.psql(bootstrap_sql(review_password, apply_password))
|
|
postgres.psql(GUARD_PREREQUISITES_PATH.read_text(encoding="utf-8"))
|
|
return {
|
|
"mode": "legacy_synthetic_fixture_schema",
|
|
"synthetic_schema_bootstrap_skipped": False,
|
|
"canonical_payload_preseed_performed": False,
|
|
"worker_credentials_configured_for_password_auth": True,
|
|
}
|
|
|
|
|
|
def source_packet_input_paths(source_packet: Path) -> frozenset[Path]:
|
|
packet = source_packet.expanduser().resolve()
|
|
return frozenset(
|
|
{
|
|
packet / "prepared" / "extracted-text.txt",
|
|
packet / "prepared" / "source-manifest.json",
|
|
packet / "proposal-packet.json",
|
|
}
|
|
)
|
|
|
|
|
|
def compile_source_packet(source_packet: Path) -> tuple[dict[str, Any], dict[str, Any], dict[str, Path]]:
|
|
paths = {
|
|
"artifact": source_packet / "prepared" / "extracted-text.txt",
|
|
"text": source_packet / "prepared" / "extracted-text.txt",
|
|
"manifest": source_packet / "prepared" / "source-manifest.json",
|
|
"expected": source_packet / "proposal-packet.json",
|
|
}
|
|
missing = [str(path) for path in paths.values() if not path.is_file()]
|
|
if missing:
|
|
raise LifecycleError(f"source packet is missing required files: {missing}")
|
|
expected = json.loads(paths["expected"].read_text(encoding="utf-8"))
|
|
if not isinstance(expected, dict):
|
|
raise LifecycleError("proposal-packet.json must contain one JSON object")
|
|
compiled = compiler.compile_source_packet(paths["artifact"], paths["text"], paths["manifest"])
|
|
if canonical_json_bytes(compiled) != canonical_json_bytes(expected):
|
|
raise LifecycleError("fresh compiler output does not match retained proposal-packet.json")
|
|
return compiled, expected, paths
|
|
|
|
|
|
def proposal_readback(postgres: DisposablePostgres, proposal_id: str) -> dict[str, Any] | None:
|
|
sql = f"""select jsonb_build_object(
|
|
'id', id::text,
|
|
'proposal_type', proposal_type,
|
|
'status', status,
|
|
'proposed_by_handle', proposed_by_handle,
|
|
'proposed_by_agent_id', proposed_by_agent_id::text,
|
|
'channel', channel,
|
|
'source_ref', source_ref,
|
|
'rationale', rationale,
|
|
'payload', payload,
|
|
'reviewed_by_handle', reviewed_by_handle,
|
|
'reviewed_by_agent_id', reviewed_by_agent_id::text,
|
|
'reviewed_at', case when reviewed_at is null then null else
|
|
to_char(reviewed_at at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') end,
|
|
'review_note', review_note,
|
|
'applied_by_handle', applied_by_handle,
|
|
'applied_by_agent_id', applied_by_agent_id::text,
|
|
'applied_at', case when applied_at is null then null else
|
|
to_char(applied_at at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') end,
|
|
'created_at', to_char(created_at at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"'),
|
|
'updated_at', to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"')
|
|
)::text
|
|
from kb_stage.kb_proposals
|
|
where id = {ap.sql_literal(proposal_id)}::uuid;"""
|
|
parsed = parse_last_json_line(postgres.psql(sql))
|
|
if parsed is not None and not isinstance(parsed, dict):
|
|
raise LifecycleError("proposal readback was not an object")
|
|
return parsed
|
|
|
|
|
|
def approval_readback(postgres: DisposablePostgres, proposal_id: str) -> dict[str, Any] | None:
|
|
sql = f"""select jsonb_build_object(
|
|
'proposal_id', proposal_id::text,
|
|
'proposal_type', proposal_type,
|
|
'payload', payload,
|
|
'reviewed_by_handle', reviewed_by_handle,
|
|
'reviewed_by_agent_id', reviewed_by_agent_id::text,
|
|
'reviewed_by_db_role', reviewed_by_db_role::text,
|
|
'reviewed_at', to_char(reviewed_at at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"'),
|
|
'review_note', review_note
|
|
)::text
|
|
from kb_stage.kb_proposal_approvals
|
|
where proposal_id = {ap.sql_literal(proposal_id)}::uuid;"""
|
|
parsed = parse_last_json_line(postgres.psql(sql))
|
|
if parsed is not None and not isinstance(parsed, dict):
|
|
raise LifecycleError("approval readback was not an object")
|
|
return parsed
|
|
|
|
|
|
def probe_applied_proposal(child: dict[str, Any]) -> dict[str, Any]:
|
|
return {
|
|
**child,
|
|
"status": "applied",
|
|
"applied_by_handle": ap.SERVICE_AGENT_HANDLE,
|
|
"applied_at": "2000-01-01T00:00:00+00:00",
|
|
}
|
|
|
|
|
|
def target_rows_readback(postgres: DisposablePostgres, child: dict[str, Any]) -> dict[str, list[dict[str, Any]]]:
|
|
sql = ap.replay_receipt.build_postflight_sql(probe_applied_proposal(child))
|
|
parsed = postgres.psql_json(sql)
|
|
if not isinstance(parsed, dict) or any(not isinstance(rows, list) for rows in parsed.values()):
|
|
raise LifecycleError("canonical target-row readback was malformed")
|
|
return parsed
|
|
|
|
|
|
def agents_readback(postgres: DisposablePostgres) -> list[dict[str, Any]]:
|
|
parsed = postgres.psql_json(
|
|
"select coalesce(jsonb_agg(to_jsonb(a) order by a.id::text), '[]'::jsonb)::text from public.agents a;"
|
|
)
|
|
if not isinstance(parsed, list):
|
|
raise LifecycleError("agent readback was malformed")
|
|
return parsed
|
|
|
|
|
|
def database_state(postgres: DisposablePostgres, child: dict[str, Any]) -> dict[str, Any]:
|
|
proposal_id = str(child["id"])
|
|
canonical_rows = target_rows_readback(postgres, child)
|
|
state = {
|
|
"agents": agents_readback(postgres),
|
|
"canonical_rows": canonical_rows,
|
|
"proposal": proposal_readback(postgres, proposal_id),
|
|
"immutable_approval": approval_readback(postgres, proposal_id),
|
|
}
|
|
return {
|
|
"database_fingerprint": canonical_sha256(state),
|
|
"canonical_fingerprint": canonical_sha256(canonical_rows),
|
|
"state": state,
|
|
}
|
|
|
|
|
|
def exact_identities(
|
|
child: dict[str, Any], canonical_rows: dict[str, list[dict[str, Any]]] | None = None
|
|
) -> dict[str, Any]:
|
|
apply_payload = child["payload"]["apply_payload"]
|
|
evidence_rows = canonical_rows.get("claim_evidence", []) if canonical_rows else []
|
|
return {
|
|
"proposal_id": child["id"],
|
|
"claim_ids": [row["id"] for row in apply_payload.get("claims", [])],
|
|
"source_ids": [row["id"] for row in apply_payload.get("sources", [])],
|
|
"planned_evidence_keys": [
|
|
{
|
|
"claim_id": row["claim_id"],
|
|
"source_id": row["source_id"],
|
|
"role": row.get("role") or "grounds",
|
|
}
|
|
for row in apply_payload.get("evidence", [])
|
|
],
|
|
"evidence_ids": [row["id"] for row in evidence_rows if row.get("id")],
|
|
"edge_ids": [row["id"] for row in canonical_rows.get("claim_edges", [])] if canonical_rows else [],
|
|
}
|
|
|
|
|
|
def review_packet(proposal: dict[str, Any]) -> dict[str, Any]:
|
|
packet = review_packets.classify_proposal(proposal)
|
|
apply_payload = proposal["payload"]["apply_payload"]
|
|
packet["candidate_rows"] = {
|
|
family: apply_payload.get(family, [])
|
|
for family in ("claims", "sources", "evidence", "edges", "reasoning_tools")
|
|
}
|
|
packet["packet_sha256"] = canonical_sha256(packet)
|
|
return packet
|
|
|
|
|
|
def write_secret_file(path: Path, key: str, value: str) -> None:
|
|
path.write_text(f"{key}={value}\n", encoding="utf-8")
|
|
path.chmod(0o600)
|
|
|
|
|
|
def _tool_base(script: Path, proposal_id: str, secrets_file: Path, role: str, container: str) -> list[str]:
|
|
return [
|
|
sys.executable,
|
|
str(script),
|
|
proposal_id,
|
|
"--secrets-file",
|
|
str(secrets_file),
|
|
"--container",
|
|
container,
|
|
"--db",
|
|
DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
role,
|
|
]
|
|
|
|
|
|
def _all_target_rows_empty(rows: dict[str, list[dict[str, Any]]]) -> bool:
|
|
return set(rows) == set(apply_lifecycle.ROW_TABLES) and all(not table_rows for table_rows in rows.values())
|
|
|
|
|
|
def require_fresh_initial_state(initial: dict[str, Any]) -> None:
|
|
"""Reject proposal or canonical target preseeding before any staging action."""
|
|
state = initial.get("state")
|
|
if not isinstance(state, dict):
|
|
raise LifecycleError("initial database state is malformed")
|
|
if state.get("proposal") is not None or state.get("immutable_approval") is not None:
|
|
raise LifecycleError("proposal or approval preseed is forbidden before staging")
|
|
rows = state.get("canonical_rows")
|
|
if not isinstance(rows, dict) or not _all_target_rows_empty(rows):
|
|
raise LifecycleError("canonical payload target preseed is forbidden before staging")
|
|
|
|
|
|
def _row_counts(rows: dict[str, list[dict[str, Any]]]) -> dict[str, int]:
|
|
return {family: len(table_rows) for family, table_rows in rows.items()}
|
|
|
|
|
|
def normalized_canonical_rows(rows: dict[str, list[dict[str, Any]]]) -> dict[str, list[dict[str, Any]]]:
|
|
return {
|
|
family: sorted(
|
|
(
|
|
ap.replay_receipt.normalize_typed_row(
|
|
row,
|
|
path=f"integrated_lifecycle.{family}",
|
|
)
|
|
for row in table_rows
|
|
),
|
|
key=canonical_json_bytes,
|
|
)
|
|
for family, table_rows in sorted(rows.items())
|
|
}
|
|
|
|
|
|
def run_lifecycle(
|
|
source_packet: Path,
|
|
output: Path,
|
|
*,
|
|
review_action: str,
|
|
reviewed_by: str = REVIEWER_HANDLE,
|
|
review_note: str = DEFAULT_REVIEW_NOTE,
|
|
genesis: GenesisInputs | None = None,
|
|
persist_receipt: bool = True,
|
|
run_group: str | None = None,
|
|
run_number: int | None = None,
|
|
) -> dict[str, Any]:
|
|
if review_action != "approve":
|
|
raise LifecycleError("the only supported explicit review action is 'approve'")
|
|
if reviewed_by != REVIEWER_HANDLE:
|
|
raise LifecycleError(f"disposable reviewer must be {REVIEWER_HANDLE!r}")
|
|
if not review_note.strip():
|
|
raise LifecycleError("review note must be non-empty")
|
|
|
|
source_packet = source_packet.resolve()
|
|
output = output.resolve()
|
|
if output in source_packet_input_paths(source_packet):
|
|
raise LifecycleError("--output must not overwrite a retained source-packet input")
|
|
temp_root = Path(tempfile.mkdtemp(prefix="leo-integrated-learning-"))
|
|
worker_receipt_dir = temp_root / "worker-receipts"
|
|
private_apply_receipt_path: Path | None = None
|
|
mode_slug = "genesis" if genesis is not None else "fixture"
|
|
container_name = f"leo-integrated-learning-{mode_slug}-{os.getpid()}-{uuid.uuid4().hex[:10]}"
|
|
run_group = run_group or uuid.uuid4().hex
|
|
postgres: DisposablePostgres | None = None
|
|
receipt: dict[str, Any] = {
|
|
"artifact": "leo_integrated_learning_lifecycle_run",
|
|
"schema": RECEIPT_SCHEMA,
|
|
"status": "fail",
|
|
"mode": "exporter_receipt_bound_genesis" if genesis is not None else "legacy_synthetic_fixture",
|
|
"run_number": run_number,
|
|
"required_tier": (
|
|
"T2_disposable_genesis_backed_runtime"
|
|
if genesis is not None
|
|
else "realistic_isolated_local_container_end_to_end"
|
|
),
|
|
"current_tier": "not_proven",
|
|
"source_packet": "source-packet",
|
|
"review_action": review_action,
|
|
"safety_boundary": {
|
|
"self_created_container_only": True,
|
|
"existing_database_target_argument_supported": False,
|
|
"vps_or_gcp_target_supported": False,
|
|
"telegram_send_performed": False,
|
|
"model_calls_performed": False,
|
|
"genesis_restore_requested": genesis is not None,
|
|
},
|
|
"checks": {},
|
|
}
|
|
|
|
try:
|
|
compiled, expected, paths = compile_source_packet(source_packet)
|
|
child = compiled["strict_child_proposal"]
|
|
parent = compiled["parent_proposal"]
|
|
proposal_id = str(child["id"])
|
|
apply_payload = child["payload"]["apply_payload"]
|
|
worker_contract_version = apply_payload.get("contract_version", 2)
|
|
if worker_contract_version != 2:
|
|
raise LifecycleError("this integrated genesis lifecycle is pinned to the V2 apply contract")
|
|
manifest = json.loads(paths["manifest"].read_text(encoding="utf-8"))
|
|
receipt["source"] = {
|
|
"source_identity": manifest["source"]["identity"],
|
|
"source_locator": manifest["source"]["locator"],
|
|
"artifact_sha256": sha256_file(paths["artifact"]),
|
|
"manifest_canonical_sha256": canonical_sha256(manifest),
|
|
"retained_proposal_packet_file_sha256": sha256_file(paths["expected"]),
|
|
"retained_proposal_packet_canonical_sha256": canonical_sha256(expected),
|
|
}
|
|
receipt["compiled"] = {
|
|
"status": compiled["status"],
|
|
"bundle_sha256": canonical_sha256(compiled),
|
|
"canonical_bytes_sha256": hashlib.sha256(canonical_json_bytes(compiled)).hexdigest(),
|
|
"retained_packet_canonical_bytes_sha256": hashlib.sha256(canonical_json_bytes(expected)).hexdigest(),
|
|
"parent_proposal_id": parent["id"],
|
|
"strict_proposal_id": proposal_id,
|
|
"candidate_counts": {
|
|
family: len(apply_payload.get(family, []))
|
|
for family in ("claims", "sources", "evidence", "edges", "reasoning_tools")
|
|
},
|
|
}
|
|
compiled_identities = exact_identities(child)
|
|
receipt["identities"] = compiled_identities
|
|
|
|
postgres = DisposablePostgres(
|
|
container_name,
|
|
secrets.token_urlsafe(32),
|
|
image=genesis.image if genesis is not None else POSTGRES_IMAGE,
|
|
genesis_backed=genesis is not None,
|
|
run_group=run_group,
|
|
)
|
|
environment = postgres.start()
|
|
receipt["environment"] = environment
|
|
review_password = secrets.token_urlsafe(32)
|
|
apply_password = secrets.token_urlsafe(32)
|
|
review_secrets = temp_root / "kb-review.env"
|
|
apply_secrets = temp_root / "kb-apply.env"
|
|
preflight_path = temp_root / "fresh-preflight.json"
|
|
write_secret_file(review_secrets, "KB_REVIEW_PASSWORD", review_password)
|
|
write_secret_file(apply_secrets, "KB_APPLY_PASSWORD", apply_password)
|
|
|
|
receipt["database_initialization"] = initialize_database(
|
|
postgres,
|
|
genesis=genesis,
|
|
review_password=review_password,
|
|
apply_password=apply_password,
|
|
)
|
|
|
|
initial = database_state(postgres, child)
|
|
require_fresh_initial_state(initial)
|
|
stage_result = postgres.psql_json(stage.build_stage_sql(child))
|
|
pending = proposal_readback(postgres, proposal_id)
|
|
if pending is None:
|
|
raise LifecycleError("staging did not persist the exact proposal")
|
|
staged = database_state(postgres, child)
|
|
packet = review_packet(pending)
|
|
receipt["phases"] = {
|
|
"initial": initial,
|
|
"staged_pending_review": {
|
|
"database_fingerprint": staged["database_fingerprint"],
|
|
"canonical_fingerprint": staged["canonical_fingerprint"],
|
|
"proposal": pending,
|
|
"stage_result": stage_result,
|
|
"review_packet": packet,
|
|
},
|
|
}
|
|
|
|
approve_script = genesis.approve_script_path if genesis is not None else HERE / "approve_proposal.py"
|
|
approve_base = [
|
|
*_tool_base(
|
|
approve_script,
|
|
proposal_id,
|
|
review_secrets,
|
|
"kb_review",
|
|
container_name,
|
|
),
|
|
"--reviewed-by",
|
|
reviewed_by,
|
|
"--review-note",
|
|
review_note,
|
|
]
|
|
approve_dry_run = run_tool([*approve_base, "--dry-run"], action="approval dry-run")
|
|
if "kb_stage.approve_strict_proposal" not in approve_dry_run.stdout:
|
|
raise LifecycleError("approval dry-run did not bind the guarded approval function")
|
|
approve_execute = run_tool(approve_base, action="explicit review approval")
|
|
approved = proposal_readback(postgres, proposal_id)
|
|
immutable_approval = approval_readback(postgres, proposal_id)
|
|
if approved is None or immutable_approval is None:
|
|
raise LifecycleError("explicit review did not create both approved state and immutable approval")
|
|
approved_state = database_state(postgres, child)
|
|
receipt["phases"]["approved_unapplied"] = {
|
|
"database_fingerprint": approved_state["database_fingerprint"],
|
|
"canonical_fingerprint": approved_state["canonical_fingerprint"],
|
|
"proposal": approved,
|
|
"immutable_approval": immutable_approval,
|
|
"review_action": {
|
|
"reviewed_by": reviewed_by,
|
|
"review_note": review_note,
|
|
"dry_run": command_receipt(
|
|
approve_dry_run,
|
|
expected_marker="kb_stage.approve_strict_proposal",
|
|
),
|
|
"execute": command_receipt(approve_execute),
|
|
},
|
|
}
|
|
|
|
target_rows_before = target_rows_readback(postgres, child)
|
|
preflight = apply_lifecycle.build_fresh_preflight(approved, target_rows_before)
|
|
preflight_path.write_text(json.dumps(preflight, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
preflight_path.chmod(0o600)
|
|
failure_state_path = temp_root / "worker-failures.json"
|
|
private_apply_receipt_path = worker_receipt_dir / f"{proposal_id}.json"
|
|
worker_script = genesis.apply_worker_script_path if genesis is not None else HERE / "apply_worker.py"
|
|
apply_script = genesis.apply_script_path if genesis is not None else HERE / "apply_proposal.py"
|
|
worker_base = [
|
|
sys.executable,
|
|
str(worker_script),
|
|
"--proposal-id",
|
|
proposal_id,
|
|
"--contract-version",
|
|
str(worker_contract_version),
|
|
"--limit",
|
|
"1",
|
|
"--max-per-tick",
|
|
"1",
|
|
"--max-attempts",
|
|
"3",
|
|
"--failure-state-file",
|
|
str(failure_state_path),
|
|
"--apply-script",
|
|
str(apply_script),
|
|
"--receipt-dir",
|
|
str(worker_receipt_dir),
|
|
"--secrets-file",
|
|
str(apply_secrets),
|
|
"--container",
|
|
container_name,
|
|
"--db",
|
|
DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
"kb_apply",
|
|
"--fresh-preflight",
|
|
str(preflight_path),
|
|
]
|
|
worker_report_only = run_tool(
|
|
[*worker_base, "--require-candidate"],
|
|
action="disabled apply worker candidate preflight",
|
|
)
|
|
report_only_state = database_state(postgres, child)
|
|
report_marker = f"would apply {proposal_id} (approve_claim)"
|
|
if report_marker not in worker_report_only.stdout:
|
|
raise LifecycleError("disabled apply worker did not select the exact approved proposal")
|
|
|
|
expected_retry_failure = subprocess.run(
|
|
[
|
|
*worker_base,
|
|
"--require-candidate",
|
|
"--enable",
|
|
"--applied-by",
|
|
"missing-disposable-worker-agent",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if expected_retry_failure.returncode != 1:
|
|
raise LifecycleError("apply worker retry probe did not fail exactly once before commit")
|
|
retry_state = json.loads(failure_state_path.read_text(encoding="utf-8"))
|
|
retry_probe_state = database_state(postgres, child)
|
|
if retry_state != {proposal_id: 1}:
|
|
raise LifecycleError("apply worker retry probe did not persist the exact failure count")
|
|
if private_apply_receipt_path.exists():
|
|
raise LifecycleError("failed apply worker retry unexpectedly wrote a replay receipt")
|
|
|
|
worker_execute = run_tool(
|
|
[*worker_base, "--require-candidate", "--enable"],
|
|
action="enabled apply worker retry",
|
|
)
|
|
if not private_apply_receipt_path.is_file():
|
|
raise LifecycleError("apply worker did not retain its private replay receipt")
|
|
if stat.S_IMODE(private_apply_receipt_path.stat().st_mode) != 0o600:
|
|
raise LifecycleError("apply worker replay receipt is not mode 0600")
|
|
apply_receipt = json.loads(private_apply_receipt_path.read_text(encoding="utf-8"))
|
|
failure_state_after_success = json.loads(failure_state_path.read_text(encoding="utf-8"))
|
|
post_apply_before = database_state(postgres, child)
|
|
worker_post_apply_refusal = subprocess.run(
|
|
[*worker_base, "--enable"],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
refusal_marker = (
|
|
f"REFUSE exact proposal execution: approved+applyable contract v{worker_contract_version} "
|
|
f"proposal {proposal_id} "
|
|
"was not selected exactly once; no writes attempted."
|
|
)
|
|
if worker_post_apply_refusal.returncode != 1 or refusal_marker not in worker_post_apply_refusal.stderr:
|
|
raise LifecycleError("post-apply exact worker did not refuse the already-applied proposal")
|
|
applied = proposal_readback(postgres, proposal_id)
|
|
if applied is None:
|
|
raise LifecycleError("applied proposal readback is missing")
|
|
final_rows = target_rows_readback(postgres, child)
|
|
applied_state = database_state(postgres, child)
|
|
|
|
recompiled, _expected_again, _paths_again = compile_source_packet(source_packet)
|
|
recompiled_child = recompiled["strict_child_proposal"]
|
|
final_identities = exact_identities(recompiled_child, final_rows)
|
|
controlled_fingerprint = payload_controlled_fingerprint(final_rows)
|
|
receipt["identities"] = final_identities
|
|
receipt["phases"]["applied"] = {
|
|
"database_fingerprint": applied_state["database_fingerprint"],
|
|
"canonical_fingerprint": applied_state["canonical_fingerprint"],
|
|
"proposal": applied,
|
|
"canonical_rows": final_rows,
|
|
"payload_controlled_fingerprint": controlled_fingerprint,
|
|
"worker_action": {
|
|
"exact_candidate_id": proposal_id,
|
|
"credential_role": "kb_apply",
|
|
"fresh_preflight_sha256": sha256_file(preflight_path),
|
|
"report_only": command_receipt(worker_report_only, expected_marker=report_marker),
|
|
"report_only_database_fingerprint": report_only_state["database_fingerprint"],
|
|
"expected_retry_failure": command_receipt(expected_retry_failure),
|
|
"retry_failure_count": retry_state[proposal_id],
|
|
"retry_probe_database_fingerprint": retry_probe_state["database_fingerprint"],
|
|
"enabled_retry": command_receipt(
|
|
worker_execute,
|
|
expected_marker=f"applied {proposal_id} (approve_claim)",
|
|
),
|
|
"failure_state_after_success": failure_state_after_success,
|
|
"post_apply_exact_refusal": {
|
|
**command_receipt(worker_post_apply_refusal),
|
|
"expected_refusal_marker": refusal_marker,
|
|
"expected_refusal_marker_present": refusal_marker in worker_post_apply_refusal.stderr,
|
|
},
|
|
"private_receipt_mode": "0600",
|
|
},
|
|
"apply_receipt": apply_receipt,
|
|
}
|
|
receipt["phases"]["recompiled_readback"] = {
|
|
"bundle_sha256": canonical_sha256(recompiled),
|
|
"matches_initial_compile": canonical_json_bytes(recompiled) == canonical_json_bytes(compiled),
|
|
"proposal_id_matches": recompiled_child["id"] == proposal_id,
|
|
"claim_ids_match": final_identities["claim_ids"] == compiled_identities["claim_ids"],
|
|
"source_ids_match": final_identities["source_ids"] == compiled_identities["source_ids"],
|
|
"canonical_rows_sha256": canonical_sha256(normalized_canonical_rows(final_rows)),
|
|
"apply_receipt_rows_sha256": canonical_sha256(
|
|
normalized_canonical_rows(apply_receipt.get("canonical_rows"))
|
|
),
|
|
}
|
|
|
|
expected_counts = ap.replay_receipt.expected_row_counts(applied)
|
|
actual_counts = _row_counts(final_rows)
|
|
checks = {
|
|
"fresh_compile_matches_retained_packet": canonical_json_bytes(compiled) == canonical_json_bytes(expected),
|
|
"fresh_compile_matches_retained_packet_byte_identically": canonical_json_bytes(compiled)
|
|
== canonical_json_bytes(expected),
|
|
"compiler_emits_pending_review": compiled.get("status") == "pending_review",
|
|
"initial_target_rows_absent": _all_target_rows_empty(initial["state"]["canonical_rows"]),
|
|
"initial_proposal_and_approval_absent": initial["state"]["proposal"] is None
|
|
and initial["state"]["immutable_approval"] is None,
|
|
"staged_proposal_exact": pending.get("id") == proposal_id and pending.get("payload") == child["payload"],
|
|
"staged_status_pending_review": pending.get("status") == "pending_review",
|
|
"review_packet_requires_human_review": packet.get("review_state") == "needs_human_review",
|
|
"stage_did_not_change_canonical_rows": staged["canonical_fingerprint"] == initial["canonical_fingerprint"],
|
|
"explicit_review_status_approved": approved.get("status") == "approved",
|
|
"approved_is_not_applied": approved.get("applied_at") is None,
|
|
"immutable_approval_matches_payload": immutable_approval.get("payload") == child["payload"],
|
|
"immutable_approval_matches_reviewer": immutable_approval.get("reviewed_by_handle") == reviewed_by,
|
|
"review_did_not_change_canonical_rows": approved_state["canonical_fingerprint"]
|
|
== initial["canonical_fingerprint"],
|
|
"worker_report_only_selected_exact_candidate": report_marker in worker_report_only.stdout,
|
|
"worker_enable_gate_prevented_apply": report_only_state["database_fingerprint"]
|
|
== approved_state["database_fingerprint"],
|
|
"worker_retry_failure_was_precommit": retry_probe_state["database_fingerprint"]
|
|
== approved_state["database_fingerprint"],
|
|
"worker_retry_count_persisted_once": retry_state == {proposal_id: 1},
|
|
"worker_retry_state_cleared_after_success": failure_state_after_success == {},
|
|
"worker_enabled_retry_applied_exact_candidate": f"applied {proposal_id} (approve_claim)"
|
|
in worker_execute.stdout,
|
|
"worker_post_apply_exact_refusal_did_not_retry": worker_post_apply_refusal.returncode == 1
|
|
and refusal_marker in worker_post_apply_refusal.stderr
|
|
and post_apply_before["database_fingerprint"] == applied_state["database_fingerprint"],
|
|
"worker_receipt_private_mode_0600": stat.S_IMODE(private_apply_receipt_path.stat().st_mode) == 0o600,
|
|
"apply_status_applied": applied.get("status") == "applied" and bool(applied.get("applied_at")),
|
|
"apply_changed_canonical_fingerprint": applied_state["canonical_fingerprint"]
|
|
!= initial["canonical_fingerprint"],
|
|
"apply_row_counts_exact": actual_counts == expected_counts,
|
|
"apply_receipt_replay_ready": apply_receipt.get("replay_ready") is True,
|
|
"apply_receipt_rows_exact": normalized_canonical_rows(apply_receipt.get("canonical_rows"))
|
|
== normalized_canonical_rows(final_rows),
|
|
"payload_controlled_fields_fingerprinted": controlled_fingerprint["row_counts"] == actual_counts,
|
|
"recompile_matches_initial": canonical_json_bytes(recompiled) == canonical_json_bytes(compiled),
|
|
"recompile_proposal_id_exact": recompiled_child["id"] == proposal_id,
|
|
"database_fingerprints_distinguish_all_transitions": len(
|
|
{
|
|
initial["database_fingerprint"],
|
|
staged["database_fingerprint"],
|
|
approved_state["database_fingerprint"],
|
|
applied_state["database_fingerprint"],
|
|
}
|
|
)
|
|
== 4,
|
|
}
|
|
if genesis is not None:
|
|
genesis_restore = receipt["database_initialization"]["genesis"]
|
|
checks.update(
|
|
{
|
|
"genesis_dump_exporter_receipt_bound_before_docker": genesis_restore["dump"][
|
|
"exporter_receipt_binding_verified_before_docker"
|
|
]
|
|
is True,
|
|
"genesis_manifest_exporter_receipt_bound_before_docker": genesis_restore["manifest"][
|
|
"exporter_receipt_binding_verified_before_docker"
|
|
]
|
|
is True,
|
|
"genesis_exporter_receipt_trusted_contract_valid": genesis_restore["exporter_receipt"][
|
|
"trusted_contract_validated_before_docker"
|
|
]
|
|
is True,
|
|
"genesis_data_schema_parity_proven": genesis_restore["parity"]["status"] == "pass"
|
|
and not genesis_restore["parity"]["problems"],
|
|
"genesis_role_global_parity_claim_honest": genesis_restore["parity"]["role_global_parity"]["status"]
|
|
== ("proven" if genesis.role_settings_capture_complete else "not_proven"),
|
|
"genesis_image_digest_pinned": genesis_restore["image"]["digest_pinned"] is True
|
|
and genesis_restore["image"]["runtime_reference_exact"] is True,
|
|
"worker_password_auth_not_trust": receipt["environment"]["host_auth_trust_requested"] is False
|
|
and receipt["database_initialization"]["worker_credentials_configured_for_password_auth"] is True,
|
|
"synthetic_bootstrap_skipped": receipt["database_initialization"][
|
|
"synthetic_schema_bootstrap_skipped"
|
|
]
|
|
is True,
|
|
"canonical_payload_preseed_forbidden": receipt["database_initialization"][
|
|
"canonical_payload_preseed_performed"
|
|
]
|
|
is False,
|
|
}
|
|
)
|
|
receipt["checks"] = checks
|
|
if not all(checks.values()):
|
|
failed = [name for name, passed in checks.items() if not passed]
|
|
raise LifecycleError(f"lifecycle checks failed: {failed}")
|
|
except (LifecycleError, OSError, ValueError, KeyError, TypeError, json.JSONDecodeError) as exc:
|
|
receipt["error"] = {"type": type(exc).__name__, "message": str(exc)}
|
|
finally:
|
|
try:
|
|
cleanup = (
|
|
postgres.cleanup()
|
|
if postgres is not None
|
|
else {
|
|
"remove_attempted": False,
|
|
"container_absent": True,
|
|
"name_readback_clear": True,
|
|
"instance_label_readback_clear": True,
|
|
"run_group_readback_clear": True,
|
|
"network_mode_was_none": False,
|
|
"tmpfs_data_dir_was_present": False,
|
|
"docker_volume_mounts_observed": [],
|
|
}
|
|
)
|
|
except (LifecycleError, OSError) as exc:
|
|
cleanup = {
|
|
"remove_attempted": bool(postgres is not None and postgres.started),
|
|
"container_absent": False,
|
|
"name_readback_clear": False,
|
|
"instance_label_readback_clear": False,
|
|
"run_group_readback_clear": False,
|
|
"network_mode_was_none": False,
|
|
"tmpfs_data_dir_was_present": False,
|
|
"docker_volume_mounts_observed": [],
|
|
"cleanup_error": {"type": type(exc).__name__, "message": str(exc)},
|
|
}
|
|
shutil.rmtree(temp_root, ignore_errors=True)
|
|
cleanup["temporary_secret_root_absent"] = not temp_root.exists()
|
|
cleanup["private_apply_receipt_removed_with_secret_root"] = (
|
|
private_apply_receipt_path is None or not private_apply_receipt_path.exists()
|
|
)
|
|
cleanup["all"] = all(
|
|
(
|
|
cleanup.get("container_absent") is True,
|
|
cleanup.get("name_readback_clear") is True,
|
|
cleanup.get("instance_label_readback_clear") is True,
|
|
cleanup.get("run_group_readback_clear") is True,
|
|
cleanup.get("network_mode_was_none") is True,
|
|
cleanup.get("tmpfs_data_dir_was_present") is True,
|
|
cleanup.get("docker_volume_mounts_observed") == [],
|
|
cleanup.get("temporary_secret_root_absent") is True,
|
|
cleanup.get("private_apply_receipt_removed_with_secret_root") is True,
|
|
)
|
|
)
|
|
receipt["cleanup"] = cleanup
|
|
receipt["checks"]["container_and_private_temp_cleanup_proven"] = cleanup["all"]
|
|
receipt["status"] = (
|
|
"pass" if "error" not in receipt and receipt["checks"] and all(receipt["checks"].values()) else "fail"
|
|
)
|
|
receipt["current_tier"] = (
|
|
(
|
|
"T2_disposable_genesis_backed_runtime"
|
|
if genesis is not None
|
|
else "realistic_isolated_local_container_end_to_end"
|
|
)
|
|
if receipt["status"] == "pass"
|
|
else "runtime_verification_failed"
|
|
)
|
|
receipt["strongest_claim"] = (
|
|
(
|
|
"An exporter-receipt-bound real genesis dump was directly restored and manifest-proven before a retained "
|
|
"source packet was freshly compiled, staged, explicitly reviewed, selected and fresh-owned applied "
|
|
"through the gated worker, deterministically recompiled, and read back with payload-controlled "
|
|
"fingerprints in networkless disposable Postgres; the container and private temporary files were "
|
|
"then independently absent."
|
|
if genesis is not None
|
|
else "A retained real source packet was freshly compiled, staged, explicitly reviewed, "
|
|
"guarded-applied into networkless disposable Postgres, deterministically recompiled, and read "
|
|
"back with exact rows; the container and private temporary files were then independently absent."
|
|
)
|
|
if receipt["status"] == "pass"
|
|
else "The integrated-learning lifecycle did not pass all fail-closed checks."
|
|
)
|
|
receipt["not_proven"] = [
|
|
"VPS or GCP canonical apply",
|
|
"live Telegram send or reply",
|
|
"human acceptance of these candidate claims for production",
|
|
]
|
|
if persist_receipt:
|
|
write_private_json(output, receipt)
|
|
return receipt
|
|
|
|
|
|
def semantic_run_summary(receipt: dict[str, Any]) -> dict[str, Any]:
|
|
"""Project one run onto deterministic source, payload, and restore semantics."""
|
|
try:
|
|
identities = receipt["identities"]
|
|
applied = receipt["phases"]["applied"]
|
|
recompiled = receipt["phases"]["recompiled_readback"]
|
|
genesis = receipt["database_initialization"]["genesis"]
|
|
apply_receipt = applied["apply_receipt"]
|
|
return {
|
|
"consumed_inputs_manifest_sha256": receipt["consumed_inputs"]["preflight_manifest_sha256"],
|
|
"source": receipt["source"],
|
|
"compiled_bundle_sha256": receipt["compiled"]["bundle_sha256"],
|
|
"proposal_id": identities["proposal_id"],
|
|
"claim_ids": identities["claim_ids"],
|
|
"source_ids": identities["source_ids"],
|
|
"planned_evidence_keys": identities["planned_evidence_keys"],
|
|
"phase_statuses": {
|
|
"staged": receipt["phases"]["staged_pending_review"]["proposal"]["status"],
|
|
"approved": receipt["phases"]["approved_unapplied"]["proposal"]["status"],
|
|
"applied": applied["proposal"]["status"],
|
|
},
|
|
"payload_controlled_fingerprint": applied["payload_controlled_fingerprint"],
|
|
"apply_payload_sha256": apply_receipt["hashes"]["apply_payload_sha256"],
|
|
"expected_row_counts": apply_receipt["expected_row_counts"],
|
|
"actual_row_counts": apply_receipt["actual_row_counts"],
|
|
"recompiled_bundle_sha256": recompiled["bundle_sha256"],
|
|
"recompile_matches_initial": recompiled["matches_initial_compile"],
|
|
"apply_worker": {
|
|
"exact_candidate_id": applied["worker_action"]["exact_candidate_id"],
|
|
"credential_role": applied["worker_action"]["credential_role"],
|
|
"retry_failure_count": applied["worker_action"]["retry_failure_count"],
|
|
"failure_state_after_success": applied["worker_action"]["failure_state_after_success"],
|
|
"private_receipt_mode": applied["worker_action"]["private_receipt_mode"],
|
|
},
|
|
"genesis": {
|
|
"dump_sha256": genesis["dump"]["sha256"],
|
|
"manifest_sha256": genesis["manifest"]["sha256"],
|
|
"exporter_receipt_sha256": genesis["exporter_receipt"]["sha256"],
|
|
"provenance_binding_sha256": genesis["exporter_receipt"]["provenance_binding_sha256"],
|
|
"image_reference": genesis["image"]["reference"],
|
|
"parity_status": genesis["parity"]["status"],
|
|
"parity_problems": genesis["parity"]["problems"],
|
|
"parity_claim_scope": genesis["parity"]["claim_scope"],
|
|
"role_global_parity": genesis["parity"]["role_global_parity"],
|
|
"key_counts": genesis["key_counts"],
|
|
"canonical_schema_table_count": genesis["canonical_schema_table_count"],
|
|
},
|
|
}
|
|
except (KeyError, TypeError) as exc:
|
|
raise LifecycleError("completed genesis run is missing repeatability evidence") from exc
|
|
|
|
|
|
def verify_run_group_cleanup(run_group: str) -> dict[str, Any]:
|
|
"""Prove that no container created by this two-run invocation remains."""
|
|
docker = shutil.which("docker")
|
|
if not docker:
|
|
return {
|
|
"checked": False,
|
|
"run_group": run_group,
|
|
"container_names": [],
|
|
"all_absent": False,
|
|
"error": "docker executable is unavailable",
|
|
}
|
|
try:
|
|
result = subprocess.run(
|
|
[
|
|
docker,
|
|
"container",
|
|
"ls",
|
|
"-a",
|
|
"--filter",
|
|
f"label=livingip.canary.run_group={run_group}",
|
|
"--format",
|
|
"{{.Names}}",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
except OSError as exc:
|
|
return {
|
|
"checked": False,
|
|
"run_group": run_group,
|
|
"container_names": [],
|
|
"all_absent": False,
|
|
"error": type(exc).__name__,
|
|
}
|
|
names = sorted(line.strip() for line in result.stdout.splitlines() if line.strip())
|
|
return {
|
|
"checked": True,
|
|
"run_group": run_group,
|
|
"container_names": names,
|
|
"docker_readback_returncode": result.returncode,
|
|
"stdout_sha256": sha256_text(result.stdout),
|
|
"stderr_sha256": sha256_text(result.stderr),
|
|
"all_absent": result.returncode == 0 and not names,
|
|
}
|
|
|
|
|
|
def run_genesis_lifecycle(
|
|
source_packet: Path,
|
|
output: Path,
|
|
*,
|
|
review_action: str,
|
|
genesis_dump: Path,
|
|
genesis_manifest: Path,
|
|
genesis_exporter_receipt: Path,
|
|
image: str,
|
|
reviewed_by: str = REVIEWER_HANDLE,
|
|
review_note: str = DEFAULT_REVIEW_NOTE,
|
|
) -> dict[str, Any]:
|
|
"""Run the same genesis-backed lifecycle twice and compare deterministic semantics."""
|
|
output = output.expanduser().resolve()
|
|
source_packet = source_packet.expanduser().resolve()
|
|
protected_path_candidates = {
|
|
genesis_dump.expanduser().resolve(),
|
|
genesis_manifest.expanduser().resolve(),
|
|
genesis_exporter_receipt.expanduser().resolve(),
|
|
*source_packet_input_paths(source_packet),
|
|
}
|
|
if output in protected_path_candidates:
|
|
raise LifecycleError("--output must not overwrite a genesis or retained source-packet input")
|
|
run_group = f"leo-genesis-{uuid.uuid4().hex}"
|
|
receipt: dict[str, Any] = {
|
|
"artifact": GENESIS_RECEIPT_ARTIFACT,
|
|
"schema": GENESIS_RECEIPT_SCHEMA,
|
|
"status": "fail",
|
|
"required_tier": "T2_disposable_genesis_backed_runtime",
|
|
"current_tier": "not_proven",
|
|
"run_group": run_group,
|
|
"repeat_count_required": GENESIS_REPEAT_COUNT,
|
|
"source_packet": "source-packet",
|
|
"safety_boundary": {
|
|
"disposable_networkless_postgres_only": True,
|
|
"existing_database_target_supported": False,
|
|
"vps_or_gcp_mutation_supported": False,
|
|
"model_calls_performed": False,
|
|
"synthetic_canonical_bootstrap_supported": False,
|
|
"canonical_payload_preseed_supported": False,
|
|
"snapshot_repackaging_performed": False,
|
|
},
|
|
"pre_docker_validation": {"status": "pending", "docker_commands_attempted": 0},
|
|
"runs": [],
|
|
"repeatability": {"status": "not_run"},
|
|
"checks": {},
|
|
}
|
|
staged: StagedLifecycleInputs | None = None
|
|
genesis: GenesisInputs | None = None
|
|
final_staging_verification: dict[str, Any] | None = None
|
|
|
|
try:
|
|
if review_action != "approve":
|
|
raise LifecycleError("the only supported explicit review action is 'approve'")
|
|
if reviewed_by != REVIEWER_HANDLE:
|
|
raise LifecycleError(f"disposable reviewer must be {REVIEWER_HANDLE!r}")
|
|
if not review_note.strip():
|
|
raise LifecycleError("review note must be non-empty")
|
|
staged = stage_lifecycle_inputs(
|
|
source_packet,
|
|
genesis_dump,
|
|
genesis_manifest,
|
|
genesis_exporter_receipt,
|
|
)
|
|
genesis = validate_genesis_inputs(
|
|
staged.genesis_dump,
|
|
staged.genesis_manifest,
|
|
staged.exporter_receipt,
|
|
image,
|
|
parity_sql_path=staged.root / STAGED_ENGINE_DESTINATIONS["engine.parity_sql"],
|
|
guard_prerequisites_path=staged.root / STAGED_ENGINE_DESTINATIONS["engine.guard_sql"],
|
|
approve_script_path=staged.root / STAGED_ENGINE_DESTINATIONS["engine.approve_proposal"],
|
|
apply_worker_script_path=staged.root / STAGED_ENGINE_DESTINATIONS["engine.apply_worker"],
|
|
apply_script_path=staged.root / STAGED_ENGINE_DESTINATIONS["engine.apply_proposal"],
|
|
)
|
|
compiled, retained, source_paths = compile_source_packet(staged.source_packet)
|
|
receipt["execution"] = {
|
|
**staged.execution,
|
|
"engine_sha256": {name: row["sha256"] for name, row in staged.files.items() if name.startswith("engine.")},
|
|
"engine_set_sha256": canonical_sha256(
|
|
{name: row["sha256"] for name, row in staged.files.items() if name.startswith("engine.")}
|
|
),
|
|
}
|
|
receipt["immutable_staging"] = {
|
|
"schema": "livingip.leoImmutableLifecycleInputs.v1",
|
|
"private_directory_mode": "0500",
|
|
"file_mode": "0400",
|
|
"preflight_manifest_sha256": staged.manifest_sha256,
|
|
"files": staged.files,
|
|
"original_paths_reopened_after_staging": False,
|
|
}
|
|
receipt["inputs"] = {
|
|
"genesis_dump": {
|
|
"bytes": genesis.dump_bytes,
|
|
"sha256": genesis.dump_sha256,
|
|
},
|
|
"genesis_manifest": {
|
|
"bytes": genesis.manifest_bytes,
|
|
"sha256": genesis.manifest_sha256,
|
|
"role_settings_capture_complete": genesis.role_settings_capture_complete,
|
|
},
|
|
"genesis_exporter_receipt": {
|
|
"bytes": staged.files["genesis.exporter_receipt"]["bytes"],
|
|
"sha256": genesis.exporter_receipt_sha256,
|
|
"trust_root_receipt_sha256": genesis.trust_root_receipt_sha256,
|
|
"schema": genesis.exporter_receipt["schema"],
|
|
"artifact": genesis.exporter_receipt["artifact"],
|
|
"run_id": genesis.exporter_receipt["run_id"],
|
|
"capture_authorization_ref": genesis.capture_authorization_ref,
|
|
"source_identity": genesis.source_identity,
|
|
"provenance_binding_sha256": genesis.provenance_binding_sha256,
|
|
},
|
|
"image": genesis.image,
|
|
"source_packet": {
|
|
"compiled_bundle_sha256": canonical_sha256(compiled),
|
|
"retained_packet_file_sha256": sha256_file(source_paths["expected"]),
|
|
"retained_packet_canonical_sha256": canonical_sha256(retained),
|
|
},
|
|
}
|
|
receipt["pre_docker_validation"] = {
|
|
"status": "pass",
|
|
"docker_commands_attempted": 0,
|
|
"dump_custom_format_signature_valid": True,
|
|
"trusted_exporter_receipt_validated": True,
|
|
"trusted_exporter_receipt_sha256": genesis.trust_root_receipt_sha256,
|
|
"dump_hash_bound_by_exporter_receipt": True,
|
|
"manifest_hash_bound_by_exporter_receipt": True,
|
|
"source_identity_and_authorization_bound": True,
|
|
"provenance_binding_verified": True,
|
|
"manifest_contract_loaded": True,
|
|
"retained_packet_recompiled_byte_identically": canonical_json_bytes(compiled)
|
|
== canonical_json_bytes(retained),
|
|
"image_digest_pinned": True,
|
|
"immutable_staging_manifest_sha256": staged.manifest_sha256,
|
|
"executing_git_head": staged.execution["git_head"],
|
|
"engine_set_sha256": receipt["execution"]["engine_set_sha256"],
|
|
"committed_engine_dependency_closure_verified": staged.execution["engine_paths_match_head"] is True
|
|
and receipt["execution"]["engine_sha256"] == staged.execution["engine_head_sha256"],
|
|
}
|
|
|
|
for run_number in range(1, GENESIS_REPEAT_COUNT + 1):
|
|
consumed_before = verify_staged_inputs(staged)
|
|
run_receipt = run_lifecycle(
|
|
staged.source_packet,
|
|
output,
|
|
review_action=review_action,
|
|
reviewed_by=reviewed_by,
|
|
review_note=review_note,
|
|
genesis=genesis,
|
|
persist_receipt=False,
|
|
run_group=run_group,
|
|
run_number=run_number,
|
|
)
|
|
consumed_after = verify_staged_inputs(staged)
|
|
run_receipt["consumed_inputs"] = {
|
|
"preflight_manifest_sha256": staged.manifest_sha256,
|
|
"executing_git_head": staged.execution["git_head"],
|
|
"engine_set_sha256": receipt["execution"]["engine_set_sha256"],
|
|
"immutable_files_sha256": consumed_before["files_sha256"],
|
|
"verified_before_run": consumed_before,
|
|
"verified_after_run": consumed_after,
|
|
"original_paths_reopened": False,
|
|
}
|
|
receipt["runs"].append(run_receipt)
|
|
|
|
run_summaries = [semantic_run_summary(run) for run in receipt["runs"] if run.get("status") == "pass"]
|
|
repeatability_sha256 = [canonical_sha256(summary) for summary in run_summaries]
|
|
post_apply_fingerprints = [
|
|
run["phases"]["applied"]["payload_controlled_fingerprint"]["sha256"]
|
|
for run in receipt["runs"]
|
|
if run.get("status") == "pass"
|
|
]
|
|
identical_post_apply_fingerprints = (
|
|
len(post_apply_fingerprints) == GENESIS_REPEAT_COUNT and len(set(post_apply_fingerprints)) == 1
|
|
)
|
|
semantic_match = (
|
|
len(run_summaries) == GENESIS_REPEAT_COUNT
|
|
and len(set(repeatability_sha256)) == 1
|
|
and identical_post_apply_fingerprints
|
|
and all(run["cleanup"].get("all") is True for run in receipt["runs"])
|
|
)
|
|
receipt["repeatability"] = {
|
|
"status": "pass" if semantic_match else "fail",
|
|
"semantic_fingerprints_sha256": repeatability_sha256,
|
|
"semantic_match": semantic_match,
|
|
"post_apply_fingerprints_sha256": post_apply_fingerprints,
|
|
"identical_post_apply_fingerprints": identical_post_apply_fingerprints,
|
|
"generated_fields_excluded": [
|
|
"claim_evidence.id",
|
|
"claim_edges.id",
|
|
"created_at",
|
|
"updated_at",
|
|
"reviewed_at",
|
|
"applied_at",
|
|
"container identity",
|
|
"Postgres system identifier",
|
|
],
|
|
"summaries": run_summaries,
|
|
}
|
|
except (LifecycleError, OSError, ValueError, KeyError, TypeError, json.JSONDecodeError) as exc:
|
|
if receipt["pre_docker_validation"].get("status") == "pending":
|
|
receipt["pre_docker_validation"]["status"] = "fail"
|
|
receipt["error"] = {"type": type(exc).__name__, "message": str(exc)}
|
|
finally:
|
|
if staged is not None:
|
|
try:
|
|
final_staging_verification = verify_staged_inputs(staged)
|
|
except (LifecycleError, OSError) as exc:
|
|
final_staging_verification = {
|
|
"all_files_match_preflight": False,
|
|
"error": {"type": type(exc).__name__, "message": str(exc)},
|
|
}
|
|
receipt.setdefault("error", {"type": type(exc).__name__, "message": str(exc)})
|
|
staging_cleanup = cleanup_staged_inputs(staged.root if staged is not None else None)
|
|
if receipt["pre_docker_validation"].get("status") == "pass":
|
|
group_cleanup = verify_run_group_cleanup(run_group)
|
|
else:
|
|
group_cleanup = {
|
|
"checked": False,
|
|
"run_group": run_group,
|
|
"container_names": [],
|
|
"all_absent": True,
|
|
"reason": "input validation failed before any Docker command",
|
|
}
|
|
per_run_cleanup = [run.get("cleanup", {}).get("all") is True for run in receipt["runs"]]
|
|
receipt["cleanup"] = {
|
|
"per_run": per_run_cleanup,
|
|
"per_run_all": len(per_run_cleanup) == GENESIS_REPEAT_COUNT and all(per_run_cleanup),
|
|
"run_group_readback": group_cleanup,
|
|
"zero_orphan_containers": group_cleanup.get("all_absent") is True,
|
|
"immutable_staging_final_verification": final_staging_verification,
|
|
"immutable_staging_cleanup": staging_cleanup,
|
|
"zero_staging_leftovers": staging_cleanup["root_absent"] is True,
|
|
}
|
|
expected_run_binding = (
|
|
{
|
|
"preflight_manifest_sha256": staged.manifest_sha256,
|
|
"executing_git_head": staged.execution["git_head"],
|
|
"engine_set_sha256": receipt.get("execution", {}).get("engine_set_sha256"),
|
|
"immutable_files_sha256": final_staging_verification.get("files_sha256")
|
|
if isinstance(final_staging_verification, dict)
|
|
else None,
|
|
}
|
|
if staged is not None
|
|
else None
|
|
)
|
|
run_input_bindings = [
|
|
{
|
|
key: run.get("consumed_inputs", {}).get(key)
|
|
for key in (
|
|
"preflight_manifest_sha256",
|
|
"executing_git_head",
|
|
"engine_set_sha256",
|
|
"immutable_files_sha256",
|
|
)
|
|
}
|
|
for run in receipt["runs"]
|
|
]
|
|
absolute_path_values = absolute_path_value_pointers(receipt)
|
|
receipt["checks"] = {
|
|
"all_inputs_validated_before_docker": receipt["pre_docker_validation"].get("status") == "pass",
|
|
"all_inputs_copied_to_private_immutable_staging": staged is not None
|
|
and receipt.get("immutable_staging", {}).get("preflight_manifest_sha256") == staged.manifest_sha256,
|
|
"both_runs_consumed_preflight_bound_bytes": len(run_input_bindings) == GENESIS_REPEAT_COUNT
|
|
and expected_run_binding is not None
|
|
and all(binding == expected_run_binding for binding in run_input_bindings),
|
|
"exactly_two_runs_completed": len(receipt["runs"]) == GENESIS_REPEAT_COUNT,
|
|
"both_runs_passed": len(receipt["runs"]) == GENESIS_REPEAT_COUNT
|
|
and all(run.get("status") == "pass" for run in receipt["runs"]),
|
|
"both_runs_match_semantically": receipt["repeatability"].get("semantic_match") is True,
|
|
"identical_post_apply_fingerprints": receipt["repeatability"].get("identical_post_apply_fingerprints")
|
|
is True,
|
|
"both_runs_cleaned_up": receipt["cleanup"]["per_run_all"],
|
|
"zero_orphan_containers": receipt["cleanup"]["zero_orphan_containers"],
|
|
"zero_staging_leftovers": receipt["cleanup"]["zero_staging_leftovers"],
|
|
"committed_engine_dependency_closure_verified": staged is not None
|
|
and staged.execution.get("engine_paths_match_head") is True
|
|
and receipt.get("execution", {}).get("engine_sha256") == staged.execution.get("engine_head_sha256"),
|
|
"portable_receipt_has_no_absolute_paths": not absolute_path_values,
|
|
}
|
|
receipt["status"] = "pass" if receipt["checks"] and all(receipt["checks"].values()) else "fail"
|
|
if receipt["status"] == "fail" and "error" not in receipt:
|
|
failed_runs = [run.get("run_number") for run in receipt["runs"] if run.get("status") != "pass"]
|
|
receipt["error"] = {
|
|
"type": "GenesisRunFailure",
|
|
"message": f"genesis lifecycle runs did not pass: {failed_runs}",
|
|
}
|
|
receipt["current_tier"] = (
|
|
"T2_disposable_genesis_backed_runtime" if receipt["status"] == "pass" else "runtime_verification_failed"
|
|
)
|
|
receipt["strongest_claim"] = (
|
|
"The same immutable staged bytes were consumed twice from one trusted exporter-receipt-bound genesis "
|
|
"in independent networkless disposable PostgreSQL containers; both exact apply-worker lifecycles, "
|
|
"post-apply fingerprints, recompiles, and zero-leftover readbacks matched."
|
|
if receipt["status"] == "pass"
|
|
else "The two-run genesis-backed lifecycle did not pass every fail-closed T2 check."
|
|
)
|
|
receipt["not_proven"] = [
|
|
"VPS or GCP canonical mutation",
|
|
"production access or production readiness",
|
|
"live Telegram send or reply",
|
|
"blank-schema reconstruction of historical canonical knowledge",
|
|
]
|
|
if genesis is not None and not genesis.role_settings_capture_complete:
|
|
receipt["not_proven"].append(
|
|
"full role/global parity because the retained source manifest omitted role and database settings"
|
|
)
|
|
write_private_json(output, receipt)
|
|
return receipt
|
|
|
|
|
|
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--source-packet", required=True, type=Path)
|
|
parser.add_argument("--output", required=True, type=Path)
|
|
parser.add_argument("--genesis-dump", type=Path)
|
|
parser.add_argument("--genesis-manifest", type=Path)
|
|
parser.add_argument("--genesis-exporter-receipt", type=Path)
|
|
parser.add_argument(
|
|
"--image",
|
|
default=DEFAULT_GENESIS_IMAGE,
|
|
help="digest-pinned PostgreSQL image used only by genesis-backed mode",
|
|
)
|
|
parser.add_argument(
|
|
"--review-action",
|
|
required=True,
|
|
choices=("approve",),
|
|
help="explicit disposable-only review action; no default is accepted",
|
|
)
|
|
parser.add_argument("--reviewed-by", default=REVIEWER_HANDLE)
|
|
parser.add_argument("--review-note", default=DEFAULT_REVIEW_NOTE)
|
|
args = parser.parse_args(argv)
|
|
genesis_values = (
|
|
args.genesis_dump,
|
|
args.genesis_manifest,
|
|
args.genesis_exporter_receipt,
|
|
)
|
|
if any(value is not None for value in genesis_values) and not all(value is not None for value in genesis_values):
|
|
parser.error(
|
|
"genesis-backed mode requires --genesis-dump, --genesis-manifest, and --genesis-exporter-receipt together"
|
|
)
|
|
if args.genesis_dump is not None and not IMAGE_DIGEST_RE.fullmatch(args.image):
|
|
parser.error("--image must be pinned by a lowercase sha256 digest")
|
|
protected_inputs = set(source_packet_input_paths(args.source_packet))
|
|
if args.genesis_dump is not None:
|
|
protected_inputs.update(
|
|
{
|
|
args.genesis_dump.expanduser().resolve(),
|
|
args.genesis_manifest.expanduser().resolve(),
|
|
args.genesis_exporter_receipt.expanduser().resolve(),
|
|
}
|
|
)
|
|
if args.output.expanduser().resolve() in protected_inputs:
|
|
parser.error("--output must not overwrite a genesis or retained source-packet input")
|
|
return args
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
args = parse_args(argv)
|
|
if args.genesis_dump is not None:
|
|
receipt = run_genesis_lifecycle(
|
|
args.source_packet,
|
|
args.output,
|
|
review_action=args.review_action,
|
|
genesis_dump=args.genesis_dump,
|
|
genesis_manifest=args.genesis_manifest,
|
|
genesis_exporter_receipt=args.genesis_exporter_receipt,
|
|
image=args.image,
|
|
reviewed_by=args.reviewed_by,
|
|
review_note=args.review_note,
|
|
)
|
|
print_private_receipt_summary(args.output.resolve(), receipt)
|
|
else:
|
|
receipt = run_lifecycle(
|
|
args.source_packet,
|
|
args.output,
|
|
review_action=args.review_action,
|
|
reviewed_by=args.reviewed_by,
|
|
review_note=args.review_note,
|
|
)
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"status": receipt["status"],
|
|
"receipt": str(args.output.resolve()),
|
|
"proposal_id": receipt.get("identities", {}).get("proposal_id"),
|
|
"current_tier": receipt["current_tier"],
|
|
"cleanup": receipt["cleanup"].get("all"),
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
)
|
|
return 0 if receipt["status"] == "pass" else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|