This repository has been archived on 2026-03-14. You can view files and clone it, but cannot push or open issues or pull requests.
php-api/CLAUDE.md
Snider 64f9c7246b
Some checks failed
CI / PHP 8.3 (push) Failing after 2s
CI / PHP 8.4 (push) Failing after 2s
docs: add CLAUDE.md project instructions
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-13 13:38:02 +00:00

78 lines
3.3 KiB
Markdown

# 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)