Round-10 review (railiance-platform) found that ContainedOperator inherited an ssh-only kubectl, so an E2 would write OpenBao and then fail its sync, restart and rollback. Also: a bad AUDIT_KUBECONFIG now leaves window-error evidence, and the receipt script validates bodies and lets a later request-changes withdraw an approval. 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
92 lines
3.7 KiB
Python
92 lines
3.7 KiB
Python
"""The E2 receipt generator emits a receipt the sender lane accepts as T03."""
|
|
import importlib.util
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from datetime import UTC, datetime
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def lane():
|
|
sys.path.insert(0, str(ROOT / "scripts"))
|
|
spec = importlib.util.spec_from_file_location("lane_e2", ROOT / "scripts/audit_core_synthetic_sender_lane.py")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def generator():
|
|
spec = importlib.util.spec_from_file_location("e2_receipt", ROOT / "scripts/rpf-wp-0015-e2-receipt.py")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_receipt_is_accepted_by_the_lane_as_t03(tmp_path, monkeypatch, capsys):
|
|
gen = generator()
|
|
owners = {o: {"acknowledged": True, "message_id": f"{o}-msg"} for o in gen.OWNERS}
|
|
monkeypatch.setattr(gen, "approvals", lambda review, contract, base: ("d" * 64, owners))
|
|
review = gen.review_module()
|
|
pins = review.load_contract()["artifact_sha256"]
|
|
monkeypatch.setattr(review, "file_sha256", lambda path: pins[str(path.relative_to(ROOT))])
|
|
monkeypatch.setattr(gen, "review_module", lambda: review)
|
|
out = tmp_path / "approval.json"
|
|
gen.main(["x", str(out)])
|
|
printed = json.loads(capsys.readouterr().out)
|
|
m = lane()
|
|
approval, spec = m.load_receipt(out, datetime.now(UTC), require_open_window=True)
|
|
assert approval["task_id"] == "RAILIANCE-WP-0024-T03"
|
|
assert printed["confirm"] == m.confirm_token(approval)
|
|
|
|
|
|
def test_refuses_to_overwrite(tmp_path):
|
|
out = tmp_path / "approval.json"
|
|
out.write_text("{}")
|
|
result = subprocess.run([sys.executable, str(ROOT / "scripts/rpf-wp-0015-e2-receipt.py"), str(out)],
|
|
capture_output=True, text=True)
|
|
assert result.returncode != 0 and out.read_text() == "{}"
|
|
|
|
|
|
def test_later_request_changes_withdraws_an_approval():
|
|
gen = generator()
|
|
review = gen.review_module()
|
|
contract = review.load_contract()
|
|
digest = review.contract_digest(contract)
|
|
|
|
def message(decision, created, mid, sender="audit-core", owner="audit-core"):
|
|
body = review.build_receipt(contract, owner, decision, "claude/x",
|
|
verification={"passed": True, "checks": []},
|
|
note="needs a fix in file.py:1" if decision == "request-changes" else None)
|
|
body["created_at"] = created
|
|
return {"id": mid, "from_agent": sender, "subject": review.receipt_subject(body), "body": json.dumps(body)}
|
|
|
|
class Resp:
|
|
def __init__(self, data): self.data = data
|
|
def __enter__(self): return self
|
|
def __exit__(self, *a): return False
|
|
def read(self): return json.dumps(self.data).encode()
|
|
|
|
def fetch(msgs):
|
|
import unittest.mock as um
|
|
with um.patch.object(gen.urllib.request, "urlopen", return_value=Resp(msgs)):
|
|
with um.patch.object(gen.json, "load", lambda r: msgs):
|
|
return gen.approvals(review, contract, "http://hub")
|
|
|
|
ok = [message("approve", "2026-11-03T10:00:00Z", f"{o}-1", o, o) for o in gen.OWNERS]
|
|
assert fetch(ok)[0] == digest
|
|
withdrawn = ok + [message("request-changes", "2026-11-03T11:00:00Z", "ac-2")]
|
|
try:
|
|
fetch(withdrawn)
|
|
except SystemExit as exc:
|
|
assert "audit-core" in str(exc)
|
|
else:
|
|
raise AssertionError("withdrawn approval was accepted")
|
|
forged = [message("approve", "2026-11-03T10:00:00Z", "f", "someone-else", "audit-core")] + ok[1:]
|
|
try:
|
|
fetch(forged)
|
|
except SystemExit:
|
|
pass
|
|
else:
|
|
raise AssertionError("approval from the wrong sender was accepted")
|