Every command that reaches a jaque process is written to a second, append-only log before it is forwarded or refused: who sent it, what it was, and whether it was accepted. This page states what is recorded, where it goes, and what a refused write looks like.

1. What is recorded

One line per command that reaches the process: the time, the source (api for a command submitted over the command API, extcmd for one read off the external command FIFO), who sent it (name and role, when the API authenticated the caller), the peer address, the RPC or verb invoked, the command itself as JSON, and whether it was accepted or rejected, with the reason when it was rejected.

A caller refused before the command is even parsed -- a bad token, a role that cannot issue it -- is recorded too, with no command body to show for it. Passive check results are not commands: they carry no sender's intent to act, only an observation, and they are not recorded here.

2. Where it goes

-audit memory, the default, keeps the last 1024 records in process memory: a ring buffer, lost on restart.

-audit file:///var/lib/jaque/audit writes one JSON line per record to files under that directory, rotated at 64 MB; rotated files older than -audit-retention (default 90 days) are removed.

Either way the trail is per process. It is never replayed into state and never folded into a projection -- it answers "who did this", not "what is true now".

3. Reading it back

The trail is served back over the API, not read from disk or memory directly: AdminService.ListAuditRecords returns records newest first to admin identities, the same role gate the rest of AdminService uses. See Admin service for the request and response shape. The file backend serves from whatever files it has still retained; the memory backend serves from its ring, so a restart still loses the same records the ring always lost.

4. A sample line

{"at":"2026-09-07T10:32:11Z","source":"api","principal":{"name":"jdoe","role":"operator"},"peer":"10.0.4.12:53214","rpc":"/jaque.v1.CommandService/AcknowledgeProblem","command":{"Target":{"object":"web-01/http"},"Sticky":false,"Author":"jdoe","Comment":"investigating"},"outcome":"accepted"}

5. When it cannot write

An audit record that cannot be written refuses the command it would have recorded: the caller gets UNAVAILABLE back with the message "audit log unavailable", and jaque_audit_write_errors_total climbs. A full disk under -audit file://... shows up this way on purpose -- a command nobody can prove was issued is worse than a command temporarily refused.

6. Security considerations

The audit file is the record of who did what: it carries the peer address and the caller's name for every command issued against this process. Own the directory to the service user, set its mode to 0750, and ship it to wherever the rest of the process's logs go.