3.1 KiB
services/audit-service
Purpose
Constructs the AuditService adapter the plugin registers in ServiceRegistry under the auditService slot. The adapter wraps a constructed AuditLogger from @suaveplan/audit-logging so downstream code depends on the stable interface declared in ../types/types.ts instead of binding to whatever the universal library exposes today. If the library renames or removes a method later, only this adapter file changes.
The wrapper is intentionally thin — every method delegates to the underlying logger one-for-one — but it gives the plugin a clean seam to add cross-cutting behaviour (tenancy enforcement, OTel correlation, idempotency) without touching every call site.
Features
- 1:1 proxy over
AuditLogger.log / query / verifyChainIntegrity / exportGDPRData / applyRetentionPolicy. getLogger()escape hatch for callers that need direct access (the underlying logger exposes operations not in the stable surface, e.g. event-bus introspection).- Constructor takes a plain
{ logger }dependency bundle — easy to swap or stub at test time.
Usage: Basic
import { AuditLogger, MemoryAuditAdapter } from "@suaveplan/audit-logging";
import { createAuditService } from "@suaveplan/api-plugin-audit/services/audit-service";
const logger = new AuditLogger({
storage: new MemoryAuditAdapter(),
secretKey: process.env.AUDIT_SECRET_KEY!,
});
const auditService = createAuditService({ logger });
await auditService.log({
type: "user.created",
severity: "info",
actor: { userId: "u1" },
});
Usage: Advanced
import {
AuditLogger,
MemoryAuditAdapter,
type AuditEvent,
} from "@suaveplan/audit-logging";
import { createAuditService } from "@suaveplan/api-plugin-audit/services/audit-service";
const auditService = createAuditService({
logger: new AuditLogger({
storage: new MemoryAuditAdapter(),
secretKey: process.env.AUDIT_SECRET_KEY!,
enableChainIntegrity: true,
}),
});
const events: AuditEvent[] = await auditService.query({
userId: "u1",
limit: 50,
order: "desc",
});
const verdict = await auditService.verifyChainIntegrity(events);
if (!verdict.valid) {
console.error("chain broken at", verdict.brokenAt, verdict.reason);
}
API Reference
createAuditService(deps: { logger: AuditLogger }): AuditService- Returns an object satisfying the
AuditServiceinterface from../types/types.ts. - Methods:
getLogger(),log(event),query(opts),verifyChainIntegrity(events),exportGDPRData(userId, signal?),applyRetentionPolicy(signal?).
- Returns an object satisfying the
Implementation Notes
Every method returns the underlying Promise directly — no wrapping, no try/catch — because the plugin's middleware path handles sink failures explicitly via audit.sink_failures_total. Consumers that call auditService.log(...) from a handler get the raw AuditError from @suaveplan/audit-logging and can branch on its codes. This separation keeps the middleware (which must never throw into the request response) and the handler-level helper (which can surface failures) consistent.