Skip to content

Audit log

Shipped

Your Turbobase instance keeps an append-only audit log of who did what. Administrators review it at /audit.

Every column on that page filters, and the filters combine: pick one event family in the toolbar, type part of an actor’s name or id, type part of an action or a target, set a date range, and narrow to the rows that carry a change. Sort by when it happened, by who did it, or by what they did. The whole matching set is reachable a page at a time — not just the most recent screenful — and the filters live in the address, so a filtered view is a link you can send to somebody. Click any row to open it: the panel says when the change happened, who made it, and which fields moved from what to what.

An export carries the whole set your filter matched, or refuses and tells you how many rows it would have left out, rather than handing over the first screenful as though it were the answer. A single file holds at most 50,000 rows — narrow the date range or the filter if yours is refused.

Each audit row captures the actor, a snapshot of that actor’s name at the time, the action, the affected target, optional before/after snapshots, and free-form context (such as IP address and user agent on a sign-in).

This list is generated from the instance’s own verb registry and is checked against it in both directions on every build, so it can be neither ahead of what is written nor behind it. Four more families are recorded outside that registry, because their exact event name is decided as the event happens; they have their own section below, and they are checked too.

  • Roles and grants — Creating, editing or deleting a shared role. The row carries the whole grant before and after, so a capability removed from a role that thirty people hold is reconstructable from the log alone.
    auth.role.created · auth.role.updated · auth.role.deleted
  • Sign-in, sessions and credentials — Who signed in, who could not, and every change to how an account proves who it is. Failed attempts carry the reason (suspended, not invited), so a session timeline reconstructs. A password CHANGE by a signed-in user is a different event from a password RESET of an account somebody may have lost control of, and each filters on its own. Setting or removing a profile picture is here too: the photograph is shown to everyone signed in to the tenant, so who changed it is a question this log has to be able to answer.
    auth.login.success · auth.login.failure · auth.login.role_unverified · auth.login.etag_blind · auth.session.minted · auth.session.revoked · auth.session.role_switched · auth.session.staff_impersonate · auth.session.view_as · auth.session.view_as_exited · auth.user.invited · auth.user.access_updated · auth.permissions.hydrated · auth.oidc_confirm.issued · auth.password.reset_requested · auth.password.reset · auth.password.changed · auth.passkey.enrolled · auth.passkey.removed · auth.totp.enrolled · auth.totp.removed · auth.otp_email.enrolled · auth.otp_email.removed · auth.profile_picture.set · auth.profile_picture.removed
  • The user directory — Suspending or reactivating a person, and linking or unlinking their source-system identity.
    user.suspended · user.reactivated · user.source_linked · user.source_unlinked
  • Connected sources — Secret rotation and clearing, re-authentication, the deploy-token handshake, the one-way switch that turns data sync on, and the two “re-read” behaviours of a linked record pair — reading the list of pairs, and switching either behaviour on or off for one of them. A switch carries both markers before and after, so when a re-read was turned on, and by whom, is answerable from the log alone.
    source.secret.rotated · source.secret.cleared · source.reauth.refreshed · source.reauth.failed · source.deploy_token.checkout · source.deploy_token.commit · source.data_sync.enabled · source.relationships.read · source.relationship_refresh.set
  • Apps — An app going live, being rolled back, having its source replaced, or being widened to everyone in the instance. The audience change is the one to watch: it exposes an app, and everything it renders, to every user here.
    app.deployed · app.rolled_back · app.shared · app.previewed · app.promoted · app.preview_discarded · app.enabled · app.disabled · app.deleted · app.source_pushed
  • Platform releases — A release deployed, pushed or rolled back, with the backend and the versions it moved between.
    release.deployed · release.pushed · release.rolled_back
  • Agent rules — The standing rules injected into every matching agent turn. A delete carries the retracted text, because the delete itself is permanent — it is what makes retracting a rule immediate. Recorded the same way whether the rule was armed from the Skills page or from the command line.
    skill.published · skill.unpublished · skill.rolled_back · skill.deleted · skill.updated
  • Knowledge base — Pages published, retracted, rolled back, deleted or rewritten, with the release each act cut. Recorded the same way whether the act came from the knowledge-base editor or from the command line.
    kb.published · kb.unpublished · kb.rolled_back · kb.deleted · kb.updated
  • Extensions, conduits and config — Deploys, tests, requests for the assistant to draft one, long-lived API token mints, permission changes, rotations, revocations and permanent deletions, authoring tool calls, binding repairs, and whole-manifest applies — each stamped to the acting administrator. A rotation names the token it retired and the one that replaced it; a permission change carries the token’s permissions both before and after, because the token itself only holds the new set; a deletion is recorded here precisely because the token’s own row is gone, so this page stays the answer to what became of it.
    extension.deployed · extension.test · extension.authored · extension.token.minted · extension.token.revoked · extension.token.rotated · extension.token.deleted · extension.token.scopes_changed · extension.mcp.call · extension.mcp.deploy · conduit.binding.retried · config.applied
  • Business-logic hooks and conduits — A hook proposed by the healing agent, and an administrator confirming, rejecting, disabling, enabling or removing it. The same five verbs cover a conduit, and a removal is recorded here precisely because the definition’s own row is gone: this page stays the answer to what became of it, and to who decided.
    hook.proposed · hook.confirmed · hook.rejected · hook.disabled · hook.enabled · hook.removed
  • Background processes — An administrator switching a deployed process off, which stops it running and stops every schedule queuing it, or back on. The row carries the state before and after and names who did it.
    process.enabled · process.disabled
  • Failed-record decisions — What an operator decided about a record the source refused, including an edited retry, which carries the whole payload before and after.
    failure.muted · failure.retried · failure.payload_edited
  • Sync — Writes pushed back to the source, a row someone linked to the record the source had already created, and whether a sync run started or was declined.
    sync.write.succeeded · sync.write.failed · sync.write.adopted · sync.run.started · sync.run.declined
  • The in-product agent — Records the chat agent created or edited on a person’s behalf, configuration and transform writes it made, the Slack actions it took once a person confirmed them (and the ones it refused), its crashes and slow turns, and consent granted to a connected MCP client. The last two are an administrator reading this trail itself through a connected assistant — searching it, or asking for one record’s whole timeline — because who read who changed what is as answerable as the change.
    chat.insert · chat.update · chat.config_write · chat.transform · chat.slack_action · chat.agent_crash · chat.tool_call_observation · chat.tool_call_long_running · chat.agent_slow_response · mcp.oauth.consent · mcp.audit_log.read · mcp.record_history.read
  • The healing agent’s own decisions — What the Mechanic did about a rejected record on its own initiative — deferred it, quarantined it, retried it, escalated it — and when a pattern was promoted to apply automatically.
    governance.defer · field_validation.quarantine · record_locked.retry · record_locked.quarantine · record_locked.workflow_quarantine · record_locked.escalate · unreadable_record.retry · unreadable_record.auto_ignore · permission.apply · permission.apply_failed · permission.reject · tier.promote · tier.promote.reject · setup.tenant.created

Five families name their event only at the moment it is recorded, so they are not in the generated list above. They are on the same trail, on the same page, and each is one of the toolbar’s event families.

  • Record changes — record.insert, record.update and record.delete, one row for every change to a mirrored record, written inside the database rather than by any part of the application. This includes the changes your connected source brings in: a change a person makes here and a change the connector projects in from your connected source are both recorded, and the actor on the row is what tells them apart — a person’s sign-in address, or sync_service for the connector. The row carries the record before and after, which is what the panel’s field-level comparison is built from. The one thing it does not carry is raw, the untouched payload your source sent: it is kept with the sync record itself, it can run to megabytes on a single transaction, and it would bury the fields that actually moved. Every column your instance has promoted out of it is recorded in full, and each row names the omission in its own context.
  • Boundary bypass — data.boundary_bypass.insert, data.boundary_bypass.update and data.boundary_bypass.delete, written inside the database rather than by any part of the application. This is the one that catches a write nobody meant to make: it is recorded when a signed-in session writes to a mirrored table directly, without going through the write path that runs your instance’s business logic first.
  • Guardrail configuration — guardrail.config.created, guardrail.config.updated, guardrail.config.activated, guardrail.config.deactivated, guardrail.config.deleted, guardrail.config.limit_changed, guardrail.config.posture_changed and guardrail.config.usage_reset. Every control over how much your instance may write back to a connected source — the rules, the rate caps, the allow-or-deny posture, and a reset of the usage counters. The exact event is decided from which setting moved, so it is recorded by the database at the moment of the change.
  • Install phase — phase.promoted, recorded when an instance is moved out of learning mode into steady state, whoever moved it.
  • Adapter operations — adapter.<source>.<operation>, one row per privileged operation an adapter performs on a connected source: creating or deleting a custom field, deploying a bundle, and so on. The event name carries the source and the operation, so the set is as wide as what that source lets an adapter do, and each row carries the guardrail decision that let it through.

Your instance keeps at least one year of audit history — the financial-record floor — and removes rows older than that on a rolling basis. One year is the shortest it can ever be: the retention window can be lengthened for an instance, never shortened below the floor. Export before you need it if you have to hand a period to an auditor after that window closes.

Every action that an authenticated identity takes is attributable to that identity, and the identity is taken from the verified session, never from what a request claims — a signed-in session cannot write an audit entry directly, only through the product’s own recorded actions. A staff impersonation session is stamped with the staff member’s identity, so a support action is traced back to a real person rather than to the borrowed user. Recording an audit event never blocks the action it’s recording — an audit write that fails is logged but never breaks the operation.