feat(api): GET /api/agent/audit — the user's agent write history #348

Closed
opened 2026-06-29 11:31:27 +00:00 by james · 0 comments
Owner

First half of epic #47's "audit log + undo" linked ticket: the read surface over the already-captured trail. The commit path writes one append-only audit_events row per applied proposal with before/after snapshots (#51, migration 023), but there's no way to list them — so the PWA can't show "what Carol changed." This adds that endpoint; undo is a separate follow-up (it needs real reversal-semantics design — conflict detection, re-creating ids, child rows, whether undo is itself audited).

Scope

  • GET /api/agent/audit — cursor-paginated (newest first) list of the authenticated user's audit events. DTO: id, entityType, entityId, action, tool, before, after (JSON snapshots decoded to structured values — null on create/delete respectively), proposalId, createdAt.
  • Per-user scoped: a user only ever sees their own trail (the table is already user_id-scoped + FK-cascade).
  • Keyset pagination on (created_at, id), mirroring the conversations list (zTimestampIdCursor + paginatedResponse). New AuditEventsRepository.listPageByUser; the existing listByUser (returns all) stays for internal callers/tests.
  • zod DTO, registered in the generated OpenAPI spec; api-client types regenerated.

Out of scope (follow-ups)

  • UndoPOST /api/agent/audit/{id}/undo reversing a write from its before/after snapshot. Own ticket + design.
  • The @carol/api-client hook + history UI.

Part of epic #47.

First half of epic #47's "audit log + undo" linked ticket: the **read** surface over the already-captured trail. The commit path writes one append-only `audit_events` row per applied proposal with before/after snapshots (#51, migration 023), but there's no way to list them — so the PWA can't show "what Carol changed." This adds that endpoint; **undo is a separate follow-up** (it needs real reversal-semantics design — conflict detection, re-creating ids, child rows, whether undo is itself audited). ## Scope - `GET /api/agent/audit` — cursor-paginated (newest first) list of the authenticated user's audit events. DTO: `id`, `entityType`, `entityId`, `action`, `tool`, `before`, `after` (JSON snapshots decoded to structured values — null on create/delete respectively), `proposalId`, `createdAt`. - Per-user scoped: a user only ever sees their own trail (the table is already `user_id`-scoped + FK-cascade). - Keyset pagination on `(created_at, id)`, mirroring the conversations list (`zTimestampIdCursor` + `paginatedResponse`). New `AuditEventsRepository.listPageByUser`; the existing `listByUser` (returns all) stays for internal callers/tests. - zod DTO, registered in the generated OpenAPI spec; api-client types regenerated. ## Out of scope (follow-ups) - **Undo** — `POST /api/agent/audit/{id}/undo` reversing a write from its before/after snapshot. Own ticket + design. - The `@carol/api-client` hook + history UI. Part of epic #47.
james closed this issue 2026-06-29 11:45:52 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#348
No description provided.