Modular Hexagonal DDD — ONE-SHOT APPLY (slim)
Self-contained. An AI agent should fetch this file only and execute it. Core version:
1.0.0-draftShort HTML entry:/slim· This file:/apply/slim.full.mdAI-neutral: assistant files are optional; architecture does not require any AI vendor. Host baseline researched: see Part C header (versions as of 2026-08).
0. Agent mandate
You are bootstrapping a slim application repository (not the docs site).
- Treat this document as the complete working standard for this session.
- Execute Part D in order after reading Parts A–C.
- When writing module code, obey Part B (Core) and Part C (host).
- Do not create a git commit unless the human explicitly asks.
- Rename illustrative contexts
Ordering,Warehouse,Directory,Identityto the human’s domains. - If AI vendor is
none, skip Part E.
Programmer prompt
Apply Modular Hexagonal DDD from <ORIGIN>/apply/slim.full.md
AI assistant: <cursor|claude|gemini|copilot|generic|none>
Bounded contexts: <list>
Do not commit unless I ask.
Part A — Design test
If the peer module is deleted and replaced by HTTP, does this module’s Application and Domain still compile?
Part B — Complete Core architecture
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)
{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)
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}/SomethingUseCasewith single public__invoke. - Nested helpers: no
UseCasesuffix; 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
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.
Part C — Slim host mapping
| Target | Slim 4.15.x (microframework; PHP 8.2+ recommended) |
| Docs | https://www.slimframework.com/docs/v4/ |
| Adapter HTML | <ORIGIN>/v1/adapters/slim |
Slim provides routing + middleware + PSR-7/15. You bring the container, ORM, and queue.
| Core | Slim place |
|---|---|
| Module root | src/{Module}/ |
| Shared | src/Shared/ |
| Composition root | PHP-DI (or other PSR-11) definitions + routes.php |
| Persistence | Chosen library in Infrastructure only |
| ACL / Events | Infra services + optional queue worker |
| UI | Invokable Action classes / controllers |
Keep public/index.php thin. See deep pages under /v1/adapters/slim/*.
Part D — Apply procedure (Slim)
- Confirm Slim 4 app + PSR-11 container
- README → one-shot URL
- ROADMAP / optional PRD
- Copy ARCHITECTURE.full.md to
.ai/ - PSR-4 Modules + Shared
- Bind ports; wire routes to UI Actions → Use Cases
- Choose persistence + migration tool; quarantine ORM
- Part E (AI) — no commit unless asked
Part F — Sketch
Route → PlaceOrderAction → Use Case → ACL port → Warehouse façade service.
Part G — Done checklist (standard)
Part E — Assistant files (optional)
Skip if AI vendor is none.
Create shared folder:
.ai/modular-hexagonal-ddd/
ARCHITECTURE.full.md # copy of the host one-shot you fetched
RULES.core.md
SKILL.md
CHECKLIST.md
slim-host.md # host-only notes from Part C
E0 — RULES.core.md
# Modular Hexagonal DDD — Core rules
Canon: <ORIGIN>/v1/core (1.0.0-draft)
One-shot: <ORIGIN>/apply/slim.full.md
Local: .ai/modular-hexagonal-ddd/ARCHITECTURE.full.md
1. Domain hardest: no host framework, ORM, other modules.
2. Use Cases: own Domain + Shared ports only.
3. Cross-module: ACL or Domain Events only.
4. Thin façades; rich events (eventId, schemaVersion); idempotent consumers.
5. No cross-module write TX; ACL validate-before-commit.
6. Shared = technical ≥2 modules only.
7. *UseCase + __invoke; no literal Feature/ folders.
8. Design test: peer→HTTP, Application/Domain still compile.
E1 — SKILL.md
---
name: modular-hexagonal-ddd
description: Enforce Modular Hexagonal DDD. Modules, ACL, Events, Shared, Use Cases.
---
Follow .ai/modular-hexagonal-ddd/ARCHITECTURE.full.md
E2 — CHECKLIST.md
- [ ] First-level *UseCase entry
- [ ] App DTO → __invoke
- [ ] I/O via Domain ports
- [ ] No ORM/facades in Application/Domain
- [ ] Sync peer → local ACL port → thin façade
- [ ] Async → rich event + translation listener → inbound UC
- [ ] Idempotent eventId
- [ ] No cross-module DB TX
- [ ] No foreign Application/Domain imports
- [ ] Shared only technical ≥2
- [ ] No Feature/ directories
- [ ] Replaceability test = yes
E3 — Cursor
.cursor/rules/modular-hexagonal-ddd.mdc← E0 + path to ARCHITECTURE.full.md.cursor/rules/slim-host.mdc← Part C summary.cursor/skills/modular-hexagonal-ddd/SKILL.md← E1
E4 — Claude
CLAUDE.md← pointer to ARCHITECTURE.full.md + E0- Shared
.ai/modular-hexagonal-ddd/*
E5 — Gemini
GEMINI.mdor.gemini/instructions.md← pointer + E0- Shared
.ai/*
E6 — GitHub Copilot
.github/copilot-instructions.md← E0 + short host section
E7 — Generic
AGENTS.mdpointing at.ai/modular-hexagonal-ddd/ARCHITECTURE.full.md
E8 — Multiple vendors
One shared .ai/modular-hexagonal-ddd/; vendor entry files only point to it.