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 ownckis itssubLabel; subscribing to a pool or a thread grants access to it directly. - Subbable-related —
member,postThreadMemberRef. TheirsubLabelis their parent'sck, 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 asubLabeland 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 asubLabel: per the base spec, it's their parent'sckwithContentappended, 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).