Audit & Error Codes Design
Document Type: Domain Design (Tier 2) Domain: AUDIT, ERRORCODES Domain Character: Configuration-heavy SRS Reference: audit-log.md, errorcodes.md Status: Draft Last Updated: 2026-01-25
1. Overview
1.1 Purpose
The Audit & Error Codes domain provides two interconnected subsystems:
- Audit Trail System - Immutable logging of all system changes for compliance, accountability, and debugging
- Error Code Catalog - Configurable error conditions generated during analysis and validation
This domain is characterized by:
- Configuration-heavy data models for error code taxonomy and properties
- Immutable write-once storage for audit records
- Multi-site isolation for both audit visibility and error code configuration
- Event-driven architecture where domain events emit to a central audit listener
1.2 Requirements Covered
| REQ ID | Title | Category |
|---|---|---|
| REQ-AUDIT-001 | Display Audit Trail | Audit Display |
| REQ-AUDIT-002 | Filter Audit Entries | Audit Filtering |
| REQ-AUDIT-003 | Export Audit Data | Audit Export |
| REQ-AUDIT-004 | Enforce Site-Based Access Control | Access Control |
| REQ-ERRORCODES-001 | Generate Westgard Rule Error Codes | QC Errors |
| REQ-ERRORCODES-002 | Generate Control Check Error Codes | Control Errors |
| REQ-ERRORCODES-003 | Generate Inhibition Error Codes | Inhibition Errors |
| REQ-ERRORCODES-004 | Generate Quantification Error Codes | Quant Errors |
| REQ-ERRORCODES-005 | Generate CT and Threshold Error Codes | CT Errors |
| REQ-ERRORCODES-006 | Generate Classification Discrepancy Error Codes | Classification Errors |
| REQ-ERRORCODES-007 | Generate Bacteremia Error Codes | Bacteremia Errors |
| REQ-ERRORCODES-008 | Generate Fluorescence Error Codes | Fluorescence Errors |
| REQ-ERRORCODES-009 | Generate Miscellaneous Analytical Error Codes | Misc Errors |
| REQ-ERRORCODES-010 | Generate Parsing Validation Blocking Error Codes | Parsing Errors |
| REQ-ERRORCODES-011 | Generate Analysis Validation Blocking Error Codes | Analysis Errors |
1.3 Constraints
Tier 2 Constraint: This document describes ownership, patterns, and design rationale. It links to reference docs for full schemas. It does not duplicate error code catalogs documented in the SRS.
1.4 Dependencies
| Direction | Domain/Component | Purpose |
|---|---|---|
| Audit receives from | All domains | AuditableEvent implementations for change tracking |
| Audit provides to | Compliance | Immutable audit trail, export capability |
| Error codes consumed by | RULES | Error code assignment during analysis |
| RUNRPT | Error display on run file reports | |
| LIMS | Error codes in LIMS exports | |
| KITCFG | Combined outcomes, error resolutions |
2. Component Architecture
2.1 Component Diagram
2.2 Component Responsibilities
| Component | Type | Responsibility | REQ Trace |
|---|---|---|---|
AuditsController | Controller | Query and display paginated audit entries | REQ-AUDIT-001, 002 |
AuditExportsController | Controller | Initiate audit export job | REQ-AUDIT-003 |
AuditFilterOptions/* | Controllers | Provide distinct filter values | REQ-AUDIT-002 |
AuditableEvent | Interface | Contract for auditable domain events | REQ-AUDIT-001 |
LogIntoDatabase | Listener | Persist audit events to database | REQ-AUDIT-001 |
GetAuditsAction | Action | Encapsulate audit query with filters | REQ-AUDIT-001, 002 |
AuditFilters | Filter | Apply filter criteria to queries | REQ-AUDIT-002, 004 |
AuditQueryBuilder | QueryBuilder | Site-scoped query building | REQ-AUDIT-004 |
AuditExportJob | Job | Background chunked export with email | REQ-AUDIT-003 |
ErrorCodesController | Controller | Error code CRUD operations | REQ-ERRORCODES-* |
GetErrorCodesAction | Action | Query error codes with site scope | REQ-ERRORCODES-* |
ErrorCode | Model | Error code entity with level/type | REQ-ERRORCODES-* |
ErrorCodesRelation | Relation | Map error codes to run targets | REQ-ERRORCODES-* |
2.3 Architectural Patterns
Pattern: Event-Driven Audit Capture
All auditable changes emit events implementing AuditableEvent:
Domain Action
└── emit(SomeEvent implements AuditableEvent)
└── LogIntoDatabase listener
└── Audit::create([...])
└── Aurora Audit DB
Pattern: Separate Audit Database
Audit records are stored in a dedicated Aurora database:
// Audit model constructor sets connection
$this->setConnection(config('database.audit')); // mysql_audit
This provides:
- Immutability guarantee (no accidental deletes via main DB)
- Independent scaling and backup policies
- Compliance isolation
Pattern: Seed vs Custom Error Codes
Error codes fall into two categories:
- Seed codes: Must exist because rule implementations are hardcoded to output them
- Custom codes: Client-defined for Combined Outcomes and Resolutions
Pattern: Error Level Assignment
Error codes target three levels:
- Well: Entire well affected
- Target: Specific target within well
- Mix: Entire mix affected
3. Data Design
3.1 Entity Ownership
This domain owns the following entities:
| Entity | Table | Purpose | Key Relationships |
|---|---|---|---|
Audit | audits (audit DB) | Immutable change records | None (standalone) |
ErrorCode | error_codes | Error condition definitions | → resolution_codes |
ResolutionCode | resolution_codes | Resolution actions for errors | → error_code |
See Database Reference for full schema.
3.2 Audit Entity Design
Audit Record Fields:
| Field | Purpose | Source |
|---|---|---|
username | User who performed action | AuditableEvent::username() |
area | System module affected | AuditableEvent::area() |
change_type | Classification (create/update/delete) | AuditableEvent::changeType() |
action | Specific action name | AuditableEvent::action() |
change_location | Affected entity identifier | AuditableEvent::changeLocation() |
value_before | Previous value (JSON or text) | AuditableEvent::beforeValue() |
value_after | New value (JSON or text) | AuditableEvent::afterValue() |
site_name | Site where change occurred | AuditableEvent::siteName() |
3.3 Error Code Entity Design
Error Level Enumeration:
| Value | Level | Description |
|---|---|---|
| 1 | Well | Error affects entire well |
| 2 | Mix | Error affects entire mix |
| 3 | Target | Error affects specific target |
Error Type Enumeration:
| Value | Type | Maps to Outcome |
|---|---|---|
| 0 | Label Error | Error |
| 1 | Error | Error |
| 2 | Warning | Warning |
| 3 | Information | Information |
| 4 | Associate Control Error | Error |
3.4 Error Code Categories
The error code taxonomy is organized by generation source:
| Category | Prefix/Pattern | Example Codes |
|---|---|---|
| Westgard QC | WG* | WG12S_HIGH_WELL, WG7T_LOW_TARGET |
| Control Check | FAILED_POS*, NEC_* | FAILED_POS_WELL, NEC_FAILURE_TARGET |
| Inhibition | INH*, IC*, BICQUAL* | INH_WELL, ICQUAL_RPT |
| Quantification | RQUANT*, QUANT_* | RQUANT_LIMITS_MISSED, BAD_R2 |
| CT/Threshold | ADJ_*, THRESHOLD_* | ADJ_CT, THRESHOLD_WRONG |
| Classification | CLSDISC*, CTDISC* | CLSDISC_WELL, CONTROL_CLSDISC_TARGET |
| Bacteremia | BACT_*, *_BACT* | BACT_NO_MATCHING_SAMPLE, LOW_BACT |
| Fluorescence | *_FL*, SIGMOID* | UNEXPECTED_FL, INCORRECT_SIGMOID |
| Parsing | INVALID_*, *_UNKNOWN | INVALID_PASSIVE_READINGS, THERMOCYCLER_UNKNOWN |
| Analysis | UNKNOWN_*, *_MISSING | UNKNOWN_MIX, ACCESSION_MISSING |
3.5 Seed vs Custom Codes
| Category | Description | Examples |
|---|---|---|
| Seed Codes | System-defined, rule implementations hardcoded | WG12S_HIGH_WELL, FAILED_POS_TARGET |
| Custom Codes | Client-defined for combined outcomes/resolutions | Client-specific workflow codes |
3.6 Naming Convention
Error codes follow the pattern: {CONDITION}_{DIRECTION}_{LEVEL}
| Component | Values | Example |
|---|---|---|
| CONDITION | WG12S, WG13S, INH, BCC, etc. | WG12S |
| DIRECTION | HIGH, LOW, (none) | HIGH |
| LEVEL | WELL, TARGET, MIX | WELL |
Result: WG12S_HIGH_WELL
3.7 Generation Formulas
| Rule | Trigger Condition |
|---|---|
| WG12S | delta = ABS(control.ct - mean); delta > 2 * SD |
| WG13S | delta > 3 * SD |
| WG22S | 2 consecutive CTs > 2 SD, same direction |
| WG7T | 7 consecutive CTs trending same direction |
| BCC | Control CT outside configured min/max limits |
| INH | Internal control indicates sample inhibition |
3.8 Processing Control Flow
3.9 Error Resolution Workflow
- GENERATED - Rule outputs error code, assigned to well/target/mix
- DISPLAYED - Run File Report shows error code and message
- RESOLUTION APPLIED - User selects configured resolution action
- RE-ANALYSIS - System re-runs rules, skipping those specified in resolution
- FINAL STATE - Error resolved or persisted based on re-analysis
4. Interface Design
4.1 APIs Provided
Audit APIs:
| Endpoint | Method | Purpose | REQ Trace |
|---|---|---|---|
/api/audits | GET | List paginated audit entries | REQ-AUDIT-001 |
/api/audit-exports | POST | Initiate export job | REQ-AUDIT-003 |
/api/audit-filter-options/actions | GET | Distinct actions | REQ-AUDIT-002 |
/api/audit-filter-options/areas | GET | Distinct areas | REQ-AUDIT-002 |
/api/audit-filter-options/change-types | GET | Distinct change types | REQ-AUDIT-002 |
/api/audit-filter-options/usernames | GET | Distinct usernames | REQ-AUDIT-002 |
/api/audit-filter-options/created-at-range | GET | Date range bounds | REQ-AUDIT-002 |
/api/audit-filter-options/site-names | GET | Accessible site names | REQ-AUDIT-004 |
Error Code APIs:
| Endpoint | Method | Purpose | REQ Trace |
|---|---|---|---|
/api/error-codes | GET | List all error codes | REQ-ERRORCODES-* |
/api/error-codes | POST | Create error codes | REQ-ERRORCODES-* |
/api/error-codes | PUT | Update error codes | REQ-ERRORCODES-* |
4.2 Events Consumed
| Event | Source | Purpose |
|---|---|---|
* implements AuditableEvent | All domains | Record change to audit trail |
AuditableEvent Interface Contract:
interface AuditableEvent {
public function username(): string;
public function area(): string;
public function changeType(): string;
public function action(): string;
public function changeLocation(): ?string;
public function beforeValue(): ?string;
public function afterValue(): ?string;
public function siteName(): ?string;
}
5. Behavioral Design
5.1 Audit Event Capture Flow
Algorithm: Capture Audit Event
Inputs:
- event: AuditableEvent implementation
Outputs:
- audit: Persisted Audit record
Assumptions:
- Audit database connection is available
- Event contains valid data
Steps:
1. LogIntoDatabase listener receives event
2. Extract audit fields from event interface methods
3. Create Audit record on audit database connection
4. Record is immutable (no update/delete methods exposed)
Notes:
- Failures logged but do not roll back originating transaction
- Audit storage is fire-and-forget for performance
5.2 Audit Export Flow
Algorithm: Export Audit Data
Inputs:
- filters: Active filter criteria
- user: Requesting user
Outputs:
- email: Email with download link(s)
Assumptions:
- User has export permissions
- S3 and SES are accessible
Steps:
1. Queue AuditExportJob with filter data and user
2. Job queries audit records matching filters
3. Chunk results by CHUNK_SIZE (25,000 records)
4. For each chunk:
a. Generate Excel file
b. Upload to S3
c. Generate temporary URL (7-day expiry)
5. Send email with all download links
6. Large exports produce multiple Excel files
Notes:
- Export includes all columns regardless of UI visibility
- Timeout: 900 seconds (15 minutes)
- Link expiry: 7 days
5.3 Error Code Assignment Flow
Algorithm: Assign Error Code to Target
Inputs:
- error_code: String identifier (e.g., "WG12S_HIGH_WELL")
- level: Well | Target | Mix
- target: RunTarget being analyzed
Outputs:
- void (error code added to target's error_codes array)
Assumptions:
- Error code exists in configuration
- Rule has authority to assign this code
Steps:
1. Rule execution detects condition
2. Rule looks up error code by identifier
3. If error_code.does_prevent_analyse:
a. Mark target as blocked
b. Prevent further rule processing
4. Add error_code to target's error_codes collection
5. Persist to run_targets.error_codes JSON column
Notes:
- Multiple error codes can be assigned to same target
- Blocking errors halt processing; non-blocking continue
6. Error Handling
6.1 Audit Error Handling
| Condition | Detection | Response | User Impact |
|---|---|---|---|
| Audit DB unavailable | Connection exception | Log error, continue operation | Audit not recorded (temporary) |
| Export job fails | Job exception handler | Log error, no email sent | User must retry |
| Email delivery fails | SES error | Log error, file still in S3 | Manual retrieval possible |
6.2 Error Code Error Handling
| Condition | Detection | Response | User Impact |
|---|---|---|---|
| Unknown error code | Lookup returns null | Log warning, skip assignment | Error not shown on report |
| Duplicate error code | Unique constraint | Reject creation, return error | Must use different code |
| Site mismatch | Query returns empty | 404 response | Error code not found |
7. Configuration
7.1 Audit Configuration
| Setting | Location | Default | Effect | REQ Trace |
|---|---|---|---|---|
DB_AUDIT_CONNECTION | .env | mysql_audit | Audit database connection name | REQ-AUDIT-001 |
DB_AUDIT_HOST | .env | 127.0.0.1 | Audit database host | REQ-AUDIT-001 |
DB_AUDIT_DATABASE | .env | vapor_audit | Audit database name | REQ-AUDIT-001 |
per_page | Request param | 10 | Audit entries per page | REQ-AUDIT-001 |
See Configuration Reference for full list.
7.2 Error Code Entity Properties
| Property | Type | Effect |
|---|---|---|
error_code | string | Unique identifier (e.g., WG12S_HIGH_WELL) |
error_message | string | Human-readable description |
error_level | enum | Well (1), Mix (2), Target (3) |
error_type | enum | Label Error, Error, Warning, Information, Associate Control Error |
does_prevent_analyse | bool | Blocks further processing when true |
is_inhibited | bool | Marks as inhibition-related |
causes_missing_mixes | bool | Marks as missing mix error |
lims_status | string | Override LIMS status when assigned |
8. Implementation Mapping
8.1 Code Locations
| Component | Type | Path |
|---|---|---|
| Audit | Model | app/Audit.php |
| AuditableEvent | Interface | app/Events/AuditableEvent.php |
| LogIntoDatabase | Listener | app/Listeners/LogIntoDatabase.php |
| AuditsController | Controller | app/Http/Controllers/AuditsController.php |
| AuditExportsController | Controller | app/Http/Controllers/AuditExportsController.php |
| AuditExportJob | Job | app/Jobs/AuditExportJob.php |
| AuditFilters | Filter | app/Filters/AuditFilters.php |
| AuditQueryBuilder | QueryBuilder | app/QueryBuilders/AuditQueryBuilder.php |
| GetAuditsAction | Action | app/Actions/Audits/GetAuditsAction.php |
| AuditExport | Export | app/Exports/AuditExport.php |
| ErrorCode | Model | app/ErrorCode.php |
| ErrorCodesRelation | Relation | app/ErrorCodesRelation.php |
| ErrorCodesController | Controller | app/Http/Controllers/ErrorCodesController.php |
| GetErrorCodesAction | Action | app/Actions/KitConfigurations/ErrorCodes/GetErrorCodesAction.php |
| ErrorCodeQueryBuilder | QueryBuilder | app/QueryBuilders/ErrorCodeQueryBuilder.php |
8.2 Requirement Traceability
| REQ ID | Design Section | Primary Code |
|---|---|---|
| REQ-AUDIT-001 | §3.2, §5.1 | Audit, AuditsController, AuditableEvent |
| REQ-AUDIT-002 | §4.1 | AuditFilters, AuditFilterOptions/* |
| REQ-AUDIT-003 | §5.2 | AuditExportJob, AuditExportsController |
| REQ-AUDIT-004 | §2.3 | AuditQueryBuilder, AuditFilters::siteNames |
| REQ-ERRORCODES-001 | §3.3, §3.4 | ErrorCode, Westgard rules |
| REQ-ERRORCODES-002 | §3.3, §3.4 | ErrorCode, BCC/BNC rules |
| REQ-ERRORCODES-003 | §3.3, §3.4 | ErrorCode, INH/IC rules |
| REQ-ERRORCODES-004 | §3.3, §3.4 | ErrorCode, RQUAL/RQUANT rules |
| REQ-ERRORCODES-005 | §3.3, §3.4 | ErrorCode, ADJ/THRESHOLD rules |
| REQ-ERRORCODES-006 | §3.3, §3.4 | ErrorCode, WDCLS/WDCT rules |
| REQ-ERRORCODES-007 | §3.3, §3.4 | ErrorCode, RBACT/SBCHECK rules |
| REQ-ERRORCODES-008 | §3.3, §3.4 | ErrorCode, FL/SIGMOID rules |
| REQ-ERRORCODES-009 | §3.3, §3.4 | ErrorCode, AMB/INCONCLUSIVE rules |
| REQ-ERRORCODES-010 | §3.3, §5.3 | ErrorCode, Parser validation |
| REQ-ERRORCODES-011 | §3.3, §5.3 | ErrorCode, Analyzer validation |
9. Design Decisions
| Decision | Rationale | Alternatives Considered |
|---|---|---|
| Separate audit database | Immutability guarantee, compliance isolation | Same DB (rejected: accidental deletes possible) |
| Event-driven audit capture | Decoupled from domain logic, consistent interface | Direct inserts (rejected: coupling, inconsistency) |
| Fire-and-forget audit writes | Performance, don't block business operations | Sync writes (rejected: latency impact) |
| Chunked export (25K records) | Memory management, multiple file strategy | Single file (rejected: memory issues), streaming (rejected: complexity) |
| Error code as string identifier | Rule implementations hardcode identifiers | Integer IDs (rejected: not human-readable in rules) |
| Soft delete for error codes | Preserve historical data integrity | Hard delete (rejected: breaks existing references) |
10. Performance Considerations
| Scenario | Concern | Mitigation |
|---|---|---|
| Large audit table | Query performance | Index on created_at, site_name; pagination |
| Export of full audit | Memory, timeout | Chunked processing, 15-minute timeout |
| Many error codes per target | JSON column size | Array storage, not normalized |
| Error code lookup in rules | Query per rule | Preload all error codes at analysis start |
11. Related Documents
| Document | Relevant Sections |
|---|---|
| SRS: audit-log.md | Requirements source for audit trail |
| SRS: errorcodes.md | Requirements source for error codes |
| SDS: Architecture | Aurora audit database, SES integration |
| SDS: Security Architecture | Site-based access control |
| SDS: Data Architecture | Audit and error code schemas |
| SDS: Rules Engine | Error code generation during analysis |
| SDS: KITCFG Domain | Error code management, error resolutions |
| SDS: Configuration Reference | Audit and error code configuration |