Skip to main content

audit_logs

Append-only audit trail of every sensitive action. Each row records who did what, when, and (during impersonation) on whose behalf.

Public surface​

Gated by the audit_log:read permission.

Verb + PathPurpose
GET /api/v1/admin/audit-logQuery the append-only log. Filters: filter[actor], filter[customer], filter[action], filter[objectType], filter[objectId]. Default limit=100, capped at 500. Each row carries stateBefore / stateAfter JSON inline so the admin viewer can render side-by-side diffs without a second roundtrip.

Recording​

AuditPort.record({ ... }) is invoked from every sensitive mutation: catalog price change, role change, credit-limit adjust, order status / payment status change "on behalf", impersonation start/end, API key out-of-scope, and others. Adding a new sensitive mutation is a two-line change at the call site.

The port is what a module types on and what the kernel publishes (packages/platform/src/kernel/ports/audit.ts); the container name it is registered under is auditLogService and has not changed. The implementation behind it, AuditLogService, is the platform's own and is reachable only by its relative path — a module that named the class would be depending on a writer shape uniform write auditing routes around, since a domain write goes through CommandBus.run and the bus writes the row.

Entities​

AuditLogEntry — actorAdminUserId, optional impersonatedCustomerAccountId, action, objectType, objectId, stateBefore, stateAfter, ipAddress, userAgent, requestId, actedAt.

Extension points​

  • External SIEM ship-out — emit a domain event on each new audit row and let an integration drain the stream into Splunk / Elastic / etc.
  • Retention — no automatic pruning today; retention windows belong to whoever runs the platform.