Expand description
Cooperation: the runtime that turns discovered, trusted runtimes of one repository into linked peers and keeps their journal converged. It owns the one peer-link table, the one journal of this runtime, the link handlers the HTTP surface answers, the dialers, the heartbeat and the expiry — and the operations (sessions, claims, handovers, reviews) every surface performs through it.
The sequence one link goes through, and where each step is decided:
candidate a trusted registry record of the same repository, or a declared seed
↓
dial hello → welcome (link::) signature, freshness, nonce, protocol,
repository, self, trust — both directions
↓
connected sync every heartbeat: marks + missing events, both ways, signed
↓ a failed round: degraded → unreachable (backoff, capped at the expiry)
expired no exchange within the expiry: the link is dropped, the runtime's
↓ streams stop beating everywhere, its claims stop excluding
reconnect the dialer says hello again; an unknown link id or a new instance is a
re-handshake, never a second peer — the table is keyed by runtimeStreamLiveness has two layers and they are deliberately separate. A link is this runtime’s connection to one peer (connected, degraded, unreachable, expired). A stream is alive while its beat keeps rising anywhere in the mesh — a runtime linked only through a relay is still alive, and a runtime that crashed stops beating for everyone at once. Claims follow streams, not links.
The whole of it, two runtimes in one process. Only the socket is replaced: the handshake, the signatures, the admission and the fold are the ones a LAN takes.
use std::collections::BTreeMap;
use std::sync::{Arc, Mutex, Weak};
use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
use majordomus_cli::mesh::cooperation::{CheckoutFacts, Cooperation, CooperationSetup};
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, SessionInfo};
use majordomus_cli::mesh::link::{LinkReply, LinkTransport, Signed, HELLO_PATH};
use majordomus_cli::mesh::registry::MeshRegistry;
use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};
use majordomus_cli::mesh::trust::TrustPolicy;
#[derive(Default)]
struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);
impl LinkTransport for Net {
fn post(&self, endpoint: &str, path: &str, m: &Signed) -> Result<LinkReply, String> {
let peer = (self.0.lock().unwrap().get(endpoint).and_then(Weak::upgrade))
.ok_or_else(|| format!("{endpoint}: nobody there"))?;
Ok(if path == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) })
}
}
let net = Arc::new(Net::default());
let runtime = |endpoint: &str| {
let c = Cooperation::new(CooperationSetup {
identity: Arc::new(NodeIdentity::ephemeral().unwrap()),
runtime: runtime_id(endpoint),
repository: of_root_commits(&["root".into()]),
endpoints: vec![endpoint.into()],
version: "doc".into(),
config: CooperationConfig::default(),
trust: TrustConfig { policy: TrustPolicy::Tofu, allow: vec![] },
journal_path: None,
registry: Arc::new(MeshRegistry::new()),
transport: Arc::clone(&net) as Arc<dyn LinkTransport>,
board: None,
checkout: CheckoutFacts::default(),
})
.unwrap();
net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c));
c
};
let (a, b) = (runtime("a:1"), runtime("b:1"));
let key = a.dial(&["b:1".into()]).expect("B welcomes A");
assert_eq!(key, b.runtime_key(), "the link is keyed by the peer's runtime");
a.claim(&SessionInfo::named("s1", "cli"), vec!["apps".into()], None,
ClaimMode::Exclusive, None).unwrap();
for _ in 0..2 {
a.journal().beat_own();
a.sync_with(&key).unwrap();
}
assert_eq!(b.state().claims.len(), 1, "the claim crossed the link");
assert_eq!(a.state().digest, b.state().digest, "one state, two runtimes");Structs§
- Checkout
Facts - What the projected sessions say about the checkout they work in. Computed once at start — branch and head are refreshed when a board session changes, never on a heartbeat, so liveness never rescans the repository.
- Cooperation
- One runtime’s whole part in the mesh, behind one handle. It holds the single journal this process writes to, the single table of links it has, and the admission lock that decides claims — and it is deliberately one object rather than a set of services, because every one of those is the other’s context: a claim is admitted against state folded from events that arrived over a link, and a link is admitted against trust the same object evaluates.
- Cooperation
Counters - The link and replication counters since start: what this runtime did, not what it holds. They are monotonic and never reset, so two readings a minute apart are a rate — which is the only way to tell a mesh that is working from one that is retrying, since both show the same peers in the same states.
- Cooperation
Setup - Everything one runtime needs before it can link to another, gathered in one place so that the runtime never reaches for it later. Each field is a decision somebody else already made — the declaration’s policy, the checkout’s identity, this process’s key, the socket to speak through — and passing them in is what lets a test replace any of them without a fixture: a fake transport, an ephemeral key, a journal that never touches the disk.
- Cooperation
Status - The whole cooperation runtime, as every surface reports it: the command line, the HTTP surface and MCP all render this one value, so that a person and an agent asking the same question of the same runtime are never told different things.
- Mesh
Verify Check - One verification check: what was checked, whether it holds, the evidence, and — when something is wrong or limited — the impact and what to do about it.
- Mesh
Verify Report - What
mesh verifyfound: the local checks, every peer’s round, and the state digest afterwards. The digest is what makes the report worth running on two machines — two runtimes that print the same digest have the same sessions, claims, handovers and reviews, and two that do not have something to reconcile, whatever their links say. - Peer
Verdict - What one sync round, run now rather than remembered, said about one peer. Verification does not report the link’s standing and stop there: it exchanges with the peer and says whether the exchange worked and whether both sides ended holding the same marks, which is the difference between a peer that answers and a peer that agrees.
- Peer
View - One peer as every surface shows it: who it is, how this runtime reaches it, and what
the link has been through. The counters are carried per peer rather than only in the
totals because the question a person asks of a flapping mesh is which peer is flapping,
and
restartsanswers a different one fromreconnects— a peer whose process keeps dying, against a link that keeps dropping under a process that never did. - Refused
View - A candidate that was refused, with the rule that refused it. A refusal is kept and shown rather than logged and dropped, because the commonest mesh failure is a link that never forms: a person who declared a seed and sees no peer needs the decision that was made about it — the wrong repository, a key nobody allowed, a clock too far out — and the direction says which side made it.
- Written
- What an operation wrote, as its answer to the caller. Every mesh operation is an event appended to this runtime’s journal, and the caller is handed the three facts it cannot work out for itself: the mesh-wide key of the thing it created, the event that says so, and the Lamport stamp that places it against everyone else’s events.
Enums§
- Cooperation
Error - Why a cooperation operation did not happen. Every variant is a decision rather than a fault: nothing here is a transport failure or a bug, so a caller that sees one has been told something true about the mesh and should say it to its user rather than retry.
- Link
State - A link’s standing, from this runtime’s side. It is a statement about a connection and
never about the peer: a runtime reachable only through a third party is
Expiredhere while its streams beat on everywhere, which is why claims follow streams and not this. - Round
Error - What a dial or a sync round did not do. The three are kept apart because they are acted on differently: an unreachable peer is retried with a backoff, a refusal is a decision that will be made the same way next time and is recorded rather than retried, and the absence of a link is this runtime’s own state and not the peer’s.
Constants§
- MAX_
PEERS - The most peers one runtime links to.
- MAX_
TARGETS_ PER_ NODE - The most runtimes of one node this runtime dials.
- PEER_
RETENTION - How long an expired peer stays listed before it leaves the table.