# Stage 1 — Authentication API Status: **done** and verified end-to-end (PHPUnit feature tests + a live `curl` run against the built-in server). ## What's there A Slim 4 REST API on SQLite with JWT bearer authentication. | Method | Path | Purpose | |--------|------|---------| | GET | `/api/health` | liveness check | | POST | `/api/auth/register` | create account, returns user + token | | POST | `/api/auth/login` | exchange email/password for a token | | GET | `/api/me` | current user (requires `Authorization: Bearer `) | - **Passwords** are hashed with `password_hash()` (bcrypt). Validation is email-format plus an 8–72 character password. Login returns a single generic "Invalid email or password" message so it does not leak which emails exist. - **Emails** are stored lower-cased in a `UNIQUE COLLATE NOCASE` column; duplicate registration returns `409`. - **Errors** always come back as `{ "error": { "message": ..., "details"?: ... } }` via [../src/Http/JsonErrorHandler.php](../src/Http/JsonErrorHandler.php). - **Tokens** are stateless HS256 JWTs. The signing secret comes from `JWT_SECRET`, or is auto-generated into `storage/secret.key` on first run. - **Migrations** are plain SQL files in [../migrations/](../migrations/), applied idempotently by [../bin/migrate.php](../bin/migrate.php) and tracked in a `schema_migrations` table. ## Dependency note `firebase/php-jwt` is pinned to `^7.0` — Composer blocks `6.10`–`6.11` for a published security advisory (`PKSA-y2cr-5h3j-g3ys`). ## Key files - [../src/bootstrap.php](../src/bootstrap.php) — app wiring + routes - [../src/Http/Controllers/AuthController.php](../src/Http/Controllers/AuthController.php) — register / login / me - [../src/Auth/JwtService.php](../src/Auth/JwtService.php), [../src/Auth/AuthMiddleware.php](../src/Auth/AuthMiddleware.php) - [../src/Repository/UserRepository.php](../src/Repository/UserRepository.php) - [../src/Support/Config.php](../src/Support/Config.php), [../src/Support/Database.php](../src/Support/Database.php) - [../tests/AuthTest.php](../tests/AuthTest.php) — 6 passing feature tests ## Run it ```bash composer install && composer migrate && composer serve # http://localhost:8080 ``` ## Local toolchain This machine has no `php`/`composer` binary. Tooling was run through the official Composer container image, which bundles PHP + Composer + `pdo_sqlite` + `mbstring`: ```bash podman run --rm -v "$PWD":/app:Z -w /app docker.io/library/composer:2 install podman run --rm -v "$PWD":/app:Z -w /app docker.io/library/composer:2 vendor/bin/phpunit ```