Superseded by 0130: the DDD layers are replaced by
kind folders.
Decisions 3 and 4 are replaced by 0091:
services hold no Encore primitives and no
__generated__/ folder; stackra gen emits the Encore
app into .stackra/encore/.Decisions 1 and 2 are amended by 0126: a feature module lives at
src/modules/<feature>/ and groups its code in action-centric kind folders (models/, actions/, queries/, …), not in
DDD layers.Context
0010 fixes a service as a workspace member with asrc/main.ts
entry, and says nothing about its inside. Encore needs its primitives (api(), Subscription, CronJob, databases) in
statically analysable files, so the inside of a service must separate framework wiring from business code. Features should
be movable between services and shippable from packages, which a layer-first layout (all controllers together, all
repositories together) makes hard. This ADR amends the src/ layout of 0010 and the src/**/__tests__/ location in
0022 where they conflict.
Decision
- A service’s code is a set of feature modules at
services/<svc>/modules/<feature>/, each holding these folders as needed:core/(entities, value objects, domain events, ports; no framework imports),application/(use cases, workflows),infrastructure/(repositories, adapters, ORM mappings),presentation/(controllers, event handlers, cron handlers) and__tests__/. - Dependencies point inward:
presentation→application→core;infrastructureimplements ports declared incore.coreimports nothing from the other three. - Encore primitives live at the service root, outside
modules/: the service declaration, databases, topics, buckets. A module receives them through DI (0042), never by importing another module’s internals. - Generated Encore entry files live in
services/<svc>/__generated__/(endpoints, subscriptions, crons), produced by 0041. They are never hand-edited. - Tests stay in
__tests__/folders (0022). Module tests sit inmodules/<feature>/__tests__/; sub-folder tests sit in their own__tests__/. Where 0022 and AGENTS.md saysrc/**/__tests__/, a service reads**/__tests__/. - One module never imports another module’s
core,applicationorinfrastructure. It uses the other module’s exported tokens and published events. src/main.tsstays the service entry of 0010 unless the Encore spike (TODO) shows it cannot; any change is recorded here.
Consequences
- A feature is one folder: easy to read, move, or lift into a package.
- Two layouts exist until a service migrates;
services/exampleandservices/healthare the first to move (TODO). validate-repository.mjsand the member standard must stop assuming “all code insrc/” for services.
Enforcement
Planned — avalidate-repository.mjs check of the module folder names and an oxlint boundaries rule for the inward direction (packages/tooling/oxlint/src/boundaries.jsonc).