AUDIT-WP-0018-T03: report bounded-executor runs that started without a receipt
A sender may declare closing_classes; nk-bounded-executor declares execution.run.started closed by execution.attribution.receipt within 7200s. GET /v1/stream-findings reports opening_without_closing past the bound, counted from the receiver's accepted_at plus the heartbeat grace allowance; a per-run data.window.not_after tightens but never extends. Identifiers and timing only. The overlay may add or shorten, never remove, rebind or lengthen. Both backends: 403 passed (1 unrelated live-catalog env failure). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 482098@bnt-lap001 Assistant-Session: 9643c95a-a398-4f4a-b56a-6119be4e845e
This commit is contained in:
parent
9fb167871b
commit
2b8c9097ad
13 changed files with 654 additions and 6 deletions
|
|
@ -482,6 +482,29 @@ class PostgresAuditBackend:
|
|||
sql += " GROUP BY action ORDER BY action"
|
||||
return [{"class": action, "count": count} for action, count in self._query(sql, params)]
|
||||
|
||||
def unclosed_openings(
|
||||
self, source: str, opening: str, closing: str, since: str, limit: int = 500
|
||||
) -> list[dict]:
|
||||
"""Opening-class events with no closing-class event on the same
|
||||
``correlation_id`` (AUDIT-WP-0018-T03). Identifiers and timing only."""
|
||||
rows = self._query(
|
||||
"SELECT o.event_id, o.correlation_id, o.accepted_at, "
|
||||
"CASE WHEN jsonb_typeof(o.record->'details'->'data'->'window'->'not_after') = 'string' "
|
||||
"THEN o.record->'details'->'data'->'window'->>'not_after' END "
|
||||
f"FROM {self._events} o "
|
||||
"WHERE o.source = %s AND o.action = %s AND o.accepted_at >= %s "
|
||||
f"AND NOT EXISTS (SELECT 1 FROM {self._events} c "
|
||||
"WHERE c.correlation_id = o.correlation_id "
|
||||
"AND c.source = %s AND c.action = %s) "
|
||||
"ORDER BY o.accepted_at, o.event_id LIMIT %s",
|
||||
(source, opening, since, source, closing, int(limit)),
|
||||
)
|
||||
return [
|
||||
{"event_id": eid, "correlation_id": cid, "accepted_at": _iso(at),
|
||||
"window_not_after": na}
|
||||
for eid, cid, at, na in rows
|
||||
]
|
||||
|
||||
def last_heartbeats(self, source: str) -> dict[str, str]:
|
||||
"""Most recent heartbeat per class for one source."""
|
||||
rows = self._query(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue