Audit trail
session.store_backend is the session's SQLite store. The methods below
read its audit rows and its flattened instance table. They are
documented but internal (see API stability): the words
in the rows are frozen, and these methods that return them may change in
a 1.x release. What each action_type means is on
Analytics & Reporting.
SqliteStore
The session's SQLite store and pixel sidecar: session.store_backend.
It holds the Patient -> Study -> Series -> Instance hierarchy, the
append-only <name>_pixels.bin sidecar, and the audit log, which a
background thread writes.
get_audit_summary()
Returns an aggregated summary of actions from the audit log.
Reads through the flush_audit_queue barrier, so every row enqueued
before the call is counted.
Returns:
| Type | Description |
|---|---|
Dict[str, int]
|
e.g., {'REMEDIATION_REPLACE': 1200, 'EXPORT': 1} |
get_audit_errors()
Every ERROR and WARNING audit row, oldest first.
Flushes the audit queue first, so every row enqueued before the call is included.
Returns:
| Type | Description |
|---|---|
List[tuple]
|
|
get_audit_losses()
Retrieves every DATA_LOSS entry, with the scope it was
recorded under.
Separate from get_audit_errors because the scopes grade differently:
a loss scoped PRIVATE or SIGNAL takes validation_status to
REVIEW_REQUIRED; one scoped STANDARD leaves it at PASS. Every
loss is reported under "3.1 Data Loss", never under "Exceptions &
Errors".
A row whose loss_scope is NULL predates the column and cannot be
graded; it is reported and left at PASS.
Returns:
| Type | Description |
|---|---|
List[tuple]
|
(timestamp, entity_uid, details, loss_scope) |
get_audit_declines()
Every REMEDIATION_DECLINED entry: a value the sweep left behind.
A scan gap says an element could not be read; this says an element was
read, a remediation was proposed for it, and the remediation did not
run, so the value is still in the graph and will reach the exported
file. The reason is in details.
Flushes first, like every other audit reader, so a row still in the queue is counted.
Returns:
| Type | Description |
|---|---|
List[tuple]
|
(timestamp, entity_uid, details) |
get_audit_scan_gaps()
Every SCAN_GAP entry: an element the PHI scan could not open.
Separate from get_audit_losses because it is a different claim. A loss
says an element was dropped at ingest and cannot reach the output; this
says an element was kept whole and the scan could not read what is
inside it.
The row states ingest-time knowledge only. Whether the element reaches
the exported file is decided later, by remove_private_tags, and
generate_report resolves that against the object graph.
No loss_scope column: only an odd-group tag reaches the parse gate,
so these are private by construction. element_tag is selected
instead, and is NULL for a row written before that column existed.
Returns:
| Type | Description |
|---|---|
List[tuple]
|
(timestamp, entity_uid, details, element_tag) |
get_audit_drops()
How many audit rows were dropped by a failed batch write.
The rows themselves are unrecoverable: a failed batch write loses them. A
non-zero count means the audit table under-states what happened, and
generate_report grades it like an exception.
Flushes first, like every other audit reader, so a row still in the queue is counted if its write fails.
Returns:
| Type | Description |
|---|---|
int
|
Rows dropped over this store object's lifetime. |
get_flattened_instances(patient_ids=None, instance_uids=None, page_size=_FLATTENED_PAGE_SIZE)
An iterator of one flat dictionary per stored instance.
For streaming exports or analysis without loading the entire graph into RAM. The rows come back one page at a time, and no database handle is held between pages, so an iterator left part-consumed holds no lock and no read snapshot. Two consequences:
- Iteration is not one snapshot. Each page is its own query, so writes that land between pages are visible and rows deleted between pages are not returned.
- Order is by
instances.id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patient_ids
|
Iterable[str]
|
Restrict the rows to
these Patient IDs, read as every |
None
|
instance_uids
|
Iterable[str]
|
Restrict the rows to
these SOP Instance UIDs. Same rules: |
None
|
page_size
|
int
|
Rows per page, defaulting to 500.
Trades resident memory against the number of queries.
Must be an |
_FLATTENED_PAGE_SIZE
|
Returns:
| Type | Description |
|---|---|
Iterator[dict]
|
One dict per instance, keyed |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If either filter is a bare |