#!/usr/bin/env python3 """Prepare exact-content runtime twins. Local files only; never applies to Kubernetes. Namespace/release/chart/ServiceAccount and caller audience move to access-engine. Image repository+digest and policy/registry argv remain exact existing-twin values until publication/path migration is separately proven. """ from pathlib import Path import argparse import copy import re import yaml ROOT = Path(__file__).resolve().parents[1] PINS = ("ops-warden", "ops-warden-fetch", "secrets-engine", "user-engine", "tenant-engine", "informed-decision-lifecycle", "informed-decision-sitting", "informed-decision-t03", "application-readback") def twin(source): result = copy.deepcopy(source) if not re.fullmatch(r"sha256:[0-9a-f]{64}", source.get("image", {}).get("digest", "")): raise ValueError("existing twin must have an immutable SHA256 digest") name = source.get("name", "") if not name.startswith("flex-auth-"): raise ValueError("existing pin must have an exact flex-auth release name") if source.get("callerAuth", {}).get("mode") != "enforce": raise ValueError("new twin requires existing enforced caller authentication") if source.get("outbox", {}).get("enabled") or source.get("auditDelivery", {}).get("enabled"): raise ValueError("durable outbox/audit twins require independent source/custody; never share writer state") result["name"] = "access-engine-" + name[len("flex-auth-"):] result["namespace"] = "access-engine" result["callerAuth"]["audience"] = "access-engine" return result def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true") args = parser.parse_args() for pin in PINS: source = yaml.safe_load((ROOT / "values" / (pin + ".yaml")).read_text()) target = ROOT / "values" / "access-engine" / (pin + ".yaml") result = twin(source) if args.check: if not target.exists() or yaml.safe_load(target.read_text()) != result: raise SystemExit(f"runtime twin drift: {target}") else: target.parent.mkdir(parents=True, exist_ok=True) target.write_text("# GENERATED by tools/gen_runtime_twins.py; same image/package as existing twin.\n" + yaml.safe_dump(result, sort_keys=False)) if __name__ == "__main__": main()