Extract the **{AGGREGATE_NAME}** aggregate from the codebase **{CODEBASE_NAME}** and describe it as a standalone DDD aggregate, suitable for import into Qlerify (an event storming / domain modeling tool).

**Isolating the Aggregate from the Service Layer**

Most business applications / backend systems have two command layers:

1. **Service layer** — workflows or application services that coordinate commands across multiple aggregates.
2. **Aggregate-level commands** — the actual mutation surface of the aggregate itself.

When modeling the aggregate in isolation, peel away the service layer to expose the underlying aggregate commands.

Concretely: if the codebase has a service or orchestrator that coordinates another module and then calls a method on the **{AGGREGATE_NAME}** module, the aggregate command is that method call — not the orchestration name. The orchestration stays outside; the aggregate only knows about the data it receives.

**What to Capture**

- **Aggregate Root Entity** — the top-level entity through which all mutations enter. Identify it by ownership of children and by being the service entry point.
- **Related Entities** — children with their own identity and individual lifecycle (add/update/remove).
- **Value Objects** — children replaced wholesale (set-replacement semantics), with no independent lifecycle. They may still have technical IDs in the implementation — still treat them as VOs.
- **Commands** — each one representing a distinct state change of the aggregate, with a corresponding domain event. If one command always triggers another command, merge them here. Find a granularity that is coarser than per-attribute changes but finer than just create/update/delete for the whole aggregate. The right level is one where each command/event pair represents a business-meaningful action that stakeholders can reason about in an event storming session. VOs do not have their own lifecycle; they are only fully replaced. For value objects, usually only one command is needed to set the value; clearing or removal can be modeled as setting a blank or empty value. When capturing commands, note which fields are create-only — attributes required on create but not available on update.
- **Domain Events** — one event per command, forming 1:1 pairs. Aim for 8–20 events per aggregate, though this is not a strict rule. Too many will make the event storming board hard for stakeholders to review. Too few will make the system harder to reason about. For value objects, usually only one command is needed to set the value; clearing or removal can be modeled as setting a blank or empty value.
- **Read Models / Queries** — queries needed by the client. These can contain computed/derived fields (totals, counts) that exist on API responses but not on entity models. When a field is clearly projection-only (totals, rollups), prefer listing it here instead of also on entity/VO attribute tables. Include short descriptions of calculated fields if not obvious.
- **Attributes** — ALL fields for every entity and VO: name, type, required/optional, defaults, notes. Prefer domain/type definitions over database schema. Describe relationships in type form (e.g. Order.items: LineItem[]) rather than database form.
- **Invariants** — business rules: required fields, non-negative amounts, set-replacement semantics (e.g. "adjustments are always replaced atomically — you cannot patch a single one"), snapshot patterns (e.g. product data copied at add-time), computed-only fields.
- **Tests** — for each aggregate command, extract tests that validate the command's behavior at the aggregate boundary. If only service-level or orchestration tests exist, extract only the part that proves aggregate behavior and ignore external orchestration. Use business language, not code identifiers or framework details. e.g. "Given no Order exists, When the caller creates an Order with a valid customer id, Then an Order is returned with an assigned id."
- **External References** — fields pointing to other aggregates by ID only (e.g. customerId → Customer in a separate bounded context). Do not model the external aggregate's internals.

**Scope**

Model only the **{AGGREGATE_NAME}** aggregate boundary. Cross-aggregate orchestration (e.g. completing one aggregate triggering creation of another, external rule evaluation computing values passed in) lives outside — note that it exists, but do not model it. Include a minimal description of the hierarchy of the entity / VO relationships. List cross-aggregate links for reference only.

Include a short description for each entity and each attribute.

Model the aggregate as a **domain/type model**, not a persistence model. Avoid database terms like foreign keys, join tables, and cascade deletes unless they are needed to explain a business rule.

For nested members inside the aggregate, describe ownership only from the parent type (e.g. Order.items: LineItem[]) and omit internal back-reference fields like parent_id or foreign key fields unless they are themselves domain-significant.
