SimPle is a full-stack social gaming platform. Users create accounts, build friend lists, host lobbies, chat in real time, and compete across a growing catalog of online games. The platform is designed so each game can plug into the host platform instead of being hard-coded into the app shell.
| Repository | Description |
|---|---|
| SimPlePlatform/SimPLe.Backend | ASP.NET Core 8 backend: auth, API, database, tests |
| SimPlePlatform/SimpLe.Frontend | Next.js 16 frontend: UI, auth pages, app shell, tests |
| Phase | Scope |
|---|---|
| Phase 1 | Social gaming host platform: auth, profiles, friends, game library, game-hosting architecture, lobbies, realtime, chat, match room, stats, notifications, admin, subscriptions, security/production readiness, trust & legal/compliance surfaces |
| Phase 2 | Actual games: Five-Letter Duel, Online Sudoku, Four in a Row, Falling Blocks Arena, Chess Lite, Checkers, Memory Grid, Snake Rush |
| Future | Hardware-enabled games via embedded devices |
Phase 1 builds everything around the games. Phase 2 adds the games themselves using the hosting architecture created in Phase 1.
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 (App Router), TypeScript, Tailwind CSS |
| Backend | ASP.NET Core 8, C# |
| Database | PostgreSQL + Entity Framework Core 8 |
| Auth | JWT HttpOnly access cookie + rotating hashed refresh tokens |
| Password hashing | Argon2id |
| OAuth | Google Identity Services ID token flow |
| CAPTCHA | Google reCAPTCHA v2 server-side verification |
| MailKit / SMTP | |
| Real-time | SignalR, planned |
| Testing | xUnit + NSubstitute, Vitest |
The backend follows Clean Architecture with a modular monolith structure:
SimPle.Api -> SimPle.Application -> SimPle.Domain
|
SimPle.Infrastructure
EF Core, JWT, Argon2, SMTP, external services
Each feature module is a folder inside the application/domain/infrastructure layers, not a separate service. This keeps deployment simple while keeping module boundaries clear.
The frontend is a Next.js App Router application. The (app) route group wraps
authenticated pages in the shared AppShell layout. Feature components live in
src/features/, UI primitives in src/components/ui/, and current planned
product data lives in src/mock/.
The DevOps evidence hub records current verification levels, portable-staging guidance, release-evidence rules, and the manual GitHub hardening checklist. It uses explicit local/CI/ staging/deployment levels so documentation never turns a local check into a cloud-deployment claim.
The zero-dependency portfolio evidence page can be published through GitHub Pages after the repository owner enables it manually. It is a public navigation page, not an application deployment or availability monitor.
| Area | Status |
|---|---|
| Email/password register, login, logout, refresh | Done |
| JWT access cookie and rotating hashed refresh tokens | Done |
| Email verification and password reset | Done |
| Google OAuth ID token flow and account linking | Done |
| reCAPTCHA v2 on login and registration | Done |
| Rate limiting, account lockout, CSRF checks, secure headers | Done |
| Optimistic concurrency on refresh rotation | Done |
| Security event logging and token cleanup background service | Done |
| Change password, change email, active sessions, revoke session, delete account | Done |
| Backend: 120 unit + 59 integration tests | Done |
| Frontend auth pages, protected routes, Google Sign-In, account security settings wired | Done |
| Area | Status |
|---|---|
| Backend: UserProfile fields on User entity (StatusMessage, Visibility, avatar/banner object keys, fallback color) | Done |
| Backend: Default profile exists for every registered user | Done |
| Backend: Current-user profile endpoint | Done |
| Backend: Public profile endpoint with visibility rules | Done |
| Backend: Profile update (display name, bio, region, status, fallback avatar color, visibility) | Done |
| Backend: S3 presigned upload flow for avatar and cover images | Done |
| Backend: Local MinIO support for S3-compatible profile media storage | Done |
| Backend: AWS S3 production path preserved through storage configuration | Done |
| Backend: Monthly username change policy with immediate change and admin-review request tracking | Done |
| Backend: External social links (GitHub, X/Twitter, Instagram, Discord, website) | Done |
Backend: Profile type social identity (Player, Developer) |
Done |
| Backend: Game interest tags (board-games, word-games, puzzle, strategy, arcade, casual, card, trivia) | Done |
Backend: EF Core migration AddUserProfiles |
Done - verified locally |
| Backend: 25 unit + 16 integration tests for profile scope | Done |
| Frontend: ProfilePage wired to real profile API | Done |
| Frontend: SettingsPage profile card wired to real profile API | Done |
| Frontend: Topbar/Sidebar identity already wired via auth session | Done |
| Security: Ownership checks, safe DTOs, visibility rules, validation | Done |
| Production: CloudFront delivery and deployed S3 verification | Pending deployment |
The original revision-1 backend/security/frontend/E2E evidence remains valid for the narrower friendship
contract. A later product-journey audit found that global people search, canonical profile routing, identity
links, relationship-aware profile actions, and privacy-aware profile/mutual friend drill-down were not in that
contract. Module 3 was reopened before Module 4; the revision-2 backend, frontend, live E2E verification,
production review, and final evidence sign-off are now all complete (including two real bugs found and fixed
during the live E2E run — see docs/modules/module-03-friends-social-graph/testing-report.md), and the module
is merged to main in both SimPLe.Backend and SimpLe.Frontend.
| Area | Status |
|---|---|
Backend: 16 /api/friends endpoints (list/search, requests, discovery, suggestions, blocks, settings) |
Done |
| Backend: Friendship/Block/UserFriendSettings/DismissedFriendSuggestion domain + migrations | Done - verified on real PostgreSQL |
| Backend: Transactional integration-event outbox (7 event types staged with the aggregate write) | Done |
| Backend: Cross-send auto-accept, decline/cancel cooldowns, block atomicity, concurrency retry | Done |
| Backend: 273 unit + 187 integration tests (incl. 18 real-Postgres concurrency/migration tests) | Done - 0 failed, 0 skipped |
| Security: BOLA/IDOR to privacy-safe 404, timing-safe discovery, per-account rate limits | Done - --security=asvs-lite, no Critical/High findings |
| Security: Audit-event logging for denials | Done - M03-006 fixed |
| Security: Block-endpoint response minimality | Done - M03-007 fixed |
Frontend: /friends, dashboard, sidebar badge, invite picker, settings privacy/blocks wired to real API |
Done |
| Frontend: 96 Vitest tests across 7 reconciled suites; contract-drift check DRIFT=0 | Done |
| Verification: Two-user Playwright E2E against a live local stack | Done - 1/1 passed |
Revision 2: canonical /u/{username} route and public/authenticated profile behavior |
Done |
| Revision 2: composed people search, identity links, and relationship-aware profile actions | Done |
| Revision 2: privacy-aware target/mutual friends lists with 20/50 keyset pagination | Done |
| Revision 2: independent search/request/friends-list visibility and abuse caps | Done |
| Revision 2: remove fake profile presence/ELO/history/achievements/favorites | Done |
| Revision 2: backend 321 unit + 224 integration; frontend 188 Vitest; contract-drift DRIFT=0 | Done - 0 failed |
| Revision 2: security findings M03-008/M03-009/M03-011 fixed, M03-010 resolved (product decision) | Done - independently re-verified |
| Revision 2: expanded 3-user/anonymous navigation, privacy, and pagination Playwright | Done - 1/1 passed, 25.7s, live local stack |
| Revision 2: production review and final evidence sign-off | Done - merged to main |
Backend, both security review phases, frontend, live E2E/accessibility verification, production review, and
final evidence sign-off are all complete and independently verified. Module 4 is also the first module whose
module-e2e-manifest.json entry sets accessibilityPolicy: "required"; the required axe-core scan surfaced 6
real accessibility defects in shared app-shell code (not Module 4 code), which were fixed with explicit user
sign-off before the scan went clean. Documentation (api-reference.md, technical-flow.md,
testing-report.md) is complete — see docs/modules/module-04-game-library-discovery/. Module 4 is
complete and merged to main in all three repos (SimPLe.Backend, SimpLe.Frontend, SimPle.Project).
| Area | Status |
|---|---|
Backend: 6 /api/games endpoints (catalog list/detail/featured, favorites list/PUT/DELETE) |
Done |
Backend: Game/GameTag/GameModeCapability/UserFavoriteGame/CatalogSeedHistory domain + migrations |
Done - verified on real PostgreSQL |
| Backend: Advisory-lock + checksum-idempotent catalog seeder (8 canonical games) | Done |
| Backend: Query-shape-bound keyset cursor, ETag/304 revalidation, lifecycle state machine | Done |
| Backend: 412 unit + 219 integration tests (incl. 32 real-Postgres tests) | Done - 0 failed |
Security: --security=light backend-phase and post-frontend-phase review |
Done - zero unwaived Critical/High/Medium; 2 Low + 4 Info deferred |
Frontend: /games, detail, dashboard, search, and profile favorites wired to real API |
Done |
Frontend: 223 Vitest tests; check-contract-drift.mjs DRIFT=0 |
Done |
| Verification: Playwright E2E against a live local stack | Done - 2/2 passed |
Verification: First module to enforce accessibilityPolicy: "required"; 6 axe violations fixed in shared app shell |
Done - zero violations after fix |
Documentation: api-reference.md, technical-flow.md, testing-report.md |
Done |
| Production review and final evidence sign-off | Done - merged to main |
Module 5 is backend-only and deliberately pure/in-memory: it replaces three orphaned, unimplemented
game-host stub files with a typed IGameDefinition<TState,TCommand,TPlayerView> plugin contract, a
non-generic host adapter, a TryResolve(slug, engineVersion) registry, an allow-listed System.Text.Json
codec with a checksummed byte envelope, a PCG32-v1 deterministic RNG, a size/budget/redaction invoker
boundary, and a catalog/engine compatibility validator. It adds no EF entity/migration, no public route, and
no frontend code — Module 4's game-library UI is untouched. Backend implementation, --security=asvs-lite
review, and targeted verification (including a two-process golden-vector determinism proof) are complete and
independently verified. Documentation (api-reference.md, technical-flow.md, testing-report.md) is
complete — see docs/modules/module-05-game-hosting-architecture/. Module 5 is complete for its local,
in-process scope. Hosted CI, portable staging, release provenance, and cloud deployment evidence are owned
by Module 14 rather than retroactively being a Module 5 requirement.
| Area | Status |
|---|---|
Backend: typed IGameDefinition contract, envelopes, PCG32-v1 RNG, allow-listed codec, registry, invoker, catalog-compatibility validator |
Done |
Backend: legacy stub disposition (IGameEngine/GameSession deleted, IGameRegistry rewritten to TryResolve) |
Done |
Backend: startup fail-fast on duplicate (slug, engineVersion) or catalog mismatch; zero product engines is a valid Phase 1 state |
Done |
Backend: 177 unit + 12 integration GameHost-filtered tests |
Done - 189/189 passed |
| Backend: no-EF-model/migration-delta proof | Done - zero GameHost entity/DbSet/migration |
Security: --security=asvs-lite review |
Done - zero unwaived Critical/High/Medium; 1 Low + 2 Info deferred |
| Verification: two-process golden-vector SHA-256 determinism proof (10 vectors) | Done - byte-identical across both runs |
| Verification: Stopwatch benchmark (10,000-command reference workload) | Done - p95 0.0293 ms vs. < 25 ms budget |
Verification: check-contract-drift.mjs (no new route/frontend surface) |
Done - DRIFT=0 |
Documentation: api-reference.md, technical-flow.md, testing-report.md |
Done |
| Local completion evidence | Done - cloud/CI delivery evidence is explicitly deferred to Module 14 |
Module 6 makes lobby creation, joining, invites, and Quick Match real, replacing the prior UI-only mock and
orphaned backend stub. It adds seven new tables (lobbies, lobby_members, lobby_invites,
lobby_join_credentials, lobby_start_requests, matchmaking_tickets, matchmaking_assignments) plus an
additive game_capability_profiles table and a new alternate key on Module 4's games table; 20 new
endpoints under /api/lobbies and /api/matchmaking; and the codebase's first outbox dispatcher and first
use of FOR UPDATE SKIP LOCKED. Backend implementation, two --security=asvs-lite review phases (backend
and post-frontend), frontend wiring, and live-stack E2E verification are complete and independently
verified. Documentation (api-reference.md, technical-flow.md, testing-report.md) is complete — see
docs/modules/module-06-lobby-matchmaking-system/. Module 6 is complete for its local scope; hosted CI,
portable staging, release provenance, and cloud deployment evidence are owned by Module 14. The matching
worker/Start action remain intentionally dormant pending Module 8's match-runtime handoff.
| Area | Status |
|---|---|
| Backend: lobby/invite/credential/matchmaking domain, outbox dispatcher, bounded transaction retry | Done |
Backend: legacy stub disposition (orphaned Lobby/LobbySlot deleted and replaced) |
Done |
| Backend: 862 unit + 375 integration tests (real PostgreSQL incl. two-worker claim race, one-active invariant) | Done - 862/862, 375/375 |
Security: --security=asvs-lite review, backend + post-frontend phases |
Done - zero unwaived Critical/High/Medium; 2 Low + 5 Info deferred |
| Frontend: create/join/leave/ready/invite/Quick Match wiring across 9 surfaces | Done - 243/243 vitest, DRIFT=0 |
| Verification: live-stack Playwright E2E (real backend + frontend + Postgres) | Done - 2/2 passed |
Documentation: api-reference.md, technical-flow.md, testing-report.md |
Done |
| Local completion evidence | Done - cloud/CI delivery evidence is explicitly deferred to Module 14 |
| Match runtime (matching worker, Start action) | Dormant pending Module 8 |
Module 7: Real-Time Presence, Lobby Updates & Chat - Locally Complete; Delivery Evidence Deferred to Module 14
Module 7 replaces the mock presence dots, lobby-update polling, and chat placeholder with real ASP.NET Core
8 SignalR: one authenticated /hubs/realtime endpoint (exact-origin allowlist, CloseOnAuthenticationExpiration,
and a per-method scope/suspension/block recheck on every subscribe/send/delete rather than trusting the
principal cached at handshake), an in-memory presence registry (Playing > InLobby > Online > Away > Offline precedence, a 5-connection-per-user cap, and 0s/2s/10s/30s reconnect), and persistent lobby chat
(30-day retention, block-aware delivery identically on the realtime and REST-history paths, with a
moderation-hold seam left empty for Module 12). Backend implementation, two --security=asvs-lite review
phases (backend and post-frontend), frontend wiring, and live-stack E2E verification are complete and
independently verified. Documentation (api-reference.md, technical-flow.md, testing-report.md) is
complete — see docs/modules/module-07-realtime-presence-chat/. Module 7 is functionally complete for its
local, single-instance scope. Its formal ordered stage-checkpoint chain (index.json) carries only the
planning stage — the backend security-review stage ran on Sonnet 5 instead of the manifest-routed Opus for
that assurance-sensitive stage, so later stages could not be chained in; the project owner explicitly
waived backfilling that chain for this module. This is a documented process/tooling gap, not a
functional one — the security, frontend-security, and verification checkpoint files themselves exist, are
internally valid, and record real, passing evidence. releaseEligible stays false regardless, pending
Module 14's CI/container/staging foundation. Match-scope chat/updates, moderation evidence copy, live
suspension enforcement, and the Redis/Azure SignalR backplane are explicitly out of scope, deferred to
Modules 8/12/14.
| Area | Status |
|---|---|
| Backend: SignalR hub, presence registry, scope authorization, chat aggregate/service/repository, retention sweeper, outbox watermark-aware handler | Done |
Backend: legacy stub disposition (dead placeholder notifier interfaces + orphaned DirectMessage enum removed) |
Done |
| Backend: full unit suite | Done - 962/962 passed (operations.json); 955/955 recorded earlier in the same session before verification-stage fixes |
Security: --security=asvs-lite review, backend + post-frontend phases |
Done - zero unwaived Critical/High; 2 Medium + 2 Low fixed and test-verified; 3 Info deferred non-blocking |
| Frontend: realtime client, presence de-mocking, chat wiring across 7 surfaces | Done - 264/264 vitest, DRIFT=0 |
| Verification: live-stack Playwright E2E (real backend + frontend + Postgres) | Done - 1/1 passed, zero axe violations |
Documentation: api-reference.md, technical-flow.md, testing-report.md |
Done |
Formal ordered stage-checkpoint chain (index.json) |
Owner-waived process gap - only planning indexed; functional evidence unaffected |
| Local completion evidence | Done - cloud/CI delivery evidence is explicitly deferred to Module 14 |
The frontend already includes mock UI for dashboard, profile, settings, friends, game library, game detail, lobby, chat, match room, leaderboards, and notifications. These screens are the product target, but they are not all wired to backend APIs yet.
The roadmap below assigns every visible mock UI surface to a module so that when the project is complete, the current UI can be 100% functional as intended.
cd backend
dotnet restore
.\scripts\Initialize-AuthEnvironment.ps1
docker compose -f compose.auth.yml up -d
dotnet ef database update --project src/SimPle.Infrastructure --startup-project src/SimPle.Api
dotnet run --project src/SimPle.ApiSwagger runs at https://localhost:7139/swagger when the backend is running.
cd frontend
npm install
cp .env.local.example .env.local
npm run devThe frontend runs at http://localhost:3000. The backend API must be running at
NEXT_PUBLIC_API_URL, defaulting to http://localhost:5147.
Purpose:
-
Secure account creation, sign-in, browser sessions, account recovery, and account-security settings.
-
Email/password register, login, logout, logout-all, refresh token flow
-
Current user endpoint
-
JWT access cookie and hashed rotating refresh token storage
-
Email verification and resend verification
-
Password reset request and confirmation
-
Google OAuth ID token flow and account linking
-
Frontend auth pages wired and tested
-
Rate limiting, validation, secure cookies, CSRF header, security headers
-
reCAPTCHA on login and registration
-
Account lockout and suspension enforcement
-
Security event logging and token cleanup background service
-
Change password (verifies current, revokes all sessions)
-
Change email flow (verification link to new address)
-
Active sessions list with IP and device info
-
Revoke individual session
-
Revoke all sessions / sign out all devices
-
Account delete with password confirmation
-
Google OAuth link/unlink management (planned)
-
Production PostgreSQL migration verification (pending deployment)
Status: Complete for core auth and account-security settings.
Purpose:
-
Public social identity, profile page, and profile-settings UI wired to the backend.
-
Display name, bio, region, status message, fallback avatar color, avatar/banner display URLs
-
Avatar/profile picture upload, replace, remove, and fallback avatar color
-
Cover/banner upload, replace, remove, and fallback banner
-
Local MinIO support for S3-compatible profile media storage
-
AWS S3 production path preserved through storage configuration
-
Presigned upload flow for profile media
-
Avatar and banner image upload via private S3-compatible presigned URLs (JPEG/PNG/WebP, SVG not allowed, 5 MB / 10 MB limits)
-
Username/handle display; 1 immediate change and 1 admin-review request per UTC calendar month
-
Profile visibility: public, friends-only (owner-only until Module 3), private
-
Web profiles: external social links for Instagram, X/Twitter, website, GitHub, and Discord where supported
-
Privacy control: public and private profile visibility
-
Friends-only visibility stored/handled if present, with Module 3 behavior documented
-
Profile type: Player and Developer social identity distinction
-
Game interest tags (board-games, word-games, puzzle, strategy, arcade, casual, card, trivia)
-
Public profile page with visibility enforcement
-
Own profile page with inline edit
-
Settings page profile card wired to real API
-
Sidebar and topbar identity from real auth session
-
Role and legacy ELO display (read-only; revision-2 Module 3 removes it from production profile UI until M10)
-
Ownership checks and safe DTOs (no email/auth fields in public profile)
-
EF Core migrations:
AddUserProfiles,AddUsernameChangeRequests,AddProfileSocialIdentityFields,FixProfileSocialIdentityAndUsernamePolicy -
Unit and integration test coverage >90% for profile scope
-
docs/modules/module-02-user-profile-social-identity/documentation added -
FriendsOnly visibility enforced per accepted friend (Module 3 revision 1)
-
Production CloudFront delivery and deployed S3 environment verification (pending deployment)
Status: Complete for local/backend/frontend Module 2 scope. Production CloudFront delivery and deployed environment verification remain planned.
Product behavior is authoritative in
../docs/module-requirements/module-03-friends-social-graph.md; this roadmap records status only.
Purpose:
- Make friends, friend requests, suggestions, blocking, and friend-related privacy controls functional.
Current UI target:
/friends- Dashboard friends panels
- Friend request badge in sidebar
- Invite friend modal friend picker
/settings-> Privacy -> friend request controls and block list
Included features:
- Friend list (keyset-paged)
- Search friends
- Send, accept, decline, cancel friend requests (incl. cross-send auto-accept and cooldowns)
- Remove friend
- Suggested players
- Mutual friends count
- Block/unblock users
- Friend request privacy: anyone, friends-of-friends, off
- Friend count surfaced on profile
- Safe exact-username discovery (Add Friend flow)
- Canonical
/u/{username}profile route; UUID/username/meambiguity resolved (non-owner legacy ids show an honest "moved" state — no backend UUID→username lookup endpoint exists) - Authenticated bounded people search by username/display-name prefix
- Profile navigation from every friend/request/suggestion/discovery/dashboard identity
- Server-derived relationship state and Add/Cancel/Accept/Decline/Remove/Block/Share profile actions
- Privacy-aware profile Friends and Mutual Friends drill-down with visible counts and keyset pagination
- Independent profile, search, friend-request, and friends-list visibility controls
- Composed topbar search shell: People now, Games/Public Lobbies explicitly labelled unavailable (M4/M6)
- Truthful unavailable states instead of fake profile presence/ELO/history/achievements/favorites
Backend/database/API work:
- Persist friendships, blocks, settings, suggestion dismissals, and a transactional integration-event outbox
- Friends controller, service, repository, DTOs, validators (16 endpoints)
- Enforce block rules across friend requests and visibility (chat/invites enforcement is out of scope until Modules 6/7 add those surfaces)
- Real-PostgreSQL verification of expression uniqueness,
xminconcurrency, CHECK/cascade, and migration backfill - People search, viewer-context, and friends/mutual-friends drill-down endpoints (5 new/changed
revision-2 endpoints), independent search/friends-list visibility +
PrivacyPolicyVersion, retired usernames, durable send caps — verified on real PostgreSQL (321 unit + 224 integration, 0 failed)
Frontend work:
- Wire
/friendstabs and actions to API - Replace mock friend counts, pending requests, and suggestions
- Replace fake presence/activity/profile progression with honest unavailable states (deferred to M7/M10/M11 as documented placeholders, not silently faked)
- Composed people search (
PeopleSearchCombobox,/search), canonical profile page, sharedPlayerIdentitycomponent, friends/mutual-friends drill-down pages — 188 Vitest tests, DRIFT=0
Revision-1 verification (historical; superseded in scope by revision-2 evidence below):
- Backend: xUnit 273 unit + 187 integration (incl. 18 real-Postgres tests), 0 failed, 0 skipped
- Security review (
--security=asvs-lite): no Critical/High production findings - Frontend: Vitest 96/0 across 7 reconciled suites,
check-contract-drift.mjsDRIFT=0 - Module E2E (Playwright, live local stack, two users): 1/1 passed
- Revision-1 production review and final evidence
Revision-2 verification:
- Backend: xUnit 321 unit + 224 integration (incl. real-Postgres migration/concurrency tests), 0 failed, 0 skipped
- Security review (
--security=asvs-lite): no Critical/High findings; M03-008/M03-009/M03-011 fixed and M03-010 resolved by product decision, all independently re-verified - Frontend: Vitest 188/0 across all reconciled suites,
check-contract-drift.mjsDRIFT=0 - Module E2E: the expanded A/B/C/anonymous Playwright scenario (
module-03-friends.spec.ts) executed against a live seeded local stack and passed (1/1, 25.7s) — proving composed search, request send/accept, authorized paginated friends drill-down (20→25 rows across the cursor boundary, no duplicates), live friends-list-visibility enforcement, anonymous Public/Private profile split,/profile/mecanonical resolution, and block convergence across search/profile/friends-list/ mutual-friends. Two real product bugs were found and fixed during this run: aCursor.cspagination defect and aProtectedRoute/route-group gap blocking anonymous access toPublicprofiles (now a dedicated(public)route group) — seetesting-report.md. - Production review and final evidence sign-off for the full revision-2 scope
Status:
- Revision 1 is complete and green (see
docs/modules/module-03-friends-social-graph/, the security audit, and historical final evidence); M03-006 and M03-007 were fixed in a follow-up pass. - Revision 2 backend (Steps 2A/2B), frontend (Steps 4A/4B), live E2E verification, production review, and
final evidence are all implemented and independently verified, including a follow-up security fix pass
verified (see
docs/security/audits/module-03-friends-social-graph.md). Module 3 is complete and merged tomainin bothSimPLe.BackendandSimpLe.Frontend(docs/ai-workflow/evidence/module-03-friends-social-graph/revision-2/final.json).
Product behavior is authoritative in
../docs/module-requirements/module-04-game-library-discovery.md.
Purpose:
- Make the game library and game detail pages real before building matchmaking and match state.
Current UI target:
/games/games/[slug]- Dashboard continue-playing and recommended game cards
- Topbar/composed search Games tab
- Profile favorite games tab
Included features:
- Game catalog (8 seeded games, lifecycle-aware: Draft/ComingSoon/Available/Maintenance/Retired)
- Game detail pages, including an honest 410 tombstone for retired games
- Search, filters (category/tag/mode, capped at 5 values/dimension), sort, keyset "load more"
- Game rules/descriptions and difficulty display
- Featured/spotlight game (single-featured-rank invariant enforced by a partial unique index)
- Favorite games (soft-delete
IsActive+CycleId, idempotent PUT/DELETE, real per-user persistence) - Supported modes: solo, AI, multiplayer, ranked (entry actions honestly disabled, naming Modules 6/8/9)
- Active/disabled game state per-mode (deferred to owning modules; lifecycle state itself is real)
Backend/database/API work:
-
GamesController(6 endpoints),GamesService,GameRepository - Game DTOs matching the UI cards/detail page (
GameCatalogDto,GameTombstoneDto,GameFavoriteDto,GameEntryActionDto) - Seeded initial game catalog via advisory-lock + checksum-idempotent
GameCatalogSeeder - Two additive EF Core migrations, verified on real PostgreSQL
Frontend work:
- Replaced
GAMESmock data with livegamesApicalls on/games, detail, dashboard, search, profile - Play, Quick Match, Invite Friend, Create Lobby, and Enter Match Room buttons rendered honestly
disabled, each naming its real owning module (6, 8, or 9) until that module ships
Verification:
- Backend: 412 unit + 219 non-Postgres integration + 32 real-Postgres tests, 0 failed
- Security review (
--security=light, both backend and post-frontend phases): zero unwaived Critical/High/Medium findings; 2 Low + 4 Info findings recorded and deferred - Frontend: 223 Vitest tests,
check-contract-drift.mjsDRIFT=0 - Module E2E (Playwright, live local stack):
module-04-game-library.spec.ts2/2 passed; also the first module to enforceaccessibilityPolicy: "required"— 6 real axe-core violations were found and fixed in shared app-shell code (with explicit user sign-off), after which the scan is clean - Production review and final evidence sign-off
Status:
- Backend, security (both phases), frontend, live E2E/accessibility verification, documentation
(
api-reference.md,technical-flow.md,testing-report.md), production review, and final evidence sign-off are all complete (seedocs/modules/module-04-game-library-discovery/). Module 4 is complete and merged tomainin all three repos (SimPLe.Backend,SimpLe.Frontend,SimPle.Project).
Product behavior and ownership boundaries are authoritative in
../docs/module-requirements/module-05-game-hosting-architecture.md; Module 5 owns engine contracts, serialization, and registry behavior, while Module 8 owns persisted match sessions.
Purpose:
- Define how games plug into the platform without hard-coding each game directly into the app shell.
Included features:
- Typed
IGameDefinition<TState,TCommand,TPlayerView>registration pattern (immutable(slug, engineVersion)key; explicitTryResolve, no latest-version fallback) - Allow-listed
System.Text.Jsonstate/command/view codec with a checksummed byte envelope - Generic deterministic engine state/command/view contracts (
GameStateEnvelope,GameCommandEnvelope,PlayerViewEnvelope,EngineTransition) - Server-authoritative move-validation contract (
ApplyCommandreturns a typed rejection with no partial mutation; client-supplied actor/seat data is never trusted by Module 5's own code) - Versioned terminal-result handoff contract (
EvaluateResult/TerminalResultCandidate); Module 10 owns rating/stats calculations -
PCG32-v1deterministic RNG seeded from one server-chosen 128-bit match seed
Backend/database/API work:
- Game engine registry/service (
GameRegistry,HostedGameDefinitionadapter,GameHostInvoker) - Engine-state serialization (
GameHostJsonContext); persisted match/session ownership remains Module 8 - Legacy stub disposition:
IGameEngine/GameSessiondeleted,IGameRegistryrewritten toTryResolve(slug, engineVersion) -
CatalogEngineCompatibilityValidatorreconciling registered engines against Module 4's catalog; startup fails fast on a mismatch or duplicate key - 177 unit + 12 integration tests for engine lookup, deterministic commands, serialization, views, and
terminal results, plus a
HiddenTokenDrafttest-only reference engine and 10 golden vectors - No EF entity, table, or migration — proven by
GameHostNoEfDeltaTests, not merely asserted
Frontend work:
- No new UI required — none built; Module 4's game-library UI is unchanged
- Existing room UI stays mock until Module 8
Verification:
- Backend: 189/189
GameHost-filtered tests (177 unit + 12 integration), 0 failed - Security review (
--security=asvs-lite): zero unwaived Critical/High/Medium findings; 1 Low + 2 Info recorded and deferred - Two-process golden-vector SHA-256 determinism proof: byte-identical across all 10 vectors
- Stopwatch benchmark (10,000-command reference workload): p95 = 0.0293 ms (budget < 25 ms), max single-command latency = 12.1803 ms (soft budget <= 100 ms)
-
check-contract-drift.mjs: DRIFT=0, confirming no new route or frontend call - Browser E2E:
not_applicable(no browser surface); the two-processGameHost-filtered test run is the manifest-mandated substitute - Local completion evidence recorded; hosted CI/portable-staging/deployment verification belongs to Module 14
Status:
- Backend, security review, and targeted verification are complete and independently verified
(see
docs/modules/module-05-game-hosting-architecture/). Module 5 is locally complete. Its hosted CI, portable staging, and deployment evidence is a later Module 14 delivery responsibility.
Product behavior is authoritative in
../docs/module-requirements/module-06-lobby-matchmaking-system.md. Module 6 owns lobby/invite/credential and matchmaking-ticket lifecycle; Module 8 owns the persisted match room the lobby hands off to once a match runtime is registered.
Purpose:
- Make the create-lobby modal and lobby page real.
Current UI target:
- Topbar Create Lobby button
/lobby/[lobbyId]- Game detail Create Lobby action
- Dashboard lobby invites and active lobby link
Included features:
- Create lobby (public/private, seats/max players, settings: game, time control, ranked/casual, region, spectators, AI fill toggle as a setup option with actual AI behavior deferred to Module 9)
- Join lobby by code/link (
LobbyJoinCredential, HMAC-SHA256 digest, constant-time compare) - Leave lobby, host controls (kick, settings patch, deterministic host transfer)
- Ready state (host implicitly ready; reset on every settings change and every join/leave/kick)
- Invite links/codes with expiry (30 minutes); invite accept/decline routes
- Required same-region Quick Match queue with deterministic ±100/±200/±400 rating-band widening at 15s/30s/60s ticket-age boundaries, anchor-oldest-ticket tie-break
- Start reaching a real, playable match room (blocked on Module 8's match runtime;
Startcorrectly returnsLobbies.MatchRuntimeUnavailablewhile no runtime is registered)
Backend/database/API work:
- Persist lobbies, members, invites, join credentials, start requests, matchmaking tickets/assignments,
and an additive
game_capability_profilestable (7 new tables total) - 20 endpoints:
LobbiesController(17 routes) andMatchmakingController(3 routes), full DTOs/ validators - Capacity, expiry, privacy, and host authorization checks; 7 partial unique indexes as the real
concurrency boundary; cross-table
pg_advisory_xact_lockfor one-active-lobby-or-ticket - Codebase's first outbox dispatcher (
OutboxProcessor/IOutboxHandler) and first use ofFOR UPDATE SKIP LOCKEDin the matching worker - Legacy stub disposition: orphaned
Lobby/LobbySlot/LobbyStatus/LobbyPrivacydeleted and replaced, following the Module 5 precedent - 862 unit + 375 integration tests, including real-PostgreSQL migration/concurrency/race suites (two- worker double-claim, concurrent last-seat join, cross-table invariant, serialization/deadlock retry)
Frontend work:
- Wired create/join/leave/ready/invite/kick/settings/Quick Match actions across 9 surfaces
(
CreateLobbyModal,QuickMatchModal,InviteFriendModal,LobbyPage,SearchResultsPage's Public Lobbies tab,DashboardPage,ProfilePage,GameDetailPage,LandingPage) - Replaced hard-coded
SP-7F-29with real lobby codes/credentials everywhere except one known remainingSidebar.tsxnav-link defect (tracked, not yet fixed) - Start intentionally left disabled with honest copy naming Module 8, instead of the prior mock navigation to a room that doesn't exist yet
- Keep live updates and chat mock until Module 7
- 243/243 Vitest passing,
check-contract-drift.mjsDRIFT=0, production build clean
Verification:
- Backend: 862/862 unit + 375/375 integration (real PostgreSQL), 0 failed
- Security review (
--security=asvs-lite), backend + post-frontend phases: zero unwaived Critical/ High/Medium; 2 Low + 5 Info recorded and deferred - Frontend: 243/243 Vitest, lint clean,
check-contract-drift.mjsDRIFT=0, production build clean - Live-stack Playwright E2E (real backend + frontend + PostgreSQL, no mocks): 2/2 passed, zero axe violations, after a fix-and-rerun loop that found and fixed one real product bug (game-lifecycle gating) and two real pre-existing accessibility defects
- Local completion evidence recorded; hosted CI/portable-staging/deployment verification belongs to Module 14
Status:
- Backend, both security review phases, frontend, and live-stack verification are complete and
independently verified (see
docs/modules/module-06-lobby-matchmaking-system/). Module 6 is locally complete. Its hosted CI, portable staging, and deployment evidence is a later Module 14 delivery responsibility. The matching worker andStartaction are intentionally dormant pending Module 8's match-runtime handoff and do not yet produce a playable match room.
Product behavior is authoritative in
../docs/module-requirements/module-07-realtime-presence-chat.md. Module 7 owns the realtime transport/authorization boundary and lobby chat; Module 8 registers match scope on the same typed contract, and Module 12 owns moderation evidence copy and the live suspension trigger.
Purpose:
- Make online status, lobby updates, and lobby chat live.
Current UI target:
- Presence dots in sidebar, topbar, friends page, lobby, and match room
- Lobby chat panel
- Match chat panel (visibly unavailable pending Module 8)
- Lobby updates without refresh
Included features:
- Presence states: online, away, playing, in lobby, offline (
Maxprecedence across up to 5 connections per user) - Lobby live updates over SignalR (thin
LobbyChangedhint + client re-fetch, replacing the prior 2-second poll) - Lobby chat (send/read/delete, block-aware identically on the realtime and REST-history paths)
- Match chat (blocked on Module 8's match-scope authorizer;
NullMatchScopeAuthorizerreturnsRealtime.ScopeNotAvailabletoday) - Persistent lobby chat with 30-day retention and authorized
(createdAt, id)cursor history - Basic abuse controls: length limits (1-1000 Unicode scalars), rate limits (5 connections/user; 5 msgs/5s + 20/min), versioned deny-list profanity filter, author-only delete producing a tombstone
Backend/database/API work:
- One authenticated
/hubs/realtimeSignalR endpoint (SubscribeLobby,UnsubscribeLobby,SendLobbyMessage,ReportActivity), exact-origin handshake allowlist,CloseOnAuthenticationExpiration -
IRealtimeScopeAuthorizerre-checking membership/suspension/block on every subscribe/send/delete (never a cached prior result);NullMatchScopeAuthorizerseam for Module 8 - In-memory presence registry, chat aggregate/service/repository, and an outbox-watermark-aware
LobbyRealtimeHandler - Two REST routes:
GET /api/chat/lobbies/{lobbyId}/messages,DELETE /api/chat/messages/{messageId} - Additive migration
20260717001316_AddChatAndRealtimeActivation(chat_messages,chat_message_holds,outbox_handler_activations) - no existing table altered or dropped -
AuthService.LogoutAsyncnow revokes the session family (approved Module 1 behavior change) - Legacy stub disposition: dead placeholder notifier interfaces deleted; orphaned
DirectMessageenum value removed, proven by a reference/search test
Frontend work:
- Wire
ChatPanelto realtime events (composer<textarea>, dedupe across REST + realtime reconciliation, stable message-id keys) - Replace mock presence/activity strings across 7 surfaces (
Sidebar,Topbar,SettingsPage,DashboardPage,FriendsPage,LobbyPage'sSeatCard,GameRoomPage) - absent presence renders as unknown, never online - Match
ChatPanelmade visibly unavailable with its mock send removed; landing copy no longer promises direct messages
Verification:
- Backend: full unit suite 962/962 passed (
operations.json), 0 build errors/warnings, real-PostgreSQL retention/hold-race and idempotency suites passed - Security review (
--security=asvs-lite), backend + post-frontend phases: zero unwaived Critical/High; 2 Medium + 2 Low findings fixed and test-verified; 3 Info findings recorded and deferred, non-blocking - Frontend: 264/264 Vitest, lint clean,
check-contract-drift.mjsDRIFT=0 (87 backend routes, 72 unique frontend calls), production build clean (19 routes) - Live-stack Playwright E2E (real backend + frontend + PostgreSQL, no mocks): 1/1 passed, zero axe violations, reached after a fix-and-rerun loop that found and fixed one real domain bug (
Lobby.CloseInternal/TryExpirenever released strandedLobbyMemberrows) and two real accessibility defects (LobbyPage.tsxmissing<h1>,ChatPanel.tsxlow-contrast placeholder text) - Local completion evidence recorded; hosted CI/portable-staging/deployment verification belongs to Module 14
Status:
- Backend, both security review phases, frontend, and live-stack verification are complete and independently
verified (see
docs/modules/module-07-realtime-presence-chat/). Module 7 is functionally, locally complete. Its formal ordered stage-checkpoint chain (index.json) carries only theplanningstage - the backend security-review stage ran on Sonnet 5 rather than the manifest-routed Opus, so later stages could not be chained in; the project owner explicitly waived backfilling that chain for this module. This is a process/tooling gap, not a functional gap: the security, frontend-security, and verification checkpoint files themselves exist, are internally valid, and record real, passing evidence.releaseEligiblestays false regardless of this waiver, pending Module 14's CI/container/staging foundation and a human-configured deployment provider. Match scope (chat and live updates) is deferred to Module 8 (NullMatchScopeAuthorizerreturnsRealtime.ScopeNotAvailabletoday); moderation evidence copy, the two-year retention domain, and a live suspension trigger are deferred to Module 12; the Redis/Azure SignalR backplane, distributed presence, sticky sessions, and multi-instance operation are deferred as a hard Phase 1 boundary, not a tuning knob. Two follow-ups remain owner-authorized and tracked, not silently resolved: the E2E spec's own lack of self-cleanup (P2, due before Module 14 CI), and a scoped, one-off, local-dev-only release of a real account's (mohannad) pre-existing orphaned lobby-membership row, authorized but not yet executed as of this evidence.
Product behavior is authoritative in
../docs/module-requirements/module-08-generic-match-room-state.md.
Purpose:
- Make
/room/[matchId]represent a real server-authoritative match.
Current UI target:
/room/[matchId]- Match timers, turn state, players, score, pause, forfeit, result modal
- Sudoku-style mock board currently used as a room placeholder
Included features:
- Match/session entity
- Match participants
- Get current match state
- One authoritative move-command service used by REST/realtime/AI adapters
- Turn validation
- Pause/resume
- Forfeit
- Disconnect/timeout handling
- Result recording
- Match history source for profile/dashboard later
Backend/database/API work:
- Persist sessions, participants, moves/events, and results
- Match controller or hub
- Server-side move validation through Module 5 engine contracts
Frontend work:
- Replace local board, turn, and timer state with server state
- Keep game-specific polish limited until actual Phase 2 games
Status:
- UI only, with backend session stubs.
Product behavior is authoritative in
../docs/module-requirements/module-09-solo-vs-ai-flow.md. Phase 1 validates the AI platform against the internal reference engine; catalog entry points remain capability-disabled until a production game supplies an AI strategy.
Purpose:
- Make Play vs AI, AI difficulty, and AI-filled seats work.
Current UI target:
- Dashboard Play vs AI
- Game detail Play vs AI and difficulty chips
- Lobby AI fill
- Match room
Vs AIstate
Included features:
- AI match creation
- Difficulty levels
- AI player identity
- AI move generation through game engines
- Solo result recording
- Solo stats later through Module 10
Backend/database/API work:
- AI player service and strategies
- Integrate AI actions with Module 8 match state
Frontend work:
- Wire AI mode buttons to real match creation
- Replace hard-coded AI opponent display
Status:
- Planned, with frontend entry points.
Product behavior is authoritative in
../docs/module-requirements/module-10-stats-achievements-leaderboards.md.
Purpose:
- Make dashboard/profile/game/leaderboard stats real.
Current UI target:
- Dashboard stat cards, recent matches, daily quests, recommended games
/profile/[userId]stats, ELO chart, match history, achievements, favorite games/leaderboards- Game detail Your Stats and Leaderboard tabs
- Match result modal ELO changes
Included features:
- Per-game stats
- Per-game Elo as the sole rating authority, with an explicit migration from legacy global
User.Elo - Match history
- Win rate, streaks, best season
- Achievement definitions
- User achievement unlock/progress
- Global-within-selected-game leaderboards
- Friends leaderboards
- Season/tier display
- Three server-generated daily quests from versioned definitions tied to real events
Backend/database/API work:
- Stats service
- Achievement service
- Leaderboard service
- Tables for player stats, achievements, user achievements, seasons, match results
- Result ingestion from Module 8
Frontend work:
- Replace mock stats, charts, leaderboards, achievements, and match history
- Keep reward visuals passive unless Module 13 provides premium/billing behavior
Status:
- UI only.
Product behavior is authoritative in
../docs/module-requirements/module-11-notifications-activity-feed.md.
Purpose:
- Make the topbar notification bell, unread counts, preferences, and activity surfaces functional.
Current UI target:
- Topbar notification bell/dropdown
- Dashboard invite waiting text and lobby invite card
/settings-> Notifications- Friends page friend activity sidecar
Included features:
- In-app notifications
- Unread count
- Mark all read
- Dismiss/read individual notification
- Notification triggers for friend requests, lobby invites, match results, achievements, and system/season messages
- Notification preferences
- Privacy-filtered friend activity feed from the brief's allow-listed real events
Backend/database/API work:
- Notifications controller, service, repository, DTOs
- Notification preferences persistence
- Event triggers from other modules
Frontend work:
- Replace
NOTIFICATIONSmock data - Wire settings notification toggles
Status:
- UI only, with backend domain stub.
Product behavior is authoritative in
../docs/module-requirements/module-12-moderation-admin-dashboard.md.
Purpose:
- Support basic safety and admin review without adding unrelated enterprise features.
Included features:
- Report user/content
- Suspend/ban users
- Review flagged chat/profile content
- Admin action audit log
- Bounded operational moderation metrics defined by the module brief
Backend/database/API work:
- Admin/moderation controller and service
- Reports, suspension records, admin audit log
- Strict role checks
Frontend work:
- Admin dashboard after backend role checks exist
Status:
- Planned, not visible in current UI.
Product behavior is authoritative in
../docs/module-requirements/module-13-premium-subscription-system.md.
Purpose:
- Support account tiers only after the core social gaming flow works.
Included features:
- Display account tier if present
- Subscription plans
- Payment-provider abstraction
- Stripe sandbox hosted Checkout and Customer Portal behind
IPaymentProvider - Webhook handling
- Subscription status enforcement
Backend/database/API work:
- Subscription records and provider IDs
- Webhook event log
- Signature verification for webhooks
Frontend work:
- Billing/settings UI only when backend billing is real
Status:
- Planned; the existing
Free|Plus|Proenum is legacy compatibility input. Module 13 introduces the authoritative Free/Premium Supporter entitlement model and a documented additive migration.
Product behavior and evidence levels are authoritative in
../docs/module-requirements/module-14-security-testing-production-readiness.md.
Purpose:
- Keep every implemented module reviewable and honest.
Included features:
- Full input validation for every module
- OpenAPI docs for implemented APIs
- CI/CD checks
- Health checks
- Vulnerability scans
- PostgreSQL migration verification
- Production configuration review
- Security audit updates per module
Backend/frontend/docs work:
- Keep module docs current with actual implementation
- Do not claim production readiness until deployment and database checks are real
Status:
- Partially implemented for auth; ongoing.
Purpose:
- Future embedded-device game support after the web platform is stable.
Included features:
- Device pairing
- Device identity and authentication
- Hardware event ingestion
- Hardware-backed game room
- Device status display
Backend/database/API work:
- Hardware devices table
- Pairing codes
- Device event ingestion endpoint
- Replay/rate-limit protection
Frontend work:
- Pairing and device status UI later
Status:
- Planned, not visible in current UI.
Product behavior is authoritative in
../docs/module-requirements/module-16-trust-legal-compliance-surfaces.md.
Purpose:
- Give every user a reachable Terms/Privacy/cookie-consent, accessibility statement, help/changelog, and self-service "download my data" export surface — added as the last Phase 1 module, since no other module owned this and Module 14 explicitly excludes new product UI.
Included features:
- Terms of Service / Privacy Policy / cookie-consent pages and versioned consent recording
- Public accessibility statement page
- Help/FAQ and changelog pages
- Consolidated self-service data-export request/download flow
- Settings links to cookie preferences and to Module 1's existing account deletion
Backend/database/API work:
-
UserConsentandDataExportRequesttables and endpoints - Export aggregation job across Modules 2/3/10/11/13's existing per-module export data
Frontend work:
- Public legal/help/changelog/accessibility routes with sitewide footer links
- Cookie-consent banner and Settings export/consent controls
Status:
- Planned, not visible in current UI. See
docs/ai-workflow/module-registry.mdfor the explicitly out-of-scope list (2FA/MFA, non-Google OAuth, tournaments, clans/guilds, referral program, guest play) closed out during the same gap-closure pass.
- Keep
docs/reviewer-notes.mdsynchronized after each completed module. - Add or update module docs and security audit notes from current evidence only; do not copy stale status from previous modules.
- Keep deployment caveats until production database, storage, CloudFront, CI/CD, and environment verification evidence exists.
After Phase 1 is complete, games are added as plugins:
- Five-Letter Duel
- Online Sudoku
- Four in a Row
- Falling Blocks Arena
- Chess Lite
- Checkers
- Memory Grid
- Snake Rush