skara-brae-common/docs/openup/requirements/supplementary-specifications.md
Jan-Peter von Hunnius 4798f55660 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).
2026-10-03 17:17:44 +02:00

5.6 KiB
Raw Blame History

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.