1.6 KiB
1.6 KiB
Data Model: Edit Combatant
Feature: 004-edit-combatant Date: 2026-03-03
Entities
Combatant (unchanged)
| Field | Type | Notes |
|---|---|---|
| id | CombatantId (branded string) | Immutable identity |
| name | string | Mutable — this feature updates it |
Encounter (unchanged structure)
| Field | Type | Notes |
|---|---|---|
| combatants | readonly Combatant[] | Edit replaces name in-place by mapping |
| activeIndex | number | Preserved during edit |
| roundNumber | number | Preserved during edit |
Events
CombatantUpdated (new)
| Field | Type | Notes |
|---|---|---|
| type | "CombatantUpdated" | Discriminant |
| combatantId | CombatantId | Which combatant was renamed |
| oldName | string | Name before edit |
| newName | string | Name after edit |
Added to the DomainEvent union type.
State Transitions
editCombatant(encounter, id, newName)
Preconditions:
newNameis non-empty and not whitespace-onlyidmatches a combatant inencounter.combatants
Postconditions:
- The combatant with matching
idhasnameset tonewName activeIndexandroundNumberunchanged- Combatant list order unchanged
- Exactly one
CombatantUpdatedevent emitted
Error cases:
idnot found →DomainError { code: "combatant-not-found" }newNameempty/whitespace →DomainError { code: "invalid-name" }
Validation Rules
| Rule | Condition | Error Code |
|---|---|---|
| Name must be non-empty | newName.trim().length === 0 |
"invalid-name" |
| Combatant must exist | No combatant with matching id |
"combatant-not-found" |