Tach DDD / Feature Slice Boundary Standard
Tach DDD / Feature Slice Boundary Standard
Section titled “Tach DDD / Feature Slice Boundary Standard”FractalOps Backend uses layer-first DDD. Layer fixes dependency authority first; bounded context names ownership inside that layer; feature names one outcome.
Canonical Shape
Section titled “Canonical Shape”backend/src/fractalops/ domain/<context>/features/<feature>/ application/<context>/features/<feature>/ adapters/<context>/features/<feature>/ interfaces/<transport>/<context>/features/<feature>/ orchestration/<context>/features/<feature>/ platform/Do not restore contexts/<context>/<layer>/, top-level features/, anonymous
tests/, or source-era infrastructure/ and presentation/ dialects.
Dependency direction:
domain <- application <- adapters/interfaces <- orchestration platform -> composition only- Domain owns pure rules and ports. No FastAPI, Pydantic, or SQLAlchemy.
- Application owns use cases. No adapter, interface, orchestration, or platform imports.
- Adapters implement owned ports and translate provider data.
- Interfaces bind HTTP, CLI, or MCP transports.
- Orchestration composes cross-feature process flow.
- Platform owns runtime wiring, configuration, telemetry, and infrastructure clients.
Sibling features collaborate through public contracts or ports. Deep implementation imports are defects.
Optional CQRS
Section titled “Optional CQRS”CQRS lives inside one application feature only when read and write behavior genuinely diverge:
application/<context>/features/<feature>/ commands/ queries/Do not create empty command/query folders or split CRUD mechanically.
Tach Gate
Section titled “Tach Gate”Repository tach.toml is executable authority:
tach check --dependencies --interfaces --exacttach check-externalRepresentative rules:
[[modules]]path = "fractalops.application.*.features"cannot_depend_on = [ "fractalops.adapters.*.features", "fractalops.interfaces.*.*.features", "fractalops.orchestration.*.features", "fractalops.platform.**",]
[[modules]]path = "fractalops.domain.*.features"cannot_depend_on_external = ["fastapi", "pydantic", "sqlalchemy"]cannot_depend_on = [ "fractalops.application.*.features", "fractalops.adapters.*.features", "fractalops.interfaces.*.*.features", "fractalops.orchestration.*.features", "fractalops.platform.**",]Do not weaken rules to hide a violation. Move behavior to its owner or introduce a small public port.
Test Co-location
Section titled “Test Co-location”Tests stay beside the smallest behavior owner:
domain/<context>/features/<feature>/*_test.pyapplication/<context>/features/<feature>/*_test.pyadapters/<context>/features/<feature>/*_contract_test.pyinterfaces/<transport>/<context>/features/<feature>/*_test.pyCross-repository runtime journeys belong in Assembly
scenarios/<outcome>/. Generated contract conformance belongs in Contract.
Frontend tests stay beside the component, route, or feature they exercise.
Migration Rule
Section titled “Migration Rule”Move one outcome at a time:
- Name owner context and feature.
- Move behavior and its tests together.
- Replace deep sibling imports with public contracts.
- Run focused tests, Tach exact gate, and external dependency gate.
- Delete compatibility facade after live references reach zero.
Compatibility trees are delete-only. Existing stale ADR or documentation does not override current source, Tach, and accepted ADR lineage.