# Skara Brae — Use-Case Specifications `Skara Brae` — OpenUP Requirements · version 2.0 (2026-10-05, restructured to the OpenUP use-case-specification template; scenario content unchanged from version 1.0). Scope: the **existing implemented system** (server MVP as of `main`, formerly `wi-2-architecture-cleanup` @ 899fde8). Every flow below is derived from actual handler code (`crates/sb-api/src/routes/mod.rs`) — status codes cited are the implemented behavior and are normative. The EA model (`docs/openup/model/skara-brae.eapx`) carries the same scenarios with per-step actors; markdown and model must agree (drift rule). # Use Case Overview | ID | Use Case | Actors | Includes / Extends | |---|---|---|---| | UC-01 | Register Account | Guest | — | | UC-02 | Authenticate | Guest | — | | UC-03 | Manage Characters | Player, Administrator | — | | UC-04 | Browse Game Catalogue | Player | — | | UC-05 | Train Stat | Player | includes Regenerate Resources | | UC-06 | Manage Equipment | Player | — | | UC-07 | Trade at Shop | Player | — | | UC-08 | Run Adventure | Player | includes Regenerate Resources, Resolve Combat | | UC-09 | Heal at Temple | Player | — | | UC-10 | Practice Bard Song | Player | — | | UC-11 | Study Magic | Player | — | | UC-12 | Level Up at Review Board | Player | — | ![Skara Brae Use Case Overview](use-case-overview.png) *Figure 1: Use case overview (rendered from the EA model via `scripts/openup/export-diagram-images.ps1`).* Shared sub-flow **Regenerate Resources**: the system recomputes time-based regeneration **at specific call sites only** — list characters, view character, run adventure, and train stat (routes/mod.rs:264–266, 331, 442, 642). Energy +1 per 180 s, nerve +1 per 300 s, HP +5% of max per 300 s (only if alive and injured), capped at maxima; `last_regen` advances to now. It is **not** applied by equip/unequip, gym view, shop, heal, songs, spells, or level-up. --- # UC-01 Register Account ## Brief Description Open registration: a guest submits name and password and receives a JWT with the `player` role. No precondition. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Guest | Primary | Unauthenticated caller; only register/login are open. | ## Preconditions and Context Precondition: none. ## Basic Flow of Events 1. Guest submits name (3–32 chars) and password (≥ 6 chars). 2. System verifies the name is unused → 409 CONFLICT if taken. 3. System hashes the password (argon2), assigns the `player` role and the next id, persists the user. 4. System issues a JWT (HS256, `player` role) and returns `{token, user_id, name, role}`. ## Alternative and Exception Flows ### Invalid input (Alternate) 1. System rejects a name outside 3–32 chars or a password under 6 chars with 400. ### Hashing or token failure (Exception) 1. System fails during password hashing or JWT creation → 500; no user is persisted. ## Post-conditions - User persisted with `player` role; JWT issued and returned. ## Special Requirements - Passwords hashed with argon2, verification constant-time (NFR-16). - JWT HS256, 24 h expiry (NFR-17); no secrets in code (NFR-18). # UC-02 Authenticate ## Brief Description Login with name and password; issues a JWT carrying the user's real role. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Guest | Primary | Unauthenticated caller; only register/login are open. | ## Preconditions and Context Precondition: none. ## Basic Flow of Events 1. Guest submits name and password. 2. System finds the user (401 if unknown) and verifies the password hash (401 on mismatch). 3. System issues a JWT carrying the user's real role (`admin`/`player`) and returns `{token, user_id, name, role}`. ## Alternative and Exception Flows ### Credentials rejected (Alternate) 1. Unknown name or wrong password → 401 UNAUTHORIZED. ### Token creation failure (Exception) 1. JWT creation fails → 500. ## Post-conditions - JWT issued with the user's real role; no persistent state change. ## Special Requirements - The middleware guards all UC-03…12 routes with this token (NFR-17). # UC-03 Manage Characters ## Brief Description Create, list and view characters. Admin may act for any user (read-only view). ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | | Administrator | Supporting | Player with elevated rights (`role = admin`); may view any user's and any character's resources read-only. | ## Preconditions and Context Precondition (create): target user exists. Admin may act for any user. ## Basic Flow of Events (create) 1. Player submits character name, race, class for their user id. 2. System validates the target user exists (404) and the trimmed name is 1–32 chars (400). 3. System rolls stats (d6+5 base 6–16 per stat ± race modifiers), computes max HP/energy/nerve from class, grants starting gold (50) and level-1 class spells to casters. 4. System assigns the next character id, stores and persists the character; returns it fully. ## Alternative and Exception Flows ### List / view (Alternate) 1. Player lists their characters (Admin: any user's); the system applies Regenerate Resources to each returned character and returns them. 2. Player views one character; the system applies regen then returns it. ### Access denied (Alternate) 1. Foreign user/character without admin role → 403 FORBIDDEN. ### Not found (Alternate) 1. User or character not found → 404. ### Invalid name (Alternate) 1. Trimmed name outside 1–32 chars → 400. ## Post-conditions - (create) Character persisted with rolled stats, class resources and starting gold. - (view/list) Regeneration applied to returned characters. ## Special Requirements - Stat rolls use the injected rng — deterministic under seed (NFR-05, WI-1). # UC-04 Browse Game Catalogue ## Brief Description Races, classes, items (type/quality/slot filters), enemies, adventure zones from static game data. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: authenticated. ## Basic Flow of Events 1. Player requests the catalogue: races, classes, items (optional type/quality/slot filters), enemies, or adventure zones. 2. System returns static game data loaded from `skara-brae-common` JSON (class info is enriched with `is_caster`). ## Alternative and Exception Flows ### Unknown item (Alternate) 1. Single item by unknown id → 404. ### Empty filter result (Alternate) 1. Filters may return an empty list (not an error). ## Post-conditions - None (read-only). ## Special Requirements - Catalogue is compiled-in and parsed once behind `LazyLock`; lock-free reads (NFR-04). - Content source is `skara-brae-common` JSON, never duplicated in code (NFR-13). # UC-05 Train Stat ## Brief Description Train a stat at a training ground; costs 1 energy + gold. Includes Regenerate Resources. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists and caller may act on it. ## Basic Flow of Events 1. Player selects a training ground (strength / dexterity / constitution / intelligence / luck) and submits the stat name. 2. System applies Regenerate Resources. 3. System checks energy ≥ 1 and gold ≥ training cost (cost grows ~1.3× per 10 stat points). 4. System deducts 1 energy and the gold cost, increments the stat; constitution training recomputes max HP (current HP clamped). 5. System persists and returns `{success, message, character}`. ## Alternative and Exception Flows ### Foreign character (Alternate) 1. Character owned by another user without admin role → 403. ### Not found (Alternate) 1. Character not found → 404. ### Not enough energy (Alternate) 1. Energy < 1 → 422. ### Not enough gold (Alternate) 1. Gold below training cost → 422. ### Unknown stat (Alternate) 1. Unknown stat name → 400. ## Post-conditions - Stat incremented; energy −1 and gold −cost deducted; max HP recomputed on constitution training; character persisted. ## Special Requirements - Rule failures flow through `DomainError` → central status mapping (CON-04). # UC-06 Manage Equipment ## Brief Description Equip from inventory / unequip back to inventory. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists and caller may act on it. ## Basic Flow of Events (equip) 1. Player submits an item id from their inventory. 2. System moves the item from inventory to its slot; a previously equipped item in that slot returns to inventory. 3. System persists and returns the updated character. ## Alternative and Exception Flows ### Unequip (Alternate) 1. Player submits a slot name; the system moves the equipped item back to inventory. ### Foreign character (Alternate) 1. Foreign character without admin role → 403. ### Not found (Alternate) 1. Character or item not found → 404. ### Item not in inventory (Alternate) 1. Equip target not in inventory → 400. ### Empty slot (Alternate) 1. Unequip on a slot with nothing equipped → 400. ## Post-conditions - Item moved between inventory and equipment slot; character persisted. ## Special Requirements - Rule failures flow through `DomainError` → central status mapping (CON-04). # UC-07 Trade at Shop ## Brief Description Buy from (always-stocked + rotating) shop stock or sell inventory items. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists and caller may act on it. ## Basic Flow of Events (buy) 1. Player views the shop: always-stocked items plus rotating stock (with quantities) alongside their inventory. 2. Player submits `buy` + item id. 3. System checks gold ≥ price (422), and for non-always-in-stock items decrements the limited stock (410 GONE if 0). 4. System deducts gold, adds the item to inventory, persists character and stock; returns `{success, message, gold}`. ## Alternative and Exception Flows ### Sell (Alternate) 1. Player submits `sell` + item id; system removes the first matching inventory item, pays half the item value, increments shop stock for non-permanent items. ### Bad request (Alternate) 1. Unknown action, or sell of an item not owned → 400. ### Not found (Alternate) 1. Item not found → 404. ### Insufficient gold (Alternate) 1. Gold below price → 422. ### Stock exhausted (Alternate) 1. Limited stock at 0 → 410. ## Post-conditions - Buy: gold deducted, item in inventory, stock decremented; Sell: item removed, half value paid, stock incremented; persisted. ## Special Requirements - Shop business logic is handler-side recorded debt (Architecture Notebook D1, Q3). # UC-08 Run Adventure ## Brief Description Zone adventure with weighted enemy pick and turn-based combat. Includes Regenerate Resources, Resolve Combat. Exception: encounter references an unknown enemy → 500 (post WI-2; previously a panic). WI-2 design driver (`sb_core::adventure` extraction). ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists and caller may act on it. ## Basic Flow of Events 1. Player requests an adventure for a zone (default `skara_brae_streets`). 2. System validates the zone (404) and applies Regenerate Resources. 3. System refuses incapacitated characters (HP ≤ 0 → 400) and characters with nerve below the zone cost (422); otherwise deducts the nerve cost. 4. System draws one enemy from the zone's weighted encounter table. 5. System resolves turn-based combat: open-ended d100 attack rolls, OB vs DB, RoleMaster crit tables with level-gap damage caps, active bard song effects, active spell damage/heal per round. 6. On player victory: XP and gold per the enemy definition, character HP set to the last round's defender HP, and loot dropped per-item chance rolls (only items existing in the catalogue). 7. On defeat: character HP set to 0; no rewards. 8. Spell-point upkeep is charged whenever a spell was active, win or lose. 9. System persists the character and returns `{zone, enemy, combat_log, loot}` (loot = item display names). ## Alternative and Exception Flows ### Foreign character (Alternate) 1. Foreign character without admin role → 403. ### Not found (Alternate) 1. Character or zone not found → 404. ### Incapacitated (Alternate) 1. HP ≤ 0 → 400. ### Insufficient nerve (Alternate) 1. Nerve below zone cost → 422. ### Unknown encounter enemy (Exception) 1. Encounter references an enemy id missing from the catalogue (data error) → 500 (post WI-2; previously a panic). ## Post-conditions - Victory: rewards granted, loot added, HP set to last defender HP; defeat: HP 0, no rewards; spell upkeep charged if a spell was active; character persisted. ## Special Requirements - Enemy draw and combat rolls use the injected rng (NFR-05, CON-03). - Referential integrity violations surface as `DomainError::UnknownEncounterEnemy` → 500 (NFR-07). - Crit damage caps by level gap; open-ended d100 (combat canon, `docs/game/`). # UC-09 Heal at Temple ## Brief Description Full or partial healing, cost = amount healed, minimum 1 gold. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists, is injured, and caller may act on it. ## Basic Flow of Events 1. Player requests healing, optionally `partial`. 2. System computes missing HP; full heals all, partial heals half (rounded up); cost = amount healed, minimum 1 gold. 3. System checks gold (422), deducts it, restores HP, persists; returns `{hp, max_hp, gold, healed: true}`. ## Alternative and Exception Flows ### Foreign character (Alternate) 1. Foreign character without admin role → 403. ### Not found (Alternate) 1. Character not found → 404. ### Already at full HP (Alternate) 1. No missing HP → 400. ### Insufficient gold (Alternate) 1. Gold below heal cost → 422. ## Post-conditions - HP restored, gold deducted, character persisted. ## Special Requirements - Healing logic is handler-side recorded debt (Architecture Notebook D1, Q3). # UC-10 Practice Bard Song ## Brief Description Set or clear the active bard song (Bard only, level-gated). ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character class is Bard. ## Basic Flow of Events 1. Player views available songs (level-gated, with combat effect descriptions) and the active song. 2. Player submits a song id; system validates level requirement (422) and sets it active; returns `{success, message, active_song}`. ## Alternative and Exception Flows ### Clear (Alternate) 1. Submitting no song id clears the active song. ### Non-Bard (Alternate) 1. Character class is not Bard → 403. ### Unknown song (Alternate) 1. Unknown song id → 404. ### Level too low (Alternate) 1. Character level below the song requirement → 422. ### Foreign character / not found (Alternate) 1. Foreign character → 403; character not found → 404. ## Post-conditions - Active song set or cleared; character persisted. ## Special Requirements - Song effects apply in UC-08 combat (step 5). # UC-11 Study Magic ## Brief Description View spellbook, learn spell levels (1–7, gold cost), activate/clear the active spell. Caster classes only; spell level = (character level / 3) + 1, uncapped by code. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character belongs to a caster class (Mage→magician, Wizard, Conjurer, Sorcerer). Spell level = (character level / 3) + 1 — uncapped by code (level 100 → spell level 34); learn requests are validated to 1–7. ## Basic Flow of Events (view spellbook) 1. Player requests their spellbook: caster class, current spell level, spell points, spells up to the achievable level (each marked known), and the learn-cost table for levels 2–7. ## Alternative and Exception Flows ### Learn spell level (Alternate) 1. Player submits a spell level (1–7). 2. System validates caster class (403), level range (400), level not above the character's current spell level (422), gold ≥ learn cost (422), and that new spells exist (400). 3. System deducts gold, adds all unknown spell ids of that level, recomputes and refills max spell points; returns `{learned_count, spell_points, max_spell_points, gold}`. ### Activate / clear active spell (Alternate) 1. Player submits a spell id (or empty to clear). 2. System validates the spell is known (403), exists (404), and spell points suffice (422); deducts the spell's points and sets it active; returns `{active_spell, spell_points}`. ## Post-conditions - (learn) spells of the level known, gold deducted, max spell points recomputed and refilled; (activate) active spell set, spell points deducted; persisted. ## Special Requirements - Active spell deals damage/heals per round and charges upkeep in UC-08 combat (steps 5, 8). - Parts of spell logic are handler-side recorded debt (Architecture Notebook D1, Q3). # UC-12 Level Up at Review Board ## Brief Description Manual level-up: XP threshold + gold cost (500 per next level), full resource restore on level-up. ## Actor Brief Descriptions | **Actor** | **Type** | **Description** | | --- | --- | --- | | Player | Primary | Authenticated user owning one or more characters (JWT role `player`). | ## Preconditions and Context Precondition: character exists and caller may act on it. ## Basic Flow of Events 1. Player requests a level-up. 2. System validates: below max level 100, XP ≥ 18·100·(level)² for the next level (i.e. `xp_for_level(next)`), gold ≥ 500·next level. 3. System deducts the gold cost, increments the level, recomputes and fully restores HP/energy/nerve and max spell points; persists; returns `{success, message, character}`. ## Alternative and Exception Flows ### Level-up rejected (Alternate) 1. Already at max level, not enough XP, or not enough gold → 422. ### Foreign character (Alternate) 1. Foreign character without admin role → 403. ### Not found (Alternate) 1. Character not found → 404. ## Post-conditions - Level +1, gold deducted, all resources fully restored and maxima recomputed; character persisted. ## Special Requirements - Level-up rule failures flow through `DomainError` → central status mapping (CON-04). --- # Traceability Notes - UC-08 is the design driver for WI-2's service extraction (`sb_core::adventure`); its status mapping feeds `DomainError` (see `analysis-design/design-wi-2-architecture-cleanup.md` §4.1–4.2). - Catalogue data backing UC-04 lives in `skara-brae-common/data/` (items, enemies, zones, spells, crit tables). - Analysis realizations for all twelve use cases: `analysis-design/uc-realization-mapping.md` §2 + EA model; design sequences: `analysis-design/sequences/`. - Requirement traceability: `supplementary-specifications.md` coverage matrix.