@suaveplan/api-plugin-audit - Hono plugin wrapping @suaveplan/audit-logging as a write-through audit trail for @suaveplan/api. Installs a global middleware recording method/path/status/duration/response-size/request-id/principal-id/tenant-id per request, exposes auditService in ServiceRegistry, and surfaces c.get("audit") for handler-level events. Configurable redaction, sampling, and exclusion. Sink is caller-supplied (any AuditStorageAdapter); default is in-memory for dev. Server-tier — Bun + Node.
Hono plugin that wraps @suaveplan/audit-logging as a write-through audit trail for @suaveplan/api. Installs a global per-request audit middleware (method / path / status / duration / response size / request id / principal id / tenant id), exposes auditService in the host ServiceRegistry, and surfaces c.get("audit") for handler-level semantic events. Sink is caller-supplied; default is an in-memory adapter for development.
Documentation tree
- audit-context — Builds the per-request
AuditContexthandle the audit middleware attaches toc.set("audit", context)before invoking… - context-augmentation — TypeScript module augmentation that adds the
audit: AuditContextslot to Hono'sContextVariableMap. Without it, `c.… - error-codes — Defines the stable error-code registry for
@suaveplan/api-plugin-auditand the concreteAuditPluginErrorclass used…- error-codes — Defines the stable error-code registry for
@suaveplan/api-plugin-auditand the concreteAuditPluginErrorclass used…
- error-codes — Defines the stable error-code registry for
- middleware — Builds the global Hono middleware that records one audit event per non-excluded request through the underlying `AuditLo…
- audit-middleware — Builds the global Hono middleware that records one audit event per non-excluded request through the underlying `AuditLo…
- otel — Owns the OpenTelemetry instrument bundle the audit plugin emits to every request lifecycle. Resolving the instruments l…
- instruments — Owns the OpenTelemetry instrument bundle the audit plugin emits to every request lifecycle. Resolving the instruments l…
- plugin — Top-level factory for the audit plugin.
createAuditPlugin(options)Zod-validates the caller's options at the boundary…- plugin — Top-level factory for the audit plugin.
createAuditPlugin(options)Zod-validates the caller's options at the boundary…
- plugin — Top-level factory for the audit plugin.
- redact — Lightweight, allocation-free-ish payload redactor used by the audit middleware to scrub secret-bearing fields from per-…
- redact — Lightweight, allocation-free-ish payload redactor used by the audit middleware to scrub secret-bearing fields from per-…
- schemas — Zod schema that validates
AuditPluginOptionsat thecreateAuditPluginfactory boundary and produces the resolved `A…- options — Zod schema that validates
AuditPluginOptionsat thecreateAuditPluginfactory boundary and produces the resolved `A…
- options — Zod schema that validates
- audit-service — Constructs the
AuditServiceadapter the plugin registers inServiceRegistryunder theauditServiceslot. The adap… - registry-augmentation — Declares the
auditServiceslot on@suaveplan/api-plugin/service-registry'sServiceRegistryinterface via TypeScri… - types — Central, runtime-free declaration of the interfaces the plugin's lifecycle, middleware, services, and context helpers d…
- types — Central, runtime-free declaration of the interfaces the plugin's lifecycle, middleware, services, and context helpers d…
Install
bun add @suaveplan/api-plugin-audit
Quick start
import { MemoryAuditAdapter } from "@suaveplan/audit-logging";
import { createAuditPlugin } from "@suaveplan/api-plugin-audit";
const plugin = createAuditPlugin({
sink: new MemoryAuditAdapter(),
secretKey: process.env.AUDIT_SECRET_KEY,
samplingRate: 1, // record every request
excludePaths: ["/health", "/openapi.json"],
});
// Register on your @suaveplan/api PluginRegistry alongside auth/tenant/etc.
Inside a route handler:
app.post("/users/:id/delete", async (c) => {
const audit = c.get("audit");
await audit.log({
type: "user.deleted",
severity: "warning",
actor: { userId: c.get("user")?.id },
target: { type: "user", id: c.req.param("id") },
});
return c.json({ ok: true });
});
Modules
- plugin/plugin —
createAuditPluginfactory. - middleware/audit-middleware — per-request middleware.
- services/audit-service —
auditServiceadapter. - services/registry-augmentation —
ServiceRegistryslot. - context/audit-context — handler-level
c.get("audit"). - context/context-augmentation — Hono
ContextVariableMapslot. - redact/redact — payload redactor.
- otel/instruments — OpenTelemetry counters + histogram.
- schemas/options — Zod options schema + defaults.
- error-codes/error-codes —
AUDIT_PLUGIN_*registry.
Features
- One audit event per non-excluded request, recorded through the underlying
AuditLogger(chain-integrity, GDPR export, retention all inherited). - Configurable redaction (case-insensitive headers, exact query / body field names).
- Head-end sampling gate with caller-supplied (or default
Math.random) RNG. - Excluded paths skip recording but still install the
auditcontext slot. - Middleware NEVER throws into the request response — sink failures are logged at warn and counted via
audit.sink_failures_total. auditServiceregistered withctx.registerService("auditService", ...)and exposed through the typedServiceRegistryslot.- Hono
ContextVariableMapaugmented withaudit: AuditContextso handlers fire explicit events without import boilerplate. - Four OpenTelemetry instruments:
audit.requests_recorded_total{outcome,sampled},audit.requests_excluded_total,audit.sink_failures_total,audit.middleware_duration_ms.