04 - Designing Dorabella

General architecture

To make any application it is wise to first consider how its overall functionality is best broken up into separate logical components. A chat application must perform at minimum:

On top of that, we want our particular chat application to sign and encrypt outgoing messages and verify and decrypt incoming ones. And since we’re using freedom.js, we want to do all of this in as decentralized a manner as possible, while still building a pragmatic and usable application.

Unfortunately the Internet has not settled on a decentralized social network, and so the natural way for most users to know if their friends are online and exchange messages with them is through proprietary services. This will not be changed in one fell swoop, and so instead our goal will be to write an application that can at least be used with any social network service, so users can choose between them more freely. And the encryption will also occur entirely on the client side, reducing the social network to a relatively uninformed and untrusted message passing channel.

As we learned in the previous section, freedom.js works by executing concurrent JavaScript threads in web workers that communicate via message passing. Each web worker is a freedom.js module that should have a distinct purpose, and there is also typically at least some JavaScript executed directly in the browser (so it can interact with the user and the DOM). Let us consider separating our chat application into three modules (not counting the direct-in-browser code):

Of these three, we only need to actually write the last one - freedom.js provides a social API as well as some standard providers for us to get started, and we will be using freedom-pgp-e2e to provide a PGP-like interface for encryption.

So our overall plan for the structure of Dorabella (from “front” to “back”) is:

TODO diagram?

Component details and API

Now that we have a general idea of the code we want to write, we should plan in more detail the structure of the main module we’ll write. In particular this means deciding on an API for communicating with outer (DOM-interacting) JavaScript, and ensuring that this API facilitates all needed uses of the other (social and crypto) modules.

The API is specified from the point of view of the outer JavaScript, listing both methods that it can invoke on the instantiated freedom.js module and events from the module that can be listened for. The values for methods are arguments that are passed in, while the values for events contain whatever information the freedom.js module is sending to the outer page.

Name Type Functionality Value(s)
send
method Use the social provider to send a message to a target buddy one string corresponding to targetBuddy (who to send the message to) and another string for the message itself
recv-status
event *Local* user status - tell the outer JavaScript whether the social provider is online or offline string
recv-uid
event Once online, tell the outer JavaScript the local user name/ID string
recv-err
event Pass errors up to the outer JavaScript (to alert the user) string
recv-message
event Listen to the social provider for messages from other users and pass them on to the outer JavaScript one string corresponding to the buddy that sent the message and another string for the message itself
recv-buddylist
event Listen to the social provider for messages about what buddies are online and pass it on to the outer JavaScript Array of objects (themselves several strings to describe buddy ID, public key, etc.)
export-publicKey
event Once PGP provider is set up, send local user public key to outer JavaScript string

Don’t worry too much if this seems overwhelming right now - writing a good API is difficult, and in real development you will likely iterate several times before settling on something like the above. You will find yourself referring back to the API throughout development, so it’s worth making it clear and literate - not too short and not too long.

Once a reasonable API has been decided, it should be added to the JSON manifest describing the application. This is the Dorabella manifest - in addition to the API, it enumerates the files that Dorabella is composed of and its freedom.js dependencies (the social and PGP providers). The API described is labeled chat, and the freedom.js module we are writing provides an implementation of this API that is usable not only as a standalone application but potentially as a dependency to be embedded in a larger application.

Now that we have the API under our belt, let’s push on to implementation, starting with the core Dorabella freedom.js module.

03 - How freedom.js works --- 05 - The core of Dorabella