php-service/CLAUDE.md
Snider dd9e2937d2 docs: add CLAUDE.md project instructions
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-13 13:38:03 +00:00

61 lines
3.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is `lthn/service`, a Composer package for the Core PHP Framework (Laravel-based). It provides SaaS service discovery, dependency resolution, versioning, health checks, and generic landing pages for services. It is a library package — not a standalone application.
**License:** EUPL-1.2
**PHP:** ^8.2
**Dependency:** `lthn/php` (the Core PHP Framework)
## Commands
There is no standalone build, lint, or test runner in this repo. This package is consumed by a host Laravel application. To run tests:
```bash
# From the host application that requires this package:
./vendor/bin/phpunit vendor/lthn/service/src/Core/Service/Tests/
# Single test file:
./vendor/bin/phpunit vendor/lthn/service/src/Core/Service/Tests/Unit/ServiceVersionTest.php
```
Tests use PHPUnit with `#[Test]` attributes (not `@test` annotations or `test_` prefixes).
## Architecture
The package has two distinct layers with separate PSR-4 namespaces:
### Core Layer (`Core\Service\` → `src/Core/Service/`)
Framework-level service infrastructure:
- **ServiceDiscovery** — Scans module paths for `ServiceDefinition` implementations, validates dependencies, resolves initialization order via topological sort, caches results for 1 hour (configurable via `core.services.cache_discovery`)
- **Contracts/** — `ServiceDefinition` (extends `AdminMenuProvider` from `Core\Front\Admin`), `ServiceDependency` (required/optional with semver constraints), `HealthCheckable`
- **ServiceVersion** — Immutable readonly value object following semver with deprecation/sunset lifecycle
- **HealthCheckResult** — Immutable readonly result with factory methods (`healthy()`, `degraded()`, `unhealthy()`, `fromException()`)
- **Enums/ServiceStatus** — Backed enum: healthy, degraded, unhealthy, unknown
- **Concerns/HasServiceVersion** — Trait providing default `version()` (1.0.0) and `dependencies()` (empty) for ServiceDefinition implementations
- **ServiceDependencyException** — Named constructors: `circular()`, `missing()`, `versionMismatch()`
### Website Layer (`Core\Website\Service\` → `src/Website/Service/`)
Public marketing/landing pages served as Livewire components:
- **Boot** — Laravel ServiceProvider that registers Blade views (`service::` namespace) and web routes
- **View/Landing** — Livewire component for service landing page, resolves workspace via subdomain (e.g., `social.host.test``social`)
- **View/Features** — Livewire component with per-service feature lists (matched by workspace slug)
- **Routes/web.php** — Two routes: `/` (Landing) and `/features` (Features)
- **View/Blade/** — Blade templates using `service::` namespace with layout and components
## Key Patterns
- All PHP files use `declare(strict_types=1)`
- Value objects are `final readonly class`
- Factory methods preferred over constructor calls for result types
- Service definitions use static methods (`definition()`, `version()`, `dependencies()`)
- `ServiceDefinition::definition()` must return array with required keys: `code`, `module`, `name`
- Service codes must match pattern: `/^[a-z][a-z0-9_-]*$/i`
- Subdomain routing: `{slug}.host.{tld}` pattern for workspace resolution
- Config keys prefixed with `core.` (e.g., `core.services.cache_discovery`, `core.module_paths`, `core.app.name`)