A Agentbar docs

Run your workspace

Audit log

Every workspace ships with an immutable audit trail at /app/audit. Admin and Owner roles can browse, filter, and inspect entries; Editor and Viewer are blocked.

What gets logged

The application writes to audit_logs for any action that materially changes workspace state or surfaces compliance exposure. Examples include:

  • Member invitations, role changes, removals.
  • Integration connect / disconnect (Slack, Teams, webhooks).
  • Integration webhook delivery failures (so broken Slack URLs are visible without tailing logs).
  • GDPR data-subject-request exports (dsr.exported) and erasures (dsr.erased).
  • Billing-plan changes initiated from the admin UI.

Action vocabulary

The application writes the following audit actions today. Filter on the Action toolbar field to surface a specific slug (substring match โ€” agent shows every agent.* row).

  • agent.created / agent.updated / agent.deleted / agent.bulk_deleted โ€” workspace owner creates / edits / removes an AI agent. Bulk-delete fires one row per affected agent so cross-tenant scoping is visible.
  • agent.published / agent.republished / agent.rolled_back โ€” the publish lifecycle. Republished fires when a draft change is re-published on top of an existing live version.
  • source.created / source.deleted โ€” knowledge sources attached to an agent (URL crawls, files, Notion, Google Docs, etc.).
  • workflow.created / workflow.updated / workflow.deleted / workflow.bulk_deleted โ€” scripted-reaction workflows.
  • member.invited / member.added / member.removed โ€” invitation, direct-add (when the invitee already had a Pitchbar account), and seat removal.
  • api_token.created / api_token.revoked / api_token.forgotten / api_token.purged โ€” workspace API token lifecycle. Forgotten = hard-deleted (single row). Purged = bulk hard-delete of every revoked row for the workspace.
  • platform_settings.updated โ€” super-admin saved a section of /settings/system. The after column records the section name + a list of changed non-sensitive keys; secret values (API keys, webhook secrets, SMTP passwords) are stripped before write so the audit row cannot leak credentials.
  • integration.webhook_secret_rotated โ€” admin rotated a webhook delivery secret.
  • dsr.exported / dsr.erased โ€” GDPR data-subject-request fulfillment.
  • impersonation.started / impersonation.stopped โ€” super-admin acted on behalf of a workspace member.

When an action fires from a context with no authenticated user (queue worker, scheduled command, webhook callback), the row's after.system_origin field carries a marker: console, webhook_or_queue, or background. Use this to distinguish "system did this" from "we forgot to capture the actor".

Each row carries: action slug, entity type / id, actor user (or System when triggered by a queue job), originating IP, user agent, and a before / after JSON snapshot.

Filtering

The toolbar accepts:

  • Action โ€” substring match (case-insensitive), e.g. dsr shows both exported and erased rows.
  • Entity type โ€” dropdown populated with the distinct entity types currently in your workspace's log, so you only see options that actually have history.
  • Actor email โ€” exact match on the user's email; pass an unknown email to surface only system-initiated rows.
  • From / To โ€” bracket created_at. Either bound is optional.

Filters compose; pagination respects the active filter set.

Retention

Audit rows are pruned daily via the scheduled command audit:prune --days=365. Default retention is one year โ€” long enough to investigate "what changed two quarters ago?" but bounded so the table doesn't grow without limit. Customers with stricter compliance requirements (SOC2, HIPAA, long-tail GDPR holds) should export their audit log via the artisan command on their own cadence before this prune fires. Override the window by passing a different --days value in your routes/console.php.

# Dry-run: report what would be pruned, change nothing.
php artisan audit:prune --days=365 --dry-run

# Force a longer retention window.
php artisan audit:prune --days=730

Why no edit / delete

Audit rows are append-only. There is no UI to edit a row, and the database has no updated_at column on audit_logs. This is intentional โ€” a compliance log that can be rewritten is not a compliance log.

Performance

The table is indexed on (workspace_id, created_at) and (entity_type, entity_id). A workspace with tens of thousands of rows still serves the first page in under 50ms. If you need to bulk-export, query the table directly via the workspace:audit-export Artisan command (planned) rather than scraping the UI.