Prepare canonical custody for audit E2 third attempt
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02991-be07-7bb3-8b6d-e9701b5621de
This commit is contained in:
parent
fc198b896f
commit
2a5c002aa5
5 changed files with 123 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
|
@ -177,6 +178,17 @@ def post_receipt(receipt: dict[str, Any], api_base: str) -> dict[str, Any]:
|
|||
return response
|
||||
|
||||
|
||||
def write_receipt(path: Path, receipt: dict[str, Any]) -> None:
|
||||
"""Persist only the canonical broker receipt, never the CLI wrapper."""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
descriptor = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
||||
try:
|
||||
with os.fdopen(descriptor, "w", encoding="utf-8") as handle:
|
||||
handle.write(json.dumps(receipt, indent=2, sort_keys=True) + "\n")
|
||||
finally:
|
||||
os.chmod(path, 0o600)
|
||||
|
||||
|
||||
def show(contract: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"interface": BROKER_INTERFACE,
|
||||
|
|
@ -206,10 +218,12 @@ def main() -> int:
|
|||
parser.add_argument("--consumer-root", type=Path)
|
||||
parser.add_argument("--reviewer")
|
||||
parser.add_argument("--note")
|
||||
parser.add_argument("--receipt-out", type=Path)
|
||||
parser.add_argument("--state-hub", default="http://127.0.0.1:8000")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
contract = validate_projection_contract(load_json(args.contract))
|
||||
receipt_out = None
|
||||
if args.command == "show":
|
||||
result = show(contract)
|
||||
elif args.command == "status":
|
||||
|
|
@ -223,6 +237,7 @@ def main() -> int:
|
|||
"secret_values_observed": False,
|
||||
}
|
||||
else:
|
||||
receipt_out = receipt
|
||||
result = {
|
||||
"ready": True,
|
||||
"engagement_id": contract["engagement_id"],
|
||||
|
|
@ -239,6 +254,7 @@ def main() -> int:
|
|||
verification = verify_adapter(args.consumer_root)
|
||||
receipt = build_approval(contract, args.reviewer, verification)
|
||||
posted = post_receipt(receipt, args.state_hub)
|
||||
receipt_out = receipt
|
||||
result = {"submitted": True, "message_id": posted["id"], "receipt": receipt}
|
||||
else:
|
||||
if not args.reviewer or not args.note:
|
||||
|
|
@ -246,6 +262,10 @@ def main() -> int:
|
|||
receipt = build_change_request(contract, args.reviewer, args.note)
|
||||
posted = post_receipt(receipt, args.state_hub)
|
||||
result = {"submitted": True, "message_id": posted["id"], "receipt": receipt}
|
||||
if args.receipt_out:
|
||||
if receipt_out is None:
|
||||
raise ReadinessError("--receipt-out requires approve or a ready status")
|
||||
write_receipt(args.receipt_out, receipt_out)
|
||||
print(json.dumps(result, indent=2, sort_keys=True))
|
||||
return 0
|
||||
except (ContractError, OSError, ReadinessError) as exc:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue