Files
skills/docs/api-stack/api/api-host/src/admin-api/audit-sink.md
2026-05-29 08:20:56 +01:00

2.4 KiB

audit-sink.ts

Purpose

MemoryAdminAuditSink is the in-memory default audit sink for the host's admin API. Every admin endpoint emits a structured AdminAuditRecord after the request settles — the sink decides what to do with it. The in-memory sink records into a local array suitable for tests + dev; production deployments swap in a sink that forwards to @suaveplan/audit-logging, syslog, or a managed audit pipeline.

The sink interface is intentionally narrow (emit(record)) so the admin API never depends on a specific audit backend. The AdminAuditRecord shape carries the principal id, action, optional plugin name, request params, outcome (success / failure), and the failure cause when applicable.

Features

  • Zero-dependency in-memory recorder.
  • snapshot() reads without clearing — useful for asserting state across multiple admin calls.
  • drain() reads + clears in one atomic step.
  • Implements the public AdminAuditSink interface so it composes with the admin API's mounting helper.

Usage: Basic

import { MemoryAdminAuditSink } from "@suaveplan/api-host/admin-api";

const sink = new MemoryAdminAuditSink();
sink.emit({
    at: new Date().toISOString(),
    principal: { id: "alice", scopes: ["host:admin"] },
    action: "plugin.start",
    plugin: "@acme/billing",
    params: {},
    outcome: "success",
});
console.log(sink.snapshot().length); // 1

Usage: Advanced

// In an integration test — drain between scenarios.
const sink = new MemoryAdminAuditSink();
// ... hit admin endpoint ...
const first = sink.drain();
// ... hit admin endpoint again ...
const second = sink.drain();

API Reference

  • new MemoryAdminAuditSink() — zero-arg ctor.
  • emit(record) — append to the in-memory log.
  • snapshot(): readonly AdminAuditRecord[] — copy without clearing.
  • drain(): readonly AdminAuditRecord[] — copy + clear.

Implementation Notes

emit is synchronous for the in-memory case — the admin API treats the return value as Promise<void> | void so an async sink (HTTP POST, IPC) plugs in identically. A failed emit raises ADMIN.AUDIT_EMIT_FAILED on the request boundary — the admin call is still considered a success because the side effect already occurred, but the audit failure is logged.

The sink never persists past process exit. Production sinks MUST ship audit records to durable storage before acknowledging the emit; otherwise tamper-evidence is impossible to assert.