Skip to content

feature: add workspace history of actions (History page + audit_events) - #271

Open
jmooves wants to merge 1 commit into
Open-Legal-Products:mainfrom
jmooves:upstream-pr/audit-history
Open

feature: add workspace history of actions (History page + audit_events)#271
jmooves wants to merge 1 commit into
Open-Legal-Products:mainfrom
jmooves:upstream-pr/audit-history

Conversation

@jmooves

@jmooves jmooves commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

User Experience

Currently no audit history exists within Mike. This feature enhancement adds an audit trail of user actions with a top-level History page and adds a sidebar entry below Workflows.

What it does

  • History page (/history): User · Created · Title (linked to the chat/review) · Status · Type · Application · Model, with search, a type filter, a date range, CSV export and pagination.
  • Recorded actions: chat turns (model used; cancelled status when a stream is aborted) with per-artifact rows mined from the persisted stream events (generated documents, edits, applied workflows), document uploads, tabular review creation and generation runs, and data exports.
  • Visibility: each user sees their own actions plus activity in projects they own or that are shared with them and reuses the existing shared_with model, no new permission concept.

Design notes

  • audit_events is append-only, added to schema.sql (fresh installs) and as a dated migration (existing deployments). Accessed only via the service-role backend.
  • The recorder (lib/audit.ts) is fire-and-forget: it can never throw or block a user-facing path - failures log and are swallowed.
  • Artifact rows come from the already-persisted assistant events, so the tool layer needed no changes.

Testing

  • npx vitest run green on this branch; tsc clean on both apps; next build includes /history.
  • Validated end-to-end on a self-hosted deployment: a chat turn, review creation and a chats export all appeared in /audit with correct fields; the type filter and CSV export verified.

🤖 Generated with Claude Code and human reviewed. :)

left_pane new_history_pane

Adds an append-only audit trail of user actions with a top-level History
page (sidebar entry): User, Created, Title (linked), Status, Type,
Application and Model columns, with search, type filter, date range, CSV
export and pagination.

Backend: audit_events table (schema.sql + dated migration), a
fire-and-forget recorder (lib/audit.ts) that can never throw or block a
user-facing path, and call sites for chat turns (model, cancelled status,
plus per-artifact rows for generated/edited documents and applied
workflows mined from the persisted stream events), document uploads,
tabular review creation/generation and data exports. GET /audit lists
events (visibility: own actions plus activity in projects owned by or
shared with the caller); GET /audit/export streams the same view as CSV.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jmooves jmooves changed the title feat: workspace history of actions (History page + audit_events) feature: add workspace history of actions (History page + audit_events) Jul 28, 2026
@amal66

amal66 commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks for taking this on — an audit trail is a real gap in Mike, and you got the hard parts right: the fire-and-forget recorder genuinely can't reject (which matters, since a floating rejection would take down the process), and visibility failing closed on a project-lookup error is exactly the right default.

A few things I'd consider blocking, all with small fixes:

  • audit_events has no revoke or RLS, so hosted PostgREST exposes it to browser roles for read and write — every other backend-only table revokes anon, authenticated. Needs the same in both schema.sql and the migration, plus enable row level security.
  • Account deletion never purges audit_events (userDataCleanup.ts) — a right-to-erasure problem, and the account export omits them too.
  • csvCell in routes/audit.ts doesn't neutralize leading =/+/-/@, and chat titles are attacker-controlled cross-user — classic CSV formula injection.
  • In schema.sql the blanket grants run before the audit_events DDL, so fresh installs get permission-denied inserts (silently, since the recorder swallows errors).

Also worth picking up: /audit/export skips the rate limiter and MFA gate the other exports have; project-document uploads aren't actually audited and doc_replicated events are mined from the wrong event shape; page/from/to are unvalidated and can 500; and the History page has no error state and races on rapid filter changes.

I've opened jmooves#1 against your branch with all of this fixed, plus tests — merge it and this PR updates, or cherry-pick what you agree with. It sits directly on your branch: five focused commits, nothing unrelated, with rebasing onto current main left to you. Both typechecks are clean and both suites pass on the result (backend 273, frontend 38).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants