Every action a control plane operator takes — provisioning, suspending, decommissioning a tenant, inviting an org member, editing a plan — emits an OrgEvent to the audit log. The audit feed is the system-of-record for "who did what, and when" at the platform layer.
This page lists the events, what they mean, and what payload they carry. The wire shape is stable; new event types are additive.
Read the audit feed
Section titled “Read the audit feed”The control plane admin console's Audit page is the primary surface — see Read the audit log. For programmatic access the events surface is documented under Reference — API.
Each event row carries this shape:
interface OrgEvent { id: string // ULID, monotonic per org type: OrgEventType // enum below actor_id: string | null // user id; null for system events actor_email: string | null // best-effort denormalised email org_id: string tenant_id: string | null // present when the event scopes to a tenant data: Record<string, unknown> created_at: string // ISO 8601, UTC}Event types
Section titled “Event types”The type field is a closed enum following the <entity>.<action>.<phase> convention so consumers can prefix-filter cleanly. New types ship in versioned platform releases; existing types never rename.
Tenant provisioning saga
Section titled “Tenant provisioning saga”The provisioning workflow emits per-phase events so the audit feed reads as a chronological narrative of the saga's progress.
| Type | Emitted when | Payload includes |
|---|---|---|
tenant.provisioning.started | A platform operator submits a provisioning request and the workflow row is written | tenant_slug, plan, requested_by |
tenant.provisioning.step_completed | A saga activity completes (one event per step — validate, allocate, schema, deploy, etc.) | step, duration_ms |
tenant.provisioning.step_failed | A saga activity failed but the workflow is still inside its retry budget | step, attempt, error |
tenant.provisioning.completed | Provisioning succeeded and the tenant is now Active | tenant_id, total_duration_seconds, resources |
tenant.provisioning.failed | An activity fails after retries; the compensation chain has run | reason, failed_step, compensation_status |
tenant.provisioning.compensating | A compensating activity has started while unwinding a failure | step, compensation_kind |
tenant.provisioning.compensated | A compensating activity ran during failure or cancellation recovery | step, compensation_kind |
tenant.provisioning.cancelled is documented here as the canonical event for an operator-initiated cancel from the tenant detail page, but the saga doesn't emit it yet. Today, a cancel surfaces as the compensation events (tenant.provisioning.compensating / tenant.provisioning.compensated) followed by the final state change to Failed. The distinct cancelled event will fire from the same code path that runs cancel compensations once the emission is wired.
Reset saga (escape valve for a stuck provisioning)
Section titled “Reset saga (escape valve for a stuck provisioning)”Reset is a separate workflow from provisioning; it runs to clear a wedged workflow handle and emits its own three events.
| Type | Emitted when | Payload includes |
|---|---|---|
tenant.provisioning.reset_started | A platform operator submits a reset on a stuck tenant | previous_state |
tenant.provisioning.reset_completed | Reset finished cleanly; the tenant is back in Pending with a fresh saga ready | previous_workflow_id |
tenant.provisioning.reset_failed | Reset itself failed (rare; usually because cancel hadn't fully completed) | reason |
Tenant deprovisioning saga
Section titled “Tenant deprovisioning saga”| Type | Emitted when | Payload includes |
|---|---|---|
tenant.deprovisioning.started | Decommission request accepted; resource release begins | tenant_id, requested_by |
tenant.deprovisioning.step_completed | A decommission step completes (one event per step) | step, duration_ms |
tenant.deprovisioning.step_failed | A decommission step failed but the workflow is still inside its retry budget | step, attempt, error |
tenant.deprovisioning.completed | Decommission finished; resources released | archive_url (if archive policy is on) |
tenant.deprovisioning.failed | A decommission step failed; partial release | failed_step, reason |
Update saga (plan/region/topology applied to a tenant)
Section titled “Update saga (plan/region/topology applied to a tenant)”The Update workflow re-applies the org's current plan to a tenant's namespace (retention, knobs). Used when the org's plan changes or when topology overrides shift.
| Type | Emitted when | Payload includes |
|---|---|---|
tenant.update.started | An update workflow starts on a tenant | change_kind, requested_by |
tenant.update.completed | The update applied cleanly | change_kind, duration_ms |
tenant.update.failed | The update failed at some step | change_kind, failed_step, reason |
Plan-upgrade saga (org plan tier flip)
Section titled “Plan-upgrade saga (org plan tier flip)”The plan-upgrade workflow flips the org's plan, recomputes effective knobs, briefly holds the tenant row read-only, and bumps the data-plane cache version.
| Type | Emitted when | Payload includes |
|---|---|---|
tenant.plan_upgrade.started | The plan upgrade saga begins | from_plan, to_plan, requested_by |
tenant.plan_upgrade.completed | Plan upgrade finished cleanly | from_plan, to_plan, duration_ms |
tenant.plan_upgrade.failed | Plan upgrade failed and compensations are running | failed_step, reason |
tenant.plan_upgrade.compensated | A compensation step ran during plan-upgrade rollback | step, compensation_kind |
tenant.plan_upgrade.compensation_failed | A compensation step itself errored — operator intervention may be required to clear stuck state | step, reason |
Tenant lifecycle (post-provisioning)
Section titled “Tenant lifecycle (post-provisioning)”| Type | Emitted when | Payload includes |
|---|---|---|
tenant.suspended | A platform operator pauses tenant traffic | reason |
tenant.resumed | A suspended tenant is resumed | none |
Organisation members
Section titled “Organisation members”| Type | Emitted when | Payload includes |
|---|---|---|
org.member_invited | A platform operator invites a new org member | invitee_email, role |
org.member_accepted | An invited member accepts | member_id |
org.member_removed | A member is removed | member_id, reason |
org.member_role_changed | A member's role within the org changes | member_id, from, to |
org.invitation_resent | A pending invitation's link was re-emailed | invitation_id |
org.invitation_revoked | A pending invitation was cancelled before acceptance | invitation_id, reason |
org.ownership_transferred | The Owner role moved from one member to another | from_member_id, to_member_id |
Plans and policy
Section titled “Plans and policy”| Type | Emitted when | Payload includes |
|---|---|---|
plan.tenant_plan_changed | A platform operator changes a tenant's plan | tenant_id, from, to, effective_at |
policy.mfa_default_changed | The platform-wide MFA default for new tenants changes | from, to |
Filtering at read time
Section titled “Filtering at read time”The endpoint takes optional type and tenant_id query parameters. The control plane console uses these to drive the audit page filters; SIEM exports use the same shape.
GET /api/v1/organizations/{id}/events?type=tenant.provisioning.failed&tenant_id={t}&cursor=01HZX...&limit=50What's missing from the audit feed
Section titled “What's missing from the audit feed”Three things are deliberately not in this feed:
- Tenant-scoped events — what individual users did inside a tenant lives in the tenant's own audit log, not the platform feed. Access via the tenant admin console.
- Read-only viewing — opening a page doesn't emit an event. Only state changes do.
- Health probe results — infrastructure-level signals belong in the observability stack, not the audit ledger.