Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Audit

The IHE ATNA audit trail: [audit] and its three sinks. Precedence, the environment-name grammar, and file discovery are on the Configuration reference index.

[audit]

The IHE ATNA audit trail (see the Audit trail chapter for what a record contains and how to search it). On by default with only the local store active: every deployment gets a queryable audit trail with nothing leaving the node, and forwarding to an external Audit Record Repository is opt-in per sink.

[audit]
enabled = true
source_id = "ferroehr"
value_if_missing = "UNKNOWN"
suppress_login_events = true
fail_mode = "open"
resolve_subject = true
queue_capacity = 8192
purpose_header = "x-purpose-of-use"
purpose_codes = []
KeyTypeDefaultDescription
enabledbooltrueMaster audit switch.
enterprise_site_idstringunsetThe AuditEnterpriseSiteID field.
source_idstringferroehrThe audit source id, also used for the destination participant.
value_if_missingstringUNKNOWNFill value for empty mandatory fields.
suppress_login_eventsbooltrueSkip successful-login records. Rejected accesses (401/403) are always recorded.
fail_modeenum{open,closed}openWhat an undeliverable audit record does. open logs, meters and lets the request succeed; closed rejects auditable operations with 503 (including when the local store has stopped accepting writes) so no PHI access goes un-audited.
resolve_subjectbooltrueEnrich the patient participant with a background lookup of the EHR’s subject. The lookup runs on the background drain, never on the request path; the IHE BALP patient patterns and the patient-centric audit search need the subject.
queue_capacityint8192Bounded audit queue capacity. Sized for write-path bursts: the drain persists in multi-row batches, so the queue only needs to ride out sink latency spikes.
server_hoststringunset ⇒ the value_if_missing fillThis node’s advertised network address, reported as the destination NetworkAccessPointID.
purpose_headerstringx-purpose-of-useThe request header a caller declares its purpose of use in, recorded on every access record. NEN 7513 asks on whose authority a record was read and EHDS Art. 9 asks why; neither is derivable from the request, so the caller declares it. IHE carries the equivalent in a SAML attribute rather than a header, so the header is FerroEHR’s own.
purpose_codeslist of string[]The purpose codes this deployment accepts. Empty records whatever the caller declares. A non-empty list records a declared code only when it is on the list, so an unagreed string does not sit in the trail reading like an established purpose.
legal_basisstringunsetThe legal basis this deployment processes under, recorded on every access record. A deployment-level fact: the controller establishes the GDPR Art. 6/9 condition once. Unset records nothing rather than a guess.

Note

The local store and the ATX:FHIR Feed both carry a FHIR R4 AuditEvent document, so both need the fhir build feature, on in the published binary and container images. A binary built with --no-default-features refuses at startup if audit.store.enabled or audit.fhir_feed.enabled is set; the DICOM/syslog feed needs no FHIR and stays available.

Note

There is no [atna] section. Configuration is strict, so a file or environment variable still setting an [atna] key fails at boot with an unknown-key error; move the setting under [audit].

[audit.store]: the local Audit Record Repository

KeyTypeDefaultDescription
enabledbooltruePersist every record in the audit schema, served through the ITI-81 GET /fhir/r4/AuditEvent search.
retention_daysint0Days to keep records; 0 keeps them forever. Applied hourly by the retention reaper. A non-zero value below the retention floor of a jurisdiction the active [privacy.identifier_scan] rules name is a boot error naming both numbers; see Audit trail.

The local store is the durability anchor of the whole subsystem: with it on, the FHIR feed drains from it, so a down repository loses nothing.

[audit.syslog]: the classic DICOM/syslog feed (ITI-20)

KeyTypeDefaultDescription
enabledboolfalseShip DICOM PS3.15 audit records to an external repository over syslog.
hoststringlocalhostRepository host.
portint514Repository port (514 for UDP, 6514 for TLS, conventionally).
transportenum{udp,tls}udpSyslog transport: RFC 5426 UDP or RFC 5425 TLS. Use tls for PHI-adjacent audit.
tls_ca_filepathunsetPEM file with the repository CA to trust for the TLS transport.
tls_identity_cert_filepathunsetClient-certificate PEM for mutual TLS.
tls_identity_key_filepathunsetClient-key PEM for mutual TLS.

[audit.fhir_feed]: the RESTful-ATNA feed (ITI-20 ATX:FHIR Feed)

KeyTypeDefaultDescription
enabledboolfalsePOST each FHIR AuditEvent to an external FHIR Audit Record Repository.
urlsecret URLhttp://localhost:8080/fhirThe repository’s FHIR base; records go to {url}/AuditEvent. Credentials embedded in the URL are redacted from every rendering.
batch_sizeint64Outbox rows shipped per poll.
poll_interval_msint2000Outbox poll interval when idle.
max_retriesint3Per-record POST retries before the record is left pending (local store on) or dropped and metered (store off).

With the local store on, the feed drains the store’s outbox and is therefore loss-free across a repository outage. With the store off it ships in-drain, and a record that exhausts its retries is dropped and counted.