@nestbolt/audit-log
Configuration
Configure @nestbolt/audit-log module options including actor resolution, disabled actions, excluded fields, and metadata.
The AuditLogModule provides two registration methods: forRoot() for static configuration and forRootAsync() for configuration that depends on other providers (such as ConfigService). The module is registered globally, so you only need to import it once in your root module.
forRoot (Static Configuration)
Use forRoot() when all configuration values are known at compile time:
import { AuditLogModule } from "@nestbolt/audit-log";
import { RequestActorResolver } from "./audit/request-actor.resolver";
@Module({
imports: [
AuditLogModule.forRoot({
defaultActor: { type: "System", id: "system" },
actorResolver: RequestActorResolver,
disabledActions: ["deleted"],
globalExcludedFields: ["password", "passwordHash", "token", "secret", "refreshToken"],
metadata: { app: "my-app", version: "1.0.0" },
}),
],
})
export class AppModule {}forRootAsync (Async Configuration)
Use forRootAsync() when configuration values need to be resolved from other providers at runtime:
import { AuditLogModule } from "@nestbolt/audit-log";
import { ConfigModule, ConfigService } from "@nestjs/config";
@Module({
imports: [
AuditLogModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
defaultActor: {
type: "System",
id: config.get<string>("APP_NAME", "unknown"),
},
globalExcludedFields: config
.get<string>("AUDIT_EXCLUDED_FIELDS", "password,token")
.split(","),
metadata: {
app: config.get<string>("APP_NAME"),
environment: config.get<string>("NODE_ENV"),
},
}),
}),
],
})
export class AppModule {}The forRootAsync method accepts the following options:
| Property | Type | Description |
|---|---|---|
imports | any[] | Modules to import (makes their providers available to useFactory) |
inject | any[] | Providers to inject into useFactory |
useFactory | (...args: any[]) => AuditLogModuleOptions | Promise<AuditLogModuleOptions> | Factory function that returns the module options |
When using forRootAsync with an actorResolver, the module automatically instantiates the resolver class using NestJS's ModuleRef.create(), so the resolver can have its own injected dependencies.
Configuration Options Reference
All options are optional. Calling AuditLogModule.forRoot() with no arguments uses the defaults.
defaultActor
defaultActor?: { type: string; id: string }Sets a fallback actor when no actorResolver is configured, or when the resolver returns null. This is useful for background jobs, seeders, or CLI commands where there is no authenticated user.
AuditLogModule.forRoot({
defaultActor: { type: "System", id: "system" },
});With this configuration, all audit log entries that cannot resolve an actor will have actorType: "System" and actorId: "system".
If neither defaultActor nor actorResolver is set, the actor_type and actor_id columns will be null.
actorResolver
actorResolver?: Type<ActorResolver>A class that implements the ActorResolver interface. The module instantiates this class as a NestJS provider, so it can inject other services (such as a request-scoped context service).
AuditLogModule.forRoot({
actorResolver: RequestActorResolver,
});The resolver is called automatically for both subscriber-based (automatic) and manual logging when no explicit actor is provided to AuditLogService.log(). See Actor Resolution for full details.
disabledActions
disabledActions?: AuditAction[] // "created" | "updated" | "deleted"Globally disable specific audit actions. When an action is disabled, the subscriber will skip it for all entities, regardless of their individual @Auditable() configuration.
// Only track creates and updates; skip deletes globally
AuditLogModule.forRoot({
disabledActions: ["deleted"],
});// Only track updates (skip creates and deletes)
AuditLogModule.forRoot({
disabledActions: ["created", "deleted"],
});This option applies only to the automatic subscriber. Manual logging via AuditLogService.log() is not affected by disabledActions.
globalExcludedFields
globalExcludedFields?: string[]Fields to exclude from audit log diffs across all entities. This is applied in addition to any per-entity except list and the always-excluded fields (id, createdAt, updatedAt, created_at, updated_at).
AuditLogModule.forRoot({
globalExcludedFields: ["password", "passwordHash", "token", "secret", "refreshToken", "apiKey"],
});Use this for sensitive fields that should never appear in audit logs, regardless of which entity they belong to.
metadata
metadata?: Record<string, any>Extra metadata attached to every audit log entry. This is stored in the metadata JSON column and can be used to record application-level context such as the application name, version, or deployment environment.
AuditLogModule.forRoot({
metadata: {
app: "billing-service",
version: "2.3.1",
environment: "production",
},
});When a manual audit log entry provides its own metadata, the manual metadata is used instead of the global metadata (it does not merge).
Full Configuration Example
Here is a complete example combining all options with async configuration:
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { EventEmitterModule } from "@nestjs/event-emitter";
import { AuditLogModule } from "@nestbolt/audit-log";
import { RequestActorResolver } from "./audit/request-actor.resolver";
@Module({
imports: [
ConfigModule.forRoot(),
EventEmitterModule.forRoot(),
TypeOrmModule.forRoot({
type: "postgres",
host: "localhost",
port: 5432,
database: "myapp",
autoLoadEntities: true,
}),
AuditLogModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
defaultActor: { type: "System", id: "system" },
actorResolver: RequestActorResolver,
disabledActions:
config.get<string>("NODE_ENV") === "test" ? ["created", "updated", "deleted"] : [],
globalExcludedFields: ["password", "passwordHash", "token", "secret"],
metadata: {
app: config.get<string>("APP_NAME", "my-app"),
environment: config.get<string>("NODE_ENV", "development"),
},
}),
}),
],
})
export class AppModule {}In this example, audit logging is completely disabled in the test environment by disabling all three actions.
Configuration Precedence
Field exclusion is applied in layers. A field is excluded from audit diffs if it matches any of the following:
- Always excluded --
id,createdAt,updatedAt,created_at,updated_atare always excluded and cannot be tracked. - Global exclusion -- fields listed in
globalExcludedFieldsare excluded from all entities. - Per-entity exclusion -- fields listed in the
exceptoption of@Auditable()are excluded from that specific entity. - Per-entity whitelist -- if the
onlyoption is set on@Auditable(), only those fields are tracked, andexceptis still applied on top.
Action filtering also has a precedence order:
- Module-level -- if an action is in
disabledActions, it is skipped globally. - Entity-level -- if
eventsis set on@Auditable(), only listed actions are tracked for that entity.
Both conditions must pass for an action to be logged.
Next Steps
- Auditable Entities -- configure per-entity tracking with the
@Auditable()decorator. - Actor Resolution -- implement a custom actor resolver.