Kit Configuration Design
Document Type: Domain Design (Tier 2) Domain: KITCFG Domain Character: Configuration-heavy SRS Reference: kitcfg.md Status: Draft Last Updated: 2026-03-06 Version: v3.1.0
1. Overview
1.1 Purpose
The Kit Configuration subsystem provides centralized management of assay and instrument configurations used in PCR analysis workflows. It is the configuration backbone of the system—rules, controls, calibrations, and outcome mappings all depend on KITCFG entities.
This domain is characterized by:
- CRUD-heavy operations with extensive validation
- Import/export functionality via Excel for bulk configuration
- Multi-entity relationships (mixes → targets → rules → outcomes)
- Multi-site isolation for tenant-specific configurations
- Audit trail integration for all changes
1.2 Requirements Covered
| REQ ID | Title | Category |
|---|---|---|
| REQ-KITCFG-001 | Manage Mix and Target Configuration | Core Config |
| REQ-KITCFG-002 | Import and Export Mix Configuration | Import/Export |
| REQ-KITCFG-003 | Manage Extraction Instruments | Instruments |
| REQ-KITCFG-004 | Manage Thermocycler Instruments | Instruments |
| REQ-KITCFG-005 | Manage Error Codes | Error Handling |
| REQ-KITCFG-006 | Manage Error Resolutions | Error Handling |
| REQ-KITCFG-007 | Manage Control Labels | Analysis Config |
| REQ-KITCFG-008 | Manage Run Tags | Organization |
| REQ-KITCFG-009 | Manage LIMS Export Mappings | Integration |
| REQ-KITCFG-010 | Provide Unified Assay Configuration Interface | UI |
| REQ-KITCFG-011 | Manage Combined Outcome Rules | Analysis Config |
| REQ-KITCFG-012 | Manage Westgard Settings | QC Config |
| REQ-KITCFG-013 | Manage Cross Contamination Limits | QC Config |
| REQ-KITCFG-014 | Manage Curve Control Limits | QC Config |
| REQ-KITCFG-015 | Manage Known Quantities | Quantification |
| REQ-KITCFG-016 | Manage Reporting Cut-offs | Reporting |
| REQ-KITCFG-017 | Manage Test Codes | Sample Config |
| REQ-KITCFG-018 | Manage QIR Quantification Settings | Quantification |
| REQ-KITCFG-019 | Manage Delta CT Configurations | Analysis Config |
| REQ-KITCFG-020 | Perform Assay Calibration Analysis | Calibration |
| REQ-KITCFG-021 | Manage Calibration Boundaries | Calibration |
| REQ-KITCFG-022 | Manage Calibration Versions | Calibration |
| REQ-KITCFG-023 | Display Calibration in Run Reports | Calibration |
| REQ-KITCFG-024 | Manage Rule Mappings | Analysis Config |
| REQ-KITCFG-025 | Manage Rule Settings | Analysis Config |
| REQ-KITCFG-026 | Manage Prepend Cycles | Analysis Config |
| REQ-KITCFG-027 | Support Multi-Site Configuration | Multi-Site |
| REQ-KITCFG-028 | Manage Help Item Tags | Support |
| REQ-KITCFG-029 | Manage Dye Configuration | Reference Data |
| REQ-KITCFG-030 | Manage Westgard Event Codes | QC Config |
| REQ-KITCFG-031 | Manage Specimen Types | Reference Data |
| REQ-KITCFG-032 | Clone Mix Configuration | Mix Clone |
| REQ-KITCFG-033 | Update Delta CT with Transactional Integrity | Delta CT |
| REQ-KITCFG-034 | Separate Delta CT Insert/Update/Delete | Delta CT |
| REQ-KITCFG-035 | Replace Quantitative with Quantification Scope | Mix/Targets |
| REQ-KITCFG-036 | Quantification Method per Mix | Mix/Targets |
| REQ-KITCFG-037 | Automatic Baseline per Target | Mix/Targets |
| REQ-KITCFG-038 | Link Virtual Mix Targets to Base Mix | Mix/Targets |
| REQ-RULETAGS-001 | Rule Tags Page Access | Rule Tags |
| REQ-RULETAGS-002 | Rule Tags Table Display | Rule Tags |
| REQ-RULETAGS-003 | Rule Tags Table Columns | Rule Tags |
| REQ-RULETAGS-004 | Rule Availability Toggle | Rule Tags |
| REQ-RULETAGS-005 | Tag Category Multi-Select Dropdowns | Rule Tags |
| REQ-RULETAGS-006 | Tag Compatibility Validation | Rule Tags |
| REQ-RULETAGS-007 | HIDDEN Modifier Tag Visibility | Rule Tags |
| REQ-RULETAGS-008 | Tag Changes Trigger Auto Mapper | Rule Tags |
| REQ-RULETAGS-009 | Rule Tags Help Data | Rule Tags |
| REQ-RULETAGS-010 | Automatic Rule Mapping Engine | Auto Rule Mapper |
| REQ-SPECIMEN-001 | Specimen Types Page Access | Specimen Mgmt |
| REQ-SPECIMEN-002 | Specimen Types Table | Specimen Mgmt |
| REQ-SPECIMEN-003 | Add Specimen | Specimen Mgmt |
| REQ-SPECIMEN-004 | Edit Specimen | Specimen Mgmt |
| REQ-SPECIMEN-005 | Delete Specimen with Warning | Specimen Mgmt |
| REQ-SPECIMEN-006 | Target Suffix Page Access | Suffix Mgmt |
| REQ-SPECIMEN-007 | Target Suffix Mapping Table | Suffix Mgmt |
| REQ-SPECIMEN-008 | Add Target Suffix Mapping | Suffix Mgmt |
| REQ-SPECIMEN-009 | Edit Target Suffix Mapping | Suffix Mgmt |
| REQ-SPECIMEN-010 | Delete Target Suffix Mapping | Suffix Mgmt |
| REQ-SPECIMEN-011 | Suffix Matching During Import | Suffix Mgmt |
| REQ-SPECIMEN-012 | Help Data Toggle | Suffix Mgmt |
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 validation rules documented in the SRS acceptance criteria.
1.4 Dependencies
| Direction | Domain/Component | Purpose |
|---|---|---|
| Provides to | FILEIMPORT | Mix matching, control label classification |
| ANALYTICS | Rule mappings, execution order | |
| RULES | QC thresholds, combined outcomes, calibration | |
| REPORTS | Mix/target structure, reporting cut-offs | |
| RUNRPT | Mix/target display, LIMS mappings | |
| CONFIGMODE | Config Mode orchestrates changes via updaters | |
| CALIBRATION | Calibration lifecycle for targets | |
| Consumes | DxAI PCR API | Calibration analysis results |
| Excel files | Bulk configuration import |
2. Component Architecture
2.1 Component Diagram
2.2 Component Responsibilities
| Component | Type | Responsibility | REQ Trace |
|---|---|---|---|
MixesController | Controller | Mix CRUD, enable/disable | REQ-KITCFG-001 |
TargetsController | Controller | Target properties, prepend cycles | REQ-KITCFG-001, 026 |
KitsController | Controller | Unified config interface | REQ-KITCFG-010 |
GlobalMixMapper | Action | Cascade config to related entities | REQ-KITCFG-001, 007, 012-014 |
*ImportSheet | Import | Excel parsing and validation | REQ-KITCFG-002, 007, 011, 012 |
*Mapper | Action | Entity-specific configuration logic | Various |
AssayCalibration | Model | Calibration state and boundaries | REQ-KITCFG-020-023 |
RuleTagsController | Controller | Rule tag CRUD, tag validation | REQ-RULETAGS-001 through 009 |
SpecimensController | Controller | Specimen type CRUD | REQ-SPECIMEN-001 through 005 |
TargetNameSuffixToSpecimenController | Controller | Suffix-to-specimen mapping CRUD | REQ-SPECIMEN-006 through 012 |
RuleMapper | Action | Orchestrates rule mapping generators | REQ-RULETAGS-010 |
BaseRuleMappingGenerator | Abstract | Base class for all auto-mapping generators | REQ-RULETAGS-010 |
CustomRuleMapping | Model | Non-automatic (custom) rule mappings | REQ-RULETAGS-010 |
WestgardRuleMapping | Model | Westgard-specific rule mappings | REQ-RULETAGS-010 |
2.3 Architectural Patterns
Pattern: Configuration Cascade
When a mix is created or modified, related entities may need updates:
Mix Created/Modified
├── ControlLabelMapper → Update control label defaults
├── WestgardLimitsMapper → Initialize QC ranges
├── RuleMapper → Apply default rule mappings
└── GlobalMixMapper → Orchestrate all mappers
Pattern: Site-Scoped Queries
All configuration queries are scoped by site for multi-site clients:
// All KITCFG queries include site scope
Mix::where('site_id', $currentSite->id)->get();
Pattern: Audit Event Emission
All configuration changes emit audit events:
// Models implement AuditableEvent interface
event(new MixCreated($mix)); // → LogIntoDatabase listener
3. Data Design
3.1 Entity Ownership
This domain owns the following entities:
| Entity | Table | Purpose | Key Relationships |
|---|---|---|---|
Mix | mixes | Assay definition | → targets, control_labels, combined_outcomes |
Target | targets | Detection target | → mix, rule_mappings |
ControlLabel | control_labels | Sample classification rules | → mix, roles |
Role | roles | Control/sample type | → control_labels |
WestgardSetting | westgard_settings | QC statistical parameters | → mix, target, role |
CombinedOutcome | combined_outcomes | Outcome mapping rules | → mix, targets, lims_status |
ErrorCode | error_codes | Error definitions | → error_resolutions |
ErrorResolution | error_resolutions | Resolution actions | → error_code |
ExtractionModel | extraction_models | Extraction instrument groups | → extraction_instruments |
ExtractionInstrument | extraction_instruments | Individual extractors | → extraction_model |
ThermocyclerModel | thermocycler_models | Thermocycler groups | → thermocyclers |
Thermocycler | thermocyclers | Individual thermocyclers | → thermocycler_model |
CurveControlLimit | curve_control_limits | BCC rule thresholds | → mix, target, role |
CrossContaminationLimit | adjacents | ADJ rule thresholds | → mix, target |
KnownQuantity | known_quantities | Quantification standards | → role, mix, target |
ReportingCutoff | quantitative_reportings | RQUANT boundaries | → mix, target |
TestCode | test_codes | Specimen type mappings | → mix |
QIRSetting | qir_settings | Quantification parameters | → targets |
DeltaCTConfig | delta_ct_configurations | CT delta thresholds | → target pairs |
AssayCalibration | assay_calibrations | Calibration data | → mix, target |
RuleMapping | rule_mappings | Rule → observation binding | → rule, mix, target, role |
Tag | tags | Run organization | (standalone) |
LimsStatus | lims_statuses | LIMS export codes | → combined_outcomes |
HelpItem | help_items | Context help entries | (standalone) |
Dye | dyes | Fluorescent reporter definitions | → targets (via observations) |
WestgardEvent | westgard_events | QC event code definitions | → westgard_limits |
Specimen | specimens | Sample type classifications | → test_codes, reportings, combined_outcomes |
CustomRuleMapping | custom_rule_mappings | Non-automatic rule-to-mix mappings | → rule, mix, target, role |
WestgardRuleMapping | westgard_rule_mappings | Westgard-specific rule mappings | → rule, mix, target, role |
TargetNameSuffixToSpecimen | target_name_suffix_to_specimens | Suffix-to-specimen mappings | → specimen, site |
Kit | kits | Kit groupings of mixes | → mixes, site |
See Database Reference for full schema.
3.2 Entity Relationship Overview
3.3 State Management
Mix State Machine:
Calibration State Machine:
4. Interface Design
4.1 APIs Provided
| Endpoint | Method | Purpose | REQ Trace |
|---|---|---|---|
/api/mixes | GET/POST | List/create mixes | REQ-KITCFG-001 |
/api/mixes/{id} | PUT/DELETE | Update/delete mix | REQ-KITCFG-001 |
/api/targets/{id} | PUT | Update target properties | REQ-KITCFG-001 |
/api/kit-configurations/import | POST | Import Excel config | REQ-KITCFG-002 |
/api/kit-configurations/export | GET | Export Excel config | REQ-KITCFG-002 |
/api/control-labels | GET/POST/PUT/DELETE | Control label CRUD | REQ-KITCFG-007 |
/api/combined-outcomes | GET/POST/PUT/DELETE | Combined outcome CRUD | REQ-KITCFG-011 |
/api/westgard-settings | GET/POST/PUT | Westgard CRUD | REQ-KITCFG-012 |
/api/assay-calibrations | GET/POST | Calibration management | REQ-KITCFG-020-022 |
/api/rule-mappings | GET/PUT | Rule mapping management | REQ-KITCFG-024 |
/api/clone-mix | POST | Clone mix configuration | REQ-KITCFG-032 |
4.2 APIs Consumed
| Service | Purpose | REQ Trace |
|---|---|---|
| DxAI PCR API | Calibration analysis | REQ-KITCFG-020 |
4.3 Events Published
| Event | Payload | Purpose | Listener |
|---|---|---|---|
MixCreated | mix_id, site_id, user_id | Audit trail | LogIntoDatabase |
MixEnabled | mix_id, site_id, user_id | Audit trail | LogIntoDatabase |
MixDisabled | mix_id, site_id, user_id | Audit trail | LogIntoDatabase |
TargetCreated | target_id, mix_id, user_id | Audit trail | LogIntoDatabase |
RuleCreated | rule_id, mapping, user_id | Audit trail | LogIntoDatabase |
WestgardSettingChanged | setting_id, old, new | Audit + re-analysis trigger | LogIntoDatabase, ResetWestgardFailures |
5. Behavioral Design
5.1 Import Engine Architecture
Algorithm: Process Kit Configuration Import
Inputs:
- file: Excel file with multiple sheets
- site_id: Target site for import
- user: Authenticated user
Outputs:
- result: ImportResult with per-row status
Assumptions:
- File format matches expected template
- User has MANAGER or SUPER_ADMIN role
- Site exists and user has access
Steps:
1. Parse Excel file into sheet collection
2. For each sheet in import order:
a. Identify sheet type (mixes, control_labels, etc.)
b. Instantiate appropriate ImportSheet handler
c. For each row:
- Validate required fields
- Validate field formats (see SRS acceptance criteria)
- Check business rules (e.g., duplicates, references)
- If valid: create/update entity, status = "Imported"
- If invalid: skip entity, status = "Ignored", capture reason
d. Collect row results
3. Emit audit events for successful imports
4. Return aggregated ImportResult
Notes:
- Import order matters: mixes before control_labels before rules
- Partial failures allowed: valid rows imported, invalid rows skipped
- Existing entities may be updated (upsert behavior)
Import Sheet Order:
| Order | Sheet | Dependencies |
|---|---|---|
| 1 | Dyes | None |
| 2 | Specimens | None |
| 3 | Mixes and Targets | Dyes |
| 4 | Extraction Instruments | None |
| 5 | Thermocyclers | None |
| 6 | Control Labels | Mixes, Roles |
| 7 | Rule Mappings | Mixes, Targets, Roles |
| 8 | Combined Outcomes | Mixes, Targets, LIMS Statuses, Specimens |
| 9 | Westgard Limits | Mixes, Targets, Roles |
| 10 | Westgard Events | None |
| 11 | Error Codes | None |
| 12 | Error Resolutions | Error Codes |
5.2 Calibration Flow
Algorithm: Execute Assay Calibration
Inputs:
- mix_id: Selected mix
- target_id: Selected target
- run_ids: Selected runs for analysis
- use_machine_cls: Whether to use machine classification
Outputs:
- calibration: AssayCalibration with observations and boundaries
Assumptions:
- Selected runs contain data for mix/target
- DxAI PCR API is accessible
- User has appropriate permissions
Steps:
1. Create AssayCalibration record (status: InProgress)
2. Extract observation data from selected runs
3. Send observation data to DxAI PCR API
4. Receive classification parameters
5. Store parameters in AssayCalibration
6. Update status to Completed
7. Return calibration for boundary adjustment
Notes:
- Concurrent calibrations allowed for different targets
- User can cancel during API call
- Failed calibrations retain Error status with message
5.3 Global Configuration Cascade
Algorithm: Apply Global Mix Mapping
Inputs:
- mix: Mix being created/modified
- action: create|update|enable|disable
Outputs:
- void (side effects on related entities)
Assumptions:
- Mix is valid and persisted
- Mapper classes are registered
Steps:
1. Instantiate GlobalMixMapper with mix
2. For each registered mapper:
a. ControlLabelMapper: Create default labels if none exist
b. WestgardLimitsMapper: Initialize ranges for new targets
c. RuleMapper: Apply default rule mappings
d. Each mapper emits own audit events
3. If action == disable:
- Do NOT delete related config (preserve for re-enable)
- Related entities remain but are inactive
Notes:
- Cascade is synchronous (same transaction)
- Failures in one mapper do not roll back others
- Disabled mix config is preserved, not deleted
5.4 Role Alias Migration Workflow
This algorithm creates a new Role from an existing control-label alias and migrates all dependent quality-control configuration. It allows laboratories to promote an alias already in use on control labels into a fully-fledged role without manually recreating every dependent mapping.
Entry Points:
| Component | Location |
|---|---|
| API Route | POST /api/role-alias-to-role |
| Controller | RoleAliasToRoleController |
| Action | MapRoleAliasToNewRoleAction::execute() |
Transactional Workflow (6 steps):
MapRoleAliasToNewRoleAction runs inside a single database transaction to ensure atomicity:
-
Gather Source Data - Load control labels matching alias and original role, fetch associated rule mappings and combined outcomes scoped to user's site
-
Create Target Role - Clone key fields (type, has_extraction, resolution_priority) from source role using authenticated user's site
-
Relink Control Ecosystem - Update matched control labels and wells to reference new role, restore soft-deleted Westgard limits
-
Duplicate Rule Configuration - Copy RuleMapping records with new UUIDs, preserve original timestamps
-
Clone Combined Outcomes - Create new outcome records, suffix names/codes with
-<role_name>-clone -
Commit or Rollback - Success commits, any exception rolls back
Data Dependencies:
| Entity | Purpose |
|---|---|
ControlLabel | Source of alias, provides mix_id for target scoping |
Well | Historical data references new role |
RuleMapping | Copied to retain rule behavior |
WestgardLimit | QC thresholds reactivated |
OutcomeToLimsStatusMapping | Combined outcome logic preserved |
5.5 Feature Toggle Cascade System
The Feature Toggle system provides import and cascade handling for feature configuration. When features have parent-child dependencies, disabling a parent automatically cascades to disable all children.
Architecture:
Validation Rules:
| Category | Rules |
|---|---|
| Feature Code | Required, string, max 255, must exist in system |
| Feature Value | Boolean (true/false, 1/0, yes/no) |
| Parent Dependency | Recursive chain validation when enabling |
| Restrictions | Certain features cannot be modified via import |
Cascade Behavior:
| Action | Result |
|---|---|
| Disable Parent | Auto-disable all children (recursive) |
| Enable Parent | Children remain unchanged (manual control) |
Import Process (4 phases):
- Excel Processing - Read file, process in 1000-row chunks
- Validation - Feature code, value, and parent dependency validation
- Update - Apply changes, trigger cascades
- Status Reporting - Report success/failure per feature
5.6 Dye Configuration (REQ-KITCFG-029)
Dyes define the fluorescent reporters and quenchers used in PCR analysis. They are associated with targets within mixes, enabling proper signal detection and identification during runfile processing.
Data Model:
| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PK | Primary key |
dye_name | string | required | Dye identifier (e.g., FAM, VIC) |
quencher | string | nullable | Quencher molecule name |
colour | string | required | Display color |
site_id | uuid | FK, required | Multi-site isolation |
created_at | timestamp | Creation timestamp | |
updated_at | timestamp | Last modification |
Import/Export:
| Operation | Sheet | Columns | Logic |
|---|---|---|---|
| Import | Dyes | DYE NAME, QUENCHER, COLOUR | firstOrNew by dye_name + site_id; upsert quencher/colour |
| Export | Dyes | DYE NAME, QUENCHER, COLOUR | All site dyes |
Relationships:
- Targets reference dyes via observations (
observations.dye_id) - Rule mappings use dyes to identify targets
Implementation:
| Component | Type | Path |
|---|---|---|
Dye | Model | app/Dye.php |
DyeImportSheet | Import | app/Imports/Sheets/DyeImportSheet.php |
DyeExport | Export | app/Exports/Config/DyeExport.php |
DyeCreated | Event | app/Events/DyeCreated.php |
5.7 Westgard Event Codes (REQ-KITCFG-030)
Westgard event codes define the error messages generated when Westgard statistical rules detect out-of-control conditions. They provide descriptive messages that appear in quality control reports and alerts.
Data Model:
| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PK | Primary key |
code | string | required | Unique event code identifier |
message | string | required | Human-readable error message |
site_id | uuid | FK, required | Multi-site isolation |
created_at | timestamp | Creation timestamp | |
updated_at | timestamp | Last modification |
Import/Export:
| Operation | Sheet | Columns | Logic |
|---|---|---|---|
| Import | Westgard Events | CODE, MESSAGE | updateOrCreate by code + site_id |
| Export | Westgard Events | CODE, MESSAGE | All site event codes |
Relationships:
- Westgard settings (REQ-KITCFG-012) reference event codes for rule evaluation
- QC failures display event code messages in reports
Implementation:
| Component | Type | Path |
|---|---|---|
WestgardEvent | Model | app/WestgardEvent.php |
WestgardEventsImportSheet | Import | app/Imports/Sheets/WestgardEventsImportSheet.php |
WestgardEventsExport | Export | app/Exports/Config/WestgardEventsExport.php |
5.8 Specimen Types (REQ-KITCFG-031)
Specimen types provide a classification layer for samples, enabling configuration of test codes, reporting cut-offs, and combined outcomes based on sample categories. Labs define specimen types specific to their workflows (e.g., "Nasopharyngeal Swab", "Plasma", "Serum").
Data Model:
| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PK | Primary key |
specimen_name | string | required, unique per site | Specimen type name |
site_id | uuid | FK, required | Multi-site isolation |
created_at | timestamp | Creation timestamp | |
updated_at | timestamp | Last modification |
Import/Export:
| Operation | Sheet | Columns | Logic |
|---|---|---|---|
| Import | Specimens | SPECIMEN NAME | firstOrNew by specimen_name + site_id; deduplicates on import |
| Export | Specimens | SPECIMEN NAME | All site specimens |
Relationships:
- Test codes (REQ-KITCFG-017) map sample labels to specimen classifications
- Reporting cut-offs (REQ-KITCFG-016) define specimen-specific quantitative groupings
- Combined outcomes (REQ-KITCFG-011) enable specimen-aware outcome rules
- Specimen-to-mix mappings track which specimens are valid for which mixes
Implementation:
| Component | Type | Path |
|---|---|---|
Specimen | Model | app/Specimen.php |
SpecimensImportSheet | Import | app/Imports/Sheets/SpecimensImportSheet.php |
SpecimensExport | Export | app/Exports/Config/SpecimensExport.php |
SpecimenCreated | Event | app/Events/SpecimenCreated.php |
SpecimenToMixMapping | Model | app/SpecimenToMixMapping.php |
5.9 Mix Clone Workflow (REQ-KITCFG-032)
Added in v3.0.1.
The Mix Clone feature allows users to clone an existing enabled mix's configuration onto an unmapped (unknown/disabled) mix, duplicating all configuration without manual re-entry.
5.9.1 API Entry Point
| Property | Value |
|---|---|
| Endpoint | POST /api/clone-mix |
| Controller | MixCloneController::__invoke |
| Auth | user-type:MANAGER,SUPER_ADMIN |
Request payload:
{
"original_mix_id": "<uuid>",
"unknown_mix_id": "<uuid>",
"control_labels": [
{ "role_id": "...", "control_labels": "Alpha, Beta" }
],
"mix_name": "New Mix Name",
"is_clone_westgard_limits": true,
"is_clone_combined_outcomes": true
}
5.9.2 Clone Action Architecture
MixCloneAction orchestrates 12 clone sub-actions inside a DB transaction:
5.9.3 Target Matching Strategy
All target-level cloning uses dye_id as the matching key between source and destination mixes:
Algorithm: Match Targets by Dye ID
For each target in the unknown (destination) mix:
1. Look up the target's dye_id
2. Find the matching target in the source mix with same dye_id
3. If match found: clone attributes from source to destination
4. If no match: skip (destination target unchanged)
For source targets with no matching dye_id in destination:
- Related data (rule mappings, limits, etc.) is NOT cloned
5.9.4 Clone Sub-Actions
| Sub-Action | Entities Cloned | Target Matching | Conditional |
|---|---|---|---|
CloneMixAndTargets | Mix metadata, target attributes (type, is_passive, expected_threshold, order, fluorescence, discrepancy, inhibition settings) | By dye_id | No |
CloneControlLabels | control_labels (role_alias, role_id) | N/A (mix-level) | No |
CloneSpecimenMappings | specimen_to_mix_mappings | N/A (mix-level) | No |
CloneRuleMappings | rule_mappings | By dye_id | No |
CloneKnownQuantities | known_quantities (role_id, target_id, known_quantity) | By dye_id | No |
CloneCalculatedQuantificationSetting | qir_settings | By dye_id | No |
CloneWestgardLimit | westgard_settings + curve_control_limits + adjacents | By dye_id | Yes (is_clone_westgard_limits) |
CloneControlRangeSetting | control_range_settings | By dye_id | Yes (with Westgard) |
CloneCrossContaminationLimits | adjacents | By dye_id | Yes (with Westgard) |
CloneReporting | quantitative_reportings | By dye_id | No |
CloneDeltaCTCombination | delta_ct_configurations | By dye_id | No |
CloneCombinedOutcomes | outcome_to_lims_status_mappings, mix results, target results, history/repeat outcomes | By dye_id via TargetMappings DTO | Yes (is_clone_combined_outcomes) |
5.9.5 Combined Outcomes Clone Detail
When is_clone_combined_outcomes is enabled, CloneCombinedOutcomes duplicates the full combined outcome hierarchy:
- OutcomeToLimsStatusMapping — New record with updated
codeandnamesuffixed for the clone.role_idpreserved from source. - OutcomeToLimsMappingMixResult — New record with
mix_idpointing to the cloned mix, linked to new outcome mapping. - OutcomeToLimsMappingTargetResult — New record with
target_idupdated to the cloned mix's matching target (viadye_id). - Required history outcomes and required repeat outcomes — Duplicated with updated target references.
Target mapping is resolved via the TargetMappings DTO, which pre-computes the source-to-destination target mapping by dye_id.
5.9.6 Design Decisions
| Decision | Rationale |
|---|---|
dye_id as sole matching key | Dyes are unique identifiers across instruments; target names may vary between mixes |
| DB transaction wrapping | Atomicity — partial clones would leave inconsistent configuration |
| Optional Westgard/CO toggles | Labs may want to clone base config without QC limits or outcome rules |
| New UUIDs for all cloned records | Prevents primary key collisions; Str::orderedUuid() ensures sortable keys |
5.9.7 Frontend Workflow
| Component | File | Purpose |
|---|---|---|
CloneMix.vue | views/CloneMix.vue | Page view with mix selectors and save/reset |
MixCloneWidget.vue | components/mixes-and-targets/MixCloneWidget.vue | Source mix selector, mix name, toggles |
CloneMixControlLabel.vue | components/mixes-and-targets/CloneMixControlLabel.vue | Per-role control label alias inputs |
Integration flow:
- User opens "Add Mixes" widget → selects unknown mix → selects clone source
- Clone state stored locally in
MixesAndTargets.vue - On save:
POST /api/clone-mixfires first, then normalPUT /mixesruns - After clone success: mixes and control labels re-fetched from server
5.10 Automatic Rule Mapper Architecture (v3.1.0)
Added in v3.1.0.
The Automatic Rule Mapper replaces manual rule-to-mix assignment with a tag-driven dispatch system. Rules are categorized by structured tags, and 32 generator classes produce the appropriate mappings automatically when tags or configuration change.
5.10.1 Generator Class Hierarchy
All generators extend BaseRuleMappingGenerator, which provides:
- Mix/target iteration with site scoping
- Control label awareness (mixes with mapped control labels)
- Tag-based rule lookup
- Mapping record creation with deduplication (
hash_key)
5.10.2 Tag-Driven Dispatch
When a rule's tags change (via the Rule Tags page or import), the orchestrator:
- Identifies which generators are relevant based on the rule's tag combination
- Executes each relevant generator for the affected site
- Generators create
custom_rule_mappingsrecords with ahash_keyfor deduplication - Completion triggers
AutomaticRuleMappingCompletednotification
5.10.3 Generator Scope
| Category | Generators | Scope |
|---|---|---|
| Patient | AMB, THRESH, COMBOUT, STDCURVE, QUANTVAL, RQUANT, DELTACT, MINFL, MAXFL, ADJ, MWCOMBOUT, RQUALQUAL, RWAC, LOD_QUAL, LOD_QUANT, BASELINE | All patient-role mixes |
| Control | BICQUAL, EXTCTRL, CONTROLFAIL, NEG/POS_SIGMOID, CT_INHIB_DELTA, CLS_DISCREPANCY, CT_DISCREPANCY, NEG_IC_CONTROL | Mixes with mapped control labels |
| System | MINCTRL, MIXMISS, WG, CUSTOM, KIT | All mixes (system-level rules) |
5.11 Rule Tag System (v3.1.0)
Added in v3.1.0.
Rules have structured tags organized into four categories that drive automatic rule mapping:
| Category | Purpose | Example Values |
|---|---|---|
| Mix Property | Which mix properties the rule examines | QUANTITATIVE, QUALITATIVE, HAS_EXTRACTION, HAS_KNOWN_QUANTITY, ... (34+ options) |
| Role Type | Which role types the rule applies to | PATIENT, CONTROL, SYSTEM, CROSSOVER |
| Target Type | Target-level constraints | IC_TARGET, PASSIVE_TARGET, ROLE_SPECIFIED_TARGETS, ALL_TARGETS |
| Modifier | Visibility/behavior modifiers | HIDDEN (SUPER_ADMIN only) |
Tag Compatibility Validation:
Not all tag combinations are valid. The system validates:
- IC_TARGET and PASSIVE_TARGET are mutually exclusive
- HIDDEN rules are only visible to SUPER_ADMIN users
- Certain Role Type + Target Type combinations are disallowed
Tag Storage:
Tags are stored in the rules.tags column (JSON). The migration add_tags_column_to_rules_table adds this column alongside is_enabled for rule availability toggling.
Seeding:
RulesSeeder loads tag assignments from a CSV file, ensuring consistent tag data across environments. The seeder is re-runnable (idempotent via rule code matching).
5.12 Specimen Type Management and Target Name Suffix System (v3.1.0)
Added in v3.1.0.
5.12.1 Specimen Type CRUD
The Specimen Types page (accessible from Config Mode Other Settings, SUPER_ADMIN only) provides CRUD for specimen type definitions:
| Operation | Endpoint | Validation |
|---|---|---|
| List | GET /api/specimens | Site-scoped |
| Create | POST /api/specimens | Unique name per site, max 255 chars |
| Update | PUT /api/specimens/{id} | Unique name excluding current |
| Delete | DELETE /api/specimens/{id} | Warning if specimen has associations |
5.12.2 Target Name Suffix to Specimen Mapping
Target name suffixes provide automatic specimen type derivation. When a target's name ends with a registered suffix, the system automatically associates the corresponding specimen type.
Algorithm: Target Suffix to Specimen Association
Inputs:
- target_name: Target name (e.g., "COVID-19 NPS")
- suffix_mappings: Site-specific suffix-to-specimen mappings
Steps:
1. For each suffix mapping (ordered by suffix length, longest first):
a. If target_name ends with suffix:
- Associate target with mapped specimen
- Break (first match wins)
2. If no suffix matches: target has no automatic specimen association
Notes:
- Suffix matching is case-sensitive
- Longest-match-first prevents ambiguous short suffixes from matching
5.12.3 Mix Deletion on Suffix Creation
When a target name suffix is created or modified, redundant mixes are deleted and their wells migrated:
This action also fires during config import when suffix-to-specimen rows are imported (StoreTargetNameSuffixToSpecimenAction).
5.12.4 Quantitative/Qualitative Scope Migration
In v3.1.0, is_quantitative moved from mix-level to specimen-level configuration. The new QUANTIFICATION_SCOPE field replaces the boolean with three values:
| Scope | Meaning |
|---|---|
OFF | Non-quantitative mix |
ALL | All specimens are quantitative |
BY_SPECIMEN | Quantification determined per-specimen |
5.13 Quantitative/Qualitative Switch Cascade (v3.1.0)
Added in v3.1.0.
Switching a mix between quantitative and qualitative modes triggers cascading configuration updates. Six action classes in app/Actions/Mixes/QuantitativeAndQualitativeSwitch/ handle the transitions:
Quantitative → Qualitative:
1. Remove quantification-related rule mappings (RQUANT, STDCURVE, etc.)
2. Clear known quantities for affected targets
3. Update QIR settings
4. Adjust combined outcome rules (remove quant-only outcomes)
5. Broadcast configuration change
Qualitative → Quantitative:
1. Add quantification-related rule mappings
2. Initialize default known quantities
3. Create QIR settings with defaults
4. Broadcast configuration change
This cascade ensures configuration consistency when a mix's quantification mode changes. The switch is atomic (wrapped in a DB transaction).
5.14 Delta CT Transaction Pattern (v3.1.0)
Enhanced in v3.1.0.
Delta CT configuration CRUD is now wrapped in a database transaction with explicit user binding:
Algorithm: Delta CT Configuration Update
Inputs:
- user: Authenticated user (passed from controller, not resolved from request)
- delta_ct_configs: Array of {target_pair, threshold} records
- action_type: insert | update | delete
Steps:
1. Begin DB transaction
2. For each config record:
a. If insert: create new DeltaCTConfig with target pair and threshold
b. If update: update existing record's threshold
c. If delete: remove record
3. Emit audit events with user context
4. Commit transaction (or rollback on error)
Notes:
- Controller passes authenticated User model, not just user_id
- Insert/update/delete are separated for clear audit trail
- Config Mode proposals for Delta CT use dedicated DeltaCtTargetCombinationConfigurationUpdater
6. Error Handling
| Condition | Detection | Response | User Impact |
|---|---|---|---|
| Import validation failure | Field validation | Skip row, status = "Ignored" | Row not imported, reason shown |
| Duplicate entity | Unique constraint | Skip row or update (upsert) | Depends on entity type |
| Referenced entity missing | Foreign key lookup | Skip row | Row not imported |
| API timeout (calibration) | HTTP timeout | Set status = Error | Calibration failed, can retry |
| Concurrent modification | Optimistic locking | Return 409 Conflict | User must refresh and retry |
7. Configuration
This domain defines configuration, but also has meta-configuration for its own behavior:
| Setting | Location | Default | Effect | REQ Trace |
|---|---|---|---|---|
unknown_mix_enabled | client_configurations | true | Auto-create Unknown mixes on import | 001 |
ct_discrepancy_delta | client_configurations | 2 | Default CT discrepancy threshold | 001 |
thermocycler_auto_populate | client_configurations | false | Auto-create thermocyclers from runfiles | 004 |
use_sample_type | client_configurations | false | Enable specimen type in mappings | 016, 017, 024 |
hide_unused_rules | client_configurations | true | Hide unassigned rules in UI | 024 |
See Configuration Reference for full list.
8. Implementation Mapping
8.1 Code Locations
| Component | Type | Path |
|---|---|---|
| MixesController | Controller | app/Http/Controllers/MixesController.php |
| TargetsController | Controller | app/Http/Controllers/TargetsController.php |
| KitsController | Controller | app/Http/Controllers/Kits/KitsController.php |
| ControlLabelsController | Controller | app/Http/Controllers/ControlLabelsController.php |
| WestgardSettingsController | Controller | app/Http/Controllers/WestgardSettingsController.php |
| AssayCalibrateableRunsController | Controller | app/Http/Controllers/AssayCalibrations/AssayCalibrateableRunsController.php |
| KitConfigurationsExportController | Controller | app/Http/Controllers/KitConfigurationsExportController.php |
| GlobalMixMapper | Action | app/Actions/GlobalMappers/GlobalMixMapper.php |
| ControlLabelMapper | Mapper | app/Actions/GlobalMappers/Mappers/ControlLabelMapper.php |
| WestgardLimitsMapper | Mapper | app/Actions/GlobalMappers/Mappers/WestgardLimitsMapper.php |
| RuleMapper | Mapper | app/Actions/GlobalMappers/Mappers/RuleMapper.php |
| MixAndTargetsImportSheet | Import | app/Imports/Sheets/MixAndTargetsImportSheet.php |
| ControlLabelsImportSheet | Import | app/Imports/Sheets/ControlLabelsImportSheet.php |
| CombinedOutcomesImportSheet | Import | app/Imports/Sheets/CombinedOutcomesImportSheet.php |
| DyeImportSheet | Import | app/Imports/Sheets/DyeImportSheet.php |
| WestgardEventsImportSheet | Import | app/Imports/Sheets/WestgardEventsImportSheet.php |
| SpecimensImportSheet | Import | app/Imports/Sheets/SpecimensImportSheet.php |
| MixCloneController | Controller | app/Http/Controllers/MixCloneController.php |
| MixCloneAction | Action | app/Actions/Mixes/Clone/MixCloneAction.php |
| CloneMixAndTargets | Clone Trait | app/Actions/Mixes/Clone/CloneMixAndTargets.php |
| CloneControlLabels | Clone Trait | app/Actions/Mixes/Clone/CloneControlLabels.php |
| CloneRuleMappings | Clone Trait | app/Actions/Mixes/Clone/CloneRuleMappings.php |
| CloneCombinedOutcomes | Clone Trait | app/Actions/Mixes/Clone/CloneCombinedOutcomes.php |
| TargetMappings | DTO | app/Actions/Mixes/Clone/DTO/TargetMappings.php |
| RuleTagsController | Controller | app/Http/Controllers/RuleTagsController.php |
| SpecimensController | Controller | app/Http/Controllers/SpecimensController.php |
| TargetNameSuffixToSpecimenController | Controller | app/Http/Controllers/TargetNameSuffixToSpecimenController.php |
| RuleMapper | Action | app/Actions/AutomaticRuleMapper/RuleMapper.php |
| BaseRuleMappingGenerator | Abstract | app/Actions/AutomaticRuleMapper/Generators/BaseRuleMappingGenerator.php |
| ThresholdRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/ThresholdRuleMappingsGenerator.php |
| NegControlRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/NegControlRuleMappingsGenerator.php |
| NegICControlRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/NegICControlRuleMappingsGenerator.php |
| CLSInvertSigmoidRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/CLSInvertSigmoidRuleMappingsGenerator.php |
| ExtractionControlsRuleMappingGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/ExtractionControlsRuleMappingGenerator.php |
| AutomaticBaselineRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/AutomaticBaselineRuleMappingsGenerator.php |
| LodQualRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/LodQualRuleMappingsGenerator.php |
| LodQuantRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/LodQuantRuleMappingsGenerator.php |
| SystemRuleMappingsGenerator | Generator | app/Actions/AutomaticRuleMapper/Generators/SystemRuleMappingsGenerator.php |
| CustomRuleMapping | Model | app/CustomRuleMapping.php |
| WestgardRuleMapping | Model | app/WestgardRuleMapping.php |
| StoreTargetNameSuffixToSpecimenAction | Action | app/Actions/StoreTargetNameSuffixToSpecimenAction.php |
| DeleteSuffixMixesAndMoveWellsAction | Action | app/Actions/DeleteSuffixMixesAndMoveWellsAction.php |
| DeltaCtTargetCombinationConfigurationUpdater | Updater | app/Actions/Configurations/Updaters/DeltaCtTargetCombinationConfigurationUpdater.php |
| MixQuantitativeQualitativeSwitchAction | Action | app/Actions/Mixes/QuantitativeAndQualitativeSwitch/MixQuantitativeQualitativeSwitchAction.php |
| AutomaticRuleMappingCompleted | Notification | app/Notifications/AutomaticRuleMappingCompleted.php |
| RulesSeeder | Seeder | database/seeders/RulesSeeder.php |
8.2 Requirement Traceability
| REQ ID | Design Section | Primary Code |
|---|---|---|
| REQ-KITCFG-001 | §3.1, §5.3 | MixesController, TargetsController, GlobalMixMapper |
| REQ-KITCFG-002 | §5.1 | MixAndTargetsImportSheet, KitConfigurationsExportController |
| REQ-KITCFG-007 | §5.3 | ControlLabelsController, ControlLabelMapper |
| REQ-KITCFG-011 | §3.1 | OutcomeToLimsStatusMappingsController, CombinedOutcomesImportSheet |
| REQ-KITCFG-012 | §5.3 | WestgardSettingsController, WestgardLimitsMapper |
| REQ-KITCFG-020-023 | §5.2 | AssayCalibrateableRunsController, DxAI integration |
| REQ-KITCFG-024-025 | §5.3 | RuleMapper, RulesMappingImportSheet |
| REQ-KITCFG-027 | §2.3 (Site-Scoped) | All controllers (middleware scoping) |
| REQ-KITCFG-029 | §5.6 | DyeImportSheet, DyeExport |
| REQ-KITCFG-030 | §5.7 | WestgardEventsImportSheet, WestgardEventsExport |
| REQ-KITCFG-031 | §5.8 | SpecimensImportSheet, SpecimensExport, SpecimensController |
| REQ-KITCFG-032 | §5.9 | MixCloneController, MixCloneAction, 12 clone sub-actions |
| REQ-KITCFG-033-034 | §5.14 | Delta CT transaction pattern, UpdateDeltaCtTargetCombinationAction |
| REQ-KITCFG-035-038 | §5.12.4 | MixDataExtractor, TargetDataExtractor, MixAndTargetsImportAction |
| REQ-RULETAGS-001 through 009 | §5.11 | RuleTagsController, tag system |
| REQ-RULETAGS-010 | §5.10 | RuleMapper, generator classes, CustomRuleMapping |
| REQ-SPECIMEN-001 through 005 | §5.12.1 | SpecimensController, specimen CRUD |
| REQ-SPECIMEN-006 through 012 | §5.12.2 | TargetNameSuffixToSpecimenController, suffix mapping |
9. Design Decisions
| Decision | Rationale | Alternatives Considered |
|---|---|---|
| Excel for import/export | Customer familiarity, offline editing | JSON/YAML (rejected: less accessible), UI-only (rejected: slow for bulk) |
| Soft-disable for mixes | Preserve config for re-enable | Hard delete (rejected: loses history) |
| Synchronous cascade | Consistency, simpler error handling | Async jobs (rejected: eventual consistency issues) |
| Site-scoped at query level | Transparent multi-tenancy | Separate databases (rejected: operational complexity) |
| Preserve instruments on delete | Historical data integrity | Allow delete (rejected: breaks run references) |
| Import order enforcement | Dependency resolution | Topological sort (rejected: over-engineering) |
| Tag-driven auto-mapping (v3.1.0) | Eliminates manual rule assignment errors; tags encode intent, generators encode logic | Manual-only (rejected: error-prone at scale), per-rule config (rejected: combinatorial explosion) |
| 32 separate generator classes (v3.1.0) | Each rule category has distinct mapping logic; single class would be unmaintainable | Monolithic mapper (rejected: 2000+ LOC), config-driven (rejected: insufficiently expressive) |
hash_key deduplication on custom_rule_mappings (v3.1.0) | Prevents duplicate mappings from repeated auto-mapper runs | Unique constraint on columns (rejected: too many columns for composite key) |
| Suffix-based specimen derivation (v3.1.0) | Automates specimen association from target naming conventions | Manual per-target (rejected: tedious for large kits), regex (rejected: too complex for users) |
| Quant/Qual switch cascade (v3.1.0) | Atomic transition ensures config consistency | Manual cleanup (rejected: leaves orphaned config) |
| Delta CT transaction wrapping (v3.1.0) | Atomicity for multi-record operations; explicit user binding for audit | Per-record saves (rejected: partial update risk) |
10. Performance Considerations
| Scenario | Concern | Mitigation |
|---|---|---|
| Large import (1000+ rows) | Memory, timeout | Chunked processing, queue for very large |
| Many mixes (100+) | Dropdown render time | Paginated API, client-side caching |
| Calibration with many runs | API timeout | Progress tracking, cancellation support |
| Multi-site with many sites | Query performance | Site index on all config tables |
| Auto-mapper with 30+ generators (v3.1.0) | Execution time for full site re-mapping | Generators run only for affected rule tags; notification on completion |
| Rule Tags page with 50+ rules (v3.1.0) | Table render with multi-select dropdowns | Paginated rules fetch (2000 per page), lazy-load tag options |
| Suffix deletion with well migration (v3.1.0) | Lock contention on wells table | Transaction-scoped; runs during import (already async) |
11. Related Documents
| Document | Relevant Sections |
|---|---|
| SRS: kitcfg.md | Requirements source |
| SDS: Architecture | Multi-site architecture |
| SDS: Data Architecture | Entity model |
| SDS: RULES Domain | Rule mapping consumers |
| SDS: FILEIMPORT Domain | Mix matching |
| SDS: Combined Outcomes Rule | Outcome configuration consumers |
| SDS: CONFIGMODE Domain | Config Mode orchestration |
| SDS: CALIBRATION Domain | Calibration lifecycle |
| SDS: CONFIGIO Domain | Import/export of new sheets |