# @suaveplan/api-audit-file — audit sink writing JSON-per-line, HMAC-SHA-256 signed records to a rotated file. Size + time rotation, maxFiles retention, bounded-queue backpressure with observable drops, append + strict-sync write modes. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`. File-rotating, HMAC-signed audit sink for `@suaveplan/api-host`. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`: writes one JSON line per record with an HMAC-SHA-256 signature, rolls the file on a size OR age trigger, and prunes the oldest rotated siblings to a configurable `maxFiles` retention cap. Suitable for single-host deployments, on-prem environments without a log shipper, and any host that prefers durable local storage of the audit trail. The sibling `@suaveplan/api-audit-stdout` covers the log-shipped use case; both sinks share the wire shape so dashboards union on metric name and partition by the `sink` attribute. ## Documentation tree - [error-codes](./src/error-codes/error-codes.md) — Frozen registry of the six stable `AUDIT_FILE.*` error codes raised by the file-rotating audit sink, plus the concrete… - [error-codes](./src/error-codes/error-codes.md) — Frozen registry of the six stable `AUDIT_FILE.*` error codes raised by the file-rotating audit sink, plus the concrete… - [fs-helpers](./src/fs-helpers/fs-helpers.md) — Isolates the `node:fs` surface the sink touches behind an injectable `FsAdapter` interface and concrete `nodeFsAdapter`… - [fs-helpers](./src/fs-helpers/fs-helpers.md) — Isolates the `node:fs` surface the sink touches behind an injectable `FsAdapter` interface and concrete `nodeFsAdapter`… - [hmac](./src/hmac/hmac.md) — Wraps `@suaveplan/crypto-hash` HMAC-SHA-256 into the two operations the file sink needs: signing a canonical record on… - [hmac](./src/hmac/hmac.md) — Wraps `@suaveplan/crypto-hash` HMAC-SHA-256 into the two operations the file sink needs: signing a canonical record on… - [instruments](./src/instruments/instruments.md) — Constructs the OTel counter bundle the file sink emits and exposes the canonical `sink="file"` attribute set. Every obs… - [instruments](./src/instruments/instruments.md) — Constructs the OTel counter bundle the file sink emits and exposes the canonical `sink="file"` attribute set. Every obs… - [retention](./src/retention/retention.md) — Enforces the `maxFiles` retention dimension of the rotation policy by deleting the oldest rotated files until at most `… - [retention](./src/retention/retention.md) — Enforces the `maxFiles` retention dimension of the rotation policy by deleting the oldest rotated files until at most `… - [rotation](./src/rotation/rotation.md) — Resolves the rotation policy carried by every `createFileAuditSink` instance and implements the rotation primitive itse… - [rotation](./src/rotation/rotation.md) — Resolves the rotation policy carried by every `createFileAuditSink` instance and implements the rotation primitive itse… - [schema](./src/schema/schema.md) — Defines the Zod schema and canonical-bytes function that bracket every audit record before it is signed and written. Th… - [schema](./src/schema/schema.md) — Defines the Zod schema and canonical-bytes function that bracket every audit record before it is signed and written. Th… - [sink](./src/sink/sink.md) — The public entry point of `@suaveplan/api-audit-file`. The `createFileAuditSink` factory composes the schema, hmac, rot… - [sink](./src/sink/sink.md) — The public entry point of `@suaveplan/api-audit-file`. The `createFileAuditSink` factory composes the schema, hmac, rot… ## Install ```bash bun add @suaveplan/api-audit-file ``` ## Quickstart ```ts import { createFileAuditSink } from "@suaveplan/api-audit-file/sink"; const sink = await createFileAuditSink({ path: "/var/log/suaveplan/audit.log", hmacKey: new TextEncoder().encode(process.env.AUDIT_HMAC_KEY ?? ""), rotation: { maxSizeBytes: 100 * 1024 * 1024, maxAgeMs: 86_400_000, maxFiles: 30 }, appendMode: "strict-sync", }); await sink.emit(envelopeFromHostPipeline); await sink.dispose(); ``` ## Modules - `./sink` — `createFileAuditSink`, `FileAuditSink`, `CreateFileAuditSinkOptions`, `AppendMode`. - `./rotation` — `RotationPolicy`, `RotationState`, `resolveRotationPolicy`, `shouldRotate`, `rotate`. - `./retention` — `enforceRetention`. - `./schema` — `AuditRecord`, `AuditRecordSchema`, `canonicalise`, `buildSignedLine`. - `./hmac` — `signRecord`, `verifyRecord`. - `./instruments` — `AuditFileInstruments`, `createAuditFileInstruments`, `SINK_ATTRIBUTE`. - `./fs-helpers` — `FsAdapter`, `nodeFsAdapter`, `listRotatedFiles`, `rotatedFilePathAt`. - `./error-codes` — `AUDIT_FILE_CODES`, `AuditFileError`, `AuditFileCode`. ## Error codes `AUDIT_FILE.INVALID_RECORD`, `AUDIT_FILE.WRITER_FAILED`, `AUDIT_FILE.QUEUE_FULL`, `AUDIT_FILE.ROTATION_FAILED`, `AUDIT_FILE.RETENTION_FAILED`, `AUDIT_FILE.PATH_NOT_WRITEABLE`. ## OTel instruments - `api.audit.records_total{sink="file"}` - `api.audit.dropped_total{sink="file"}` - `api.audit.rotation_evicted_total{sink="file"}` ## Tier Server-tier — depends on `node:fs/promises`.