- owners_write_cap : when the list of owners is changed, a crypto_box containing the RepoWriteCapSecret should be included here for each owner. This should also be done at creation time, with the UserId of the first owner, except for individual private store repo, because it doesn't have a RepoWriteCapSecret. The vector has the same order and size as the owners one. Each owner finds their write_cap here.
the previous branch heads, and the **ACKS** are empty.
Can be used also to update the branch definition when users are removed (in order to refresh the ReadCap)
In this case, the total_order quorum is needed, and **DEPS** indicates the BranchCapRefresh commit.
```rust
struct BranchV0 {
/// Branch public key ID
id: PubKey,
crdt: BranchCrdt,
/// Reference to the repository commit
repo: ObjectRef,
root_branch_readcap_id: ObjectId,
/// Pub/sub topic for publishing events
topic: PubKey,
topic_privkey: Vec<u8>,
pulled_from: Vec<u8>,
/// App-specific metadata (not used)
metadata: Vec<u8>,
}
```
- root_branch_readcap_id : object ID of the current root_branch commit (ReadCap), in order to keep in sync this branch with root_branch. The key is not provided because external readers should not be able to access the root branch definition.
It is only used by verifiers (who have the key already).
- topic_privkey : a BranchWriteCapSecret, encrypted with a nonce = 0 and a key derived as follow
BLAKE3 derive_key ("NextGraph Branch WriteCap Secret BLAKE3 key", RepoWriteCapSecret, TopicId, BranchId ) so that only editors of the repo can decrypt the privkey. For individual store repo, the RepoWriteCapSecret is zero
- pulled_from : optional: this branch is the result of a pull request coming from another repo. Contains a serialization of a ReadBranchLink of a transactional branch from another repo
If it is part of the Repository creation, that needs to create several branches (Store, Overlay or User branches, and Header branch) then it is also signed by the SyncSignature.
**DEPS**: if update branch: previous AddBranch commit of the same BranchId
- topic_id : the new topic_id. Will be needed immediately by future readers in order to subscribe to the pub/sub). Should be identical to the one in the Branch definition. None if merged_in.
- branch_read_cap : the new branch definition commit (we need the ObjectKey in order to open the pub/sub Event). None if merged_in
- crdt : one of (the string indicates the primary class of the branch)
- Graph(String),
- YMap(String),
- YArray(String),
- YXml(String),
- YText(String),
- Automerge(String),
- Elmer(String),
- branch_type : one of
- Header,
- Main,
- Transactional,
- Store,
- Overlay,
- User,
- Chat,
- Stream,
- Comments,
- BackLinks,
- Context,
### SyncSignature
Sync Threshold Signature of a single commit or a chain of commits.
Points to the new Signature Object. Based on the total order quorum (or owners quorum). Mandatory for UpdateRootBranch, UpdateBranch, some AddBranch, RemoveBranch, RemoveMember, RemovePermission, Quorum, Compact, sync Transaction, RootCapRefresh, BranchCapRefresh
/// the two "orders" PublicKeys (total_order and partial_order)
orders_pk_sets: OrdersPublicKeySetsV0,
}
/// Enum for "orders" PKsets.
enum OrdersPublicKeySetsV0 {
Store(ObjectRef),
Repo(
(
threshold_crypto::PublicKey,
Option<threshold_crypto::PublicKey>,
),
),
None,
}
```
- CertificateSignatureV0.TotalOrder : indicates the total_order quorum set has been used to sign the certificate.
- CertificateSignatureV0.Owners : indicates that the owners set signed the certificate. If the previous cert's total order PKset has a threshold value of 0 or 1 (1 or 2 signers in the quorum),then it is allowed that the next certificate (this one) will be signed by the owners PKset instead. This is for a simple reason: if a user is removed from the list of signers in the total_order quorum,then in those 2 cases, the excluded signer will probably not cooperate to their exclusion, and will not sign the new certificate. To avoid deadlocks, we allow the owners to step in and sign the new cert instead. The Owners are also used when there is no quorum/signer defined (OrdersPublicKeySetsV0::None).
- CertificateSignatureV0.Store : in case the new certificate being signed is an update on the store certificate (OrdersPublicKeySetsV0::Store(ObjectRef) has changed from previous cert) then the signature is in that new store certificate, and not here. Nothing else should have changed in the CertificateContent, and the validity of the new store cert has to be checked.
- CertificateContentV0.previous : the previous certificate in the chain of trust. Can be another Certificate or the Repository commit's body when we are at the root of the chain of trust.
- CertificateContentV0.readcap_id : the Commit Id of the latest RootBranch definition (= the ReadCap ID) in order to keep in sync with the options for signing. Not used for verifying (this is why the secret is not present).
- OrdersPublicKeySetsV0 : Can be inherited from the store, in this case, it is an ObjectRef pointing to the latest Certificate of the store. Or can be 2 PublicKeys defined specially for this repo,
- OrdersPublicKeySetsV0::Repo.0 one for the total_order (first one).
- OrdersPublicKeySetsV0::Repo.1 the other for the partial_order (second one.is optional, as some repos are forcefully totally ordered and do not have this set).
- OrdersPublicKeySetsV0::None : the total_order quorum is not defined (yet, or anymore). There are no signers for the total_order, neither for the partial_order. The owners replace them.
Updates the ReadCap of the public, protected, Group and Dialog stores of the User
This is used to speedup joining the overlay of such stores, for new devices on new brokers (or for the web-app that always need it) so they don't have to read the whole pub/sub of the StoreRepo in order to get the last ReadCap
**DEPS** : to the previous ones (if any)
```rust
struct StoreUpdateV0 {
// id of the store.
store: StoreRepo,
store_read_cap: ReadCap,
overlay_branch_read_cap: ReadCap,
/// Metadata (not used)
metadata: Vec<u8>,
}
```
### AddRepo
Adds a repo into the store branch.
The repo's `store` field should match the destination store
and the referenced rootbranch definition(s) should have compatible causal past (the newer AddSignerCap must have a newer epoch compared to the one of the replaced cap )
```rust
struct AddSignerCapV0 {
cap: SignerCap,
/// Metadata (not used)
metadata: Vec<u8>,
}
/// when a signing capability is removed, a new SignerCap should be
/// committed to User branch, with the removed key set to None
struct SignerCap {
repo: RepoId,
/// latest RootBranch commit or Quorum commit that defines the signing epoch
- author : Commit author, a BLAKE3 keyed hash of UserId. Key is a BLAKE3 derive_key ("NextGraph UserId Hash Overlay Id for Commit BLAKE3 key", overlayId). Hash will be different than for ForwardedPeerAdvertV0 so that core brokers dealing with public sites wont be able to correlate commits and editing peers (via common author's hash).O nly the brokers of the authors that pin a repo for Outer Overlay exposure, will be able to correlate. It also is a different hash than the OuterOverlayId, which is good to prevent correlation when the RepoId is used as author (for Repository, RootBranch and Branch commits)
- branch : BranchId the commit belongs to (not a ref, as readers do not need to access the branch definition)
- perms : optional list of dependencies on some commits in the root branch that contain the write permission needed for this commit
- header_keys : Keys counterpart of all the references present in the header (deps, acks, files, etc...) as the header only has the IDs.
- quorum : one of :
- NoSigning
- PartialOrder
- TotalOrder
- Owners
- IamTheSignature
- body: When the commit is reverted or erased (after compaction), the CommitBody is deleted, creating a dangling reference
### CommitHeader
Header of a Commit, can be embedded or used as a reference.
Contains only the IDs of the references present in the Header (acls, deps, files, etc...). The keys are in CommitContent.
The Brokers can read the CommitHeader.
On the ExtProtocol, the CommitHeader is stripped from the blocks, so that external readers cannot reconstruct the DAG (they will only be able to read the commit they have been given access to). If the full branch needs to be shared on the ExtProtocol, then a ReadCap of a Branch should be shared instead.
The decision to embed or reference is make according to the space left in the CommitContent. Most of the time, it will be embedded.
```rust
struct CommitHeaderV0 {
/// current valid commits in HEAD before inserting new commit
- compact : tells brokers that this is a hard snapshot and that all the ACKs and full causal past should be treated as ndeps (their body removed). Brokers will only perform the deletion of bodies after this commit has been ACKed by at least one subsequent commit. But if the next commit is a nack, the deletion is aborted.
A Random Access File is an immutable binary file that can be stored in the repo, and that can be read in random access. If the file is big, there is no cost if we want to seek to a specific position inside the file, or when decrypting it, everything is streamable and can also be ran in parallel. The uploading is also streamable and can be done concurrently.
Each block that composes the file is addressable directly. There is no need to decrypt all the file first, nor to have all the file in memory before being able to read it.
- BlockV0.commit_header_key : optional Key needed to open the CommitHeader. Can be omitted if the Commit is shared without its causal past, or if the block is not a root block of commit, or that commit is a root commit (first in branch)
- BlockContentV0.children : Block IDs for child nodes in the Merkle tree. It is empty if ObjectContent fits in one block or this block is a leaf. In both cases, encrypted_content is then not empty
- BlockContentV0.encrypted_content : contains an encrypted ChunkContentV0, encrypted using convergent encryption with ChaCha20: nonce = 0 and key = BLAKE3 keyed hash (convergence_key, plaintext of ChunkContentV0), with convergence_key = BLAKE3 derive_key ("NextGraph Data BLAKE3 key", StoreRepo + store's repo ReadCapSecret ) which is basically similar to the InnerOverlayId but not hashed, so that brokers cannot do "confirmation of a file" attacks.
It can also contain additional blocks that are sent together with the commit (additional_blocks).
And it can also contain a list of ObjectIds that are associated with this commit, but which content isn't pushed in the pub/sub. Interested parties will have to get those blocks separately. This is useful for the broker mainly, to keep a good reference counting on blocks.
```rust
enum Event {
V0(EventV0),
}
struct EventV0 {
content: EventContentV0,
/// Signature over content by topic priv key
topic_sig: Sig,
/// Signature over content by publisher PeerID priv key
peer_sig: Sig,
}
struct EventContentV0 {
/// Pub/sub topic
pub topic: TopicId,
// on public repos, should be obfuscated
pub publisher: PeerId,
/// Commit sequence number of publisher
pub seq: u64,
pub blocks: Vec<Block>,
pub file_ids: Vec<BlockId>,
pub key: Vec<u8>,
}
```
- EventContentV0.blocks : Blocks with encrypted content. First in the list is always the commit block followed by its children, then its optional header and body blocks (and eventual children).
- EventContentV0.file_ids : Ids of additional Blocks (FILES or Objects) that are not to be pushed in the pub/sub. They will be retrieved later separately by interested users (with BlocksGet)
- EventContentV0.key : Encrypted key for the Commit object (the first Block in `blocks` vec)
The ObjectKey is encrypted using ChaCha20 with a nonce = commit_seq and a key = BLAKE3 derive_key ("NextGraph Event Commit ObjectKey ChaCha20 key", RepoId + BranchId + branch_secret(ReadCapSecret of the branch) + publisher)
except for Dialog Overlays where the Hash is computed from 2 secrets.
- StoreOverlay::OwnV0 : The repo is a store, so the overlay can be derived from its own ID. In this case, the branchId of the `overlay` branch is entered here as PubKey of the StoreOverlayV0 variants.