Skip to content

Audit log: append-only record of who searched, read and wrote what #94

Closed

Description

@waymark-ops

Context

Once Waymark answers other people over the network, an admin must be able to answer "who read this document?", "which token was used from where?" and "who wrote this note?". This issue adds an append-only audit log and a CLI to read it. Producers are added by later issues (#95, #96, epic #19); this issue defines the format, the writer and the admin commands, and logs the account changes from #93.

Part of epic #18. Depends on #93.

Goal

Every security-relevant event is appended as one JSON line to a monthly file under $WAYMARK_HOME/audit/, and waymark audit filters and prints it.

Evidence

Exact decisions

Storage

  • $WAYMARK_HOME/audit/YYYY-MM.jsonl (UTC month), created with 0o600 / directory 0o700 where supported. Append-only: the writer only opens with append; nothing in Waymark rewrites or deletes these files. Retention is the admin's job (documented).
  • One event = one line of JSON, written synchronously enough that an event logged before a response is on disk before the response is sent (a crash may lose at most the line being written).

Event shape

{ "at": "2026-11-01T12:00:00.000Z", "event": "search", "outcome": "ok", "user": "alan", "tokenId": "tok_1a2b3c4d", "via": "mcp-http", "ip": "10.0.0.5", "object": null, "detail": { "query": "why sqlite", "results": 7 } }
  • event (closed list, extended by later issues): auth.denied, user.created, user.updated, user.linked, user.unlinked, token.created, token.revoked, search, document.read, note.saved, handoff.created, handoff.claimed, session.saved, bot.ask.
  • outcome: ok | denied | error. via: cli | mcp-http | api | bot:<platform>. object: doc id or user/token id when relevant.
  • user = Waymark user name or owner for local CLI actions; ip only for network requests.
  • detail: event-specific, small. Search query text is logged only when config audit.queries is true (default false); otherwise detail.queryChars (length) is logged instead. Never tokens, hashes, request bodies or document text. All strings pass through redact() and control characters are escaped (log injection).
  • auth.denied detail: reason (missing | invalid | expired | revoked | disabled | forbidden) and the token id when known; never the presented token.

Who logs in this issue

The #93 CLI commands (user …, token …) log their events with via: cli, user: owner. Read/write events over the network are added by #95/#96; local CLI search/show are not logged (owner reading their own files).

waymark audit

waymark audit [--since <ISO or Nd>] [--until <ISO>] [--user <name>] [--event <e>]... [--outcome ok|denied|error] [--limit <n, default 100>] [--json]

  • Reads only the monthly files overlapping the range, newest first.
  • Text line: 2026-11-01 12:00:00Z search ok alan mcp-http 10.0.0.5 "why sqlite" (7 results) (one compact summary per event type; unknown types print detail as JSON).
  • --json prints matching events as JSON Lines.
  • Malformed lines are skipped with one stderr warning per file.

Docs

docs/server.md "Audit log": location, fields, privacy switch audit.queries, retention advice, example jq queries.

Acceptance criteria

  • Writing events produces valid JSONL in the right monthly file (fixed clock in tests across a month boundary).
  • audit.queries: false → no query text in the file, only its length; true → redacted query text.
  • A token-like string or control characters in a detail field are redacted/escaped (test).
  • ADR-0003 team server model + users, groups, linked identities and API tokens #93 commands emit their events.
  • waymark audit filters by since/user/event/outcome and limit; text and JSON formats tested.
  • npm run check passes.

Out of scope

Shipping logs to SIEM/syslog (users can tail the files), tamper-evidence (hash chains), log rotation by size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: permissionsAccess control and auth, API keys, auditenhancementNew feature or requestsecuritySecurity-related

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions