Files
2026-05-27 23:29:53 +01:00

89 lines
6.7 KiB
Markdown

# @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.
<!-- begin:auto-docs -->
## Documentation tree
- [audit-context](./src/context/audit-context.md) — Builds the per-request `AuditContext` handle the audit middleware attaches to `c.set("audit", context)` before invoking…
- [context-augmentation](./src/context/context-augmentation.md) — TypeScript module augmentation that adds the `audit: AuditContext` slot to Hono's `ContextVariableMap`. Without it, `c.…
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-audit` and the concrete `AuditPluginError` class used…
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-audit` and the concrete `AuditPluginError` class used…
- [middleware](./src/middleware/audit-middleware.md) — Builds the global Hono middleware that records one audit event per non-excluded request through the underlying `AuditLo…
- [audit-middleware](./src/middleware/audit-middleware.md) — Builds the global Hono middleware that records one audit event per non-excluded request through the underlying `AuditLo…
- [otel](./src/otel/instruments.md) — Owns the OpenTelemetry instrument bundle the audit plugin emits to every request lifecycle. Resolving the instruments l…
- [instruments](./src/otel/instruments.md) — Owns the OpenTelemetry instrument bundle the audit plugin emits to every request lifecycle. Resolving the instruments l…
- [plugin](./src/plugin/plugin.md) — Top-level factory for the audit plugin. `createAuditPlugin(options)` Zod-validates the caller's options at the boundary…
- [plugin](./src/plugin/plugin.md) — Top-level factory for the audit plugin. `createAuditPlugin(options)` Zod-validates the caller's options at the boundary…
- [redact](./src/redact/redact.md) — Lightweight, allocation-free-ish payload redactor used by the audit middleware to scrub secret-bearing fields from per-…
- [redact](./src/redact/redact.md) — Lightweight, allocation-free-ish payload redactor used by the audit middleware to scrub secret-bearing fields from per-…
- [schemas](./src/schemas/options.md) — Zod schema that validates `AuditPluginOptions` at the `createAuditPlugin` factory boundary and produces the resolved `A…
- [options](./src/schemas/options.md) — Zod schema that validates `AuditPluginOptions` at the `createAuditPlugin` factory boundary and produces the resolved `A…
- [audit-service](./src/services/audit-service.md) — Constructs the `AuditService` adapter the plugin registers in `ServiceRegistry` under the `auditService` slot. The adap…
- [registry-augmentation](./src/services/registry-augmentation.md) — Declares the `auditService` slot on `@suaveplan/api-plugin/service-registry`'s `ServiceRegistry` interface via TypeScri…
- [types](./src/types/types.md) — Central, runtime-free declaration of the interfaces the plugin's lifecycle, middleware, services, and context helpers d…
- [types](./src/types/types.md) — Central, runtime-free declaration of the interfaces the plugin's lifecycle, middleware, services, and context helpers d…
<!-- end:auto-docs -->
## Install
```bash
bun add @suaveplan/api-plugin-audit
```
## Quick start
```ts
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:
```ts
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](./src/plugin/plugin.md) — `createAuditPlugin` factory.
- [middleware/audit-middleware](./src/middleware/audit-middleware.md) — per-request middleware.
- [services/audit-service](./src/services/audit-service.md) — `auditService` adapter.
- [services/registry-augmentation](./src/services/registry-augmentation.md) — `ServiceRegistry` slot.
- [context/audit-context](./src/context/audit-context.md) — handler-level `c.get("audit")`.
- [context/context-augmentation](./src/context/context-augmentation.md) — Hono `ContextVariableMap` slot.
- [redact/redact](./src/redact/redact.md) — payload redactor.
- [otel/instruments](./src/otel/instruments.md) — OpenTelemetry counters + histogram.
- [schemas/options](./src/schemas/options.md) — Zod options schema + defaults.
- [error-codes/error-codes](./src/error-codes/error-codes.md) — `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 `audit` context slot.
- Middleware NEVER throws into the request response — sink failures are logged at warn and counted via `audit.sink_failures_total`.
- `auditService` registered with `ctx.registerService("auditService", ...)` and exposed through the typed `ServiceRegistry` slot.
- Hono `ContextVariableMap` augmented with `audit: AuditContext` so 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`.