//TODO: on tauri (or forward in local broker, or CLI), prefer a BoxPublic to a Domain. Domain always comes first though, so we need to reorder the list
//TODO: use site.bootstraps to order the list of brokerInfo.
forbroker_infoinbrokers{
matchbroker_info{
matchbroker_info{
BrokerInfoV0::ServerV0(server)=>{
BrokerInfoV0::ServerV0(server)=>{
leturl=server.get_ws_url(&location).await;
leturl=server.get_ws_url(&location).await;
@ -508,7 +510,7 @@ pub async fn connect_wallet(
ifurl.is_some(){
ifurl.is_some(){
leturl=url.unwrap();
leturl=url.unwrap();
ifurl.1.len()==0{
ifurl.1.len()==0{
// TODO deal with BoxPublic and on tauri all Box...
// TODO deal with Box(Dyn)Public -> tunnel, and on tauri/forward/CLIs, deal with all Box -> direct connections (when url.1.len is > 0)
/// When --public is used, this option will disallow clients to connect to the public interface too. Otherwise, by default, they can. Should be used in combination with a --domain option
/// When --public or --dynamic is used, this option will disallow clients to connect to the public interface too. Otherwise, by default, they can. Should be used in combination with a --domain option
// core listeners always come after the domain ones, which is good as the first bootstrap in the list should be the domain (if there is also a core_with_clients that generates a BoxPublic bootstrap)
Domain(String),// accepts an option trailing ":port" number
Domain(String),// accepts an optional trailing ":port" number
//Core(Vec<BindAddress>),
//Core(Vec<BindAddress>),
}
}
@ -835,7 +835,7 @@ pub enum AcceptForwardForV0 {
PublicDomain((String,String)),
PublicDomain((String,String)),
/// X-Forwarded-For accepted only for clients with public addresses. First param is the domain of the proxy server
/// X-Forwarded-For accepted only for clients with public addresses. First param is the domain of the proxy server
/// domain can take an option port (trailing `:port`)
/// domain can take an optional port (trailing `:port`)
/// second param is the privKey of the PeerId of the proxy server, useful when the proxy server is load balancing to several daemons
/// second param is the privKey of the PeerId of the proxy server, useful when the proxy server is load balancing to several daemons
/// that should all use the same PeerId to answer requests
/// that should all use the same PeerId to answer requests
PublicDomainPeer((String,PrivKey,String)),
PublicDomainPeer((String,PrivKey,String)),
@ -960,7 +960,7 @@ pub struct ListenerV0 {
/// when the box is behind a DMZ, and ipv6 is enabled, the private interface will get the external public IpV6. with this option we allow binding to it
/// when the box is behind a DMZ, and ipv6 is enabled, the private interface will get the external public IpV6. with this option we allow binding to it
pubbind_public_ipv6: bool,
pubbind_public_ipv6: bool,
/// default to false. Set to true by --core (use --core-and-clients to override to false). only useful for a public IP listener, if the clients should use another listener like --domain or --domain-private.
/// default to false. Set to true by --core (use --core-with-clients to override to false). only useful for a public IP listener, if the clients should use another listener like --domain or --domain-private.
/// do not set it on a --domain or --domain-private, as this will enable the relay_websocket feature, which should not be used except by app.nextgraph.one
/// do not set it on a --domain or --domain-private, as this will enable the relay_websocket feature, which should not be used except by app.nextgraph.one
pubrefuse_clients: bool,
pubrefuse_clients: bool,
@ -1166,6 +1166,9 @@ pub type ForwardedPeerId = PubKey;
/// The store has a special branch called `overlay` that is used to manage access to the InnerOverlay
/// The ref is split in two: id and key.
/// only the ReadCapSecret is needed to access the InnerOverlay
/// The ID can be omitted if reading the overlay members should not be allowed.
/// the full readcap of this branch is needed in order to subscribe to the topic and decrypt the events. The branchId can be found in the branch Definition
/// In this case, the pinning broker will not be able to subscribe to the overlay root topic
/// it can be useful to subscribe to this topic i the user is at least a reader of the store's repo, so it will be notified of refreshReadCap on the overlay
/// and will therefor lose access if the overlay is refreshed.
/// if the user is an external user to the store, it will lose access to the InnerOverlay after a RefreshReadCap of the overlay branch of the store.
/// Contains the object of newly published Commit, its optional blocks, and optional refs and their blocks.
/// Contains the objects of newly published Commit, its optional blocks, and optional refs and their blocks.
/// If a block is not present in the Event, its ID should be present in block_ids and the block should be put on the emitting broker beforehand with BlocksPut.
/// If a block is not present in the Event, its ID should be present in block_ids and the block should be put on the emitting broker beforehand with BlocksPut.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructEventContentV0{
pubstructEventContentV0{
/// Pub/sub topic
/// Pub/sub topic
pubtopic: TopicId,
pubtopic: TopicId,
pubpublisher: ForwardedPeerId,
// TODO: could be obfuscated (or not, if we want to be able to recall events)
// on public repos, should be obfuscated
pubpublisher: PeerId,
/// Commit sequence number of publisher
/// Commit sequence number of publisher
pubseq: u64,
pubseq: u64,
/// Blocks with encrypted content. First in the list is always the commit block, the others are optional.
/// 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),
/// blocks of the REFS are optional (only sent here if user specifically want to push them to the pub/sub).
/// the first in the list MUST contain a commit_header_key
/// When saved locally (the broker keeps the associated event, until the topic is refreshed(the last heads retain their events) ),
/// so, this `blocks` list is emptied (as the blocked are saved in the overlay storage anyway) and their IDs are kept on the side.
/// then when the event needs to be send in reply to a *TopicSyncReq, the blocks list is regenerated from the IDs,
/// so that a valid EventContent can be sent (and so that its signature can be verified successfully)
pubblocks: Vec<Block>,
pubblocks: Vec<Block>,
/// Ids of additional Blocks with encrypted content that are not to be pushed in the pub/sub
/// Ids of additional Blocks (REFS) with encrypted content that are not to be pushed in the pub/sub
/// they will be retrieved later by interested users
pubblock_ids: Vec<BlockId>,
pubblock_ids: Vec<BlockId>,
/// Encrypted key for the Commit object (the first Block in blocks)
/// can be :
/// The key is encrypted using ChaCha20:
/// * Encrypted key for the Commit object (the first Block in blocks vec)
/// Request to refresh the Pinning of a previously pinned repo.
/// it can consist of updating the expose_outer, the list of ro_topics and/or rw_topics,
/// and in case of a ban_member, the broker will effectively flush the topics locally after all local members except the banned one, have refreshed
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructRefreshPinRepoV0{
/// The new PinRepo info
pubpin: PinRepo,
/// optional hashed member ID that should be banned
pubban_member: Option<Digest>,
/// when banning, list of topics that are to be flushed (once all the local members have left, except the one to be banned)
/// All the honest local members have to send this list in order for the banned one to be effectively banned
/// for each Topic, a signature over the hashed UserId to ban, by the Topic private key.
/// The banning process on the broker is meant to flush topics that would remain dangling if the malicious member would not unpin them after being removed from members of repo.
/// The userId of banned user is revealed to the local broker where it was attached, which is a breach of privacy deemed acceptable
/// as only a broker that already knew the userid will enforce it, and
/// that broker might be interested to know that the offending user was banned from a repo, as only malicious users are banned.
/// The broker might also discard this information, and just proceeed with the flush without much ado.
/// Of course, if the broker is controlled by the malicious user, it might not proceed with the ban/flush. But who cares. That broker will keep old data forever, but it is a malicious broker anyway.
pubflush_topics: Vec<(TopicId,Sig)>,
}
/// Request to pin a repo
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumRefreshPinRepo{
V0(RefreshPinRepoV0),
}
/// Request to unpin a repo on the broker.
/// Request to unpin a repo on the broker.
/// When client will disconnect, the subscriptions and publisherAdvert of the topics will be removed on the broker
/// When client will disconnect, the subscriptions and publisherAdvert of the topics will be removed on the broker
/// (for that user only. other users might continue to have the repo pinned)
/// (for that user only. other users might continue to have the repo pinned)
@ -2680,16 +2804,18 @@ pub enum TopicUnsub {
}
}
/// Request a Block by ID
/// Request a Block by ID
/// commit_header_key is always set to None in the reply when request is made on OuterOverlay of protected or Group overlays
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructBlockGetV0{
pubstructBlockGetV0{
/// Block ID to request
/// Block IDs to request
pubid: BlockId,
pubids: Vec<BlockId>,
/// Whether or not to include all children recursively
/// Whether or not to include all children recursively
pubinclude_children: bool,
pubinclude_children: bool,
/// Topic the object is referenced from
/// Topic the object is referenced from, if it is known by the requester.
pubtopic: Option<PubKey>,
/// can be used to do a BlockSearchTopic in the core overlay.
pubtopic: Option<TopicId>,
}
}
/// Request an object by ID
/// Request an object by ID
@ -2699,9 +2825,9 @@ pub enum BlockGet {
}
}
implBlockGet{
implBlockGet{
pubfnid(&self)-> BlockId{
pubfnids(&self)-> &Vec<BlockId>{
matchself{
matchself{
BlockGet::V0(o)=>o.id,
BlockGet::V0(o)=>&o.ids,
}
}
}
}
pubfninclude_children(&self)-> bool{
pubfninclude_children(&self)-> bool{
@ -2738,6 +2864,7 @@ impl BlocksPut {
}
}
/// Request to know if some blocks are present locally
/// Request to know if some blocks are present locally
/// used by client before publishing an event, to know what to push
@ -3463,42 +3592,51 @@ impl From<AuthResult> for ProtocolMessage {
}
}
//
//
// DIRECT / OUT-OF-BAND MESSAGES
// LINKS
//
//
/// Link/invitation to the repository
/// Link to a repository
/// Consists of an identifier (repoid), a ReadCap or WriteCap, and a locator (peers and overlayLink)
/// Those capabilities are not durable: They can be refreshed by the members and previously shared Caps will become obsolete/revoked.
/// As long as the user is a member of the repo and subscribes to the root topic (of the repo, and of the store if needed/applicable), they will receive the updated capabilities.
/// But if they don't subscribe, they will lose access after the refresh.
/// For durable read capabilities of non-members, see PermaReadCap.
/// In most cases, the link is shared and the recipient opens it and subscribes soon afterward.
/// Perma capabilities are needed only when the link is stored on disk and kept there unopened for a long period.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructRepoLinkV0{
pubstructRepoLinkV0{
/// Repository public key ID
/// Repository ID
pubid: Identity,
pubid: RepoId,
puboverlay: OverlayLink,
/// read capability for the whole repo
/// current (at the time of sharing the link) root branch definition commit
pubread_cap: ReadCap,
/// Repository secret. Only set for editors
/// Write capability secret. Only set for editors. in this case, overlay MUST be set to an InnerOverlay
pubrepo_secret: Option<SymKey>,
pubwrite_cap_secret: Option<RepoWriteCapSecret>,
/// current root branch definition commit
/// Current overlay link, used to join the overlay
/// Link to object(s) or to a branch from a repository
/// The latest ReadCap of the branch (or main branch) will be downloaded from the outerOverlay, if the peer brokers listed below allow it.
/// that can be shared to non-members
/// The snapshot can be downloaded instead
/// This locator is durable, because the public site are served differently by brokers.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructObjectLinkV0{
pubstructPublicRepoLocatorV0{
/// Request to send to an overlay peer
/// Repository ID
pubreq: ExtRequest,
pubrepo: RepoId,
/// optional branchId to access. a specific public branch,
/// if not set, the main branch of the repo will be used.
pubbranch: Option<BranchId>,
/// optional commits of head to access.
/// if not set, the main branch of the repo will be used.
pubheads: Vec<ObjectRef>,
/// optional snapshot to download, in order to display the content quicker to end-user.
pubsnapshot: Option<ObjectRef>,
/// The public site store
pubpublic_store: PubKey,
/// Peer brokers to connect to
pubpeers: Vec<PeerAdvert>,
}
/// Keys for the root blocks of the requested objects
/// Link to a public repository
pubkeys: Vec<ObjectRef>,
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumPublicRepoLocator{
V0(PublicRepoLocatorV0),
}
}
/// Link to object(s) or to a branch from a repository
/// Read access to a branch of a Public, Protected or Group store.
/// that can be shared to non-members
/// The overlay to join can be the outer or the inner, depending on what was offered in the link.
/// The difference between the two is that in the outer overlay, only one broker is contacted.
/// In the inner overlay, all the publisher's brokers are contacted, so subscription to the pub/sub is more reliable, less prone to outage.
/// This is not a durable link. If the topic has been refreshed, the pubsub won't be able to be subscribed to,
/// but TopicSyncReq will still work (answering the commits up until the moment the topic was refreshed)
/// and the optional heads will always be retrievable
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumObjectLink{
pubstructReadBranchLinkV0{
V0(ObjectLinkV0),
/// Repository ID
pubrepo: RepoId,
pubbranch: BranchId,// must match the one in read_cap
/// an optional list of heads that can fetched in this branch
/// useful if a specific head is to be shared
pubheads: Vec<ObjectRef>,
/// read capability for the branch
/// current (at the time of sharing the link) branch definition commit
pubread_cap: ReadCap,
/// Current overlay link, used to join the overlay, most of the time, an outerOverlay is preferred
puboverlay: OverlayLink,
/// Peer brokers to connect to
pubpeers: Vec<PeerAdvert>,
}
}
/// Owned repository with private key
/// Link to a repository
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructRepoKeysV0{
pubenumReadBranchLink{
/// Repository private key
V0(ReadBranchLinkV0),
pubkey: PrivKey,
}
/// Repository secret
/// Obtains one or more objects of a repo (Commit, File) by their ID.
pubsecret: SymKey,
/// On an outerOverlay, the header is always emptied (no way to reconstruct the DAG of commits) except on public overlays or if a topicId is provided
/// If the intent is to share a whole DAG of commits at a definite CommitID/HEAD, then ReadBranchLink should be used instead (or PublicRepoLocator if public site)
#[derive(Clone, Debug, Serialize, Deserialize)]
pubstructObjectLinkV0{
/// Repository ID: not used to make the request. but useful for commits, to know which repo they are from without needing to fetch and open the full DAG of commits.
/// (but the one here might be wrong. only when opening the DAG can the real repo be known. also note that on outerOverlay of non public stores, the DAG is not accessible)
/// note that it could be omitted, specially if the objects are files. As files are content-addressable and belong to an overlay but not to a specific repo or topic.
pubrepo: Option<RepoId>,
/// An optional topic that will be used to retrieve the Certificate of a commit, if needed
/// (topic has to be checked with the one inside the commit. the one here might be wrong. it is provided here as an optimization)
/// or can be used to help with BlockSearchTopic.
/// If the topic is provided, a TopicSyncReq can be performed, and the causal past of the commit will appear (by repeated tried while narrowing down on the ancestors),
/// hence defeating the "emptied header" protection
pubtopic: Option<TopicId>,
pubobjects: Vec<ObjectRef>,
/// Overlay to join
puboverlay: OverlayLink,
/// Peers to connect to
/// Peer brokers to connect to
pubpeers: Vec<PeerAdvert>,
pubpeers: Vec<PeerAdvert>,
}
}
/// Owned repository with private key
/// Link to a specific commit, without its causal past
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumRepoKeys{
pubenumObjectLink{
V0(RepoKeysV0),
V0(ObjectLinkV0),
}
}
/// NextGraph Link V0
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumNgLinkV0{
Repo(RepoLink),
PublicRepo(PublicRepoLocator),
Branch(ReadBranchLink),
Object(ObjectLink),
}
/// NextGraph Link
#[derive(Clone, Debug, Serialize, Deserialize)]
pubenumNgLink{
V0(NgLinkV0),
}
// TODO: PermaLinks and PostInbox (and ExtRequests)
// we check that the ACK is the repository singleton commit. in this case, it means we are dealing with the first RootBranch commit, which is fine to have no deps.