fix: audit batch 2 visibility (I-1 shadow dropped rows, I-2 partial policy failure, I-5 failure policy table)

- I-1: evaluate_shadow counts dropped rows by cause (unparseable /
  unknown_tier / explicit / duplicate) with the identity
  audit_rows_total == routed_task_n + dropped_total; the shadow
  endpoint passes created_at/id through and reports audit totals
  next to sample counts.
- I-2 (option b): parse logs a warning naming each tier dropped for
  an invalid mode/requires; load attaches partial_failures to the
  policy; the worker records a task-level
  worker_routing_policy_load_failed audit for partial failures
  (same action as full failure, detail says failure=partial);
  the shadow report carries the policy fingerprint, dropped tiers
  and partial failures (no task context on that path, so no
  task-level audit there).
- I-5: coordinator gate audit lookup failure now raises
  _CoordGateLookupFailed and the merge converts it to escalate
  (no requeue, no round consumed); persisted-model lookup failure
  and required-tools check failure each write a named audit row
  before falling through to dispatch/allow; audit-loop evaluate
  failure stays escalate (regression test).
- Test fixtures: coordinator suites build audit_log via AuthStore
  as production's first real audit does, since their stubbed
  _audit never creates the table.
This commit is contained in:
host committed 2026-11-04 18:02:22 +00:00
1 parent 44e0f4f1d6
commit a7f77c8a98
7 files changed
+648 -40

No files matched your search

+31 -2
View File
@@ -4212,7 +4212,7 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler):
conn = self._db()
try:
audit_rows = conn.execute(
"SELECT detail FROM audit_log"
"SELECT detail, created_at, id FROM audit_log"
" WHERE project_id = ? AND action = 'worker_routing'"
" ORDER BY created_at, id LIMIT 10001",
(project_id,),
@@ -4262,8 +4262,16 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler):
entry["unpriced_tokens"] += int(row["total_tokens"] or 0)
else:
entry["usd_micros"] += int(row["usd_micros"])
# Audit batch 2 (I-1): pass created_at/id through instead
# of stripping them — evaluate_shadow sorts by them for
# dedup, and the fetched rows were already ordered this
# way; stripping forced the sort to rely on input order.
# The report now carries audit_rows_total (from evaluate)
# next to routed_task_n, reconciled by dropped_rows.
report = _evaluate_shadow(
[{"detail": row["detail"]} for row in audit_rows],
[{"detail": row["detail"],
"created_at": row["created_at"],
"id": row["id"]} for row in audit_rows],
tasks_by_id, costs_by_task, explicit_n=explicit_n)
report["project_id"] = project_id
report["truncated"] = truncated
@@ -4360,6 +4368,27 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler):
report["recommendation"] += (
" Note: audit rows were truncated to 10000, so"
" this report is based on a partial sample.")
# Audit batch 2 (I-2): the currently loaded policy, as the
# report sees it — fingerprint plus any tiers dropped by
# fail-closed parsing and any source-level partial
# failures. This endpoint has no task context, so it
# cannot emit a task-level audit; that visibility lives
# on the worker dispatch path (see worker.py run_one).
# When no usable policy loads, status is "unavailable"
# and dropped tiers are unknown (not empty-by-claim).
if _policy is None:
report["routing_policy"] = {
"status": "unavailable", "fingerprint": None,
"dropped_tiers": [], "partial_failures": []}
else:
_dropped = list(getattr(_policy, "dropped_tiers", []) or [])
_partial = list(getattr(_policy, "partial_failures", [])
or [])
report["routing_policy"] = {
"status": "partial" if (_dropped or _partial) else "ok",
"fingerprint": _policy.content_fingerprint(),
"dropped_tiers": _dropped,
"partial_failures": _partial}
self._send_json(200, report)
def _task_cost(self, user_id, task_id):