Audit Journal
The audit journal is the append-only, tamper-evident record of security-relevant actions. It is the answer to "who changed that, and when".
Two design decisions
It lives outside QUBIQ
The journal is written to an external SQL database — PostgreSQL, MySQL or SQL Server — deliberately never the app's own database.
The reason is straightforward: a system that stores its own audit trail can rewrite its own history. Putting the journal in a database QUBIQ merely writes to, under separate administration, removes that possibility.
It is hash-chained
Each record carries the hash of its predecessor. Altering or removing any row breaks every subsequent link, so tampering is detectable even by someone with write access to the database.
The chain starts from a genesis anchor, so a fresh journal begins cleanly and its integrity can be verified from the first record onward.
Configuration
| Action | Where | Permission |
|---|---|---|
| Configure the storage connection | Settings → Audit Log | Manage Audit |
| Read the journal | Settings → Audit Log → Open Audit Log | View Audit Log |
| Verify the chain | Verify integrity, in the Audit Log | View Audit Log |
Manage Audit is super-admin only by default; View Audit Log is available to admins. Being able to read the journal and being able to reconfigure where it goes are deliberately different levels of trust.
Set this up before go-live. Until a storage connection is configured, the interface shows a "configure audit storage" hint rather than an error — events are buffered, but you are not yet retaining them anywhere durable.
Reading the journal Changed in 1.0.7
The Audit Log lists the newest events first. Narrow it with the search box (actor, entity, outcome), Origin and Category; choose 50, 100, 250 or 500 rows per page, and page with the arrows — the double arrow jumps back to the newest events.
Filters search the whole journal. Before 1.0.7 they were applied only to the page already loaded, so narrowing by origin, category or text looked inside the current hundred rows and a record two pages back simply was not found — a dangerous answer from the one place people go to establish what happened. The narrowing is now done by the audit service, across everything stored.
The pager also says where you are. The footer shows the row range (rows 101–200) and end of journal when there is nothing older, so a greyed Next reads as the end rather than as a broken button. Changing page or filter returns the list to its first row, and a page that fails to load says so with Try again, instead of leaving the previous page on screen while the counter moved on.
Durability
Events are published to a durable stream the instant they are emitted, before any database write is attempted. The audit service drains that stream into the external store.
| Condition | Behaviour |
|---|---|
| Storage unavailable | Events stay buffered on the stream; retried |
| Duplicate delivery | Recognised by event ID and treated as success — the journal is idempotent |
| Malformed event | Dropped as permanently bad, rather than wedging the stream |
The consequence: a database outage delays the journal, it does not lose it.
Watch the buffer. New in 1.0.8 That stream is a store-and-forward buffer in all but
name, and the one an auditor most needs to see backing up. It appears in Settings → Store & Forward as Audit Journal, with the same fill, age, drain rate and time-to-full readout as the
other buffers, and raises the same pressure and full alarms. Unlike them it can never be paused or
purged — purging it would destroy audit records, so the actions are refused on the server, not
merely hidden. → Store & Forward
What is recorded
| Category | Examples |
|---|---|
| Authentication | Login success and failure, logout, lockout |
| User administration | Create, edit, role change, activate, deactivate, delete |
| Permission changes | Role-to-permission matrix edits |
| Connection changes | Create, edit, delete, credential changes |
| Namespace changes | Tag and binding changes |
| Alarm operations | Acknowledge, shelve, suppress, restore |
| Configuration | System settings, audit settings, historian designation |
| Backup | Export and restore |
| Privileged operations | Historian ownership claims, service control |
| AI actions | Assistant proposals, approvals and rejections |
Each record carries the actor, the action, the target, the timestamp, the client IP and enough before/after detail to reconstruct the change.
TRUSTED_PROXIESOtherwise every record shows the proxy's address instead of the operator's.
Verifying integrity
Verify integrity in the Audit Log (needs View Audit Log) walks the chain and reports any break — or Chain intact with the number of rows checked. Run it:
- On a schedule, as a control
- Before relying on the journal in an investigation
- After any database maintenance that touched the audit tables
A break tells you the record set has been altered since it was written. It does not tell you by whom — that is what your database's own controls are for.
Attribution and AI
Actions originating from the AI assistant are recorded with both identities: the assistant as the origin, and the human whose proposal it acted on as the actor. An AI-initiated change is never anonymous.
Compliance alignment
The journal is designed against IEC 62443-3-3:
| Requirement | How it is met |
|---|---|
| SR 2.8 — auditable events and record fields | Categories above, with actor, target, timestamp, source |
| SR 2.10 — no loss of audit data | Durable stream buffering before storage |
| SR 2.11 — authoritative timestamps | Server-assigned, not client-supplied |
| SR 2.12 — non-repudiation | Per-actor attribution plus the hash chain |
Sector regulations (FDA 21 CFR Part 11, GxP, and similar) generally require the same properties: attributable, contemporaneous, and protected from alteration.
Operating the journal
Choose the storage database deliberately. Ideally on a different host, under different administration from QUBIQ. That separation is the control.
Retain according to your policy, not by default. Industrial audit retention is often measured in years; the journal grows steadily and predictably.
Back it up separately. It is not part of a QUBIQ configuration backup — deliberately, so that restoring a configuration cannot overwrite the audit history.
Read it periodically. A journal nobody looks at until an incident is a journal whose gaps you discover at the worst moment.
Journal versus execution logs
| Audit journal | Execution / system logs | |
|---|---|---|
| Records | Security-relevant actions | Pipeline runs, diagnostics |
| Storage | External SQL | Internal |
| Tamper-evident | Yes | No |
| Clearable from the interface | No | Yes, with Clear Execution Logs / Clear System Logs |
| Purpose | Accountability | Troubleshooting |
That execution logs can be cleared and the audit journal cannot is the distinction. Clearing logs is itself an audited action.