Skip to content

Manual Logging

Use AuditService.log() for business events that are not automatically tracked by the Prisma extension.

Basic Usage

typescript
await auditService.log({
  action: 'invoice.approved',
  targetId: 'inv-123',
  targetType: 'Invoice',
  metadata: { amount: 5000, currency: 'USD' },
});

With Transaction

typescript
await prisma.base.$transaction(async (tx) => {
  await tx.invoice.update({ where: { id }, data: { status: 'approved' } });
  await auditService.log({
    action: 'invoice.approved',
    targetType: 'Invoice',
    targetId: id,
  }, tx);
  // Both roll back together if anything fails
});

AuditLogModule.forRoot / forRootAsync Options

OptionTypeDefaultDescription
prismaPrismaClientrequiredBase Prisma client for audit storage
actorExtractor(req) => AuditActor | Promise<AuditActor>requiredExtracts actor from HTTP request
tenantRequiredbooleanfalseWhen true, log() requires tenant context; ambient query()/getById() require context unless an explicit tenantId or allTenants: true scope is provided
excludeRoutesRouteInfo[][]Routes excluded from AuditActorMiddleware
registerGlobalInterceptorbooleantrueSet false to bind AuditInterceptor manually
correlationIdHeaderstringx-request-idHeader copied into metadata.correlationId
correlationIdGetter(req) => string | undefinedCustom correlation ID source
tableNamestringaudit_logsAudit table name used by module-side log/query/scan/export/prune APIs
tenantResolver() => string | nullCustom tenant lookup before the optional @nestarc/tenancy fallback
onAuditError(error, ctx) => voidStructured audit failure callback
loggerAuditLoggerWarning/error logger compatible with console and NestJS LoggerService
sensitiveFieldsstring[][]Metadata keys redacted recursively in objects and arrays for manual logs
sensitiveFieldsByModelRecord<string, string[]>{}Model-specific metadata redaction keys
prismaModulegenerated Prisma modulelegacy @prisma/client fallbackRequired with the Prisma 7 prisma-client generator; pass { Prisma } from the generated output

Sensitive-key redaction traverses manual-log metadata recursively through nested objects and arrays. Global sensitiveFields and model-specific keys selected from sensitiveFieldsByModel by targetType are combined before storage. ManualAuditLogInput does not accept changes; automatic tracking populates AuditEntry.changes, while custom business context belongs in metadata.

Reason Metadata

Use @AuditReason() when a handler needs to attach a human-readable reason to entries emitted during the request:

typescript
@Patch(':id/role')
@AuditAction('user.role.changed')
@AuditReason('admin role update')
async updateRole() {
  // automatic tracking and manual logs can read the request audit reason
}

Released under the MIT License.