docs: plan completed game portfolio implementation
This commit is contained in:
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.
|
||||
- One adventure can reference multiple completed sessions from the same club.
|
||||
- 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.
|
||||
- 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.
|
||||
@@ -30,9 +30,9 @@ Add a public portfolio of completed tabletop adventures. A club owner or co-GM c
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -173,7 +173,7 @@ The storage key remains provider-neutral. A future S3-compatible implementation
|
||||
|
||||
## 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:
|
||||
|
||||
@@ -210,7 +210,7 @@ Protected DTOs may carry IDs needed for editing and moderation.
|
||||
|
||||
### Protected Management
|
||||
|
||||
Through `AuthorizedSessionService`:
|
||||
Through `AuthorizedPortfolioService`:
|
||||
|
||||
- Load draft and published adventure cards 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 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 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.
|
||||
- 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
|
||||
|
||||
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
|
||||
|
||||
@@ -320,6 +320,8 @@ volumes:
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user