Skip to content

Commit 771f7d1

Browse files
Pigbibicodex
andcommitted
Reslice feed status quarantine contract
Co-Authored-By: Codex <noreply@openai.com>
1 parent 294e30b commit 771f7d1

4 files changed

Lines changed: 489 additions & 61 deletions

File tree

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

0 commit comments

Comments
 (0)