{ "exportedFrom": "docs/openup/model/skara-brae.eapx (Analysis-Design realization packages)", "realizations": [ { "id": "UC-01 Realization", "useCase": "UC-01 Register Account", "elements": [ { "name": "AccountRegistry", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::{register, seed_users}`. argon2 hash via `sb-auth::hash`; JWT via `sb-auth::jwt`" }, { "name": "AuthBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `POST /api/auth/register`, `AuthResponse`. " }, { "name": "UserAccount", "stereotype": "entity", "notes": "Design element: . Design element: `sb-shared::user::User`, `Role`. persisted via `sb-db::Database`" } ] }, { "id": "UC-02 Realization", "useCase": "UC-02 Authenticate", "elements": [ { "name": "Authenticator", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::login`, `sb-auth::{hash::verify_password, jwt::create_token}`. " }, { "name": "TokenService", "stereotype": "boundary", "notes": "Design element: . Design element: `POST /api/auth/login`, `AuthResponse`, `middleware::auth::auth_middleware`. middleware guards all UC-03…12" } ] }, { "id": "UC-03 Realization", "useCase": "UC-03 Manage Characters", "elements": [ { "name": "Character", "stereotype": "entity", "notes": "Design element: . Design element: `sb-shared::character::Character` (+ `Race`, `Class`, `CharacterStats`). " }, { "name": "CharacterCatalog", "stereotype": "boundary", "notes": "Design element: . Design element: `GET/POST /api/users/{id}/characters`, `GET /api/characters/{id}`. store: `AppState.characters`" }, { "name": "CharacterFactory", "stereotype": "controller", "notes": "Design element: . Design element: `sb-core::character::create_character`. takes injected rng (WI-1)" }, { "name": "ResourceRegenerator", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::character::apply_regen` (+ regen constants — WI-2 names them). included sub-flow" } ] }, { "id": "UC-04 Realization", "useCase": "UC-04 Browse Game Catalogue", "elements": [ { "name": "CatalogueBrowser", "stereotype": "boundary", "notes": "Design element: . Design element: `GET /api/{races,classes,items,enemies,adventures}`; response types `sb-shared::responses`. data from `sb-common` JSON via `sb-core::{character::RACES/CLASSES, data, items}`" }, { "name": "GameData", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::data::{EnemyDef, ZoneDef, EncounterEntry, LootDrop}`, `items::load_all_items`. " } ] }, { "id": "UC-05 Realization", "useCase": "UC-05 Train Stat", "elements": [ { "name": "GymBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `GET/POST /api/characters/{id}/gym`, `GymResponse`, `TrainStatResponse`. " }, { "name": "TrainingGrounds", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::character::TRAINING_GROUNDS`, `training_cost` (+ cost constants WI-2). " }, { "name": "TrainingService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-core::services::train_stat`. error type `DomainError` (WI-2)" } ] }, { "id": "UC-06 Realization", "useCase": "UC-06 Manage Equipment", "elements": [ { "name": "Equipment/Inventory", "stereotype": "entity", "notes": "Design element: . Design element: `Character.equipment` / `.inventory`, `sb-shared::item::Item`. " }, { "name": "EquipmentBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `POST /api/characters/{id}/{equip,unequip}`. " }, { "name": "EquipmentService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-core::services::{equip_item, unequip_item}`. `DomainError` (WI-2)" } ] }, { "id": "UC-07 Realization", "useCase": "UC-07 Trade at Shop", "elements": [ { "name": "ShopBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `GET/POST /api/characters/{id}/shop`, `ShopResponse`, `ShopActionResponse`. " }, { "name": "ShopService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::{shop_action, buy_item, sell_item}` (handler-side; extraction candidate, design note Q3). prices: `sb-core::items::{item_price, item_sell_price}`" }, { "name": "ShopStock", "stereotype": "entity", "notes": "Design element: . Design element: `AppState.shop_stock`. persisted via `sb-db`" } ] }, { "id": "UC-08 Realization", "useCase": "UC-08 Run Adventure", "elements": [ { "name": "AdventureBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `GET /api/characters/{id}/adventure`; `AdventureRunResponse` (**new, WI-2**), `sb-shared::responses::CombatLog`. " }, { "name": "AdventureService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-core::adventure::run_adventure` (**new, WI-2**) + `services::pick_enemy` → `Result` (WI-2). takes injected rng; `DomainError` (WI-2)" }, { "name": "Combatant", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::combat::CombatStats`. built from Character/EnemyDef" }, { "name": "CombatEngine", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::combat::{resolve_combat_full, resolve_attack, crit tables, open_ended_roll}` + combat constants (WI-2). " }, { "name": "SpellEffect / BardSong", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::combat::SpellEffect`, `sb-core::spells`, `sb-core::songs`. " } ] }, { "id": "UC-09 Realization", "useCase": "UC-09 Heal at Temple", "elements": [ { "name": "HealingService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::heal_character` (handler-side; extraction candidate, Q3). " }, { "name": "TempleBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `POST /api/characters/{id}/heal`; `HealResponse` (**new, WI-2**). " } ] }, { "id": "UC-10 Realization", "useCase": "UC-10 Practice Bard Song", "elements": [ { "name": "BardSong", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::songs::BARD_SONGS`, `Character.active_song`. " }, { "name": "SongBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `GET/POST /api/characters/{id}/songs`, `SongsResponse`, `SetSongResponse`. " }, { "name": "SongService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::set_song`; `sb-core::songs::available_songs`. " } ] }, { "id": "UC-11 Realization", "useCase": "UC-11 Study Magic", "elements": [ { "name": "MagicBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `GET/POST /api/characters/{id}/spells`; `SpellbookResponse`, `LearnSpellResponse` (**new, WI-2**). " }, { "name": "MagicService", "stereotype": "controller", "notes": "Design element: . Design element: `sb-api::routes::{get_spells, learn_spell_level}`; `sb-core::spells::{spells_for_class, spell_learn_cost, max_spell_points, caster_spell_level (WI-2)}`. " }, { "name": "Spell", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::spells::SpellDef`, `Character.{known_spells, active_spell, spell_points}`. " } ] }, { "id": "UC-12 Realization", "useCase": "UC-12 Level Up at Review Board", "elements": [ { "name": "Progression", "stereotype": "entity", "notes": "Design element: . Design element: `sb-core::character::{xp_for_level, level_up_cost, MAX_LEVEL}` (+ curve constants WI-2). " }, { "name": "ReviewBoard", "stereotype": "controller", "notes": "Design element: . Design element: `sb-core::character::level_up`. `DomainError` (WI-2)" }, { "name": "ReviewBoundary", "stereotype": "boundary", "notes": "Design element: . Design element: `POST /api/characters/{id}/level-up`, `LevelUpResponse`. " } ] } ], "crossCutting": [ { "name": "Constants", "notes": "sb-core::constants realizes NFR \"no magic numbers\"." }, { "name": "DomainError", "notes": "sb-core::error::DomainError + sb-api::routes::domain_status (status mapping table, design note §4.1) realize the error paths of UC-05/06/08/12." }, { "name": "Responses", "notes": "sb-api::routes::responses realizes NFR-19 (wire-format freeze)." } ] }