Chuyển tới nội dung chính

Audit log

riverbase_core::logstore records what every command and query did. Writes on the command path are part of the command's transaction, so the audit trail always matches the state.

Channels​

ChannelTable purposeWritten byDefault
contextRequest context: actor, profile, tenant, correlationCommand and query engineson
commandEach command and its terminal statusCommand engineon
eventOne row per successful #[domain_action]Aggregate sessionon
messageIntegration messagesemit_messageon
activityHuman-readable audit entriesemit_activity, reportson
responseThe response returned to the callerCommand engineon
queryQuery executionsQuery engineoff

Idempotency records (idempotency, on by default) and outbox rows are written alongside.

Configuration​

[riverbase.audit_log]
command = true
event = true
message = true
activity = true
response = true
query = false

Each key has an env override: RIVERBASE_AUDIT_LOG_COMMAND, …_EVENT, …_MESSAGE, …_ACTIVITY, …_RESPONSE, …_QUERY, …_CONTEXT. A disabled channel is backed by NoOpLogStore. Turning off idempotency disables response replay for retried requests.

Building the bundle​

DomainRuntime::from_config builds it for you. To build it by hand, for example in a worker:

use riverbase_core::logstore::PostgresDomainLogStore;

let logs = PostgresDomainLogStore::new(pool.clone())
.into_bundle_with_config(&config.audit_log);

DomainLogStore exposes each channel (logs.activities, …) as a LogStore you can append to outside a command. For example, ActivityEmitter records activities from a custom route.

Command status​

A command row starts as Created and moves to a terminal success or error status (CommandLogStatus) when its unit of work completes. A row stuck in Created means the process died mid-command. Nothing else committed with it.

Idempotency​

Clients send an idempotency key with a command. The engine stores the response under that key in the same transaction, and a retry returns the stored response. The response header that echoes the key is configured by resp_header_idempotency in [riverbase.auth].

Outbox​

emit_message writes an OutboxStore row in the command transaction. The publisher started by DomainRuntime::from_config (or by spawn_outbox_publisher) delivers rows to the MessageBus after commit, retrying failures. Delivery is at least once.

Retention​

purge_audit_logs with an AuditRetentionConfig deletes audit rows past their retention window. Run it from a scheduled job; it is never called implicitly.

Where it lives​

On Postgres, the tables are in the riverbase_audit schema and are created by the framework migrations in establish_dbpool.