Documentation
All resources for understanding, using, and extending the DB API.
User Manual ¶
Base URL: /{tenant}/{version}/... (e.g. /acme/v1/posts)
Auth: Writes require Authorization: Bearer <token> (Passport).
Standard response
{ "success": true, "data": { ... }, "message": "..." }
{ "success": false, "message": "...", "errors": { "field": ["..."] } }
Status codes
200OK ·201Created ·202Accepted (async)400Bad request ·401Unauthenticated ·403Module not enabled404Not found ·422Validation error ·429Rate limited
Modules & endpoints (summary)
| Module | Gate | Endpoints |
|---|---|---|
| Blog | blog | posts, categories, tags — CRUD + search |
| Forms | forms | create, find, submit (public) |
| Identity | — | users — always available, no gate |
| Languages | languages | list, find, create |
| Pages | pages | find, create, update (block editor) |
| TodoList | todolist | find, create, update tasks |
See docs/user-manual.md for full endpoint tables and curl examples.
Development Guide ¶
How to extend the API with new aggregates, commands, queries, and handlers.
File layout per aggregate
src/{Context}/{Aggregate}/
├── Domain/ # Pure PHP — no Laravel, no Eloquent
│ ├── {Aggregate}.php (extends AggregateRoot)
│ ├── {Aggregate}Id.php (extends Uuid)
│ ├── {Prop}ValueObject.php
│ ├── *CreatedDomainEvent.php
│ └── {Aggregate}Repository.php (interface)
├── Application/ # CQRS handlers + response DTOs
│ ├── Create/ Command + Handler
│ ├── Find/ Query + Handler
│ ├── Update/ Command + Handler
│ ├── SearchByCriteria/
│ └── Response/ {Aggregate}Response.php
├── Infrastructure/ # Laravel-specific wiring
│ ├── Controller/ (invokable, extends ApiController)
│ ├── Persistence/ (Elouqent*Repository)
│ └── Module/ (ModuleProvisioner, if new tables)
└── Tests/Domain/ (unit tests)
Adding a new feature (step by step)
- Create Domain layer: aggregate root + VOs + domain event + repository interface
- Create Application layer: Command/Query + Handler + Response DTO
- Create Infrastructure layer: Controller (invokable,
#[OA\*]annotations) + Persistence repository - Wire it up: bind repository in
RepositoryServiceProvider, register handler inDomainServiceProvider, add route inroutes/api.php - Write Feature test in
tests/Feature/(mock buses, cover 200/401/403/404/422) - Verify:
php artisan test && php artisan l5-swagger:generate && ./init.sh
See docs/development.md for full details.
Architecture ¶
Three patterns layered together:
- DDD — 6 bounded contexts (
Blogging,Identity,Forms,Language,PageManagement,TodoList). Each aggregate hasDomain → Application → Infrastructure. Inner layers never depend on outer layers. - CQRS — Writes go through a
CommandBus, reads through aQueryBus. Handlers are single-method classes. Domain events recorded on aggregates and dispatched by the bus. - Table-per-tenant — URL
/{tenant}/{version}/...resolves to a tenant whoseapp_idprefixes all tables (acme_posts,acme_users).
Middleware pipeline
Request → identify_tenant → api.version → tenant → require.module:X → auth:api → Controller
(resolve) (validate) (set) (gate) (token) (dispatch bus)
Identity is cross-cutting
User routes are not behind a require.module gate. Users are foundational for authentication (Passport), and every tenant needs user resolution regardless of which business modules are enabled.
See docs/architecture.md for full details.
Conventions ¶
declare(strict_types=1)on every file undersrc/andapp/- Classes are
final; VOs and DTOs arefinal readonly - Controllers: invokable, extend
ApiController, injectCommandBus/QueryBus - Response envelope:
{"success": bool, "data": ..., "message": "..."}viasendResponse()/sendError() - Namespaces:
Dbapi\insrc/,App\inapp/,Dba\DddSkeleton\for skeleton - No
dd(),dump(),Log::debug, or TODOs without feature ref
See docs/conventions.md for the full rule set.
Testing ¶
| Type | Location | What |
|---|---|---|
| Domain unit | src/{Ctx}/{Agg}/Tests/Domain/ | Aggregate + VO behaviour |
| Feature | tests/Feature/ | HTTP route via mocked buses |
| Unit | tests/Unit/ | Shared logic |
# Run all tests php artisan test # Static analysis composer stan # Regenerate OpenAPI docs php artisan l5-swagger:generate
See docs/verification.md for the verification ladder.
Deployment ¶
composer install --no-dev --optimize-autoloader php artisan config:cache php artisan route:cache php artisan migrate php artisan passport:keys php artisan dba:tenant:provision app_demo
See docs/development.md §5 for full deployment guide.
GitHub Flow ¶
# Agent creates branch git checkout -b feature/123-my-feature # Agent commits (never to master!) .agents/scripts/commit.sh "Add translatable Comment aggregate" # Agent pushes .agents/scripts/push.sh # Human creates PR, reviews, merges to master gh pr create --fill
Blocked Direct commits to master/main are forbidden. Only humans may merge via PR.
Agent Harness ¶
| Script | Purpose |
|---|---|
.agents/scripts/commit.sh | Stage + test + commit. Refuses master. Never pushes. |
.agents/scripts/push.sh | Push to origin. Refuses master without --force. |
.agents/scripts/human-gate.sh | CI/CD gate: blocks agent merges to master. |