Initial commit
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
# 2. The Design Protocol (TDFDDD)
|
||||
|
||||
**Type-Driven Functional Domain-Driven Design**
|
||||
|
||||
This is the rigorous process we use to discover, design, and implement features.
|
||||
Do not skip steps.
|
||||
Do not write implementation code until the design is frozen.
|
||||
|
||||
## How to read this page
|
||||
|
||||
This page is the **current protocol** for real work in this repository.
|
||||
It keeps the explanatory logic from the original 5-phase method, but rearranges that logic to fit the new **feature-first, slice-first** process.
|
||||
|
||||
- The old 5-phase design logic still exists as the conceptual backbone.
|
||||
- The repository workflow now applies that logic across **feature artifacts** and then **one workflow slice at a time**.
|
||||
- The simpler human practice flow is preserved in [../by-hand/README.md](../by-hand/README.md).
|
||||
|
||||
## The governing idea
|
||||
|
||||
The key shift is:
|
||||
|
||||
1. **Discover the feature broadly first** so bounded contexts, handoffs, and workflow inventory are visible.
|
||||
2. **Then design and implement one workflow slice at a time** inside one bounded context.
|
||||
|
||||
This keeps the rich domain reasoning from TDFDDD while avoiding monolithic feature-wide blueprints and bloated implementation passes.
|
||||
|
||||
## Phase 1: Feature Discovery
|
||||
|
||||
_Goal: Understand the feature as a whole before designing any single slice._
|
||||
|
||||
This phase inherits the old **event storming / discovery** logic, but applies it at the **feature level**.
|
||||
The job is to identify **what happens** in the business story without worrying about code yet.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Identify the feature story, actors, commands, and outcomes.
|
||||
2. Identify the main business process and major domain facts.
|
||||
3. Capture feature-level business rules, invariants, and edge cases.
|
||||
4. Resolve the decision tree one branch at a time instead of jumping across many ambiguities at once.
|
||||
5. Ask clarifying questions one at a time, and periodically restate the current shared understanding before moving on.
|
||||
6. Identify candidate bounded contexts.
|
||||
7. Identify candidate workflow slices.
|
||||
8. When terminology stabilizes, record:
|
||||
- project-wide terms in `docs/reference/shared-language.md`
|
||||
- feature-level terms in `design/feature/<feature-slug>/discovery.md`
|
||||
9. Write `design/feature/<feature-slug>/discovery.md`.
|
||||
10. Create or update `design/feature/<feature-slug>/status.md`.
|
||||
|
||||
### Why this phase exists
|
||||
|
||||
If the feature story itself is muddy, everything downstream will be muddy too.
|
||||
A weak feature discovery causes false bounded contexts, confused workflow ownership, and shallow slice design later.
|
||||
|
||||
### Output
|
||||
|
||||
- `design/feature/<feature-slug>/discovery.md`
|
||||
- `design/feature/<feature-slug>/status.md`
|
||||
|
||||
## Phase 2: Context & Workflow Decomposition
|
||||
|
||||
_Goal: Map the feature into bounded contexts, workflow slices, and handoffs._
|
||||
|
||||
This is the major addition to the protocol.
|
||||
It sits between broad feature discovery and deep single-slice design.
|
||||
It exists so we do not accidentally core-sketch a workflow without understanding where it lives, what it owns, and what it hands off.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Confirm the bounded contexts touched by the feature.
|
||||
2. Map feature steps to workflow slices.
|
||||
3. Record cross-context handoffs and orchestration notes in `design/feature/<feature-slug>/design.md`.
|
||||
4. Create or update `design/workflows/<bounded-context-slug>/shared-language.md` for each context involved.
|
||||
5. Create `design/workflows/<bounded-context-slug>/<workflow-slug>/01-decomposition.md` for each slice.
|
||||
6. Choose a recommended slice implementation order.
|
||||
7. Update the feature status file so the decomposition and slice inventory are visible.
|
||||
|
||||
### Why this phase exists
|
||||
|
||||
The old process worked well for a single workflow, but it was easy to over-apply it to a whole feature.
|
||||
That created large sketches, blurred bounded contexts, and implementation passes that were too big.
|
||||
Decomposition fixes that by making workflow ownership and handoffs explicit before deep design starts.
|
||||
|
||||
### Output
|
||||
|
||||
- `design/feature/<feature-slug>/design.md`
|
||||
- `design/workflows/<bounded-context-slug>/shared-language.md`
|
||||
- `design/workflows/<bounded-context-slug>/<workflow-slug>/01-decomposition.md`
|
||||
- updated `design/feature/<feature-slug>/status.md`
|
||||
|
||||
## Phase 3: Slice Discovery
|
||||
|
||||
_Goal: Interrogate one workflow slice deeply enough to sketch it well._
|
||||
|
||||
This phase brings the old discovery questions back, but only for one selected workflow slice.
|
||||
The point is to prevent the later F# sketch from being shallow or under-informed.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Select exactly one workflow slice.
|
||||
2. Clarify the happy path, unhappy paths, invariants, and edge cases for that slice.
|
||||
3. Clarify what the slice owns versus what it only observes from other contexts.
|
||||
4. Record handoff assumptions.
|
||||
5. Restate the slice in plain domain language until the ownership boundary feels crisp.
|
||||
6. Update bounded-context shared language if terminology stabilizes.
|
||||
7. Write `design/workflows/<bounded-context-slug>/<workflow-slug>/02-discovery.md`.
|
||||
|
||||
### Why this phase exists
|
||||
|
||||
Your worry here is the right one: a core sketch is weak if the workflow-specific discovery is weak.
|
||||
Feature discovery should map the terrain.
|
||||
Slice discovery should interrogate the one path you are actually about to design.
|
||||
|
||||
### Output
|
||||
|
||||
- `design/workflows/<bounded-context-slug>/<workflow-slug>/02-discovery.md`
|
||||
- optional updates to `design/workflows/<bounded-context-slug>/shared-language.md`
|
||||
|
||||
## Phase 4: Core Sketch
|
||||
|
||||
_Goal: Figure out what information is required to make the decision for one workflow slice._
|
||||
|
||||
This is still the old **core sketch / policy signature** phase, now applied to exactly one bounded-context workflow.
|
||||
At this stage, the emphasis is still on **what information is needed**, not on fully modeled types.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Draft the slice policy signature in **F# pseudo-code**.
|
||||
2. Determine the required owned state needed to answer the question.
|
||||
3. Identify any observed external inputs or handoff data that the slice may read.
|
||||
4. Record the command, events, and boundary notes.
|
||||
5. Write `design/workflows/<bounded-context-slug>/<workflow-slug>/03-core-sketch.md`.
|
||||
|
||||
### What this phase is not
|
||||
|
||||
- It is **not** the full domain model yet.
|
||||
- It is **not** implementation.
|
||||
- It is **not** cross-context orchestration design.
|
||||
|
||||
The job is to reveal the decision boundary clearly enough that modeling can become precise.
|
||||
|
||||
### Output
|
||||
|
||||
- `design/workflows/<bounded-context-slug>/<workflow-slug>/03-core-sketch.md`
|
||||
|
||||
## Phase 5: Blueprint
|
||||
|
||||
_Goal: Freeze the contract in F# for one workflow slice._
|
||||
|
||||
This phase combines the old **domain modeling** and **contract finalization** logic for one slice.
|
||||
F# remains the primary design language and frozen contract before assembly.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Model the **primitives**.
|
||||
2. Model the **compounds**.
|
||||
3. Model the **aggregates / states**.
|
||||
4. Model the **events**.
|
||||
5. Finalize the signatures for:
|
||||
- `decide`
|
||||
- `apply`
|
||||
- the workflow boundary
|
||||
6. Treat the F# blueprint as the authoritative design contract.
|
||||
7. Write `design/workflows/<bounded-context-slug>/<workflow-slug>/04-blueprint.fs`.
|
||||
8. Update `design/workflows/<bounded-context-slug>/shared-model.fs` only when the context gains reusable shared F# pieces.
|
||||
|
||||
### Design standards in this phase
|
||||
|
||||
- Avoid primitive obsession.
|
||||
- Make illegal states unrepresentable.
|
||||
- Keep the policy pure.
|
||||
- Model outputs as domain facts, not booleans.
|
||||
- Separate:
|
||||
- policy for pure decisions
|
||||
- model for pure state transition math
|
||||
- workflow for impure orchestration
|
||||
|
||||
### Why F# matters here
|
||||
|
||||
F# is not an optional flavoring step.
|
||||
It is the design language that makes the contract precise before implementation starts.
|
||||
If the blueprint is weak, assembly will start inventing domain meaning instead of translating it.
|
||||
|
||||
### Output
|
||||
|
||||
- `design/workflows/<bounded-context-slug>/<workflow-slug>/04-blueprint.fs`
|
||||
- optional updates to `design/workflows/<bounded-context-slug>/shared-model.fs`
|
||||
|
||||
## Phase 6: Assembly
|
||||
|
||||
_Goal: Translate one frozen F# blueprint into code._
|
||||
|
||||
This is still the old implementation / assembly phase, but it now runs on **exactly one workflow slice at a time**.
|
||||
Assembly is a translation step from the frozen F# contract, not a redesign step.
|
||||
|
||||
### What to do
|
||||
|
||||
1. Read one `04-blueprint.fs` file.
|
||||
2. Translate F# types to Effect schemas and TypeScript constructs.
|
||||
3. Derive executable specifications from the frozen contract:
|
||||
- workflow scenarios from the command and events
|
||||
- policy examples from the decision rules
|
||||
- model invariants from the state definitions
|
||||
4. Implement using vertical **RED -> GREEN -> REFACTOR** cycles:
|
||||
- write one failing test for one observable behavior at the public seam
|
||||
- write the minimal code to make it pass
|
||||
- refactor only while green
|
||||
5. Keep tests focused on behavior through the contract, not implementation details.
|
||||
6. Concentrate review rigor at the design and seam level.
|
||||
7. Update `design/feature/<feature-slug>/status.md` for the current slice.
|
||||
|
||||
### Test style by seam
|
||||
|
||||
- **Models / Policies (Pure):** example-based tests plus property-based tests for invariants and edge cases.
|
||||
- **Workflows (Impure):** scenario tests using Effect test layers or in-memory adapters.
|
||||
- **Services / Adapters:** contract tests and integration tests against real infrastructure when needed.
|
||||
|
||||
### Review emphasis
|
||||
|
||||
- Review policies and workflows closely because they carry business meaning and orchestration correctness.
|
||||
- Review service and adapter internals mainly for seam correctness, capability behavior, and absence of misplaced business logic.
|
||||
- Trust strong domain types and contracts to reduce how much infrastructure code must be re-derived line by line.
|
||||
|
||||
## Rules that apply across phases
|
||||
|
||||
- One workflow slice belongs to one bounded context.
|
||||
- No cross-context decision logic belongs inside a workflow slice.
|
||||
- Cross-context behavior belongs in feature-level handoff and orchestration notes.
|
||||
- Shared language should exist both globally and per bounded context.
|
||||
- F# remains the primary design language and frozen contract before assembly.
|
||||
- Implementation should proceed one workflow slice at a time.
|
||||
- For the exact artifact layout, see [../reference/design-artifact-structure.md](../reference/design-artifact-structure.md).
|
||||
|
||||
## Security Verification
|
||||
|
||||
Security review is a required part of the process even though it is not itself a core design phase.
|
||||
It acts as a verification gate around the design and implementation work.
|
||||
|
||||
### Design security verification
|
||||
|
||||
Run a security review on the frozen design before or during the transition from blueprint to assembly, when the slice has enough shape to inspect.
|
||||
|
||||
Review at least:
|
||||
|
||||
- the workflow story and trust boundaries
|
||||
- the domain model and capability boundaries
|
||||
- sink categories and sanitization ownership
|
||||
- secrets handling assumptions
|
||||
- blast-radius and isolation assumptions
|
||||
- detection, recovery, and security test expectations
|
||||
|
||||
In Amp, use the `tdfddd-security-verification` skill when you want a structured, review-only report.
|
||||
|
||||
### Implementation security verification
|
||||
|
||||
Run a second security review after implementation on the changed workflow slice and its adjacent seams.
|
||||
Expand the scope only when needed.
|
||||
|
||||
Review at least:
|
||||
|
||||
- untrusted input parsing into trusted domain types
|
||||
- dangerous sinks and context-specific protections
|
||||
- over-broad capabilities or injected authority
|
||||
- secret and sensitive-config handling
|
||||
- unsafe dynamic behavior
|
||||
- security-focused test coverage at risky seams
|
||||
|
||||
In Amp, use the `tdfddd-security-verification` skill for a structured, review-only report over code and nearby surfaces.
|
||||
Reference in New Issue
Block a user