openup: doc restructure - template alignment + design sequences (non-PSP)
Align the OpenUP markdown set to the blank templates (process-data repo, templates/openup/) per BUILD-CHECKLIST 7. Scenario step text unchanged; the EA model needs no change (brief descriptions already live in the model's UC/actor notes). - vision.md: positioning tables, stakeholder summary, user environment, needs-and-features table (R1/R2), other product requirements - use-case-model.md: per-UC specification sections (brief description, actor descriptions, named alternative/exception subsections with numbered steps, post-conditions, special requirements) - supplementary-specifications.md: category tables with priority and use-case columns + reverse coverage matrix; IDs unchanged - test/quality-check-procedure.md: migrated from Joplin (single content home); stale open items marked resolved (WI-1/WI-2) - analysis-design/sequences/: 12 PlantUML design sequences (lifelines = analysis classes, messages = design elements; per the PlantUML layout style guide) + PNG renders; embedded in Architecture Notebook 9.3 - Joplin consolidated: project content notes deleted (all live in docs/game + docs/openup); Joplin keeps the status note only
This commit is contained in:
parent
93bb034752
commit
193562cbc4
30 changed files with 1200 additions and 124 deletions
|
|
@ -1,51 +1,93 @@
|
|||
# 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.
|
||||
`Skara Brae` — OpenUP Requirements · version 2.0 (2026-10-05, restructured to the OpenUP
|
||||
supplementary-specifications template: category tables with priority and use-case trace +
|
||||
coverage matrix; requirement IDs unchanged from version 1.0).
|
||||
Non-functional requirements and constraints for the server MVP. Facts cite code where they
|
||||
are implemented; assumptions are marked. Category tailoring vs stock OpenUP: this project
|
||||
adds **Quality Gates** and **Data** categories (project-specific acceptance and
|
||||
game-data rules); a Standards category is not applicable at R1.
|
||||
|
||||
## 1. Performance / Scalability
|
||||
# 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.
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| 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. | High | UC-01..UC-12 |
|
||||
| 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). | High | UC-03, UC-05, UC-08 |
|
||||
| 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)*. | Medium | UC-03, UC-05, UC-08 |
|
||||
| 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. | High | UC-04 |
|
||||
|
||||
## 2. Reliability / Correctness
|
||||
# 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).
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| 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()`. | High | UC-03, UC-07, UC-08 |
|
||||
| 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. | Medium | UC-01, UC-03, UC-05..UC-12 |
|
||||
| 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). | High | UC-08 |
|
||||
|
||||
## 3. Quality Gates (per-commit acceptance)
|
||||
# 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).
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| NFR-08 | `cargo fmt --check` clean (fmt baseline established by WI-2). | High | all |
|
||||
| NFR-09 | `cargo clippy --all-targets -- -D warnings` clean — zero-warning policy. | High | all |
|
||||
| NFR-10 | `cargo test --workspace` fully green (45 sb-core tests at WI-2 start; suite only grows). | High | all |
|
||||
| NFR-11 | Behavior-identical refactor — JSON field names/order, HTTP status codes, game semantics, and RNG draw order unchanged (WI-2-specific; standing interpretation for future refactors). | High | all |
|
||||
| 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). | High | all |
|
||||
|
||||
## 4. Data
|
||||
# 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.
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| 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. | High | UC-04 |
|
||||
| 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. | Medium | UC-01, UC-03, UC-07 |
|
||||
| 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. | High | UC-05, UC-08, UC-12 |
|
||||
|
||||
## 5. Security
|
||||
# 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.
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| NFR-16 | Passwords hashed with argon2; verification constant-time via the crate. | High | UC-01, UC-02 |
|
||||
| NFR-17 | JWT (HS256, `jsonwebtoken`), 24 h expiry; all game routes behind auth middleware; cross-user access requires the `admin` role (403 otherwise). | High | UC-01..UC-12 |
|
||||
| NFR-18 | No secrets in code; JWT secret and admin/player seed passwords come from environment/configuration. | High | UC-01, UC-02 |
|
||||
|
||||
## 6. Constraints
|
||||
# Interfaces
|
||||
|
||||
- **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.
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| 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. | High | UC-01..UC-12 |
|
||||
| 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. | High | UC-01..UC-12 |
|
||||
|
||||
## 7. Usability / API
|
||||
# Design Constraints
|
||||
|
||||
- **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.
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| 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). | High | all |
|
||||
| CON-02 | HTTP framework **Axum 0.8** (ws + macros features), tokio, tower stack (CORS/trace/compression-gzip). | High | all |
|
||||
| CON-03 | `rand 0.9`; domain functions take `rng: &mut impl Rng`; handlers obtain RNG only from `request_rng()` (WI-1 rule). | High | UC-03, UC-07, UC-08 |
|
||||
| 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. | High | UC-05, UC-06, UC-08, UC-12 |
|
||||
| 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. | High | all |
|
||||
| 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). `roadmap.md` stays at the project-top folder per the earlier PM decision. | Medium | — |
|
||||
|
||||
# Documentation
|
||||
|
||||
| **ID** | **Requirement** | **Priority** | **Use Cases** |
|
||||
| --- | --- | --- | --- |
|
||||
| DOC-01 | The OpenUP artifact set (Vision, Use-Case Specifications, Supplementary Specifications, Architecture Notebook, test artifacts) and the game-design canon (`docs/game/`) live in the skara-brae-common repo and are maintained there; the EA model and its exports render them. Joplin keeps project status only. | Medium | — |
|
||||
|
||||
# Use Case Coverage Matrix
|
||||
|
||||
| **ID** | **Use Case** | **Traced Requirements** |
|
||||
| --- | --- | --- |
|
||||
| UC-01 | Register Account | NFR-01, NFR-06, NFR-16, NFR-17, NFR-18, NFR-19, NFR-20 |
|
||||
| UC-02 | Authenticate | NFR-16, NFR-17, NFR-18, NFR-19, NFR-20 |
|
||||
| UC-03 | Manage Characters | NFR-01, NFR-02, NFR-03, NFR-05, NFR-06, NFR-14, NFR-17, NFR-19, NFR-20 |
|
||||
| UC-04 | Browse Game Catalogue | NFR-04, NFR-13, NFR-19, NFR-20 |
|
||||
| UC-05 | Train Stat | NFR-02, NFR-03, NFR-06, NFR-11, NFR-12, NFR-15, CON-04 |
|
||||
| UC-06 | Manage Equipment | NFR-06, NFR-11, NFR-12, CON-04 |
|
||||
| UC-07 | Trade at Shop | NFR-05, NFR-06, NFR-14, CON-03 |
|
||||
| UC-08 | Run Adventure | NFR-02, NFR-03, NFR-05, NFR-07, NFR-11, NFR-15, CON-03, CON-04 |
|
||||
| UC-09 | Heal at Temple | NFR-06, NFR-11, NFR-12 |
|
||||
| UC-10 | Practice Bard Song | NFR-06, NFR-11, NFR-12 |
|
||||
| UC-11 | Study Magic | NFR-06, NFR-11, NFR-12, NFR-15 |
|
||||
| UC-12 | Level Up at Review Board | NFR-06, NFR-11, NFR-12, NFR-15, CON-04 |
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
# Skara Brae — Use Case Model
|
||||
# Skara Brae — Use-Case Specifications
|
||||
|
||||
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.
|
||||
`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).
|
||||
|
||||
## Actors
|
||||
# Use Case Overview
|
||||
|
||||
| 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 |
|
||||
| ID | Use Case | Actors | Includes / Extends |
|
||||
|---|---|---|---|
|
||||
| UC-01 | Register Account | Guest | — |
|
||||
| UC-02 | Authenticate | Guest | — |
|
||||
| UC-03 | Manage Characters | Player (Admin read) | — |
|
||||
| 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 | — |
|
||||
|
|
@ -30,88 +27,372 @@ Scope: the **existing implemented system** (server MVP as of `wi-2-architecture-
|
|||
|
||||

|
||||
|
||||
*Figure 1: Use case overview (rendered from the EA model, `docs/openup/model/skara-brae.eapx`, via `scripts/openup/export-diagram-images.ps1`).*
|
||||
*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.
|
||||
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
|
||||
# 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
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-02 Authenticate
|
||||
### 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
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-03 Manage Characters
|
||||
### Credentials rejected (Alternate)
|
||||
|
||||
**Main success scenario (create):**
|
||||
1. Player submits character name, race, class for their user id (Admin may act for any user).
|
||||
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.
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
**Alternate flows:** foreign user/character without admin role → 403 FORBIDDEN; user/character not found → 404; invalid name → 400.
|
||||
### List / view (Alternate)
|
||||
|
||||
## UC-04 Browse Game Catalogue
|
||||
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
|
||||
|
||||
**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).
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-05 Train Stat
|
||||
### 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
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-06 Manage Equipment
|
||||
### 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)
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
**Alternate flows:** foreign character → 403; character/item not found → 404; item not in inventory → 400; nothing equipped in slot → 400.
|
||||
### Unequip (Alternate)
|
||||
|
||||
## UC-07 Trade at Shop
|
||||
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)
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
**Alternate flows:** unknown action or item not owned (sell) → 400; item not found → 404; insufficient gold → 422; stock exhausted → 410.
|
||||
### Sell (Alternate)
|
||||
|
||||
## UC-08 Run Adventure
|
||||
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
|
||||
|
||||
**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.
|
||||
|
|
@ -122,53 +403,232 @@ Shared sub-flow **Regenerate Resources**: the system recomputes time-based regen
|
|||
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).
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-09 Heal at Temple
|
||||
### 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
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-10 Practice Bard Song
|
||||
### 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
|
||||
|
||||
**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.
|
||||
## Alternative and Exception Flows
|
||||
|
||||
## UC-11 Study Magic
|
||||
### Clear (Alternate)
|
||||
|
||||
**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).
|
||||
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)
|
||||
|
||||
**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):**
|
||||
## 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}`.
|
||||
|
||||
**Scenario (activate/clear active spell):**
|
||||
### 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}`.
|
||||
|
||||
## UC-12 Level Up at Review Board
|
||||
## 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
|
||||
|
||||
**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.
|
||||
## 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
|
||||
# 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.
|
||||
|
|
|
|||
|
|
@ -1,41 +1,84 @@
|
|||
# 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/)
|
||||
`Skara Brae` — OpenUP Requirements · Vision · version 2.0 (2026-10-05, restructured to the
|
||||
OpenUP vision template; content unchanged in substance from version 1.0, WI-2).
|
||||
Canonical home: **skara-brae-common repo**, `docs/openup/` (decision 2026-10-03).
|
||||
|
||||
## Problem / Opportunity
|
||||
## 1. Introduction
|
||||
|
||||
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.
|
||||
This Vision describes Skara Brae, a text-based browser MMORPG built as a modern
|
||||
re-implementation of a proven formula. The document is maintained alongside an
|
||||
implemented, growing system: the server MVP (accounts, characters, training, adventures,
|
||||
economy, magic, progression) is live at `main` with the OpenUP artifact set generated from
|
||||
it; later-phase features are committed in intent but not built.
|
||||
|
||||
## Product Vision
|
||||
The product comprises three repositories: `skara-brae-server` (Rust/Axum backend),
|
||||
`skara-brae-client` (Vue 3 SPA) and `skara-brae-common` (bilingual game-data package and
|
||||
OpenUP artifact home). In the tables below, R1 denotes the delivered server MVP and R2 the
|
||||
later-phase features (not yet committed to dates).
|
||||
|
||||
**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).
|
||||
References: game design canon in `docs/game/`, OpenUP artifact set in `docs/openup/`,
|
||||
EA model in `docs/openup/model/skara-brae.eapx`.
|
||||
|
||||
**Tagline:** *Set your hero to work. Close the app. Come back to loot.*
|
||||
## 2. Positioning
|
||||
|
||||
## Stakeholders
|
||||
### 2.1 Problem Statement
|
||||
|
||||
- **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.
|
||||
| | |
|
||||
| --- | --- |
|
||||
| The problem of | 2000s-era engines under proven text-based browser MMORPGs |
|
||||
| affects | players of the genre (retention-heavy games with dated UX and closed stacks) and a solo developer wanting a type-safe, API-first base for community tooling |
|
||||
| the impact of which is | incumbents carry legacy engines; no modern reference implementation exists for the formula with real-time feedback, idle-friendly pacing and an open API |
|
||||
| a successful solution would be | a 2026-era, type-safe full-stack implementation: instant feedback, mobile-first PWA, API-first design, offline-friendly idle progression, self-hostable by one operator |
|
||||
|
||||
## Key Features (committed MVP scope, Phase 1)
|
||||
### 2.2 Product Position Statement
|
||||
|
||||
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.
|
||||
| For | players of deep, numeric-progression browser games and the solo operator building for them |
|
||||
| --- | --- |
|
||||
| Who | need a modern, maintainable instance of the proven Torn-style loop |
|
||||
| Skara Brae | is a fantasy text-based/idle MMORPG set in an ancient city of stone and sorcery (The Bard's Tale I inspiration, dark-fantasy tone) |
|
||||
| That | transplants the proven loop — energy-gated activities, training, economy — into that setting, adds idle-RPG elements (offline progression, hireable workers, pets) and grounds combat in a RoleMaster-inspired crit system |
|
||||
| Unlike | incumbent PHP-era engines with closed APIs |
|
||||
| Our product | ships a Rust/Axum REST API, a Vue 3 PWA client, language-neutral game data, and a self-hosted Forgejo/Jenkins pipeline — with the tagline: *Set your hero to work. Close the app. Come back to loot.* |
|
||||
|
||||
Later phases (not committed): PvP, guilds, properties, crafting, pets, blessings, offline workers, tower endgame.
|
||||
## 3. Stakeholder Descriptions
|
||||
|
||||
## Constraints & Quality Bars
|
||||
### 3.1 Stakeholder Summary
|
||||
|
||||
- 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.
|
||||
| **Name** | **Description** | **Responsibilities** |
|
||||
| --- | --- | --- |
|
||||
| Owner/developer (solo) | Builds and operates the game on self-hosted infrastructure | Scope, releases, quality gate, external hosting (Forgejo/Jenkins pipeline) |
|
||||
| Players | Web/PWA users; the API-first contract also serves future community tools | Play; consume the public API within its contract |
|
||||
|
||||
## Success Criteria (current iteration)
|
||||
### 3.2 User Environment
|
||||
|
||||
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.
|
||||
Players use a browser or installed PWA against the hosted Vue 3 SPA; the client polls the
|
||||
REST API (assumed refresh cadence ~15 s; server behavior is poll-frequency-independent by
|
||||
design). The operator runs a single Rust process per deployment (systemd), with optional
|
||||
write-through SQLite persistence, behind Caddy TLS; game state otherwise lives in memory.
|
||||
All game content ships compiled-in from `skara-brae-common` JSON — no external data
|
||||
services for R1.
|
||||
|
||||
## 4. Product Overview
|
||||
|
||||
### 4.1 Needs and Features
|
||||
|
||||
| **Need** | **Priority** | **Features** | **Planned Release** |
|
||||
| --- | --- | --- | --- |
|
||||
| Progress a character | High | Accounts (register/login, JWT), character creation (5 races, 10 classes), stat training with escalating gold costs, level-up review board | R1 |
|
||||
| Adventure and fight | High | Energy/nerve-gated zone adventures, turn-based combat with open-ended d100 rolls and RoleMaster crit tables, XP/gold/loot | R1 |
|
||||
| Run an economy | High | Shop (buy/sell, rotating stock), equipment slots, inventory | R1 |
|
||||
| Wield magic and song | High | Class-gated spell levels with spell points, bard songs with combat effects | R1 |
|
||||
| Regenerate over time | High | Energy/nerve/HP resources with lazy timed regeneration; temple healing | R1 |
|
||||
| Consume the game programmatically | High | REST JSON API (Rust/Axum), Vue 3 client; WebSocket notifications | R1 (WS: later R1+) |
|
||||
| Play idly | Medium | Offline progression, hireable workers, pets; further endgame (tower, guilds, properties, crafting, blessings, PvP) | R2 |
|
||||
|
||||
## 5. Other Product Requirements
|
||||
|
||||
| **Requirement** | **Priority** | **Planned Release** |
|
||||
| --- | --- | --- |
|
||||
| Behavior continuity: refactors must be wire-format and game-semantics identical | High | R1 (standing) |
|
||||
| Quality gates: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, full test suite — zero-warning policy | High | R1 (standing) |
|
||||
| Game data lives in the shared `skara-brae-common` repo as language-neutral JSON (single source of truth for server, client and future generated wiki) | High | R1 |
|
||||
| BIGINT (`i64`) stat growth; stats only ever go up | High | R1 |
|
||||
| Self-hosted pipeline: Forgejo (git), Jenkins CI, systemd + Caddy deployment | Medium | R1 |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue