@hazeljs/audit
v1.0.6
Published
Audit logging and event trail for HazelJS applications
Maintainers
Readme
@hazeljs/audit
Audit logging and event trail for HazelJS. Record who did what, when, and with what outcome.
Compliance-ready audit events from HTTP requests and custom business logic. Console, file, or Kafka. Redact secrets, add actors from context, and plug in your own transports.
Features
- HTTP audit —
AuditInterceptorlogs every request (method, path, result) - Custom events — Inject
AuditServiceand calllog()with action, resource, actor - Transports — Console (default), file (JSONL with rotation), Kafka (JSON or Avro)
- @Audit decorator — Mark handlers with action/resource for metadata and tooling
- Redaction — Sensitive keys (password, token, etc.) redacted by default
- Actor from context —
actorFromContext()maps request user to audit actor
Installation
npm install @hazeljs/audit @hazeljs/coreQuick Start
1. Register the module
import { HazelModule } from '@hazeljs/core';
import { AuditModule } from '@hazeljs/audit';
@HazelModule({
imports: [AuditModule.forRoot()],
})
export class AppModule {}With the module registered, use AuditInterceptor to log every HTTP request, or inject AuditService and call log() for custom events.
2. Module options
AuditModule.forRoot({
transports: [new ConsoleAuditTransport()], // default
includeRequestContext: true,
redactKeys: ['password', 'token', 'secret', 'authorization'],
});3. Custom events with AuditService
import { Injectable } from '@hazeljs/core';
import { AuditService } from '@hazeljs/audit';
import type { RequestContext } from '@hazeljs/core';
@Injectable()
export class OrderService {
constructor(private readonly audit: AuditService) {}
async create(data: CreateOrderDto, context: RequestContext) {
const order = await this.repo.create(data);
this.audit.log({
action: 'order.create',
actor: this.audit.actorFromContext(context),
resource: 'Order',
resourceId: order.id,
result: 'success',
metadata: { amount: order.total },
});
return order;
}
}Audit event shape
- action — e.g.
user.login,order.create - actor —
{ id, username?, role? }from request context when available - resource / resourceId — what was affected
- result —
success|failure|denied - timestamp — ISO string (set automatically if omitted)
- method / path — from HTTP context when using the interceptor
- metadata — extra structured data (sensitive keys redacted by default)
Transports
Console (default)
Writes one JSON line per event to stdout.
import { ConsoleAuditTransport } from '@hazeljs/audit';
transports: [new ConsoleAuditTransport()],File (JSONL)
Appends to a file. Creates the file and parent dir on first event. Supports rotation by size or by day.
import { FileAuditTransport } from '@hazeljs/audit';
transports: [
new FileAuditTransport({
filePath: 'logs/audit.jsonl',
ensureDir: true,
maxSizeBytes: 10 * 1024 * 1024, // 10MB
rollDaily: true, // audit.2025-03-01.jsonl
}),
],Kafka
Sends each event to a Kafka topic. Use with @hazeljs/kafka: pass KafkaProducerService as the sender. Optional key for partitioning; optional serialize for custom format (default JSON). For Avro, pass a serialize function that returns a Buffer (e.g. using avsc or Confluent Schema Registry).
import { KafkaAuditTransport } from '@hazeljs/audit';
import { KafkaProducerService } from '@hazeljs/kafka';
const transport = new KafkaAuditTransport({
sender: kafkaProducerService, // from your app's container
topic: 'audit',
key: (e) => e.actor?.id?.toString(), // optional partition key
// serialize: (e) => avroType.toBuffer(e), // optional Avro
});Custom transport
Implement AuditTransport (interface with log(event: AuditEvent)) to send events to your database, SIEM, or logging service.
@Audit decorator
Mark handlers with custom action/resource for metadata and tooling:
import { Controller, Post, Body } from '@hazeljs/core';
import { Audit } from '@hazeljs/audit';
@Controller('/orders')
export class OrderController {
@Post()
@Audit({ action: 'order.create', resource: 'Order' })
async create(@Body() dto: CreateOrderDto) {
return this.orderService.create(dto);
}
}License
Apache 2.0 © HazelJS
