Domain model notation
The GraphQL SDL, diagram and use-case conventions used to record an accepted domain model.
Use this page while writing or reviewing the model. The procedure that discovers the entities, runs the six checks and obtains approval remains in Model a domain.
GraphQL SDL
Express the domain as GraphQL schema definition language in Markdown. This does not decide the API technology. SDL is the interface definition language for this artefact because it makes obligation and cardinality syntax instead of prose.
| SDL | Carries |
|---|---|
type | an entity |
field: T! | a mandatory attribute |
field: [T!]! | cardinality |
id: ID! | identity; its absence signals a value object |
enum | a closed set and the family it belongs to |
interface / union | a shared shape or a genuine either-or |
Mutation | a command — one per act in the circuit |
Query | a read use case |
input | exactly what a command needs |
A prose model says “a request has a territory.” SDL states
declaredTerritory: Territory!: absence and cardinality are no longer hidden.
Schema conventions
-
Identifiers are always English. Prose stays in the client's language. Types, fields, enum values and mutations are English in every project.
-
Carry a normative lexicon from each business term to one English identifier. See naming.
-
Cite requirements with a directive so traceability is machine-checkable.
type Request @spec(ref: "DOM-010") { status: RequestStatus! @spec(ref: "DOM-022") } -
Every nullable field is a question: why can it be absent, and at which lifecycle point does it become present?
-
Design what the checks find. Never leave missing concepts as comments in a schema that claims to describe the target system.
-
Reference other aggregates by identity:
applicantId: ID!, not an embeddedApplicant.
Diagrams
SDL states relationships one line at a time; diagrams expose their shape. Use only the view needed to answer a question prose answers badly.
| Diagram | Question it answers | Kind |
|---|---|---|
| Aggregate at creation | what is fixed when it exists | erDiagram |
| Facts added afterwards | what accumulates or stays empty | erDiagram |
| Organisation and access | which dimensions intersect | erDiagram |
| Domain hinge | how money, time or authority clusters | erDiagram |
| Lifecycle | which acts change state | stateDiagram-v2 |
| End-to-end story | where the hand-offs and holes are | sequenceDiagram |
- Split before ten entities. Two diagrams of six beat one unreadable star of twelve; the split also names a possible domain seam.
- Draw the clusters the specification omits. Payment, access history and versioning are common thin spots.
- Use client-language labels and English identifiers. Apply the same split as the schema.
- Verify every Mermaid block. Parsing proves syntax; inspect one rendered page to prove legibility.
Use cases
Each command in the circuit is one mutation; each read is one query. The signature states what the use case takes and returns.
type Mutation {
"CIR-011 — management completes its review and submits a decision"
submitDecision(input: SubmitDecisionInput!): Request!
@spec(ref: "CIR-011")
@actor(role: MANAGEMENT)
@requires(state: UNDER_REVIEW)
}Write the Cockburn body beside it: actor, goal, trigger, precondition, result, main success scenario, and material extensions. The signature and scenario have different jobs; neither replaces the other.
Keep use cases at the user-goal level: what someone sits down intending to accomplish, not update a field and not run the whole programme.