Continuity
Two people talk over pairwise DIDs. Either of them can change address, or end, and the news arrives in messages that come late, out of order, or at a different device. Continuity answers where the relationship goes next, from the facts alone, without letting arrival time pick a winner.
Every figure on this page runs the published @estoc/continuity model in your browser. Each one is a set of facts you can
switch on and off; the answers beside it are what the model derives from exactly those facts.
Pairs on a lattice
From your side, a relationship is an oriented pair C(local, peer): your DID first, theirs second. Swapping them asks a
different question. In the figures your DIDs are the columns and the peer's are the
rows, so when you rotate the pair moves right, and when the peer rotates it moves down. The numbers in
A0, A1, B0 only tell DIDs apart; they carry no time and no order.
The model reads three kinds of fact:
-
peer-observation: an authenticated message from the peer to exactly your local DID. If it carried the peer's verified
from_priorrotation, it also names the DID the peer rotated from. - peer-ending: the peer's verified proof that it ended.
- local-decision: a choice you saved, to rotate your DID or to end.
- your rotation, usable
- the peer's rotation, usable
- a derived join
- in history, not usable
- a saved rotation, waiting
- in conflict
o0inside a pair: a receipt thereend e: an ending there
Select any pair in a figure to query it. Hover a fact to see where it sits.
One receipt, two pairs
B1 writes to A0, carrying proof that it rotated from B0. That receipt is one fact, p1, and it sits at two pairs: it
claims the rotation at C(A0,B0), the pair the peer left, and records a receipt at C(A0,B1). The head of C(A0,B0) moves to C(A0,B1).
A hundred receipts carrying the same proof are still one fact.
Switch on x: another relationship that also talks to B0. Sharing a DID connects nothing, so C(X0,B0) keeps its own head.
Your rotation waits for an echo
Saving a rotation from A0 to A1 records your intent. Before the model relies on it, it asks for evidence that the pair you are leaving was live: an authenticated message from the peer, or from a successor of the peer, to exactly A0. Until then the head is unresolved. It does not fall back to the old pair either, since a forward change is known.
Switch on o0 and the rotation becomes usable. Try o1 instead, a message to A1: it says nothing about A0, so
the head stays unresolved. Or try p1: B1 is a successor of B0 and wrote to A0, which confirms A0 and moves both sides at
once.
Both of you rotate
You rotated to A1 and the peer rotated to B1, each without seeing the other's move. The model joins the two: where both rotations apply, it derives the pair of both successors, C(A1,B1), along the dotted join links. Every pair reaches the same head, whichever you start from.
The join invents no receipt. Select C(A1,B1): nothing shows that B1 has written to A1, so confirmation answers
not yet. Switch on o2, a plain message from B1 to A1, and it answers yes.
Why does p1, received at A0, move C(A1,B0) too? A change of the peer applies across its same-peer context: the
pairs your own rotations connect while the peer stays B0. Your changes apply across the same-local context, the pairs the
peer's rotations connect. Select a pair and use the context buttons to see both.
A fork, not a race
Two of your devices hold different facts. One has o0, d1 and p1, and its head is C(A1,B1).
The other has learned p2: B2 wrote to A1, carrying a rotation from B0 to B2. When their facts meet, B0 has two
successors in one context.
Switch on p2.
The model reports competing-changes with the pairs it masks, and picks neither. No timestamp, arrival order or device
decides. Any replica holding the same facts reports the same conflict, so the conflict itself is where they converge. The head given
earlier is withdrawn; messages already sent stay sent, and resolving the fork is up to the people and the host.
Other shapes block a head too: two saved successors of your own, even before either is confirmed; a cycle back to a pair the rotations left; and a join that would pair a DID with itself. All of them are scenarios in the sandbox.
Endings
An ending closes one side within a context. Here B0 ended, in a proof sent to A0. Because d1 links C(A0,B0) to C(A1,B0)
while the peer stays B0, the ending applies to C(A1,B0) as well. An ending creates no empty pair, and it does not mean the contact was
deleted or blocked.
Switch on p1: B0 has now both rotated and ended in one context, and those compete. A rotation followed by the successor's
ending, B0 to B1 and then B1 ends, would be ordinary history.
How head answers
For a known pair, the answer takes the first of these that holds:
- conflict: a conflict reaches the pair, or a claim reaches it only through history no usable link vouches for.
- ended: an ending of either side applies through usable links.
- unresolved: saved rotations still wait for an observation of their predecessor address.
- head: the unique pair the usable forward links lead to, with the facts that support them.
A pair no fact mentions is no-evidence.
Sandbox
Select a pair, then add facts at it. The scenario menu holds the harder cases from the illustrated guide, such as a link only the positive graph has, and an onward rotation on a side branch. The facts live in the page address, so a link reproduces what you see.
What the model leaves to the host
-
Evidence. The model reads facts, not messages. Verifying
from_priorproofs is@estoc/from-prior's; authenticating envelopes and saving decisions is the host's. - Completeness. Every answer is relative to the facts supplied. More facts can expose a conflict and withdraw a head.
- Same revision. Check an operation's prerequisites and commit it against the same revision of the facts.
- Authority. A head is a continuity prerequisite, not permission to send.
- Coordination. Converging on the same facts does not coordinate anything. Two offline devices can each pick a successor; the model shows the fork once their facts meet.
The package README has the full host contract, and the illustrated guide links every case to its test.