# Modular Hexagonal DDD — CORE ONE-SHOT (framework-agnostic) > Fetch this when you need Core only. Host apply files embed the same Core as Part B. > **Core version:** `1.0.0-draft` ## B1. Purpose Build applications as **replaceable bounded-context modules** using Hexagonal Architecture (ports & adapters) + DDD. This docs site is the **sole canon**; consuming repos keep thin pointers, not a forked essay. ## B2. Module layout (MUST) ```text {Module}/ Application/ # UseCases, Application DTO, Providers / composition root Domain/ # Entities, Ports, Events, Enums, Domain DTOs Infrastructure/ # Persistence adapters, ExternalServices (ACL), Config, listeners UI/ # Controllers, Routes, validation, admin UI, console Shared/ # Promoted technical ports/adapters only (after promote rule) ``` Host roots vary (`app/Modules`, `src/Modules`, packages). **Roles do not.** ## B3. Strictness ladder (MUST) | Strictness | Area | Allowed | Forbidden | | ---------- | ---- | ------- | --------- | | Hardest | **Domain** | Own Domain types + Shared kernel ports | Other modules; host facades/helpers; ORM; framework traits on Domain Events | | Strict | **Application Use Cases / App DTOs** | Own Domain + Shared ports | Facades, ORM, foreign Application/Domain, peer `*ModuleInterface` | | Relaxed | **Composition root** | Container binds, routes, config merge | Business rules | | Outer | **Infrastructure & UI** | Framework, ORM, HTTP, ACL adapters, admin | Leaking ORM/foreign Domain into Domain/Use Cases | Dependency direction: **Domain ← Application ← Infrastructure/UI**. Ports in Domain; adapters in Infrastructure. ## B4. Golden flow (MUST) ```text UI → Application DTO → first-level *UseCase::__invoke → Domain (Entity / Domain service) → Domain Port → Infrastructure adapter (ORM / ACL / HTTP) → back as Entity / result → UI presents ``` ## B5. Use Cases & DTOs (MUST) - First-level: `Application/UseCases/{Capability}/SomethingUseCase` with single public `__invoke`. - Nested helpers: **no** `UseCase` suffix; **not** called from UI. - Mirror `{Capability}/` for DTOs and Ports. - ACL need ports: `Domain/Ports/Acl/`. Module façades: `Domain/Ports/Module/`. - Never create a literal `Feature/` directory. - Application DTO = UI/CLI input. Domain DTO = intra-module only. - Other modules never call Use Cases — only ACL / Events. ## B6. Cross-module bridges (MUST) Application/Domain of A **never** import Application/Domain of B. | Need | Bridge | | ---- | ------ | | Peer answer **now** | **Sync ACL**: local `{Need}PortInterface` → Infra ACL adapter → thin peer `{This}ModuleInterface` | | Peer reacts **later** | **Async Domain Event** → consumer Infra **translation listener** → inbound Use Case | - Mapping only in ACL adapter; façades thin + HTTP-mappable; Prefer ACL **validate before** local commit. - Events: pure Domain class; Shared `EventDispatcherInterface`; `eventId` + `occurredAt` + `schemaVersion` + rich happy-path payload; idempotent consumers; no Domain re-fetch on happy path; prefer outbox. - No cross-module write transaction. Reports: ACL reads or owned projections. ## B7. Shared promote rule (MUST) | Situation | Where | | --------- | ----- | | Tech used by one module | That module’s Infrastructure | | Same tech used by ≥2 modules | Promote to Shared | | Cross-module **business** concept | Never Shared — ACL / Events | Typical Shared: `DomainException`, `DatabaseTransactionInterface`, `EventDispatcherInterface`, `ClockInterface`, `ConfigReaderInterface`, `Ensure`. ## B8–B9. Persistence & UI (MUST) - Map persistence records ↔ Domain Entities in Infrastructure; never leak ORM into Use Cases/Domain. - UI: authorize → DTO → Use Case → present. ## B10. Decision tree ```text Only this module? → Golden flow Need peer now? → ACL Peer later? → Event Multi-step? → Orchestration (still ACL+Events) Report across contexts? → Projection / ACL read Tech in 2+ modules? → Shared Business in 2+ modules? → ACL/Events — never Shared ``` ## B11. Anti-patterns Peer imports in Use Cases; god façades; thin-ID events; Shared business enums; ORM in Domain; Entity extends ORM; literal `Feature/`; cross-module DB TX; ORM joins across modules for policy. ## B12. Examples `Ordering`, `Warehouse`, `Directory`, `Identity` only — rename to your domains. ## B13. Quality assertions Boundary tests must fail CI if: foreign Application/Domain imports; peer `*ModuleInterface` in Use Cases; ORM/facades in Domain/Use Cases; literal `Feature/` folders. Also: behaviour tests, formatter, static analysis, event idempotency.