You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DDD — Code organised by bounded context (Blogging, Identity, Forms, Language, PageManagement, TodoList) and inside each context by aggregate (Post, User, Form, …). Every aggregate has Domain → Application → Infrastructure. Inner layers never depend on outer layers.
CQRS — Writes go through a CommandBus, reads through a QueryBus. Handlers are single-method (__invoke) classes. Domain events are recorded on the aggregate and dispatched by the bus.
Table-per-tenant — The URL segment /{tenant}/{version}/... resolves to a tenant whose app_id prefixes all Eloquent table names at runtime (e.g. acme_posts, acme_users).
All routes live under /{tenant}/{version}/ with middleware pipeline identify_tenant → api.version → tenant. Writes marked 🔒 require auth:api (Bearer token).
Resolution order: (1) tenant DB allowed_versions → (2) tenant config map → (3) global fallback.
Testing
# Run all tests (115+ tests, 215+ assertions)
php artisan test# Inside Sail
./vendor/bin/sail artisan test# Static analysis (PHPStan level 5)
composer stan
# Lint (configurable)
composer lint
Swagger / OpenAPI
# Regenerate OpenAPI docs from PHP attributes
php artisan l5-swagger:generate
Endpoint
Description
/api/documentation
Swagger UI (interactive, try-it-out)
/api/swagger-docs
Raw OpenAPI 3.0 JSON
Annotations live on each controller (#[OA\Get], #[OA\Post], etc.) and globally in src/OpenApi.php (shared schemas: SuccessResponse, ErrorResponse, Post, Category, Tag, Form, User, Language, Page, Task).
CLI commands
Command
Purpose
dba:tenant:create
Create a new tenant with optional module provisioning