195 lines
5.8 KiB
Markdown
195 lines
5.8 KiB
Markdown
|
|
# Audit Logging Strategy
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This document defines how CLQMS should capture audit and operational logs across four tables:
|
||
|
|
|
||
|
|
- `logpatient` — patient, visit, and ADT activity
|
||
|
|
- `logorder` — orders, tests, specimens, results, and QC
|
||
|
|
- `logmaster` — master data and configuration changes
|
||
|
|
- `logsystem` — sessions, security, import/export, and system operations
|
||
|
|
|
||
|
|
The intent is to audit all domains, including master data changes, and to standardize event capture so reporting and compliance are consistent.
|
||
|
|
|
||
|
|
## Table Ownership
|
||
|
|
|
||
|
|
| Event | Table |
|
||
|
|
| --- | --- |
|
||
|
|
| Patient registered/updated/merged | `logpatient` |
|
||
|
|
| Insurance/consent changed | `logpatient` |
|
||
|
|
| Patient visit (admit/transfer/discharge) | `logpatient` |
|
||
|
|
| Order created/cancelled | `logorder` |
|
||
|
|
| Sample received/rejected | `logorder` |
|
||
|
|
| Result entered/verified/amended | `logorder` |
|
||
|
|
| Result released/retracted/corrected | `logorder` |
|
||
|
|
| QC result recorded | `logorder` |
|
||
|
|
| Test panel added/removed | `logmaster` |
|
||
|
|
| Reference range changed | `logmaster` |
|
||
|
|
| Analyzer config updated | `logmaster` |
|
||
|
|
| User role changed | `logmaster` |
|
||
|
|
| User login/logout | `logsystem` |
|
||
|
|
| Import/export job start/end | `logsystem` |
|
||
|
|
|
||
|
|
## Standard Log Schema (Shared Columns)
|
||
|
|
|
||
|
|
Use a shared schema for all four tables to keep instrumentation and reporting consistent. The legacy names below match existing patterns and can be reused.
|
||
|
|
|
||
|
|
| Column | Description |
|
||
|
|
| --- | --- |
|
||
|
|
| `LogID` (PK) | Auto increment primary key per table (e.g., `LogPatientID`) |
|
||
|
|
| `TblName` | Source table name |
|
||
|
|
| `RecID` | Record ID of the entity |
|
||
|
|
| `FldName` | Field name that changed (nullable for bulk events) |
|
||
|
|
| `FldValuePrev` | Previous value (string or JSON) |
|
||
|
|
| `FldValueNew` | New value (string or JSON) |
|
||
|
|
| `UserID` | Acting user ID (nullable for system actions) |
|
||
|
|
| `SiteID` | Site context |
|
||
|
|
| `DIDType` | Device identifier type |
|
||
|
|
| `DID` | Device identifier |
|
||
|
|
| `MachineID` | Workstation or host identifier |
|
||
|
|
| `SessionID` | Session identifier |
|
||
|
|
| `AppID` | Client application ID |
|
||
|
|
| `ProcessID` | Process/workflow identifier |
|
||
|
|
| `WebPageID` | UI page/context (nullable) |
|
||
|
|
| `EventID` | Event code (see catalog) |
|
||
|
|
| `ActivityID` | Action code (create/update/delete/read/etc.) |
|
||
|
|
| `Reason` | User/system reason |
|
||
|
|
| `LogDate` | Timestamp of event |
|
||
|
|
| `Context` | JSON metadata (optional but recommended) |
|
||
|
|
| `IpAddress` | Remote IP (optional but recommended) |
|
||
|
|
|
||
|
|
Recommended: keep a JSON string in `Context` for extra details (e.g., route, request id, batch id, error message). Use size limits to avoid oversized rows.
|
||
|
|
|
||
|
|
## Event Catalog
|
||
|
|
|
||
|
|
### logpatient
|
||
|
|
|
||
|
|
**Patient core**
|
||
|
|
|
||
|
|
- Register patient
|
||
|
|
- Update demographics
|
||
|
|
- Merge/unmerge/split
|
||
|
|
- Identity changes (MRN, external identifiers)
|
||
|
|
- Consent grant/revoke/update
|
||
|
|
- Insurance add/update/remove
|
||
|
|
- Patient record view (if required by compliance)
|
||
|
|
|
||
|
|
**Visit/ADT**
|
||
|
|
|
||
|
|
- Admit, transfer, discharge
|
||
|
|
- Bed/ward/unit changes
|
||
|
|
- Visit status updates
|
||
|
|
|
||
|
|
**Other**
|
||
|
|
|
||
|
|
- Patient notes/attachments added/removed
|
||
|
|
- Patient alerts/flags changes
|
||
|
|
|
||
|
|
### logorder
|
||
|
|
|
||
|
|
**Orders/tests**
|
||
|
|
|
||
|
|
- Create/cancel/reopen order
|
||
|
|
- Add/remove tests
|
||
|
|
- Priority changes
|
||
|
|
- Order comments added/removed
|
||
|
|
|
||
|
|
**Specimen lifecycle**
|
||
|
|
|
||
|
|
- Collected, labeled, received, rejected
|
||
|
|
- Centrifuged, aliquoted, stored
|
||
|
|
- Disposed/expired
|
||
|
|
|
||
|
|
**Results**
|
||
|
|
|
||
|
|
- Result entered/updated
|
||
|
|
- Verified/amended
|
||
|
|
- Released/retracted/corrected
|
||
|
|
- Result comments/interpretation changes
|
||
|
|
- Auto-verification override
|
||
|
|
|
||
|
|
**QC**
|
||
|
|
|
||
|
|
- QC result recorded
|
||
|
|
- QC failure/override
|
||
|
|
|
||
|
|
### logmaster
|
||
|
|
|
||
|
|
**Value sets**
|
||
|
|
|
||
|
|
- Create/update/retire value set items
|
||
|
|
|
||
|
|
**Test definitions**
|
||
|
|
|
||
|
|
- Test definition updates (units, methods, ranges)
|
||
|
|
- Reference range changes
|
||
|
|
- Formula/delta check changes
|
||
|
|
- Test panel membership add/remove
|
||
|
|
|
||
|
|
**Infrastructure**
|
||
|
|
|
||
|
|
- Analyzer/instrument config changes
|
||
|
|
- Host app integration config
|
||
|
|
- Coding system changes
|
||
|
|
|
||
|
|
**Users/roles**
|
||
|
|
|
||
|
|
- User create/disable/reset
|
||
|
|
- Role changes
|
||
|
|
- Permission changes
|
||
|
|
|
||
|
|
**Sites/workstations**
|
||
|
|
|
||
|
|
- Site/location/workstation CRUD
|
||
|
|
|
||
|
|
### logsystem
|
||
|
|
|
||
|
|
**Sessions & security**
|
||
|
|
|
||
|
|
- Login/logout
|
||
|
|
- Failed login attempts
|
||
|
|
- Lockouts/password resets
|
||
|
|
- Token issue/refresh/revoke
|
||
|
|
- Authorization failures
|
||
|
|
|
||
|
|
**Import/export**
|
||
|
|
|
||
|
|
- Import/export job start/end
|
||
|
|
- Batch ID, source, record counts, status
|
||
|
|
|
||
|
|
**System operations**
|
||
|
|
|
||
|
|
- Background jobs start/end
|
||
|
|
- Integration sync runs
|
||
|
|
- System config changes
|
||
|
|
- Service errors that affect data integrity
|
||
|
|
|
||
|
|
## Activity & Event Codes
|
||
|
|
|
||
|
|
Use consistent `ActivityID` and `EventID` values. Recommended defaults:
|
||
|
|
|
||
|
|
- `ActivityID`: `CREATE`, `UPDATE`, `DELETE`, `READ`, `MERGE`, `SPLIT`, `CANCEL`, `REOPEN`, `VERIFY`, `AMEND`, `RETRACT`, `RELEASE`, `IMPORT`, `EXPORT`, `LOGIN`, `LOGOUT`
|
||
|
|
- `EventID`: domain-specific codes (e.g., `PATIENT_REGISTERED`, `ORDER_CREATED`, `RESULT_VERIFIED`, `QC_RECORDED`)
|
||
|
|
|
||
|
|
## Capture Guidelines
|
||
|
|
|
||
|
|
- Always capture `UserID`, `SessionID`, `SiteID`, and `LogDate` when available.
|
||
|
|
- If the action is system-driven, set `UserID` to `SYSTEM` (or null) and add context in `Context`.
|
||
|
|
- Store payload diffs in `FldValuePrev` and `FldValueNew` for single-field changes; for multi-field changes, put a JSON diff in `Context` and leave `FldName` null.
|
||
|
|
- For bulk operations, store batch metadata in `Context` (`batch_id`, `record_count`, `source`).
|
||
|
|
- Do not log secrets, tokens, or full PHI when not required. Mask or omit sensitive fields.
|
||
|
|
|
||
|
|
## Retention & Governance
|
||
|
|
|
||
|
|
- Define retention policy per table (e.g., 7 years for patient/order, 2 years for system).
|
||
|
|
- Archive before purge; record purge activity in `logsystem`.
|
||
|
|
- Restrict write/delete permissions to service accounts only.
|
||
|
|
|
||
|
|
## Implementation Checklist
|
||
|
|
|
||
|
|
1. Create the four tables with shared schema (or migrate existing log tables to match).
|
||
|
|
2. Add a single audit service with helpers to build a normalized payload.
|
||
|
|
3. Instrument controllers/services for each event category above.
|
||
|
|
4. Add automated tests for representative audit writes.
|
||
|
|
5. Document `EventID` codes used by each endpoint/service.
|