Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0217e-8c4c-7383-be6b-f50a6e485306
167 lines
5.6 KiB
Python
167 lines
5.6 KiB
Python
"""Allowlisted, non-secret summaries over local append-only evidence."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import re
|
|
import uuid
|
|
from collections import Counter
|
|
from dataclasses import asdict, dataclass
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
_LABEL = re.compile(r"^[a-z][a-z0-9-]{0,79}$")
|
|
_DECISION_REF = re.compile(r"^[A-Z][A-Z0-9-]{2,80}$")
|
|
_DELIVERY_RESULTS = {"delivered", "failed", "queued", "skipped-no-topic"}
|
|
_VERIFY_RESULT = re.compile(r"^(positive|negative):(pass|fail)$")
|
|
_ERROR_RESULT = re.compile(
|
|
r"^failed-(Catalog|Decision|PolicyGuard|Backend|Provisioning|Verification|Delivery)Error$"
|
|
)
|
|
|
|
|
|
def _safe_label(value: object) -> str:
|
|
text = value if isinstance(value, str) else ""
|
|
return text if _LABEL.fullmatch(text) else "invalid-label"
|
|
|
|
|
|
def _safe_result(value: object) -> str:
|
|
text = value if isinstance(value, str) else ""
|
|
if (
|
|
_LABEL.fullmatch(text)
|
|
or _VERIFY_RESULT.fullmatch(text)
|
|
or _ERROR_RESULT.fullmatch(text)
|
|
):
|
|
return text
|
|
return "invalid-label"
|
|
|
|
|
|
def _safe_decision_ref(value: object) -> str:
|
|
text = value if isinstance(value, str) else ""
|
|
if not text:
|
|
return ""
|
|
try:
|
|
return str(uuid.UUID(text))
|
|
except ValueError:
|
|
return text if _DECISION_REF.fullmatch(text) else ""
|
|
|
|
|
|
def _safe_timestamp(value: object) -> str:
|
|
if not isinstance(value, str):
|
|
return ""
|
|
try:
|
|
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
|
|
if parsed.tzinfo is None:
|
|
return ""
|
|
return parsed.astimezone(timezone.utc).isoformat()
|
|
except ValueError:
|
|
return ""
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class LaneAuditSummary:
|
|
catalog_id: str
|
|
operation_records: int
|
|
malformed_records: int
|
|
first_ts: str
|
|
last_ts: str
|
|
actions: dict[str, int]
|
|
results: dict[str, int]
|
|
decision_refs: list[str]
|
|
session_cleanup: dict[str, int]
|
|
hub_delivery: dict[str, int]
|
|
|
|
def to_json(self) -> dict[str, Any]:
|
|
return asdict(self)
|
|
|
|
def render(self) -> str:
|
|
lines = [
|
|
f"Lane audit summary for '{self.catalog_id}'",
|
|
f" operation records: {self.operation_records}",
|
|
f" malformed records: {self.malformed_records}",
|
|
f" first: {self.first_ts or 'n/a'}",
|
|
f" last: {self.last_ts or 'n/a'}",
|
|
" actions: " + _render_counts(self.actions),
|
|
" results: " + _render_counts(self.results),
|
|
" decisions: " + (", ".join(self.decision_refs) or "none"),
|
|
" session cleanup: " + _render_counts(self.session_cleanup),
|
|
" hub delivery: " + _render_counts(self.hub_delivery),
|
|
]
|
|
return "\n".join(lines)
|
|
|
|
|
|
def _render_counts(counts: dict[str, int]) -> str:
|
|
return ", ".join(f"{key}={value}" for key, value in sorted(counts.items())) or "none"
|
|
|
|
|
|
def summarize_lane_evidence(evidence_dir: Path, catalog_id: str) -> LaneAuditSummary:
|
|
"""Summarize one lane without returning arbitrary record fields or detail."""
|
|
actions: Counter[str] = Counter()
|
|
results: Counter[str] = Counter()
|
|
cleanup: Counter[str] = Counter()
|
|
hub_delivery: Counter[str] = Counter()
|
|
decisions: set[str] = set()
|
|
timestamps: list[str] = []
|
|
malformed = 0
|
|
operation_records = 0
|
|
|
|
for path in sorted(Path(evidence_dir).glob("evidence-*.jsonl")):
|
|
try:
|
|
lines = path.read_text(encoding="utf-8").splitlines()
|
|
except OSError:
|
|
malformed += 1
|
|
continue
|
|
for line in lines:
|
|
try:
|
|
record = json.loads(line)
|
|
except (json.JSONDecodeError, TypeError):
|
|
malformed += 1
|
|
continue
|
|
if not isinstance(record, dict):
|
|
malformed += 1
|
|
continue
|
|
if record.get("catalog_id") != catalog_id:
|
|
continue
|
|
action = _safe_label(record.get("action"))
|
|
result = _safe_result(record.get("result"))
|
|
if action == "evidence-delivery":
|
|
if result in _DELIVERY_RESULTS:
|
|
hub_delivery[result] += 1
|
|
else:
|
|
hub_delivery["invalid"] += 1
|
|
continue
|
|
|
|
operation_records += 1
|
|
actions[action] += 1
|
|
results[result] += 1
|
|
timestamp = _safe_timestamp(record.get("ts"))
|
|
if timestamp:
|
|
timestamps.append(timestamp)
|
|
decision = _safe_decision_ref(record.get("decision_id"))
|
|
if decision:
|
|
decisions.add(decision)
|
|
|
|
detail = record.get("detail")
|
|
session = detail.get("session") if isinstance(detail, dict) else None
|
|
if isinstance(session, dict):
|
|
attempted = session.get("revocation_attempted") is True
|
|
succeeded = session.get("revocation_succeeded") is True
|
|
if succeeded:
|
|
cleanup["succeeded"] += 1
|
|
elif attempted:
|
|
cleanup["failed"] += 1
|
|
else:
|
|
cleanup["not-attempted"] += 1
|
|
|
|
timestamps.sort()
|
|
return LaneAuditSummary(
|
|
catalog_id=catalog_id,
|
|
operation_records=operation_records,
|
|
malformed_records=malformed,
|
|
first_ts=timestamps[0] if timestamps else "",
|
|
last_ts=timestamps[-1] if timestamps else "",
|
|
actions=dict(sorted(actions.items())),
|
|
results=dict(sorted(results.items())),
|
|
decision_refs=sorted(decisions),
|
|
session_cleanup=dict(sorted(cleanup.items())),
|
|
hub_delivery=dict(sorted(hub_delivery.items())),
|
|
)
|