Skip to content

Commit d3b0e66

Browse files
Pigbibicodex
andcommitted
Add validated feed primitive status
Co-Authored-By: Codex <noreply@openai.com>
1 parent 294e30b commit d3b0e66

4 files changed

Lines changed: 500 additions & 60 deletions

File tree

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
"""Validated producer rows and canonical per-feed status contract."""
2+
from __future__ import annotations
3+
4+
import hashlib
5+
import json
6+
import re
7+
from collections.abc import Iterable, Mapping
8+
from dataclasses import dataclass
9+
from typing import Any
10+
11+
STATUS_VERSION = "pert.feed_primitives.v1"
12+
MAX_ROWS_PER_FEED = 10_000
13+
_ROW_KEYS = frozenset({"item_id", "published_at", "source_type", "source_url", "author", "text"})
14+
_FEED_KEYS = frozenset({"feed_id", "feed_url", "kind", "state", "rows", "error_code"})
15+
_FEED_WIRE_KEYS = frozenset(
16+
{"feed_id", "feed_url", "kind", "state", "accepted_row_count", "rejected_row_count", "row_digest", "error_code"}
17+
)
18+
_STATUS_KEYS = frozenset(
19+
{
20+
"status_version",
21+
"configured_feed_count",
22+
"feed_count",
23+
"successful_feed_count",
24+
"failed_feed_count",
25+
"quarantined_feed_count",
26+
"accepted_row_count",
27+
"rejected_row_count",
28+
"publication_complete",
29+
"eligible_for_live_publication",
30+
"aggregate_row_digest",
31+
"feeds",
32+
}
33+
)
34+
_STATES = frozenset({"accepted", "failed", "quarantined"})
35+
_KINDS = frozenset({"rss", "atom", "unknown"})
36+
_SAFE_ERROR = re.compile(r"^[a-z][a-z0-9_]*$")
37+
38+
39+
class PrimitiveStatusError(ValueError):
40+
def __init__(self, code: str) -> None:
41+
self.code = code
42+
super().__init__(code)
43+
44+
45+
def _fail(code: str) -> PrimitiveStatusError:
46+
return PrimitiveStatusError(code)
47+
48+
49+
def _canonical_bytes(value: object) -> bytes:
50+
try:
51+
return json.dumps(
52+
value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False
53+
).encode("utf-8")
54+
except (TypeError, ValueError, UnicodeError, OverflowError, RecursionError):
55+
raise _fail("status_serialization_invalid") from None
56+
57+
58+
def _digest(value: object) -> str:
59+
return hashlib.sha256(_canonical_bytes(value)).hexdigest()
60+
61+
62+
def _string(value: object, code: str, *, allow_empty: bool = True) -> str:
63+
if type(value) is not str or (not allow_empty and not value):
64+
raise _fail(code)
65+
return value
66+
67+
68+
@dataclass(frozen=True, slots=True)
69+
class PrimitiveRow:
70+
item_id: str
71+
published_at: str
72+
source_type: str
73+
source_url: str
74+
author: str
75+
text: str
76+
77+
@classmethod
78+
def from_mapping(cls, value: object) -> "PrimitiveRow":
79+
if isinstance(value, cls):
80+
value = value.to_mapping()
81+
if not isinstance(value, Mapping) or set(value) != _ROW_KEYS:
82+
raise _fail("row_shape_invalid")
83+
try:
84+
snapshot = dict(value)
85+
except (TypeError, ValueError, RuntimeError):
86+
raise _fail("row_shape_invalid") from None
87+
return cls(
88+
item_id=_string(snapshot["item_id"], "row_invalid", allow_empty=False),
89+
published_at=_string(snapshot["published_at"], "row_invalid", allow_empty=False),
90+
source_type=_string(snapshot["source_type"], "row_invalid", allow_empty=False),
91+
source_url=_string(snapshot["source_url"], "row_invalid", allow_empty=False),
92+
author=_string(snapshot["author"], "row_invalid"),
93+
text=_string(snapshot["text"], "row_invalid"),
94+
)
95+
96+
def to_mapping(self) -> dict[str, str]:
97+
return {
98+
"item_id": self.item_id,
99+
"published_at": self.published_at,
100+
"source_type": self.source_type,
101+
"source_url": self.source_url,
102+
"author": self.author,
103+
"text": self.text,
104+
}
105+
106+
107+
def _snapshot_rows(value: object) -> tuple[PrimitiveRow, ...]:
108+
if isinstance(value, (str, bytes, Mapping)) or not isinstance(value, Iterable):
109+
raise _fail("rows_shape_invalid")
110+
rows: list[PrimitiveRow] = []
111+
try:
112+
for item in value:
113+
if len(rows) >= MAX_ROWS_PER_FEED:
114+
raise _fail("rows_limit_exceeded")
115+
rows.append(PrimitiveRow.from_mapping(item))
116+
except PrimitiveStatusError:
117+
raise
118+
except (TypeError, ValueError, RuntimeError, RecursionError):
119+
raise _fail("rows_invalid") from None
120+
return tuple(rows)
121+
122+
123+
def _snapshot_feed(value: object) -> dict[str, Any]:
124+
if not isinstance(value, Mapping) or set(value) != _FEED_KEYS:
125+
raise _fail("feed_shape_invalid")
126+
try:
127+
snapshot = dict(value)
128+
except (TypeError, ValueError, RuntimeError):
129+
raise _fail("feed_shape_invalid") from None
130+
feed_id = _string(snapshot["feed_id"], "feed_invalid", allow_empty=False)
131+
feed_url = _string(snapshot["feed_url"], "feed_invalid", allow_empty=False)
132+
kind = _string(snapshot["kind"], "feed_invalid", allow_empty=False)
133+
state = _string(snapshot["state"], "feed_invalid", allow_empty=False)
134+
error_code = snapshot["error_code"]
135+
if kind not in _KINDS or state not in _STATES or (
136+
error_code is not None and (type(error_code) is not str or not _SAFE_ERROR.fullmatch(error_code))
137+
):
138+
raise _fail("feed_invalid")
139+
rows = _snapshot_rows(snapshot["rows"])
140+
if state == "accepted" and (not rows or error_code is not None):
141+
raise _fail("feed_state_invalid")
142+
if state == "failed" and (rows or not error_code):
143+
raise _fail("feed_state_invalid")
144+
if state == "quarantined" and not error_code:
145+
raise _fail("feed_state_invalid")
146+
return {
147+
"feed_id": feed_id,
148+
"feed_url": feed_url,
149+
"kind": kind,
150+
"state": state,
151+
"rows": rows,
152+
"error_code": error_code,
153+
}
154+
155+
156+
def _feed_wire(feed: Mapping[str, Any]) -> dict[str, object]:
157+
rows = [row.to_mapping() for row in feed["rows"]]
158+
return {
159+
"feed_id": feed["feed_id"],
160+
"feed_url": feed["feed_url"],
161+
"kind": feed["kind"],
162+
"state": feed["state"],
163+
"accepted_row_count": len(rows),
164+
"rejected_row_count": 0,
165+
"row_digest": _digest(rows),
166+
"error_code": feed["error_code"],
167+
}
168+
169+
170+
def build_status(feed_records: Iterable[Mapping[str, object]]) -> dict[str, object]:
171+
if isinstance(feed_records, (str, bytes, Mapping)):
172+
raise _fail("feed_records_invalid")
173+
try:
174+
records = [_snapshot_feed(item) for item in feed_records]
175+
except PrimitiveStatusError:
176+
raise
177+
except (TypeError, ValueError, RuntimeError, RecursionError):
178+
raise _fail("feed_records_invalid") from None
179+
if not records:
180+
raise _fail("configured_feed_empty")
181+
if len({item["feed_id"] for item in records}) != len(records):
182+
raise _fail("feed_duplicate")
183+
records.sort(key=lambda item: (item["feed_id"], item["feed_url"]))
184+
feeds = [_feed_wire(item) for item in records]
185+
accepted = sum(item["state"] == "accepted" for item in records)
186+
failed = sum(item["state"] == "failed" for item in records)
187+
quarantined = sum(item["state"] == "quarantined" for item in records)
188+
rows = [row.to_mapping() for item in records for row in item["rows"]]
189+
complete = accepted == len(records) and failed == 0 and quarantined == 0 and bool(rows)
190+
return {
191+
"status_version": STATUS_VERSION,
192+
"configured_feed_count": len(records),
193+
"feed_count": len(records),
194+
"successful_feed_count": accepted,
195+
"failed_feed_count": failed,
196+
"quarantined_feed_count": quarantined,
197+
"accepted_row_count": len(rows),
198+
"rejected_row_count": 0,
199+
"publication_complete": complete,
200+
"eligible_for_live_publication": complete,
201+
"aggregate_row_digest": _digest(rows),
202+
"feeds": feeds,
203+
}
204+
205+
206+
def _validate_wire(value: object) -> dict[str, object]:
207+
if not isinstance(value, Mapping) or set(value) != _STATUS_KEYS:
208+
raise _fail("status_shape_invalid")
209+
try:
210+
snapshot = dict(value)
211+
except (TypeError, ValueError, RuntimeError):
212+
raise _fail("status_shape_invalid") from None
213+
if snapshot["status_version"] != STATUS_VERSION or type(snapshot["feeds"]) is not list:
214+
raise _fail("status_shape_invalid")
215+
integer_keys = (
216+
"configured_feed_count",
217+
"feed_count",
218+
"successful_feed_count",
219+
"failed_feed_count",
220+
"quarantined_feed_count",
221+
"accepted_row_count",
222+
"rejected_row_count",
223+
)
224+
if any(type(snapshot[key]) is not int or snapshot[key] < 0 for key in integer_keys):
225+
raise _fail("status_counter_invalid")
226+
if any(type(snapshot[key]) is not bool for key in ("publication_complete", "eligible_for_live_publication")):
227+
raise _fail("status_counter_invalid")
228+
if snapshot["publication_complete"] != snapshot["eligible_for_live_publication"] or not _is_digest(
229+
snapshot["aggregate_row_digest"]
230+
):
231+
raise _fail("status_integrity_invalid")
232+
if snapshot["configured_feed_count"] != snapshot["feed_count"] or snapshot["feed_count"] != len(snapshot["feeds"]):
233+
raise _fail("status_counter_mismatch")
234+
expected_counts = {
235+
"successful_feed_count": 0,
236+
"failed_feed_count": 0,
237+
"quarantined_feed_count": 0,
238+
"accepted_row_count": 0,
239+
"rejected_row_count": 0,
240+
}
241+
feed_ids: set[str] = set()
242+
for feed in snapshot["feeds"]:
243+
if not isinstance(feed, Mapping) or set(feed) != _FEED_WIRE_KEYS:
244+
raise _fail("feed_wire_shape_invalid")
245+
if (
246+
any(type(feed[key]) is not str or not feed[key] for key in ("feed_id", "feed_url", "kind", "state"))
247+
or feed["kind"] not in _KINDS
248+
or feed["state"] not in _STATES
249+
):
250+
raise _fail("feed_wire_shape_invalid")
251+
if feed["feed_id"] in feed_ids:
252+
raise _fail("feed_duplicate")
253+
feed_ids.add(feed["feed_id"])
254+
if (
255+
type(feed["accepted_row_count"]) is not int
256+
or feed["accepted_row_count"] < 0
257+
or type(feed["rejected_row_count"]) is not int
258+
or feed["rejected_row_count"] < 0
259+
):
260+
raise _fail("feed_counter_invalid")
261+
if not _is_digest(feed["row_digest"]):
262+
raise _fail("feed_digest_invalid")
263+
state = feed["state"]
264+
error = feed["error_code"]
265+
if state not in _STATES or (error is not None and (type(error) is not str or not _SAFE_ERROR.fullmatch(error))):
266+
raise _fail("feed_state_invalid")
267+
if state == "accepted" and (
268+
feed["accepted_row_count"] <= 0 or feed["rejected_row_count"] != 0 or error is not None
269+
):
270+
raise _fail("feed_state_invalid")
271+
if state == "failed" and (feed["accepted_row_count"] != 0 or feed["rejected_row_count"] != 0 or not error):
272+
raise _fail("feed_state_invalid")
273+
if state == "quarantined" and not error:
274+
raise _fail("feed_state_invalid")
275+
expected_counts[f"{state if state != 'accepted' else 'successful'}_feed_count"] += 1
276+
expected_counts["accepted_row_count"] += feed["accepted_row_count"]
277+
expected_counts["rejected_row_count"] += feed["rejected_row_count"]
278+
if any(snapshot[key] != value for key, value in expected_counts.items()):
279+
raise _fail("status_counter_mismatch")
280+
complete = (
281+
snapshot["successful_feed_count"] == snapshot["feed_count"]
282+
and snapshot["feed_count"] > 0
283+
and snapshot["accepted_row_count"] > 0
284+
)
285+
if snapshot["publication_complete"] != complete:
286+
raise _fail("status_counter_mismatch")
287+
return snapshot
288+
289+
290+
def _is_digest(value: object) -> bool:
291+
return type(value) is str and len(value) == 64 and all(char in "0123456789abcdef" for char in value)
292+
293+
294+
def serialize_status(value: Mapping[str, object]) -> bytes:
295+
return _canonical_bytes(_validate_wire(value))
296+
297+
298+
def parse_status_bytes(wire: bytes) -> dict[str, object]:
299+
if type(wire) is not bytes:
300+
raise _fail("status_wire_invalid")
301+
def pairs(items: list[tuple[str, object]]) -> dict[str, object]:
302+
result: dict[str, object] = {}
303+
for key, item in items:
304+
if key in result:
305+
raise _fail("status_duplicate_key")
306+
result[key] = item
307+
return result
308+
try:
309+
value = json.loads(wire.decode("utf-8"), object_pairs_hook=pairs)
310+
except (UnicodeError, json.JSONDecodeError, TypeError, ValueError, RecursionError):
311+
raise _fail("status_wire_invalid") from None
312+
parsed = _validate_wire(value)
313+
if serialize_status(parsed) != wire:
314+
raise _fail("status_noncanonical")
315+
return parsed
316+
317+
318+
def status_for_rows(wire: bytes, feed_records: Iterable[Mapping[str, object]]) -> dict[str, object]:
319+
parse_status_bytes(wire)
320+
expected = build_status(feed_records)
321+
if serialize_status(expected) != wire:
322+
raise _fail("status_integrity_mismatch")
323+
return expected

0 commit comments

Comments
 (0)