Docs Menu

Specs

domains/pools.md · shown exactly as it appears in the repository

Pools Domain Vocabulary

Status: Draft, v0.1 (versioned independently of the base protocol spec). License: CC-BY-4.0 — see ../LICENSE-DOCS.

Overview

This document is a domain vocabulary: a Layer 2 extension built on top of the base Bonafide protocol (../spec/), describing the actual content types, relationships, and commands the bonafide.pools domain declares, per the mechanism ../spec/05-content-model.md defines (registerContentValidator/registerNamespace) but deliberately leaves open for each domain to fill in. It does not modify or extend the base protocol itself — everything here is additional detail a domain built on Bonafide chooses to declare, the same way any other domain could declare its own, different vocabulary.

This document versions independently of the base spec (../spec/08-versioning-governance.md) — Pools' content model is expected to change on its own schedule, not the base protocol's.

Domain identifier

Pools' domain identifier is bonafide.pools, giving it the namespace pools per the derivation rule in ../spec/05-content-model.md — this is the namespace every content type below is registered and validated under.

Subbable taxonomy

Per ../spec/04-access-control.md's subLabel section, every content type a domain declares falls into one of four categories that determine how access control labels it. Pools declares:

  • Subbable — pool, postThread. A piece of content's own ck is its subLabel; subscribing to a pool or a thread grants access to it directly.
  • Subbable-related — member, postThreadMemberRef. Their subLabel is their parent's ck, derived by the function below — they travel under the same access grant as the thing they belong to.
  • Unshareable — none. Pools has no content type that's categorically excluded from every subscription.
  • Subscription-unrelated — alias, a base-protocol content type (not one of Pools' own eight — see Content types below). It's never assigned a subLabel and never shared under any subscription.
  • Everything else — post, postReaction, message, messageReaction. These don't fall into any of the four named categories above but still need a subLabel: per the base spec, it's their parent's ck with Content appended, using the same parent-derivation function as the subbable-related case.

Deriving the parent

Wherever a subLabel needs a parent's ck — the subbable-related case and the "everything else" case above — Pools derives it as:

content.postThreadCK ?? content.poolCK ?? null

A postThread-scoped item's parent is the thread; otherwise it's the pool.

Content types

Every type below also carries the base content envelope (../spec/05-content-model.md's "The content envelope" section) — those fields aren't repeated per type. What follows is what the pools namespace adds on top, per type: its required and optional fields, and any fields it declares local-only (stripped before sharing, per the base spec's "Shareable vs. local descriptors" rule).

pool

A top-level container members belong to and post content into. Subbable (see Subbable taxonomy above) — its own ck is its subLabel.

Field Required? Purpose
poolName required Display name.
filename required Cover image filename.
hasDarkCover required Whether the cover image is dark-toned, for overlay/text styling.
memberCount required Current member count. Owner-authoritative — only the owning party updates it; non-owners receive corrected values via the owner's update broadcast.
contributorList required cks of the members currently granted contributor status — an explicit grant, distinct from plain membership, that gates permission to create a post in this pool. Same owner-authoritative rule as memberCount.
subLabel required Per the Subbable taxonomy above: the pool's own ck.
poolDescription optional Free-text description.

Local-only (never shared): isSubscribed, fileSize, sortDate, unreadCount.

post

Content created by a pool member — the pool's primary shared content. Falls in the base spec's "everything else" subLabel bucket (see Subbable taxonomy above): its subLabel is ${poolCK}Content.

Field Required? Purpose
poolCK required Parent pointer — the pool this post belongs to.
memberCK required The authoring member's ck.
subLabel required Per the Subbable taxonomy above: ${poolCK}Content.
reliesOnCxnId required Content-reliance, set to the pool's receivedFromCxnId — so a post cascade-deletes if the connection the pool itself depends on is removed.
urlTitle optional Link-preview title, client-supplied, for a post's url.
urlDescription optional Link-preview description, client-supplied.
urlImage optional Link-preview image, client-supplied.

At least one of postTitle, postDescription, filenames, or url is required — a post must carry some actual content.

Local-only: fileSize, postThreadCount (number of postThreads under this post).

A post's originDOS/remainingDOS default to 1 (the base-protocol default) when authored by the pool's owner, but are explicitly set to 2 when authored by any other member — a Pools-specific propagation policy, not a base-protocol rule.

postReaction

A member's reaction to a post. Falls in the base spec's "everything else" subLabel bucket (see Subbable taxonomy above): its subLabel is ${poolCK}Content, where poolCK is denormalized from the reacted-to post purely as a query-optimization label, not a schema-required field (see the base schema's labels concept, distinct from the subLabel category of the same name).

Field Required? Purpose
reactionType required The kind of reaction (e.g. a like).
memberCK required The reacting member's ck.
postCK required Parent pointer — the post being reacted to.
subLabel required Per the Subbable taxonomy above: ${poolCK}Content.
reliesOnMemberCK required Content-reliance on the post's authoring member — so a reaction cascade-deletes if that member record is removed.
reliesOnCxnId required Content-reliance, denormalized from the reacted-to post's own reliesOnCxnId.

No optional fields, and nothing declared local-only.

Same non-owner propagation bump as post: originDOS/remainingDOS default to 1, but are set to 2 when the reacting member isn't the pool's owner.

member

A party's own representation within a pool — one member record per pool per connection. Subbable-related (see Subbable taxonomy above): its subLabel is the parent pool's ck.

Field Required? Purpose
memberName required Display name within the pool.
aliasCode required The connection alias (cxnAliasCode) this membership resolves back to — links the member record to the underlying connection.
memberRole required owner (the pool's creator) or subscriber (anyone who joins).
poolCK required Parent pointer — the pool this membership belongs to.
subLabel required Per the Subbable taxonomy above: the parent pool's ck.
reliesOnCxnId required Content-reliance — a member record cascade-deletes if its connection is removed.
filename optional Profile image filename.

Local-only: fileSize (profile image file size).

Same propagation split as post/postReaction: a subscriber's originDOS/remainingDOS are set to 2; an owner's default to 1.

postThread

A reply/discussion thread attached to a post. Subbable (see Subbable taxonomy above) — its own ck is its subLabel.

Field Required? Purpose
postThreadName required Computed from the thread's connected members (calculateThreadName), not client-supplied free text.
postCK required Parent pointer — the post this thread is attached to.
subLabel required Per the Subbable taxonomy above: the thread's own ck.
reliesOnMemberCK required Content-reliance, denormalized from the parent post's authoring member.
reliesOnCxnId required Content-reliance, denormalized from the parent pool's receivedFromCxnId.
reliesOnSecondaryCxnId required Content-reliance, denormalized from the parent post's own receivedFromCxnId — a separate slot because the pool and the post can have different origin connections.

No optional fields. poolCK and the creating member's own memberCK are also present on the document, denormalized as query-optimization labels (not schema-required), same as postReaction's poolCK.

Local-only: isSubscribed, unreadCount, contentPreview (a preview snippet of the thread's most recent message, initialized to "No messages yet..."), sortDate.

postThreadMemberRef

A party's own representation within a postThread — the thread-scoped counterpart to member, one per thread per connection. Subbable-related (see Subbable taxonomy above): its subLabel is the parent thread's ck.

Field Required? Purpose
aliasCode required The connection alias (cxnAliasCode) this ref resolves back to — same role as on member.
memberRole required owner (the thread's creator) or subscriber (anyone added to it).
memberCK required The pool member this ref represents within the thread.
postThreadCK required Parent pointer — the thread this ref belongs to.
subLabel required Per the Subbable taxonomy above: the parent thread's ck.
reliesOnMemberCK required Content-reliance, denormalized from the thread's own reliesOnMemberCK (ultimately the parent post's authoring member).
reliesOnSecondaryMemberCK required Content-reliance, denormalized from the thread's own creating member (postThread.memberCK).
reliesOnCxnId required Content-reliance, denormalized from the thread's own reliesOnCxnId (the parent pool's origin connection).
reliesOnSecondaryCxnId required Content-reliance, denormalized from the thread's own receivedFromCxnId — 'me' if this party created the thread locally, otherwise the connection it arrived from.

No optional fields. postCK and poolCK are also present, denormalized as query-optimization labels (not schema-required), same pattern as postThread's.

Nothing declared local-only.

Same propagation split as the other types: a subscriber's originDOS/remainingDOS are set to 2; an owner's default to 1.

message

A message sent within a postThread. Falls in the base spec's "everything else" subLabel bucket (see Subbable taxonomy above): its subLabel is ${postThreadCK}Content.

Field Required? Purpose
postThreadMemberRefCK required The sending party's own postThreadMemberRef — identifies who sent the message.
postThreadCK required Parent pointer — the thread this message belongs to.
subLabel required Per the Subbable taxonomy above: ${postThreadCK}Content.
reliesOnMemberCK required Content-reliance, denormalized from the parent thread's own reliesOnMemberCK (ultimately the post's authoring member).
reliesOnSecondaryMemberCK required Content-reliance, denormalized from the parent thread's own creating member (postThread.memberCK).
reliesOnCxnId required Content-reliance, denormalized from the parent thread's own reliesOnCxnId (the pool's origin connection).
reliesOnSecondaryCxnId required Content-reliance, denormalized from the parent thread's own reliesOnSecondaryCxnId (the post's origin connection) — not the thread's receivedFromCxnId this time, unlike postThreadMemberRef's equivalent slot.

At least one of messageText or filenames is required.

No optional fields. poolCK, postCK, and memberCK are also present, denormalized as query-optimization labels (not schema-required), same pattern as the other thread-scoped types.

Local-only: fileSize.

Same propagation split as the other types: a non-owner sender's originDOS/remainingDOS are set to 2; an owner's default to 1. Sending a message also updates the parent thread's local-only contentPreview, unreadCount, and sortDate fields.

messageReaction

A member's reaction to a message. Falls in the base spec's "everything else" subLabel bucket (see Subbable taxonomy above): its subLabel is ${postThreadCK}Content.

Field Required? Purpose
reactionType required The kind of reaction.
postThreadMemberRefCK required The reacting party's own postThreadMemberRef — who reacted.
messageCK required Parent pointer — the message being reacted to.
subLabel required Per the Subbable taxonomy above: ${postThreadCK}Content.
reliesOnPostThreadMemberRefCK required Content-reliance on the reacted-to message's own sender ref — a reaction cascade-deletes if that ref is removed.
reliesOnMemberCK required Content-reliance, denormalized from the message's own reliesOnMemberCK (ultimately the post's authoring member).
reliesOnSecondaryMemberCK required Content-reliance, denormalized from the message's own reliesOnSecondaryMemberCK (the thread's creating member).
reliesOnThirdMemberCK required Content-reliance, denormalized from the message's own memberCK — the message's author's underlying pool member (distinct from this reaction's own reacting member, below).
reliesOnCxnId required Content-reliance, denormalized from the message's own reliesOnCxnId.
reliesOnSecondaryCxnId required Content-reliance, denormalized from the message's own reliesOnSecondaryCxnId.

No optional fields. postThreadCK, postCK, poolCK, and memberCK (the reacting member, not the message's author) are also present, denormalized as query-optimization labels (not schema-required).

Nothing declared local-only.

Same propagation split as the other types: a non-owner reactor's originDOS/remainingDOS are set to 2; an owner's default to 1. Creating a reaction also updates the parent thread's local-only contentPreview and sortDate (not unreadCount this time).