- Add OpenSpec experimental workflow with commands (opsx-apply, opsx-archive, opsx-explore, opsx-propose) - Add Serena memory system for project context - Implement User API (UserController, UserModel, routes) - Add Specimen delete endpoint - Update Test definitions and Routes - Sync API documentation (OpenAPI) - Archive completed 2026-03-08-backend-specs change
17 KiB
17 KiB
CLQMS Architecture & Codebase Structure
High-Level Architecture
CLQMS follows a clean architecture pattern with clear separation of concerns:
┌─────────────────────────────────────────────────────────────┐
│ API Consumers │
│ (Web Apps, Mobile Apps, Desktop Clients, Instruments) │
└────────────────────┬────────────────────────────────────────┘
│ HTTP/HTTPS (JSON)
┌────────────────────┴────────────────────────────────────────┐
│ REST API Layer │
│ (Controllers: Patient, Order, Specimen, Result, etc.) │
│ - JWT Authentication Filter │
│ - Request Validation │
│ - Response Formatting │
└────────────────────┬────────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────────┐
│ Business Logic Layer │
│ (Models + Libraries + Services) │
│ - ValueSet Library (JSON-based lookups) │
│ - Base Model (UTC normalization) │
│ - Edge Processing Service │
└────────────────────┬────────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────────┐
│ Data Access Layer │
│ (CodeIgniter Query Builder) │
└────────────────────┬────────────────────────────────────────┘
│
┌────────────────────┴────────────────────────────────────────┐
│ MySQL Database │
│ (Migration-managed schema) │
└─────────────────────────────────────────────────────────────┘
Directory Structure Overview
Root Directory Files
clqms01-be/
├── .env # Environment configuration
├── .gitignore # Git ignore rules
├── AGENTS.md # AI agent instructions (THIS FILE)
├── README.md # Project documentation
├── PRD.md # Product Requirements Document
├── TODO.md # Implementation tasks
├── USER_STORIES.md # User stories
├── composer.json # PHP dependencies
├── composer.lock # Locked dependency versions
├── phpunit.xml.dist # PHPUnit configuration
├── spark # CodeIgniter CLI tool
└── preload.php # PHP preloader
app/ - Application Core
app/
├── Controllers/ # API endpoint handlers
│ ├── BaseController.php # Base controller class
│ ├── AuthController.php # Authentication endpoints
│ ├── AuthV2Controller.php # V2 auth endpoints
│ ├── DashboardController.php # Dashboard data
│ ├── EdgeController.php # Instrument integration
│ ├── Patient/ # Patient management
│ │ └── PatientController.php
│ ├── Organization/ # Organization structure
│ │ ├── AccountController.php
│ │ ├── SiteController.php
│ │ ├── DisciplineController.php
│ │ ├── DepartmentController.php
│ │ └── WorkstationController.php
│ ├── Specimen/ # Specimen management
│ │ ├── SpecimenController.php
│ │ ├── SpecimenCollectionController.php
│ │ ├── SpecimenPrepController.php
│ │ ├── SpecimenStatusController.php
│ │ └── ContainerDefController.php
│ ├── OrderTest/ # Order management
│ │ └── OrderTestController.php
│ ├── Result/ # Result management
│ │ └── ResultController.php
│ ├── Test/ # Test definitions
│ │ └── TestsController.php
│ ├── Contact/ # Contact management
│ │ ├── ContactController.php
│ │ ├── OccupationController.php
│ │ └── MedicalSpecialtyController.php
│ ├── ValueSetController.php # ValueSet API endpoints
│ ├── ValueSetDefController.php # ValueSet definitions
│ ├── LocationController.php # Location management
│ ├── CounterController.php # Counter management
│ ├── PatVisitController.php # Patient visit management
│ └── SampleController.php # Sample management
│
├── Models/ # Data access layer
│ ├── BaseModel.php # Base model with UTC normalization
│ ├── Patient/ # Patient models
│ │ ├── PatientModel.php
│ │ ├── PatAttModel.php # Patient address
│ │ ├── PatComModel.php # Patient comments
│ │ └── PatIdtModel.php # Patient identifiers
│ ├── Organization/ # Organization models
│ │ ├── AccountModel.php
│ │ ├── SiteModel.php
│ │ ├── DisciplineModel.php
│ │ ├── DepartmentModel.php
│ │ └── WorkstationModel.php
│ ├── Specimen/ # Specimen models
│ │ ├── SpecimenModel.php
│ │ ├── SpecimenCollectionModel.php
│ │ ├── SpecimenPrepModel.php
│ │ ├── SpecimenStatusModel.php
│ │ └── ContainerDefModel.php
│ ├── OrderTest/ # Order models
│ │ ├── OrderTestModel.php
│ │ ├── OrderTestDetModel.php
│ │ └── OrderTestMapModel.php
│ ├── Result/ # Result models
│ │ ├── PatResultModel.php
│ │ └── ResultValueSetModel.php
│ ├── Test/ # Test models
│ │ ├── TestDefSiteModel.php
│ │ ├── TestDefTechModel.php
│ │ ├── TestDefCalModel.php
│ │ ├── TestDefGrpModel.php
│ │ └── RefNumModel.php
│ ├── Contact/ # Contact models
│ │ ├── ContactModel.php
│ │ ├── OccupationModel.php
│ │ └── MedicalSpecialtyModel.php
│ ├── ValueSet/ # ValueSet models (DB-based)
│ │ └── ValueSetModel.php
│ ├── EdgeResModel.php # Edge results
│ ├── CounterModel.php # Counter management
│ ├── PatVisitModel.php # Patient visits
│ └── ...
│
├── Libraries/ # Reusable libraries
│ ├── ValueSet.php # JSON-based lookup system
│ └── Data/ # ValueSet JSON files
│ ├── valuesets/
│ │ ├── sex.json
│ │ ├── marital_status.json
│ │ ├── race.json
│ │ ├── order_priority.json
│ │ ├── order_status.json
│ │ ├── specimen_type.json
│ │ ├── specimen_status.json
│ │ ├── result_status.json
│ │ ├── test_type.json
│ │ └── ... (many more)
│
├── Database/ # Database operations
│ ├── Migrations/ # Database schema migrations
│ │ ├── Format: YYYY-MM-DD-NNNNNN_Description.php
│ │ ├── Define up() and down() methods
│ │ └── Use $this->forge methods
│ └── Seeds/ # Database seeders
│
├── Config/ # Configuration files
│ ├── App.php # App configuration
│ ├── Database.php # Database configuration
│ ├── Routes.php # API route definitions
│ ├── Filters.php # Request filters (auth, etc.)
│ └── ...
│
├── Filters/ # Request/response filters
│ └── AuthFilter.php # JWT authentication filter
│
└── Helpers/ # Helper functions
└── utc_helper.php # UTC date conversion helpers
public/ - Public Web Root
public/
├── index.php # Front controller (entry point)
├── api-docs.yaml # OpenAPI/Swagger documentation (CRITICAL!)
├── docs.html # API documentation HTML
├── .htaccess # Apache rewrite rules
└── robots.txt # SEO robots file
tests/ - Test Suite
tests/
├── feature/ # Integration/API tests
│ ├── ContactControllerTest.php
│ ├── OrganizationControllerTest.php
│ ├── TestsControllerTest.php
│ ├── UniformShowTest.php # Tests show endpoint format
│ └── Patients/
│ └── PatientCreateTest.php
├── unit/ # Unit tests
├── _support/ # Test support utilities
└── README.md # Test documentation
vendor/ - Composer Dependencies
vendor/
├── codeigniter4/ # CodeIgniter framework
├── firebase/ # JWT library
├── phpunit/ # PHPUnit testing framework
└── ... # Other dependencies
writable/ - Writable Directory
writable/
├── cache/ # Application cache
├── logs/ # Application logs
├── session/ # Session files
└── uploads/ # File uploads
API Route Structure
Routes are defined in app/Config/Routes.php:
Public Routes (No Authentication)
/api/v2/auth/login # User login
/api/v2/auth/register # User registration
/api/demo/order # Create demo order
Authenticated Routes (JWT Required)
/api/patient # Patient CRUD
/api/patvisit # Patient visit CRUD
/api/organization/* # Organization management
/api/specimen/* # Specimen management
/api/ordertest # Order management
/api/tests # Test definitions
/api/valueset/* # ValueSet management
/api/result/* # Result management
Edge API (Instrument Integration)
POST /api/edge/results # Receive results
GET /api/edge/orders # Fetch pending orders
POST /api/edge/orders/:id/ack # Acknowledge order
POST /api/edge/status # Log instrument status
Core Design Patterns
1. BaseController Pattern
All controllers extend BaseController:
- Provides access to
$this->request,$this->response - Uses
ResponseTraitfor JSON responses - Centralizes common functionality
2. BaseModel Pattern
All models extend BaseModel:
- UTC Date Normalization: Automatically converts dates to UTC before insert/update
- ISO 8601 Output: Automatically converts dates to ISO format on retrieval
- Soft Deletes: Automatic soft delete support via
DelDatefield - Hooks: Uses
beforeInsert,beforeUpdate,afterFind, etc.
3. ValueSet Pattern
JSON-based static lookup system:
- Fast, cached lookups for static values
- Easy maintenance via JSON files
- Automatic label transformation for API responses
- Clear cache after updates
4. Controller-Model-Database Flow
HTTP Request
↓
Controller (Validation, Auth)
↓
Model (Business Logic, Data Access)
↓
Database (MySQL via Query Builder)
↓
Model (Transform, Add Labels)
↓
Controller (Format Response)
↓
JSON Response
Key Integration Points
1. JWT Authentication
- Filter:
AuthFilterinapp/Filters/ - Middleware checks JWT token from Cookie header
- Routes grouped with
'filter' => 'auth'
2. Edge API Integration
- Controller:
EdgeController.php - Models:
EdgeResModel,EdgeStatusModel,EdgeAckModel - Staging:
edgerestable for raw results - Processing: Auto or manual to
patresulttable
3. ValueSet Integration
- Library:
ValueSet.phpinapp/Libraries/ - Data: JSON files in
app/Libraries/Data/valuesets/ - Usage:
ValueSet::get('name'),ValueSet::transformLabels() - Cache: Application-level caching
4. UTC Date Handling
- Model:
BaseModel.phphandles conversion - Helper:
utc_helper.phpprovides conversion functions - Normalization: Local → UTC before DB operations
- Output: UTC → ISO 8601 for API responses
Database Schema Organization
Transactional Tables
patient- Patient registryporder- Laboratory ordersspecimen- Specimenspatresult- Patient resultspatresultdetail- Result detailspatvisit- Patient visitsedgeres- Raw instrument results
Master Data Tables
valueset- Value set valuesvaluesetdef- Value set definitionstestdefsite- Test definitionstestdeftech- Technical specstestdefcal- Calculated teststestdefgrp- Test groupsrefnum- Numeric reference rangesreftxt- Text reference ranges
Organization Tables
account- Accountssite- Sitesdiscipline- Disciplinesdepartment- Departmentsworkstation- Workstations
Integration Tables
edgestatus- Instrument statusedgeack- Order acknowledgmenttestmap- Instrument test mapping
Important Architectural Decisions
1. API-Only Design
- No view layer, no HTML rendering
- All responses are JSON
- Frontend-agnostic for maximum flexibility
2. JWT Authentication
- Stateless authentication
- Token stored in HTTP-only cookie
- 1-hour expiration (configurable)
3. Soft Deletes
- All transactional tables use
DelDate - Data preserved for audit trails
- Automatic filtering via BaseModel
4. UTC Timezone
- All database dates in UTC
- Automatic conversion via BaseModel
- ISO 8601 format for API responses
5. JSON-Based ValueSets
- Static lookups in JSON files
- Fast, cached access
- Easy to maintain and version control
6. Migration-Based Schema
- Database changes via migrations
- Version-controlled schema history
- Easy rollback capability
Critical Files to Know
| File | Purpose | Importance |
|---|---|---|
AGENTS.md |
AI agent instructions | Critical - Always read first |
app/Config/Routes.php |
API route definitions | Critical - Defines all endpoints |
public/api-docs.yaml |
OpenAPI documentation | Critical - MUST update after changes |
app/Libraries/ValueSet.php |
Lookup system | High - Used throughout |
app/Models/BaseModel.php |
Base model with UTC | High - All models extend this |
app/Filters/AuthFilter.php |
JWT authentication | High - Secures endpoints |
phpunit.xml.dist |
Test configuration | Medium - Configure database for tests |
.env |
Environment config | High - Contains secrets (JWT_SECRET, DB creds) |
Common Patterns for Code Navigation
Finding Controller for an Endpoint
- Check
app/Config/Routes.phpfor route - Find controller class in
app/Controllers/ - View controller method implementation
Finding Model for a Table
- Table name:
patient→ Model:PatientModel.php - Look in
app/Models/or subdirectories - Check
$table,$primaryKey,$allowedFields
Understanding a Feature
- Start with controller method
- Follow to model methods
- Check related models via joins
- Refer to migrations for table structure
- Check API documentation in
public/api-docs.yaml
Adding a New Endpoint
- Create controller method
- Create/update model if needed
- Add route in
app/Config/Routes.php - Write tests in
tests/feature/ - Update
public/api-docs.yaml - Run tests to verify