Files
skills/docs/api-stack/api/api-plugin-audit/src/services/audit-service.md
2026-05-29 08:20:56 +01:00

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 AuditService interface from ../types/types.ts.
    • Methods: getLogger(), log(event), query(opts), verifyChainIntegrity(events), exportGDPRData(userId, signal?), applyRetentionPolicy(signal?).

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.