Audit Logging
Every mutation in @azmr/db and every AI fix attempt is written to a tamper-evident audit log.
How the hash chain works
Entry 1: { action: "createTable", prevHash: "", hash: "a3f..." }
Entry 2: { action: "insert", prevHash: "a3f...", hash: "9b2..." }
Entry 3: { action: "insert", prevHash: "9b2...", hash: "c41..." }Modifying entry 2's content changes its hash. Entry 3's prevHash then no longer matches entry 2's hash — the tamper is immediately detectable by replaying the chain.
Usage
import { createAuditLogger } from "@azmr/security";
const audit = createAuditLogger("payments");
audit.log("payment:processed", { orderId: "abc123", amount: 99.99 });
audit.log("payment:refunded", { orderId: "abc123" });Log format
Each line is a JSON object:
{
"timestamp": "2026-04-08T00:00:00.000Z",
"context": "payments",
"action": "payment:processed",
"meta": { "orderId": "abc123", "amount": 99.99 },
"prevHash": "a3f2c1...",
"hash": "9b2d44..."
}Concurrency and restarts
Every createAuditLogger() call targeting the same resolved log path — including one from a different package, or one created after a process restart — shares one hash chain. On creation, the logger seeds itself from the last valid entry already on disk, rather than starting a fresh chain at prevHash: "". This means two loggers (e.g. @azmr/db and @azmr/ai, both writing to the default .azmara/audit.log) interleave into a single valid chain instead of each producing false "chain broken" reports.
Single writer process per log file
This module assumes one writer process per log file — there is no file locking. Two separate OS processes appending to the same path concurrently can still interleave writes and desync their chains. If multiple processes must write to the same audit log, route them through one process rather than writing directly from each.
log() appends synchronously (fs.appendFileSync), so each call blocks the event loop until the write completes — a deliberate trade of throughput for simple, easy-to-reason-about ordering.
Log location
Default: .azmara/audit.log
Override:
AZMARA_AUDIT_LOG=/var/log/azmara/audit.logWhat NOT to log
Never log these
- Passwords or password hashes
- API keys or tokens
- Full PII (name + email + address combined)
- Session tokens or JWTs
These never belong in meta — log identifiers (user ID, order ID) instead.