From 1061dc074238f74c453f184a3c68f19f27b69e5c Mon Sep 17 00:00:00 2001 From: planner-bot Date: Tue, 18 Aug 2026 14:40:30 +0000 Subject: [PATCH] =?UTF-8?q?WIP=20checkpoint:=20Plan:=20Social=20=E2=80=94?= =?UTF-8?q?=20Friends,=20Chat=20&=20Groups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/planning/social.md | 170 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 docs/planning/social.md diff --git a/docs/planning/social.md b/docs/planning/social.md new file mode 100644 index 0000000..2474127 --- /dev/null +++ b/docs/planning/social.md @@ -0,0 +1,170 @@ +# Social — Friends, Chat & Groups — Plan + +> **Status:** Planned +> **Owner:** Platform team +> **Feature ID:** `social` +> **Godot version:** 4.6.2 stable +> **Backend:** FastAPI + SQLAlchemy (async) + PostgreSQL + Redis + +## 1. Overview + +This document breaks the **Social** feature into user stories and right-sized +implementation tasks. The feature delivers: + +- **Friends & following** — a friend request/accept model plus a one-way follow + relationship, with block lists. +- **Presence & status** — online/offline, custom status message, last-seen. +- **Chat** — direct messages (DM) and in-experience (world/room) chat with + **first-class safety**: server-side text filtering, report-message, and rate + limiting. +- **Groups** — named groups with roles (owner/admin/member) and a simple group + page. +- **Public profiles** — avatar, bio, favorite experiences, and a friends list + that respects privacy settings. + +## 2. Why chat safety is the differentiator + +The platform is explicitly meant to pull adults away from a youth-oriented +competitor. Chat is the highest-risk surface: it is real-time, user-generated, +and where abuse happens fastest. Safety is therefore treated as a **blocking +requirement**, not an add-on: + +- Every message passes a **server-side text filter** before it is stored or + delivered. The client filter is cosmetic only; the server is authoritative. +- Every message can be **reported**; reports flow into a moderation queue with + actor + reason + audit trail (mirroring `content_moderation.md`). +- Sending is **rate limited** per user (Redis token bucket) to stop flooding and + harassment-by-volume. +- Report and block are always reachable from a message context in the UI. + +## 3. Existing constraints (do not re-build) + +- **Auth:** JWT bearer tokens; `get_current_user` / `CurrentUser` dependency in + `app/dependencies.py`. All social endpoints reuse this. +- **DB:** async SQLAlchemy + Alembic; migration `0001_initial` is the head. +- **Redis:** configured (`REDIS_URL`) but unused so far; adopted here for + presence and rate limiting. +- **Models:** `User`, `World` (owner_id), `Asset` (owner_id, is_public). Avatars + and favorite-experience references point at existing rows. +- **Client:** Godot 4.6.2, minimal `main_menu.gd`; no social UI yet. + +## 4. Key design decisions + +| Concern | Decision | +|---|---| +| Message transport | REST for send/history; **WebSocket** gateway for real-time delivery + presence (matches `networking.md`'s "WebSocket as secondary transport" for chat) | +| Presence store | Redis (TTL heartbeat) + persisted `last_seen_at` on the user record | +| Text filtering | Pluggable `TextFilter` interface with a deterministic default (profanity list + normalization) so it runs without external services; third-party hook later | +| Rate limiting | Redis token-bucket dependency, reusable across all social endpoints | +| Reports | `message_reports` table + moderation endpoints (list/review/resolve) with audit fields | +| Friends vs. follow | Friends = mutual (request→accept). Follow = one-way (no approval). Block = hard deny that also hides content and prevents DMs | +| Privacy | Per-user settings JSON (`profile_visibility`, `friends_list_visibility`, `favorites_visibility`) enforced server-side on every read | +| Groups | `groups` + `group_members` (role: owner/admin/member) + group page aggregate endpoint | +| Real-time | One WebSocket endpoint multiplexing presence, DM, and world-chat messages via Redis pub/sub | + +## 5. User stories + +### US-1 Friends & following +As a player, I can send a friend request, accept/decline incoming requests, +unfriend, follow/unfollow other players, and block users so they can't interact +with me. + +**Acceptance criteria** +- Friend requests are one-directional until accepted; accepted friendships are mutual. +- Follow is one-way and requires no approval. +- Block prevents DMs, hides the blocked user's profile/friends interactions, and + removes any existing friendship/follow between the two. +- Duplicate/self requests are rejected idempotently. + +### US-2 Presence & status +As a player, I can see whether my friends are online, their custom status, and +when they were last seen. + +**Acceptance criteria** +- Online/offline is derived from a server-side heartbeat (Redis TTL), not client claims. +- `last_seen_at` persists and is visible (subject to privacy settings). +- Custom status text is optional and length-limited. + +### US-3 Public profiles +As a player, I can view a public profile page showing avatar, bio, favorite +experiences, and a friends list that respects the owner's privacy settings. + +**Acceptance criteria** +- Avatar and bio are editable by the owner only. +- Favorite experiences reference existing `World` rows. +- A viewer sees only the sections the owner's privacy settings allow; blocked + users see a restricted view. + +### US-4 Chat (DM + in-experience) with safety +As a player, I can send direct messages and chat inside a world/room. Messages +are filtered, rate limited, and reportable. + +**Acceptance criteria** +- Server filters message text before storing/delivering; filtered content is either + rejected (blocking) or redacted (configurable per filter policy). +- Send rate is limited per user (token bucket); excess sends get `429`. +- Every message has a stable id, author, timestamp, and conversation/world scope. +- Any message can be reported with a reason; reports are stored and reviewable. +- Real-time delivery over WebSocket with REST fallback for history. + +### US-5 Groups +As a player, I can create a group, join/leave groups, and (as owner/admin) +manage roles and view a simple group page. + +**Acceptance criteria** +- Each group has exactly one owner and any number of admins/members. +- Role transitions are authorized (only owner can transfer ownership or promote/demote admins). +- Group page lists name, description, member list with roles, and member count. + +### US-6 Godot client +As a player, I can access friends, presence, chat, profiles, and groups from the +game UI. + +**Acceptance criteria** +- An API client handles JWT auth, HTTP, and WebSocket for all social calls. +- Dedicated screens/panels: friends+presence, DM & world chat (with report), + profile page, group page. +- Client-side filtering is cosmetic; server responses remain authoritative. + +## 6. Task breakdown + +Right-sized to 1–3 files / one coherent piece of functionality each. Task IDs +are sequential for dependency chaining. + +| # | Task | Story | Depends on | +|---|------|-------|-----------| +| 1 | Friends/follow/block models + Alembic migration | US-1 | — | +| 2 | Friends & follow API router | US-1 | 1 | +| 3 | Presence & status model + endpoints (Redis heartbeat) | US-2 | — | +| 4 | Profile model + migration + own-profile endpoints | US-3 | 1 | +| 5 | Public profile view + favorites + privacy enforcement | US-3 | 2, 4 | +| 6 | Chat data models + migration (conversations, messages, reports) | US-4 | — | +| 7 | Text filtering service + profanity config | US-4 | — | +| 8 | Redis rate-limiting dependency | US-4 | — | +| 9 | DM chat send/list endpoints (filter + rate limit) | US-4 | 6, 7, 8 | +| 10 | Report-message endpoint + moderation queue | US-4 | 6, 9 | +| 11 | In-experience (world/room) chat endpoints | US-4 | 9 | +| 12 | Real-time WebSocket gateway (presence + DM + world chat) | US-4 | 3, 9, 11 | +| 13 | Group + membership models + migration | US-5 | — | +| 14 | Groups API (CRUD, join/leave, roles, group page) | US-5 | 13 | +| 15 | Godot API client (auth + HTTP + WebSocket) | US-6 | 2 | +| 16 | Godot friends & presence UI | US-6 | 3, 15 | +| 17 | Godot chat UI (DM + world chat + report) | US-6 | 12, 15 | +| 18 | Godot profile page UI | US-6 | 5, 15 | +| 19 | Godot groups UI + group page | US-6 | 14, 15 | + +## 7. Phasing + +- **Phase 1 (data + core APIs):** tasks 1–5 (friends, presence, profiles). +- **Phase 2 (chat safety — the differentiator):** tasks 6–12 (chat + safety + + realtime). This is the critical path and highest priority. +- **Phase 3 (groups):** tasks 13–14. +- **Phase 4 (client):** tasks 15–19, each landing after its backend dependency. + +## 8. Out of scope for this feature + +- Age verification / maturity gating (covered by `content_moderation.md`). +- Voice chat, media/image messages, message editing/deletion history. +- Third-party profanity/toxicity vendors (the `TextFilter` interface leaves a + hook, but the default is deterministic and dependency-free). +- Mobile push notifications.