agent-comms 9.0.15 → 9.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -0
- package/dist/core/bridge-mesh.d.ts.map +1 -1
- package/dist/core/bridge-mesh.js +1 -0
- package/dist/core/bridge-mesh.js.map +1 -1
- package/dist/core/coordinator-role.d.ts +15 -2
- package/dist/core/coordinator-role.d.ts.map +1 -1
- package/dist/core/coordinator-role.js +109 -11
- package/dist/core/coordinator-role.js.map +1 -1
- package/dist/core/data-frame-routing.d.ts +18 -2
- package/dist/core/data-frame-routing.d.ts.map +1 -1
- package/dist/core/data-frame-routing.js +93 -26
- package/dist/core/data-frame-routing.js.map +1 -1
- package/dist/core/ledger-gaps.d.ts +68 -0
- package/dist/core/ledger-gaps.d.ts.map +1 -0
- package/dist/core/ledger-gaps.js +170 -0
- package/dist/core/ledger-gaps.js.map +1 -0
- package/dist/core/tool.d.ts +6 -0
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +18 -1
- package/dist/core/tool.js.map +1 -1
- package/dist/core/wire-mesh-transport.d.ts +3 -2
- package/dist/core/wire-mesh-transport.d.ts.map +1 -1
- package/dist/core/wire-mesh-transport.js +1 -1
- package/dist/core/wire-mesh-transport.js.map +1 -1
- package/package.json +2 -2
- package/src/core/bridge-mesh.ts +1 -0
- package/src/core/coordinator-role.ts +126 -7
- package/src/core/data-frame-routing.ts +113 -26
- package/src/core/ledger-gaps.ts +234 -0
- package/src/core/tool.ts +30 -0
- package/src/core/wire-mesh-transport.ts +2 -2
package/README.md
CHANGED
|
@@ -601,3 +601,5 @@ npx agent-comms account import ~/account.bundle # on the other machine, then d
|
|
|
601
601
|
Copy the account this way or by joining, never by copying `~/.agent-comms` between machines: each machine keeps a writer id of its own for the grant ledger below, and two machines sharing one would corrupt it.
|
|
602
602
|
|
|
603
603
|
Every grant your account issues, and every revocation of one, is recorded in a replicated ledger rather than on the machine that minted it: each machine appends to a data-domain log of its own (wire-mesh's replicated issuer grant ledger pattern, `spec/PATTERNS.md`), and the logs replicate to every machine holding the account, so `dm_revoke` on any of them finds and revokes a grant another one issued. Entries are sealed under a key derived from the account key, so a device that stores or relays them without holding the account sees only ciphertext, and writing to the ledger still needs the account's private key. The ledger replicates over direct peer connections (the local mesh, or machines that reach each other directly) and between machines that meet only through the relay hub, over a relay pairing sealed end to end between the two devices so the hub carries ciphertext; either way a log is offered only to a device whose membership proof names this account, and a hub-reachable device of any other account is never offered it. A revocation itself is also announced to every connected peer the moment it is made. Grants a build before the ledger recorded in `user-identity.json` are moved into it the first time a bridge starts, with nothing to do by hand. A ledger entry that cannot be read does not stop the rest of it being read, so listing and revoking a device's grants still work. Each unreadable entry is reported once, naming its log and position, and is listed by `whoami`. It may hold a grant or a revocation: a grant recorded only in it is not revoked, and a revocation recorded only in it is not applied on this machine, until the entry is repaired or replaced from another machine's replica of the account. A removal or a `dm_revoke` that skipped one says so and is reported as incomplete, never as a clean success, and a bridge that starts with one reports that revocations may be missing.
|
|
604
|
+
|
|
605
|
+
A machine that stays behind a writer log notices it. Each replication round it compares this side's head of every log with the highest head a live peer of the account announced for it, and a log that stays behind for three rounds in a row with no new entry arriving is reported on the error output and listed by `whoami` and `update`, one line per log: `Account ledger log <log id> is behind: this machine holds up to entry <n>, a peer announces <m>, and <r> rounds have passed without the missing entries arriving; a grant or a revocation in them is not applied here`. At most eight such lines are printed, then `Account ledger: <k> more logs are behind`. That wording is part of the interface and changes only with a release that says so. The same gap is reported again only when it has grown and ten rounds have passed since the last report, and every peer that announced a higher head is asked again for the missing entries on each round the stall lasts. A round counts towards a stall unless this machine reached no peer of the account in it: an offer that fails or goes unanswered at one device never stops the count while another device is reached. At most 256 logs are tracked, preferring logs this machine already holds, and a head more than a million entries ahead of this machine's is ignored and reported once. What this cannot detect: a single path that withholds everything, including the head of the log, since the head is learned from the same frames; a log beyond the 256 tracked that this machine holds nothing of; a head more than a million entries ahead; a log that is behind but still advancing, since each new entry restarts the count; and any round in which this machine reaches no peer of the account at all. Bounding what a withheld log can cost takes a shorter lifetime for the grants themselves.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-mesh.d.ts","sourceRoot":"","sources":["../../src/core/bridge-mesh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAKtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAOlD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,iSAAiS;IACjS,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,0uBAA0uB;AAC1uB,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kBAAkB,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CAC/C;AAED,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACrC,sGAAsG;IACtG,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,+MAA+M;IAC/M,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,sSAAsS;AACtS,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,CAMhB;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,
|
|
1
|
+
{"version":3,"file":"bridge-mesh.d.ts","sourceRoot":"","sources":["../../src/core/bridge-mesh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAKtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAOlD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,iSAAiS;IACjS,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,0uBAA0uB;AAC1uB,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kBAAkB,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CAC/C;AAED,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACrC,sGAAsG;IACtG,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,+MAA+M;IAC/M,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,sSAAsS;AACtS,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,CAMhB;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,CA0EhB;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAIrB;AAED,6JAA6J;AAC7J,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAQrB"}
|
package/dist/core/bridge-mesh.js
CHANGED
|
@@ -79,6 +79,7 @@ export function createBridgeMeshSyncFromIdentity(identity, slot, options) {
|
|
|
79
79
|
naming: store.naming,
|
|
80
80
|
getNewerVersionIfAny: () => versionChecker.getNewerVersionIfAny(),
|
|
81
81
|
getUnreadableLedgerEntries: () => store.accountLedger?.unreadableEntries().length ?? 0,
|
|
82
|
+
getStalledLedgerLogs: () => transport.dataFrames.stalledLogs(),
|
|
82
83
|
});
|
|
83
84
|
const revocation = createRevocationView();
|
|
84
85
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-mesh.js","sourceRoot":"","sources":["../../src/core/bridge-mesh.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bridge-mesh.js","sourceRoot":"","sources":["../../src/core/bridge-mesh.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Claims travel as wire-mesh session frames (MeshTransport.broadcastCoordinatorClaim/sendCoordinatorClaim), and only over sessions to peers on this machine, because both duties the role assigns are facts about one machine: a PID probe can only see local processes and the cc-peer front can only reach local Claude Code sessions.
|
|
5
5
|
*
|
|
6
|
-
* When a claim is made: a store claims only when it knows of no incumbent and is the first on the machine as far as it can tell. A store that bound the well-known port with no first-contact presence configured can meet other stores only through that port, so it claims at once; one that may be reachable through first contact (it bound the port, or could neither join nor bind it) first waits one claim wait for an incumbent's announcement, so a store arriving at an existing mesh never takes the role at an equal term before the holder's claim reaches it. Both ends of every machine-local session announce the incumbent they know as the session is enrolled. When the incumbent departs, the lowest device-id among the peers this side has a machine-local session to claims at once at a raised term, and every other survivor claims too if, one claim wait later, the claim it accepts still names a holder it has no session to, which covers a lowest-id peer that is itself gone or was never reachable.
|
|
6
|
+
* When a claim is made: a store claims only when it knows of no incumbent and is the first on the machine as far as it can tell. A store that bound the well-known port with no first-contact presence configured can meet other stores only through that port, so it claims at once; one that may be reachable through first contact (it bound the port, or could neither join nor bind it) first waits one claim wait for an incumbent's announcement, so a store arriving at an existing mesh never takes the role at an equal term before the holder's claim reaches it. Both ends of every machine-local session announce the incumbent they know as the session is enrolled. When the incumbent departs, the lowest device-id among the peers this side has a machine-local session to claims at once at a raised term, and every other survivor claims too if, one claim wait later, the claim it accepts still names a holder it has no session to, which covers a lowest-id peer that is itself gone or was never reachable. A claim that is accepted names a holder that is here when it is accepted, so the wait after an accepted claim never starts: the claim waits are the one after a departure and the one at start-up.
|
|
7
|
+
*
|
|
8
|
+
* Whose claims count: claims are accepted from the peers this machine already trusts with a machine-local session, and this module does not authenticate them further. A claim is evaluated only when its holder is this side, the peer that sent it (the session's authenticated device-id, never a field of the frame), or a peer this side has a machine-local session to. A claim gossiped onward by a peer other than its holder is therefore still accepted wherever the holder is reachable, which is every peer of a fully connected machine. Any other claim waits until its holder's session is enrolled and is dropped after one claim wait, and is not evaluated at all when, by then, its sender has no machine-local session. Waiting claims are bounded per sender: each machine-local peer has at most PENDING_CLAIMS_PER_SENDER of them, at most one per holder, kept in the election's own order (higher term first, an equal term by lowest holder id), and a claim whose term no later claim could supersede is not kept.
|
|
7
9
|
*/
|
|
8
10
|
import type { CoordinatorFrame } from "wire-mesh-core/generated/protocol";
|
|
9
11
|
import type { ConnectionHandle, MeshTransport } from "./transport.js";
|
|
@@ -39,6 +41,8 @@ export declare class CoordinatorRole {
|
|
|
39
41
|
private takeoverStreak;
|
|
40
42
|
/** The claim, as `term:holder`, each peer was last answered with. A peer whose view lags keeps sending the claims it knows, and answering each one with the same incumbent only multiplies the traffic: the answer is repeated only when the incumbent changes or the peer's session is enrolled afresh, since the earlier answer may have been lost with the old session. */
|
|
41
43
|
private readonly answered;
|
|
44
|
+
/** The claims set aside, by the device-id of the session that sent each, best first in the election's own order. */
|
|
45
|
+
private readonly pending;
|
|
42
46
|
constructor(deps: Readonly<CoordinatorRoleDeps>);
|
|
43
47
|
private get election();
|
|
44
48
|
/** Whether this side holds the role now. */
|
|
@@ -51,12 +55,21 @@ export declare class CoordinatorRole {
|
|
|
51
55
|
claimIfVacantAfterWait(): void;
|
|
52
56
|
/** Tells a peer whose machine-local session was just enrolled which claim this side accepts, so a joiner learns the incumbent instead of claiming over it. A no-op while this side knows of none. */
|
|
53
57
|
announceTo(handle: Readonly<ConnectionHandle>): Promise<void>;
|
|
54
|
-
/** Evaluates a claim a peer gossiped. An accepted claim is gossiped on to every peer so the supersession reaches peers the sender is not connected to,
|
|
58
|
+
/** Evaluates a claim a peer gossiped. An accepted claim is gossiped on to every peer so the supersession reaches peers the sender is not connected to, a claim whose holder is not here waits for that holder to enrol and is dropped after one claim wait; a stale or tiebreak-losing claim is answered with the incumbent so its sender converges, and a claim whose term no later claim could supersede is dropped unevaluated, neither gossiped nor answered. Receiving the incumbent itself is neither, and is dropped without a reply, which is what stops two peers that agree from echoing it forever. */
|
|
55
59
|
handleClaim(handle: Readonly<ConnectionHandle>, frame: Readonly<CoordinatorFrame>): Promise<void>;
|
|
56
60
|
/** Recovers the role when the departed peer held it. The lowest device-id among the peers this side has a machine-local session to claims at once at a raised term; every other survivor waits one claim wait and claims itself if the claim it then accepts still names a holder it has no session to, then runs onDelayedTakeover (the caller's single-authority announcement of the departed holder, which a delayed successor makes too). */
|
|
57
61
|
handleDeparture(peerId: string, onDelayedTakeover: () => Promise<void>): Promise<void>;
|
|
58
62
|
/** Stops taking part and gives the duties up if this side held them, once any transition still running has finished. Idempotent. */
|
|
59
63
|
stop(): Promise<void>;
|
|
64
|
+
/** Whether the holder a claim names is this side, the peer that sent it, or a peer this side has a machine-local session to. The sender is the handle's authenticated device-id, so a peer cannot name itself as someone else. */
|
|
65
|
+
private holderIsHere;
|
|
66
|
+
/** Keeps a claim whose holder is not here until that holder's session is enrolled, and drops it after one claim wait. The sender keeps at most PENDING_CLAIMS_PER_SENDER of them, one per holder, so a new claim for a holder already waiting replaces it only at a higher term, and when the sender is over its share the claim the election ranks last goes. */
|
|
67
|
+
private setAside;
|
|
68
|
+
/** Removes one waiting claim and its timer. */
|
|
69
|
+
private forget;
|
|
70
|
+
/** Takes every waiting claim that names `holder`, best first, except those whose sender no longer has a machine-local session here. */
|
|
71
|
+
private takePendingFor;
|
|
72
|
+
private dropAllPending;
|
|
60
73
|
private isLowestSurvivor;
|
|
61
74
|
/** Whether the claim this side accepts leaves the role without a holder it can reach: there is no claim at all, or it names a device that is neither this side nor a peer this side has a machine-local session to. */
|
|
62
75
|
private incumbentUnreachable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator-role.d.ts","sourceRoot":"","sources":["../../src/core/coordinator-role.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"coordinator-role.d.ts","sourceRoot":"","sources":["../../src/core/coordinator-role.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAKtE,yGAAyG;AACzG,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mRAAmR;AACnR,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,IAAI,CAC1B,aAAa,EACb,2BAA2B,GAAG,sBAAsB,GAAG,iBAAiB,CACzE,CAAC;IACF,0XAA0X;IAC1X,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,gFAAgF;IAChF,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC;AA+BD,qBAAa,eAAe;IAiBd,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhBjC,4KAA4K;IAC5K,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,oKAAoK;IACpK,OAAO,CAAC,OAAO,CAAS;IACxB,4MAA4M;IAC5M,OAAO,CAAC,WAAW,CAAoC;IACvD,+EAA+E;IAC/E,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,OAAO,CAAS;IACxB,gRAAgR;IAChR,OAAO,CAAC,cAAc,CAAK;IAC3B,8WAA8W;IAC9W,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,oHAAoH;IACpH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;gBAEhC,IAAI,EAAE,QAAQ,CAAC,mBAAmB,CAAC;IAEhE,OAAO,KAAK,QAAQ,GAKnB;IAED,4CAA4C;IAC5C,QAAQ,IAAI,OAAO;IAInB,kGAAkG;IAClG,OAAO,IAAI,oBAAoB,GAAG,SAAS;IAM3C,2NAA2N;IACrN,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAKpC,gSAAgS;IAChS,sBAAsB,IAAI,IAAI;IAK9B,qMAAqM;IAC/L,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBnE,klBAAklB;IAC5kB,WAAW,CACf,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAClC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC;IA6BhB,ibAAib;IAC3a,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;IAShB,oIAAoI;IAC9H,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,kOAAkO;IAClO,OAAO,CAAC,YAAY;IAYpB,kWAAkW;IAClW,OAAO,CAAC,QAAQ;IA+BhB,+CAA+C;IAC/C,OAAO,CAAC,MAAM;IASd,uIAAuI;IACvI,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,gBAAgB;IAUxB,uNAAuN;IACvN,OAAO,CAAC,oBAAoB;IAO5B,4OAA4O;IAC5O,OAAO,CAAC,cAAc;YAkBR,KAAK;IAMnB,OAAO,CAAC,eAAe;IAMvB,wNAAwN;YAC1M,WAAW;IAMzB,mSAAmS;YACrR,YAAY;CAM3B"}
|
|
@@ -3,16 +3,27 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Claims travel as wire-mesh session frames (MeshTransport.broadcastCoordinatorClaim/sendCoordinatorClaim), and only over sessions to peers on this machine, because both duties the role assigns are facts about one machine: a PID probe can only see local processes and the cc-peer front can only reach local Claude Code sessions.
|
|
5
5
|
*
|
|
6
|
-
* When a claim is made: a store claims only when it knows of no incumbent and is the first on the machine as far as it can tell. A store that bound the well-known port with no first-contact presence configured can meet other stores only through that port, so it claims at once; one that may be reachable through first contact (it bound the port, or could neither join nor bind it) first waits one claim wait for an incumbent's announcement, so a store arriving at an existing mesh never takes the role at an equal term before the holder's claim reaches it. Both ends of every machine-local session announce the incumbent they know as the session is enrolled. When the incumbent departs, the lowest device-id among the peers this side has a machine-local session to claims at once at a raised term, and every other survivor claims too if, one claim wait later, the claim it accepts still names a holder it has no session to, which covers a lowest-id peer that is itself gone or was never reachable.
|
|
6
|
+
* When a claim is made: a store claims only when it knows of no incumbent and is the first on the machine as far as it can tell. A store that bound the well-known port with no first-contact presence configured can meet other stores only through that port, so it claims at once; one that may be reachable through first contact (it bound the port, or could neither join nor bind it) first waits one claim wait for an incumbent's announcement, so a store arriving at an existing mesh never takes the role at an equal term before the holder's claim reaches it. Both ends of every machine-local session announce the incumbent they know as the session is enrolled. When the incumbent departs, the lowest device-id among the peers this side has a machine-local session to claims at once at a raised term, and every other survivor claims too if, one claim wait later, the claim it accepts still names a holder it has no session to, which covers a lowest-id peer that is itself gone or was never reachable. A claim that is accepted names a holder that is here when it is accepted, so the wait after an accepted claim never starts: the claim waits are the one after a departure and the one at start-up.
|
|
7
|
+
*
|
|
8
|
+
* Whose claims count: claims are accepted from the peers this machine already trusts with a machine-local session, and this module does not authenticate them further. A claim is evaluated only when its holder is this side, the peer that sent it (the session's authenticated device-id, never a field of the frame), or a peer this side has a machine-local session to. A claim gossiped onward by a peer other than its holder is therefore still accepted wherever the holder is reachable, which is every peer of a fully connected machine. Any other claim waits until its holder's session is enrolled and is dropped after one claim wait, and is not evaluated at all when, by then, its sender has no machine-local session. Waiting claims are bounded per sender: each machine-local peer has at most PENDING_CLAIMS_PER_SENDER of them, at most one per holder, kept in the election's own order (higher term first, an equal term by lowest holder id), and a claim whose term no later claim could supersede is not kept.
|
|
7
9
|
*/
|
|
8
|
-
import { CoordinatorElection, compareDeviceIds, } from "wire-mesh-core/domain/coordinator-election";
|
|
10
|
+
import { CoordinatorElection, compareDeviceIds, isSupersedableTerm, } from "wire-mesh-core/domain/coordinator-election";
|
|
9
11
|
import { deviceIdFromHex, deviceIdToHex, } from "wire-mesh-core/domain/device-id";
|
|
10
12
|
/** The longest delay setTimeout accepts: past it the timer fires at once, which would turn a long backoff into a burst of takeovers. */
|
|
11
13
|
const MAX_TIMER_MS = 0x7fff_ffff;
|
|
14
|
+
/** Orders waiting claims as the election ranks claims: a higher term first, and at an equal term the lower holder id, compared as the election compares it. */
|
|
15
|
+
function rankedFirst(left, right) {
|
|
16
|
+
if (left.frame.term !== right.frame.term) {
|
|
17
|
+
return right.frame.term - left.frame.term;
|
|
18
|
+
}
|
|
19
|
+
return compareDeviceIds(left.frame.coordinator, right.frame.coordinator);
|
|
20
|
+
}
|
|
12
21
|
function sameClaim(frame, claim) {
|
|
13
22
|
return (frame.term === claim.term &&
|
|
14
23
|
compareDeviceIds(frame.coordinator, claim.coordinator) === 0);
|
|
15
24
|
}
|
|
25
|
+
/** How many claims one machine-local peer may have waiting for their holders to enrol, one per holder. */
|
|
26
|
+
const PENDING_CLAIMS_PER_SENDER = 4;
|
|
16
27
|
export class CoordinatorRole {
|
|
17
28
|
deps;
|
|
18
29
|
/** Built on first use rather than at construction, because MeshStore's peerId is assigned after its constructor runs (every bridge sets it to the identity's device-id). */
|
|
@@ -28,6 +39,8 @@ export class CoordinatorRole {
|
|
|
28
39
|
takeoverStreak = 0;
|
|
29
40
|
/** The claim, as `term:holder`, each peer was last answered with. A peer whose view lags keeps sending the claims it knows, and answering each one with the same incumbent only multiplies the traffic: the answer is repeated only when the incumbent changes or the peer's session is enrolled afresh, since the earlier answer may have been lost with the old session. */
|
|
30
41
|
answered = new Map();
|
|
42
|
+
/** The claims set aside, by the device-id of the session that sent each, best first in the election's own order. */
|
|
43
|
+
pending = new Map();
|
|
31
44
|
constructor(deps) {
|
|
32
45
|
this.deps = deps;
|
|
33
46
|
}
|
|
@@ -63,23 +76,41 @@ export class CoordinatorRole {
|
|
|
63
76
|
/** Tells a peer whose machine-local session was just enrolled which claim this side accepts, so a joiner learns the incumbent instead of claiming over it. A no-op while this side knows of none. */
|
|
64
77
|
async announceTo(handle) {
|
|
65
78
|
this.answered.delete(handle.id);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
// Taken before the first await, so a claim released here is neither dropped by its timer nor taken twice while the announcement is being sent.
|
|
80
|
+
const released = this.takePendingFor(handle.id);
|
|
81
|
+
try {
|
|
82
|
+
const frame = this.electionInstance?.announceCurrent();
|
|
83
|
+
if (frame !== undefined) {
|
|
84
|
+
await this.deps.requireTransport().sendCoordinatorClaim(handle, frame);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
this.deps.onError(error);
|
|
89
|
+
}
|
|
90
|
+
// The session just enrolled may be the holder claims were set aside for. One claim failing to evaluate never costs the others theirs.
|
|
91
|
+
for (const waiting of released) {
|
|
92
|
+
try {
|
|
93
|
+
await this.handleClaim(waiting.handle, waiting.frame);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
this.deps.onError(error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
70
99
|
}
|
|
71
|
-
/** Evaluates a claim a peer gossiped. An accepted claim is gossiped on to every peer so the supersession reaches peers the sender is not connected to,
|
|
100
|
+
/** Evaluates a claim a peer gossiped. An accepted claim is gossiped on to every peer so the supersession reaches peers the sender is not connected to, a claim whose holder is not here waits for that holder to enrol and is dropped after one claim wait; a stale or tiebreak-losing claim is answered with the incumbent so its sender converges, and a claim whose term no later claim could supersede is dropped unevaluated, neither gossiped nor answered. Receiving the incumbent itself is neither, and is dropped without a reply, which is what stops two peers that agree from echoing it forever. */
|
|
72
101
|
async handleClaim(handle, frame) {
|
|
73
102
|
if (this.stopped)
|
|
74
103
|
return;
|
|
104
|
+
if (!this.holderIsHere(handle, frame)) {
|
|
105
|
+
this.setAside(handle, frame);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
75
108
|
const result = this.election.evaluate(frame);
|
|
76
109
|
if (result.outcome === "accepted") {
|
|
77
110
|
this.answered.clear();
|
|
78
111
|
this.cancelClaimWait();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
else
|
|
82
|
-
this.takeoverStreak = 0;
|
|
112
|
+
// The holder of an accepted claim is here, so there is no incumbent to wait out.
|
|
113
|
+
this.takeoverStreak = 0;
|
|
83
114
|
await this.deps.requireTransport().broadcastCoordinatorClaim(frame);
|
|
84
115
|
}
|
|
85
116
|
else if (result.outcome === "retained" &&
|
|
@@ -109,8 +140,75 @@ export class CoordinatorRole {
|
|
|
109
140
|
async stop() {
|
|
110
141
|
this.stopped = true;
|
|
111
142
|
this.cancelClaimWait();
|
|
143
|
+
this.dropAllPending();
|
|
112
144
|
await this.syncHolding();
|
|
113
145
|
}
|
|
146
|
+
/** Whether the holder a claim names is this side, the peer that sent it, or a peer this side has a machine-local session to. The sender is the handle's authenticated device-id, so a peer cannot name itself as someone else. */
|
|
147
|
+
holderIsHere(handle, frame) {
|
|
148
|
+
const holder = deviceIdToHex(frame.coordinator);
|
|
149
|
+
return (holder === this.deps.getPeerId() ||
|
|
150
|
+
holder === handle.id ||
|
|
151
|
+
this.deps.requireTransport().electionPeerIds().has(holder));
|
|
152
|
+
}
|
|
153
|
+
/** Keeps a claim whose holder is not here until that holder's session is enrolled, and drops it after one claim wait. The sender keeps at most PENDING_CLAIMS_PER_SENDER of them, one per holder, so a new claim for a holder already waiting replaces it only at a higher term, and when the sender is over its share the claim the election ranks last goes. */
|
|
154
|
+
setAside(handle, frame) {
|
|
155
|
+
// A claim whose term no later claim could supersede is dropped by the election unevaluated, wherever its holder is, so it never takes a place here.
|
|
156
|
+
if (!isSupersedableTerm(frame.term))
|
|
157
|
+
return;
|
|
158
|
+
const holder = deviceIdToHex(frame.coordinator);
|
|
159
|
+
const mine = this.pending.get(handle.id) ?? [];
|
|
160
|
+
const same = mine.find((entry) => entry.holder === holder);
|
|
161
|
+
if (same !== undefined) {
|
|
162
|
+
if (same.frame.term >= frame.term)
|
|
163
|
+
return;
|
|
164
|
+
this.forget(handle.id, same);
|
|
165
|
+
}
|
|
166
|
+
const timer = setTimeout(() => {
|
|
167
|
+
const waiting = (this.pending.get(handle.id) ?? []).find((entry) => entry.holder === holder && entry.frame === frame);
|
|
168
|
+
if (waiting !== undefined)
|
|
169
|
+
this.forget(handle.id, waiting);
|
|
170
|
+
}, this.deps.claimWaitMs);
|
|
171
|
+
// Never what keeps a process alive: a store shutting down stops the role anyway.
|
|
172
|
+
timer.unref();
|
|
173
|
+
const kept = [
|
|
174
|
+
...(this.pending.get(handle.id) ?? []),
|
|
175
|
+
{ handle, frame, holder, timer },
|
|
176
|
+
].sort(rankedFirst);
|
|
177
|
+
this.pending.set(handle.id, kept);
|
|
178
|
+
for (const extra of kept.slice(PENDING_CLAIMS_PER_SENDER)) {
|
|
179
|
+
this.forget(handle.id, extra);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Removes one waiting claim and its timer. */
|
|
183
|
+
forget(sender, entry) {
|
|
184
|
+
clearTimeout(entry.timer);
|
|
185
|
+
const rest = (this.pending.get(sender) ?? []).filter((other) => other !== entry);
|
|
186
|
+
if (rest.length === 0)
|
|
187
|
+
this.pending.delete(sender);
|
|
188
|
+
else
|
|
189
|
+
this.pending.set(sender, rest);
|
|
190
|
+
}
|
|
191
|
+
/** Takes every waiting claim that names `holder`, best first, except those whose sender no longer has a machine-local session here. */
|
|
192
|
+
takePendingFor(holder) {
|
|
193
|
+
const senders = this.deps.requireTransport().electionPeerIds();
|
|
194
|
+
const taken = [];
|
|
195
|
+
for (const [sender, entries] of [...this.pending]) {
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
if (entry.holder !== holder)
|
|
198
|
+
continue;
|
|
199
|
+
this.forget(sender, entry);
|
|
200
|
+
if (senders.has(sender))
|
|
201
|
+
taken.push(entry);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return taken.sort(rankedFirst);
|
|
205
|
+
}
|
|
206
|
+
dropAllPending() {
|
|
207
|
+
for (const [sender, entries] of [...this.pending]) {
|
|
208
|
+
for (const entry of entries)
|
|
209
|
+
this.forget(sender, entry);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
114
212
|
isLowestSurvivor(departedPeerId) {
|
|
115
213
|
const selfId = this.deps.getPeerId();
|
|
116
214
|
const self = deviceIdFromHex(selfId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator-role.js","sourceRoot":"","sources":["../../src/core/coordinator-role.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"coordinator-role.js","sourceRoot":"","sources":["../../src/core/coordinator-role.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import type { DataHaveFrame, DataRequestFrame, Frame } from "wire-mesh-core/gene
|
|
|
6
6
|
import type { Connection } from "wire-mesh-core/ports/transport";
|
|
7
7
|
import type { KeyValueStorage } from "wire-mesh-core/ports/storage";
|
|
8
8
|
import type { AccountLedgerReplica } from "./account-ledger.js";
|
|
9
|
+
import { LedgerGapTracker, type StalledLedgerLog } from "./ledger-gaps.js";
|
|
9
10
|
import type { WireMeshTransportOptions } from "./wire-mesh-transport-options.js";
|
|
10
11
|
/** The most entries one data-entries reply carries, for every log this side answers for, the account ledger's included: a longer log catches up over several rounds, so the bound only caps one frame's size. */
|
|
11
12
|
export declare const DATA_ENTRIES_RESPONSE_LIMIT = 100;
|
|
@@ -36,22 +37,31 @@ export declare function routeDataFrame(deps: Readonly<{
|
|
|
36
37
|
dataStorage: KeyValueStorage | undefined;
|
|
37
38
|
account: Readonly<AccountReplication> | undefined;
|
|
38
39
|
peerSessions: ReadonlyMap<string, unknown>;
|
|
40
|
+
gaps?: Pick<LedgerGapTracker, "noteHave"> | undefined;
|
|
39
41
|
onError: ((error: Error) => void) | undefined;
|
|
40
42
|
}>, connection: Readonly<Connection>, frame: Frame): Promise<void>;
|
|
41
43
|
/** Handles one core/data frame that arrived through a relay pairing, from the device the pairing's secure channel authenticated as `fromDeviceHex`. Only a frame naming one of the account's writer logs, from a device that holds the same account, is acted on, and any answer goes back through the same pairing; every other relayed data frame is dropped, since a device met only through the hub has no standing to read or write this side's other logs. Any handler error is reported via onError and swallowed, as in routeDataFrame. */
|
|
42
44
|
export declare function routeRelayedDataFrame(deps: Readonly<{
|
|
43
45
|
account: Readonly<AccountReplication> | undefined;
|
|
44
46
|
hub: Readonly<HubDataChannel> | undefined;
|
|
47
|
+
gaps?: Pick<LedgerGapTracker, "noteHave"> | undefined;
|
|
45
48
|
onError: ((error: Error) => void) | undefined;
|
|
46
49
|
}>, fromDeviceHex: string, frame: Readonly<DataDomainFrame>): Promise<void>;
|
|
47
|
-
/**
|
|
50
|
+
/** What one round of offering the account ledger found out. */
|
|
51
|
+
export interface LedgerOfferRound {
|
|
52
|
+
/** Whether this side reached any device of the account: an offer went out to at least one, or there was nothing to offer and a device was there to offer it to. False means this machine is offline as far as the account goes, which says nothing about whether any peer withholds anything; an offer to one device that failed does not make it false while another got through. */
|
|
53
|
+
reached: boolean;
|
|
54
|
+
/** This side's head sequence of each log it holds, by log id hex, read once for the round. */
|
|
55
|
+
localHeads: ReadonlyMap<string, number>;
|
|
56
|
+
}
|
|
57
|
+
/** Offers every account writer log this machine holds to every device that holds the same account and that this side can reach (agent-comms#344): over a live, trusted data connection, or, for a device it meets only through the relay hub, over a relay pairing. Such a device that is behind asks for what it is missing, which is the data-domain fan-out that carries each machine's grants and revocations to every other. A device reachable both ways is offered the logs once, directly. Called on the gossip cadence, so a machine that was away when an entry was written still catches up the next time it is reachable. A send that fails is reported through onError and the rest carry on; the next round retries it. Resolves with whether any device was reached and with this side's heads, read once. */
|
|
48
58
|
export declare function announceAccountLedger(deps: Readonly<{
|
|
49
59
|
connectionsByPeer: ReadonlyMap<string, Readonly<Connection>>;
|
|
50
60
|
account: Readonly<AccountReplication>;
|
|
51
61
|
hub: Readonly<HubDataChannel> | undefined;
|
|
52
62
|
peerSessions: ReadonlyMap<string, unknown>;
|
|
53
63
|
onError: ((error: Error) => void) | undefined;
|
|
54
|
-
}>): Promise<
|
|
64
|
+
}>): Promise<LedgerOfferRound>;
|
|
55
65
|
export interface DataFrameRouterDeps {
|
|
56
66
|
dataStorage: KeyValueStorage | undefined;
|
|
57
67
|
/** Absent for a transport with no account ledger. */
|
|
@@ -72,9 +82,15 @@ export declare class DataFrameRouter {
|
|
|
72
82
|
/** Every peer this side has ever received a frame from, keyed by device-id hex, tracking the raw wire-mesh-core Connection each frame arrived on: what sendDataFrame needs, since neither AcceptedMeshSession nor MeshSession exposes a generic "send an arbitrary frame" method the way the raw Connection itself does. Registered eagerly on the very first frame from a connection (including one still in quarantine, e.g. before connect_request approval) so a later sendDataFrame call can reach it; routeDataFrame's own trust gate (peerSessions.has) is what actually decides whether to act on anything received this way, not this map. */
|
|
73
83
|
private readonly connectionsByPeer;
|
|
74
84
|
private announceInterval;
|
|
85
|
+
/** What each peer says the account's writer logs reach, and the rounds this side has stayed behind it. Undefined for a transport with no account ledger. */
|
|
86
|
+
private readonly gaps;
|
|
75
87
|
/** Whether an announcement round is still running, so a round slowed by an unreachable hub peer is not stacked on by the next tick. */
|
|
76
88
|
private announcing;
|
|
77
89
|
constructor(deps: Readonly<DataFrameRouterDeps>);
|
|
90
|
+
/** Sends a data-request to one source, over its direct session when it has one and through the relay hub otherwise. */
|
|
91
|
+
private requestFrom;
|
|
92
|
+
/** The account ledger's logs this side has stayed behind for several rounds, for whoami. Empty when there is no account ledger. */
|
|
93
|
+
stalledLogs(): StalledLedgerLog[];
|
|
78
94
|
/** See routeDataFrame. */
|
|
79
95
|
route(connection: Readonly<Connection>, frame: Frame): Promise<void>;
|
|
80
96
|
/** See routeRelayedDataFrame. An arrow property, so the transport can hand it to the hub session as a callback. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-frame-routing.d.ts","sourceRoot":"","sources":["../../src/core/data-frame-routing.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,KAAK,EACN,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAEjF,iNAAiN;AACjN,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,uFAAuF;AACvF,MAAM,WAAW,kBAAkB;IACjC,wMAAwM;IACxM,MAAM,EAAE,MAAM,oBAAoB,GAAG,SAAS,CAAC;IAC/C,wOAAwO;IACxO,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxD;AAED,8MAA8M;AAC9M,MAAM,WAAW,cAAc;IAC7B,+HAA+H;IAC/H,KAAK,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC/B,2FAA2F;IAC3F,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,+JAA+J;AAC/J,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM;IACT,KAAK,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC/B,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,KAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,GACA,cAAc,CAKhB;AAED,sRAAsR;AACtR,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC,oBAAoB,CAAC,EACjE,QAAQ,EAAE,CACR,SAAS,EAAE,MAAM,KACd,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,GACjD,kBAAkB,GAAG,SAAS,CAehC;AAED,4yBAA4yB;AAC5yB,wBAAsB,cAAc,CAClC,IAAI,EAAE,QAAQ,CAAC;IACb,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,WAAW,EAAE,eAAe,GAAG,SAAS,CAAC;IACzC,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC;IAClD,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/C,CAAC,EACF,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,EAChC,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"data-frame-routing.d.ts","sourceRoot":"","sources":["../../src/core/data-frame-routing.ts"],"names":[],"mappings":"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"}
|