# Backend — Laravel 10 ## Module pattern Every feature lives in `app/Modules//`: - `Controllers/Controller.php` — thin: authorize → DTO → action → resource - `Actions/CreateAction.php` — handle(DTO): Model - `Actions/UpdateAction.php` — handle(Model, DTO): Model - `Models/.php` — Eloquent model - `Resources/Resource.php` — explicit field list, no `$this->resource` - `DTOs/Data.php` — readonly constructor + static `fromRequest()` - `Requests/CreateRequest.php` / `UpdateRequest.php` - `Policies/Policy.php` ## Commands ``` composer test # Pest, SQLite in-memory composer static-analysis # pint --test + phpstan + phpmd (all must pass) php artisan migrate # run migrations (against Docker MySQL) ``` ## DB schema - `users`: id, name, email, password, role(enum:admin|staff), timestamps - `clients`: id, client_number(unique), name, notes(JSON), timestamps - `history_entries`: id, client_id(FK), type(enum), body(text), author_id(FK), updated_by(FK nullable), deleted_at, timestamps ## Auth - Sanctum SPA cookie sessions — `EnsureFrontendRequestsAreStateful` on `api` middleware group - Filament: `web` guard, `/admin/login` - No Passport, no tokens ## API conventions - Resources always wrap in `data` key (JsonResource default) - Paginated lists: `data[]` + `meta.total` etc. - 201 on create, 200 on update, 204 on delete