Collaborative community

What does the full collaborative social community platform require, what exists, and what is still missing? This document is the requirements-and-evidence record for that active ob

What does the full collaborative social community platform require, what exists, and what is still missing? This document is the requirements-and-evidence record for that active objective. It extends the earlier MVP scope. Passing the HTTP contracts does not complete the objective; editor synchronization, cursor overlays, conflict recovery and complete community journeys are still required. No hosted promotion or real social email campaign has been performed for this work.

Status: active work. Persistent social, notification, membership, presence and edit APIs pass SQLite and PostgreSQL fixtures; profile, discussion and collection UI is being qualified. See the table below and implementation status.

Entities#

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#FAFAF7', 'primaryTextColor': '#1C1C1B', 'primaryBorderColor': '#1C1C1B', 'lineColor': '#64645F', 'fontFamily': 'DM Sans, Inter, system-ui, sans-serif'}}}%%
flowchart LR
  ACCOUNT["Account<br/>profile · picture · links · achievements"]
  PROJECT["Project (draft)<br/>members · roles · edits · sessions"]
  RELEASE[("Release / catalog entry<br/>immutable, public or not")]
  COLLECTION["Collection<br/>private · unlisted · public"]
  THREAD["Discussion thread<br/>anchored · public or team-only"]
  INBOX["Notifications<br/>center · preferences · deliveries"]

  ACCOUNT -->|follows| ACCOUNT
  ACCOUNT -->|likes · bookmarks| RELEASE
  ACCOUNT -->|owns| COLLECTION --> RELEASE
  ACCOUNT -->|invited viewer / commenter / editor| PROJECT
  PROJECT -->|publishes| RELEASE
  THREAD -.anchored to.-> RELEASE
  THREAD -.anchored to.-> PROJECT
  ACCOUNT -->|receives| INBOX
  ACCOUNT -.blocks · reports.-> ACCOUNT

  classDef source fill:#F0442E,stroke:#1C1C1B,color:#FAFAF7
  classDef shared fill:#DCEBDD,stroke:#1C1C1B,color:#1C1C1B
  classDef host fill:#DED8F0,stroke:#1C1C1B,color:#1C1C1B
  class RELEASE source
  class ACCOUNT,PROJECT,COLLECTION,THREAD shared
  class INBOX host

Mutable social data never enters a portable Toy or an immutable release package.

Requirements and evidence#

RequirementImplementedRemaining work and qualification
ProfilesPublic pages for all accounts, display name, bio, eight HTTPS links, normalized picture upload/removal, public work, real earned achievementsConsistent account/header avatars; real multi-account profile/avatar browser journey passed
Collections and liked workPrivate/unlisted/public named collections, explicit ordered membership, public collection pages, optional public Likes tab; bookmarks remain privateFull collection pagination/reordering UI and browser journeys
EngagementFollows/unfollows, likes/unlikes, following feed, and posts: product reviews, threaded comments and replies with mentions, likes, helpful votes, pins, publisher responses, edit history, removal/resolution and durable anchorsCompeting UI writes and full moderation/block/report browser journeys; review → response → reply → like → pin browser journey
Shared draftsViewer/commenter/editor invitations, acceptance, roles/removal, shared project listing and enforced accessWorkspace invitation/membership controls and live draft entry
Concurrent editingValidated historical authoring batches, independent-field merging, atomic revisions, conflict rejection and author-specific UndoConnect editor pending edits, conflict review, reconnect, Redo and two-browser journeys
Cursors and sessionsAccount-bound tab identities, bounded cursor/selections, expiry and authorized readsWorkspace cursor/selection overlays and cleanup/reconnect journeys
Collaborative notesPublic versus team-only anchored threads with read/comment permissionsEditor selection/reveal and team discussion UI
NotificationsUnified notification center with read/dismiss state, an event × channel preference matrix with locked required events, deduplication, collapsing and deep linksBell with unread count and ETag polling; filters, grouped rows, optimistic actions; see notifications and localization
Email and push channelsLeased delivery for every channel, verified recipients, preference/visibility checks at delivery, bounded retries, digests, SES/Resend, web push, bounce suppression and scoped one-click unsubscribeInjected-transport tests; operator delivery/bounce monitoring and hosted qualification remain. Native push is planned only
Community controlsBlocking (read-time post filter), reports with kind: post, configured moderator report queue, post removal, restore and verified-badge clearingModerator queue view and complete blocking/reporting browser journeys

Identity and access#

SQLite migration 9 and PostgreSQL migration 10 add community, membership, session and edit records. Server-owned projects.parent_release records actual fork provenance separately from editable source for the remixer achievement. Achievements derive from real public work and contributions; no accounts or awards are invented.

Rule
Bookmarks stay separate from explicit public likes
Private collections and liked work are not exposed unless the owner chooses
Public collections show visitors only public Toys; later visibility changes withdraw them
Blocks prevent interaction; they cannot make anonymously readable public URLs secret
Invitations reveal inviter, project identity and role before acceptance, never draft source
Every draft, team, session and edit operation checks accepted membership
Only owners manage other members; members may leave; publishing and visibility remain owner actions
Revocation and blocking deny subsequent reads, edits, notes and presence, including old edit retries

Shared editing#

The API accepts a durable request key, an existing base project version and a shared authoring batch. It applies the batch to that admitted historical source, merges independent fields against the latest source, validates the complete result and commits through the existing applyBatch project writer. Scalar and array collisions reject with COLLABORATION_CONFLICT; invalid graph dependencies reject atomically. Toy identity stays stable. The authenticated account supplies the audit actor.

Undo reverses only the author's recorded change against the latest source, preserving unrelated peer work. A conflicting reversal rejects; an edit cannot be undone twice; Undo itself is recorded. Edit audit rows reference existing revision snapshots instead of duplicating whole source documents.

Presence limitValue
Expiring sessions per account8
Invited members per project32
Selected identities per message100, with view/scope and bounded coordinates
Unchanged-state pollsOmit source
Rate bucketsPresence and edits are separate

Presence stays outside Toys and audio callbacks.

Posts: reviews, comments and replies#

One posts table (SQLite migration 11, PostgreSQL 12) carries reviews, comments and replies, replacing the foundation comment table in place. services/api/src/posts.ts owns the rules; posts-store.ts owns storage and database triggers keep thread shape, depth, identity and the three-pin limit.

KindSubjectsRules
reviewproductRating 1–5, optional 120-character title and 8 KiB Markdown; one per account and product (a second save edits it); not by publisher members or the project owner; verified email or one day of account age required
commentproduct, project, version, storefront, docs_page1 byte to 8 KiB Markdown; anchors and team-only notes stay on project subjects with the rules below
replyInherited from the rootDepth ≤ 4; a reply to a depth-4 post continues on its parent with a quoted @handle. A publisher response is the one flagged reply per review
RuleBehavior
Verified ownerFrozen at creation from an active product:<id> billing grant only; free claims and plays do not verify; refunds never rewrite it; moderators can clear it
Reviewed versionChosen by the author or suggested from the latest installation, else the selected library release; an edit after a newer version is published shows "Updated after version X" with the prior rating
Rating summaryrating_summary is recomputed in the transaction of every review write, removal, restore or moderation and exposed on listings as ratingSummary; library items no longer carry ratings
Edits and historyEvery content edit stores the previous body, rating and title in the immutable post_revisions, readable by the author and moderators
RemovalAuthor removal clears the text; subject owners (project owner, editing publisher member) remove comments and replies but not reviews; moderators remove anything. Tombstones remain while visible replies need them
BlocksRead-time filter in both directions; replies, reactions, mentions and notifications between blocked accounts are refused or dropped
PinsUp to three roots per subject by the subject manager or a moderator, rendered first
Notificationsreply, mention, publisher_response, review_on_your_product, comment_on_your_work and pinned commit with the post; deliveries are planned by the notification service

The web PostFeed renders Reviews (rating summary histogram filters, ReviewComposer, helpful sort) and Discussion tabs, threads with collapse below depth 2, reactions, pins, publisher responses, edit/remove/report and moderator actions. It replaces the Toy page discussion and editor team notes, and renders directly on the public React profile, collection and product pages inside the shared shell.

Notifications and operation#

Community events (follow, like, comment, reply, mention, invitation, collaboration edit) are written by notify() in the same transaction as the event. It drops self-notifications and blocked actors, deduplicates per account and collapses unread repeats with the same group key (for example likes on one Toy) into one row with a count. One NotificationRunner delivers every channel: it acquires a database lease, re-checks the verified address, current preferences, blocks and resource access, then calls the provider outside transactions. Retries keep provider identity; two runners cannot claim the same live lease. SES delivery is at-least-once across a crash after acceptance; exactly-once email is not claimed. Six attempts bound retries and rows retain delivery and failure evidence.

Email and push link to the authenticated app rather than embedding private source or comment text, and push bodies never name people or projects. Unsubscribe tokens are random, stored hashed, scoped to one category or all optional email, and can never disable required account, security or purchase notices. The unsubscribe page never mutates on GET; RFC 8058 one-click uses POST. The design and routes are in notifications and localization.

TUNETOYS_MODERATOR_ACCOUNT_IDS explicitly configures durable account IDs for report review. No administrator credential is seeded. PostgreSQL runtime privileges include the new tables. Offline import includes durable social data and orders threaded posts by insertion to preserve parent foreign keys. Cursor sessions are transient.

Verification#

CheckCovers
services/api/test/community.test.mjsReal HTTP/SDK profiles, interactions, project discussion and team notes through posts, reports, visibility, roles, concurrent edits, author Undo, revocation and immutable packages
services/api/test/posts.test.mjsReview eligibility and uniqueness, verified-owner freeze, legacy reviews, summaries, helpful/rating sorts, publisher responses, edit history, depth, pins, blocks, moderation and notifications
services/api/test/community-mail.test.mjs, notifications.test.mjsInjected delivery: leases, retries, digests, suppression, web push encryption, preferences, center routes and scoped unsubscribe without sending real mail or push
Both on SQLite and disposable PostgreSQLThe first database checkpoint passed 58 PostgreSQL tests and the complete root npm run check
npm run test:community-ui -w @tunetoys/web (after a browser build)Profile/avatar editing, follows, likes/replies, private-to-public collections, notifications/read state and anonymous 390px discovery, without page errors or horizontal overflow

The goal additionally requires every remaining workspace, cursor, conflict, reconnect and moderation item in the requirements table to be implemented and verified before completion.

Implementation#

  • services/api — community.ts, community-routes.ts, community-access.ts, community-pages.ts, notifications.ts, notification-runner.ts, posts.ts, posts-routes.ts, posts-store.ts
  • services/api/migrations — community and collaboration migrations
  • packages/authoring — collaboration.ts merge and author Undo
  • apps/web — CommunityApp.tsx, CollaborationPanel.tsx, PostFeed.tsx, ReviewComposer.tsx, RatingSummary.tsx, CreatorProfilePage.tsx, CollectionPage.tsx

Edit this page on GitHub

esc

↑ ↓ move↩ open⌘↩ new tabesc close