audit-logger: a module that records every event on the mesh
The universal consumer from ADR 0046 — no privilege, just a module that
consumes '#' and writes each event to an append-only trail. Its whole code
is on('#', record); the manifest declares consumes:['#'] and a log dir.
Records module.*, mesh.* and node.* events alike (ADR 0047's namespace).
Type-checks against @novox/mesh-sdk; the handler test records a module
event and a node event with their metadata; the manifest parses against
the consumes-enabled schema.
Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
// The audit handler — appends one line per event to an append-only audit log. It is the whole of
|
||||
// the module's code: an audit logger is not a privileged component, only a module that listens to
|
||||
// everything and writes it down (novox/hq ADR 0046).
|
||||
|
||||
import { appendFile, mkdir } from "node:fs/promises";
|
||||
import { dirname } from "node:path";
|
||||
import type { Event } from "@novox/mesh-sdk/events";
|
||||
|
||||
/** Where the trail is written. A directory the host applies; one file per node. */
|
||||
export function auditLogPath(env: NodeJS.ProcessEnv = process.env): string {
|
||||
return env.AUDIT_LOG ?? "/var/lib/audit-logger/audit.log";
|
||||
}
|
||||
|
||||
/** Append an event to the trail as one JSON line, keeping the metadata an audit needs first. */
|
||||
export async function record(event: Event, path: string): Promise<void> {
|
||||
const line =
|
||||
JSON.stringify({
|
||||
id: event.type + "@" + event.at, // a stable-ish key until x-event-id headers land (ADR 0047)
|
||||
type: event.type,
|
||||
source: event.source,
|
||||
node: event.node,
|
||||
at: event.at,
|
||||
body: event.body,
|
||||
}) + "\n";
|
||||
await mkdir(dirname(path), { recursive: true }).catch(() => {});
|
||||
await appendFile(path, line, { mode: 0o600 });
|
||||
}
|
||||
Reference in New Issue
Block a user