railiance-platform/scripts/render_backup_credential_contract.py

63 lines
2.4 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Export a validated, public CCR as JSON for the stdlib node delivery helper.
Uses the platform's existing PyYAML validator. No credential lookup or live call.
After CCR status updates, YAML remains the source of truth; export and review its
new JSON hash before an attended delivery. Draft exports remain non-executable.
"""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import sys
from application_backup_credentials import PROFILES, contract
ROOT = Path(__file__).resolve().parents[1]
def render(source, application):
spec = importlib.util.spec_from_file_location("backup_ccr_validator", ROOT / "scripts/credential-change.py")
validator = importlib.util.module_from_spec(spec)
spec.loader.exec_module(validator)
ccr, errors, _ = validator.validate_ccr(source)
if errors or validator.applier_policy_violations(ccr):
raise ValueError("invalid_reader_contract")
policy = validator.policy_artifact_diff(ccr)
if not policy["matches"]:
raise ValueError("policy_source_mismatch")
ccr["source_ccr_sha256"] = hashlib.sha256(source.read_bytes()).hexdigest()
ccr["policy_sha256"] = hashlib.sha256(validator.generated_policy_hcl(ccr).encode()).hexdigest()
raw = (json.dumps(ccr, indent=2, sort_keys=True) + "\n").encode()
contract(raw, application)
return raw
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--ccr", type=Path, required=True)
parser.add_argument("--application", choices=PROFILES, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
try:
raw = render(args.ccr, args.application)
fd = os.open(args.output, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
with os.fdopen(fd, "wb") as stream:
stream.write(raw)
stream.flush()
os.fsync(stream.fileno())
print(json.dumps({"status": "rendered", "application": args.application,
"ccr_sha256": hashlib.sha256(raw).hexdigest(), "effects": ["public_contract_export"]}))
return 0
except Exception: # noqa: BLE001 - metadata-only fixed diagnostics
print('{"status":"failed","code":"contract_export_failed"}', file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())