Second stores durable audit events in MongoDB so owners and admins can answer what changed in a workspace without reading prompts, source files, secrets, or raw app data. Audit logs are different from the existing realtime systems:Documentation Index
Fetch the complete documentation index at: https://docs.second.so/llms.txt
Use this file to discover all available pages before exploring further.
- Workspace events are Redis invalidation hints for mounted UI.
- Builder and app-agent streams are ordered user-visible run streams.
- Audit events are append-only, queryable workspace records.
Permissions
Workspace-wide audit logs requireaudit:read. Owners and admins have this
permission by default; members do not.
Audit reads always go through requireWorkspaceContext, then check
audit:read, then query audit_events with workspaceId. Looking up an audit
event by ID also includes workspaceId, so an event from another workspace
returns 404.
Exports are not part of the open-source v1 implementation, so there is no
audit:export permission yet.
Event shape
Every audit event records:| Field | Purpose |
|---|---|
workspaceId | Tenant boundary. Every query includes it. |
occurredAt / observedAt | When the action happened and when the platform stored it. |
eventName | Stable dot-delimited name such as member.role_changed. |
category | Broad area such as apps, members, integrations, or app_data. |
actor | User, agent, worker, app, or system identity known by the server. |
source | Platform, builder agent, app iframe, app agent, worker, or system provenance. |
target | Workspace object affected by the event. |
outcome / severity | Success, denial, failure, started, completed, plus importance. |
metadata | Small sanitized facts needed for investigation. |
changes | Changed field names and before/after hashes when useful. |
relatedIds | Safe IDs such as app, run, review, integration, or app-data document IDs. |
What is recorded
Open-source v1 records the core governance and platform events:| Area | Example events |
|---|---|
| Apps and builder runs | app.created, builder_run.created, builder_run.started, builder_run.completed, builder_run.failed, builder_message.submitted |
| Source snapshots | app.source_snapshot.updated with hash, file count, byte size, and artifact flag only |
| App metadata | app.renamed, app.deleted, app.visibility_changed, app.teams_changed, app.collaborator_added, app.collaborator_removed, app.collaborators_changed |
| Review and publishing | review.requested, review.approved, review.changes_requested, review.superseded, app.published |
| Members and teams | member.invited, member.invitation_revoked, member.role_changed, member.removed, team.created, team.renamed, team.deleted, member.team_added, member.team_removed |
| Integrations | integration.requested, integration.configured, integration.secret_rotated, integration.reset, integration.deleted, oauth.provider_configured, oauth.provider_secret_rotated, oauth.connected, oauth.connect_failed, oauth.revoked, oauth.token_refreshed |
| Permission denials | access.denied for safe same-workspace authorization failures |
| App-agent governance and runs | app.agents_config.approved, app.agents_config.stale, app_agent_run.created, app_agent_run.started, app_agent_run.completed, app_agent_run.failed |
| Custom tools | tool.custom.executed, tool.custom.denied, tool.custom.mocked, tool.custom.failed |
| App data writes | app_data.document.inserted, app_data.document.updated, app_data.document.upserted, app_data.document.deleted |
| Audit usage | audit.viewed through an explicit rate-limited POST |
Redaction
Audit metadata is sanitized before storage. The recorder strips control characters, caps metadata depth/size, truncates long strings and arrays, and redacts sensitive keys. Never store these in audit events:- source files, compiled artifacts, sourcemaps
- prompts, assistant messages, reasoning, full transcripts
- full app documents or full app-data documents
- integration secret values, OAuth tokens, API keys, cookies, sessions
- raw request headers, request bodies, or provider responses
- internal tokens, connection strings, private keys
Performance model
Audit history is not loaded on app lists, sidebar navigation, settings shells, chat routes, or access checks. The audit settings page uses bounded read APIs and manual refresh. Open-source v1 does not add an audit EventSource route. If live audit streaming is added later, it should use compact projections and must still authorize the connection withaudit:read.
Builder chat and app-agent streaming paths use nonblocking audit writes where
waiting on audit storage would make stream startup or completion feel slower.
The durable run/app mutation remains the source of truth if an audit insert
fails.
Tenant isolation
Every stored event hasworkspaceId. Every audit read includes workspaceId.
Target IDs are never used alone for lookup.
Browser-origin data is never trusted for actor, workspace, app, or source trust.
The server sets those fields from authenticated workspace context or from
validated internal worker context.