Communities
A community (what other chat apps might call a “server”) is where people gather into categories and channels to talk. In a conventional app the backend owns all of that data. Colibri works differently: a community is itself an AT Protocol identity.
A community is a set of gated spaces whose authority is the community’s DID. Each member’s messages live in that member’s own repository, and a reader reaches them through the space that holds them.
Six spaces
Section titled “Six spaces”All six have the community’s DID as their authority.
| Space type | Key | Holds | Who can read |
|---|---|---|---|
social.colibri.beta.community.profile |
self |
the community record | anyone, unless the community is private |
social.colibri.beta.community.configuration |
self |
settings, categories, labels | members |
social.colibri.beta.community.members |
self |
members, roles, labels | members |
social.colibri.beta.community.moderation |
self |
the moderation log | holders of moderation.viewLog |
social.colibri.beta.channel.text |
tid |
channel, messages, reactions, labels | per channel |
social.colibri.beta.channel.voice |
tid |
the channel record | per channel |
The first four are created once, when the community is created. The last two are space types, and a community has one space of that type per channel.
A channel is its space
Section titled “A channel is its space”There is no channel container that holds messages. The space is the channel.
Its key is the channel’s identity, and the channel’s own configuration lives at
record key self inside it.
Creating a channel creates a space, and deleting one deletes the space. Adding a new kind of channel later means adding a new space type.
The personal space
Section titled “The personal space”Each user also has one space of their own, social.colibri.beta.actor.preferences,
whose authority is the user’s own DID. It holds their mutes, their settings and
their read cursors, none of which anyone else has any business reading.
Its policy is an empty member list. The space manager authorizes the owner before it consults the policy, so the owner always gets in and no one else ever does.
Where records live
Section titled “Where records live”Which repository a record is written to tells you who is accountable for it.
Written by the community
Section titled “Written by the community”The AppView holds the community’s credentials and writes these on its behalf. They are the community’s structure and its authoritative state.
| Record | What it is |
|---|---|
social.colibri.beta.community |
The community definition, at key self in the profile space. |
social.colibri.beta.community.settings |
Category order, join approval, link embeds, and the labelers this community honours. |
social.colibri.beta.category |
A category, holding an ordered list of channel keys. |
social.colibri.beta.role |
A role and its permissions. |
social.colibri.beta.member |
A member: their DID, their roles and when they joined. Keyed by the subject’s DID. |
social.colibri.beta.channel |
A channel’s configuration, at key self in the channel’s own space. |
social.colibri.beta.moderation |
The append-only log of bans, unbans and kicks. |
social.colibri.beta.member is keyed by the subject’s DID, so looking someone up
is a direct fetch rather than a scan, and a community cannot hold two member
records for the same person.
Written by each member
Section titled “Written by each member”Written by the user, to the user’s own repository, and read through the space.
| Record | What it is |
|---|---|
social.colibri.beta.message |
A message. Its space is the channel it was sent in. |
social.colibri.beta.reaction |
A reaction, targeting a message by author and key. |
social.colibri.beta.label |
A label on some content, if the user is one of the community’s labelers. |
social.colibri.beta.actor.profile |
The user’s Colibri profile. This one is still public. |
social.colibri.beta.actor.mute |
One muted subject, in the user’s own preferences space. |
social.colibri.beta.actor.settings |
Notification level, community order, GIF favourites. |
social.colibri.beta.channel.read |
Read cursors, one record per community. |
Your messages are stored in your own repository. You own them, they travel with your atproto identity, and deleting one is an ordinary record deletion. They are not public: a reader needs a credential for the channel’s space to see them at all.
Joining
Section titled “Joining”Joining is the social.colibri.beta.community.join
procedure. The AppView checks the invitation or the community’s join policy, and
either writes the member record or records a pending application. Nothing is
reconciled between two repositories, and there is no state where you are half
joined.
The consequence of joining is that the AppView will start answering “yes” when the community’s PDS asks whether you may read that community’s spaces.
What creating a community does
Section titled “What creating a community does”- Creates an account on the configured PDS and stores its password, encrypted.
- Creates the profile, configuration, members and moderation spaces.
- Writes the community record, an Owner role holding every permission, and a member record for the creator.
- Seeds a usable layout: a
generaltext channel and aGeneralvoice channel, each in its own space, grouped into a “Text channels” and a “Voice channels” category.
Channel spaces are created before the record that describes them, so a failure part way through leaves an empty space rather than a record pointing at nothing.
See also
Section titled “See also”- Permissioned Spaces: what a space is and how access is granted.
- Moderation: what a community can do about a message it dislikes.
- AppView Architecture: the service that writes these records and serves them back.