All checks were successful
build / build-test (push) Successful in 16s
Windows/EA session per BUILD-CHECKLIST 0-6 (the planned human-gate path, executed on the EA machine). Baseline built from EABase.eapx via build-model.ps1 and verified per checklist 4: 3 actors, 12 UCs with scenarios, 13 associations, 0 include connectors, 7 SS requirements, 12 realization packages / 36 elements; UC-08 MSS (9 steps) and UC-11 learn spell level (3 steps) match use-case-model.md verbatim. Script fixes (defects 1-3 of the session log): PS 5.1 hashtable parse error; realization UC lookup now accepts short and full use-case names. Enrichment after a manual layout pass - model changes are surgical from now on, re-running build-model.ps1 is forbidden (checklist 6): - add-analysis-associations.ps1: 24 analysis associations per mapping 2a (boundary-controller-entity; UC-04 boundary-entity) rendered via DiagramLinks without touching manual layout; 4 uses-dependencies to DomainError (UC-05/06/08/12 error paths, model-level) - add-design-package.ps1: Analysis-Design/Design - joint component model (skara-brae-client, sb-api, sb-auth, sb-db, sb-core, sb-shared, sb-common; 10 dependencies, rule inward). Joint-model decision recorded in mapping 1: one model for server+client+common; client- side UC realizations are a future work item. Markdown sources updated first (drift rule): mapping 1 tree + 2a interactions + 3 design component model; checklist 6. Exports regenerated from the model: use-case-model.json new, uc-realizations.json re-exported (useCase full names, notes merged, crossCutting added; element content verified equal to the markdown-to-json generator output). Open: XMI backup - ExportPackageXMI fails via COM (DISP_E_TYPEMISMATCH, PS 5.1 + cscript); manual EA UI export per model/README.md option 2.
157 lines
15 KiB
Markdown
157 lines
15 KiB
Markdown
# Skara Brae — Analysis & Design Model (text form)
|
||
|
||
Version 1.0 (WI-2, 2026-10-03) · OpenUP artifact: `analysis-design/uc-realization-mapping.md`
|
||
This is the **content the EA model will carry** once the modeling pipeline exists. The EA repository itself (`.eapx`, keyfob-station style) is planned for a later work item — EA is a human-gated interactive tool; this document is the authoritative source any future EA builder script generates from.
|
||
|
||
## 1. Model structure (planned EA packages)
|
||
|
||
```
|
||
Model: Skara Brae
|
||
├── Requirements
|
||
│ ├── Vision (from requirements/vision.md)
|
||
│ ├── Use Case Model
|
||
│ │ ├── Actors: Player, Administrator, Guest
|
||
│ │ └── Use Cases UC-01 … UC-12 (from requirements/use-case-model.md;
|
||
│ │ scenarios as Basic Path / Alternate / Exception with per-step Actor)
|
||
│ └── Supplementary Specifications (from requirements/supplementary-specifications.md)
|
||
└── Analysis-Design
|
||
├── Architecture Overview (crate/layer diagram, dependency rule)
|
||
├── UC-01 Realization … UC-12 Realization (one package per UC: analysis classes,
|
||
│ design elements, realization table below)
|
||
└── Design (component model of the joint architecture — server
|
||
crates + skara-brae-client + skara-brae-common; §3)
|
||
```
|
||
|
||
Joint-model decision (2026-10-03): one EA model covers the whole product — server, client
|
||
and common — because the use cases are player-facing and Requirement→realization
|
||
traceability spans tiers. Client-side UC realization packages (Vue boundary elements per
|
||
UC) are a future work item: no markdown source exists yet; they are NOT invented here.
|
||
Today the client enters the model via the §4 component model only.
|
||
|
||
## 2. UC realization mapping (analysis classes → design elements)
|
||
|
||
Legend — **Analysis class** (OpenUP stereotype): `«controller»`, `«entity»`, `«boundary»`. **Design element**: crate::module::item (Rust). "WI-2" marks elements introduced or re-homed by this work item; everything else exists at 899fde8.
|
||
|
||
| UC | Analysis class | Stereotype | Design element | Notes |
|
||
|---|---|---|---|---|
|
||
| UC-01 Register | AccountRegistry | controller | `sb-api::routes::{register, seed_users}` | argon2 hash via `sb-auth::hash`; JWT via `sb-auth::jwt` |
|
||
| | UserAccount | entity | `sb-shared::user::User`, `Role` | persisted via `sb-db::Database` |
|
||
| | AuthBoundary | boundary | `POST /api/auth/register`, `AuthResponse` | |
|
||
| UC-02 Authenticate | Authenticator | controller | `sb-api::routes::login`, `sb-auth::{hash::verify_password, jwt::create_token}` | |
|
||
| | TokenService | boundary | `POST /api/auth/login`, `AuthResponse`, `middleware::auth::auth_middleware` | middleware guards all UC-03…12 |
|
||
| UC-03 Manage Characters | CharacterFactory | controller | `sb-core::character::create_character` | takes injected rng (WI-1) |
|
||
| | Character | entity | `sb-shared::character::Character` (+ `Race`, `Class`, `CharacterStats`) | |
|
||
| | CharacterCatalog | boundary | `GET/POST /api/users/{id}/characters`, `GET /api/characters/{id}` | store: `AppState.characters` |
|
||
| | ResourceRegenerator | entity | `sb-core::character::apply_regen` (+ regen constants — WI-2 names them) | included sub-flow |
|
||
| UC-04 Browse Catalogue | CatalogueBrowser | boundary | `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}` |
|
||
| | GameData | entity | `sb-core::data::{EnemyDef, ZoneDef, EncounterEntry, LootDrop}`, `items::load_all_items` | |
|
||
| UC-05 Train Stat | TrainingService | controller | `sb-core::services::train_stat` | error type `DomainError` (WI-2) |
|
||
| | TrainingGrounds | entity | `sb-core::character::TRAINING_GROUNDS`, `training_cost` (+ cost constants WI-2) | |
|
||
| | GymBoundary | boundary | `GET/POST /api/characters/{id}/gym`, `GymResponse`, `TrainStatResponse` | |
|
||
| UC-06 Manage Equipment | EquipmentService | controller | `sb-core::services::{equip_item, unequip_item}` | `DomainError` (WI-2) |
|
||
| | Equipment/Inventory | entity | `Character.equipment` / `.inventory`, `sb-shared::item::Item` | |
|
||
| | EquipmentBoundary | boundary | `POST /api/characters/{id}/{equip,unequip}` | |
|
||
| UC-07 Trade at Shop | ShopService | controller | `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}` |
|
||
| | ShopStock | entity | `AppState.shop_stock` | persisted via `sb-db` |
|
||
| | ShopBoundary | boundary | `GET/POST /api/characters/{id}/shop`, `ShopResponse`, `ShopActionResponse` | |
|
||
| UC-08 Run Adventure | **AdventureService** | controller | `sb-core::adventure::run_adventure` (**new, WI-2**) + `services::pick_enemy` → `Result` (WI-2) | takes injected rng; `DomainError` (WI-2) |
|
||
| | CombatEngine | entity | `sb-core::combat::{resolve_combat_full, resolve_attack, crit tables, open_ended_roll}` + combat constants (WI-2) | |
|
||
| | Combatant | entity | `sb-core::combat::CombatStats` | built from Character/EnemyDef |
|
||
| | SpellEffect / BardSong | entity | `sb-core::combat::SpellEffect`, `sb-core::spells`, `sb-core::songs` | |
|
||
| | AdventureBoundary | boundary | `GET /api/characters/{id}/adventure`; `AdventureRunResponse` (**new, WI-2**), `sb-shared::responses::CombatLog` | |
|
||
| UC-09 Heal at Temple | HealingService | controller | `sb-api::routes::heal_character` (handler-side; extraction candidate, Q3) | |
|
||
| | TempleBoundary | boundary | `POST /api/characters/{id}/heal`; `HealResponse` (**new, WI-2**) | |
|
||
| UC-10 Practice Bard Song | SongService | controller | `sb-api::routes::set_song`; `sb-core::songs::available_songs` | |
|
||
| | BardSong | entity | `sb-core::songs::BARD_SONGS`, `Character.active_song` | |
|
||
| | SongBoundary | boundary | `GET/POST /api/characters/{id}/songs`, `SongsResponse`, `SetSongResponse` | |
|
||
| UC-11 Study Magic | MagicService | controller | `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)}` | |
|
||
| | Spell | entity | `sb-core::spells::SpellDef`, `Character.{known_spells, active_spell, spell_points}` | |
|
||
| | MagicBoundary | boundary | `GET/POST /api/characters/{id}/spells`; `SpellbookResponse`, `LearnSpellResponse` (**new, WI-2**) | |
|
||
| UC-12 Level Up | ReviewBoard | controller | `sb-core::character::level_up` | `DomainError` (WI-2) |
|
||
| | Progression | entity | `sb-core::character::{xp_for_level, level_up_cost, MAX_LEVEL}` (+ curve constants WI-2) | |
|
||
| | ReviewBoundary | boundary | `POST /api/characters/{id}/level-up`, `LevelUpResponse` | |
|
||
|
||
Cross-cutting design elements (WI-2): `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; `sb-core::constants` realizes NFR "no magic numbers"; `sb-api::routes::responses` realizes NFR-19 (wire-format freeze).
|
||
|
||
Dependency rule check (Clean Architecture): all controllers/entities above live in `sb-core`/`sb-shared` (domain side, no HTTP imports); all boundaries live in `sb-api`; the single current violations (ShopService, HealingService, parts of MagicService in sb-api) are recorded as debt with a follow-up question — the model must not paper over them (stale docs are defects).
|
||
|
||
### 2a. Analysis interactions (associations + dependencies, added 2026-10-03)
|
||
|
||
Within each realization package the analysis classes collaborate per the robustness rule
|
||
boundary ↔ controller ↔ entity (boundary never touches entity directly — exception: UC-04
|
||
has no controller, its boundary reads the static catalogue entity). Each association serves
|
||
the UC's Basic Path steps (boundary receives the actor request, controller applies the
|
||
rules, entities hold the state). Cross-cutting: the four `«uses»` dependencies realize the
|
||
error paths (Alternate/Exception flows) named in the cross-cutting paragraph above.
|
||
|
||
| UC | From | To | Type | Serves |
|
||
|---|---|---|---|---|
|
||
| UC-01 | AuthBoundary | AccountRegistry | Association | MSS steps 1–4 |
|
||
| UC-01 | AccountRegistry | UserAccount | Association | MSS steps 3–4 |
|
||
| UC-02 | TokenService | Authenticator | Association | MSS steps 1–3 |
|
||
| UC-03 | CharacterCatalog | CharacterFactory | Association | MSS (create) steps 1–4 |
|
||
| UC-03 | CharacterFactory | Character | Association | MSS steps 3–4 |
|
||
| UC-03 | CharacterFactory | ResourceRegenerator | Association | list/view (regen on return) |
|
||
| UC-04 | CatalogueBrowser | GameData | Association (no controller in this realization) | MSS steps 1–2 |
|
||
| UC-05 | GymBoundary | TrainingService | Association | MSS steps 1–5 |
|
||
| UC-05 | TrainingService | TrainingGrounds | Association | MSS steps 3–4 |
|
||
| UC-06 | EquipmentBoundary | EquipmentService | Association | MSS (equip) + unequip |
|
||
| UC-06 | EquipmentService | Equipment/Inventory | Association | MSS steps 2–3 |
|
||
| UC-07 | ShopBoundary | ShopService | Association | MSS (buy) + sell |
|
||
| UC-07 | ShopService | ShopStock | Association | MSS steps 3–4 |
|
||
| UC-08 | AdventureBoundary | AdventureService | Association | MSS steps 1–9 |
|
||
| UC-08 | AdventureService | CombatEngine | Association | MSS step 5 |
|
||
| UC-08 | AdventureService | Combatant | Association | MSS step 5 |
|
||
| UC-08 | AdventureService | SpellEffect / BardSong | Association | MSS steps 5, 8 |
|
||
| UC-09 | TempleBoundary | HealingService | Association | MSS steps 1–3 |
|
||
| UC-10 | SongBoundary | SongService | Association | MSS steps 1–2 + clear |
|
||
| UC-10 | SongService | BardSong | Association | MSS steps 1–2 |
|
||
| UC-11 | MagicBoundary | MagicService | Association | view + learn + activate |
|
||
| UC-11 | MagicService | Spell | Association | learn + activate steps |
|
||
| UC-12 | ReviewBoundary | ReviewBoard | Association | MSS steps 1–3 |
|
||
| UC-12 | ReviewBoard | Progression | Association | MSS step 2 |
|
||
|
||
The authoritative connector count is **24 associations** (UC-01:2, UC-02:1, UC-03:3,
|
||
UC-04:1, UC-05:2, UC-06:2, UC-07:2, UC-08:4 — its realization has one boundary, one
|
||
controller and three entities, UC-09:1, UC-10:2, UC-11:2, UC-12:2) plus **4 cross-cutting
|
||
dependencies** below — 28 connectors in total.
|
||
|
||
| UC | From (controller) | To | Type | Serves |
|
||
|---|---|---|---|---|
|
||
| UC-05 | TrainingService | DomainError (Architecture Overview) | Dependency «uses» | Alternate flows (error paths) |
|
||
| UC-06 | EquipmentService | DomainError (Architecture Overview) | Dependency «uses» | Alternate flows (error paths) |
|
||
| UC-08 | AdventureService | DomainError (Architecture Overview) | Dependency «uses» | Exception (unknown enemy → 500) |
|
||
| UC-12 | ReviewBoard | DomainError (Architecture Overview) | Dependency «uses» | Alternate flows (error paths) |
|
||
|
||
## 3. Design component model (joint architecture, added 2026-10-03)
|
||
|
||
Package `Analysis-Design / Design` — components of the three repos and their dependency
|
||
rule (sources: design note §2–3, mapping §2 dependency paragraph, client repo @ 34dc02f,
|
||
common repo @ wi-2-openup-docs). Every component note carries the UCs it serves.
|
||
|
||
| Component | Kind | Notes (traceability) |
|
||
|---|---|---|
|
||
| skara-brae-client | Component (presentation tier) | Vue 3.5 SPA (TypeScript, Pinia, Vite); monolithic App.vue @ 34dc02f; JWT bearer; REST via Vite proxy to :8080. Serves UC-01…12 as the player-facing boundary. |
|
||
| sb-api | Component (boundary/adapter) | Axum routes/handlers, `domain_status`, `responses` (wire-format freeze). May import sb-core, sb-shared, sb-common, sb-db, sb-auth (design §3). Serves all UC boundaries per §2. |
|
||
| sb-auth | Component (adapter) | argon2 hashing + JWT (UC-01/02). Imports sb-shared. |
|
||
| sb-db | Component (adapter) | persistence via `sb-db::Database`. Imports sb-shared. |
|
||
| sb-core | Component (domain) | controllers/entities: adventure (UC-08), services (UC-05/06), character (UC-03/12), combat, spells (UC-11), songs (UC-10), data/items (UC-04). Must not reference axum/http/serde_json::json!/tokio/sb-db/sb-api (design §3). |
|
||
| sb-shared | Component (domain types) | `User`, `Character`, `Item`, response types. Zero HTTP imports. Entities of all UCs. |
|
||
| sb-common | Component (data) | bilingual data package: data/ JSON (items, enemies, spells, zones), rust/ crate, ts/ package, codegen/. UC-04 data source; consumed by sb-core + sb-api; future client codegen. |
|
||
|
||
Dependencies (arrows = depends on): skara-brae-client → sb-api (REST/JSON);
|
||
sb-api → {sb-core, sb-shared, sb-db, sb-auth, sb-common}; sb-core → {sb-shared, sb-common};
|
||
sb-db → sb-shared; sb-auth → sb-shared. The dependency rule: inward toward
|
||
sb-core/sb-shared (domain); adapters (sb-api/sb-db/sb-auth) and the client at the edge.
|
||
|
||
## 4. Research summary — keyfob-station EA pipeline (reference)
|
||
|
||
Source: read-only clone `http://192.168.1.10:3000/jan/keyfob-station.git` (inspected 2026-10-03; no modifications).
|
||
|
||
- **Model file:** `docs/openup/model/keyfob-station.eapx` (MS Access database — the EA native format; EABase-derived). Never hand-edited.
|
||
- **Structure:** Model → `Requirements` package → `Use Case Model` package containing `Actor` and `UseCase` elements; scenario lists are stored on each use case as named scenarios of type **Basic Path / Alternate / Exception**, each with ordered steps carrying a per-step **Actor** tag and notes. An `Analysis-Design` package holds **one `UC-N Realization` package per use case** (realization diagrams + design elements).
|
||
- **Builders are surgical scripts:** `scripts/add-*.ps1` (PowerShell driving the EA COM object `New-Object -ComObject EA.App`, `$repo.OpenFile($modelPath)`). Each script opens the model, adds/rebuilds exactly one package's contents, and closes it — because EA repository IDs and package rebuilds clobber manual edits, hand edits do not survive; all content lives in the scripts (scenario text is embedded as PowerShell arrays of `Name/Type/Notes/Steps`). This matches our standards note: *model additions are surgical; builders rebuild whole packages*.
|
||
- **Exports:** `scripts/export-model-json.ps1` walks the Use Case Model package and emits `exports/use-case-model.json` + `supplementary-requirements.json`; realization diagrams are exported to PDF/PNG into `docs/openup/analysis-design/`. The JSON export is the doc-machine readable form of the same content.
|
||
- **Windows-only:** the pipeline runs on Windows (EA is a Win32 app; scripts use `.ps1` + COM). For Skara Brae, the same pattern applies when the modeling WI lands: keep `docs/openup/*.md` (this file set) as the source the builder scripts embed, never the reverse.
|
||
|
||
Adoption decision for Skara Brae (updated at 1B rework): the EA model + generator pipeline is **in WI-2 scope**. This document (§1–2) plus `requirements/use-case-model.md` are the content source; the model-home recommendation, agent preparation steps, generator scripts (`scripts/openup/build-model.ps1`, `export-model.ps1`), and the human-gate checklist are specified in `design-wi-2-architecture-cleanup.md` §11. The `.eapx` interactive editing session remains human-gated; everything around it is COD-phase agent work.
|