diff --git a/.gitignore b/.gitignore index 5b495ab..462bee8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,127 +1,127 @@ -#------------------------- -# Operating Specific Junk Files -#------------------------- - -# OS X -.DS_Store -.AppleDouble -.LSOverride - -# OS X Thumbnails -._* - -# Windows image file caches -Thumbs.db -ehthumbs.db -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# Linux -*~ - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -#------------------------- -# Environment Files -#------------------------- -# These should never be under version control, -# as it poses a security risk. -.env -.vagrant -Vagrantfile - -#------------------------- -# Temporary Files -#------------------------- -writable/cache/* -!writable/cache/index.html - -writable/logs/* -!writable/logs/index.html - -writable/session/* -!writable/session/index.html - -writable/uploads/* -!writable/uploads/index.html - -writable/debugbar/* -!writable/debugbar/.gitkeep - -php_errors.log - -#------------------------- -# User Guide Temp Files -#------------------------- -user_guide_src/build/* -user_guide_src/cilexer/build/* -user_guide_src/cilexer/dist/* -user_guide_src/cilexer/pycilexer.egg-info/* - -#------------------------- -# Test Files -#------------------------- -tests/coverage* - -# Don't save phpunit under version control. -phpunit - -#------------------------- -# Composer -#------------------------- -vendor/ - -#------------------------- -# IDE / Development Files -#------------------------- - -# Modules Testing -_modules/* - -# phpenv local config -.php-version - -# Jetbrains editors (PHPStorm, etc) -.idea/ -*.iml - -# NetBeans -/nbproject/ -/build/ -/nbbuild/ -/dist/ -/nbdist/ -/nbactions.xml -/nb-configuration.xml -/.nb-gradle/ - -# Sublime Text -*.tmlanguage.cache -*.tmPreferences.cache -*.stTheme.cache -*.sublime-workspace -*.sublime-project -.phpintel -/api/ - -# Visual Studio Code -.vscode/ - -/results/ -/phpunit*.xml +#------------------------- +# Operating Specific Junk Files +#------------------------- + +# OS X +.DS_Store +.AppleDouble +.LSOverride + +# OS X Thumbnails +._* + +# Windows image file caches +Thumbs.db +ehthumbs.db +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Linux +*~ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +#------------------------- +# Environment Files +#------------------------- +# These should never be under version control, +# as it poses a security risk. +.env +.vagrant +Vagrantfile + +#------------------------- +# Temporary Files +#------------------------- +writable/cache/* +!writable/cache/index.html + +writable/logs/* +!writable/logs/index.html + +writable/session/* +!writable/session/index.html + +writable/uploads/* +!writable/uploads/index.html + +writable/debugbar/* +!writable/debugbar/.gitkeep + +php_errors.log + +#------------------------- +# User Guide Temp Files +#------------------------- +user_guide_src/build/* +user_guide_src/cilexer/build/* +user_guide_src/cilexer/dist/* +user_guide_src/cilexer/pycilexer.egg-info/* + +#------------------------- +# Test Files +#------------------------- +tests/coverage* + +# Don't save phpunit under version control. +phpunit + +#------------------------- +# Composer +#------------------------- +vendor/ + +#------------------------- +# IDE / Development Files +#------------------------- + +# Modules Testing +_modules/* + +# phpenv local config +.php-version + +# Jetbrains editors (PHPStorm, etc) +.idea/ +*.iml + +# NetBeans +/nbproject/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/nbactions.xml +/nb-configuration.xml +/.nb-gradle/ + +# Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache +*.sublime-workspace +*.sublime-project +.phpintel +/api/ + +# Visual Studio Code +.vscode/ + +/results/ +/phpunit*.xml /public/.htaccess \ No newline at end of file diff --git a/.serena/.gitignore b/.serena/.gitignore index 2e510af..32a4ef9 100644 --- a/.serena/.gitignore +++ b/.serena/.gitignore @@ -1,2 +1,2 @@ -/cache -/project.local.yml +/cache +/project.local.yml diff --git a/.serena/memories/project_overview.md b/.serena/memories/project_overview.md index c1a0095..938f590 100644 --- a/.serena/memories/project_overview.md +++ b/.serena/memories/project_overview.md @@ -1,32 +1,32 @@ -# CLQMS Project Overview -- **Name:** CLQMS (Clinical Laboratory Quality Management System) -- **Type:** Headless REST API backend (no view layer for product UX) -- **Purpose:** Manage clinical laboratory workflows (patients, orders, specimens, results, value sets, edge/instrument integration) via JSON APIs. -- **Framework/Runtime:** CodeIgniter 4 on PHP 8.1+ -- **Database:** MySQL (legacy PascalCase column naming in many tables) -- **Auth:** JWT (firebase/php-jwt), typically required for protected `/api/*` endpoints. - -## Architecture Notes -- API-first and frontend-agnostic; clients consume REST JSON endpoints. -- Controllers delegate business logic to models/services; avoid direct DB query logic in controllers. -- Standardized response format with `status`, `message`, `data`. -- ValueSet/Lookups system supports static lookup data and API-managed lookup definitions. -- OpenAPI docs live under `public/api-docs.yaml`, `public/paths/*.yaml`, `public/components/schemas/*.yaml` and are bundled into `public/api-docs.bundled.yaml`. - -## High-Level Structure -- `app/Config` - framework and app configuration (routes, filters, etc.) -- `app/Controllers` - REST controllers -- `app/Models` - data access and DB logic -- `app/Services` - service-layer logic -- `app/Filters` - auth/request filters -- `app/Helpers` - helper functions (including UTC handling per conventions) -- `app/Libraries` - shared libraries (lookups/valuesets, etc.) -- `app/Traits` - reusable traits (including response behavior) -- `tests/feature`, `tests/unit` - PHPUnit test suites -- `public/paths`, `public/components/schemas` - modular OpenAPI source files - -## Key Dependencies -- `codeigniter4/framework` -- `firebase/php-jwt` -- `mossadal/math-parser` +# CLQMS Project Overview +- **Name:** CLQMS (Clinical Laboratory Quality Management System) +- **Type:** Headless REST API backend (no view layer for product UX) +- **Purpose:** Manage clinical laboratory workflows (patients, orders, specimens, results, value sets, edge/instrument integration) via JSON APIs. +- **Framework/Runtime:** CodeIgniter 4 on PHP 8.1+ +- **Database:** MySQL (legacy PascalCase column naming in many tables) +- **Auth:** JWT (firebase/php-jwt), typically required for protected `/api/*` endpoints. + +## Architecture Notes +- API-first and frontend-agnostic; clients consume REST JSON endpoints. +- Controllers delegate business logic to models/services; avoid direct DB query logic in controllers. +- Standardized response format with `status`, `message`, `data`. +- ValueSet/Lookups system supports static lookup data and API-managed lookup definitions. +- OpenAPI docs live under `public/api-docs.yaml`, `public/paths/*.yaml`, `public/components/schemas/*.yaml` and are bundled into `public/api-docs.bundled.yaml`. + +## High-Level Structure +- `app/Config` - framework and app configuration (routes, filters, etc.) +- `app/Controllers` - REST controllers +- `app/Models` - data access and DB logic +- `app/Services` - service-layer logic +- `app/Filters` - auth/request filters +- `app/Helpers` - helper functions (including UTC handling per conventions) +- `app/Libraries` - shared libraries (lookups/valuesets, etc.) +- `app/Traits` - reusable traits (including response behavior) +- `tests/feature`, `tests/unit` - PHPUnit test suites +- `public/paths`, `public/components/schemas` - modular OpenAPI source files + +## Key Dependencies +- `codeigniter4/framework` +- `firebase/php-jwt` +- `mossadal/math-parser` - Dev: `phpunit/phpunit`, `fakerphp/faker` \ No newline at end of file diff --git a/.serena/memories/style_and_conventions.md b/.serena/memories/style_and_conventions.md index 5179848..c6a8431 100644 --- a/.serena/memories/style_and_conventions.md +++ b/.serena/memories/style_and_conventions.md @@ -1,43 +1,43 @@ -# CLQMS Style and Conventions -## PHP and Naming -- PHP 8.1+, PSR-4 autoloading (`App\\` => `app/`, `Config\\` => `app/Config/`). -- Follow PSR-12 where applicable. -- Class names: PascalCase. -- Method names: camelCase. -- Properties: legacy snake_case and newer camelCase coexist. -- Constants: UPPER_SNAKE_CASE. -- DB tables: snake_case; many DB columns are legacy PascalCase. -- JSON fields in API responses often use PascalCase for domain fields. - -## Controller Pattern -- Controllers should handle HTTP concerns and delegate to model/service logic. -- Avoid embedding DB query logic directly inside controllers. -- Use `ResponseTrait` and consistent JSON envelope responses. - -## Response Pattern -- Success: `status=success`, plus message/data. -- Error: structured error response with proper HTTP status codes. -- Empty strings may be normalized to `null` by custom response behavior. - -## DB and Data Handling -- Prefer CodeIgniter Model/Query Builder usage. -- Use UTC helper conventions for datetime handling. -- Multi-table writes should be wrapped in transactions. -- For nested entities/arrays, extract and handle nested payloads carefully before filtering and persistence. - -## Error Handling -- Use try/catch for JWT and external operations. -- Log errors with `log_message('error', ...)`. -- Return structured API errors with correct status codes. - -## Testing Convention -- PHPUnit tests in `tests/`. -- Test naming: `test`. -- Typical status expectation: 200 (GET/PATCH), 201 (POST), 400/401/404/500 as appropriate. - -## API Docs Rule (Critical) -- Any controller/API contract change must update corresponding OpenAPI YAML files under: - - `public/paths/*.yaml` - - `public/components/schemas/*.yaml` - - optionally `public/api-docs.yaml` if references/tags change +# CLQMS Style and Conventions +## PHP and Naming +- PHP 8.1+, PSR-4 autoloading (`App\\` => `app/`, `Config\\` => `app/Config/`). +- Follow PSR-12 where applicable. +- Class names: PascalCase. +- Method names: camelCase. +- Properties: legacy snake_case and newer camelCase coexist. +- Constants: UPPER_SNAKE_CASE. +- DB tables: snake_case; many DB columns are legacy PascalCase. +- JSON fields in API responses often use PascalCase for domain fields. + +## Controller Pattern +- Controllers should handle HTTP concerns and delegate to model/service logic. +- Avoid embedding DB query logic directly inside controllers. +- Use `ResponseTrait` and consistent JSON envelope responses. + +## Response Pattern +- Success: `status=success`, plus message/data. +- Error: structured error response with proper HTTP status codes. +- Empty strings may be normalized to `null` by custom response behavior. + +## DB and Data Handling +- Prefer CodeIgniter Model/Query Builder usage. +- Use UTC helper conventions for datetime handling. +- Multi-table writes should be wrapped in transactions. +- For nested entities/arrays, extract and handle nested payloads carefully before filtering and persistence. + +## Error Handling +- Use try/catch for JWT and external operations. +- Log errors with `log_message('error', ...)`. +- Return structured API errors with correct status codes. + +## Testing Convention +- PHPUnit tests in `tests/`. +- Test naming: `test`. +- Typical status expectation: 200 (GET/PATCH), 201 (POST), 400/401/404/500 as appropriate. + +## API Docs Rule (Critical) +- Any controller/API contract change must update corresponding OpenAPI YAML files under: + - `public/paths/*.yaml` + - `public/components/schemas/*.yaml` + - optionally `public/api-docs.yaml` if references/tags change - Rebuild docs bundle after YAML updates. \ No newline at end of file diff --git a/.serena/memories/suggested_commands.md b/.serena/memories/suggested_commands.md index e406b0e..b57344b 100644 --- a/.serena/memories/suggested_commands.md +++ b/.serena/memories/suggested_commands.md @@ -1,32 +1,32 @@ -# Suggested Commands (Windows) -## Core Project Commands -- Install dependencies: `composer install` -- Run all tests: `./vendor/bin/phpunit` -- Run one test file: `./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php` -- Run one test method: `./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php` -- Run test suite: `./vendor/bin/phpunit --testsuite App` -- Run with coverage: `./vendor/bin/phpunit --coverage-html build/logs/html` - -## CodeIgniter/Spark Commands -- Create migration: `php spark make:migration ` -- Create model: `php spark make:model ` -- Create controller: `php spark make:controller ` -- Apply migrations: `php spark migrate` -- Rollback migrations: `php spark migrate:rollback` -- Run local app: `php spark serve` - -## OpenAPI Docs Commands -- Rebundle API docs after YAML changes: `node public/bundle-api-docs.js` - -## Git and Shell Utilities (Windows) -- Git status: `git status` -- Diff changes: `git diff` -- Show staged diff: `git diff --cached` -- Recent commits: `git log --oneline -n 10` -- List files (PowerShell): `Get-ChildItem` -- Recursive file search (PowerShell): `Get-ChildItem -Recurse -File` -- Text search (PowerShell): `Select-String -Path .\* -Pattern "" -Recurse` - -## Notes -- Testing DB values in `phpunit.xml.dist` are environment-specific; verify before running tests. +# Suggested Commands (Windows) +## Core Project Commands +- Install dependencies: `composer install` +- Run all tests: `./vendor/bin/phpunit` +- Run one test file: `./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php` +- Run one test method: `./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php` +- Run test suite: `./vendor/bin/phpunit --testsuite App` +- Run with coverage: `./vendor/bin/phpunit --coverage-html build/logs/html` + +## CodeIgniter/Spark Commands +- Create migration: `php spark make:migration ` +- Create model: `php spark make:model ` +- Create controller: `php spark make:controller ` +- Apply migrations: `php spark migrate` +- Rollback migrations: `php spark migrate:rollback` +- Run local app: `php spark serve` + +## OpenAPI Docs Commands +- Rebundle API docs after YAML changes: `node public/bundle-api-docs.js` + +## Git and Shell Utilities (Windows) +- Git status: `git status` +- Diff changes: `git diff` +- Show staged diff: `git diff --cached` +- Recent commits: `git log --oneline -n 10` +- List files (PowerShell): `Get-ChildItem` +- Recursive file search (PowerShell): `Get-ChildItem -Recurse -File` +- Text search (PowerShell): `Select-String -Path .\* -Pattern "" -Recurse` + +## Notes +- Testing DB values in `phpunit.xml.dist` are environment-specific; verify before running tests. - API docs bundle output file: `public/api-docs.bundled.yaml`. \ No newline at end of file diff --git a/.serena/memories/task_completion_checklist.md b/.serena/memories/task_completion_checklist.md index e89d338..3c69ed9 100644 --- a/.serena/memories/task_completion_checklist.md +++ b/.serena/memories/task_completion_checklist.md @@ -1,9 +1,9 @@ -# Task Completion Checklist -When finishing a coding change in CLQMS: - -1. Run targeted tests first (file/method-level), then broader PHPUnit suite if scope warrants it. -2. Verify API response structure consistency (`status`, `message`, `data`) and proper HTTP status codes. -3. If controllers or API contracts changed, update OpenAPI YAML files in `public/paths` and/or `public/components/schemas`. -4. Rebundle OpenAPI docs with `node public/bundle-api-docs.js` after YAML updates. -5. Confirm no secrets/credentials were introduced in tracked files. +# Task Completion Checklist +When finishing a coding change in CLQMS: + +1. Run targeted tests first (file/method-level), then broader PHPUnit suite if scope warrants it. +2. Verify API response structure consistency (`status`, `message`, `data`) and proper HTTP status codes. +3. If controllers or API contracts changed, update OpenAPI YAML files in `public/paths` and/or `public/components/schemas`. +4. Rebundle OpenAPI docs with `node public/bundle-api-docs.js` after YAML updates. +5. Confirm no secrets/credentials were introduced in tracked files. 6. Review diff for legacy field naming compatibility (PascalCase DB columns/JSON domain fields where expected). \ No newline at end of file diff --git a/.serena/project.yml b/.serena/project.yml index 6d9bc7e..2db9369 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -1,135 +1,135 @@ -# the name by which the project can be referenced within Serena -project_name: "clqms01-be" - - -# list of languages for which language servers are started; choose from: -# al bash clojure cpp csharp -# csharp_omnisharp dart elixir elm erlang -# fortran fsharp go groovy haskell -# java julia kotlin lua markdown -# matlab nix pascal perl php -# php_phpactor powershell python python_jedi r -# rego ruby ruby_solargraph rust scala -# swift terraform toml typescript typescript_vts -# vue yaml zig -# (This list may be outdated. For the current list, see values of Language enum here: -# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py -# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) -# Note: -# - For C, use cpp -# - For JavaScript, use typescript -# - For Free Pascal/Lazarus, use pascal -# Special requirements: -# Some languages require additional setup/installations. -# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers -# When using multiple languages, the first language server that supports a given file will be used for that file. -# The first language is the default language and the respective language server will be used as a fallback. -# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. -languages: -- php - -# the encoding used by text files in the project -# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings -encoding: "utf-8" - -# line ending convention to use when writing source files. -# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) -# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. -line_ending: - -# The language backend to use for this project. -# If not set, the global setting from serena_config.yml is used. -# Valid values: LSP, JetBrains -# Note: the backend is fixed at startup. If a project with a different backend -# is activated post-init, an error will be returned. -language_backend: - -# whether to use project's .gitignore files to ignore files -ignore_all_files_in_gitignore: true - -# list of additional paths to ignore in this project. -# Same syntax as gitignore, so you can use * and **. -# Note: global ignored_paths from serena_config.yml are also applied additively. -ignored_paths: [] - -# whether the project is in read-only mode -# If set to true, all editing tools will be disabled and attempts to use them will result in an error -# Added on 2025-04-18 -read_only: false - -# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. -# Below is the complete list of tools for convenience. -# To make sure you have the latest list of tools, and to view their descriptions, -# execute `uv run scripts/print_tool_overview.py`. -# -# * `activate_project`: Activates a project by name. -# * `check_onboarding_performed`: Checks whether project onboarding was already performed. -# * `create_text_file`: Creates/overwrites a file in the project directory. -# * `delete_lines`: Deletes a range of lines within a file. -# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. -# * `execute_shell_command`: Executes a shell command. -# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. -# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). -# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). -# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. -# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. -# * `initial_instructions`: Gets the initial instructions for the current project. -# Should only be used in settings where the system prompt cannot be set, -# e.g. in clients you have no control over, like Claude Desktop. -# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. -# * `insert_at_line`: Inserts content at a given line in a file. -# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. -# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). -# * `list_memories`: Lists memories in Serena's project-specific memory store. -# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). -# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). -# * `read_file`: Reads a file within the project directory. -# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. -# * `remove_project`: Removes a project from the Serena configuration. -# * `replace_lines`: Replaces a range of lines within a file with new content. -# * `replace_symbol_body`: Replaces the full definition of a symbol. -# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. -# * `search_for_pattern`: Performs a search for a pattern in the project. -# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. -# * `switch_modes`: Activates modes by providing a list of their names -# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. -# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. -# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. -# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. -excluded_tools: [] - -# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default) -included_optional_tools: [] - -# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. -# This cannot be combined with non-empty excluded_tools or included_optional_tools. -fixed_tools: [] - -# list of mode names to that are always to be included in the set of active modes -# The full set of modes to be activated is base_modes + default_modes. -# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this setting overrides the global configuration. -# Set this to [] to disable base modes for this project. -# Set this to a list of mode names to always include the respective modes for this project. -base_modes: - -# list of mode names that are to be activated by default. -# The full set of modes to be activated is base_modes + default_modes. -# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this overrides the setting from the global configuration (serena_config.yml). -# This setting can, in turn, be overridden by CLI parameters (--mode). -default_modes: - -# initial prompt for the project. It will always be given to the LLM upon activating the project -# (contrary to the memories, which are loaded on demand). -initial_prompt: "" - -# time budget (seconds) per tool call for the retrieval of additional symbol information -# such as docstrings or parameter information. -# This overrides the corresponding setting in the global configuration; see the documentation there. -# If null or missing, use the setting from the global configuration. -symbol_info_budget: - -# list of regex patterns which, when matched, mark a memory entry as read‑only. -# Extends the list from the global configuration, merging the two lists. -read_only_memory_patterns: [] +# the name by which the project can be referenced within Serena +project_name: "clqms01-be" + + +# list of languages for which language servers are started; choose from: +# al bash clojure cpp csharp +# csharp_omnisharp dart elixir elm erlang +# fortran fsharp go groovy haskell +# java julia kotlin lua markdown +# matlab nix pascal perl php +# php_phpactor powershell python python_jedi r +# rego ruby ruby_solargraph rust scala +# swift terraform toml typescript typescript_vts +# vue yaml zig +# (This list may be outdated. For the current list, see values of Language enum here: +# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py +# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) +# Note: +# - For C, use cpp +# - For JavaScript, use typescript +# - For Free Pascal/Lazarus, use pascal +# Special requirements: +# Some languages require additional setup/installations. +# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers +# When using multiple languages, the first language server that supports a given file will be used for that file. +# The first language is the default language and the respective language server will be used as a fallback. +# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. +languages: +- php + +# the encoding used by text files in the project +# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings +encoding: "utf-8" + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# The language backend to use for this project. +# If not set, the global setting from serena_config.yml is used. +# Valid values: LSP, JetBrains +# Note: the backend is fixed at startup. If a project with a different backend +# is activated post-init, an error will be returned. +language_backend: + +# whether to use project's .gitignore files to ignore files +ignore_all_files_in_gitignore: true + +# list of additional paths to ignore in this project. +# Same syntax as gitignore, so you can use * and **. +# Note: global ignored_paths from serena_config.yml are also applied additively. +ignored_paths: [] + +# whether the project is in read-only mode +# If set to true, all editing tools will be disabled and attempts to use them will result in an error +# Added on 2025-04-18 +read_only: false + +# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. +# Below is the complete list of tools for convenience. +# To make sure you have the latest list of tools, and to view their descriptions, +# execute `uv run scripts/print_tool_overview.py`. +# +# * `activate_project`: Activates a project by name. +# * `check_onboarding_performed`: Checks whether project onboarding was already performed. +# * `create_text_file`: Creates/overwrites a file in the project directory. +# * `delete_lines`: Deletes a range of lines within a file. +# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `execute_shell_command`: Executes a shell command. +# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. +# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). +# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. +# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. +# * `initial_instructions`: Gets the initial instructions for the current project. +# Should only be used in settings where the system prompt cannot be set, +# e.g. in clients you have no control over, like Claude Desktop. +# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. +# * `insert_at_line`: Inserts content at a given line in a file. +# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. +# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). +# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). +# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). +# * `read_file`: Reads a file within the project directory. +# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. +# * `remove_project`: Removes a project from the Serena configuration. +# * `replace_lines`: Replaces a range of lines within a file with new content. +# * `replace_symbol_body`: Replaces the full definition of a symbol. +# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `search_for_pattern`: Performs a search for a pattern in the project. +# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. +# * `switch_modes`: Activates modes by providing a list of their names +# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. +# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. +# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. +# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +excluded_tools: [] + +# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default) +included_optional_tools: [] + +# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. +# This cannot be combined with non-empty excluded_tools or included_optional_tools. +fixed_tools: [] + +# list of mode names to that are always to be included in the set of active modes +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this setting overrides the global configuration. +# Set this to [] to disable base modes for this project. +# Set this to a list of mode names to always include the respective modes for this project. +base_modes: + +# list of mode names that are to be activated by default. +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this overrides the setting from the global configuration (serena_config.yml). +# This setting can, in turn, be overridden by CLI parameters (--mode). +default_modes: + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +# time budget (seconds) per tool call for the retrieval of additional symbol information +# such as docstrings or parameter information. +# This overrides the corresponding setting in the global configuration; see the documentation there. +# If null or missing, use the setting from the global configuration. +symbol_info_budget: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] diff --git a/AGENTS.md b/AGENTS.md index 54c3ddb..5f508bc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,316 +1,316 @@ -# AGENTS.md - Code Guidelines for CLQMS - -> **CLQMS (Clinical Laboratory Quality Management System)** - A headless REST API backend for clinical laboratory workflows built with CodeIgniter 4. - ---- - -## Build, Test & Lint Commands - -```bash -# Run all tests -./vendor/bin/phpunit - -# Run a specific test file -./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php - -# Run a specific test method -./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php - -# Run tests with coverage -./vendor/bin/phpunit --coverage-html build/logs/html - -# Run tests by suite -./vendor/bin/phpunit --testsuite App - -# Generate scaffolding -php spark make:migration -php spark make:model -php spark make:controller - -# Database migrations -php spark migrate -php spark migrate:rollback -``` - ---- - -## Code Style Guidelines - -### PHP Standards -- **PHP Version**: 8.1+ -- **PSR-4 Autoloading**: `App\` maps to `app/`, `Config\` maps to `app/Config/` -- **PSR-12 Coding Style** (follow where applicable) - -### Naming Conventions - -| Element | Convention | Example | -|---------|-----------|---------| -| Classes | PascalCase | `PatientController` | -| Methods | camelCase | `createPatient()` | -| Properties | snake_case (legacy) / camelCase (new) | `$patient_id` / `$patientId` | -| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` | -| Tables | snake_case | `patient_visits` | -| Columns | PascalCase (legacy) | `PatientID`, `NameFirst` | -| JSON fields | PascalCase | `"PatientID": "123"` | - -### Imports & Namespaces -- Fully qualified namespaces at the top -- Group imports: Framework first, then App, then external -- Alphabetical order within groups - -```php -model = new \App\Models\ExampleModel(); - } - - public function index() - { - $data = $this->model->findAll(); - return $this->respond(['status' => 'success', 'data' => $data], 200); - } - - public function create() - { - $data = $this->request->getJSON(true); - $result = $this->model->createWithRelations($data); - return $this->respond(['status' => 'success', 'data' => $result], 201); - } -} -``` - -### Response Format -All API responses use standardized format: - -```php -// Success -return $this->respond([ - 'status' => 'success', - 'message' => 'Operation completed', - 'data' => $data -], 200); - -// Error -return $this->respond([ - 'status' => 'failed', - 'message' => 'Error description', - 'data' => [] -], 400); -``` - -**Note**: Custom `ResponseTrait` automatically converts empty strings to `null`. - -### Error Handling -- Use try-catch for JWT and external calls -- Log errors: `log_message('error', $message)` -- Return structured error responses with appropriate HTTP status codes - -```php -try { - $decoded = JWT::decode($token, new Key($key, 'HS256')); -} catch (\Firebase\JWT\ExpiredException $e) { - return $this->respond(['status' => 'failed', 'message' => 'Token expired'], 401); -} catch (\Exception $e) { - return $this->respond(['status' => 'failed', 'message' => 'Invalid token'], 401); -} -``` - -### Database Operations -- Use CodeIgniter Query Builder or Model methods -- Use `helper('utc')` for UTC date conversion -- Wrap multi-table operations in transactions - -```php -$this->db->transStart(); -// ... database operations -$this->db->transComplete(); - -if ($this->db->transStatus() === false) { - return $this->respond(['status' => 'error', 'message' => 'Transaction failed'], 500); -} -``` - -### Model Patterns -- Extend `BaseModel` for automatic UTC date handling -- Use `checkDbError()` for database error detection - -```php -error(); - if (!empty($error['code'])) { - throw new \Exception("{$context} failed: {$error['code']} - {$error['message']}"); - } - } -} -``` - -### Testing Guidelines - -```php -withBodyFormat('json')->post($this->endpoint, $payload); - $result->assertStatus(201); - } -} -``` - -**Test Naming**: `test` (e.g., `testCreatePatientValidationFail`) - -**Test Status Codes**: 200 (GET/PATCH), 201 (POST), 400 (Validation), 401 (Unauthorized), 404 (Not Found), 500 (Server Error) - -### API Design -- **Base URL**: `/api/` -- **Authentication**: JWT token via HttpOnly cookie -- **Content-Type**: `application/json` -- **Methods**: GET (read), POST (create), PATCH (partial update), DELETE (delete) - -### Routes Pattern -```php -$routes->group('api/patient', function ($routes) { - $routes->get('/', 'Patient\PatientController::index'); - $routes->post('/', 'Patient\PatientController::create'); - $routes->get('(:num)', 'Patient\PatientController::show/$1'); - $routes->patch('/', 'Patient\PatientController::update'); - $routes->delete('/', 'Patient\PatientController::delete'); -}); -``` - -### Security -- Use `auth` filter for protected routes -- Sanitize user inputs -- Use parameterized queries -- Store secrets in `.env`, never commit - ---- - -## Project-Specific Conventions - -### API Documentation Sync -**CRITICAL**: When updating any controller, you MUST also update the corresponding OpenAPI YAML documentation: - -- **Paths**: `public/paths/.yaml` (e.g., `patients.yaml`, `orders.yaml`) -- **Schemas**: `public/components/schemas/.yaml` -- **Main file**: `public/api-docs.yaml` (for tags and schema references) - -**After updating YAML files**, regenerate the bundled documentation: -```bash -node public/bundle-api-docs.js -``` - -This produces `public/api-docs.bundled.yaml` which is used by Swagger UI/Redoc. - -### Controller-to-YAML Mapping -| Controller | YAML Path File | YAML Schema File | -|-----------|----------------|------------------| -| `PatientController` | `paths/patients.yaml` | `components/schemas/patient.yaml` | -| `PatVisitController` | `paths/patient-visits.yaml` | `components/schemas/patient-visit.yaml` | -| `OrderTestController` | `paths/orders.yaml` | `components/schemas/orders.yaml` | -| `SpecimenController` | `paths/specimen.yaml` | `components/schemas/specimen.yaml` | -| `TestsController` | `paths/tests.yaml` | `components/schemas/tests.yaml` | -| `AuthController` | `paths/authentication.yaml` | `components/schemas/authentication.yaml` | -| `ResultController` | `paths/results.yaml` | `components/schemas/*.yaml` | -| `EdgeController` | `paths/edge-api.yaml` | `components/schemas/edge-api.yaml` | -| `LocationController` | `paths/locations.yaml` | `components/schemas/master-data.yaml` | -| `ValueSetController` | `paths/valuesets.yaml` | `components/schemas/valuesets.yaml` | -| `ContactController` | `paths/contact.yaml` | (inline schemas) | - -### Legacy Field Naming -Database uses PascalCase columns: `PatientID`, `NameFirst`, `Birthdate`, `CreatedAt`, `UpdatedAt` - -### ValueSet System -```php -use App\Libraries\Lookups; - -$genders = Lookups::get('gender'); -$label = Lookups::getLabel('gender', '1'); // Returns 'Female' -$options = Lookups::getOptions('gender'); -$labeled = Lookups::transformLabels($data, ['Sex' => 'gender']); -``` - -### Nested Data Handling -For entities with nested data (PatIdt, PatCom, PatAtt): -- Extract nested arrays before filtering -- Use transactions for multi-table operations -- Handle empty/null arrays appropriately - ---- - -## Environment Configuration - -### Database (`.env`) -```ini -database.default.hostname = localhost -database.default.database = clqms01 -database.default.username = root -database.default.password = adminsakti -database.default.DBDriver = MySQLi -``` - -### JWT Secret (`.env`) -```ini -JWT_SECRET = '5pandaNdutNdut' -``` - ---- - -## Additional Notes - -- **API-Only**: No view layer - headless REST API -- **Frontend Agnostic**: Any client can consume these APIs -- **Stateless**: JWT-based authentication per request -- **UTC Dates**: All dates stored in UTC, converted for display - -*© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.* +# AGENTS.md - Code Guidelines for CLQMS + +> **CLQMS (Clinical Laboratory Quality Management System)** - A headless REST API backend for clinical laboratory workflows built with CodeIgniter 4. + +--- + +## Build, Test & Lint Commands + +```bash +# Run all tests +./vendor/bin/phpunit + +# Run a specific test file +./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php + +# Run a specific test method +./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php + +# Run tests with coverage +./vendor/bin/phpunit --coverage-html build/logs/html + +# Run tests by suite +./vendor/bin/phpunit --testsuite App + +# Generate scaffolding +php spark make:migration +php spark make:model +php spark make:controller + +# Database migrations +php spark migrate +php spark migrate:rollback +``` + +--- + +## Code Style Guidelines + +### PHP Standards +- **PHP Version**: 8.1+ +- **PSR-4 Autoloading**: `App\` maps to `app/`, `Config\` maps to `app/Config/` +- **PSR-12 Coding Style** (follow where applicable) + +### Naming Conventions + +| Element | Convention | Example | +|---------|-----------|---------| +| Classes | PascalCase | `PatientController` | +| Methods | camelCase | `createPatient()` | +| Properties | snake_case (legacy) / camelCase (new) | `$patient_id` / `$patientId` | +| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` | +| Tables | snake_case | `patient_visits` | +| Columns | PascalCase (legacy) | `PatientID`, `NameFirst` | +| JSON fields | PascalCase | `"PatientID": "123"` | + +### Imports & Namespaces +- Fully qualified namespaces at the top +- Group imports: Framework first, then App, then external +- Alphabetical order within groups + +```php +model = new \App\Models\ExampleModel(); + } + + public function index() + { + $data = $this->model->findAll(); + return $this->respond(['status' => 'success', 'data' => $data], 200); + } + + public function create() + { + $data = $this->request->getJSON(true); + $result = $this->model->createWithRelations($data); + return $this->respond(['status' => 'success', 'data' => $result], 201); + } +} +``` + +### Response Format +All API responses use standardized format: + +```php +// Success +return $this->respond([ + 'status' => 'success', + 'message' => 'Operation completed', + 'data' => $data +], 200); + +// Error +return $this->respond([ + 'status' => 'failed', + 'message' => 'Error description', + 'data' => [] +], 400); +``` + +**Note**: Custom `ResponseTrait` automatically converts empty strings to `null`. + +### Error Handling +- Use try-catch for JWT and external calls +- Log errors: `log_message('error', $message)` +- Return structured error responses with appropriate HTTP status codes + +```php +try { + $decoded = JWT::decode($token, new Key($key, 'HS256')); +} catch (\Firebase\JWT\ExpiredException $e) { + return $this->respond(['status' => 'failed', 'message' => 'Token expired'], 401); +} catch (\Exception $e) { + return $this->respond(['status' => 'failed', 'message' => 'Invalid token'], 401); +} +``` + +### Database Operations +- Use CodeIgniter Query Builder or Model methods +- Use `helper('utc')` for UTC date conversion +- Wrap multi-table operations in transactions + +```php +$this->db->transStart(); +// ... database operations +$this->db->transComplete(); + +if ($this->db->transStatus() === false) { + return $this->respond(['status' => 'error', 'message' => 'Transaction failed'], 500); +} +``` + +### Model Patterns +- Extend `BaseModel` for automatic UTC date handling +- Use `checkDbError()` for database error detection + +```php +error(); + if (!empty($error['code'])) { + throw new \Exception("{$context} failed: {$error['code']} - {$error['message']}"); + } + } +} +``` + +### Testing Guidelines + +```php +withBodyFormat('json')->post($this->endpoint, $payload); + $result->assertStatus(201); + } +} +``` + +**Test Naming**: `test` (e.g., `testCreatePatientValidationFail`) + +**Test Status Codes**: 200 (GET/PATCH), 201 (POST), 400 (Validation), 401 (Unauthorized), 404 (Not Found), 500 (Server Error) + +### API Design +- **Base URL**: `/api/` +- **Authentication**: JWT token via HttpOnly cookie +- **Content-Type**: `application/json` +- **Methods**: GET (read), POST (create), PATCH (partial update), DELETE (delete) + +### Routes Pattern +```php +$routes->group('api/patient', function ($routes) { + $routes->get('/', 'Patient\PatientController::index'); + $routes->post('/', 'Patient\PatientController::create'); + $routes->get('(:num)', 'Patient\PatientController::show/$1'); + $routes->patch('/', 'Patient\PatientController::update'); + $routes->delete('/', 'Patient\PatientController::delete'); +}); +``` + +### Security +- Use `auth` filter for protected routes +- Sanitize user inputs +- Use parameterized queries +- Store secrets in `.env`, never commit + +--- + +## Project-Specific Conventions + +### API Documentation Sync +**CRITICAL**: When updating any controller, you MUST also update the corresponding OpenAPI YAML documentation: + +- **Paths**: `public/paths/.yaml` (e.g., `patients.yaml`, `orders.yaml`) +- **Schemas**: `public/components/schemas/.yaml` +- **Main file**: `public/api-docs.yaml` (for tags and schema references) + +**After updating YAML files**, regenerate the bundled documentation: +```bash +node public/bundle-api-docs.js +``` + +This produces `public/api-docs.bundled.yaml` which is used by Swagger UI/Redoc. + +### Controller-to-YAML Mapping +| Controller | YAML Path File | YAML Schema File | +|-----------|----------------|------------------| +| `PatientController` | `paths/patients.yaml` | `components/schemas/patient.yaml` | +| `PatVisitController` | `paths/patient-visits.yaml` | `components/schemas/patient-visit.yaml` | +| `OrderTestController` | `paths/orders.yaml` | `components/schemas/orders.yaml` | +| `SpecimenController` | `paths/specimen.yaml` | `components/schemas/specimen.yaml` | +| `TestsController` | `paths/tests.yaml` | `components/schemas/tests.yaml` | +| `AuthController` | `paths/authentication.yaml` | `components/schemas/authentication.yaml` | +| `ResultController` | `paths/results.yaml` | `components/schemas/*.yaml` | +| `EdgeController` | `paths/edge-api.yaml` | `components/schemas/edge-api.yaml` | +| `LocationController` | `paths/locations.yaml` | `components/schemas/master-data.yaml` | +| `ValueSetController` | `paths/valuesets.yaml` | `components/schemas/valuesets.yaml` | +| `ContactController` | `paths/contact.yaml` | (inline schemas) | + +### Legacy Field Naming +Database uses PascalCase columns: `PatientID`, `NameFirst`, `Birthdate`, `CreatedAt`, `UpdatedAt` + +### ValueSet System +```php +use App\Libraries\Lookups; + +$genders = Lookups::get('gender'); +$label = Lookups::getLabel('gender', '1'); // Returns 'Female' +$options = Lookups::getOptions('gender'); +$labeled = Lookups::transformLabels($data, ['Sex' => 'gender']); +``` + +### Nested Data Handling +For entities with nested data (PatIdt, PatCom, PatAtt): +- Extract nested arrays before filtering +- Use transactions for multi-table operations +- Handle empty/null arrays appropriately + +--- + +## Environment Configuration + +### Database (`.env`) +```ini +database.default.hostname = localhost +database.default.database = clqms01 +database.default.username = root +database.default.password = adminsakti +database.default.DBDriver = MySQLi +``` + +### JWT Secret (`.env`) +```ini +JWT_SECRET = '5pandaNdutNdut' +``` + +--- + +## Additional Notes + +- **API-Only**: No view layer - headless REST API +- **Frontend Agnostic**: Any client can consume these APIs +- **Stateless**: JWT-based authentication per request +- **UTC Dates**: All dates stored in UTC, converted for display + +*© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.* diff --git a/LICENSE b/LICENSE index 24728f6..aefe3d4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,22 @@ -The MIT License (MIT) - -Copyright (c) 2014-2019 British Columbia Institute of Technology -Copyright (c) 2019-present CodeIgniter Foundation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The MIT License (MIT) + +Copyright (c) 2014-2019 British Columbia Institute of Technology +Copyright (c) 2019-present CodeIgniter Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 4a9f9b1..f8a3f56 100644 --- a/README.md +++ b/README.md @@ -1,553 +1,553 @@ -# CLQMS (Clinical Laboratory Quality Management System) - -> **A REST API backend for modern clinical laboratory workflows.** - ---- - -## 🤖 For Claude Code - -**When working in this repository, prioritize Serena MCP tools for code operations:** - -- **Use `find_symbol` / `get_symbols_overview`** instead of `Read` for exploring code structure -- **Use `replace_symbol_body`** instead of `Edit` for modifying functions, methods, classes -- **Use `insert_before_symbol` / `insert_after_symbol`** for adding new code symbols -- **Use `search_for_pattern`** instead of `Grep` for searching code patterns -- **Use `list_dir` / `find_file`** instead of `Glob` for file discovery - -This minimizes tool calls and leverages semantic code understanding for this PHP codebase. - ---- - -CLQMS is a **headless REST API backend** designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system provides comprehensive JSON endpoints for laboratory operations. - -**Key Characteristic:** This is an **API-only system** with no view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems. - ---- - -## 🏛️ Core Architecture & Design - -CLQMS is a **headless REST API system** following a clean architecture pattern. The system is designed to be consumed by any frontend client (web, mobile, desktop) through comprehensive JSON endpoints. - -**API-First Architecture:** -- **No View Layer:** This system provides REST APIs only - no HTML views, no server-side rendering -- **Frontend Agnostic:** Any client can consume these APIs (React, Vue, Angular, mobile apps, desktop apps) -- **JSON-First:** All requests/responses use JSON format -- **Stateless:** Each API request is independent with JWT authentication - -The system is currently undergoing a strategic **Architectural Redesign** to consolidate legacy structures into a high-performance, maintainable schema. This design focuses on reducing technical debt and improving data consistency across: - -- **Unified Test Definitions:** Consolidating technical, calculated, and site-specific test data. -- **Reference Range Centralization:** A unified engine for numeric, threshold, text, and coded results. -- **Ordered Workflow Management:** Precise tracking of orders from collection to verification. - ---- - -## 🛡️ Strategic Pillars - -- **Precision & Accuracy:** Strict validation for all laboratory parameters and reference ranges. -- **Scalability:** Optimized for high-volume diagnostic environments. -- **Compliance:** Built-in audit trails and status history for full traceability. -- **Interoperability:** Modular architecture designed for LIS, HIS, and analyzer integrations. - ---- - -## 🛠️ Technical Stack - -| Component | Specification | -| :------------- | :------------ | -| **Language** | PHP 8.1+ (PSR-compliant) | -| **Framework** | CodeIgniter 4 (API-only mode) | -| **Security** | JWT (JSON Web Tokens) Authorization | -| **Database** | MySQL (Optimized Schema Migration in progress) | -| **API Format** | RESTful JSON | -| **Testing** | PHPUnit 10.5+ | - - ---- - -## 📂 Documentation & Specifications - -### Key Documents - -| Document | Location | Description | -|----------|----------|-------------| -| **PRD** | `PRD.md` | Complete Product Requirements Document (API-focused) | -| **Technical Guide** | `CLAUDE.md` | Architecture, coding standards, common commands | -| **API Overview** | This file | REST API documentation and endpoints | -| **Database Migrations** | `app/Database/Migrations/` | Database schema history | - -### API Documentation - -All API endpoints follow REST conventions: - -**Base URL:** `/api` - -**Authentication:** JWT token required for most endpoints (except `/api/login`, `/api/demo/*`) - -**Response Format:** -```json -{ - "status": "success|error", - "message": "Human-readable message", - "data": { ... } -} -``` - ---- - -## 🔌 REST API Overview - -### API Endpoint Categories - -#### Authentication & Authorization - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `POST` | `/api/login` | User login, returns JWT token | No | -| `POST` | `/api/logout` | Invalidate JWT token | Yes | -| `POST` | `/api/refresh` | Refresh JWT token | Yes | - -#### Patient Management - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `GET` | `/api/patient` | List patients with pagination | Yes | -| `GET` | `/api/patient/{id}` | Get patient details | Yes | -| `POST` | `/api/patient` | Create new patient | Yes | -| `PATCH` | `/api/patient/{id}` | Update patient | Yes | -| `DELETE` | `/api/patient/{id}` | Soft delete patient | Yes | - -#### Order Management - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `GET` | `/api/ordertest` | List orders | Yes | -| `GET` | `/api/ordertest/{id}` | Get order details | Yes | -| `POST` | `/api/ordertest` | Create order | Yes | -| `PATCH` | `/api/ordertest/{id}` | Update order | Yes | -| `DELETE` | `/api/ordertest/{id}` | Delete order | Yes | -| `POST` | `/api/ordertest/status` | Update order status | Yes | - -#### Demo/Test Endpoints (No Auth) - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `POST` | `/api/demo/order` | Create demo order with patient | No | - -#### Specimen Management - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `GET` | `/api/specimen` | List specimens | Yes | -| `GET` | `/api/specimen/{id}` | Get specimen details | Yes | -| `POST` | `/api/specimen` | Create specimen | Yes | -| `PATCH` | `/api/specimen/{id}` | Update specimen | Yes | -| `POST` | `/api/specimen/status` | Update specimen status | Yes | - -#### Result Management - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `GET` | `/api/patresult` | List patient results | Yes | -| `GET` | `/api/patresult/{id}` | Get result details | Yes | -| `POST` | `/api/patresult` | Enter new result | Yes | -| `PATCH` | `/api/patresult/{id}` | Update result | Yes | -| `POST` | `/api/patresult/status` | Verify result (VER/REV/REP) | Yes | - -#### Edge API (Instrument Integration) - -| Method | Endpoint | Description | Auth Required | -|--------|----------|-------------|---------------| -| `POST` | `/api/edge/results` | Receive instrument results | API Key | -| `GET` | `/api/edge/orders` | Fetch pending orders | API Key | -| `POST` | `/api/edge/orders/{id}/ack` | Acknowledge order | API Key | -| `POST` | `/api/edge/status` | Log instrument status | API Key | - -### API Response Format - -All API endpoints return JSON in this format: - -**Success Response:** -```json -{ - "status": "success", - "message": "Operation completed successfully", - "data": { - // Response data here - } -} -``` - -**Error Response:** -```json -{ - "status": "error", - "message": "Error description", - "errors": [ - { - "field": "field_name", - "message": "Validation error message" - } - ] -} -``` - -### Authentication - -Most endpoints require JWT authentication: - -**Request Headers:** -``` -Authorization: Bearer {jwt_token} -Content-Type: application/json -``` - -**Login Request Example:** -```bash -POST /api/login -{ - "username": "labuser", - "password": "password123" -} -``` - -**Login Response:** -```json -{ - "status": "success", - "message": "Login successful", - "data": { - "token": "eyJ0eXAiOiJKV1QiLCJhbGc...", - "expires_in": 3600, - "user": { - "id": 1, - "username": "labuser", - "name": "Lab User" - } - } -} -``` - ---- - -## Lookups Library (`app/Libraries/ValueSet.php`) - -CLQMS uses a **JSON file-based lookup system** loaded via `App\Libraries\Lookups` class. All lookup data is stored as JSON files in `app/Libraries/Data/valuesets/` for easy maintenance and versioning. - -### How It Works - -- `Lookups` class extends `ValueSet` which handles caching and file loading -- Each lookup is stored as `app/Libraries/Data/valuesets/{name}.json` -- Lookup names are lowercase with underscores (e.g., `gender.json`, `order_priority.json`) - -### Available Lookups - -| Lookup File | Description | Example Values | -|-------------|-------------|----------------| -| `gender` | Patient gender | Female, Male, Unknown | -| `order_priority` | Order priority levels | Stat, ASAP, Routine, Preop | -| `order_status` | Order lifecycle status | STC, SCtd, SArrv, SRcvd | -| `specimen_type` | Specimen types | BLD, SER, PLAS, UR, CSF | -| `specimen_status` | Specimen status | Ordered, Collected, Received | -| `specimen_condition` | Specimen quality flags | HEM, ITC, LIP, CLOT | -| `specimen_activity` | Specimen workflow events | COLLECT, RECEIVE, REJECT | -| `result_type` | Result data types | NMRIC, RANGE, TEXT, VSET | -| `result_unit` | Common measurement units | g/dL, mg/dL, x10^6/mL | -| `result_status` | Result validation status | Preliminary, Final, Corrected | -| `test_type` | Test definition types | TEST, PARAM, CALC, GROUP | -| `test_activity` | Test workflow activities | Order, Analyse, VER, REV | -| `test_status` | Test active status | Active, Inactive, Discontinued | -| `priority` | General priority values | STAT, HIGH, NORMAL, LOW | -| `race` | Ethnicity/race categories | Jawa, Sunda, Batak, etc. | -| `religion` | Religious affiliations | Islam, Kristen, Katolik, Hindu | -| `marital_status` | Marital status | Single, Married, Divorced | -| `death_indicator` | Death status flags | Yes, No | -| `identifier_type` | ID document types | KTP, Passport, SSN, SIM | -| `operation` | CRUD operation types | Create, Read, Update, Delete | -| `site_type` | Healthcare facility types | GH, PH, GHL, PHL, GL, PL | -| `site_class` | Facility classification | A, B, C, D, Utm, Ptm | -| `ws_type` | Workstation types | Primary, Secondary | -| `enable_disable` | Boolean toggle states | Enabled, Disabled | -| `entity_type` | Entity classification | Patient, Provider, Site | -| `requested_entity` | Requestor types | Physician, Nurse, Lab | -| `location_type` | Location categories | OPD, IPD, ER, LAB | -| `area_class` | Geographic classifications | Urban, Rural, Suburban | -| `adt_event` | ADT event types | Admission, Transfer, Discharge | -| `body_site` | Collection sites | Left Arm, Right Arm, Finger | -| `collection_method` | Specimen collection methods | Venipuncture, Fingerstick | -| `container_size` | Tube/container volumes | 3mL, 5mL, 10mL | -| `container_class` | Container types | Vacutainer, Tube, Cup | -| `container_cap_color` | Tube cap colors | Red, Purple, Blue, Green | -| `additive` | Tube additives | EDTA, Heparin, Fluoride | -| `fasting_status` | Fasting requirement flags | Fasting, Non-Fasting | -| `ethnic` | Ethnicity categories | Various regional groups | -| `math_sign` | Mathematical operators | +, -, *, /, =, <, > | -| `formula_language` | Formula expression types | Formula, Expression | -| `generate_by` | Generation methods | Auto, Manual, Import | -| `did_type` | Device identification types | Serial, MAC, UUID | -| `activity_result` | Activity outcomes | Success, Fail, Retry | -| `reference_type` | Reference value types | NMRIC, TEXT, LIST | -| `range_type` | Range calculation types | REF, CRTC, VAL, RERUN | -| `numeric_ref_type` | Numeric ref types | Reference, Critical, Valid | -| `text_ref_type` | Text reference types | Normal, Abnormal, Critical | -| `request_status` | Request status | Pending, Approved, Rejected | -| `v_category` | ValueSet categories | Various categories | - -### Usage - -```php -use App\Libraries\Lookups; - -// Get all lookups (loads all JSON files, cached) -$allLookups = Lookups::getAll(); - -// Get single lookup formatted for dropdowns -$gender = Lookups::get('gender'); -// Returns: [{"value":"1","label":"Female"},{"value":"2","label":"Male"},...] - -// Get raw data without formatting -$raw = Lookups::getRaw('gender'); -// Returns: [{"key":"1","value":"Female"},{"key":"2","value":"Male"},...] - -// Get label for a specific key -$label = Lookups::getLabel('gender', '1'); // Returns 'Female' - -// Get key/value pairs for select inputs -$options = Lookups::getOptions('gender'); -// Returns: [["key":"1","value":"Female"],...] - -// Transform database records with lookup text labels -$patients = [ - ['ID' => 1, 'Sex' => '1', 'Priority' => 'S'], - ['ID' => 2, 'Sex' => '2', 'Priority' => 'R'], -]; -$labeled = Lookups::transformLabels($patients, [ - 'Sex' => 'gender', - 'Priority' => 'order_priority' -]); -// Result: [['ID'=>1, 'Sex'=>'1', 'SexText'=>'Female', 'Priority'=>'S', 'PriorityText'=>'Stat'],...] - -// Clear cache after modifying valueset data -Lookups::clearCache(); -``` - -### When to Use - -| Approach | Use Case | -|----------|----------| -| **Lookups Library** | Server-side static values that rarely change (gender, status, types) - fast, cached | -| **API `/api/valueset*`** | Dynamic values managed by admins at runtime, or for frontend clients needing lookup data | - -### Adding New Lookups - -1. Create `app/Libraries/Data/valuesets/{name}.json`: -```json -{ - "name": "example_lookup", - "description": "Example lookup description", - "values": [ - {"key": "1", "value": "Option One"}, - {"key": "2", "value": "Option Two"}, - {"key": "3", "value": "Option Three"} - ] -} -``` - -2. Access via `Lookups::get('example_lookup')` - ---- - -## 📋 Master Data Management - -CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via REST API endpoints. - -### 🧪 Laboratory Tests - -The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels. - -#### Test Types - -| Type Code | Description | Table | -|-----------|-------------|-------| -| `TEST` | Individual laboratory test with technical specs | `testdefsite` + `testdeftech` | -| `PARAM` | Parameter value (non-lab measurement) | `testdefsite` + `testdeftech` | -| `CALC` | Calculated test with formula | `testdefsite` + `testdefcal` | -| `GROUP` | Panel/profile containing multiple tests | `testdefsite` + `testdefgrp` | -| `TITLE` | Section title for report organization | `testdefsite` | - -#### API Endpoints - -| Method | Endpoint | Description | -|--------|----------|-------------| -| `GET` | `/api/tests` | List all tests with optional filtering | -| `GET` | `/api/tests/{id}` | Get test details with type-specific data | -| `POST` | `/api/tests` | Create new test definition | -| `PATCH` | `/api/tests` | Update existing test | -| `DELETE` | `/api/tests` | Soft delete test (sets EndDate) | - -#### Filtering Parameters - -- `TestSiteName` - Search by test name (partial match) -- `TestType` - Filter by test type VID (1-5) -- `VisibleScr` - Filter by screen visibility (0/1) -- `VisibleRpt` - Filter by report visibility (0/1) - -#### Test Response Structure - -```json -{ - "status": "success", - "message": "Data fetched successfully", - "data": [ - { - "TestSiteID": 1, - "TestSiteCode": "CBC", - "TestSiteName": "Complete Blood Count", - "TestType": 4, - "TypeCode": "GROUP", - "TypeName": "Group Test", - "SeqScr": 50, - "VisibleScr": 1, - "VisibleRpt": 1 - } - ] -} -``` - -### 📏 Reference Ranges - -Reference Ranges define normal and critical values for test results. The system supports multiple reference range types based on patient demographics. - -#### Reference Range Types - -| Type | Table | Description | -|------|-------|-------------| -| Numeric | `refnum` | Numeric ranges with age/sex criteria | -| Text | `reftxt` | Text-based reference values | - -#### Numeric Reference Range Structure - -| Field | Description | -|-------|-------------| -| `NumRefType` | Type: REF (Reference), CRTC (Critical), VAL (Validation), RERUN | -| `RangeType` | RANGE or THOLD | -| `Sex` | Gender filter (0=All, 1=Female, 2=Male) | -| `AgeStart` | Minimum age (years) | -| `AgeEnd` | Maximum age (years) | -| `LowSign` | Low boundary sign (=, <, <=) | -| `Low` | Low boundary value | -| `HighSign` | High boundary sign (=, >, >=) | -| `High` | High boundary value | -| `Flag` | Result flag (H, L, A, etc.) | - -#### API Endpoints - -| Method | Endpoint | Description | -|--------|----------|-------------| -| `GET` | `/api/refnum` | List numeric reference ranges | -| `GET` | `/api/refnum/{id}` | Get reference range details | -| `POST` | `/api/refnum` | Create reference range | -| `PATCH` | `/api/refnum` | Update reference range | -| `DELETE` | `/api/refnum` | Soft delete reference range | - -### 📑 Value Sets - -Value Sets are configurable dropdown options used throughout the system. Each Value Set Definition (VSetDef) contains multiple Value Set Values (ValueSet). - -#### Value Set Hierarchy - -``` -valuesetdef (VSetDefID, VSName, VSDesc) - └── valueset (VID, VSetID, VValue, VDesc, VOrder, VCategory) -``` - -#### Common Value Sets - -| VSetDefID | Name | Example Values | -|-----------|------|----------------| -| 1 | Priority | STAT (S), ASAP (A), Routine (R), Preop (P) | -| 2 | Enable/Disable | Disabled (0), Enabled (1) | -| 3 | Gender | Female (1), Male (2), Unknown (3) | -| 10 | Order Status | STC, SCtd, SArrv, SRcvd, SAna, etc. | -| 15 | Specimen Type | BLD, SER, PLAS, UR, CSF, etc. | -| 16 | Unit | L, mL, g/dL, mg/dL, etc. | -| 27 | Test Type | TEST, PARAM, CALC, GROUP, TITLE | -| 28 | Result Unit | g/dL, g/L, mg/dL, x10^6/mL, etc. | -| 35 | Test Activity | Order, Analyse, VER, REV, REP | - -#### API Endpoints - -| Method | Endpoint | Description | -|--------|----------|-------------| -| `GET` | `/api/valuesetdef` | List all value set definitions | -| `GET` | `/api/valuesetdef/{id}` | Get valueset with all values | -| `GET` | `/api/valuesetdef/{id}/values` | Get values for specific valueset | -| `POST` | `/api/valuesetdef` | Create new valueset definition | -| `PATCH` | `/api/valuesetdef` | Update valueset definition | -| `DELETE` | `/api/valuesetdef` | Delete valueset definition | - -#### Value Set Response Structure - -```json -{ - "status": "success", - "data": { - "VSetDefID": 27, - "VSName": "Test Type", - "VSDesc": "testdefsite.TestType", - "values": [ - { "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 }, - { "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 }, - { "VID": 3, "VValue": "CALC", "VDesc": "Calculated Test", "VOrder": 3 }, - { "VID": 4, "VValue": "GROUP", "VDesc": "Group Test", "VOrder": 4 }, - { "VID": 5, "VValue": "TITLE", "VDesc": "Title", "VOrder": 5 } - ] - } -} -``` - -### 📊 Database Tables Summary - -| Category | Tables | Purpose | -|----------|--------|---------| -| Tests | `testdefsite`, `testdeftech`, `testdefcal`, `testdefgrp`, `testmap` | Test definitions | -| Reference Ranges | `refnum`, `reftxt` | Result validation | -| Value Sets | `valuesetdef`, `valueset` | Configurable options | - ---- - -## 🔌 Edge API - Instrument Integration - -The **Edge API** provides endpoints for integrating laboratory instruments via the `tiny-edge` middleware. Results from instruments are staged in the `edgeres` table before processing into the main patient results (`patres`). - -### Endpoints - -| Method | Endpoint | Description | -|--------|----------|-------------| -| `POST` | `/api/edge/results` | Receive instrument results (stored in `edgeres`) | -| `GET` | `/api/edge/orders` | Fetch pending orders for an instrument | -| `POST` | `/api/edge/orders/:id/ack` | Acknowledge order delivery to instrument | -| `POST` | `/api/edge/status` | Log instrument status updates | - -### Workflow - -``` -Instrument → tiny-edge → POST /api/edge/results → edgeres table → [Manual/Auto Processing] → patres table -``` - -**Key Features:** -- **Staging Table:** All results land in `edgeres` first for validation -- **Rerun Handling:** Duplicate `SampleID` + `TestSiteCode` increments `AspCnt` in `patres` -- **Configurable Processing:** Auto or manual processing based on settings -- **Status Tracking:** Full audit trail via `edgestatus` and `edgeack` tables - ---- - -### 📜 Usage Notice - -**This is an API-only backend system.** There are no views, HTML templates, or server-side rendering components. Frontend applications should consume these REST endpoints to build user interfaces for laboratory operations. - -This repository contains proprietary information intended for the 5Panda Team and authorized collaborators. - ---- -*© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.* +# CLQMS (Clinical Laboratory Quality Management System) + +> **A REST API backend for modern clinical laboratory workflows.** + +--- + +## 🤖 For Claude Code + +**When working in this repository, prioritize Serena MCP tools for code operations:** + +- **Use `find_symbol` / `get_symbols_overview`** instead of `Read` for exploring code structure +- **Use `replace_symbol_body`** instead of `Edit` for modifying functions, methods, classes +- **Use `insert_before_symbol` / `insert_after_symbol`** for adding new code symbols +- **Use `search_for_pattern`** instead of `Grep` for searching code patterns +- **Use `list_dir` / `find_file`** instead of `Glob` for file discovery + +This minimizes tool calls and leverages semantic code understanding for this PHP codebase. + +--- + +CLQMS is a **headless REST API backend** designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system provides comprehensive JSON endpoints for laboratory operations. + +**Key Characteristic:** This is an **API-only system** with no view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems. + +--- + +## 🏛️ Core Architecture & Design + +CLQMS is a **headless REST API system** following a clean architecture pattern. The system is designed to be consumed by any frontend client (web, mobile, desktop) through comprehensive JSON endpoints. + +**API-First Architecture:** +- **No View Layer:** This system provides REST APIs only - no HTML views, no server-side rendering +- **Frontend Agnostic:** Any client can consume these APIs (React, Vue, Angular, mobile apps, desktop apps) +- **JSON-First:** All requests/responses use JSON format +- **Stateless:** Each API request is independent with JWT authentication + +The system is currently undergoing a strategic **Architectural Redesign** to consolidate legacy structures into a high-performance, maintainable schema. This design focuses on reducing technical debt and improving data consistency across: + +- **Unified Test Definitions:** Consolidating technical, calculated, and site-specific test data. +- **Reference Range Centralization:** A unified engine for numeric, threshold, text, and coded results. +- **Ordered Workflow Management:** Precise tracking of orders from collection to verification. + +--- + +## 🛡️ Strategic Pillars + +- **Precision & Accuracy:** Strict validation for all laboratory parameters and reference ranges. +- **Scalability:** Optimized for high-volume diagnostic environments. +- **Compliance:** Built-in audit trails and status history for full traceability. +- **Interoperability:** Modular architecture designed for LIS, HIS, and analyzer integrations. + +--- + +## 🛠️ Technical Stack + +| Component | Specification | +| :------------- | :------------ | +| **Language** | PHP 8.1+ (PSR-compliant) | +| **Framework** | CodeIgniter 4 (API-only mode) | +| **Security** | JWT (JSON Web Tokens) Authorization | +| **Database** | MySQL (Optimized Schema Migration in progress) | +| **API Format** | RESTful JSON | +| **Testing** | PHPUnit 10.5+ | + + +--- + +## 📂 Documentation & Specifications + +### Key Documents + +| Document | Location | Description | +|----------|----------|-------------| +| **PRD** | `PRD.md` | Complete Product Requirements Document (API-focused) | +| **Technical Guide** | `CLAUDE.md` | Architecture, coding standards, common commands | +| **API Overview** | This file | REST API documentation and endpoints | +| **Database Migrations** | `app/Database/Migrations/` | Database schema history | + +### API Documentation + +All API endpoints follow REST conventions: + +**Base URL:** `/api` + +**Authentication:** JWT token required for most endpoints (except `/api/login`, `/api/demo/*`) + +**Response Format:** +```json +{ + "status": "success|error", + "message": "Human-readable message", + "data": { ... } +} +``` + +--- + +## 🔌 REST API Overview + +### API Endpoint Categories + +#### Authentication & Authorization + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `POST` | `/api/login` | User login, returns JWT token | No | +| `POST` | `/api/logout` | Invalidate JWT token | Yes | +| `POST` | `/api/refresh` | Refresh JWT token | Yes | + +#### Patient Management + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `GET` | `/api/patient` | List patients with pagination | Yes | +| `GET` | `/api/patient/{id}` | Get patient details | Yes | +| `POST` | `/api/patient` | Create new patient | Yes | +| `PATCH` | `/api/patient/{id}` | Update patient | Yes | +| `DELETE` | `/api/patient/{id}` | Soft delete patient | Yes | + +#### Order Management + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `GET` | `/api/ordertest` | List orders | Yes | +| `GET` | `/api/ordertest/{id}` | Get order details | Yes | +| `POST` | `/api/ordertest` | Create order | Yes | +| `PATCH` | `/api/ordertest/{id}` | Update order | Yes | +| `DELETE` | `/api/ordertest/{id}` | Delete order | Yes | +| `POST` | `/api/ordertest/status` | Update order status | Yes | + +#### Demo/Test Endpoints (No Auth) + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `POST` | `/api/demo/order` | Create demo order with patient | No | + +#### Specimen Management + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `GET` | `/api/specimen` | List specimens | Yes | +| `GET` | `/api/specimen/{id}` | Get specimen details | Yes | +| `POST` | `/api/specimen` | Create specimen | Yes | +| `PATCH` | `/api/specimen/{id}` | Update specimen | Yes | +| `POST` | `/api/specimen/status` | Update specimen status | Yes | + +#### Result Management + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `GET` | `/api/patresult` | List patient results | Yes | +| `GET` | `/api/patresult/{id}` | Get result details | Yes | +| `POST` | `/api/patresult` | Enter new result | Yes | +| `PATCH` | `/api/patresult/{id}` | Update result | Yes | +| `POST` | `/api/patresult/status` | Verify result (VER/REV/REP) | Yes | + +#### Edge API (Instrument Integration) + +| Method | Endpoint | Description | Auth Required | +|--------|----------|-------------|---------------| +| `POST` | `/api/edge/results` | Receive instrument results | API Key | +| `GET` | `/api/edge/orders` | Fetch pending orders | API Key | +| `POST` | `/api/edge/orders/{id}/ack` | Acknowledge order | API Key | +| `POST` | `/api/edge/status` | Log instrument status | API Key | + +### API Response Format + +All API endpoints return JSON in this format: + +**Success Response:** +```json +{ + "status": "success", + "message": "Operation completed successfully", + "data": { + // Response data here + } +} +``` + +**Error Response:** +```json +{ + "status": "error", + "message": "Error description", + "errors": [ + { + "field": "field_name", + "message": "Validation error message" + } + ] +} +``` + +### Authentication + +Most endpoints require JWT authentication: + +**Request Headers:** +``` +Authorization: Bearer {jwt_token} +Content-Type: application/json +``` + +**Login Request Example:** +```bash +POST /api/login +{ + "username": "labuser", + "password": "password123" +} +``` + +**Login Response:** +```json +{ + "status": "success", + "message": "Login successful", + "data": { + "token": "eyJ0eXAiOiJKV1QiLCJhbGc...", + "expires_in": 3600, + "user": { + "id": 1, + "username": "labuser", + "name": "Lab User" + } + } +} +``` + +--- + +## Lookups Library (`app/Libraries/ValueSet.php`) + +CLQMS uses a **JSON file-based lookup system** loaded via `App\Libraries\Lookups` class. All lookup data is stored as JSON files in `app/Libraries/Data/valuesets/` for easy maintenance and versioning. + +### How It Works + +- `Lookups` class extends `ValueSet` which handles caching and file loading +- Each lookup is stored as `app/Libraries/Data/valuesets/{name}.json` +- Lookup names are lowercase with underscores (e.g., `gender.json`, `order_priority.json`) + +### Available Lookups + +| Lookup File | Description | Example Values | +|-------------|-------------|----------------| +| `gender` | Patient gender | Female, Male, Unknown | +| `order_priority` | Order priority levels | Stat, ASAP, Routine, Preop | +| `order_status` | Order lifecycle status | STC, SCtd, SArrv, SRcvd | +| `specimen_type` | Specimen types | BLD, SER, PLAS, UR, CSF | +| `specimen_status` | Specimen status | Ordered, Collected, Received | +| `specimen_condition` | Specimen quality flags | HEM, ITC, LIP, CLOT | +| `specimen_activity` | Specimen workflow events | COLLECT, RECEIVE, REJECT | +| `result_type` | Result data types | NMRIC, RANGE, TEXT, VSET | +| `result_unit` | Common measurement units | g/dL, mg/dL, x10^6/mL | +| `result_status` | Result validation status | Preliminary, Final, Corrected | +| `test_type` | Test definition types | TEST, PARAM, CALC, GROUP | +| `test_activity` | Test workflow activities | Order, Analyse, VER, REV | +| `test_status` | Test active status | Active, Inactive, Discontinued | +| `priority` | General priority values | STAT, HIGH, NORMAL, LOW | +| `race` | Ethnicity/race categories | Jawa, Sunda, Batak, etc. | +| `religion` | Religious affiliations | Islam, Kristen, Katolik, Hindu | +| `marital_status` | Marital status | Single, Married, Divorced | +| `death_indicator` | Death status flags | Yes, No | +| `identifier_type` | ID document types | KTP, Passport, SSN, SIM | +| `operation` | CRUD operation types | Create, Read, Update, Delete | +| `site_type` | Healthcare facility types | GH, PH, GHL, PHL, GL, PL | +| `site_class` | Facility classification | A, B, C, D, Utm, Ptm | +| `ws_type` | Workstation types | Primary, Secondary | +| `enable_disable` | Boolean toggle states | Enabled, Disabled | +| `entity_type` | Entity classification | Patient, Provider, Site | +| `requested_entity` | Requestor types | Physician, Nurse, Lab | +| `location_type` | Location categories | OPD, IPD, ER, LAB | +| `area_class` | Geographic classifications | Urban, Rural, Suburban | +| `adt_event` | ADT event types | Admission, Transfer, Discharge | +| `body_site` | Collection sites | Left Arm, Right Arm, Finger | +| `collection_method` | Specimen collection methods | Venipuncture, Fingerstick | +| `container_size` | Tube/container volumes | 3mL, 5mL, 10mL | +| `container_class` | Container types | Vacutainer, Tube, Cup | +| `container_cap_color` | Tube cap colors | Red, Purple, Blue, Green | +| `additive` | Tube additives | EDTA, Heparin, Fluoride | +| `fasting_status` | Fasting requirement flags | Fasting, Non-Fasting | +| `ethnic` | Ethnicity categories | Various regional groups | +| `math_sign` | Mathematical operators | +, -, *, /, =, <, > | +| `formula_language` | Formula expression types | Formula, Expression | +| `generate_by` | Generation methods | Auto, Manual, Import | +| `did_type` | Device identification types | Serial, MAC, UUID | +| `activity_result` | Activity outcomes | Success, Fail, Retry | +| `reference_type` | Reference value types | NMRIC, TEXT, LIST | +| `range_type` | Range calculation types | REF, CRTC, VAL, RERUN | +| `numeric_ref_type` | Numeric ref types | Reference, Critical, Valid | +| `text_ref_type` | Text reference types | Normal, Abnormal, Critical | +| `request_status` | Request status | Pending, Approved, Rejected | +| `v_category` | ValueSet categories | Various categories | + +### Usage + +```php +use App\Libraries\Lookups; + +// Get all lookups (loads all JSON files, cached) +$allLookups = Lookups::getAll(); + +// Get single lookup formatted for dropdowns +$gender = Lookups::get('gender'); +// Returns: [{"value":"1","label":"Female"},{"value":"2","label":"Male"},...] + +// Get raw data without formatting +$raw = Lookups::getRaw('gender'); +// Returns: [{"key":"1","value":"Female"},{"key":"2","value":"Male"},...] + +// Get label for a specific key +$label = Lookups::getLabel('gender', '1'); // Returns 'Female' + +// Get key/value pairs for select inputs +$options = Lookups::getOptions('gender'); +// Returns: [["key":"1","value":"Female"],...] + +// Transform database records with lookup text labels +$patients = [ + ['ID' => 1, 'Sex' => '1', 'Priority' => 'S'], + ['ID' => 2, 'Sex' => '2', 'Priority' => 'R'], +]; +$labeled = Lookups::transformLabels($patients, [ + 'Sex' => 'gender', + 'Priority' => 'order_priority' +]); +// Result: [['ID'=>1, 'Sex'=>'1', 'SexText'=>'Female', 'Priority'=>'S', 'PriorityText'=>'Stat'],...] + +// Clear cache after modifying valueset data +Lookups::clearCache(); +``` + +### When to Use + +| Approach | Use Case | +|----------|----------| +| **Lookups Library** | Server-side static values that rarely change (gender, status, types) - fast, cached | +| **API `/api/valueset*`** | Dynamic values managed by admins at runtime, or for frontend clients needing lookup data | + +### Adding New Lookups + +1. Create `app/Libraries/Data/valuesets/{name}.json`: +```json +{ + "name": "example_lookup", + "description": "Example lookup description", + "values": [ + {"key": "1", "value": "Option One"}, + {"key": "2", "value": "Option Two"}, + {"key": "3", "value": "Option Three"} + ] +} +``` + +2. Access via `Lookups::get('example_lookup')` + +--- + +## 📋 Master Data Management + +CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via REST API endpoints. + +### 🧪 Laboratory Tests + +The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels. + +#### Test Types + +| Type Code | Description | Table | +|-----------|-------------|-------| +| `TEST` | Individual laboratory test with technical specs | `testdefsite` + `testdeftech` | +| `PARAM` | Parameter value (non-lab measurement) | `testdefsite` + `testdeftech` | +| `CALC` | Calculated test with formula | `testdefsite` + `testdefcal` | +| `GROUP` | Panel/profile containing multiple tests | `testdefsite` + `testdefgrp` | +| `TITLE` | Section title for report organization | `testdefsite` | + +#### API Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/api/tests` | List all tests with optional filtering | +| `GET` | `/api/tests/{id}` | Get test details with type-specific data | +| `POST` | `/api/tests` | Create new test definition | +| `PATCH` | `/api/tests` | Update existing test | +| `DELETE` | `/api/tests` | Soft delete test (sets EndDate) | + +#### Filtering Parameters + +- `TestSiteName` - Search by test name (partial match) +- `TestType` - Filter by test type VID (1-5) +- `VisibleScr` - Filter by screen visibility (0/1) +- `VisibleRpt` - Filter by report visibility (0/1) + +#### Test Response Structure + +```json +{ + "status": "success", + "message": "Data fetched successfully", + "data": [ + { + "TestSiteID": 1, + "TestSiteCode": "CBC", + "TestSiteName": "Complete Blood Count", + "TestType": 4, + "TypeCode": "GROUP", + "TypeName": "Group Test", + "SeqScr": 50, + "VisibleScr": 1, + "VisibleRpt": 1 + } + ] +} +``` + +### 📏 Reference Ranges + +Reference Ranges define normal and critical values for test results. The system supports multiple reference range types based on patient demographics. + +#### Reference Range Types + +| Type | Table | Description | +|------|-------|-------------| +| Numeric | `refnum` | Numeric ranges with age/sex criteria | +| Text | `reftxt` | Text-based reference values | + +#### Numeric Reference Range Structure + +| Field | Description | +|-------|-------------| +| `NumRefType` | Type: REF (Reference), CRTC (Critical), VAL (Validation), RERUN | +| `RangeType` | RANGE or THOLD | +| `Sex` | Gender filter (0=All, 1=Female, 2=Male) | +| `AgeStart` | Minimum age (years) | +| `AgeEnd` | Maximum age (years) | +| `LowSign` | Low boundary sign (=, <, <=) | +| `Low` | Low boundary value | +| `HighSign` | High boundary sign (=, >, >=) | +| `High` | High boundary value | +| `Flag` | Result flag (H, L, A, etc.) | + +#### API Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/api/refnum` | List numeric reference ranges | +| `GET` | `/api/refnum/{id}` | Get reference range details | +| `POST` | `/api/refnum` | Create reference range | +| `PATCH` | `/api/refnum` | Update reference range | +| `DELETE` | `/api/refnum` | Soft delete reference range | + +### 📑 Value Sets + +Value Sets are configurable dropdown options used throughout the system. Each Value Set Definition (VSetDef) contains multiple Value Set Values (ValueSet). + +#### Value Set Hierarchy + +``` +valuesetdef (VSetDefID, VSName, VSDesc) + └── valueset (VID, VSetID, VValue, VDesc, VOrder, VCategory) +``` + +#### Common Value Sets + +| VSetDefID | Name | Example Values | +|-----------|------|----------------| +| 1 | Priority | STAT (S), ASAP (A), Routine (R), Preop (P) | +| 2 | Enable/Disable | Disabled (0), Enabled (1) | +| 3 | Gender | Female (1), Male (2), Unknown (3) | +| 10 | Order Status | STC, SCtd, SArrv, SRcvd, SAna, etc. | +| 15 | Specimen Type | BLD, SER, PLAS, UR, CSF, etc. | +| 16 | Unit | L, mL, g/dL, mg/dL, etc. | +| 27 | Test Type | TEST, PARAM, CALC, GROUP, TITLE | +| 28 | Result Unit | g/dL, g/L, mg/dL, x10^6/mL, etc. | +| 35 | Test Activity | Order, Analyse, VER, REV, REP | + +#### API Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/api/valuesetdef` | List all value set definitions | +| `GET` | `/api/valuesetdef/{id}` | Get valueset with all values | +| `GET` | `/api/valuesetdef/{id}/values` | Get values for specific valueset | +| `POST` | `/api/valuesetdef` | Create new valueset definition | +| `PATCH` | `/api/valuesetdef` | Update valueset definition | +| `DELETE` | `/api/valuesetdef` | Delete valueset definition | + +#### Value Set Response Structure + +```json +{ + "status": "success", + "data": { + "VSetDefID": 27, + "VSName": "Test Type", + "VSDesc": "testdefsite.TestType", + "values": [ + { "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 }, + { "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 }, + { "VID": 3, "VValue": "CALC", "VDesc": "Calculated Test", "VOrder": 3 }, + { "VID": 4, "VValue": "GROUP", "VDesc": "Group Test", "VOrder": 4 }, + { "VID": 5, "VValue": "TITLE", "VDesc": "Title", "VOrder": 5 } + ] + } +} +``` + +### 📊 Database Tables Summary + +| Category | Tables | Purpose | +|----------|--------|---------| +| Tests | `testdefsite`, `testdeftech`, `testdefcal`, `testdefgrp`, `testmap` | Test definitions | +| Reference Ranges | `refnum`, `reftxt` | Result validation | +| Value Sets | `valuesetdef`, `valueset` | Configurable options | + +--- + +## 🔌 Edge API - Instrument Integration + +The **Edge API** provides endpoints for integrating laboratory instruments via the `tiny-edge` middleware. Results from instruments are staged in the `edgeres` table before processing into the main patient results (`patres`). + +### Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `POST` | `/api/edge/results` | Receive instrument results (stored in `edgeres`) | +| `GET` | `/api/edge/orders` | Fetch pending orders for an instrument | +| `POST` | `/api/edge/orders/:id/ack` | Acknowledge order delivery to instrument | +| `POST` | `/api/edge/status` | Log instrument status updates | + +### Workflow + +``` +Instrument → tiny-edge → POST /api/edge/results → edgeres table → [Manual/Auto Processing] → patres table +``` + +**Key Features:** +- **Staging Table:** All results land in `edgeres` first for validation +- **Rerun Handling:** Duplicate `SampleID` + `TestSiteCode` increments `AspCnt` in `patres` +- **Configurable Processing:** Auto or manual processing based on settings +- **Status Tracking:** Full audit trail via `edgestatus` and `edgeack` tables + +--- + +### 📜 Usage Notice + +**This is an API-only backend system.** There are no views, HTML templates, or server-side rendering components. Frontend applications should consume these REST endpoints to build user interfaces for laboratory operations. + +This repository contains proprietary information intended for the 5Panda Team and authorized collaborators. + +--- +*© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.* diff --git a/app/.htaccess b/app/.htaccess index 3462048..bcfc421 100644 --- a/app/.htaccess +++ b/app/.htaccess @@ -1,6 +1,6 @@ - - Require all denied - - - Deny from all - + + Require all denied + + + Deny from all + diff --git a/app/Common.php b/app/Common.php index 95f5544..50315c4 100644 --- a/app/Common.php +++ b/app/Common.php @@ -1,15 +1,15 @@ - - */ - public array $allowedHostnames = []; - - /** - * -------------------------------------------------------------------------- - * Index File - * -------------------------------------------------------------------------- - * - * Typically, this will be your `index.php` file, unless you've renamed it to - * something else. If you have configured your web server to remove this file - * from your site URIs, set this variable to an empty string. - */ - #public string $indexPage = 'index.php'; - public string $indexPage = ''; - - /** - * -------------------------------------------------------------------------- - * URI PROTOCOL - * -------------------------------------------------------------------------- - * - * This item determines which server global should be used to retrieve the - * URI string. The default setting of 'REQUEST_URI' works for most servers. - * If your links do not seem to work, try one of the other delicious flavors: - * - * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] - * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] - * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] - * - * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! - */ - public string $uriProtocol = 'REQUEST_URI'; - - /* - |-------------------------------------------------------------------------- - | Allowed URL Characters - |-------------------------------------------------------------------------- - | - | This lets you specify which characters are permitted within your URLs. - | When someone tries to submit a URL with disallowed characters they will - | get a warning message. - | - | As a security measure you are STRONGLY encouraged to restrict URLs to - | as few characters as possible. - | - | By default, only these are allowed: `a-z 0-9~%.:_-` - | - | Set an empty string to allow all characters -- but only if you are insane. - | - | The configured value is actually a regular expression character group - | and it will be used as: '/\A[]+\z/iu' - | - | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! - | - */ - public string $permittedURIChars = 'a-z 0-9~%.:_\-'; - - /** - * -------------------------------------------------------------------------- - * Default Locale - * -------------------------------------------------------------------------- - * - * The Locale roughly represents the language and location that your visitor - * is viewing the site from. It affects the language strings and other - * strings (like currency markers, numbers, etc), that your program - * should run under for this request. - */ - public string $defaultLocale = 'en'; - - /** - * -------------------------------------------------------------------------- - * Negotiate Locale - * -------------------------------------------------------------------------- - * - * If true, the current Request object will automatically determine the - * language to use based on the value of the Accept-Language header. - * - * If false, no automatic detection will be performed. - */ - public bool $negotiateLocale = false; - - /** - * -------------------------------------------------------------------------- - * Supported Locales - * -------------------------------------------------------------------------- - * - * If $negotiateLocale is true, this array lists the locales supported - * by the application in descending order of priority. If no match is - * found, the first locale will be used. - * - * IncomingRequest::setLocale() also uses this list. - * - * @var list - */ - public array $supportedLocales = ['en']; - - /** - * -------------------------------------------------------------------------- - * Application Timezone - * -------------------------------------------------------------------------- - * - * The default timezone that will be used in your application to display - * dates with the date helper, and can be retrieved through app_timezone() - * - * @see https://www.php.net/manual/en/timezones.php for list of timezones - * supported by PHP. - */ - public string $appTimezone = 'UTC'; - - /** - * -------------------------------------------------------------------------- - * Default Character Set - * -------------------------------------------------------------------------- - * - * This determines which character set is used by default in various methods - * that require a character set to be provided. - * - * @see http://php.net/htmlspecialchars for a list of supported charsets. - */ - public string $charset = 'UTF-8'; - - /** - * -------------------------------------------------------------------------- - * Force Global Secure Requests - * -------------------------------------------------------------------------- - * - * If true, this will force every request made to this application to be - * made via a secure connection (HTTPS). If the incoming request is not - * secure, the user will be redirected to a secure version of the page - * and the HTTP Strict Transport Security (HSTS) header will be set. - */ - public bool $forceGlobalSecureRequests = false; - - /** - * -------------------------------------------------------------------------- - * Reverse Proxy IPs - * -------------------------------------------------------------------------- - * - * If your server is behind a reverse proxy, you must whitelist the proxy - * IP addresses from which CodeIgniter should trust headers such as - * X-Forwarded-For or Client-IP in order to properly identify - * the visitor's IP address. - * - * You need to set a proxy IP address or IP address with subnets and - * the HTTP header for the client IP address. - * - * Here are some examples: - * [ - * '10.0.1.200' => 'X-Forwarded-For', - * '192.168.5.0/24' => 'X-Real-IP', - * ] - * - * @var array - */ - public array $proxyIPs = []; - - /** - * -------------------------------------------------------------------------- - * Content Security Policy - * -------------------------------------------------------------------------- - * - * Enables the Response's Content Secure Policy to restrict the sources that - * can be used for images, scripts, CSS files, audio, video, etc. If enabled, - * the Response object will populate default values for the policy from the - * `ContentSecurityPolicy.php` file. Controllers can always add to those - * restrictions at run time. - * - * For a better understanding of CSP, see these documents: - * - * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ - * @see http://www.w3.org/TR/CSP/ - */ - public bool $CSPEnabled = false; -} + + */ + public array $allowedHostnames = []; + + /** + * -------------------------------------------------------------------------- + * Index File + * -------------------------------------------------------------------------- + * + * Typically, this will be your `index.php` file, unless you've renamed it to + * something else. If you have configured your web server to remove this file + * from your site URIs, set this variable to an empty string. + */ + #public string $indexPage = 'index.php'; + public string $indexPage = ''; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * This item determines which server global should be used to retrieve the + * URI string. The default setting of 'REQUEST_URI' works for most servers. + * If your links do not seem to work, try one of the other delicious flavors: + * + * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] + * + * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! + */ + public string $uriProtocol = 'REQUEST_URI'; + + /* + |-------------------------------------------------------------------------- + | Allowed URL Characters + |-------------------------------------------------------------------------- + | + | This lets you specify which characters are permitted within your URLs. + | When someone tries to submit a URL with disallowed characters they will + | get a warning message. + | + | As a security measure you are STRONGLY encouraged to restrict URLs to + | as few characters as possible. + | + | By default, only these are allowed: `a-z 0-9~%.:_-` + | + | Set an empty string to allow all characters -- but only if you are insane. + | + | The configured value is actually a regular expression character group + | and it will be used as: '/\A[]+\z/iu' + | + | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! + | + */ + public string $permittedURIChars = 'a-z 0-9~%.:_\-'; + + /** + * -------------------------------------------------------------------------- + * Default Locale + * -------------------------------------------------------------------------- + * + * The Locale roughly represents the language and location that your visitor + * is viewing the site from. It affects the language strings and other + * strings (like currency markers, numbers, etc), that your program + * should run under for this request. + */ + public string $defaultLocale = 'en'; + + /** + * -------------------------------------------------------------------------- + * Negotiate Locale + * -------------------------------------------------------------------------- + * + * If true, the current Request object will automatically determine the + * language to use based on the value of the Accept-Language header. + * + * If false, no automatic detection will be performed. + */ + public bool $negotiateLocale = false; + + /** + * -------------------------------------------------------------------------- + * Supported Locales + * -------------------------------------------------------------------------- + * + * If $negotiateLocale is true, this array lists the locales supported + * by the application in descending order of priority. If no match is + * found, the first locale will be used. + * + * IncomingRequest::setLocale() also uses this list. + * + * @var list + */ + public array $supportedLocales = ['en']; + + /** + * -------------------------------------------------------------------------- + * Application Timezone + * -------------------------------------------------------------------------- + * + * The default timezone that will be used in your application to display + * dates with the date helper, and can be retrieved through app_timezone() + * + * @see https://www.php.net/manual/en/timezones.php for list of timezones + * supported by PHP. + */ + public string $appTimezone = 'UTC'; + + /** + * -------------------------------------------------------------------------- + * Default Character Set + * -------------------------------------------------------------------------- + * + * This determines which character set is used by default in various methods + * that require a character set to be provided. + * + * @see http://php.net/htmlspecialchars for a list of supported charsets. + */ + public string $charset = 'UTF-8'; + + /** + * -------------------------------------------------------------------------- + * Force Global Secure Requests + * -------------------------------------------------------------------------- + * + * If true, this will force every request made to this application to be + * made via a secure connection (HTTPS). If the incoming request is not + * secure, the user will be redirected to a secure version of the page + * and the HTTP Strict Transport Security (HSTS) header will be set. + */ + public bool $forceGlobalSecureRequests = false; + + /** + * -------------------------------------------------------------------------- + * Reverse Proxy IPs + * -------------------------------------------------------------------------- + * + * If your server is behind a reverse proxy, you must whitelist the proxy + * IP addresses from which CodeIgniter should trust headers such as + * X-Forwarded-For or Client-IP in order to properly identify + * the visitor's IP address. + * + * You need to set a proxy IP address or IP address with subnets and + * the HTTP header for the client IP address. + * + * Here are some examples: + * [ + * '10.0.1.200' => 'X-Forwarded-For', + * '192.168.5.0/24' => 'X-Real-IP', + * ] + * + * @var array + */ + public array $proxyIPs = []; + + /** + * -------------------------------------------------------------------------- + * Content Security Policy + * -------------------------------------------------------------------------- + * + * Enables the Response's Content Secure Policy to restrict the sources that + * can be used for images, scripts, CSS files, audio, video, etc. If enabled, + * the Response object will populate default values for the policy from the + * `ContentSecurityPolicy.php` file. Controllers can always add to those + * restrictions at run time. + * + * For a better understanding of CSP, see these documents: + * + * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ + * @see http://www.w3.org/TR/CSP/ + */ + public bool $CSPEnabled = false; +} diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index 9a92824..bedd33b 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -1,92 +1,92 @@ -|string> - */ - public $psr4 = [ - APP_NAMESPACE => APPPATH, - ]; - - /** - * ------------------------------------------------------------------- - * Class Map - * ------------------------------------------------------------------- - * The class map provides a map of class names and their exact - * location on the drive. Classes loaded in this manner will have - * slightly faster performance because they will not have to be - * searched for within one or more directories as they would if they - * were being autoloaded through a namespace. - * - * Prototype: - * $classmap = [ - * 'MyClass' => '/path/to/class/file.php' - * ]; - * - * @var array - */ - public $classmap = []; - - /** - * ------------------------------------------------------------------- - * Files - * ------------------------------------------------------------------- - * The files array provides a list of paths to __non-class__ files - * that will be autoloaded. This can be useful for bootstrap operations - * or for loading functions. - * - * Prototype: - * $files = [ - * '/path/to/my/file.php', - * ]; - * - * @var list - */ - public $files = []; - - /** - * ------------------------------------------------------------------- - * Helpers - * ------------------------------------------------------------------- - * Prototype: - * $helpers = [ - * 'form', - * ]; - * - * @var list - */ - public $helpers = []; -} +|string> + */ + public $psr4 = [ + APP_NAMESPACE => APPPATH, + ]; + + /** + * ------------------------------------------------------------------- + * Class Map + * ------------------------------------------------------------------- + * The class map provides a map of class names and their exact + * location on the drive. Classes loaded in this manner will have + * slightly faster performance because they will not have to be + * searched for within one or more directories as they would if they + * were being autoloaded through a namespace. + * + * Prototype: + * $classmap = [ + * 'MyClass' => '/path/to/class/file.php' + * ]; + * + * @var array + */ + public $classmap = []; + + /** + * ------------------------------------------------------------------- + * Files + * ------------------------------------------------------------------- + * The files array provides a list of paths to __non-class__ files + * that will be autoloaded. This can be useful for bootstrap operations + * or for loading functions. + * + * Prototype: + * $files = [ + * '/path/to/my/file.php', + * ]; + * + * @var list + */ + public $files = []; + + /** + * ------------------------------------------------------------------- + * Helpers + * ------------------------------------------------------------------- + * Prototype: + * $helpers = [ + * 'form', + * ]; + * + * @var list + */ + public $helpers = []; +} diff --git a/app/Config/Boot/development.php b/app/Config/Boot/development.php index a868447..1f9c2b0 100644 --- a/app/Config/Boot/development.php +++ b/app/Config/Boot/development.php @@ -1,34 +1,34 @@ - - */ - public array $file = [ - 'storePath' => WRITEPATH . 'cache/', - 'mode' => 0640, - ]; - - /** - * ------------------------------------------------------------------------- - * Memcached settings - * ------------------------------------------------------------------------- - * - * Your Memcached servers can be specified below, if you are using - * the Memcached drivers. - * - * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached - * - * @var array - */ - public array $memcached = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'weight' => 1, - 'raw' => false, - ]; - - /** - * ------------------------------------------------------------------------- - * Redis settings - * ------------------------------------------------------------------------- - * - * Your Redis server can be specified below, if you are using - * the Redis or Predis drivers. - * - * @var array - */ - public array $redis = [ - 'host' => '127.0.0.1', - 'password' => null, - 'port' => 6379, - 'timeout' => 0, - 'database' => 0, - ]; - - /** - * -------------------------------------------------------------------------- - * Available Cache Handlers - * -------------------------------------------------------------------------- - * - * This is an array of cache engine alias' and class names. Only engines - * that are listed here are allowed to be used. - * - * @var array> - */ - public array $validHandlers = [ - 'dummy' => DummyHandler::class, - 'file' => FileHandler::class, - 'memcached' => MemcachedHandler::class, - 'predis' => PredisHandler::class, - 'redis' => RedisHandler::class, - 'wincache' => WincacheHandler::class, - ]; - - /** - * -------------------------------------------------------------------------- - * Web Page Caching: Cache Include Query String - * -------------------------------------------------------------------------- - * - * Whether to take the URL query string into consideration when generating - * output cache files. Valid options are: - * - * false = Disabled - * true = Enabled, take all query parameters into account. - * Please be aware that this may result in numerous cache - * files generated for the same page over and over again. - * ['q'] = Enabled, but only take into account the specified list - * of query parameters. - * - * @var bool|list - */ - public $cacheQueryString = false; -} + + */ + public array $file = [ + 'storePath' => WRITEPATH . 'cache/', + 'mode' => 0640, + ]; + + /** + * ------------------------------------------------------------------------- + * Memcached settings + * ------------------------------------------------------------------------- + * + * Your Memcached servers can be specified below, if you are using + * the Memcached drivers. + * + * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached + * + * @var array + */ + public array $memcached = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 1, + 'raw' => false, + ]; + + /** + * ------------------------------------------------------------------------- + * Redis settings + * ------------------------------------------------------------------------- + * + * Your Redis server can be specified below, if you are using + * the Redis or Predis drivers. + * + * @var array + */ + public array $redis = [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'database' => 0, + ]; + + /** + * -------------------------------------------------------------------------- + * Available Cache Handlers + * -------------------------------------------------------------------------- + * + * This is an array of cache engine alias' and class names. Only engines + * that are listed here are allowed to be used. + * + * @var array> + */ + public array $validHandlers = [ + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, + 'memcached' => MemcachedHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, + ]; + + /** + * -------------------------------------------------------------------------- + * Web Page Caching: Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * ['q'] = Enabled, but only take into account the specified list + * of query parameters. + * + * @var bool|list + */ + public $cacheQueryString = false; +} diff --git a/app/Config/Constants.php b/app/Config/Constants.php index fb56bb1..45f32c4 100644 --- a/app/Config/Constants.php +++ b/app/Config/Constants.php @@ -1,79 +1,79 @@ -|string|null - */ - public $defaultSrc; - - /** - * Lists allowed scripts' URLs. - * - * @var list|string - */ - public $scriptSrc = 'self'; - - /** - * Lists allowed stylesheets' URLs. - * - * @var list|string - */ - public $styleSrc = 'self'; - - /** - * Defines the origins from which images can be loaded. - * - * @var list|string - */ - public $imageSrc = 'self'; - - /** - * Restricts the URLs that can appear in a page's `` element. - * - * Will default to self if not overridden - * - * @var list|string|null - */ - public $baseURI; - - /** - * Lists the URLs for workers and embedded frame contents - * - * @var list|string - */ - public $childSrc = 'self'; - - /** - * Limits the origins that you can connect to (via XHR, - * WebSockets, and EventSource). - * - * @var list|string - */ - public $connectSrc = 'self'; - - /** - * Specifies the origins that can serve web fonts. - * - * @var list|string - */ - public $fontSrc; - - /** - * Lists valid endpoints for submission from `
` tags. - * - * @var list|string - */ - public $formAction = 'self'; - - /** - * Specifies the sources that can embed the current page. - * This directive applies to ``, `