Context
0040 organised services as DDD layers. Accepted 0091 and 0126 already removed the generated folder and set the feature-module path. The owner’s intent-map item P9 and the audit’s module-layout answer (audit Q9) replace the DDD layers with kind folders, organised around what each file does.Decision
- A feature module lives at
src/modules/<feature>/. Its code sits in kind folders:models/,actions/,queries/,services/,events/,listeners/,workflows/,policies/,permissions/,settings/andcontracts/. interfaces/,types/,constants/,tokens/,errors/anddecorators/appear once a module has two or more files of that kind (0128 decision 4).raw/holds only@Controllerraw endpoints (webhooks, streaming,/api/auth/*). Actions never use it.- There are no
controllers/,dtos/,repositories/orpresentation/folders. - Dependencies point inward. Actions, listeners and workflows depend on services and models. Models import from no other folder.
- Where the sources disagree, the later one wins. P9 names a
permissions.tsfile; the audit (L547) names apermissions/folder, and the folder wins.
Consequences
- Services are organised by what they do, and an agent finds an action in
actions/. - The
services/encorescaffold template, which still uses the old shape, is replaced with plain TypeScript (gap D). - The validator’s
checkServiceUnitmust describe this shape. Until it does, the validator and this ADR disagree.
Enforcement
planned —checkServiceUnit in tools/scripts/validate-repository.mjs checks the kind-folder set and forbids the
controllers/, dtos/, repositories/ and presentation/ folders. Dependency direction is planned for the
packages/tooling/oxlint/boundaries.jsonc rules.
Alternatives
- Keep DDD layers (0040): superseded by this ADR, per the owner’s audit answer.
- One flat
modules/<feature>/folder with no kinds: rejected, because it hides the action-first shape.
Supersedes and sources
Supersedes: 0040. Builds on: 0126. Sources: owner intent-map item P9 (stackra-notes/owner-docs-intent-map.md, Part 4, accepted L584); audit Q9 (stackra-decisions-2026-10-19.md L547,
2026-10-20); gap B4 (layout half).