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.
271 lines
No EOL
19 KiB
JSON
271 lines
No EOL
19 KiB
JSON
{
|
|
"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)."
|
|
}
|
|
]
|
|
} |