# Backend context Read `ai/shared.md` first. This file covers backend-specific rules. ## Project context **Stack:** PHP 8.4, Laravel 13, PHPUnit, Larastan, Composer. **Location:** `backend/`. The application is still close to the Laravel starter structure. Do not introduce a domain architecture, repository layer, service layer, or other abstraction before the codebase and requested behavior justify it. Match existing Laravel conventions and inspect similar code before adding a new pattern. ## Laravel patterns - Keep controllers thin. Put reusable business behavior in an appropriately named application or domain class once the behavior warrants extraction. - Use dedicated request validation rather than validating substantial payloads inline in controllers. - Let unexpected exceptions reach Laravel's exception handler. Catch only exceptions that can be handled meaningfully at the current boundary. - Use Eloquent relationships and query scopes consistently rather than duplicating query fragments. - Avoid speculative interfaces and abstractions with only one trivial implementation. - The Vue application is a separate project under `frontend/website/`. - Keep frontend source, dependencies, builds, and delivery out of the backend unless the user explicitly asks to integrate them. - The backend root route is intentionally unclaimed. The built-in health endpoint is `/up`. ## Tests - Follow the existing PHPUnit organization under `tests/Unit/` and `tests/Feature/`. - Prefer `PHPUnit\Framework\TestCase` when a test only exercises plain PHP. - Extend `Tests\TestCase` only when the test needs Laravel's container, facades, database, routing, or HTTP kernel. - HTTP feature tests extend `Tests\TestCase`. - Use `RefreshDatabase` when a test reads or writes database state. - Assert behavior at the appropriate seam: - Unit tests cover isolated business behavior and edge cases. - Feature tests cover routing, middleware, validation, persistence, and response shape. - Do not duplicate every business branch through the HTTP layer when unit coverage already proves it. Feature tests should focus on wiring and the public contract. ## Test database - Development and runtime use PostgreSQL through the local Unix socket. - PHPUnit intentionally uses SQLite `:memory:` as configured in `phpunit.xml`. - Feature tests are self-contained and do not require the process-compose PostgreSQL service. - Never point `RefreshDatabase` tests at the development PostgreSQL database. - Keep mail set to the PHPUnit `array` transport unless a test explicitly exercises a real mail integration. ## PHP rules - Put imports at the top of the file. Do not use inline fully qualified class names when a normal `use` statement is clearer. - Do not use arrow functions. Use regular anonymous functions. - Do not add default values to function or constructor parameters. Pass every argument explicitly, including nullable arguments. - Use descriptive names for classes, methods, parameters, and local variables. - Document exceptions with `@throws` when a caller is expected to handle them. ## Seeders - Keep `DatabaseSeeder` as the orchestrator. - Split substantial seed data into one seeder per domain concept and invoke them in dependency order. - Do not add production repository or model APIs solely to make seeding convenient. - Use existing lookup methods for cross-seeder relationships. When a group of records only makes sense together, keep them in one seeder and retain local references. ## Migrations - Attainly is not in production yet. - While no production database exists, edit the original `create_*` migration when changing a table instead of accumulating follow-up alter migrations. - Keep one migration file per table during this pre-production phase. - Rebuild the development database with: ```sh php artisan migrate:fresh --seed ``` - Once a production database exists, replace this policy with additive, forward-only migrations. ## Before completing backend work - Run the focused test during development. - Run `php artisan test` before completion. - Run the Composer static-analysis scripts. - Fix failures caused by the change. Report unrelated baseline failures precisely rather than hiding them or expanding scope without authorization.