docs(openup): move WI-2 OpenUP work set verbatim from skara-brae-server
All OpenUP artifacts are versioned in skara-brae-common under docs/openup/ per the 2026-10-03 decision reversal in design-wi-2-architecture-cleanup.md (supersedes the earlier in-server-docs decision). Verbatim move, no content changes: analysis-design/, requirements/, test/ (6 files).
This commit is contained in:
parent
9cd8e2f717
commit
4798f55660
6 changed files with 1066 additions and 0 deletions
51
docs/openup/requirements/supplementary-specifications.md
Normal file
51
docs/openup/requirements/supplementary-specifications.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Skara Brae — Supplementary Specifications
|
||||
|
||||
Version 1.0 (WI-2, 2026-10-03) · OpenUP artifact: `requirements/supplementary-specifications.md`
|
||||
Non-functional requirements and constraints for the server MVP. Facts cite code where they are implemented; assumptions are marked.
|
||||
|
||||
## 1. Performance / Scalability
|
||||
|
||||
- **NFR-01 (in-memory state):** all game state (users, characters, shop stock) is held in process memory behind `tokio::sync::RwLock` (`crates/sb-api/src/routes/mod.rs:33–42`). Single-process deployment; persistence is write-through to SQLite, reads never hit the DB.
|
||||
- **NFR-02 (lazy regeneration):** resource regeneration is computed on every character access from elapsed wall-clock time (`apply_regen`, character.rs:105–122) — no timers, no background ticks. Intervals: energy 180 s, nerve 300 s, HP 300 s (5% max HP per tick).
|
||||
- **NFR-03 (client polling):** clients poll character state to observe regeneration; the assumed UI refresh cadence is ~15 s *(assumption carried from project planning; server-side behavior is poll-frequency-independent by design NFR-02)*.
|
||||
- **NFR-04 (static catalogue):** items, enemies, zones, spells, and crit tables are compiled in via `include_str!` from `skara-brae-common` JSON and parsed once behind `LazyLock`; catalogue reads are lock-free after first access.
|
||||
|
||||
## 2. Reliability / Correctness
|
||||
|
||||
- **NFR-05 (deterministic domain logic):** all domain randomness is injected `StdRng` (WI-1); identical seeds produce identical outcomes. Request paths construct RNG only at `request_rng()`.
|
||||
- **NFR-06 (persistence best-effort):** persistence failures are logged (`tracing::error`) and do not fail the request; in-memory state remains authoritative for the process lifetime.
|
||||
- **NFR-07 (referential data integrity):** zone encounter tables must reference existing enemy ids and loot drops must reference existing item ids; violations are detected at first use (WI-2: `DomainError::UnknownEncounterEnemy` → 500 instead of a panic).
|
||||
|
||||
## 3. Quality Gates (per-commit acceptance)
|
||||
|
||||
- **NFR-08:** `cargo fmt --check` clean (fmt baseline established by WI-2).
|
||||
- **NFR-09:** `cargo clippy --all-targets -- -D warnings` clean — zero-warning policy.
|
||||
- **NFR-10:** `cargo test --workspace` fully green (45 sb-core tests at WI-2 start; suite only grows).
|
||||
- **NFR-11 (WI-2-specific):** behavior-identical refactor — JSON field names/order, HTTP status codes, game semantics, and RNG draw order unchanged.
|
||||
- **NFR-12:** no `unwrap()`/`expect()` on request paths outside the documented keep-with-reason invariants in the design-note §6 ledger (covers sb-api, sb-core, sb-db mutex poisoning, sb-auth time/entropy invariants).
|
||||
|
||||
## 4. Data
|
||||
|
||||
- **NFR-13 (shared data source):** all game content lives in the `skara-brae-common` repo as language-neutral JSON under `data/` — single source of truth consumed at build time by server (`include_str!` + serde) and client. Server must not duplicate or transform these definitions in code.
|
||||
- **NFR-14 (persistence format):** optional SQLite via `SB_DB_PATH` (rusqlite; users, characters, shop stock with `next_character_id`). Absent the variable the server runs purely in-memory with seeded `admin`/`player` accounts.
|
||||
- **NFR-15 (numeric headroom):** stats are `i64` (BIGINT) — “exponential growth, tiered display” is a product commitment; no narrowing conversions to smaller integers in new code.
|
||||
|
||||
## 5. Security
|
||||
|
||||
- **NFR-16:** passwords hashed with argon2; verification constant-time via the crate.
|
||||
- **NFR-17:** JWT (HS256, `jsonwebtoken`), 24 h expiry; all game routes behind auth middleware; cross-user access requires the `admin` role (403 otherwise).
|
||||
- **NFR-18:** no secrets in code; JWT secret and admin/player seed passwords come from environment/configuration.
|
||||
|
||||
## 6. Constraints
|
||||
|
||||
- **CON-01:** Rust, edition **2024**; workspace crates `sb-api` / `sb-core` / `sb-db` / `sb-auth` / `sb-shared` + external sibling `sb-common` (absolute path dependency; submodule migration planned).
|
||||
- **CON-02:** HTTP framework **Axum 0.8** (ws + macros features), tokio, tower stack (CORS/trace/compression-gzip).
|
||||
- **CON-03:** `rand 0.9`; domain functions take `rng: &mut impl Rng`; handlers obtain RNG only from `request_rng()` (WI-1 rule).
|
||||
- **CON-04:** Error handling: `thiserror 2` in-domain; **no new error/framework dependencies**; one domain error enum (`sb_core::error::DomainError`) with a single central HTTP status mapping in sb-api.
|
||||
- **CON-05:** Clean Architecture dependency rule: sb-core has zero knowledge of HTTP/axum/serde_json/tokio/tracing/sb-db; ports (domain traits) would live in sb-core, adapters outward.
|
||||
- **CON-06:** OpenUP work products are versioned in the **skara-brae-common repo** under `docs/openup/` — one canonical project-docs home (decision reversed 2026-10-03 from the earlier skara-brae-server `docs/openup/` plan). The drafted WI-2 artifacts move there verbatim (coder, session 2); WI-1 artifacts at the old project-top folder migrate there as well. `roadmap.md` stays at the project-top folder per the earlier PM decision.
|
||||
|
||||
## 7. Usability / API
|
||||
|
||||
- **NFR-19:** REST JSON API; field names and order are a wire contract — refactors must preserve them byte-for-byte. The current API emits JSON object keys in **lexicographic order** (serde_json resolves without `preserve_order`; `json!` uses BTreeMap-backed maps), and the typed-response structs of WI-2 declare fields in that order to stay byte-identical.
|
||||
- **NFR-20:** meaningful HTTP status codes: 400 malformed input, 401 auth failure, 403 foreign/non-permitted resource, 404 unknown resource, 409 name conflict, 410 shop stock exhausted, 422 game-rule violation (resources/requirements), 500 internal.
|
||||
170
docs/openup/requirements/use-case-model.md
Normal file
170
docs/openup/requirements/use-case-model.md
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
# Skara Brae — Use Case Model
|
||||
|
||||
Version 1.0 (WI-2, 2026-10-03) · OpenUP artifact: `requirements/use-case-model.md`
|
||||
Scope: the **existing implemented system** (server MVP as of `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.
|
||||
|
||||
## Actors
|
||||
|
||||
| Actor | Description |
|
||||
|---|---|
|
||||
| **Player** | Authenticated user owning one or more characters (JWT role `player`). |
|
||||
| **Administrator** | Player with elevated rights (`role = admin`); may view any user's and any character's resources read-only. |
|
||||
| **Guest** | Unauthenticated caller; only register/login are open. |
|
||||
|
||||
## Use Case Overview
|
||||
|
||||
| ID | Use Case | Primary Actor | Includes / Extends |
|
||||
|---|---|---|---|
|
||||
| UC-01 | Register Account | Guest | — |
|
||||
| UC-02 | Authenticate | Guest | — |
|
||||
| UC-03 | Manage Characters | Player (Admin read) | — |
|
||||
| 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 | — |
|
||||
|
||||
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
|
||||
|
||||
**Precondition:** none. **Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Alternate flows:** name length invalid → 400; password too short → 400; name taken → 409; hashing/token failure → 500.
|
||||
|
||||
## UC-02 Authenticate
|
||||
|
||||
**Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Alternate flows:** unknown name or wrong password → 401 UNAUTHORIZED; token creation failure → 500.
|
||||
|
||||
## UC-03 Manage Characters
|
||||
|
||||
**Main success scenario (create):**
|
||||
1. Player submits character name, race, class for their user id (Admin may act for any user).
|
||||
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.
|
||||
|
||||
**Scenario (list/view):** Player lists their characters (Admin: any user's); the system applies Regenerate Resources to each returned character and returns them. Viewing one character applies regen then returns it.
|
||||
|
||||
**Alternate flows:** foreign user/character without admin role → 403 FORBIDDEN; user/character not found → 404; invalid name → 400.
|
||||
|
||||
## UC-04 Browse Game Catalogue
|
||||
|
||||
**Main success scenario:**
|
||||
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`).
|
||||
|
||||
**Alternate flows:** single item by unknown id → 404; filters may return an empty list (not an error).
|
||||
|
||||
## UC-05 Train Stat
|
||||
|
||||
**Precondition:** character exists and caller may act on it. **Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Alternate flows:** foreign character → 403; character not found → 404; not enough energy → 422; not enough gold → 422; unknown stat name → 400.
|
||||
|
||||
## UC-06 Manage Equipment
|
||||
|
||||
**Main success scenario (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.
|
||||
|
||||
**Scenario (unequip):** Player submits a slot name; the system moves the equipped item back to inventory.
|
||||
|
||||
**Alternate flows:** foreign character → 403; character/item not found → 404; item not in inventory → 400; nothing equipped in slot → 400.
|
||||
|
||||
## UC-07 Trade at Shop
|
||||
|
||||
**Main success scenario (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}`.
|
||||
|
||||
**Scenario (sell):** Player submits `sell` + item id; system removes the first matching inventory item, pays half the item value, increments shop stock for non-permanent items.
|
||||
|
||||
**Alternate flows:** unknown action or item not owned (sell) → 400; item not found → 404; insufficient gold → 422; stock exhausted → 410.
|
||||
|
||||
## UC-08 Run Adventure
|
||||
|
||||
**Precondition:** character exists and caller may act on it. **Main success scenario:**
|
||||
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).
|
||||
|
||||
**Alternate flows:** foreign character → 403; character/zone not found → 404; incapacitated → 400; insufficient nerve → 422. **Exception:** encounter references an unknown enemy (data error) → 500 (post WI-2; previously a panic).
|
||||
|
||||
## UC-09 Heal at Temple
|
||||
|
||||
**Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Alternate flows:** foreign character → 403; not found → 404; already at full HP → 400; insufficient gold → 422.
|
||||
|
||||
## UC-10 Practice Bard Song
|
||||
|
||||
**Precondition:** character class is Bard. **Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Scenario (clear):** submitting no song id clears the active song. **Alternate flows:** non-Bard → 403; unknown song → 404; level too low → 422; foreign character → 403; not found → 404.
|
||||
|
||||
## UC-11 Study Magic
|
||||
|
||||
**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, and the practical ceiling is emergent from the data (spells are defined only through level 7, so higher computed levels surface no new spells).
|
||||
|
||||
**Scenario (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.
|
||||
|
||||
**Scenario (learn spell level):**
|
||||
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}`.
|
||||
|
||||
**Scenario (activate/clear active spell):**
|
||||
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}`.
|
||||
|
||||
## UC-12 Level Up at Review Board
|
||||
|
||||
**Main success scenario:**
|
||||
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}`.
|
||||
|
||||
**Alternate flows (all 422):** already at max level; not enough XP; not enough gold. Foreign character → 403; not found → 404.
|
||||
|
||||
---
|
||||
|
||||
## 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).
|
||||
41
docs/openup/requirements/vision.md
Normal file
41
docs/openup/requirements/vision.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Skara Brae — Vision
|
||||
|
||||
Version 1.0 (WI-2, 2026-10-03) · OpenUP artifact: `requirements/vision.md` · Canonical home: **skara-brae-common repo**, `docs/openup/` (decision reversed 2026-10-03; drafts move verbatim from skara-brae-server/docs/)
|
||||
|
||||
## Problem / Opportunity
|
||||
|
||||
Text-based browser MMORPGs have proven retention and monetization for two decades (Torn City, since 2004), but incumbents carry 2000s-era engines. There is room for a modern, API-first, type-safe implementation of the formula: deep numeric progression, player-driven economy, idle-friendly pacing, real-time feedback.
|
||||
|
||||
## Product Vision
|
||||
|
||||
**Skara Brae** is a fantasy text-based/idle MMORPG set in an ancient, labyrinthine city of stone and sorcery (The Bard's Tale I inspiration, dark-fantasy tone). It transplants **Torn City's proven loop** — energy-gated activities, training, economy, social systems — into that setting, adds **idle-RPG elements** (offline progression, hireable workers, pets; Idle Fantasy inspiration), and grounds combat in a **RoleMaster-inspired critical-hit system** (open-ended d100, crit tables with bleed/stun effects, level-gap damage caps).
|
||||
|
||||
**Tagline:** *Set your hero to work. Close the app. Come back to loot.*
|
||||
|
||||
## Stakeholders
|
||||
|
||||
- **Owner/developer (solo)** — builds and operates the game on self-hosted infrastructure (Forgejo/Jenkins pipeline).
|
||||
- **Players** — web/PWA users; the API-first contract also serves future community tools.
|
||||
|
||||
## Key Features (committed MVP scope, Phase 1)
|
||||
|
||||
1. Accounts (register/login, JWT) and character creation (5 races, 10 classes).
|
||||
2. Stat training with escalating gold costs; energy/nerve/HP resources with lazy timed regeneration.
|
||||
3. Adventures (energy/nerve-gated zone runs) with turn-based combat, crit tables, XP/gold/loot.
|
||||
4. Economy: shop (buy/sell, stock), equipment slots, inventory.
|
||||
5. Magic (class-gated spell levels, spell points) and bard songs (combat buffs).
|
||||
6. Level-up review board; temple healing.
|
||||
7. REST API (Rust/Axum) + Vue 3 client; WebSocket notifications.
|
||||
|
||||
Later phases (not committed): PvP, guilds, properties, crafting, pets, blessings, offline workers, tower endgame.
|
||||
|
||||
## Constraints & Quality Bars
|
||||
|
||||
- Behavior continuity: refactors must be wire-format and game-semantics identical (WI-2 governs).
|
||||
- Quality gates: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, full test suite — zero-warning policy.
|
||||
- Game data lives in the shared `skara-brae-common` repo as language-neutral JSON (single source of truth for server, client, and a future generated wiki).
|
||||
- BIGINT (`i64`) stat growth; stats only ever go up.
|
||||
|
||||
## Success Criteria (current iteration)
|
||||
|
||||
WI-1 delivered injectable RNG (deterministic domain tests). This iteration (WI-2) delivers an architecture cleanup that makes the codebase safe to grow on: typed responses, domain-extracted adventure service, named game-balance constants, one domain error taxonomy, fmt baseline — with all 45 existing tests green and zero behavior change. Longer term: a playable MVP per the feature list above.
|
||||
Loading…
Add table
Add a link
Reference in a new issue