Settings
Audit log
Append-only history of changes to the workspace: who changed what, when, and through which door (the app, the API, MCP, the Copilot, webhooks, imports and public feedback).
The Audit Log is the workspace's append-only event history: who changed what, when, and through which door.
What you'll see
- Event list: when, who, and what changed, written as a sentence: "published Checkout", "set Lead to Ada", "changed status from Planned to In Progress", "added beta to tags", "edited the description". Statuses, priorities, dates and linked records show by name, and long text is named rather than quoted. Then the channel it came through when it wasn't the app (
via API,via MCP,via Copilot), and the record's ID, which links to its page when it has one - Filters: type (any entity type, plus members, invitations, API tokens, widget keys, integrations, custom fields, comments, Claude Code sessions and workspace settings), action (created, updated, moved to Trash, restored, deleted permanently, linked, unlinked, revoked, connected, synced, imported and the rest) and source
- Paging: the latest 100 rows, then Load more; the count shows how many match
Every entity's detail also ends with an Activity section: that record's own history, newest first, loaded by the record's ID, so renaming a record keeps its history together. Links show on both records: linking feedback to a feature appears in the feature's Activity and in the feedback's.
Each row keeps the name of the person who acted, so the trail still says who did what after their account is deleted.
Sources
| Source | Meaning |
|---|---|
| App | A signed-in person in ProductOS |
| API | The REST API with an API token |
| MCP | An MCP connection (Claude and other clients), attributed to the person who connected it and to its token |
| Copilot | A change the in-app AI proposed and a person applied |
| Webhook | GitHub, Jira, Linear or another provider calling in |
| Scheduled | A scheduled integration sync |
| Widget, Portal, Feedback API | Feedback that arrived from outside, with no signed-in person |
| Onboarding, Import | The first-run wizard and workspace imports |
What's captured
| Area | Recorded |
|---|---|
| Entities in the app | Edits made in entity details, bulk actions and the right-click menu, with the fields that changed; changes applied from the Copilot |
| Members | Role changes, ownership transfers, removals, two-factor resets, recovery-code rotation, invitations sent, resent, revoked and accepted |
| Access | API tokens issued and revoked, MCP connections made and revoked (including automatic revocations), widget and Feedback API keys created, renamed and revoked, the Anthropic API key set or cleared (never its value) |
| Workspace | Settings changes (name, slug, timezone, language, sprint cadence, entity names, two-factor requirement, public changelog, portal and roadmap), the workspace identity on the Knowledge page, custom fields, team groups, onboarding completion and resets, the Danger zone's Delete all data |
| Integrations | Connect and disconnect (which settings changed, never their values), sync schedules, each sync run with its row count, imports from Linear and Jira |
| Collaboration | Comments added, edited, deleted and restored; documents linked to and removed from features; Claude Code sessions dispatched, cancelled and completed |
| From outside | Webhook changes to features and sessions (a merged pull request moving a feature forward, a pull request linked to the Work it names, an issue update), and feedback from the widget, the portal and the Feedback API |
| Imports | Every record a spreadsheet import or onboarding creates, and a summary row per run; a Replace import, and an import that fails and rolls back, record the wipe |
What's not captured
- Reads, searches and AI generation that writes nothing
- Sign-ins and sign-outs
- Personal settings: notification preferences, the notification inbox, saved views and view-mode preferences
- Derived data: embeddings, AI insight caches and AI urgency scores
- Claude Code session transcripts, which are their own log in the Sessions view
- The individual records an integration sync writes: each run is one row with its count
Read access
- Owners + Admins: full access
- Members, Commenters, Viewers: no access; the nav item appears dimmed with a lock icon, and the section renders a Locked panel explaining that admin or owner is required
The same rule holds everywhere the full trail can be read: GET /api/v1/audit-log, GET /api/v1/activity-log (list, single row and export), the MCP connector's list_entities, search_entities and get_entity on activity-log, and the database itself all need admin or owner. Below admin, a direct database read returns only the rows you wrote yourself.
Every role still sees an entity's own Activity section, the dashboard's recent activity and the Activity page. Below admin, those show changes to records (features, feedback, releases and the other entity types), comments and Claude Code sessions, and leave out rows about members, invitations, API tokens, widget keys, integrations, custom fields, repositories and workspace settings. GET /api/v1/activity serves all three: it takes the same filters as the audit-log route, plus search (text in the record's title as stored on the row) and user_id=none (changes no person made).
Append-only
No surface edits an audit row, and nothing deletes one except the owner's Delete all data in the Danger zone, which wipes the log with everything else and then records that it did. The API answers 403 to PATCH, DELETE and bulk actions on activity-log, and the AI action catalog has no write for it. A new row is always attributed to whoever made the call (and to their API token, when one was used), whatever user a request body names.
Retention
Rows are retained for the life of the workspace; tiered retention is not enforced.
API
GET /api/v1/audit-log returns the trail newest first. Filter with entity_type (a type such as features, or a subject such as members or api-tokens), entity_id, user_id, token_id, action (a verb such as updated), source (such as mcp or webhook), since and until, and page with limit (up to 200) and offset. entity_id matches the entity's own rows and the links that point at it. Older rows written under earlier spellings of a type or verb match the same filters. Each row carries actor_name, the person's name when it was written.
Related
- Members and roles
- API authentication: changes made with an API token are attributed to the token and its issuer