railiance-platform/scripts/rpf-wp-0015-e2-receipt.py
codex a7392437e1
All checks were successful
CCR intake gate / gate (push) Successful in 13s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Prepare the RPF-WP-0015-T03 synthetic E2 window: receipt generator and readiness record.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 236506@bnt-lap001
Assistant-Session: 09087018-91e1-48c5-ab2f-acfbb62c92e4
2026-11-03 14:29:57 +01:00

56 lines
2.9 KiB
Python
Executable file

#!/usr/bin/env python3
"""Write the RPF-WP-0015-T03 synthetic E2 approval receipt for one founder window.
Usage: scripts/rpf-wp-0015-e2-receipt.py OUTPUT.json [--start-in-min N]
The window is 15 minutes and starts now, or N minutes from now. Writing the
receipt and running the window is the founder GO for that window; D5
(2fd5849c) authorizes the exercise class only. The owner acknowledgements are
the round-9 approvals of review contract 014627d6 (audit-core 0d0da0d2,
rapp-postgres 6d047a08, railiance-platform c4a80a60). They stay valid only
while the pinned artifacts in interfaces/RAILIANCE-WP-0024-owner-reviews.json
are unchanged; the script refuses otherwise. The receipt holds no credential
values. It refuses to overwrite an existing file.
"""
import hashlib
import json
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
pins = json.loads((ROOT / "interfaces/RAILIANCE-WP-0024-owner-reviews.json").read_text())["artifact_sha256"]
drift = [p for p, h in pins.items() if hashlib.sha256((ROOT / p).read_bytes()).hexdigest() != h]
if drift:
sys.exit("owner-reviewed artifacts changed since contract 014627d6; new owner approvals needed: " + ", ".join(drift))
if len(sys.argv) < 2:
sys.exit(__doc__)
out = sys.argv[1]
delay = int(sys.argv[sys.argv.index('--start-in-min') + 1]) if '--start-in-min' in sys.argv else 0
start = datetime.now(timezone.utc).replace(second=0, microsecond=0) + timedelta(minutes=delay)
end = start + timedelta(minutes=15)
tag = start.strftime('%Y%m%dt%H%M')
z = lambda t: t.strftime('%Y-%m-%dT%H:%M:%SZ')
receipt = {
"procedure": "audit-core-database-lease-recovery",
"task_id": "RAILIANCE-WP-0024-T03",
"status": "approved",
"approval_id": f"rpf-wp-0015-t03-e2-{tag}z-founder-go",
"window": {"start": z(start), "end": z(end)},
"abort_operator": "founder (platform-root), attended",
"owners": {
"audit-core": {"acknowledged": True, "message_id": "0d0da0d2-36a1-4ffc-b7bf-7896fad691f6"},
"rapp-postgres": {"acknowledged": True, "message_id": "6d047a08-e9c8-4dbf-95b9-dca039791329"},
"railiance-platform": {"acknowledged": True, "message_id": "c4a80a60-a415-4f2b-8928-751407473641"},
},
"synthetic_load": {"contract_id": "RAILIANCE-WP-0024-T02-SYNTHETIC-01",
"driver_revision": "sha256:941ba251f638869626b06e9cbf430c70188c0bdf4715e3eff9c7610366f68662"},
"synthetic_sender": {"identity": f"t03-e2-synthetic-sender-{start:%Y%m%d}",
"source": f"t03-e2-synthetic-{start:%Y%m%d}",
"tenant": f"tenant:trial:t03-e2-synthetic-{start:%Y%m%d}",
"expires_at": z(end)},
}
with open(out, 'x') as f:
json.dump(receipt, f, indent=2); f.write('\n')
print(json.dumps({"approval_id": receipt["approval_id"], "window": receipt["window"],
"confirm": f"audit-core-synthetic-sender:{receipt['approval_id']}:attended"}))