
M09 Domain
Model domain concepts in Rust with DDD patterns—entities, value objects, aggregates, and invariants—before wiring persistence or APIs.
Overview
m09-domain is an agent skill for the Build phase that guides domain-driven design in Rust—mapping entities, value objects, aggregates, and repositories to ownership-safe patterns.
Install
npx skills add https://github.com/zhanghandong/rust-skills --skill m09-domainWhat is this skill?
- Maps six domain concepts (Entity, Value Object, Aggregate Root, Repository, Domain Event, Service) to Rust patterns and
- Three-step thinking prompt: identity, invariants, and data ownership before defining types
- Guidance on private fields, validated constructors, and type-state for always-valid domain objects
- Bilingual trigger coverage including 领域模型 and 领域驱动设计 for DDD-oriented Rust work
- Layer 2 design-choice framing: role of each concept in the domain before coding
- 6 domain concept → Rust pattern mappings in the reference table
- 3-step thinking prompt before creating a domain type
Adoption & trust: 711 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You know the business rules in plain language but are unsure how to express entities, invariants, and aggregate boundaries in Rust without fighting the borrow checker later.
Who is it for?
Solo builders designing a new Rust service or refactoring toward DDD with clear aggregate roots and validated constructors.
Skip if: Teams that only need syntax help, one-off scripts with no domain rules, or projects where persistence schema is frozen and domain modeling is already documented elsewhere.
When should I use this skill?
CRITICAL: Use for domain modeling when triggers include domain model, DDD, entity, value object, aggregate, repository pattern, business rules, validation, or invariant.
What do I get? / Deliverables
You get a consistent domain concept → Rust pattern map and a short checklist so new types reflect identity, invariants, and ownership before you implement repositories or HTTP handlers.
- Domain type decisions (entity vs value object, aggregate boundaries)
- Invariant and ownership notes aligned to Rust patterns
Recommended Skills
Journey fit
Domain modeling is a core Build-phase design step where backend structure and business rules are decided before implementation details. Backend subphase is the canonical shelf for entity/value-object design, repository traits, and ownership choices in Rust services.
How it compares
Use for design-time DDD choices in Rust, not as a substitute for an ORM integration or automatic schema generator skill.
Common Questions / FAQ
Who is m09-domain for?
Rust developers and solo builders using agent-assisted coding who need structured domain modeling before backend implementation.
When should I use m09-domain?
During Build when defining entities, value objects, aggregates, repositories, or business invariants—or when SKILL.md triggers mention domain model, DDD, or 领域驱动设计.
Is m09-domain safe to install?
Review the Security Audits panel on this Prism page and your org policy before adding any third-party skill; this skill is documentation-only procedural knowledge with no stated tool permissions.
SKILL.md
READMESKILL.md - M09 Domain
# Domain Modeling > **Layer 2: Design Choices** ## Core Question **What is this concept's role in the domain?** Before modeling in code, understand: - Is it an Entity (identity matters) or Value Object (interchangeable)? - What invariants must be maintained? - Where are the aggregate boundaries? --- ## Domain Concept → Rust Pattern | Domain Concept | Rust Pattern | Ownership Implication | |----------------|--------------|----------------------| | Entity | struct + Id | Owned, unique identity | | Value Object | struct + Clone/Copy | Shareable, immutable | | Aggregate Root | struct owns children | Clear ownership tree | | Repository | trait | Abstracts persistence | | Domain Event | enum | Captures state changes | | Service | impl block / free fn | Stateless operations | --- ## Thinking Prompt Before creating a domain type: 1. **What's the concept's identity?** - Needs unique identity → Entity (Id field) - Interchangeable by value → Value Object (Clone/Copy) 2. **What invariants must hold?** - Always valid → private fields + validated constructor - Transition rules → type state pattern 3. **Who owns this data?** - Single owner (parent) → owned field - Shared reference → Arc/Rc - Weak reference → Weak --- ## Trace Up ↑ To domain constraints (Layer 3): ``` "How should I model a Transaction?" ↑ Ask: What domain rules govern transactions? ↑ Check: domain-fintech (audit, precision requirements) ↑ Check: Business stakeholders (what invariants?) ``` | Design Question | Trace To | Ask | |-----------------|----------|-----| | Entity vs Value Object | domain-* | What makes two instances "the same"? | | Aggregate boundaries | domain-* | What must be consistent together? | | Validation rules | domain-* | What business rules apply? | --- ## Trace Down ↓ To implementation (Layer 1): ``` "Model as Entity" ↓ m01-ownership: Owned, unique ↓ m05-type-driven: Newtype for Id "Model as Value Object" ↓ m01-ownership: Clone/Copy OK ↓ m05-type-driven: Validate at construction "Model as Aggregate" ↓ m01-ownership: Parent owns children ↓ m02-resource: Consider Rc for shared within aggregate ``` --- ## Quick Reference | DDD Concept | Rust Pattern | Example | |-------------|--------------|---------| | Value Object | Newtype | `struct Email(String);` | | Entity | Struct + ID | `struct User { id: UserId, ... }` | | Aggregate | Module boundary | `mod order { ... }` | | Repository | Trait | `trait UserRepo { fn find(...) }` | | Domain Event | Enum | `enum OrderEvent { Created, ... }` | ## Pattern Templates ### Value Object ```rust struct Email(String); impl Email { pub fn new(s: &str) -> Result<Self, ValidationError> { validate_email(s)?; Ok(Self(s.to_string())) } } ``` ### Entity ```rust struct UserId(Uuid); struct User { id: UserId, email: Email, // ... other fields } impl PartialEq for User { fn eq(&self, other: &Self) -> bool { self.id == other.id // Identity equality } } ``` ### Aggregate ```rust mod order { pub struct Order { id: OrderId, items: Vec<OrderItem>, // Owned children // ... } impl Order { pub fn add_item(&mut self, item: OrderItem) { // Enforce aggregate invariants } } } ``` --- ## Common Mistakes | Mistake | Why Wrong | Better | |---------|-----------|--------| | Primitive obsession | No type safety | Newtype wrappers | | Public fields with invariants | Invariants violated | Private + accessor | | Leaked aggregate internals | Broken encapsulation | Methods on root | | String for semantic types | No validation | Validated newtype | --- ## Related Skills | When | See | |