Implement the 004-edit-combatant feature that adds the possibility to change a combatants name

This commit is contained in:
Lukas
2026-03-04 10:05:13 +01:00
parent aed234de7b
commit a9df826fef
16 changed files with 854 additions and 5 deletions

View File

@@ -0,0 +1,59 @@
# 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**:
- `newName` is non-empty and not whitespace-only
- `id` matches a combatant in `encounter.combatants`
**Postconditions**:
- The combatant with matching `id` has `name` set to `newName`
- `activeIndex` and `roundNumber` unchanged
- Combatant list order unchanged
- Exactly one `CombatantUpdated` event emitted
**Error cases**:
- `id` not found → `DomainError { code: "combatant-not-found" }`
- `newName` empty/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"` |