86 lines
5.2 KiB
Markdown
86 lines
5.2 KiB
Markdown
# @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.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## 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…
|
|
<!-- end:auto-docs -->
|
|
|
|
## 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`.
|
|
|