# Copenhagen Truck Wash API Backend API for Copenhagen Truck Wash services. ## Architecture & Stack - **Edge Proxy:** [Traefik 2.11](https://doc.traefik.io/traefik/) (Handles TLS termination, routing, and rate limiting). - **Web Server:** [Caddy 2.7](https://caddyserver.com/) (Serves the PHP application via FastCGI). - **PHP Runtime:** PHP 8.2-FPM (Scale out with workers `php1` to `php5`). - **Cache/Queue:** Redis 7. - **Observability:** Jaeger (Tracing), Prometheus (Metrics). ## Getting Started ### Prerequisites - Docker Desktop 4.x+ - PHP 8.2 CLI (optional, for host-side testing) ### Local Development To bring up the minimal development stack (Traefik, Redis, MySQL debug DB, Caddy, and one PHP worker): ```powershell docker compose up -d traefik redis mysql-debug php1 caddy ``` The API is accessible at: - `http://localhost` - `https://localhost` (using Traefik default cert) - `http(s)://localhost/api/` (proxied with `/api` prefix stripped) To start all services including multiple PHP workers and development tools (Jaeger, Portainer): ```powershell docker compose --profile dev up -d ``` ### Configuration Configuration is primarily managed via environment variables. - The application root is located at `services/nginx/app`. - `services/nginx/app/config.php` loads configuration from the environment (requires `USE_ENV=true`). - `php1` performs an automatic `composer install` on startup if `AUTO_COMPOSER_INSTALL=true`. #### Environment Change Runbook When updating `.env` values used by PHP containers (for example e-conomic tokens), recreate affected services so Docker applies the new env: ```powershell docker compose up -d --force-recreate php1 php2 php3 php4 php5 php-cron ``` ## Testing The project now uses [Pest](https://pestphp.com/) as the primary test runner in `services/nginx/app`. ### Running Tests All commands are run from `services/nginx/app`: ```powershell composer test composer test:unit composer test:integration composer test:api composer test:coverage ``` For local Docker development, run the PHP suites inside `php1`: ```powershell docker exec php1 sh -lc "cd /var/www/html && composer test:unit" docker exec php1 sh -lc "cd /var/www/html && composer test:integration" docker exec php1 sh -lc "cd /var/www/html && composer test:api" ``` Integration tests are opt-in and should be run with required services available: ```powershell $env:RUN_INTEGRATION_TESTS='1' composer test:integration ``` ### API Test Suite The `Api` suite exercises real HTTP endpoints instead of calling route handlers in-process. - `composer test:api` enables `RUN_API_TESTS=1` automatically. - By default the suite starts a temporary PHP server with `php -S 127.0.0.1:18080 index.php` and hits the app over HTTP. - The suite covers the real router, request parsing, auth headers, status codes, and JSON response envelopes. - Tests run serially and use explicit database/Redis fixtures plus reverse-order cleanup instead of transaction rollbacks. - The default phase-1 coverage includes `/ping`, auth session routes, departments, department categories, and orders CRUD including the legacy `PUT /order` alias. - API server logs are written to `services/nginx/app/build/logs/api-server.out.log` and `services/nginx/app/build/logs/api-server.err.log`. To point the suite at an already-running base URL instead of the self-started PHP server: ```powershell $env:API_TEST_BASE_URL='http://127.0.0.1:18080' composer test:api ``` The suite requires an initialized application schema. Redis-backed flows are used when Redis is configured, but the suite can still boot without `caddy` or the full reverse-proxy stack. ### Run Tests Against A Cloned Live DB (Docker-Isolated) Use the helper scripts in `scripts/` to: 1. Clone the configured live DB into a local MySQL Docker container. 2. Start an isolated Redis container. 3. Run tests in a separate temporary PHP Docker container pointed at that clone. PowerShell: ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\clone-live-db-and-test.ps1 -Force ``` Bash: ```bash FORCE=1 ./scripts/clone-live-db-and-test.sh ``` Optional overrides: - Test command: `-TestCommand "composer test:integration"` or `TEST_COMMAND="composer test:integration"` - Keep containers after run: `-KeepContainers` or `KEEP_CONTAINERS=1` - Skip image build: `-SkipBuild` or `SKIP_BUILD=1` - Force image rebuild: `-ForceBuild` or `FORCE_BUILD=1` ### Clone Live DB Into `mysql-debug` Service To refresh the docker-compose debug DB from live credentials in `.env`: PowerShell: ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\clone-live-to-debug-db.ps1 -Force ``` Bash: ```bash FORCE=1 ./scripts/clone-live-to-debug-db.sh ``` ### Test Layout - `tests/Unit/*`: isolated unit and route-level behavior tests. - `tests/Integration/*`: Redis/DB-backed tests intended for Docker/CI environments. - `tests/Api/*`: real HTTP endpoint tests that boot a temporary PHP server and assert full request/response behavior. - `tests/Api/api_coverage_manifest.php`: selected phase-1 endpoint manifest used by the API meta-test to enforce happy-path and failure coverage. - `tests//*`: legacy procedural scripts retained during migration; keep them runnable until matching Pest coverage exists. ## Logs & Monitoring - **Logs:** `docker compose logs -f [service_name]` (e.g., `php1`, `caddy`, `traefik`). - **Traefik Dashboard:** `http://traefik.localhost` (available in dev). - **Jaeger (Tracing):** `http://localhost:16686` (when running with `--profile dev`). - **Portainer:** `http://localhost:9000` (when running with `--profile dev`). ## API Documentation - **OpenAPI:** The authoritative OpenAPI 3.0 contract is at `openapi.yaml`. - **Self-Serve Module Guide:** Implementation and API guide at `services/nginx/app/modules/selfserve/selfserve.md`. - **Writerside:** Documentation projects are located in `/Writerside` and `/Writerside2`. - **Generated Writerside API Reference:** The active Writerside project lives in `/documentation` and is generated from `openapi.yaml`. ### Writerside OpenAPI Generation Workflow Prerequisite: - Python 3 with PyYAML (`pip install pyyaml`) Run from repository root: ```powershell python scripts/generate_writerside_openapi_docs.py generate python scripts/generate_writerside_openapi_docs.py check ``` Contribution rule: 1. Update `openapi.yaml`. 2. Regenerate docs (`python scripts/generate_writerside_openapi_docs.py generate`). 3. Verify (`python scripts/generate_writerside_openapi_docs.py check`).