AZMARA PLATFORM
Security

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.log

What 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.

On this page