Skip to main content
Halite writes an audit log entry for every significant action — logins, permission checks, key operations, job runs, settings changes, and more. The log is stored in the database and queryable through both the UI and the API.

What is recorded

Each entry in the audit_log table captures the following fields (from audit/models.py):

Sensitive field redaction

args_json is automatically redacted before being written. Any key whose name matches a known sensitive identifier has its value replaced with [REDACTED]. The redacted keys include: password, passwd, pw, secret, token, api_key, apikey, authorization, new_password, and current_password.

When entries are written

The audit/writer.py record() function is called by route handlers at the point of the authorization decision or action outcome. Because it is called explicitly rather than via middleware, coverage is intentional — every route that calls record() is audited. Examples of audited actions:
  • Login (auth.login) — written on both successful and failed login attempts. Failed attempts have decision = "deny" and user_id = null.
  • Change password (auth.change_password) — written on both success and failure.
  • Any other action where a route handler explicitly calls audit_record(...).

Auditing reads

By default, read-only requests (e.g. listing minions or jobs) are not written to the audit log. A reserved AUDIT_AUDIT_READS setting exists (default false) but is not currently wired into request handling.

Querying the log

The audit log is available at GET /api/audit. Access requires the view:audit:* permission, which only the admin role holds by default (see RBAC & Permissions).

Query parameters

Results are always ordered newest-first (at descending). The response includes a total count (across all matching rows, not just the current page) alongside the entries array.

Example response shape