Groups
1 Group membership lifecycle
stateDiagram-v2 [*] --> requests: entry request [*] --> seat: join w/token [*] --> pending: admin invitation requests --> seat: approve pending --> seat: join seat --> [*]: leave requests --> [*]: leave pending --> [*]: admin delete
2 Foreign group lifecycle
A foreign group is a group that we possess some information about but that we are not a full member of yet.
A minimal information we can have about a group, apart from knowing its existence, is a group preview. Obtaining a group preview is non-obligatory – we might want to preview groups we have no intention to join. A group preview can be requested of public and private groups without any permissions, while previewing a secret group requires a valid access token. Note: secret group previews currently remain unimplemented.
There are two ways to join a group: we can ask the group host for entry, or we can attempt to join directly, possibly with an access token. A successful entry request yields a group access token received from the host, that is then used to join the group.
A group join has two stages: in the first stage we poke the group host with access token. If successful, we are granted a seat in the group. Subsequently, we subscribe to the group host on two paths: general update path, and a ship specific update path that is used to communicate facts not meant for everyone (such as admin-only facts, or personal tokens sent only to the requester). Note: currently all communications happens on personal update paths.
NOTE: how can we distinguish between a kick terminating response, and a kick due to other conditions? It seems there is no reliable way to do that. But we could issue a pre-emptive leave on our own if we received a response. This way a kick can only signal a problem.
2.1 Foreign group lookup
stateDiagram [*] --> preview: subscribe for preview preview --> error preview --> kick preview --> done done --> preview: refresh kick --> preview: retry after delay error --> preview: retry
2.2 Foreign group join progress
stateDiagram [*] --> ask: ask for entry ask --> X1: cancel ask --> error1: poke fail ask --> error1: watch fail ask --> join: token fact ask --> join: user join [*] --> join: user join join --> watch: poke ack join --> error2: poke fail join --> X2: cancel watch --> done: join completed watch --> X3: cancel watch --> error3: watch fail
3 Sequences
3.1 Ask request
3.1.1 Public group ask
An ask request issued to a public group is automatically approved, unless the client has been banned. The group host generates a new invite token and sends it to the client, which then proceeds to join the group with the received access token.
sequenceDiagram participant client participant host client ->> host: %ask poke client ->> host: %watch /ask/ship alt permission denied host->>client: poke nack host->client: watch nack else host->>client: poke ack host->host: generate token host->>client: watch ack host->>client: %give token client->>host: join w/ token end
3.1.2 Private group ask
An ask request issued to a private group is recorded in requests.admissions, unless the ship has been banned. Group admins can then approve or deny requests. For an approved request, the group host issues a token that is then send to the client. The client then uses the token to join the group. If an ask request has been denied, the group host notifies the client by kicking his subscription, which terminates the flow at the client side.
3.1.2.1 Client ask
sequenceDiagram participant client participant host client ->> host: %ask poke client ->> host: %watch /ask/ship alt permission denied host->>client: poke nack host->>client: watch nack else host->>client: poke ack host->>client: watch ack host->host: record request end
3.1.2.2 Admin approve and deny
sequenceDiagram participant client participant host participant admin opt request approved admin->>host: approve the request host->host: delete the record host->host: generate new token host->>client: %give token host->>client: %kick client->>host: join w/token end opt request denied admin->>host: deny the request host->host: delete the record host->>client: %kick end
3.2 Group join request
3.3 Group leave
A client agent is in some way registered by the group host in the following cases: (1) he is already a group member, (2) he is in the process of joining the group and has a registered seat, (3) he has issued a group ask request, (4) he has been added to the pending list.
If the client then wishes to forfeit that registration, he can issue a group leave request. The group host will then de-register the client from all existing records. In particular, the host will do the following.
- Delete the client’s seat and kicks any outstanding group subscriptions.
- Delete the client hosted channels.
- Delete the client’s ask request and kicks any outstanding ask subscriptions.
- Delete the the client from the pending list.
sequenceDiagram participant client participant host client ->> host: %leave poke opt is member host->host: delete the seat host->>client: %kick on /updates/time host->>client: poke %ack end opt is asking host->host: delete the request host->>client: %kick on /ask/ship host->>client: poke %ack end opt is pending host -> host: delete from pending host->>client: poke %ack end
3.4 Channel preview
Channel previews carry the metadata of a channel, together with the associated group preview. Q: can a channel belong to two groups at once? Do we guard against it? This is useful because in some contexts our starting point are the channels, which do not, by themselves, carry associated group information. Imagine we want to display a list of channels that have unread notifications. We know their identity, but on the display list we would also like to show the owning group icon etc. A channel preview enables us to store all required information in one place, and resolve it, if it is yet missing.
sequenceDiagram participant ca as client A participant host as group host participant cb as client B ca ->> host: watch /v1/channels/$nest/preview alt hosts channel host ->> host: verify read permissions host ->> ca: %give channel preview else host ->> cb: watch /v1/channels/$nest/preview cb->> cb: verify read permissions cb->> host: %give channel preview host ->> ca: %give channel preview end
4 Permissions
4.1 Group management
Admin rights are required to issue group management actions. A role can be designated as having admin rights, and any user being assigned the role is considered an admin. A newly created group has a default admin role with id %admin.
The following actions are admin-restricted:
- Updating group metadata
- Changing group entry policy
- Membership management
- Roles management
- Channel management
- Section manegement
Only the group host is allowed to assign or revoke admin rights to a role. However, any admin is able to assign and revoke roles, including admin roles.
The group host is always considered to possess admin rights required to execute a group action, irrespective of any assigned roles.
Note: should we restrict assignment of admin-enabled roles to the group host? Otherwise two admins could try to revoke each other’s rights to manage the group in an attempt to gain control of the group.
4.2 Channel permissions
A channel has read, write permissions which can be assigned to specific roles. If no roles has been assigned a given permission, it means the permission is granted to all group members.
Due to somewhat unfortunate architectural reasons, channel read and write permissions are stored in two separate places. The read permissions are stored in the groups agent, while the write permissions are stored in the channels-server. The reason for this is that when a group member wants to join a channel, it makes the decision based on the information available in the client group data, which includes read permissions. Write permissions, on the other hand, are only checked when a user attempts to post a message. This action is directed to the channels-server agent, which can verify the write permissions without needing to query external data.