Skip to content

Audit Logging

TSKit records user actions to an audit log. This gives you a trail of who did what and when, useful for security, debugging, and compliance.

The audit system has three parts:

  1. Facade (lib/facades/audit.ts) - The audit.log() function you call from server functions. It automatically captures the IP address and user agent from the request headers.
  2. Service (services/audit.service.ts) - Handles insertion and querying of audit records.
  3. Labels (lib/audit-labels.ts) - Maps action strings to human-readable labels for the UI.

Call audit.log() from any server function:

await audit.log({
actorId: context.user.id,
action: 'billing.checkout.created',
targetType: 'organization',
targetId: context.organization.id,
metadata: { planId: data.planId },
})

The ipAddress and userAgent fields are captured automatically - you don’t need to pass them.

Actions use dot-notation following the pattern domain.resource.verb:

  • billing.checkout.created
  • billing.subscription.cancelled
  • billing.plan.changed
  • team.member.invited
  • team.member.removed
  • team.member.role_changed
  • settings.profile.updated
  • settings.password.changed
  • settings.two_factor.enabled
  • admin.user.banned

The first segment (before the first dot) is treated as the domain. This is used for filtering in the UI.

FieldTypeRequiredDescription
actorIdstringNoThe user who performed the action
actionstringYesDot-notation action name
targetTypestringNoType of the target (e.g., “user”, “organization”)
targetIdstringNoID of the target
metadataobjectNoExtra key-value data
ipAddressstringAutoCaptured automatically
userAgentstringAutoCaptured automatically

The query() function in services/audit.service.ts supports filtering and cursor-based pagination:

const result = await query({
actorId: userId,
action: 'billing', // prefix match - finds all billing.* actions
from: new Date('2024-01-01'),
to: new Date('2024-12-31'),
cursor: lastItemId,
limit: 50,
})
// { items: AuditLog[], nextCursor: string | null }

Audit logs are displayed in two places:

  • Admin dashboard at /admin/audit - All audit logs across the app, accessible to admins.
  • User settings at /settings/activity - The current user’s own activity log.
FilePurpose
lib/facades/audit.tsAudit facade with auto IP/UA capture
lib/audit-labels.tsHuman-readable labels for action strings
services/audit.service.tsLog insertion and querying
database/schemas/audit.tsAudit log table schema