Group: GNU Social P2P/Design/Agent2LocalCore
UI to Core Protocol
Keys
The UI has a public key and a root control key. All values are opaque to the Core and are decrypted on the UI side. The UI should have a local cache for performance.
Core Side
Data manipulation:
- put(path, value) - performs store[path] = value
- get(path) - returns store[path]
- delete(path) - performs delete store[path]
- scan(max, start_path[, end_path]) - returns paths in range [start_path, end_path)
- multiget(max, start_path [, end_path]) - returns paths, values in range
Sharing:
Mounting allows accessing a friend's store as if it was local. Mounts are read-only and are cached on the Core. The UI notifies others of changes to their store with send - see below.
- mount(route, remote_path, local_path) - attach friend store
- unmount(local_path) - detach friend store
- set_control_key(subject_path, control_path, control_key) - allow access to subject_path through control_path
route includes: friend_id, information required to route to the friend, such as domain or IP
path_key is the key used to encrypt the subtree rooted at the path. It is never available to the Core
control_path is the path of a node in the store that is used to control access to content nodes. It can correspond to a tag (e.g. 'work') or to a friend.
control_key is the subject node path_key encrypted with the control node path_key
All nodes will be accessible through a root control_path, who's path_key is the minimum the UI needs to access the entire store.
Notification:
- send(route, local_prefix) - sends a subtree to friend
- request(local_prefix, max, order) - request a subtree from a mount
UI Side
- on_receive(route, local_prefix) - notification that a send was received
on_receive is a result of send from friend.
- on_mount_done(local_prefix, result)
- on_send_done(local_prefix, result) - notification of a send completed or failed
REST HTTP binding
A simple binding of the Core to UI protocol over HTTP REST. All {} enclosed structures are JSON encoded.
Data manipulation:
put(path, value)
-> PUT '/store/$path', { value: $value }
get(path) -> GET '/store/$path'
returns { value: $value, control_keys: $control_keys }
delete(path) -> DELETE '/store/$path'
returns number deleted (0 or 1)
scan(start_path, end_path, max) -> GET '/store/$start_path#scan?end=$end_path&max=$max'
returns [ $path* ]
multiget(max, start_path [, end_path]) -> GET '/store/$start_path#multi?end=$end_path&max=$max'
returns [ {path: $path, value: $value, control_keys: $control_keys}* ]
Sharing:
set_control_key(subject_path, control_path, control_key)
-> PUT '/store/$subject_path#permit_key/$control_path', { key: $control_key }
-> DELETE '/store/$subject_path#permit_key/$control_path'
mount(route, remote_path, local_path)
-> POST '/store/$local_path#mount', { route: $route, remote: $remote_path }
unmount(local_path) -> DELETE '/store/$local_path#mount'
Communication:
send(route, local_path)
-> POST '/store/$local_path#send', { route: $route }
request(local_path, max, order)
-> POST '/store/$local_path#request', { max: $max, order: $order }
Callbacks to UI:
UI performs:
GET '/event'
This is a blocking call. Possible results:
on_receive(route, path)
-> { type: 'receive', path: $path, success: true, $route }
-> { type: 'receive', path: $path, success: false, $route, message: "..." }
on_send_done(route, path, result)
-> { type: 'send_done', path: $path, success: true }
-> { type: 'send_done', path: $path, success: false, message: "..." }
on_mount_done(route, path, result)
-> { type: 'mount_done', path: $path, success: true }
-> { type: 'mount_done', path: $path, success: false, message: "..." }
NOTES:
- ↑ The UI should get the content of the path, decrypt using the UI public key, then set_control_key($path, ...) to set a control_key for the incoming node. This will enable the UI to access the node without performing a public key operation in the future (for improved performance).