backblaze-proofframe / scripts /live_proof.py
ADJCJH's picture
Sync post-live local Genblaze proof evidence
74ee21a verified
Raw
History Blame Contribute Delete
6.64 kB
#!/usr/bin/env python3
"""Preflight and run ProofFrame's final live sponsor proof gate."""
from __future__ import annotations
import argparse
import importlib.util
import json
from pathlib import Path
import subprocess
import sys
from typing import Any, Callable
from proofframe.config import Settings
ROOT = Path(__file__).resolve().parents[1]
API_SMOKE = ROOT / "scripts" / "api_smoke.py"
def package_available(module: str) -> bool:
return importlib.util.find_spec(module) is not None
def add_requirement(
checks: list[dict[str, Any]], name: str, ok: bool, remediation: str
) -> None:
checks.append({"name": name, "ok": ok, "remediation": "" if ok else remediation})
def build_preflight_report(
settings: Settings,
*,
require_storage_backend: str,
require_generation_backend: str,
available: Callable[[str], bool] = package_available,
) -> dict[str, Any]:
checks: list[dict[str, Any]] = []
add_requirement(
checks,
"storage backend mode",
settings.storage_backend == require_storage_backend,
f"Set PROOFFRAME_STORAGE_BACKEND={require_storage_backend}.",
)
add_requirement(
checks,
"generation backend mode",
settings.generation_backend == require_generation_backend,
f"Set PROOFFRAME_GENERATION_BACKEND={require_generation_backend}.",
)
if require_storage_backend == "b2":
add_requirement(checks, "B2 endpoint", bool(settings.b2_endpoint_url), "Set B2_ENDPOINT_URL.")
add_requirement(checks, "B2 bucket", bool(settings.b2_bucket), "Set B2_BUCKET.")
add_requirement(checks, "B2 key id", bool(settings.b2_key_id), "Set B2_KEY_ID.")
add_requirement(
checks,
"B2 application key",
bool(settings.b2_application_key),
"Set B2_APPLICATION_KEY or B2_APP_KEY.",
)
add_requirement(
checks,
"boto3 package",
available("boto3"),
"Install integrations with `pip install -e '.[integrations]'`.",
)
if require_generation_backend == "genblaze":
add_requirement(
checks,
"B2 region for Genblaze sink",
bool(settings.b2_region_for_backblaze()),
(
"Set B2_REGION or use a Backblaze S3 endpoint like "
"https://s3.us-west-004.backblazeb2.com."
),
)
if require_generation_backend == "genblaze":
add_requirement(
checks,
"Genblaze provider",
settings.genblaze_provider_supported(),
"Set GENBLAZE_PROVIDER=gmicloud, openai, or local.",
)
add_requirement(
checks,
"Genblaze provider API key",
(not settings.genblaze_provider_requires_key()) or bool(settings.genblaze_provider_key()),
settings.genblaze_key_remediation(),
)
add_requirement(
checks,
"Genblaze image model",
bool(settings.genblaze_image_model),
"Set GENBLAZE_IMAGE_MODEL.",
)
modules = ["genblaze_core", *settings.genblaze_provider_modules()]
if require_storage_backend == "b2":
modules.append("genblaze_s3")
for module in modules:
add_requirement(
checks,
f"{module} package",
available(module),
"Install integrations with `pip install -e '.[integrations]'`.",
)
missing = [check for check in checks if not check["ok"]]
return {
"ok": not missing,
"storage_backend": settings.storage_backend,
"generation_backend": settings.generation_backend,
"genblaze_provider": settings.genblaze_provider,
"required_storage_backend": require_storage_backend,
"required_generation_backend": require_generation_backend,
"checks": checks,
"missing": missing,
"secret_policy": (
"No credential values are printed. Evidence output is delegated to api_smoke.py, "
"which refuses secret-like keys, bearer tokens, signed URL parameters, and GMI-style keys."
),
}
def build_api_smoke_command(
*,
base_url: str,
evidence_out: Path,
require_storage_backend: str,
require_generation_backend: str,
) -> list[str]:
return [
sys.executable,
str(API_SMOKE),
"--base-url",
base_url,
"--require-storage-backend",
require_storage_backend,
"--require-generation-backend",
require_generation_backend,
"--evidence-out",
str(evidence_out),
]
def run_live_proof(args: argparse.Namespace) -> int:
settings = Settings.from_env()
report = build_preflight_report(
settings,
require_storage_backend=args.require_storage_backend,
require_generation_backend=args.require_generation_backend,
)
print(json.dumps(report, indent=2))
if not report["ok"]:
return 2
if args.preflight_only:
return 0
command = build_api_smoke_command(
base_url=args.base_url,
evidence_out=args.evidence_out,
require_storage_backend=args.require_storage_backend,
require_generation_backend=args.require_generation_backend,
)
completed = subprocess.run(command, check=False)
return completed.returncode
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Preflight and run the final B2/Genblaze live proof gate."
)
parser.add_argument("--base-url", default="http://127.0.0.1:8088")
parser.add_argument(
"--require-storage-backend",
choices=["b2", "local"],
default="b2",
help="Expected storage backend reported by the running app.",
)
parser.add_argument(
"--require-generation-backend",
choices=["genblaze", "mock"],
default="genblaze",
help="Expected generation backend reported by the running app.",
)
parser.add_argument(
"--evidence-out",
type=Path,
default=Path("docs/assets/final-live-proof-evidence.json"),
help="Safe evidence JSON path written by api_smoke.py.",
)
parser.add_argument(
"--preflight-only",
action="store_true",
help="Only check required env/packages; do not call api_smoke.py.",
)
return parser
def main() -> None:
raise SystemExit(run_live_proof(build_parser().parse_args()))
if __name__ == "__main__":
main()