This protocol exchanges content that isn't encrypted.
In the native apps, this protocol runs between the front-end part of the App and the back-end part that is running inside Tauri from Rust compiled into the app binary. Both sides of the protocol are in the same process, but there is an interface between them provided by Tauri (which is made of JSON objects), but this is transparent to the App developer.
In the web-app, the same happens, but the "back-end" part runs inside the same JS context, and is some WASM code compiled from Rust. The passing of messages doesn't involve JSON, as JS POJOs are directly exchanged at the interface.
If the App opens a session with a remote Verifier, the protocol is ran inside a WebSocket, with Noise encryption.
This protocol is available directly from the JS and Rust APIs and you do not need to implement it again or send messages manually. New bindings are always welcomed, for any contributor who wants to add them.
All the protocol messages are embedded inside an `AppRequest` message, and are replied by the Verifier with an `AppResponse`.
A new session needs to be opened with the LocalBroker methods, not documented here (it will be documented in the APIs reference). Once the session is opened, the session_id needs to be passed in every request.
- NuriV0.branch : if None, the main branch is chosen
- InnerOverlayLink.store_overlay_readcap : The store has a special branch called `Overlay` that is used to manage access to the InnerOverlay. Only the ReadCapSecret is needed to access the InnerOverlay. The full readcap of this branch is needed in order to subscribe to the topic and decrypt the events, and hence be able to subscribe to refreshes of the InnerOverlay. The branchId can be found in the branch Definition. It can be useful to subscribe to this topic if the user is a member of the store's repo, so it will be notified of BranchCapRefresh on the overlay. To the contrary, if the user is an external user to the store, they won't be able to subscribe and they will loose access to the InnerOverlay after a BranchCapRefresh of the overlay branch of the store.
- BrokerServerTypeV0::Domain : accepts an optional trailing ":`port`" number
replies with an `AppResponseV0::Nuri(string)` containing the string representation of the Document's Nuri, of the form `did:ng:o:[repo_id]:v:[overlay_id]`.
### DocUpdate
Updates the **graph** or **discrete** nature of the Document, or both.
Replied with `AppResponseV0::Ok`.
If set, the `NuriV0.branch` should be of the variant `BranchId(_)`. If None, the main branch will be used.
A SPARQL Update query. Can span multiple Documents (by indicating a `GRAPH <Nuri>` or `WITH <Nuri>`, and optional `USING <Nuri>` with a Nuri of the form `did:ng:o:v`).
The `AppRequestV0.nuri` is mandatory and will represent the default graph.
Replied with a `AppResponseV0::Ok`.
The `NuriV0.target` cannot be a `UserSite`, `AllDialogs` nor `AllGroups`.
content_type // a string representing an IANA media type
))),
}
```
#### first Response
```rust
AppResponseV0::FileUploading(upload_id) // a u32
```
#### one or more chunk put Request(s) : RandomAccessFilePutChunk
upload your file in chunks of maximum 1 048 564 bytes, for best efficiency.
Repeat this call until you finished upload all your file.
Add another extra call at the end, with a size of zero. This will indicate that you are done with uploading chunks.
Replied with a `AppResponseV0::Ok` for each chunk that is non-empty.
The last call with an empty chunk is replied with an `AppResponseV0::FileUploaded(reference)` containing an `ObjectRef` to the uploaded file, that you should use in the next call `AppRequestPayloadV0::AddFile`.
```rust
// example AppRequestV0
AppRequestV0 {
...,
command : AppRequestCommandV0::FilePut,
nuri: NuriV0::new_empty(),
payload: Some(AppRequestPayload::V0(
AppRequestPayloadV0::RandomAccessFilePutChunk(
(upload_id, chunk) // chunk is a Vec<u8>
)
)),
}
```
- nuri : can be omitted in those calls, unlike the 2 other type of calls
#### last Request : AddFile
Finally you make an `AppRequestPayloadV0::AddFile` call that will attach the Object to your document's branch.
```rust
// example AppRequestV0
AppRequestV0 {
...,
command : AppRequestCommandV0::FilePut,
nuri: NuriV0 {
target: NuriTargetV0::Repo(repo_id),
overlay: Some(overlay_id),
branch: // can be omitted (defaults to main branch)
... // all the rest empty
},
payload: Some(AppRequestPayload::V0(
AppRequestPayloadV0::AddFile(
DocAddFile {
...
}
)
)),
}
struct DocAddFile {
filename: Option<String>,
object: ObjectRef,
}
```
- DocAddFile.object : must be the reference you obtained from the last call to `RandomAccessFilePutChunk`.
The first response contains some meta-data about the branch called `TabInfo`. It is used mostly by the App to display the document header and instantiate the document's viewer.
Then a second response contains the **materialized state** of the document as it is known by the local Verifier at the moment of the subscribe request.
- AppRequestV0.nuri.target : represents the default graph. Can be NuriV0::UserSite or NuriV0::None and in those cases, the **union graph** of all the graphs is used as default graph.
- for SELECT queries: an `AppResponseV0::QueryResult(buffer)` where buffer is a `Vec<u8>` containing a UTF-8 serialization of a JSON string representing a JSON Sparql Query Result. See [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/).
- AppHistory.swimlane_state : can be discarded. It is only used by our GUI representation of the history in the Apps. Same with the x and y values in CommitInfo.
- an optional string that is present only if the commit is a signature. In this case, the string represents a list of the signed commits `c:[commit_id]:k:[commit_key]` joined with `:` (at least one commit is present), followed by partial Nuri for the signature object `:s:[signature_object_id]:k:[signature_object_key]`.
If the signature is immediately available, the response is `AppResponseV0::True`. The new HEAD containing the signature can be immediately fetched with a call to `SignatureStatus`.
If the signature is not immediately available (because the quorum needs to sign it and it can take some time), the response is `AppResponseV0::False`. A notification will be sent to the user once the signature is ready (not implemented yet).
### SignedSnapshotRequest
Requests that a snapshot be taken from the current materialized state at the HEADs, and that this new commit containing the snapshot, be signed asynchronously.
If the signature is immediately available, the response is `AppResponseV0::True`. The newly created snapshot and its signature can be immediately fetched with a call to `SignatureStatus`.
If the signature is not immediately available (because the quorum needs to sign it and it can take some time), the response is `AppResponseV0::False`. A notification will be sent to the user once the signature is ready (not implemented yet). The snapshot is already available as the last commit in HEAD, but it isn't signed yet.