Manage · Audit log

Trace an action before you export it

RepoOps gathers mirrored audit envelope events into one newest-first table. Narrow the question by repo, time, actor, action, or account, inspect the row, then export the same bounded result set.

For: the repository operator investigating an action, and the team member reviewing events already pushed to the hosted account

What it does, and why it helps

The desktop Audit log reads kind:"audit" envelopes from each visible tracked repository's event store. It projects the time, repository, actor, action, account, scope, and payload into one row shape. Search applies all selected filters and sorts the result newest first. Last 7d fills an inclusive date window. Export CSV sends the same filters and limit to the API.

That distinction matters: this is the envelope mirror, not the original audit ledger. Writers in lib/audit-log.mjs append the primary day-partitioned record first, then try the envelope mirror without failing the primary write if mirroring fails. The table can therefore omit a primary row. It also returns at most the chosen limit, 200 by default and 5,000 at most. Start with a bounded question, inspect the payload in context, and treat the export as that filtered record rather than proof that no other event exists.

The pain. A timestamp or action name is not enough to explain an incident. The useful question joins who acted, which repository and account were in scope, what action was recorded, and what bounded payload came with it.

The point of view. Narrow the audit question before exporting. A filtered row is evidence for an investigation, not a verdict about intent and not a claim that the trail is complete.

What gets easier. Finding recent rows across tracked repositories, matching an actor id without case sensitivity, selecting an action the current window has recorded, and carrying the same filters into a CSV download.

When it helps. Use it after an account, repository, supervisor, connector, SAML, SCIM, or other producer writes an audit envelope and you need the actor, action, time, account, or payload fields in one view.

Its limits. The page does not reconstruct intent, verify a payload against its source system, or prove completeness. The desktop payload cell shows at most 240 characters, though CSV keeps the projected payload. Undated local reads do not open monthly archives. The result and CSV are capped at 5,000 rows.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 An event happened.
  2. 0:01 A timestamp alone cannot answer who acted or what changed.
  3. 0:06 Filter by actor and action first, then narrow the time window and repository.
  4. 0:13 RepoOps shows the mirrored envelope's actor, account, action, and bounded payload.
  5. 0:18 The CSV applies the same filters and inclusive dates you inspected.
  6. 0:23 Keep the filtered record, then investigate the source event in its context.

Synthetic example. Read the guide

Where to find it

Where to find it

  • Desktop: localhost:4000, then Local settings in the sidebar, then Audit log under Workspace utilities.
  • Hosted: repoops.ai/team/cloud-audit, from Team & settings in the sidebar, then Cloud audit under Account and access.
  • Keyboard: ⌘ K, then type “Audit log”.

When to use it

Trace an action reported by an operator

Situation. An operator remembers part of the actor id and the day, but not which tracked repository emitted the row.

What you do. Leave Repo at All repos. Set Since (date) and Until (date), enter the fragment in Actor (substring), choose the recorded Action, and press Search.

What you see. The table shows When (UTC), Repo, Actor, Action, Account, and Payload. Actor matching is case-insensitive substring matching; Action and Account ID are exact matches.

What it establishes. You have a bounded set of mirrored envelopes to compare with the source action. A matching row establishes what the envelope recorded, not why the actor acted.

Hand off a filtered event set

Situation. A reviewer needs the rows behind a date and action question in a file, without copying a truncated payload preview from the table.

What you do. Apply the filters, choose a Limit that covers the intended working set, press Search, inspect the count, then press Export CSV.

What you see. The CSV uses stable columns for timestamp, repository, actor type, actor id, action, account, scope, and payload. It carries the current filter query and limit.

What it establishes. The reviewer gets the same capped, filtered rows as the query. If the cap was reached, narrow the date or repository and export another window; the file does not claim to contain the whole trail.

Before you start

Supported versions
RepoOps desktop v0.3.1, the release this guide was read against.
Where it runs
Local: Local settings, Workspace utilities, Audit log. Hosted: repoops.ai/team/cloud-audit reads audit envelopes the account has received. The hosted surface omits the desktop Repo and Account ID inputs, but keeps Since, Until, Actor (substring), Action, Limit, Search, and Export CSV.
Permissions
A local install without an explicit tenant scope scans every tracked repository, including repositories with different account labels. An explicit tenant scope reads that account's repositories plus unassigned repositories. Hosted access needs an authenticated, entitled team member. The sidebar marks Audit log owner/admin, but the page itself checks membership and does not call canManage, so the navigation label is not an access-control boundary.
Connections
The desktop needs tracked repository paths containing .claude/brain/events day files. The hosted view needs audit envelopes in the account's events table, either pushed from a bound device through the opted-in cloud path or written by a hosted producer.
Plan
The local route has no plan gate. The hosted page is inside the hosted dashboard entitlement and seat checks. This shared Audit log CSV is not the separate Enterprise team administration export at /team/audit.

Configure it

  1. State the question before choosing a limit.

    Decide whether repository, date, actor, action, or account is the fact you are testing. The API joins all supplied filters, so each added field narrows the same result set.

  2. Set the repository and time window.

    Keep Repo at All repos for a cross-repository question, or choose one tracked repo. Since (date) and Until (date) are inclusive. Last 7d fills both dates and runs the query.

  3. Narrow by actor, action, or account.

    Actor (substring) ignores case. Action is exact and its choices come from actions recorded in the current result window. Account ID is an exact payload match and narrows within the already visible repository scope; it never widens account access.

  4. Inspect before exporting.

    Press Search, check the row count and limit, then read the table. Payload omits action and accountId because each has its own column, and the preview truncates after 240 characters. Use Export CSV when you need the full projected payload.

SettingWhereA sensible choiceWhy it matters
RepoAudit log controlsAll repos (the default), or one tracked repositoryThis chooses which visible repository roots the local reader scans.
Since (date)Audit log controlsBlank, or the first day to includeA date also lets the local reader open matching monthly archives when recent raw files do not fill the limit.
Until (date)Audit log controlsBlank, or the last day to includeA date-only value includes the whole named day.
Actor (substring)Audit log controlsBlank, or part of an email or idThe match is case-insensitive against actor.id.
ActionAudit log controlsAny (the default), or an action recorded in the windowThe match is exact. The list is derived from recorded rows rather than a fixed vocabulary.
Account IDAudit log controlsBlank, or an exact payload account idIt narrows the current scope and cannot expose another tenant's repository.
LimitAudit log controls200 (the default); 50, 1,000, or 5,000The limit caps both the displayed result and the CSV. The API clamps any other value from 1 to 5,000.
ⓘ
To stop or undo
Clear the text and date fields, return Repo to All repos and Action to Any, choose the desired Limit, then press Search. This only resets the query. Not provided: a switch that stops audit producers or disables the Audit log reader.

What you should see

A recent cross-repository view

Configuration. Repo is All repos, the other filters are blank, and Limit is 200.

Expect. The desktop returns up to 200 newest mirrored audit envelopes from visible tracked repositories. An undated query reads current raw day files and does not open monthly archives.

Verify. The meta line reports the row count, limit, and account. The first column is When (UTC), and the empty state reads No audit rows match these filters.

The Last 7d date window

Configuration. Press Last 7d, then optionally add Actor (substring) or Action.

Expect. RepoOps fills Since (date) with the date seven days before the current date, fills Until (date) with the current date, and runs Search. Both boundary dates are included.

Verify. The meta line names the since and until values. Each returned When (UTC) value falls inside that date window.

A CSV that matches the query

Configuration. Set a bounded date, repository, actor, action, or account question, choose the limit, inspect Search, then press Export CSV.

Expect. The browser downloads audit-YYYY-MM-DD.csv with the current filters and no more than the selected limit.

Verify. The local header starts ts, repoId, actorType, actorId, action, accountId, scope, payload. Compare its row count and filter values with the on-screen query before treating it as evidence.

Data and cost

What is captured
The reader projects an envelope id, timestamp, actor type and id, scope, payload action, payload accountId, repository id, and the remaining payload. The page does not create those events. Writers decide their payload; for example, cross-client ask stores a SHA-256 query hash rather than the query text.
Who can see it
On a local single-operator install, the view spans every tracked repository. An explicit local tenant scope narrows repository roots. Hosted queries require an authenticated account membership and filter the events table by account id. The hosted navigation hides this row from non-managers, but the route currently enforces membership rather than an owner/admin role.
How long it is kept
Local envelope day files stay raw for 30 days by default, controlled by REPOOPS_EVENTS_RETENTION_DAYS, then move into monthly gzip archives rather than being deleted. Primary day-partitioned audit ledgers stay raw for 90 days by default through REPOOPS_AUDIT_RETENTION_DAYS, then archive. The local reader opens envelope archives only for a dated query. Hosted audit rows are hard-deleted after 13 months. A tab visit is stored as an audit row but records usage, so it goes after 30 days with the rest of the hosted telemetry, and REPOOPS_NEON_RETENTION_DAYS can shorten that 30 and nothing else. An organization window may tighten either, but not extend them. account.delete-requested rows are exempt from the hosted event sweep.
What leaves the machine
Local Search and Export CSV read repository files and make no model call. The download leaves the process only to the requesting browser. When cloud event sync is enabled, redacted envelopes are pushed to the bound hosted account; the hosted page reads only events already stored there.
What it costs
There is no model or third-party API call for Search, Last 7d, or Export CSV. Local cost is file reads and storage. Hosted use consumes the existing database, network, and hosted plan resources, with no per-query model spend.

When the result differs

SymptomLikely causeNext action
An old event is missing from an unfiltered local search.Undated reads do not open monthly gzip archives, even when fewer rows than the limit were found in raw day files.Set Since (date) or Until (date) to the period that contains the event, then press Search again.
A row exists in a primary audit ledger but not in Audit log.The primary write happens first and the envelope mirror is best effort. This page reads only audit envelopes that reached the mirror.Inspect the producer's day-partitioned audit ledger. Do not use an absent mirror row as proof that the primary action did not occur.
The payload cell ends before the expected field.The table preview is capped at 240 characters and omits action and accountId, which have their own columns.Export the filtered rows and inspect the payload column in the CSV.
The export stops at 200 or 5,000 rows.Limit defaults to 200 and the API hard cap is 5,000. Export CSV uses that same limit.Choose the intended Limit and narrow the date or repository into separate windows if the result reaches the cap.
The hosted table has no row that appears locally.The hosted page sees only audit envelopes pushed or written into that account's events table, and hosted retention may already have removed an older row.Check the bound account, event sync state, selected dates, and account membership. Keep the local primary ledger as the source record for its producer.
Disable
Not provided. Audit log is a read and export surface with no enable switch; disabling a producer or cloud sync is a separate action and does not remove stored rows.
Roll back
Not provided. Search, Last 7d, and Export CSV do not mutate the audit store, so there is no Audit log change to roll back.
Revoke access
Not provided on this page. Hosted access follows session, device-token, and team-membership controls. Revoke those credentials or membership on their owning surfaces; the local Audit log has no feature-specific credential.
Delete
Not provided. The page has no row-delete action. Local envelopes live under .claude/brain/events and primary rows under .claude/brain/audit; hosted event rows leave through retention or the separate account deletion process.

Maintenance evidence

Feature id
audit-log (spine leaf audit-log)
Owner
Identity production (K5.F), Guide: LDG-0717
Supported product version
RepoOps v0.3.1
Last verified
2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source; local and hosted routes, retention jobs, scope checks, and tests read in the same pass
Example fixtures
lib/audit-events.test.mjs, lib/audit-api.test.mjs, lib/audit-log.events.test.mjs, website/app/api/audit/audit.test.ts, website/lib/audit-until-param.test.ts, website/lib/audit-actions.db.test.ts
Source references
lib/canonical-spine.json, public/audit-log.html, lib/audit-api.mjs, lib/audit-events.mjs, lib/audit-log.mjs, lib/audit-partition.mjs, lib/brain-events.mjs, website/app/team/(home)/cloud-audit/page.tsx, website/lib/audit-events-repo.ts, website/app/api/audit/route.ts, website/app/team/(home)/layout.tsx, website/app/api/cron/events-retention/route.ts
Documentation review
Independent review requested on the slice pull request; not yet recorded.
Video review
Narrated story rendered and published 2026-09-26 (render 24f0bd0dd5f6, LDG-1018) with the breadcrumb Local settings, checked against main at 0f24215b5. One frame, the captions and the transcript were reviewed by the authoring agent, not an independent reviewer; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.

Last updated