Skip to content

Commit 8c3d693

Browse files
authored
Harden owner request packet parsing (#244)
1 parent 7a98bc2 commit 8c3d693

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

scripts/owner_requests/validate_owner_request_docs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def load_json(path: Path) -> dict[str, Any]:
4343

4444
def request_packet_body(text: str, request_id: str) -> str | None:
4545
match = re.search(
46-
rf"^### {re.escape(request_id)}\n(?P<body>.*?)(?=^### |\Z)",
46+
rf"^### {re.escape(request_id)}\n(?P<body>.*?)(?=^## |\Z)",
4747
text,
4848
re.MULTILINE | re.DOTALL,
4949
)
@@ -58,6 +58,7 @@ def receipt_backed_packet_section_problems(rel: str, text: str, requests: list[d
5858
request_id = str(req.get("id") or "")
5959
body = request_packet_body(text, request_id)
6060
if body is None:
61+
problems.append(f"{rel}: {request_id} must have its own ready-to-carry packet section")
6162
continue
6263
if "receipt-backed" not in body.lower():
6364
problems.append(f"{rel}: {request_id} must distinguish its receipt-backed status")

tests/test_owner_request_docs.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,52 @@ def test_receipt_backed_validation_is_packet_scoped(self):
5353
[],
5454
)
5555

56+
def test_receipt_backed_validation_requires_matching_packet_section(self):
57+
module = load("validate_owner_request_docs", "scripts/owner_requests/validate_owner_request_docs.py")
58+
text = """## Ready-to-carry packets
59+
60+
| Request | Status |
61+
|---|---|
62+
| `ORQ-FAKE-SKILLS-001` | `landed` |
63+
64+
### ORQ-FAKE-SKILLS-TYPO-001
65+
66+
Receipt-backed status: `owner_landing_ref` and `owner_proof_ref` are linked here.
67+
"""
68+
problems = module.receipt_backed_packet_section_problems(
69+
"fake/OWNER_REQUESTS.md",
70+
text,
71+
[{"id": "ORQ-FAKE-SKILLS-001", "queue_status": "landed"}],
72+
)
73+
self.assertEqual(
74+
problems,
75+
["fake/OWNER_REQUESTS.md: ORQ-FAKE-SKILLS-001 must have its own ready-to-carry packet section"],
76+
)
77+
78+
def test_request_packet_body_stops_before_later_h2_sections(self):
79+
module = load("validate_owner_request_docs", "scripts/owner_requests/validate_owner_request_docs.py")
80+
text = """## Ready-to-carry packets
81+
82+
### ORQ-FAKE-SKILLS-001
83+
84+
Status: `landed`; owner receipt linked.
85+
86+
## Center sources
87+
88+
Receipt-backed status: `owner_landing_ref` and `owner_proof_ref` are generic later text.
89+
"""
90+
body = module.request_packet_body(text, "ORQ-FAKE-SKILLS-001")
91+
self.assertIsNotNone(body)
92+
self.assertNotIn("## Center sources", body)
93+
problems = module.receipt_backed_packet_section_problems(
94+
"fake/OWNER_REQUESTS.md",
95+
text,
96+
[{"id": "ORQ-FAKE-SKILLS-001", "queue_status": "landed"}],
97+
)
98+
self.assertIn("fake/OWNER_REQUESTS.md: ORQ-FAKE-SKILLS-001 must distinguish its receipt-backed status", problems)
99+
self.assertIn("fake/OWNER_REQUESTS.md: ORQ-FAKE-SKILLS-001 must name owner_landing_ref in its packet", problems)
100+
self.assertIn("fake/OWNER_REQUESTS.md: ORQ-FAKE-SKILLS-001 must name owner_proof_ref in its packet", problems)
101+
56102
def test_owner_request_protocol_declines_center_activation(self):
57103
text = (ROOT / "mechanics/OWNER_REQUEST_PROTOCOL.md").read_text(encoding="utf-8")
58104
self.assertIn("A request packet is not owner acceptance", text)

0 commit comments

Comments
 (0)