Initial commit
This commit is contained in:
commit
5eea2dab3d
1 changed files with 116 additions and 0 deletions
116
README.org
Normal file
116
README.org
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#+title: Bloom Specification
|
||||
|
||||
This is the specification for the Bloom chat protocol version α1.
|
||||
|
||||
* Preamble
|
||||
Bloom is a chat protocol built on the following core principles:
|
||||
- Simplicity: it must be relatively simple to implement a client or server.
|
||||
- Resilience: the Bloom network must be resilient against network instability.
|
||||
- Privacy: messages sent via Bloom must be secured against snooping.
|
||||
- Comprehensiveness: Bloom must support a comprehensive set of chat features as expected of a modern protocol.
|
||||
- Extensibility: Bloom must be easy to extend, and easy to interact with for the developer.
|
||||
|
||||
In practice, most of these tenets are yet to be actioned, and Bloom is in a very early stage of development. The following features are planned, and at current state may or may not be implemented (note that many of these features are intended to be opt-in):
|
||||
- Reply to message.
|
||||
- Edit message.
|
||||
- Delete message.
|
||||
- Read receipts.
|
||||
- Media sharing.
|
||||
- Markup text.
|
||||
- Custom emojis.
|
||||
- Typing indicator.
|
||||
- Status indicator.
|
||||
- End to end encryption of messages.
|
||||
- Self-messaging.
|
||||
- Tagging.
|
||||
- Pinning.
|
||||
- Voice calling.
|
||||
- Video Calling.
|
||||
- Group chats and Channels.
|
||||
- GPS location.
|
||||
- Bluetooth messaging.
|
||||
- Server multi-networking and duplication.
|
||||
|
||||
* Overview
|
||||
Each end-user uses a =Client= to connect to a =Server=. Each =Client= connection is tied to a single =User= object on the server, which contains metadata about the user (including their login password, phone number, etc). Each user has an associated =Inbox= stack to which other users can send messages. Messages are sent via =Update= objects, which are uniquely identified by the a ULID, the origin =User=, and the destination =User=.
|
||||
|
||||
=Updates= may be sent directly to the =Server=, which directs them to the correct =Inbox= stack or otherwise interprets the request. In order to directly message another user, it is only necessary to know the username of the target, and to send an =Update= of a support =Type= to the =Server=, with the destination of the target user. The =Inbox= stack for each user is synchronised in real-time between the =Server= and each =Client= which is currently logged in as the specified =User=.
|
||||
|
||||
* Update Representation
|
||||
Due to the ease of parser implementation and my undying devotion to the Lisp arts, =Update= objects in Bloom are represented as simplified s-expressions. The following grammar specification defines all possible =Update= objects:
|
||||
#+begin_src fundamental
|
||||
UPDATE ::= '(' TYPE (KEYWORD EXPR)* ')'
|
||||
EXPR ::= STRING | LIST | SYMBOL | NUMBER | ULID
|
||||
LIST ::= '(' EXPR* ')'
|
||||
ULID ::= (ALPHA | NUM)+
|
||||
SYMBOL ::= TYPE | KEYWORD
|
||||
TYPE ::= IDENT
|
||||
KEYWORD ::= ':' IDENT
|
||||
IDENT ::= (ALPHA | NUM | SEP)+
|
||||
STRING ::= '"' !('"')* '"'
|
||||
NUMBER ::= NUM+ ('.' NUM*)? | '.' NUM+
|
||||
|
||||
ALPHA ::= 'a..zA..Z'
|
||||
NUM ::= '0..9'
|
||||
SEP ::= '-' | '_'
|
||||
#+end_src
|
||||
|
||||
The =TYPE= of an =Update= specifies to the server how the =Update= should be handled. The list of =KEYWORDS= and =EXPRS= which follows contains the necessary information for the server to handle the given =UPDATE=. The list of arguments forms a list of key-value pairs, or an association list in Lisp terminology, and can be mapped to a dictionary in any other language. In each pair of values, for example a keyword ':ping' and an expr '100', the keyword is the key of the value of expr.
|
||||
|
||||
=Update= objects do not require any specific order for the key-value pairs to present in (other than each keyword being followed by it's intended value), and so a =Type= specification like so:
|
||||
#+begin_src fundamental
|
||||
(foo :bar STRING :rab NUMBER)
|
||||
#+end_src
|
||||
does not require =:bar= to be present before =:rab= when the message is sent.
|
||||
|
||||
Additional data can also be sent via each =Update=, which the type does not necessarily require. In the above example, the server can append =:metadata= to the =foo= object, and this should not cause any issue for the client or server receiving the =Update=.
|
||||
|
||||
** Update Types
|
||||
The following update types are supported in the core specification.
|
||||
|
||||
*** Response
|
||||
#+begin_src fundamental
|
||||
(response :action STRING :status NUMBER :message STRING :data LIST)
|
||||
#+end_src
|
||||
|
||||
A reply from the client or server that a requested =:action= was received and process, resulting in a =:status=.
|
||||
=:message= is an empty string unless the =:action= and =:status= dictates that additional information should be sent back to the original sender.
|
||||
=:data= is typically an empty list, however may be a list of further key-value pairs which contain requested information.
|
||||
|
||||
Each =:status= corresponds to a result:
|
||||
- 0: the action was successful.
|
||||
- 1: the action was unsuccessful due to an error on the recipient (see =:message= for additional information).
|
||||
- 2: the action was unsuccessful as the requester is unauthorized.
|
||||
|
||||
*** Log In
|
||||
#+begin_src fundamental
|
||||
(log-in :username STRING :password STRING)
|
||||
#+end_src
|
||||
|
||||
A request from the client to the server to log in as the given =:username=, using the given =:password=.
|
||||
All update types besides =response= and =log-in= will fail with a =:status= of 2 unless the user logs in to the server first.
|
||||
|
||||
*** Message
|
||||
#+begin_src fundamental
|
||||
(message :id ULID :origin-user STRING :destination-user STRING :message STRING :timestamp NUMBER)
|
||||
#+end_src
|
||||
|
||||
Sends a =:message= from the =:origin-user= to the =:destination-user=. This message has a unique =:id=, and =:timestamp= is the unix timestamp for the original message object from the =:origin-user=. These updates are pushed by the server to the =:destination-users= inbox, which is then synchronised by immediately sending the update onwards to any clients connected as the =:destination-user=.
|
||||
|
||||
*** Backfill
|
||||
#+begin_src fundamental
|
||||
(backfill :user STRING :since ULID)
|
||||
#+end_src
|
||||
|
||||
Requests a server or client to send all messages in the =:users= inbox stack, =:since= the message ULID specified.
|
||||
Requested messages are sent as individual =message= objects.
|
||||
|
||||
*** Describe User
|
||||
#+begin_src fundamental
|
||||
(describe-user :user STRING)
|
||||
#+end_src
|
||||
|
||||
Requests the server to provide a list of information detailing a given =:user=. This information is returned via a =response= update, where the =:data= contains at minimum the following information:
|
||||
- =:username=: a string, the username of the requested user.
|
||||
- =:image=: a string, a URL to the profile picture of the requested user. This string may be empty.
|
||||
- =:phone-number=: a string, the phone number of the user. This string may be empty.
|
||||
Loading…
Add table
Add a link
Reference in a new issue