docs: plan completed game portfolio implementation

This commit is contained in:
2026-05-30 21:36:05 +03:00
parent 991c7e1965
commit ac417731d6
2 changed files with 1218 additions and 8 deletions
File diff suppressed because it is too large Load Diff
@@ -15,7 +15,7 @@ Add a public portfolio of completed tabletop adventures. A club owner or co-GM c
- A portfolio item is an independent adventure entity, not a flag on one session. - A portfolio item is an independent adventure entity, not a flag on one session.
- One adventure can reference multiple completed sessions from the same club. - One adventure can reference multiple completed sessions from the same club.
- Reviews are submitted by authenticated players, not entered manually by a GM. - Reviews are submitted by authenticated players, not entered manually by a GM.
- A player can review an adventure after being registered for at least one linked completed session. - A player can review an adventure after being actively registered as a non-GM participant for at least one linked completed session. Waitlisted players are not eligible.
- Each player can submit one review per adventure. - Each player can submit one review per adventure.
- A review is public only after the player explicitly consents to publication and a club owner or co-GM approves it. - A review is public only after the player explicitly consents to publication and a club owner or co-GM approves it.
- Public reviews show a display-name snapshot captured at submission time. They never expose platform IDs or account links. - Public reviews show a display-name snapshot captured at submission time. They never expose platform IDs or account links.
@@ -30,9 +30,9 @@ Add a public portfolio of completed tabletop adventures. A club owner or co-GM c
## Architecture ## Architecture
Add a portfolio vertical slice to `GmRelay.Web` and a schema migration in `GmRelay.Bot`. The portfolio tables reference the existing `game_groups`, `players`, and `sessions` tables but do not change the recruitment catalog query or its future-session filters. Add a bounded portfolio vertical slice to `GmRelay.Web` and a schema migration in `GmRelay.Bot`. The portfolio tables reference the existing `game_groups`, `players`, and `sessions` tables but do not change the recruitment catalog query or its future-session filters.
The protected management flow is exposed through `AuthorizedSessionService`, which reuses the existing owner/co-GM group authorization model. Public reads and authenticated review submission are exposed through `ISessionStore` and `SessionService`. Keep portfolio persistence separate from the already large scheduling store. `IPortfolioStore` and `PortfolioService` own portfolio reads, writes, and review submission. `AuthorizedPortfolioService` wraps protected management operations and reuses `ISessionStore.IsGroupManagerAsync` plus the existing current-user identity model for owner/co-GM authorization. Public Razor pages inject `IPortfolioStore` directly for sanitized reads.
Cover storage is isolated behind `IPortfolioCoverStorage`. Pages and services work with generated storage keys and public paths rather than physical file locations. The local implementation stores files in a persistent mounted directory and serves them through a dedicated request path. A future S3 implementation can generate equivalent public paths or signed delivery URLs while preserving the same service contract and database fields. Cover storage is isolated behind `IPortfolioCoverStorage`. Pages and services work with generated storage keys and public paths rather than physical file locations. The local implementation stores files in a persistent mounted directory and serves them through a dedicated request path. A future S3 implementation can generate equivalent public paths or signed delivery URLs while preserving the same service contract and database fields.
@@ -173,7 +173,7 @@ The storage key remains provider-neutral. A future S3-compatible implementation
## Service Contracts ## Service Contracts
Add sanitized DTOs to `ISessionStore`. Public DTOs must not expose player IDs, group IDs, session IDs, platform identifiers, moderator IDs, physical storage paths, or join links. Add sanitized DTOs to `IPortfolioStore`. Public DTOs must not expose player IDs, group IDs, session IDs, platform identifiers, moderator IDs, physical storage paths, or join links.
Representative contracts: Representative contracts:
@@ -210,7 +210,7 @@ Protected DTOs may carry IDs needed for editing and moderation.
### Protected Management ### Protected Management
Through `AuthorizedSessionService`: Through `AuthorizedPortfolioService`:
- Load draft and published adventure cards for a managed club. - Load draft and published adventure cards for a managed club.
- Load eligible completed sessions for a managed club. - Load eligible completed sessions for a managed club.
@@ -229,7 +229,7 @@ An authenticated user can submit a review from `/portfolio/{slug}` only when:
- The adventure is public. - The adventure is public.
- The user explicitly checks publication consent. - The user explicitly checks publication consent.
- The user is registered in `session_participants` for at least one linked session. - The user is registered in `session_participants` as a non-GM participant with `registration_status = 'Active'` for at least one linked session.
- The linked session is in the past. - The linked session is in the past.
- The user has not submitted a review for this adventure before. - The user has not submitted a review for this adventure before.
@@ -245,11 +245,11 @@ Extend `GroupDetails.razor` with a completed-adventures section:
- List draft and published portfolio cards. - List draft and published portfolio cards.
- Show title, publication state, linked-session count, displayed-GM count, and review moderation count. - Show title, publication state, linked-session count, displayed-GM count, and review moderation count.
- Provide a create action and edit links. - Provide a create action, edit links, and a link to the club's completed-session list.
### Completed Session Quick Action ### Completed Session Quick Action
Extend session history with an "Добавить в портфолио" action for a completed session that is not already linked. The action opens the adventure editor with that session preselected. Add a protected `/group/{groupId}/completed` page that lists past sessions for a managed club. Extend that page and session history with an "Добавить в портфолио" action for a completed session that is not already linked. The action opens the adventure editor with that session preselected.
### Adventure Editor ### Adventure Editor
@@ -320,6 +320,8 @@ volumes:
Development configuration uses a local directory under the application content root or an explicitly configured path. Development configuration uses a local directory under the application content root or an explicitly configured path.
The Web Docker image creates `/app/portfolio-covers` and assigns it to `$APP_UID` before switching to the non-root runtime user.
--- ---
## Documentation ## Documentation