Skip to main content
src/ is divided by domain, not by technical role. Each module owns its data, its rules and the plumbing that persists them, which keeps billing logic out of the AI code and vice versa.

A module

Presentation is a module of its own rather than a layer inside each one, so every HTTP concern lives in one place.

The domain layer

Entities are Doctrine-mapped classes that expose behavior rather than setters for every field:
Identifiers are UUIDv7 values stored as binary, which keeps them sortable by creation time while staying opaque. Value objects validate in the constructor and are immutable, so an invalid value can’t reach an entity:
Repository interfaces live in the domain and are implemented in infrastructure, so handlers depend on the contract rather than Doctrine. Domain events are plain objects carrying the entity they describe, dispatched after the change. See Events.

The application layer

Commands are data holders that convert scalars into value objects and name their handler:
Handlers do the work and dispatch the event:
Queries use the same pattern: ReadPlanCommand, ListPlansCommand and CountPlansCommand are commands whose handlers return data.

The infrastructure layer

Module bootstrappers wire the module during boot: binding repository interfaces to implementations, registering navigation entries, and adding listeners. Doctrine repositories extend a shared base that is deliberately immutable: each filter returns a clone with a narrowed query, so a repository can be passed around without one caller’s filter leaking into another’s.
Two behaviors come from the base class:
  • Soft deletes. Entities with a deletedAt field are filtered out automatically.
  • Cursor pagination. Results can be sliced relative to a known ID rather than an offset, which is what the API’s starting_after and ending_before parameters use.

Layering rules

Treat this as the intended direction rather than an enforced rule: parts of the codebase reach across it. New code, including plugin code, is easier to maintain when it follows the direction.