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:
Jan-Peter von Hunnius 2026-10-03 17:17:44 +02:00
parent 9cd8e2f717
commit 4798f55660
6 changed files with 1066 additions and 0 deletions

View 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.