1772 lines
75 KiB
Python
1772 lines
75 KiB
Python
#!/usr/bin/env python3
|
|
"""Run the complete no-send Working Leo suite against one generated Cloud SQL DB.
|
|
|
|
The script is an orchestration and transport adapter. Benchmark semantics,
|
|
composition packets/checks, proposal lifecycle transitions, and GatewayRunner
|
|
session behavior remain owned by their existing modules.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import ast
|
|
import asyncio
|
|
import copy
|
|
import hashlib
|
|
import ipaddress
|
|
import json
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import textwrap
|
|
import uuid
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
from typing import Any
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
REPO_ROOT = HERE.parent
|
|
sys.path.insert(0, str(HERE))
|
|
|
|
import apply_proposal as apply_proposal # noqa: E402
|
|
import approve_proposal # noqa: E402
|
|
import run_approve_claim_clone_canary as guarded # noqa: E402
|
|
import run_gcp_generated_db_direct_claim_suite as gcp # noqa: E402
|
|
import run_leo_clone_bound_handler_checkpoint as bound # noqa: E402
|
|
import run_leo_clone_composition_checkpoint as composition # noqa: E402
|
|
import run_leo_clone_lifecycle_checkpoint as lifecycle # noqa: E402
|
|
import working_leo_open_ended_benchmark as benchmark # noqa: E402
|
|
|
|
SCHEMA = "livingip.gcpGeneratedDbWorkingLeoSuite.v1"
|
|
VALIDATION_SCHEMA = "livingip.gcpGeneratedDbWorkingLeoValidation.v1"
|
|
TARGET_DB_PREFIX = "teleo_clone_"
|
|
EXPECTED_CATALOG_COUNT = 20
|
|
EXPECTED_COMPOSITION_CHECK_COUNT = 34
|
|
ALLOWED_WRITE_PURPOSES = frozenset({"stage", "review", "apply"})
|
|
DEFAULT_STAGE_ROLE = "kb_stage"
|
|
DEFAULT_REVIEW_ROLE = "kb_review"
|
|
DEFAULT_APPLY_ROLE = "kb_apply"
|
|
TARGET_IDENTITY_ARTIFACT = "gcp_generated_database_target_identity"
|
|
SOURCE_BASELINE_ARTIFACT = "gcp_working_leo_source_baseline"
|
|
ROLE_RECEIPT_PREFIX = "__GCP_ROLE_RECEIPT__"
|
|
UNSUPPORTED_INHERITED_COMPOSITION_CHECKS = frozenset(
|
|
{
|
|
"production_database_unchanged",
|
|
"production_gate_schema_unchanged",
|
|
}
|
|
)
|
|
UNSUPPORTED_INHERITED_LIFECYCLE_CHECKS = frozenset({"production_row_fingerprints_unchanged"})
|
|
|
|
PINNED_RUNTIME_PATHS = (
|
|
Path(__file__).resolve(),
|
|
HERE / "run_gcp_generated_db_direct_claim_suite.py",
|
|
HERE / "run_leo_clone_bound_handler_checkpoint.py",
|
|
HERE / "run_leo_clone_composition_checkpoint.py",
|
|
HERE / "run_leo_clone_lifecycle_checkpoint.py",
|
|
HERE / "working_leo_open_ended_benchmark.py",
|
|
HERE / "stage_normalized_proposal.py",
|
|
HERE / "approve_proposal.py",
|
|
HERE / "apply_proposal.py",
|
|
)
|
|
|
|
|
|
def sha256_json(value: Any) -> str:
|
|
payload = json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
|
|
return hashlib.sha256(payload.encode()).hexdigest()
|
|
|
|
|
|
def safe_message(exc: BaseException, *, secret_values: tuple[str, ...] = ()) -> str:
|
|
return bound.redact_text(str(exc), secret_values=secret_values)
|
|
|
|
|
|
def load_pinned_receipt(path: Path, expected_sha256: str, artifact: str) -> tuple[dict[str, Any], str]:
|
|
try:
|
|
content = path.read_bytes()
|
|
payload = json.loads(content)
|
|
except (OSError, json.JSONDecodeError) as exc:
|
|
raise bound.CheckpointError(f"{artifact} receipt is unreadable") from exc
|
|
actual_sha256 = hashlib.sha256(content).hexdigest()
|
|
if actual_sha256 != expected_sha256:
|
|
raise bound.CheckpointError(f"{artifact} receipt does not match its supplied SHA-256 pin")
|
|
if not isinstance(payload, dict) or payload.get("artifact") != artifact:
|
|
raise bound.CheckpointError(f"{artifact} receipt has the wrong artifact type")
|
|
if payload.get("status") != "pass" or payload.get("problems") != []:
|
|
raise bound.CheckpointError(f"{artifact} receipt is not a clean pass")
|
|
return payload, actual_sha256
|
|
|
|
|
|
def validate_target_identity_receipt(
|
|
args: argparse.Namespace, path: Path, expected_sha256: str
|
|
) -> dict[str, Any]:
|
|
payload, actual_sha256 = load_pinned_receipt(path, expected_sha256, TARGET_IDENTITY_ARTIFACT)
|
|
required = {
|
|
"target_database": args.target_db,
|
|
"project": args.project,
|
|
"instance": args.instance,
|
|
"server_address": args.host,
|
|
}
|
|
mismatches = [key for key, expected in required.items() if payload.get(key) != expected]
|
|
if mismatches:
|
|
raise bound.CheckpointError("target identity receipt mismatch: " + ", ".join(sorted(mismatches)))
|
|
if not str(payload.get("system_identifier") or "").strip():
|
|
raise bound.CheckpointError("target identity receipt is missing system_identifier")
|
|
try:
|
|
address = ipaddress.ip_address(str(payload.get("server_address") or ""))
|
|
except ValueError as exc:
|
|
raise bound.CheckpointError("target identity receipt has an invalid server address") from exc
|
|
if not address.is_private:
|
|
raise bound.CheckpointError("target identity receipt server address is not private")
|
|
return {
|
|
"sha256": actual_sha256,
|
|
"target_database": payload["target_database"],
|
|
"project": payload["project"],
|
|
"instance": payload["instance"],
|
|
"server_address": payload["server_address"],
|
|
"system_identifier": str(payload["system_identifier"]),
|
|
"captured_at_utc": payload.get("captured_at_utc"),
|
|
}
|
|
|
|
|
|
def validate_source_baseline_receipt(
|
|
args: argparse.Namespace, path: Path, expected_sha256: str
|
|
) -> dict[str, Any]:
|
|
payload, actual_sha256 = load_pinned_receipt(path, expected_sha256, SOURCE_BASELINE_ARTIFACT)
|
|
if payload.get("project") != args.project or payload.get("instance") != args.instance:
|
|
raise bound.CheckpointError("source baseline receipt project/instance context does not match")
|
|
guard = payload.get("guard_snapshot")
|
|
gate = payload.get("gate_schema")
|
|
if not isinstance(guard, dict) or not isinstance(gate, dict):
|
|
raise bound.CheckpointError("source baseline receipt is missing guard_snapshot or gate_schema")
|
|
identity = guard.get("database_identity") or {}
|
|
if not identity.get("current_database") or not identity.get("system_identifier"):
|
|
raise bound.CheckpointError("source baseline receipt has incomplete physical database identity")
|
|
for section in ("counts", "rowset_md5"):
|
|
values = guard.get(section)
|
|
missing = [table for table in composition.PRODUCTION_TABLES if table not in (values or {})]
|
|
if missing:
|
|
raise bound.CheckpointError(
|
|
f"source baseline receipt {section} is missing tables: " + ", ".join(sorted(missing))
|
|
)
|
|
return {
|
|
"sha256": actual_sha256,
|
|
"project": payload["project"],
|
|
"instance": payload["instance"],
|
|
"source_database": identity["current_database"],
|
|
"source_system_identifier": str(identity["system_identifier"]),
|
|
"guard_snapshot": guard,
|
|
"gate_schema": gate,
|
|
"captured_at_utc": payload.get("captured_at_utc"),
|
|
}
|
|
|
|
|
|
def runtime_manifest() -> list[dict[str, Any]]:
|
|
return [
|
|
{
|
|
"repo_relative_path": path.relative_to(REPO_ROOT).as_posix(),
|
|
"sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
|
|
"size_bytes": path.stat().st_size,
|
|
}
|
|
for path in PINNED_RUNTIME_PATHS
|
|
]
|
|
|
|
|
|
def full_catalog() -> list[dict[str, Any]]:
|
|
catalog = benchmark.prompt_catalog(include_cory_style=True, include_direct_claim_followups=True)
|
|
if len(catalog) != EXPECTED_CATALOG_COUNT:
|
|
raise bound.CheckpointError(
|
|
f"Working Leo catalog drifted: expected {EXPECTED_CATALOG_COUNT}, found {len(catalog)}"
|
|
)
|
|
return catalog
|
|
|
|
|
|
def composition_check_contract() -> list[str]:
|
|
"""Read the existing composition check names without restating them here."""
|
|
tree = ast.parse(textwrap.dedent(Path(composition.__file__).read_text(encoding="utf-8")))
|
|
for node in ast.walk(tree):
|
|
if not isinstance(node, ast.Dict):
|
|
continue
|
|
keys = [key.value for key in node.keys if isinstance(key, ast.Constant) and isinstance(key.value, str)]
|
|
if "source_packet_validated" in keys and "isolated_restart_and_memory_survived" in keys:
|
|
if len(keys) != EXPECTED_COMPOSITION_CHECK_COUNT:
|
|
raise bound.CheckpointError(
|
|
"composition scorer drifted: "
|
|
f"expected {EXPECTED_COMPOSITION_CHECK_COUNT} checks, found {len(keys)}"
|
|
)
|
|
return keys
|
|
raise bound.CheckpointError("existing composition scorer contract could not be located")
|
|
|
|
|
|
def validate_target_database(target_db: str) -> None:
|
|
if not bound.SAFE_DB_NAME_RE.fullmatch(target_db):
|
|
raise bound.CheckpointError("--target-db must be a safe explicit Postgres database name")
|
|
if not target_db.startswith(TARGET_DB_PREFIX):
|
|
raise bound.CheckpointError(
|
|
f"--target-db must start with {TARGET_DB_PREFIX!r}; live/fallback databases are forbidden"
|
|
)
|
|
|
|
|
|
def validate_local_inputs(args: argparse.Namespace) -> dict[str, Any]:
|
|
validate_target_database(args.target_db)
|
|
tool_sha = gcp.validate_reviewed_file(
|
|
args.cloudsql_tool,
|
|
gcp.REVIEWED_CLOUDSQL_TOOL_SHA256,
|
|
"Cloud SQL bridge helper",
|
|
)
|
|
manifest_sha = gcp.validate_reviewed_file(
|
|
args.manifest_sql,
|
|
gcp.REVIEWED_MANIFEST_SQL_SHA256,
|
|
"Postgres parity manifest",
|
|
)
|
|
parity = gcp.validate_parity_receipt(args.parity_receipt, args.target_db)
|
|
catalog = full_catalog()
|
|
composition_checks = composition_check_contract()
|
|
gcp_composition_checks = [
|
|
name for name in composition_checks if name not in UNSUPPORTED_INHERITED_COMPOSITION_CHECKS
|
|
]
|
|
source_manifest = runtime_manifest()
|
|
target_receipt_path = getattr(args, "target_identity_receipt", None)
|
|
target_receipt_pin = getattr(args, "target_identity_sha256", None)
|
|
source_receipt_path = getattr(args, "source_baseline_receipt", None)
|
|
source_receipt_pin = getattr(args, "source_baseline_sha256", None)
|
|
missing_execute_inputs = [
|
|
flag
|
|
for flag, value in (
|
|
("--target-identity-receipt", target_receipt_path),
|
|
("--target-identity-sha256", target_receipt_pin),
|
|
("--source-baseline-receipt", source_receipt_path),
|
|
("--source-baseline-sha256", source_receipt_pin),
|
|
("--instance", getattr(args, "instance", None)),
|
|
)
|
|
if not value
|
|
]
|
|
target_identity_receipt = (
|
|
validate_target_identity_receipt(args, target_receipt_path, target_receipt_pin)
|
|
if target_receipt_path and target_receipt_pin
|
|
else None
|
|
)
|
|
source_baseline_receipt = (
|
|
validate_source_baseline_receipt(args, source_receipt_path, source_receipt_pin)
|
|
if source_receipt_path and source_receipt_pin
|
|
else None
|
|
)
|
|
if getattr(args, "execute", False) and missing_execute_inputs:
|
|
raise bound.CheckpointError("execute inputs are missing: " + ", ".join(missing_execute_inputs))
|
|
return {
|
|
"reviewed_inputs": {
|
|
"cloudsql_tool_sha256": tool_sha,
|
|
"manifest_sql_sha256": manifest_sha,
|
|
},
|
|
"parity_receipt": parity,
|
|
"runtime_manifest": source_manifest,
|
|
"runtime_manifest_sha256": sha256_json(source_manifest),
|
|
"catalog_contract": {
|
|
"count": len(catalog),
|
|
"ids": [row["id"] for row in catalog],
|
|
"catalog_sha256": sha256_json(catalog),
|
|
"scorer": "working_leo_open_ended_benchmark.score_results",
|
|
},
|
|
"composition_contract": {
|
|
"inherited_check_count": len(composition_checks),
|
|
"inherited_check_names": composition_checks,
|
|
"inherited_checks_sha256": sha256_json(composition_checks),
|
|
"inherited_34_of_34_claimable": False,
|
|
"unsupported_in_gcp": sorted(UNSUPPORTED_INHERITED_COMPOSITION_CHECKS),
|
|
"gcp_required_check_count": len(gcp_composition_checks),
|
|
"gcp_required_check_names": gcp_composition_checks,
|
|
"gcp_required_checks_sha256": sha256_json(gcp_composition_checks),
|
|
"scorer": "run_leo_clone_composition_checkpoint.run_checkpoint",
|
|
},
|
|
"target_identity_receipt": target_identity_receipt,
|
|
"source_baseline_receipt": source_baseline_receipt,
|
|
"execute_input_contract": {
|
|
"ready": not missing_execute_inputs,
|
|
"missing": missing_execute_inputs,
|
|
},
|
|
}
|
|
|
|
|
|
def capability_receipt_sql() -> str:
|
|
return f"""select {apply_proposal.sql_literal(ROLE_RECEIPT_PREFIX)} || jsonb_build_object(
|
|
'session_user', session_user,
|
|
'current_user', current_user,
|
|
'current_database', current_database(),
|
|
'transaction_read_only', current_setting('transaction_read_only'),
|
|
'default_transaction_read_only', current_setting('default_transaction_read_only'),
|
|
'is_superuser', coalesce((select rolsuper from pg_roles where rolname = session_user), false),
|
|
'can_select_proposals', has_table_privilege(session_user, 'kb_stage.kb_proposals', 'SELECT'),
|
|
'can_insert_proposals', has_table_privilege(session_user, 'kb_stage.kb_proposals', 'INSERT'),
|
|
'can_update_proposals', has_table_privilege(session_user, 'kb_stage.kb_proposals', 'UPDATE'),
|
|
'can_approve', has_function_privilege(
|
|
session_user, 'kb_stage.approve_strict_proposal(uuid,text,jsonb,text,text)', 'EXECUTE'
|
|
),
|
|
'can_assert_apply', has_function_privilege(
|
|
session_user, 'kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamptz,text)', 'EXECUTE'
|
|
),
|
|
'can_finish_apply', has_function_privilege(
|
|
session_user,
|
|
'kb_stage.finish_approved_proposal(uuid,text,jsonb,text,uuid,timestamptz,text,text)',
|
|
'EXECUTE'
|
|
),
|
|
'can_insert_canonical',
|
|
has_table_privilege(session_user, 'public.claims', 'INSERT')
|
|
and has_table_privilege(session_user, 'public.sources', 'INSERT')
|
|
and has_table_privilege(session_user, 'public.claim_evidence', 'INSERT')
|
|
and has_table_privilege(session_user, 'public.claim_edges', 'INSERT')
|
|
)::text;
|
|
"""
|
|
|
|
|
|
def validate_capability_receipt(
|
|
receipt: dict[str, Any], *, args: argparse.Namespace, purpose: str, role: str, writable: bool
|
|
) -> None:
|
|
expected_roles = {
|
|
"read": args.read_role,
|
|
"stage": args.stage_role,
|
|
"review": "kb_review",
|
|
"apply": "kb_apply",
|
|
}
|
|
if role != expected_roles[purpose]:
|
|
raise bound.CheckpointError(f"{purpose} phase used an unexpected role")
|
|
checks = {
|
|
"session_user": receipt.get("session_user") == role,
|
|
"current_user": receipt.get("current_user") == role,
|
|
"current_database": receipt.get("current_database") == args.target_db,
|
|
"default_transaction_read_only": receipt.get("default_transaction_read_only")
|
|
== ("off" if writable else "on"),
|
|
"not_superuser": receipt.get("is_superuser") is False,
|
|
"can_select_proposals": receipt.get("can_select_proposals") is True,
|
|
"cannot_update_proposals": receipt.get("can_update_proposals") is False,
|
|
}
|
|
expected_capabilities = {
|
|
"read": {
|
|
"can_insert_proposals": False,
|
|
"can_approve": False,
|
|
"can_assert_apply": False,
|
|
"can_finish_apply": False,
|
|
"can_insert_canonical": False,
|
|
},
|
|
"stage": {
|
|
"can_insert_proposals": True,
|
|
"can_approve": False,
|
|
"can_assert_apply": False,
|
|
"can_finish_apply": False,
|
|
"can_insert_canonical": False,
|
|
},
|
|
"review": {
|
|
"can_insert_proposals": False,
|
|
"can_approve": True,
|
|
"can_assert_apply": False,
|
|
"can_finish_apply": False,
|
|
"can_insert_canonical": False,
|
|
},
|
|
"apply": {
|
|
"can_insert_proposals": False,
|
|
"can_approve": False,
|
|
"can_assert_apply": True,
|
|
"can_finish_apply": True,
|
|
"can_insert_canonical": True,
|
|
},
|
|
}
|
|
checks.update(
|
|
{
|
|
name: receipt.get(name) is expected
|
|
for name, expected in expected_capabilities[purpose].items()
|
|
}
|
|
)
|
|
failed = sorted(name for name, passed in checks.items() if not passed)
|
|
if failed:
|
|
raise bound.CheckpointError(f"{purpose} phase capability receipt failed: " + ", ".join(failed))
|
|
|
|
|
|
class CloudSqlExecutor:
|
|
"""Exact-target Cloud SQL transport with phase-scoped write authority."""
|
|
|
|
def __init__(self, args: argparse.Namespace) -> None:
|
|
self.args = args
|
|
self.receipts: list[dict[str, Any]] = []
|
|
|
|
def _password(self, secret_name: str) -> str:
|
|
try:
|
|
value = gcp.run(
|
|
[
|
|
"gcloud",
|
|
"secrets",
|
|
"versions",
|
|
"access",
|
|
"latest",
|
|
f"--secret={secret_name}",
|
|
f"--project={self.args.project}",
|
|
]
|
|
).strip()
|
|
except BaseException as exc:
|
|
raise bound.CheckpointError("Cloud SQL credential resolution failed") from exc
|
|
if not value:
|
|
raise bound.CheckpointError(f"Cloud SQL credential secret {secret_name!r} resolved empty")
|
|
return value
|
|
|
|
def execute(
|
|
self,
|
|
sql: str,
|
|
*,
|
|
role: str,
|
|
password_secret: str,
|
|
purpose: str = "read",
|
|
writable: bool = False,
|
|
) -> str:
|
|
if purpose not in {"read", *ALLOWED_WRITE_PURPOSES}:
|
|
raise bound.CheckpointError("unknown database authority phase")
|
|
if writable and purpose not in ALLOWED_WRITE_PURPOSES:
|
|
raise bound.CheckpointError("write mode is allowed only for stage/review/apply controller phases")
|
|
if writable and not getattr(self.args, f"allow_{purpose}", False):
|
|
raise bound.CheckpointError(f"controller phase {purpose!r} was not explicitly authorized")
|
|
validate_target_database(self.args.target_db)
|
|
if not bound.SAFE_DB_NAME_RE.fullmatch(role):
|
|
raise bound.CheckpointError("Cloud SQL role must be an explicit safe identifier")
|
|
if writable and role == "postgres":
|
|
raise bound.CheckpointError("postgres write authority is forbidden")
|
|
if purpose == "stage" and role in {
|
|
self.args.read_role,
|
|
self.args.review_role,
|
|
self.args.apply_role,
|
|
"postgres",
|
|
}:
|
|
raise bound.CheckpointError("stage authority must use a dedicated non-postgres role")
|
|
if purpose == "review" and role != "kb_review":
|
|
raise bound.CheckpointError("review authority must use kb_review")
|
|
if purpose == "apply" and role != "kb_apply":
|
|
raise bound.CheckpointError("apply authority must use kb_apply")
|
|
password = self._password(password_secret)
|
|
pgoptions = "-c default_transaction_read_only=off" if writable else "-c default_transaction_read_only=on"
|
|
identity_guard = """\\set ON_ERROR_STOP on
|
|
select current_database() = :'expected_database' as exact_database_bound \\gset
|
|
\\if :exact_database_bound
|
|
\\else
|
|
\\echo 'refusing database fallback' >&2
|
|
\\quit 97
|
|
\\endif
|
|
"""
|
|
command = [
|
|
"psql",
|
|
(
|
|
f"host={self.args.host} port=5432 dbname={self.args.target_db} "
|
|
f"user={role} sslmode=require connect_timeout=8"
|
|
),
|
|
"-X",
|
|
"-Atq",
|
|
"-v",
|
|
"ON_ERROR_STOP=1",
|
|
"-v",
|
|
f"expected_database={self.args.target_db}",
|
|
]
|
|
env = {**os.environ, "PGPASSWORD": password, "PGOPTIONS": pgoptions}
|
|
try:
|
|
try:
|
|
output = gcp.run(
|
|
command,
|
|
env=env,
|
|
input_text=identity_guard + capability_receipt_sql() + sql,
|
|
)
|
|
except BaseException as exc:
|
|
raise bound.CheckpointError(safe_message(exc, secret_values=(password,))) from exc
|
|
finally:
|
|
env.pop("PGPASSWORD", None)
|
|
env.pop("PGOPTIONS", None)
|
|
password = ""
|
|
lines = output.splitlines()
|
|
receipt_lines = [line for line in lines if line.startswith(ROLE_RECEIPT_PREFIX)]
|
|
if len(receipt_lines) != 1:
|
|
raise bound.CheckpointError(f"{purpose} phase did not return exactly one capability receipt")
|
|
try:
|
|
capability = json.loads(receipt_lines[0][len(ROLE_RECEIPT_PREFIX) :])
|
|
except json.JSONDecodeError as exc:
|
|
raise bound.CheckpointError(f"{purpose} phase returned an invalid capability receipt") from exc
|
|
validate_capability_receipt(capability, args=self.args, purpose=purpose, role=role, writable=writable)
|
|
self.receipts.append(
|
|
{
|
|
"purpose": purpose,
|
|
"role": role,
|
|
"target_database": self.args.target_db,
|
|
"writable": writable,
|
|
"default_transaction_read_only": "off" if writable else "on",
|
|
"sql_sha256": hashlib.sha256(sql.encode()).hexdigest(),
|
|
"explicit_database_guard": True,
|
|
"capability_receipt": capability,
|
|
}
|
|
)
|
|
return "\n".join(line for line in lines if not line.startswith(ROLE_RECEIPT_PREFIX)) + (
|
|
"\n" if output.endswith("\n") else ""
|
|
)
|
|
|
|
def read(
|
|
self,
|
|
sql: str,
|
|
*,
|
|
role: str | None = None,
|
|
secret: str | None = None,
|
|
purpose: str = "read",
|
|
) -> str:
|
|
return self.execute(
|
|
sql,
|
|
role=role or self.args.read_role,
|
|
password_secret=secret or self.args.password_secret,
|
|
purpose=purpose,
|
|
)
|
|
|
|
def stage(self, sql: str) -> str:
|
|
return self.execute(
|
|
sql,
|
|
role=self.args.stage_role,
|
|
password_secret=self.args.stage_password_secret,
|
|
purpose="stage",
|
|
writable=True,
|
|
)
|
|
|
|
def review(self, sql: str) -> str:
|
|
return self.execute(
|
|
sql,
|
|
role=self.args.review_role,
|
|
password_secret=self.args.review_password_secret,
|
|
purpose="review",
|
|
writable=True,
|
|
)
|
|
|
|
def apply(self, sql: str) -> str:
|
|
return self.execute(
|
|
sql,
|
|
role=self.args.apply_role,
|
|
password_secret=self.args.apply_password_secret,
|
|
purpose="apply",
|
|
writable=True,
|
|
)
|
|
|
|
def json(self, sql: str, *, stage: bool = False) -> Any:
|
|
output = self.stage(sql) if stage else self.read(sql)
|
|
rows = [line.strip() for line in output.splitlines() if line.strip().startswith(("{", "["))]
|
|
if not rows:
|
|
raise bound.CheckpointError("Cloud SQL query returned no JSON row")
|
|
try:
|
|
return json.loads(rows[-1])
|
|
except json.JSONDecodeError as exc:
|
|
raise bound.CheckpointError("Cloud SQL query returned invalid JSON") from exc
|
|
|
|
|
|
def verify_distinct_credential_values(executor: CloudSqlExecutor) -> dict[str, Any]:
|
|
values: list[str] = []
|
|
try:
|
|
for secret_name in (
|
|
executor.args.password_secret,
|
|
executor.args.stage_password_secret,
|
|
executor.args.review_password_secret,
|
|
executor.args.apply_password_secret,
|
|
):
|
|
values.append(executor._password(secret_name))
|
|
if len(set(values)) != len(values):
|
|
raise bound.CheckpointError("read/stage/review/apply credential values must be distinct")
|
|
return {"checked": True, "distinct": True, "credential_count": len(values)}
|
|
finally:
|
|
for index in range(len(values)):
|
|
values[index] = ""
|
|
values.clear()
|
|
|
|
|
|
def _completed(command: list[str], returncode: int, stdout: str = "", stderr: str = "") -> subprocess.CompletedProcess[str]:
|
|
return subprocess.CompletedProcess(command, returncode, stdout, stderr)
|
|
|
|
|
|
def _load_proposal(executor: CloudSqlExecutor, proposal_id: str, *, role: str, secret: str) -> dict[str, Any]:
|
|
args = SimpleNamespace(proposal_id=proposal_id)
|
|
sql = f"""select jsonb_build_object(
|
|
'id', id::text, 'proposal_type', proposal_type, 'status', status,
|
|
'payload', payload, 'reviewed_by_handle', reviewed_by_handle,
|
|
'reviewed_by_agent_id', reviewed_by_agent_id::text,
|
|
'reviewed_at', reviewed_at::text, 'review_note', review_note
|
|
)::text from kb_stage.kb_proposals
|
|
where id = {apply_proposal.sql_literal(args.proposal_id)}::uuid;"""
|
|
purpose = "review" if role == executor.args.review_role else "apply"
|
|
output = executor.read(sql, role=role, secret=secret, purpose=purpose).strip()
|
|
if not output:
|
|
raise bound.CheckpointError(f"proposal not found in generated database: {proposal_id}")
|
|
return json.loads(output.splitlines()[-1])
|
|
|
|
|
|
def _review_command(executor: CloudSqlExecutor, proposal_id: str, *, dry_run: bool) -> subprocess.CompletedProcess[str]:
|
|
command = ["gcp-controller-review", proposal_id]
|
|
try:
|
|
proposal = _load_proposal(
|
|
executor,
|
|
proposal_id,
|
|
role=executor.args.review_role,
|
|
secret=executor.args.review_password_secret,
|
|
)
|
|
approve_proposal.assert_approvable(proposal, lifecycle.REVIEWER_HANDLE, lifecycle.REVIEW_NOTE)
|
|
sql = approve_proposal.build_approve_sql(proposal, lifecycle.REVIEWER_HANDLE, lifecycle.REVIEW_NOTE)
|
|
if dry_run:
|
|
return _completed(command, 0, sql)
|
|
output = executor.review(sql)
|
|
return _completed(command, 0, output)
|
|
except (Exception, SystemExit) as exc:
|
|
return _completed(command, 1, stderr=safe_message(exc))
|
|
|
|
|
|
def _apply_command(executor: CloudSqlExecutor, proposal_id: str, *, dry_run: bool) -> subprocess.CompletedProcess[str]:
|
|
command = ["gcp-controller-apply", proposal_id]
|
|
try:
|
|
proposal = _load_proposal(
|
|
executor,
|
|
proposal_id,
|
|
role=executor.args.apply_role,
|
|
secret=executor.args.apply_password_secret,
|
|
)
|
|
apply_proposal.assert_applyable(proposal)
|
|
sql = apply_proposal.build_apply_sql(proposal, lifecycle.APPLIED_BY_HANDLE)
|
|
if dry_run:
|
|
return _completed(command, 0, sql)
|
|
output = executor.apply(sql)
|
|
return _completed(command, 0, output)
|
|
except (Exception, SystemExit) as exc:
|
|
return _completed(command, 1, stderr=safe_message(exc))
|
|
|
|
|
|
def _target_identity(args: argparse.Namespace, db_identity: dict[str, Any]) -> dict[str, Any]:
|
|
return {
|
|
"id": f"cloudsql:{db_identity['system_identifier']}:{args.target_db}",
|
|
"name": args.target_db,
|
|
"image": "cloudsql-postgres",
|
|
"labels": {bound.DISPOSABLE_LABEL_KEY: bound.DISPOSABLE_LABEL_VALUE},
|
|
"network_mode": "none",
|
|
"ports": {},
|
|
"mount_sources": [],
|
|
"started_at": None,
|
|
}
|
|
|
|
|
|
def assert_live_target_identity(
|
|
args: argparse.Namespace, retained: dict[str, Any], live: dict[str, Any]
|
|
) -> None:
|
|
checks = {
|
|
"target_database": live.get("current_database") == retained.get("target_database") == args.target_db,
|
|
"system_identifier": str(live.get("system_identifier") or "")
|
|
== str(retained.get("system_identifier") or ""),
|
|
"server_address": str(live.get("server_address") or "")
|
|
== str(retained.get("server_address") or "")
|
|
== args.host,
|
|
"project": retained.get("project") == args.project,
|
|
"instance": retained.get("instance") == args.instance,
|
|
"tls": live.get("ssl") is True,
|
|
"default_read_only": live.get("default_transaction_read_only") == "on",
|
|
}
|
|
failed = sorted(name for name, passed in checks.items() if not passed)
|
|
if failed:
|
|
raise bound.CheckpointError("live target identity does not match retained receipt: " + ", ".join(failed))
|
|
|
|
|
|
def _source_identity(source_baseline: dict[str, Any]) -> dict[str, Any]:
|
|
identity = source_baseline["guard_snapshot"]["database_identity"]
|
|
return {
|
|
"id": f"retained-source:{identity['system_identifier']}:{identity['current_database']}",
|
|
"name": str(identity["current_database"]),
|
|
"image": "retained-source-baseline-receipt",
|
|
"labels": {},
|
|
"network_mode": "reference-only",
|
|
"ports": {},
|
|
"mount_sources": [],
|
|
"started_at": None,
|
|
}
|
|
|
|
|
|
def _build_gcp_read_wrapper(
|
|
args: argparse.Namespace,
|
|
*,
|
|
cloudsql_tool: Path,
|
|
tool_log: Path,
|
|
run_nonce: str,
|
|
prompt_id: str | None = None,
|
|
) -> str:
|
|
wrapper = gcp.build_cloudsql_wrapper(
|
|
cloudsql_tool=cloudsql_tool,
|
|
tool_log=tool_log,
|
|
target_db=args.target_db,
|
|
host=args.host,
|
|
project=args.project,
|
|
password_secret=args.password_secret,
|
|
run_nonce=run_nonce,
|
|
)
|
|
wrapper = wrapper.replace(
|
|
f"PASSWORD_SECRET={shlex.quote(args.password_secret)}\n",
|
|
f"PASSWORD_SECRET={shlex.quote(args.password_secret)}\nREAD_ROLE={shlex.quote(args.read_role)}\n",
|
|
1,
|
|
)
|
|
wrapper = wrapper.replace("user=postgres sslmode=require", "user=$READ_ROLE sslmode=require", 1)
|
|
wrapper = wrapper.replace(
|
|
" 'default_transaction_read_only', current_setting('default_transaction_read_only')\n",
|
|
" 'default_transaction_read_only', current_setting('default_transaction_read_only'),\n"
|
|
" 'session_user', session_user,\n"
|
|
" 'current_user', current_user\n",
|
|
1,
|
|
)
|
|
wrapper = wrapper.replace(
|
|
'--password-secret "$PASSWORD_SECRET" "$@"',
|
|
'--password-secret "$PASSWORD_SECRET" --user "$READ_ROLE" "$@"',
|
|
1,
|
|
)
|
|
if prompt_id is not None:
|
|
encoded_prompt_id = json.dumps(prompt_id)
|
|
wrapper = wrapper.replace(
|
|
' "run_nonce": run_nonce,\n "container":',
|
|
f' "run_nonce": run_nonce,\n "prompt_id": {encoded_prompt_id},\n "container":',
|
|
)
|
|
if "user=$READ_ROLE" not in wrapper or '--user "$READ_ROLE"' not in wrapper:
|
|
raise bound.CheckpointError("reviewed Cloud SQL wrapper could not be rebound to the dedicated read role")
|
|
return wrapper
|
|
|
|
|
|
def _cloudsql_lifecycle_wrapper(
|
|
args: argparse.Namespace,
|
|
*,
|
|
tool_log: Path,
|
|
run_marker: str,
|
|
run_nonce: str,
|
|
cloudsql_tool: Path | None = None,
|
|
) -> str:
|
|
base = _build_gcp_read_wrapper(
|
|
args,
|
|
cloudsql_tool=cloudsql_tool or args.cloudsql_tool,
|
|
tool_log=tool_log,
|
|
run_nonce=run_nonce,
|
|
)
|
|
marker = "if ! PGPASSWORD=\"$(gcloud secrets versions access latest"
|
|
if marker not in base:
|
|
raise bound.CheckpointError("reviewed Cloud SQL wrapper shape changed; lifecycle injection refused")
|
|
internal = shlex.join(
|
|
[
|
|
str(Path(sys.executable).resolve()),
|
|
str(Path(__file__).resolve()),
|
|
lifecycle.INTERNAL_STAGE_COMMAND,
|
|
"--target-db",
|
|
args.target_db,
|
|
"--host",
|
|
args.host,
|
|
"--project",
|
|
args.project,
|
|
"--instance",
|
|
args.instance,
|
|
"--password-secret",
|
|
args.password_secret,
|
|
"--read-role",
|
|
args.read_role,
|
|
"--stage-password-secret",
|
|
args.stage_password_secret,
|
|
"--stage-role",
|
|
args.stage_role,
|
|
"--run-marker",
|
|
run_marker,
|
|
"--tool-log",
|
|
str(tool_log),
|
|
"--run-nonce",
|
|
run_nonce,
|
|
"--target-identity-receipt",
|
|
str(args.target_identity_receipt),
|
|
"--target-identity-sha256",
|
|
args.target_identity_sha256,
|
|
]
|
|
)
|
|
branch = f"""if [[ "${{1:-}}" == {shlex.quote(lifecycle.STAGE_COMMAND)} ]]; then
|
|
if [[ "$#" -ne 1 ]]; then
|
|
printf '%s\\n' '{lifecycle.STAGE_COMMAND} accepts no model-supplied arguments' >&2
|
|
exit 64
|
|
fi
|
|
exec {internal}
|
|
fi
|
|
|
|
"""
|
|
return base.replace(marker, branch + marker, 1)
|
|
|
|
|
|
class RuntimeAdapter:
|
|
"""Temporarily route existing clone runner transport through Cloud SQL."""
|
|
|
|
def __init__(
|
|
self,
|
|
args: argparse.Namespace,
|
|
executor: CloudSqlExecutor,
|
|
source_baseline: dict[str, Any],
|
|
db_identity: dict[str, Any],
|
|
) -> None:
|
|
self.args = args
|
|
self.executor = executor
|
|
self.source_baseline = source_baseline
|
|
self.target = _target_identity(args, db_identity)
|
|
self.source = _source_identity(source_baseline)
|
|
self.originals: list[tuple[Any, str, Any]] = []
|
|
|
|
def patch(self, module: Any, name: str, replacement: Any) -> None:
|
|
self.originals.append((module, name, getattr(module, name)))
|
|
setattr(module, name, replacement)
|
|
|
|
def _psql_json(self, container: str, database: str, sql: str) -> Any:
|
|
self._assert_target(container, database)
|
|
normalized = sql.lower()
|
|
stage = "normalized_stage_result" in normalized or "lifecycle_stage_result" in normalized
|
|
if not stage and any(token in normalized for token in ("insert into", "update ", "delete from", "drop ")):
|
|
raise bound.CheckpointError("unclassified SQL write refused by GCP runtime adapter")
|
|
return self.executor.json(sql, stage=stage)
|
|
|
|
def _assert_target(self, container: str, database: str) -> None:
|
|
if database != self.args.target_db or container not in {self.args.target_db, self.target["id"]}:
|
|
raise bound.CheckpointError("database transport attempted to rebind away from supplied generated DB")
|
|
|
|
def _container_identity(self, container: str) -> dict[str, Any]:
|
|
if container in {self.args.target_db, self.target["id"]}:
|
|
return copy.deepcopy(self.target)
|
|
if container == bound.PRODUCTION_CONTAINER:
|
|
return copy.deepcopy(self.source)
|
|
raise bound.CheckpointError(f"unknown database identity requested: {container!r}")
|
|
|
|
def _guard_snapshot(self, container: str, database: str, *, tables: tuple[str, ...]) -> dict[str, Any]:
|
|
if container == bound.PRODUCTION_CONTAINER:
|
|
return copy.deepcopy(self.source_baseline["guard_snapshot"])
|
|
self._assert_target(container, database)
|
|
return self.saved_guard_snapshot(self.target["id"], self.args.target_db, tables=tables)
|
|
|
|
def _gate_schema(self, container: str, database: str) -> dict[str, Any]:
|
|
if container == bound.PRODUCTION_CONTAINER:
|
|
return copy.deepcopy(self.source_baseline["gate_schema"])
|
|
self._assert_target(container, database)
|
|
return self.saved_gate_schema(self.target["id"], self.args.target_db)
|
|
|
|
def _bound_patch_bridge(self, temp_profile: Path, _container: str, _database: str) -> dict[str, Any]:
|
|
bridge = gcp.patch_temp_bridge(self.args, temp_profile)
|
|
wrapper = Path(bridge["wrapper_path"])
|
|
wrapper_text = _build_gcp_read_wrapper(
|
|
self.args,
|
|
cloudsql_tool=temp_profile / "bin" / "cloudsql_memory_tool.py",
|
|
tool_log=Path(bridge["tool_log_path"]),
|
|
run_nonce=bridge["run_nonce"],
|
|
)
|
|
bound._detach_and_write(wrapper, wrapper_text, mode=0o700)
|
|
bridge["wrapper_sha256"] = hashlib.sha256(wrapper_text.encode()).hexdigest()
|
|
bridge["bridge_skill_path"] = str(temp_profile / "skills" / "teleo-kb-bridge" / "SKILL.md")
|
|
bridge["bound_container_id"] = self.target["id"]
|
|
return bridge
|
|
|
|
def _read_tool_proof(self, path: Path, _container: str, _database: str, **kwargs: Any) -> dict[str, Any]:
|
|
return self.saved_read_tool_proof(path, gcp.SOURCE_COMPUTE, self.args.target_db, **kwargs)
|
|
|
|
def _copy_profile(self, *, run_id: str, prompt_id: str, **_kwargs: Any) -> tuple[Path, dict[str, Any]]:
|
|
return self.saved_copy_profile(run_id=run_id, prompt_id=prompt_id, live_profile=self.args.live_profile)
|
|
|
|
def _copy_auth(self, temp_profile: Path, **_kwargs: Any) -> dict[str, Any]:
|
|
return self.saved_copy_auth(temp_profile, live_profile=self.args.live_profile)
|
|
|
|
def _guarded_psql(self, container: str, database: str, sql: str, *, tuples: bool = True) -> str:
|
|
del tuples
|
|
self._assert_target(container, database)
|
|
return self.executor.read(sql)
|
|
|
|
def _approve(self, _guard_args: argparse.Namespace, proposal_id: str, database: str, *, dry_run: bool = False) -> subprocess.CompletedProcess[str]:
|
|
if database != self.args.target_db:
|
|
raise bound.CheckpointError("review attempted database fallback")
|
|
return _review_command(self.executor, proposal_id, dry_run=dry_run)
|
|
|
|
def _apply(self, _guard_args: argparse.Namespace, proposal_id: str, database: str, *, dry_run: bool = False) -> subprocess.CompletedProcess[str]:
|
|
if database != self.args.target_db:
|
|
raise bound.CheckpointError("apply attempted database fallback")
|
|
return _apply_command(self.executor, proposal_id, dry_run=dry_run)
|
|
|
|
def _lifecycle_wrapper(self, *, tool_log: Path, run_marker: str, run_nonce: str, **_kwargs: Any) -> str:
|
|
return _cloudsql_lifecycle_wrapper(
|
|
self.args,
|
|
tool_log=tool_log,
|
|
run_marker=run_marker,
|
|
run_nonce=run_nonce,
|
|
cloudsql_tool=tool_log.parent / "bin" / "cloudsql_memory_tool.py",
|
|
)
|
|
|
|
def __enter__(self) -> RuntimeAdapter:
|
|
try:
|
|
self.saved_psql_json = bound._psql_json
|
|
self.saved_guard_snapshot = bound.database_guard_snapshot
|
|
self.saved_gate_schema = composition.gate_schema_manifest
|
|
self.saved_read_tool_proof = bound.read_tool_proof
|
|
self.saved_copy_profile = bound.copy_profile
|
|
self.saved_copy_auth = bound.copy_ephemeral_model_auth
|
|
self.patch(bound, "_psql_json", self._psql_json)
|
|
self.target_gate = self.saved_gate_schema(self.target["id"], self.args.target_db)
|
|
|
|
self.patch(bound, "container_identity", self._container_identity)
|
|
self.patch(bound, "database_guard_snapshot", self._guard_snapshot)
|
|
self.patch(bound, "service_state", lambda: gcp.service_state(self.args.service))
|
|
self.patch(bound, "bridge_hashes", lambda _profile=None: gcp.profile_hashes(self.args.live_profile))
|
|
self.patch(bound, "patch_temp_bridge", self._bound_patch_bridge)
|
|
self.patch(bound, "read_tool_proof", self._read_tool_proof)
|
|
self.patch(bound, "copy_profile", self._copy_profile)
|
|
self.patch(bound, "copy_ephemeral_model_auth", self._copy_auth)
|
|
self.patch(guarded, "_psql", self._guarded_psql)
|
|
self.patch(guarded, "_approve", self._approve)
|
|
self.patch(guarded, "_apply", self._apply)
|
|
self.patch(
|
|
lifecycle,
|
|
"assert_disposable_target",
|
|
self._assert_disposable_target,
|
|
)
|
|
self.patch(lifecycle, "build_lifecycle_wrapper", self._lifecycle_wrapper)
|
|
self.patch(composition, "gate_schema_manifest", self._gate_schema)
|
|
return self
|
|
except BaseException:
|
|
self._restore()
|
|
raise
|
|
|
|
def _assert_disposable_target(
|
|
self, container: str, database: str
|
|
) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
self._assert_target(container, database)
|
|
target = self._container_identity(container)
|
|
source = self._container_identity(bound.PRODUCTION_CONTAINER)
|
|
bound.validate_disposable_target_identity(target, source)
|
|
return target, source
|
|
|
|
def __exit__(self, _type: Any, _value: Any, _traceback: Any) -> None:
|
|
self._restore()
|
|
|
|
def _restore(self) -> None:
|
|
for module, name, original in reversed(self.originals):
|
|
setattr(module, name, original)
|
|
self.originals.clear()
|
|
|
|
|
|
def database_identity_receipt(executor: CloudSqlExecutor) -> dict[str, Any]:
|
|
return executor.json(
|
|
"""begin transaction read only;
|
|
select jsonb_build_object(
|
|
'current_database', current_database(),
|
|
'system_identifier', (select system_identifier::text from pg_control_system()),
|
|
'server_address', host(inet_server_addr()),
|
|
'server_port', inet_server_port(),
|
|
'ssl', coalesce((select ssl from pg_stat_ssl where pid=pg_backend_pid()), false),
|
|
'transaction_read_only', current_setting('transaction_read_only'),
|
|
'default_transaction_read_only', current_setting('default_transaction_read_only'),
|
|
'session_user', session_user,
|
|
'current_user', current_user
|
|
)::text;
|
|
rollback;
|
|
"""
|
|
)
|
|
|
|
|
|
def _catalog_turn_args(args: argparse.Namespace, prompt: dict[str, Any]) -> SimpleNamespace:
|
|
return SimpleNamespace(
|
|
chat_id=args.chat_id,
|
|
user_id=args.user_id,
|
|
user_name=args.user_name,
|
|
prompt=prompt["message"],
|
|
prompt_id=prompt["id"],
|
|
run_id=args.run_id,
|
|
turn_timeout=args.turn_timeout,
|
|
)
|
|
|
|
|
|
async def run_catalog(args: argparse.Namespace, db_identity: dict[str, Any]) -> dict[str, Any]:
|
|
catalog = full_catalog()
|
|
report: dict[str, Any] = {
|
|
"catalog_count": len(catalog),
|
|
"results": [],
|
|
"errors": [],
|
|
}
|
|
for index, prompt in enumerate(catalog, 1):
|
|
try:
|
|
result = await run_catalog_prompt(args, prompt, db_identity, index=index)
|
|
except Exception as exc:
|
|
result = {
|
|
"turn": index,
|
|
"prompt_id": prompt["id"],
|
|
"dimension": prompt["dimension"],
|
|
"prompt": prompt["message"],
|
|
"reply": "",
|
|
"evidence_pass": False,
|
|
"pass": False,
|
|
"errors": [{"type": type(exc).__name__, "message": safe_message(exc)}],
|
|
}
|
|
report["errors"].append(
|
|
{"prompt_id": prompt["id"], "type": type(exc).__name__, "message": safe_message(exc)}
|
|
)
|
|
report["results"].append(result)
|
|
report["score"] = benchmark.score_results(
|
|
report["results"],
|
|
include_cory_style=True,
|
|
include_direct_claim_followups=True,
|
|
)
|
|
scores = {row["prompt_id"]: row for row in report["score"]["scores"]}
|
|
for result in report["results"]:
|
|
scorer_pass = scores.get(result["prompt_id"], {}).get("pass") is True
|
|
result["scorer_pass"] = scorer_pass
|
|
result["pass"] = scorer_pass and result.get("evidence_pass") is True
|
|
isolation = catalog_session_isolation(report["results"])
|
|
report["session_isolation"] = isolation
|
|
report["checks"] = {
|
|
"catalog_20_of_20": report.get("score", {}).get("pass") is True
|
|
and report.get("score", {}).get("passes") == EXPECTED_CATALOG_COUNT
|
|
and len(report["results"]) == EXPECTED_CATALOG_COUNT,
|
|
"every_scored_prompt_has_target_bound_read_evidence": bool(report["results"])
|
|
and all(result.get("evidence_pass") is True for result in report["results"]),
|
|
"every_prompt_passes_scorer_and_evidence": bool(report["results"])
|
|
and all(result.get("pass") is True for result in report["results"]),
|
|
"send_and_delivery_absent_per_prompt": bool(report["results"])
|
|
and all((result.get("safety") or {}).get("send_and_delivery_absent") is True for result in report["results"]),
|
|
"every_gateway_child_and_profile_cleaned": bool(report["results"])
|
|
and all((result.get("cleanup") or {}).get("passes") is True for result in report["results"]),
|
|
"fresh_private_profile_per_prompt": isolation["all_profiles_unique"] is True,
|
|
"dc_prompts_isolated_from_oe_cs_context": isolation["dc_isolated"] is True,
|
|
}
|
|
report["status"] = "pass" if not report["errors"] and all(report["checks"].values()) else "fail"
|
|
return report
|
|
|
|
|
|
def prompt_scoped_tool_evidence(
|
|
path: Path,
|
|
*,
|
|
prompt_id: str,
|
|
run_nonce: str,
|
|
target_db: str,
|
|
db_identity: dict[str, Any],
|
|
read_role: str,
|
|
) -> dict[str, Any]:
|
|
proof = bound.read_tool_proof(
|
|
path,
|
|
gcp.SOURCE_COMPUTE,
|
|
target_db,
|
|
run_nonce=run_nonce,
|
|
database_identity=db_identity,
|
|
require_database_read_only=True,
|
|
require_default_read_only=True,
|
|
)
|
|
events: list[dict[str, Any]] = []
|
|
parse_errors: list[str] = []
|
|
for number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
|
|
try:
|
|
events.append(json.loads(line))
|
|
except json.JSONDecodeError as exc:
|
|
parse_errors.append(f"line {number}: {exc}")
|
|
prompt_and_nonce_match = bool(events) and all(
|
|
event.get("prompt_id") == prompt_id and event.get("run_nonce") == run_nonce for event in events
|
|
)
|
|
successful_reads = [
|
|
invocation
|
|
for invocation in proof.get("invocations", [])
|
|
if invocation.get("returncode") == 0
|
|
and invocation.get("argv")
|
|
and invocation["argv"][0] in bound.READ_ONLY_BRIDGE_COMMANDS
|
|
]
|
|
role_bound = bool(proof.get("invocations")) and all(
|
|
(invocation.get("database_identity") or {}).get("session_user") == read_role
|
|
and (invocation.get("database_identity") or {}).get("current_user") == read_role
|
|
for invocation in proof["invocations"]
|
|
)
|
|
checks = {
|
|
"log_parsed": not parse_errors,
|
|
"prompt_and_run_nonce_match": prompt_and_nonce_match,
|
|
"target_bound_without_fallback": proof.get("all_bound_to_supplied_target") is True,
|
|
"default_read_only": proof.get("default_read_only_required") is True,
|
|
"all_invocations_successful": proof.get("all_completed_successfully") is True,
|
|
"relevant_successful_read_present": bool(successful_reads),
|
|
"dedicated_read_role_bound": role_bound,
|
|
}
|
|
return {
|
|
"prompt_id": prompt_id,
|
|
"run_nonce": run_nonce,
|
|
"checks": checks,
|
|
"pass": all(checks.values()),
|
|
"proof": proof,
|
|
"parse_errors": parse_errors,
|
|
}
|
|
|
|
|
|
async def run_catalog_prompt(
|
|
args: argparse.Namespace,
|
|
prompt: dict[str, Any],
|
|
db_identity: dict[str, Any],
|
|
*,
|
|
index: int,
|
|
) -> dict[str, Any]:
|
|
temp_profile: Path | None = None
|
|
provider_environment: dict[str, str] = {}
|
|
profile_id = uuid.uuid4().hex
|
|
result: dict[str, Any] = {
|
|
"turn": index,
|
|
"prompt_id": prompt["id"],
|
|
"dimension": prompt["dimension"],
|
|
"prompt": prompt["message"],
|
|
"private_profile_id": profile_id,
|
|
"prior_prompt_ids": [],
|
|
"fresh_private_profile": False,
|
|
"errors": [],
|
|
}
|
|
try:
|
|
temp_profile, copy_audit = bound.copy_profile(
|
|
run_id=f"{args.run_id}-{prompt['id']}",
|
|
prompt_id=prompt["id"],
|
|
live_profile=args.live_profile,
|
|
)
|
|
result["profile_copy_audit"] = copy_audit
|
|
result["fresh_private_profile"] = copy_audit.get("passes") is True
|
|
result["model_auth_binding"] = bound.copy_ephemeral_model_auth(
|
|
temp_profile,
|
|
live_profile=args.live_profile,
|
|
)
|
|
provider_environment, environment_audit = bound.load_ephemeral_provider_environment(temp_profile)
|
|
result["model_auth_binding"]["environment_binding"] = environment_audit
|
|
bridge = gcp.patch_temp_bridge(args, temp_profile)
|
|
wrapper = Path(bridge["wrapper_path"])
|
|
wrapper_text = _build_gcp_read_wrapper(
|
|
args,
|
|
cloudsql_tool=temp_profile / "bin" / "cloudsql_memory_tool.py",
|
|
tool_log=Path(bridge["tool_log_path"]),
|
|
run_nonce=bridge["run_nonce"],
|
|
prompt_id=prompt["id"],
|
|
)
|
|
bound._detach_and_write(wrapper, wrapper_text, mode=0o700)
|
|
gateway = await bound.invoke_gateway_subprocess(
|
|
_catalog_turn_args(args, prompt),
|
|
temp_profile,
|
|
provider_environment=provider_environment,
|
|
)
|
|
evidence = prompt_scoped_tool_evidence(
|
|
Path(bridge["tool_log_path"]),
|
|
prompt_id=prompt["id"],
|
|
run_nonce=bridge["run_nonce"],
|
|
target_db=args.target_db,
|
|
db_identity=db_identity,
|
|
read_role=args.read_role,
|
|
)
|
|
surface = gateway.get("tool_surface") or {}
|
|
result.update(
|
|
{
|
|
"reply": gateway.get("reply") or "",
|
|
"gateway": gateway,
|
|
"tool_evidence": evidence,
|
|
"evidence_pass": evidence["pass"],
|
|
"persisted_session_id": (gateway.get("transcript_tool_trace") or {}).get("session_id"),
|
|
"safety": {
|
|
"send_and_delivery_absent": gateway.get("posted_to_telegram") is False
|
|
and surface.get("send_message_tool_enabled") is False
|
|
and surface.get("gateway_adapter_count") == 0,
|
|
},
|
|
}
|
|
)
|
|
except Exception as exc:
|
|
result["reply"] = ""
|
|
result["evidence_pass"] = False
|
|
result["errors"].append(
|
|
{
|
|
"type": type(exc).__name__,
|
|
"message": safe_message(exc, secret_values=tuple(provider_environment.values())),
|
|
}
|
|
)
|
|
finally:
|
|
provider_environment.clear()
|
|
child_cleanup = bound.cleanup_active_gateway_children()
|
|
root = temp_profile.parent if temp_profile else None
|
|
removed = bound.remove_tree(root) if not bound._ACTIVE_GATEWAY_CHILDREN else False
|
|
absent = bound.temp_path_absent(root)
|
|
result["cleanup"] = {
|
|
"gateway_children": child_cleanup,
|
|
"profile_removed": removed,
|
|
"profile_absent": absent,
|
|
"registry_clear": not bound._ACTIVE_GATEWAY_CHILDREN,
|
|
"passes": removed and absent and not bound._ACTIVE_GATEWAY_CHILDREN,
|
|
}
|
|
return result
|
|
|
|
|
|
def catalog_session_isolation(results: list[dict[str, Any]]) -> dict[str, bool]:
|
|
profile_ids = [result.get("private_profile_id") for result in results]
|
|
dc = [result for result in results if str(result.get("prompt_id") or "").startswith("DC-")]
|
|
session_ids = [result.get("persisted_session_id") for result in dc]
|
|
return {
|
|
"all_profiles_unique": bool(profile_ids)
|
|
and all(profile_ids)
|
|
and len(profile_ids) == len(set(profile_ids)),
|
|
"dc_isolated": len(dc) == len(benchmark.CORY_DIRECT_CLAIM_FOLLOWUP_SCENARIOS)
|
|
and all(result.get("fresh_private_profile") is True and result.get("prior_prompt_ids") == [] for result in dc)
|
|
and all(session_ids)
|
|
and len(session_ids) == len(set(session_ids)),
|
|
}
|
|
|
|
|
|
def catalog_gate_pass(catalog_report: dict[str, Any]) -> bool:
|
|
checks = catalog_report.get("checks") or {}
|
|
return catalog_report.get("status") == "pass" and bool(checks) and all(checks.values())
|
|
|
|
|
|
async def run_existing_component(
|
|
args: argparse.Namespace,
|
|
executor: CloudSqlExecutor,
|
|
source_baseline: dict[str, Any],
|
|
target_identity: dict[str, Any],
|
|
*,
|
|
kind: str,
|
|
) -> dict[str, Any]:
|
|
db_identity = database_identity_receipt(executor)
|
|
gcp.validate_database_identity(db_identity, args.target_db)
|
|
assert_live_target_identity(args, target_identity, db_identity)
|
|
with tempfile.TemporaryDirectory(prefix=f"gcp-working-leo-{kind}-") as private_dir:
|
|
Path(private_dir).chmod(0o700)
|
|
placeholder = Path(private_dir) / "credential-route-only"
|
|
placeholder.write_text("credentials resolve through named GCP secrets\n", encoding="utf-8")
|
|
output = Path(private_dir) / f"{kind}.json"
|
|
common = {
|
|
"container": args.target_db,
|
|
"db": args.target_db,
|
|
"output": output,
|
|
"run_marker": lifecycle.new_marker(f"gcp-{kind}"),
|
|
"conversation_marker": lifecycle.new_marker(f"gcp-{kind}-memory"),
|
|
"chat_id": args.chat_id,
|
|
"user_id": args.user_id,
|
|
"user_name": args.user_name,
|
|
"turn_timeout": args.turn_timeout,
|
|
"review_secrets_file": str(placeholder),
|
|
"apply_secrets_file": str(placeholder),
|
|
"copy_model_auth": True,
|
|
"operator_review": args.allow_review,
|
|
"guarded_apply": args.allow_apply,
|
|
}
|
|
component_args = SimpleNamespace(**common)
|
|
with RuntimeAdapter(args, executor, source_baseline, db_identity):
|
|
if kind == "composition":
|
|
result = await composition.run_checkpoint(component_args)
|
|
elif kind == "lifecycle":
|
|
result = await lifecycle.run_lifecycle(component_args)
|
|
else:
|
|
raise AssertionError(f"unknown component {kind!r}")
|
|
unsupported = (
|
|
UNSUPPORTED_INHERITED_COMPOSITION_CHECKS
|
|
if kind == "composition"
|
|
else UNSUPPORTED_INHERITED_LIFECYCLE_CHECKS
|
|
)
|
|
result["unsupported_inherited_check_values"] = {
|
|
name: (result.get("checks") or {}).get(name) for name in sorted(unsupported)
|
|
}
|
|
for name in unsupported:
|
|
(result.get("checks") or {})[name] = None
|
|
result["inherited_status_before_gcp_adaptation"] = result.get("status")
|
|
result["status"] = "requires_gcp_aggregate_evaluation"
|
|
result["claim_ceiling"] = (
|
|
"This embedded component report preserves existing composition/lifecycle semantics against the pinned "
|
|
"target and retained source baseline. Source postflight invariants listed as unsupported were not run "
|
|
"live and are not counted; only the aggregate GCP evaluation may declare this component passing."
|
|
)
|
|
return result
|
|
|
|
|
|
def database_manifest_receipt(executor: CloudSqlExecutor, args: argparse.Namespace) -> dict[str, Any]:
|
|
rows = gcp.normalize_database_manifest_rows(executor.read(args.manifest_sql.read_text(encoding="utf-8")))
|
|
return {
|
|
"target_database": args.target_db,
|
|
"rows": rows,
|
|
"sha256": sha256_json(rows),
|
|
"table_count": sum(row.get("kind") == "table" for row in rows),
|
|
"total_rows": sum(int(row.get("row_count") or 0) for row in rows if row.get("kind") == "table"),
|
|
}
|
|
|
|
|
|
def database_fingerprint_from_manifest(manifest: dict[str, Any]) -> dict[str, Any]:
|
|
identity = next(row for row in manifest["rows"] if row.get("kind") == "identity")
|
|
return {
|
|
"sha256": manifest["sha256"],
|
|
"table_count": manifest["table_count"],
|
|
"total_rows": manifest["total_rows"],
|
|
"database": identity.get("database"),
|
|
"server_address": identity.get("server_address"),
|
|
"ssl": identity.get("ssl"),
|
|
"transaction_read_only": identity.get("transaction_read_only"),
|
|
}
|
|
|
|
|
|
def _object_fingerprint(before: Any, after: Any) -> dict[str, Any]:
|
|
return {
|
|
"before": before,
|
|
"after": after,
|
|
"before_sha256": sha256_json(before),
|
|
"after_sha256": sha256_json(after),
|
|
"changed": before != after,
|
|
}
|
|
|
|
|
|
def _object_change_manifest(composition_report: dict[str, Any], lifecycle_report: dict[str, Any]) -> dict[str, Any]:
|
|
normalized = composition_report.get("normalized_child") or {}
|
|
lifecycle_fixture = lifecycle_report.get("fixture_ids") or {}
|
|
composition_rows = composition_report.get("final_canonical_rows") or {}
|
|
lifecycle_rows = lifecycle_report.get("final_canonical_rows") or {}
|
|
objects = {
|
|
"composition_proposal": _object_fingerprint(
|
|
None,
|
|
(composition_report.get("guarded_apply") or {}).get("applied_readback"),
|
|
),
|
|
"composition_approval": _object_fingerprint(
|
|
None,
|
|
(composition_report.get("operator_review") or {}).get("approval_snapshot"),
|
|
),
|
|
"composition_canonical_rows": _object_fingerprint(
|
|
{key: [] for key in composition_rows},
|
|
composition_rows,
|
|
),
|
|
"lifecycle_proposal": _object_fingerprint(None, lifecycle_report.get("final_applied_readback")),
|
|
"lifecycle_approval": _object_fingerprint(
|
|
None,
|
|
lifecycle_report.get("immutable_approval_readback_after_apply"),
|
|
),
|
|
"lifecycle_canonical_rows": _object_fingerprint(
|
|
{key: [] for key in lifecycle_rows},
|
|
lifecycle_rows,
|
|
),
|
|
}
|
|
identifiers = {
|
|
"composition_proposal_id": normalized.get("id"),
|
|
"composition_claim_ids": (normalized.get("planned_row_ids") or {}).get("claims") or [],
|
|
"composition_source_ids": (normalized.get("planned_row_ids") or {}).get("sources") or [],
|
|
"lifecycle_proposal_id": lifecycle_fixture.get("proposal_id"),
|
|
"lifecycle_claim_id": lifecycle_fixture.get("claim_id"),
|
|
"lifecycle_source_id": lifecycle_fixture.get("source_id"),
|
|
}
|
|
return {
|
|
"identifiers": identifiers,
|
|
"objects": objects,
|
|
"sha256": sha256_json({"identifiers": identifiers, "objects": objects}),
|
|
"scope": "generated_rows_only",
|
|
"composition_unrelated_rows_unchanged": (composition_report.get("checks") or {}).get(
|
|
"unrelated_clone_rows_unchanged"
|
|
),
|
|
"lifecycle_unrelated_rows_unchanged": (lifecycle_report.get("checks") or {}).get(
|
|
"all_unrelated_clone_rows_unchanged"
|
|
),
|
|
}
|
|
|
|
|
|
async def run_live_suite(args: argparse.Namespace, validated: dict[str, Any]) -> dict[str, Any]:
|
|
executor = CloudSqlExecutor(args)
|
|
target_identity = validated.get("target_identity_receipt") or {}
|
|
source_baseline = validated.get("source_baseline_receipt") or {}
|
|
report: dict[str, Any] = {
|
|
"schema": SCHEMA,
|
|
"mode": "gcp_generated_db_working_leo_no_send",
|
|
"target_database": args.target_db,
|
|
"required_tier": "gcp_disposable_copied_cloudsql_database",
|
|
"posted_to_telegram": False,
|
|
"production_profile_mutation_attempted": False,
|
|
"systemd_restart_attempted": False,
|
|
"model_authority": ["read", "stage_pending_proposal"],
|
|
"controller_authority": {
|
|
"stage": args.allow_stage,
|
|
"review": args.allow_review,
|
|
"apply": args.allow_apply,
|
|
"roles": {
|
|
"read": args.read_role,
|
|
"stage": args.stage_role,
|
|
"review": args.review_role,
|
|
"apply": args.apply_role,
|
|
},
|
|
},
|
|
**validated,
|
|
"errors": [],
|
|
}
|
|
report["credential_value_separation"] = verify_distinct_credential_values(executor)
|
|
before_service = gcp.service_state(args.service)
|
|
before_profile = gcp.profile_hashes(args.live_profile)
|
|
before_identity = database_identity_receipt(executor)
|
|
gcp.validate_database_identity(before_identity, args.target_db)
|
|
assert_live_target_identity(args, target_identity, before_identity)
|
|
before_manifest = database_manifest_receipt(executor, args)
|
|
before_fingerprint = database_fingerprint_from_manifest(before_manifest)
|
|
report.update(
|
|
{
|
|
"service_before": before_service,
|
|
"live_profile_hashes_before": before_profile,
|
|
"database_identity_before": before_identity,
|
|
"database_fingerprint_before": before_fingerprint,
|
|
"database_manifest_before": before_manifest,
|
|
}
|
|
)
|
|
phases: tuple[tuple[str, Callable[[], Any]], ...] = (
|
|
("catalog", lambda: run_catalog(args, before_identity)),
|
|
(
|
|
"composition",
|
|
lambda: run_existing_component(
|
|
args,
|
|
executor,
|
|
source_baseline,
|
|
target_identity,
|
|
kind="composition",
|
|
),
|
|
),
|
|
(
|
|
"lifecycle",
|
|
lambda: run_existing_component(
|
|
args,
|
|
executor,
|
|
source_baseline,
|
|
target_identity,
|
|
kind="lifecycle",
|
|
),
|
|
),
|
|
)
|
|
for name, start in phases:
|
|
try:
|
|
report[name] = await start()
|
|
except Exception as exc:
|
|
message = safe_message(exc)
|
|
report[name] = {"status": "fail", "errors": [{"type": type(exc).__name__, "message": message}]}
|
|
report["errors"].append({"phase": name, "type": type(exc).__name__, "message": message})
|
|
break
|
|
|
|
report["gateway_child_cleanup"] = bound.cleanup_active_gateway_children()
|
|
postflight: tuple[tuple[str, Callable[[], Any]], ...] = (
|
|
("service_after", lambda: gcp.service_state(args.service)),
|
|
("live_profile_hashes_after", lambda: gcp.profile_hashes(args.live_profile)),
|
|
("database_identity_after", lambda: database_identity_receipt(executor)),
|
|
("database_manifest_after", lambda: database_manifest_receipt(executor, args)),
|
|
)
|
|
for name, capture in postflight:
|
|
try:
|
|
report[name] = capture()
|
|
except Exception as exc:
|
|
report[name] = None
|
|
report["errors"].append(
|
|
{"phase": name, "type": type(exc).__name__, "message": safe_message(exc)}
|
|
)
|
|
report["database_fingerprint_after"] = (
|
|
database_fingerprint_from_manifest(report["database_manifest_after"])
|
|
if report.get("database_manifest_after")
|
|
else None
|
|
)
|
|
if report.get("database_identity_after"):
|
|
try:
|
|
gcp.validate_database_identity(report["database_identity_after"], args.target_db)
|
|
assert_live_target_identity(args, target_identity, report["database_identity_after"])
|
|
except Exception as exc:
|
|
report["errors"].append(
|
|
{
|
|
"phase": "database_identity_after",
|
|
"type": type(exc).__name__,
|
|
"message": safe_message(exc),
|
|
}
|
|
)
|
|
|
|
composition_report = report.get("composition") or {}
|
|
lifecycle_report = report.get("lifecycle") or {}
|
|
report["object_level_changes"] = _object_change_manifest(composition_report, lifecycle_report)
|
|
report["database_operation_receipts"] = executor.receipts
|
|
runtime_after = runtime_manifest()
|
|
report["runtime_manifest_after"] = runtime_after
|
|
composition_checks = composition_report.get("checks") or {}
|
|
lifecycle_checks = lifecycle_report.get("checks") or {}
|
|
gcp_required_names = validated["composition_contract"]["gcp_required_check_names"]
|
|
gcp_composition_results = {name: composition_checks.get(name) is True for name in gcp_required_names}
|
|
report["composition_gcp_evaluation"] = {
|
|
"inherited_34_of_34_claimed": False,
|
|
"unsupported_inherited_checks": sorted(UNSUPPORTED_INHERITED_COMPOSITION_CHECKS),
|
|
"required_checks": gcp_composition_results,
|
|
"passed": bool(gcp_composition_results)
|
|
and all(gcp_composition_results.values())
|
|
and not composition_report.get("errors"),
|
|
}
|
|
source_identity = source_baseline.get("guard_snapshot", {}).get("database_identity", {})
|
|
catalog_report = report.get("catalog") or {}
|
|
catalog_checks = catalog_report.get("checks") or {}
|
|
operation_purposes = {receipt.get("purpose") for receipt in executor.receipts}
|
|
gcp_lifecycle_results = {
|
|
name: value is True
|
|
for name, value in lifecycle_checks.items()
|
|
if name not in UNSUPPORTED_INHERITED_LIFECYCLE_CHECKS
|
|
}
|
|
report["lifecycle_gcp_evaluation"] = {
|
|
"unsupported_inherited_checks": sorted(UNSUPPORTED_INHERITED_LIFECYCLE_CHECKS),
|
|
"required_checks": gcp_lifecycle_results,
|
|
"passed": bool(gcp_lifecycle_results)
|
|
and all(gcp_lifecycle_results.values())
|
|
and not lifecycle_report.get("errors"),
|
|
}
|
|
report["checks"] = {
|
|
"catalog_status_and_all_safety_checks_pass": catalog_gate_pass(catalog_report),
|
|
"composition_gcp_non_tautological_checks_pass": report["composition_gcp_evaluation"]["passed"] is True,
|
|
"source_baseline_is_independently_retained_and_physically_distinct": bool(source_baseline.get("sha256"))
|
|
and source_identity.get("system_identifier")
|
|
and str(source_identity.get("system_identifier")) != str(before_identity.get("system_identifier")),
|
|
"proposal_lifecycle_exact_under_gcp_supported_checks": report["lifecycle_gcp_evaluation"]["passed"]
|
|
is True,
|
|
"process_memory_survived": (composition_checks.get("isolated_restart_and_memory_survived") is True)
|
|
and (lifecycle_checks.get("isolated_handler_reopened_with_same_session") is True),
|
|
"database_identity_stable": bool(before_identity)
|
|
and before_identity == report.get("database_identity_after"),
|
|
"physical_target_matches_sha_pinned_receipt": bool(target_identity.get("sha256"))
|
|
and str(before_identity.get("system_identifier")) == target_identity.get("system_identifier"),
|
|
"service_unchanged": before_service == report.get("service_after"),
|
|
"live_profile_unchanged": before_profile == report.get("live_profile_hashes_after"),
|
|
"runtime_inputs_unchanged": validated["runtime_manifest"] == runtime_after,
|
|
"object_changes_exact_and_unrelated_rows_stable": report["object_level_changes"].get(
|
|
"composition_unrelated_rows_unchanged"
|
|
)
|
|
is True
|
|
and report["object_level_changes"].get("lifecycle_unrelated_rows_unchanged") is True
|
|
and all(
|
|
item.get("changed") is True
|
|
for item in (report["object_level_changes"].get("objects") or {}).values()
|
|
),
|
|
"phase_roles_and_capabilities_verified": {"read", "stage", "review", "apply"}
|
|
<= operation_purposes
|
|
and bool(executor.receipts)
|
|
and all(
|
|
(
|
|
receipt["writable"] is True
|
|
and receipt["purpose"] in ALLOWED_WRITE_PURPOSES
|
|
and receipt["default_transaction_read_only"] == "off"
|
|
)
|
|
or (
|
|
receipt["writable"] is False
|
|
and receipt["default_transaction_read_only"] == "on"
|
|
)
|
|
for receipt in executor.receipts
|
|
),
|
|
"credential_values_verified_distinct_without_retention": report["credential_value_separation"]
|
|
== {"checked": True, "distinct": True, "credential_count": 4},
|
|
"no_send_proven_by_component_tool_surfaces": catalog_checks.get(
|
|
"send_and_delivery_absent_per_prompt"
|
|
)
|
|
is True
|
|
and composition_checks.get("no_telegram_send") is True
|
|
and lifecycle_checks.get("no_telegram_send") is True,
|
|
"no_systemd_restart": report["systemd_restart_attempted"] is False,
|
|
}
|
|
report["status"] = "pass" if not report["errors"] and all(report["checks"].values()) else "fail"
|
|
report["claim_ceiling"] = (
|
|
"A pass proves the 20-prompt catalog with prompt-scoped target-bound read evidence, the GCP-supported "
|
|
"non-tautological subset of the existing composition contract, exact pending/review/applied lifecycle, and "
|
|
"process-level private-session memory against one SHA-pinned disposable Cloud SQL target. The inherited "
|
|
"34/34 composition claim is explicitly unsupported because source postflight checks were not executed live."
|
|
)
|
|
return bound.redact_value(report)
|
|
|
|
|
|
async def run_orchestrator(args: argparse.Namespace) -> dict[str, Any]:
|
|
report: dict[str, Any]
|
|
try:
|
|
validated = validate_local_inputs(args)
|
|
if args.validation_only:
|
|
report = {
|
|
"schema": VALIDATION_SCHEMA,
|
|
"mode": "validation_only",
|
|
"status": "pass",
|
|
"target_database": args.target_db,
|
|
"posted_to_telegram": False,
|
|
"systemd_restart_attempted": False,
|
|
"database_connection_attempted": False,
|
|
"model_call_attempted": False,
|
|
"authority": {
|
|
"model": ["read", "stage_pending_proposal"],
|
|
"controller_only": ["review", "apply"],
|
|
},
|
|
**validated,
|
|
"errors": [],
|
|
}
|
|
else:
|
|
report = await run_live_suite(args, validated)
|
|
except BaseException as exc:
|
|
report = {
|
|
"schema": SCHEMA,
|
|
"mode": "validation_only" if args.validation_only else "gcp_generated_db_working_leo_no_send",
|
|
"status": "fail",
|
|
"target_database": args.target_db,
|
|
"posted_to_telegram": False,
|
|
"systemd_restart_attempted": False,
|
|
"errors": [
|
|
{
|
|
"phase": "orchestrator",
|
|
"type": type(exc).__name__,
|
|
"message": safe_message(exc),
|
|
}
|
|
],
|
|
}
|
|
report["completed_at_utc"] = bound.utc_now()
|
|
report = bound.redact_value(report)
|
|
bound.write_report(args.output, report)
|
|
return report
|
|
|
|
|
|
def parse_internal_stage_args(argv: list[str]) -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(add_help=False)
|
|
parser.add_argument("--target-db", required=True)
|
|
parser.add_argument("--host", required=True)
|
|
parser.add_argument("--project", required=True)
|
|
parser.add_argument("--instance", required=True)
|
|
parser.add_argument("--password-secret", required=True)
|
|
parser.add_argument("--read-role", required=True)
|
|
parser.add_argument("--stage-password-secret", required=True)
|
|
parser.add_argument("--stage-role", required=True)
|
|
parser.add_argument("--run-marker", required=True)
|
|
parser.add_argument("--tool-log", required=True, type=Path)
|
|
parser.add_argument("--run-nonce", required=True)
|
|
parser.add_argument("--target-identity-receipt", required=True, type=Path)
|
|
parser.add_argument("--target-identity-sha256", required=True)
|
|
args = parser.parse_args(argv)
|
|
args.review_role = "kb_review"
|
|
args.apply_role = "kb_apply"
|
|
args.allow_stage = True
|
|
args.allow_review = False
|
|
args.allow_apply = False
|
|
return args
|
|
|
|
|
|
def internal_stage_main(argv: list[str]) -> int:
|
|
args = parse_internal_stage_args(argv)
|
|
invocation_id = uuid.uuid4().hex
|
|
try:
|
|
validate_target_database(args.target_db)
|
|
executor = CloudSqlExecutor(args)
|
|
target_identity = validate_target_identity_receipt(
|
|
args,
|
|
args.target_identity_receipt,
|
|
args.target_identity_sha256,
|
|
)
|
|
identity = database_identity_receipt(executor)
|
|
gcp.validate_database_identity(identity, args.target_db)
|
|
assert_live_target_identity(args, target_identity, identity)
|
|
start = {
|
|
"phase": "start",
|
|
"invocation_id": invocation_id,
|
|
"run_nonce": args.run_nonce,
|
|
"container": gcp.SOURCE_COMPUTE,
|
|
"database": args.target_db,
|
|
"database_identity": identity,
|
|
"argv": [lifecycle.STAGE_COMMAND],
|
|
}
|
|
with args.tool_log.open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps(start, sort_keys=True) + "\n")
|
|
fixture = lifecycle.build_lifecycle_fixture(args.run_marker)
|
|
result = executor.json(lifecycle.build_stage_sql(fixture), stage=True)
|
|
status = 0
|
|
print(json.dumps({"status": "pending_review", **result}, sort_keys=True))
|
|
except Exception as exc:
|
|
status = 2
|
|
print(json.dumps({"status": "rejected", "error": safe_message(exc)}, sort_keys=True))
|
|
end = {
|
|
"phase": "end",
|
|
"invocation_id": invocation_id,
|
|
"run_nonce": args.run_nonce,
|
|
"container": gcp.SOURCE_COMPUTE,
|
|
"database": args.target_db,
|
|
"returncode": status,
|
|
}
|
|
with args.tool_log.open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps(end, sort_keys=True) + "\n")
|
|
return status
|
|
|
|
|
|
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
mode = parser.add_mutually_exclusive_group(required=True)
|
|
mode.add_argument("--validation-only", action="store_true")
|
|
mode.add_argument("--execute", action="store_true", help="Run paid model calls and authorized clone writes.")
|
|
parser.add_argument("--target-db", required=True)
|
|
parser.add_argument("--cloudsql-tool", required=True, type=Path)
|
|
parser.add_argument("--manifest-sql", default=gcp.DEFAULT_MANIFEST_SQL, type=Path)
|
|
parser.add_argument("--parity-receipt", required=True, type=Path)
|
|
parser.add_argument("--target-identity-receipt", type=Path)
|
|
parser.add_argument("--target-identity-sha256")
|
|
parser.add_argument("--source-baseline-receipt", type=Path)
|
|
parser.add_argument("--source-baseline-sha256")
|
|
parser.add_argument("--output", required=True, type=Path)
|
|
parser.add_argument("--host", default=gcp.DEFAULT_HOST)
|
|
parser.add_argument("--project", default=gcp.DEFAULT_PROJECT)
|
|
parser.add_argument("--instance")
|
|
parser.add_argument("--password-secret", default=gcp.DEFAULT_SECRET)
|
|
parser.add_argument("--read-role", default="kb_read")
|
|
parser.add_argument("--stage-role", default=DEFAULT_STAGE_ROLE)
|
|
parser.add_argument("--review-role", default=DEFAULT_REVIEW_ROLE)
|
|
parser.add_argument("--apply-role", default=DEFAULT_APPLY_ROLE)
|
|
parser.add_argument("--stage-password-secret")
|
|
parser.add_argument("--review-password-secret")
|
|
parser.add_argument("--apply-password-secret")
|
|
parser.add_argument("--service", default=gcp.DEFAULT_SERVICE)
|
|
parser.add_argument("--live-profile", default=bound.LIVE_PROFILE, type=Path)
|
|
parser.add_argument("--chat-id", default=bound.DEFAULT_CHAT_ID)
|
|
parser.add_argument("--user-id", default=bound.DEFAULT_USER_ID)
|
|
parser.add_argument("--user-name", default="codex GCP Working Leo suite")
|
|
parser.add_argument("--run-id", default="gcp-working-leo-" + uuid.uuid4().hex[:12])
|
|
parser.add_argument("--turn-timeout", default=300, type=int)
|
|
parser.add_argument("--allow-stage", action="store_true")
|
|
parser.add_argument("--allow-review", action="store_true")
|
|
parser.add_argument("--allow-apply", action="store_true")
|
|
args = parser.parse_args(argv)
|
|
try:
|
|
validate_target_database(args.target_db)
|
|
args.output = bound.validate_private_output_path(args.output)
|
|
except bound.CheckpointError as exc:
|
|
parser.error(str(exc))
|
|
for path_flag in ("cloudsql_tool", "manifest_sql", "parity_receipt"):
|
|
if not getattr(args, path_flag).is_file():
|
|
parser.error(f"--{path_flag.replace('_', '-')} must exist")
|
|
for path_flag in ("target_identity_receipt", "source_baseline_receipt"):
|
|
value = getattr(args, path_flag)
|
|
if value is not None and not value.is_file():
|
|
parser.error(f"--{path_flag.replace('_', '-')} must exist when supplied")
|
|
if args.turn_timeout <= 0:
|
|
parser.error("--turn-timeout must be positive")
|
|
if args.execute:
|
|
receipt_inputs = (
|
|
args.target_identity_receipt,
|
|
args.target_identity_sha256,
|
|
args.source_baseline_receipt,
|
|
args.source_baseline_sha256,
|
|
args.instance,
|
|
)
|
|
if not all(receipt_inputs):
|
|
parser.error(
|
|
"execution requires --instance plus SHA-pinned target identity and source baseline receipts"
|
|
)
|
|
missing_flags = [name for name in ("stage", "review", "apply") if not getattr(args, f"allow_{name}")]
|
|
if missing_flags:
|
|
parser.error("execution requires explicit controller flags: " + ", ".join(missing_flags))
|
|
missing_secrets = [
|
|
name
|
|
for name in ("stage_password_secret", "review_password_secret", "apply_password_secret")
|
|
if not getattr(args, name)
|
|
]
|
|
if missing_secrets:
|
|
parser.error("execution requires named stage/review/apply credential secrets")
|
|
if len({args.stage_password_secret, args.review_password_secret, args.apply_password_secret}) != 3:
|
|
parser.error("stage, review, and apply credential secret names must be distinct")
|
|
if args.read_role == "postgres" or args.stage_role == "postgres":
|
|
parser.error("execute mode forbids postgres as the read or stage role")
|
|
if args.stage_role in {args.read_role, args.review_role, args.apply_role}:
|
|
parser.error("--stage-role must be a dedicated role distinct from read/review/apply")
|
|
if args.review_role != "kb_review" or args.apply_role != "kb_apply":
|
|
parser.error("execute mode requires exact kb_review and kb_apply controller roles")
|
|
if not args.live_profile.is_dir():
|
|
parser.error("--live-profile must exist for execution")
|
|
return args
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
raw = list(sys.argv[1:] if argv is None else argv)
|
|
if raw and raw[0] == lifecycle.INTERNAL_STAGE_COMMAND:
|
|
return internal_stage_main(raw[1:])
|
|
args = parse_args(raw)
|
|
with bound.termination_cleanup_handlers():
|
|
report = asyncio.run(run_orchestrator(args))
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"status": report.get("status"),
|
|
"mode": report.get("mode"),
|
|
"target_database": args.target_db,
|
|
"output": str(args.output),
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
)
|
|
return 0 if report.get("status") == "pass" else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|