-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/org channels #151
base: master
Are you sure you want to change the base?
Feature/org channels #151
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
--- | ||
permalink: /spec/17 | ||
parent: Stable specs | ||
title: 17/ORGANISATION-CHANNELS | ||
--- | ||
|
||
# 17/ORGANISATION-CHANNELS | ||
|
||
> Version: 0.1 | ||
> | ||
> Status: Raw | ||
> | ||
> Authors: Andrea Maria Piana <andreap@status.im> | ||
> | ||
|
||
- [Organisation channels](#17organisation-channels) | ||
- [Reason](#reason) | ||
- [Fetching information about an organisation](#fetching-information-about-an-organisation) | ||
- [Joining an organisation](#joining-an-organisation) | ||
- [Updating channels](#updating-channels) | ||
|
||
## Reason | ||
|
||
Organisation channels are a way to allow users to build communities and create curated content. | ||
|
||
## Fetching information about an organisation | ||
|
||
An organisation is uniquely identified by a public key. | ||
|
||
This public key can be discovered through different means, links, indexable web pages or search directories for example. | ||
|
||
Given that the public key of the organisation is known, information about the channels and members can be fetched by listening to a discovery topic derived by the public key: | ||
|
||
``` | ||
Does not matter which topic for now, as long as it does not clash with public chats. | ||
``` | ||
|
||
The organisation SHOULD publish periodically an `OrganisationDescription` message, | ||
at least once every 24 hours, ideally more to minimise the dependency on mailservers. | ||
|
||
|
||
```protobuf | ||
message ChatMessageIdentity { | ||
// stubbing this, it's already been prepared in a different PR | ||
string ens_name = 1; | ||
string profile_picture = 2; // not a string, more complex data structure, but you get the point | ||
string display_name = 3; | ||
string description = 4; // this is actually unique to an organisation, and chatMessageIdentity might want to be updated, or similar | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how extensive this needs to be; I imagine it can't be updated for channels that have already been created later. Other information we might want for a sorted and categorized view of chats would be:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can add new fields as we implement new functionalities, this is always a non-breaking change (we can't remove fields). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me think on when we would want to add these. If the data is available, Desktop client likely starts handling them as soon as possible as they're looking for a more visual and rich way to explore community chats and other (more visual real estate, lower discovery risks wrt store policies) |
||
|
||
} | ||
message OrganisationPermissions { | ||
enum Access { | ||
UNKNOWN_ACCESS = 0; | ||
NO_MEMBERSHIP = 1; | ||
INVITATION_ONLY = 2; | ||
ON_REQUEST = 3; | ||
} | ||
|
||
bool ens_only = 1; | ||
bool can_request_access = 2; | ||
// https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md is a candidate for the algorithm to be used in case we want to have private organisational chats, lighter than pairwise encryption using the DR, less secure, but more efficient for large number of participants | ||
bool private = 3; | ||
Access access = 4; | ||
} | ||
|
||
message OrganisationDescription { | ||
uint64 clock = 1; | ||
repeated bytes members = 2; | ||
OrganisationPermissions permissions = 3; | ||
ChatMessageIdentity identity = 5; | ||
repeated OrganisationChat chats = 6; | ||
} | ||
|
||
message OrganisationChat { | ||
string chat_id = 1; | ||
uint64 clock = 2; | ||
repeated bytes members = 3; | ||
OrganisationPermissions permissions = 4; | ||
string name = 5; | ||
} | ||
``` | ||
|
||
Where: | ||
|
||
`clock` is a logical clock, described [here](link to clock value) | ||
`members` is a list of compressed public keys that represent the members of the organisation | ||
`identity` is a `ChatMessageIdentity` with a list of details about the organisation identity | ||
`permissions` is a list of permissions set by the creator of the organisation | ||
`chats` is a list of chats/(channels?) associated with the organisation | ||
|
||
|
||
### Permissions | ||
|
||
Permissions can be set at the organisation level or at the chat level. | ||
|
||
Permissions at the chat level cannot override permissions at the organisation level. | ||
(Here I will describe rules, but most of them should be simple, i.e you can't set a | ||
channel public in an private organisation, you can have a member of a chat who is not | ||
cammellos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
a member of an organisation) | ||
|
||
`ens_only` means that only user who have an `ENS` can join the organisation | ||
`private` indicates whether the organisation channels are encrypted with a secret | ||
key shared only by members, otherwise the key is derivable by the chat_id | ||
`access` indicates how membership works for this organisation. | ||
When is `NO_MEMBERSHIP` anyone can read and write on the channels, `private` MUST be set to false in this case. | ||
When is `INVITE_ONLY` users MUST NOT request access, if `private` is set to `false` the channel | ||
will be read-only. Only upon receiving an `OrganisationInvitation` a user will be able to join. | ||
When is `ON_REQUEST` users MUST send a `OrganisationRequestJoin` to join the organisation. | ||
|
||
|
||
## Joining an organisation | ||
|
||
If an organisation access is set to `ON_REQUEST` a user MUST send a | ||
message `OrganisationRequestJoin` if they want to join the organisation. | ||
A `chat_id` MAY also be specified if they are interested in joining a particular channel | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the association of |
||
of the organisation that has access also set to `ON_REQUEST`. | ||
|
||
An organisation MUST send back a `OrganisationRequestJoinResponse` with the `accepted` | ||
flag set. | ||
If set to `true` a `grant` MUST be also sent which is constructed by: | ||
|
||
``` | ||
Signature(public-key,org-id,clock/some other stuff) | ||
``` | ||
|
||
``` | ||
This part I am not sure, but I think some kind of mechanism is needed, | ||
the correct way would be to piggy back the whole description of the org, but | ||
that's likely to resources intensive. So a grant is basically the next best thing, but | ||
there might be other methods. | ||
``` | ||
|
||
This grant MAY be attached to each message so that client can optimistically process | ||
messages coming from this user even though the most up-to-date `OrganistationDescription` has not been fetched. | ||
|
||
(The idea here is that we don't want to have issue with ordering of messages, for example | ||
if I joined channel `x`, and I fetch messages from the mailserver, I might see a post from a new | ||
user `y` before I have fetched the org description, so I don't know whether the user | ||
is actually allowed to post. By using a grant, I can optimistically process their messages, | ||
knowing that at some point between my latest version of the memberships and what I haven't fetched | ||
yet, they have been added to the org. In case they have been removed afterward, I can go back and delete those | ||
messages, but in most cases I should be fine. | ||
Comment on lines
+133
to
+142
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this solution, I have a few questions.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There's no easy way to know, so I would have the client keep grant as long as it's not invalid, but say 7 days should be plenty for now for example.
The issue with grants is that they are not completely authoritative and that they only reflect partial updates, so clients should only optimistically act on them, and revert if necessary. So you could see a It is essentially a mixture between a purely event driven protocol (private group chats), which is very bandwidth heavy but has little loss of information/room for state inconsistencies, and a purely materialized view, which has high loss of information, room for state inconsistencies, but low bandwidth.
No, there's no mechanism for it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not sending an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sorry, it's not specified, but that's the implemented behavior (on top of resending), will update the docs We'd still need the grant I think in case clients have partial history, as the admin might not always be online and it's possible they are not able to retrieve historic messages. |
||
|
||
|
||
``` | ||
message OrganisationInvitation { | ||
OrganisationDescription organisation = 1; | ||
bytes grant = 2; | ||
} | ||
|
||
message OrganisationRequestJoin { | ||
string ens_name = 1; | ||
string chat_id = 2; | ||
} | ||
|
||
message OrganisationRequestJoinResponse { | ||
bool accepted = 1; | ||
bytes grant = 2; | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can this be assured? Or is this more of a soft guarantee ("don't use a topic that corresponds to known ASCII string (e.g.)"?
What happens if someone else decided to use that topic in the network? (I assume nothing but some extra BW, just to make sure)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So a filter would be a combination of topic + encryption key.
For this channels we should not re-use the same algorithm for calculating those, mainly for bw issues.
If there's a topic only clash (different encryption keys), that's not an issue as we would have two different filters handling this.
If there's both a topic and encryption key clash (that's completely avoidable on our side), then we might start having issues, but
chat-id
is in the message so I believe we can still differentiate them.