-->
A grassroots-level protocol.
Compromise is the little-death that brings total obliteration.
Servers have two endpoints:
/:signer/:cosigner/:tangent
POST/GET/DELETE
entries without requiring a websocket connection.
POST
requires all 3 parameters and a signature from the signer.GET
requires any combination of 1-3 of the parameters, with underscores being a wildcard, and returns paginated results.DELETE
requires all 3 parameters and a signature from either the signer or cosigner.signer
cosigner
tangent
limit
(number, default 1)
after
(hash, default null)
before
(hash, default null)
ascending
(boolean, default false)
/ws
id
- Used to track responses to requestsaction
- POST|GET|DELETE|RESPONSE
or SUBSCRIBE|UNSUBSCRIBE|MESSAGE
path
- /:signer/:cosigner/:tangent
data
- (for POST
, RESPONSE
, and MESSAGE
)Entries are rows in the nodes’ local databases, and have the following properties:
Public metadata:
Private metadata: (optionally encrypted, depending on the public/private boolean)
Data is replicated 3 times in the network, and each replica is stored on the node closest to each of the three parameters.
Data is not guaranteed to exist forever on the network - nodes treat data as a LRU cache, and will delete old data when they run out of space. In order to keep data alive, clients should store their data locally and occasionally request or reupload it.
For example, #like
might be a frequent topic, so whatever node is in charge of it will only be able to keep the most recent entries alive. This is fine, because the purpose of the network is to provide a cache to bridge the gap between peers that are online asynchronously, not store data forever.
Due to the fact that websockets on https sites require wss, browsers will need to use a gateway url, similar to how IPFS gateways work.
This spec does not currently provide anonymity, as there are no “hops” between nodes. It may be implemented as an option in the future, depending on the needs of the applications that use it.
The following are examples of how the protocol could be used to implement features of a social network. These mechanisms are not strictly defined, and implementers are encouraged to experiment with different ways of building their applications. All paths can either be used with the REST or websocket endpoints, depending on whether the application needs real-time updates.
For readability, keys are prefixed with a colon (:alice
) and hashes are prefixed with a hashtag (#profile
).
Profile:
:alice/:alice/#profile
: Get Alice’s profileFriendship:
:alice/:bob/#friend
: Get the status of Alice’s friendship towards Bob:alice/:bob/_
: Get all keys that Alice has addressed to Bob:alice/_/#friend
: Get friendships from Alice_/:bob/#friend
: Get friendships towards Bob:bob/_/_
: Get latest activity from Bob_/:bob/_
: Get latest activity towards Bob_/_/#friend
: Get latest friendships on the whole networkCreating a post:
:post/:post/#cats
: Then, she would publish the post, maybe to the topic #cats
. If the post is private, she will need to distribute the read key to the intended audience.:alice/:post/#post
: If Alice wants the post to be tied to her identity, she can signify ownership by publishing and cosigning an entry with both her key and the post’s write key, to prove that she holds both keys.:post/:platform/#post
: If she wants to publish the post to a platform, the address might look like this, as this would give the platform the ability to moderate posts. This would most likely redirect to the original :post/:post/#cats
address.Commenting on a post:
:comment/:post/#comment
: Then, he would add the comment to the post.
DELETE
requests can be authorized by either the signer or cosigner.:bob/:comment/#comment
: If Bob wants the comment to be tied to his identity, he can create an entry signed by both his key and the comment’s key.Creating a pointer:
:pointer/:pointer/#pointer
: Create a pointer to a post, comment, or other entry. These keys and hash can really be anything, as the action of being a pointer is defined in the (optionally encrypted) datatype, not the schema.Managing a group:
:group/:group/#group
: Get the group’s metadata:group/_/#epoch
: Get the latest decryption epochs:epoch/:alice/#key
: Get Alice’s decryption key for an epoch_/:group/#message
: Get the latest messages in the group. Users would create a new keypair for each message, which is similar to how posts and comments work, but messages would likely not be published to users’ accounts like a post would.Due to the lack of identity-based authentication, it is expected that spam would be a problem, which is an unfortunate side-effect of decentralization. Applications will have to implement their own spam filters, which will most likely look like web-of-trust setups, but nodes may have heuristics and rate limits to help with this.
There will need to be a way to handle nodes that are misbehaving, most likely looking like a reputation system involving uptime and responsiveness. This will be implemented in the future, but is not a part of the initial spec.
Nodes will need to be able to subscribe to “nukelists”, which are lists of trusted public keys that can request nodes to delete entries. While this is technically a form of censorship, it is a necessary evil due to the fact that entries are not always encrypted. This is not unprecedented, as decentralized systems like Storj have similar mechanisms.
Eventually, it is a goal to implement higher-level features, such as a way to cache static content, upload logic as wasm binaries, or have more detailed search indexes, depending on the needs of the applications that use it.
Github: @heapswap/subfield
Author: @kahnpoint