📚 Audit-log series — stack on master (merge bottom → top)
- #10603 — part 1: Tier-1 audited dbUtils +
AuditAction enum → master (reland of #10514, reverted in #10584)
- #10515 — part 2:
auditedTransaction (branded AuditedTx) → #10603
- #10516 — part 3: Tier-2 pipeline + coverage middleware → #10515
- #10517 — part 4: read API (internal-dashboard) → #10516
Supersedes the production-based stack (#10355 / #10457 / #10510 / #10511 / #10513).
You are here: #10517
Description
Part 4 (on master, stacks on #10516) — the customer-facing read over the ClickHouse audit_logs table, on the internal-dashboard surface (dashboard-session auth) instead of the public v3.1 API.
clickhouse-audit-logs.ts — getAuditLogs(): org-scoped keyset pagination ordered (createdAt DESC, id DESC) to match the table ORDER BY, opaque cursor, exact-match parameterized filters over a hardcoded column allowlist (incl. the MATERIALIZED auth_method_kind/credential_id/actor_email).
GET /api/internal-dashboard/audit_logs — getDashboardRouter + getDashboardOrgAuthInfo, org ADMIN required, forces is_internal = 0 so internal/admin-token/system rows never surface to customers.
How did I test this PR
⚠️ Static-only (worktree has no deps); CI typecheck/lint is the backstop. Carried-over reader follow-ups (flagged earlier): reject undecodable cursors instead of replaying page 1, and over-fetch so dropped-on-validation rows don't end pagination early.
🤖 Generated with Claude Code
Update (chorm port)
- Read path now goes through chorm's client service (
makeService over the existing singleton): pinned deterministic read settings + typed errors. Row decoding moved zod → effect Schema, still per-row tolerant. SQL, filters, and keyset pagination unchanged.
- The carried-over reader follow-ups are done: malformed cursors are rejected with 400, and
nextCursor derives from raw rows so validation-dropped rows can't end pagination early.
- Org-wide reads are now index-range scans via the new
(org_id, project_id, createdAt, id) sort key (fixed in #10516, which owns the DDL).