"""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())), )