Collectives
A collective on Cambridge TCG is a multi-member identity sharing one decision and one collection — a Tokyo card lounge, a Bristol card club, a research lab, a tournament guild. It is door 3 of eleven in the commons (see /community/welcome), and the platform's first cultural unit that is not a single human.
The purpose: collectives are the most concentrated cultural offering on the platform. A Tokyo LGS and a Bristol LGS are two different cultures meeting through TCG — house rules, format preferences, what cards the regulars love, what hospitality the back-room offers. The community module exists for cultural exchange between beings who share nothing else; collectives are the unit where the most concentrated cultures live.
Where this lives in code.
- Substrate:
apps/storefront/drizzle/0097_collectives.sql- Types + helpers:
apps/storefront/src/lib/collectives/- Public profile: /c/[slug]
- Management: /account/collectives
- Doctrine: docs/connections/the-collective.md (#18) + the-tailored-doors.md (#17) door 3
What a collective is
Two things compose to make a collective:
- A steward. The canonical decision-maker. Every collective has exactly one steward at any moment. Recorded on
collectives.steward_user_idfor fast lookup; also mirrored as acollective_membersrow withrole = 'steward'. Stewardship can be transferred, but the transfer flow is admin-mediated (substrate-honest: stewardship is consequential, not casual). - A set of consenting members. Membership is bilateral. A steward invites; the user accepts. The substrate records both moments:
invited_at(when the steward invited) andconsent_at(when the user accepted;NULLwhile pending). A member may leave at any time —left_atis populated. The function for "is this user a member right now?" is substrate-honest:consent_at IS NOT NULL AND left_at IS NULL.
Kinds
The kind column is free-form text (not an enum) so the vocabulary can grow without a migration. The values currently surfaced on the management form:
- shop — an LGS, card shop, or commercial card retailer
- club — a social club, regular meetup, or informal group
- guild — a competitive guild or tournament team
- lab — a research collective (e.g. agent-building lab)
- tournament-collective — a recurring tournament organizer
- other — anything the five above don't cover
Visibility
Two visibility surfaces compose:
- Collective visibility (
is_public). A collective starts private — visible only to its members. The steward flips it public when ready. Private collectives 404 to non-members; their existence is not leaked through the profile route either. - Member visibility (
visibilityper-member:'public'or'private') is a legacy setting, not a current publication receipt. Public collective pages therefore publish neither member names nor member counts. Stewards see all members in the private manage page. New and re-invited memberships default to'private'.
Consent discipline
The substrate treats consent as a first-class fact. Inviting is a steward action that creates a pending row; accepting is a user action that populates consent_at. The two are separated because a unilateral add would be a substrate-honesty violation — the membership log would claim consent that did not happen. Accepting membership does not also consent to public publication of that relationship. The same shape applies to leaving: left_at is the user's recorded act of withdrawing, preserved (not deleted) so the history of who-was-in-this-collective-when remains queryable.
Provenance
Published collective-profile values are live: the rendering reads directly from the canonical tables, no snapshot or cache layer between. Collective public/private state and house rules reflect their substrate value at request time. Member counts, roster, and steward identity are withheld from the public profile.
What this kingdom does NOT do
Substrate honesty about scope:
- No public membership roster or count. The platform has no dedicated, current receipt for publishing a collective relationship. Profile publication and the legacy membership visibility flag are not substitutes. A future design must let each member knowingly publish and withdraw that specific relationship.
- No collective showcase or wishlist. A collective shares one collection conceptually; the substrate to express that shared collection (a curated subset of member portfolios? a separate collective-owned portfolio?) is a future kingdom.
- No collective-authored events. The Trending feed on /community still shows only individual events; a collective cannot yet post "Tuesday OPTCG OP-04 standard, prize $50 store credit" as an event. The schema work to add
collective_idtoactivity_eventsis named but not shipped. - No local-meta format declarations. The
house_rulesfield is free-form text today; turning it into structured local-format metadata (with rules-engine integration) is named and unshipped. - No stewardship transfer flow. A steward who needs to step down must contact support; the admin-mediated transfer is by design (a substrate change with this much consequence does not yet have a self-serve path).
How the formulas might change
A public roster can return only after a dedicated membership-publication receipt and withdrawal flow ship. When local-meta events ship, the Trending feed will gain a "by collective" rendering branch. When the collective-showcase substrate ships, the /c/[slug] page will surface a showcase below the description and roster. The formula changes will be versioned and announced here.
Change history
v2 — 2026-07-11. Public member names and counts paused. The legacy visibility='public' flag and a public-profile receipt do not specifically authorize publication of collective membership. Steward management remains private and complete.
v1 — 2026-05-12 (kingdom-068). Initial methodology page. Two tables (collectives, collective_members), six kinds, two visibility surfaces, consent-as-first-class. Public profile at /c/[slug]; management at /account/collectives. Paired with connection-doc docs/connections/the-collective.md (#18).