# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Package Overview This is `lthn/php-api`, a Laravel package providing REST API infrastructure: OpenAPI documentation, rate limiting, webhook signing, API versioning, and secure API key management. Part of the Core PHP Framework monorepo ecosystem. ## Commands ```bash ./vendor/bin/pest # Run all tests ./vendor/bin/pest --filter=ApiKey # Run tests matching "ApiKey" ./vendor/bin/pint --dirty # Format changed files ./vendor/bin/pint src/ # Format specific directory ./vendor/bin/pint --test # Check formatting without changes (CI uses this) ``` Tests live in `src/Api/Tests/Feature/`, not the root `tests/` directory. ## Architecture **Three-namespace design:** - `Core\Front\Api\` (`src/Front/Api/`) — API frontage: middleware group, versioning middleware, rate limiter config. **This is the Laravel auto-discovered provider** (registered in `composer.json extra.laravel.providers`). It fires `ApiRoutesRegistering` during boot. - `Core\Api\` (`src/Api/`) — Backend API logic: authentication, scopes, models, webhook services, OpenAPI docs. Uses the event-driven `$listens` pattern to register lazily when `ApiRoutesRegistering` fires. - `Core\Website\Api\` (`src/Website/Api/`) — Frontend documentation UI: controllers, views, web routes for `/api/docs`. **Boot chain:** `Front\Api\Boot` (auto-discovered) → fires `ApiRoutesRegistering` → `Api\Boot` registers middleware aliases and routes via event handler. **Event-driven boot** via `$listens` array in `Core\Api\Boot`: ```php public static array $listens = [ AdminPanelBooting::class => 'onAdminPanel', ApiRoutesRegistering::class => 'onApiRoutes', ConsoleBooting::class => 'onConsole', ]; ``` **Middleware aliases** registered via events (not `bootstrap/app.php`): - `api.auth` / `auth.api` → `AuthenticateApiKey` (bcrypt + legacy SHA-256 key validation) - `api.scope` / `api.scope.enforce` → `CheckApiScope` / `EnforceApiScope` (wildcard-capable permissions) - `api.rate` → `RateLimitApi` (tier-based with burst allowance) - `api.version` → `ApiVersion` (URL/header version parsing) - `api.sunset` → `ApiSunset` (deprecation headers) **Key services:** - `WebhookService` — HMAC-SHA256 signed delivery with exponential backoff retries - `RateLimitService` — Sliding window, per-workspace, tier-based (`free` → `enterprise`) - `IpRestrictionService` — API key IP whitelisting with CIDR support - `OpenApiBuilder` — Generates spec from PHP attributes on controllers ## OpenAPI Documentation Attributes ```php use Core\Api\Documentation\Attributes\{ApiTag, ApiResponse, ApiParameter, ApiSecurity, ApiHidden}; #[ApiTag('Products')] #[ApiResponse(200, ProductResource::class)] #[ApiSecurity('apiKey')] class ProductController { #[ApiParameter('filter', 'query', 'string', 'Filter products')] public function index() { } } ``` ## Conventions - UK English (colour, organisation, centre) - PSR-12 with `declare(strict_types=1);` - Type hints on all parameters and return types - Pest for testing (not PHPUnit directly) - Font Awesome Pro icons (not Heroicons) - Flux Pro components (not vanilla Alpine) ## License EUPL-1.2 (copyleft applies to Core\ namespace)