@kubun/plugin-p2p 0.10.1 → 0.12.0

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.
Files changed (201) hide show
  1. package/lib/context/delegation.js +130 -1
  2. package/lib/context/group.js +1646 -1
  3. package/lib/context/hub.js +151 -1
  4. package/lib/context/join.js +115 -1
  5. package/lib/context/peer.d.ts +92 -0
  6. package/lib/context/peer.js +1216 -0
  7. package/lib/context/require-admin.d.ts +57 -0
  8. package/lib/context/require-admin.js +57 -0
  9. package/lib/context/sync.d.ts +12 -0
  10. package/lib/context/sync.js +252 -1
  11. package/lib/context/types.d.ts +58 -22
  12. package/lib/context/types.js +48 -1
  13. package/lib/groups/access-default-token.d.ts +44 -0
  14. package/lib/groups/access-default-token.js +103 -0
  15. package/lib/groups/admin-roster.d.ts +55 -0
  16. package/lib/groups/admin-roster.js +69 -0
  17. package/lib/groups/anchor-store.d.ts +15 -0
  18. package/lib/groups/anchor-store.js +37 -0
  19. package/lib/groups/app-cursor-store.d.ts +17 -0
  20. package/lib/groups/app-cursor-store.js +34 -0
  21. package/lib/groups/broadcast-codec.js +6 -1
  22. package/lib/groups/broadcast.d.ts +238 -106
  23. package/lib/groups/broadcast.js +702 -1
  24. package/lib/groups/catalog-token.d.ts +50 -0
  25. package/lib/groups/catalog-token.js +96 -0
  26. package/lib/groups/circle-projection.d.ts +90 -0
  27. package/lib/groups/circle-projection.js +202 -0
  28. package/lib/groups/circle-reducers.d.ts +139 -0
  29. package/lib/groups/circle-reducers.js +128 -0
  30. package/lib/groups/commit-adoption.d.ts +77 -0
  31. package/lib/groups/commit-adoption.js +108 -0
  32. package/lib/groups/commit-journal.d.ts +14 -0
  33. package/lib/groups/commit-journal.js +65 -0
  34. package/lib/groups/control-request.d.ts +66 -0
  35. package/lib/groups/control-request.js +101 -0
  36. package/lib/groups/events.d.ts +19 -2
  37. package/lib/groups/events.js +10 -1
  38. package/lib/groups/group-anchor.d.ts +24 -0
  39. package/lib/groups/group-anchor.js +22 -0
  40. package/lib/groups/group-crypto.d.ts +42 -0
  41. package/lib/groups/group-crypto.js +159 -0
  42. package/lib/groups/group-handle-registry.d.ts +138 -9
  43. package/lib/groups/group-handle-registry.js +533 -1
  44. package/lib/groups/group-handlers.d.ts +30 -0
  45. package/lib/groups/group-handlers.js +218 -0
  46. package/lib/groups/group-health-monitor.d.ts +11 -0
  47. package/lib/groups/group-health-monitor.js +139 -1
  48. package/lib/groups/group-mls.d.ts +66 -0
  49. package/lib/groups/group-mls.js +696 -0
  50. package/lib/groups/group-peer-manager.d.ts +301 -0
  51. package/lib/groups/group-peer-manager.js +1336 -0
  52. package/lib/groups/group-protocols.d.ts +754 -0
  53. package/lib/groups/group-protocols.js +448 -0
  54. package/lib/groups/invite-payload.d.ts +49 -1
  55. package/lib/groups/invite-payload.js +26 -1
  56. package/lib/groups/join-request-identity.d.ts +21 -0
  57. package/lib/groups/join-request-identity.js +43 -0
  58. package/lib/groups/join-utils.d.ts +61 -0
  59. package/lib/groups/join-utils.js +366 -1
  60. package/lib/groups/ledger-affected-events.d.ts +20 -0
  61. package/lib/groups/ledger-affected-events.js +85 -0
  62. package/lib/groups/ledger-commit-fold.d.ts +107 -0
  63. package/lib/groups/ledger-commit-fold.js +167 -0
  64. package/lib/groups/ledger-ingest.d.ts +124 -0
  65. package/lib/groups/ledger-ingest.js +212 -0
  66. package/lib/groups/ledger.d.ts +44 -0
  67. package/lib/groups/ledger.js +30 -0
  68. package/lib/groups/manager.d.ts +217 -85
  69. package/lib/groups/manager.js +798 -1
  70. package/lib/groups/mls-codec.d.ts +28 -7
  71. package/lib/groups/mls-codec.js +33 -1
  72. package/lib/groups/mls-encryptor.d.ts +2 -2
  73. package/lib/groups/mls-encryptor.js +33 -1
  74. package/lib/groups/mls-group-handle.d.ts +37 -2
  75. package/lib/groups/mls-group-handle.js +18 -1
  76. package/lib/groups/mls-json.js +17 -1
  77. package/lib/groups/mls-receive-errors.d.ts +27 -0
  78. package/lib/groups/mls-receive-errors.js +39 -0
  79. package/lib/groups/mls-state.d.ts +6 -4
  80. package/lib/groups/mls-state.js +79 -1
  81. package/lib/groups/peer-presence.d.ts +90 -0
  82. package/lib/groups/peer-presence.js +295 -0
  83. package/lib/groups/peer-selection.d.ts +37 -0
  84. package/lib/groups/peer-selection.js +72 -0
  85. package/lib/groups/roster-projection.d.ts +53 -0
  86. package/lib/groups/roster-projection.js +65 -0
  87. package/lib/groups/store-received-grant.d.ts +7 -3
  88. package/lib/groups/store-received-grant.js +161 -1
  89. package/lib/groups/store-received-revocation.d.ts +19 -16
  90. package/lib/groups/store-received-revocation.js +83 -1
  91. package/lib/hub/ack-backoff.d.ts +22 -0
  92. package/lib/hub/ack-backoff.js +88 -0
  93. package/lib/hub/http-client.d.ts +18 -10
  94. package/lib/hub/http-client.js +15 -1
  95. package/lib/hub/hub-like.d.ts +75 -0
  96. package/lib/hub/hub-like.js +1022 -0
  97. package/lib/hub/loopback-log-hub.d.ts +20 -0
  98. package/lib/hub/loopback-log-hub.js +178 -0
  99. package/lib/hub/manager.d.ts +25 -40
  100. package/lib/hub/manager.js +155 -1
  101. package/lib/hub/peer-scoped-hub-view.d.ts +35 -0
  102. package/lib/hub/peer-scoped-hub-view.js +92 -0
  103. package/lib/hub/sender-scoped-hub-view.d.ts +41 -0
  104. package/lib/hub/sender-scoped-hub-view.js +59 -0
  105. package/lib/hub/server-did.d.ts +67 -0
  106. package/lib/hub/server-did.js +131 -0
  107. package/lib/hub/wiring.d.ts +77 -51
  108. package/lib/hub/wiring.js +189 -1
  109. package/lib/index.d.ts +58 -22
  110. package/lib/index.js +563 -1
  111. package/lib/peer/connection-registry.d.ts +45 -0
  112. package/lib/peer/connection-registry.js +52 -0
  113. package/lib/peer/handlers.d.ts +69 -0
  114. package/lib/peer/handlers.js +110 -0
  115. package/lib/protocol.d.ts +214 -1
  116. package/lib/protocol.js +519 -1
  117. package/lib/schema.d.ts +3 -1
  118. package/lib/schema.js +1150 -39
  119. package/lib/sync/access-default-sender.d.ts +23 -0
  120. package/lib/sync/access-default-sender.js +80 -0
  121. package/lib/sync/authorize.d.ts +58 -4
  122. package/lib/sync/authorize.js +114 -1
  123. package/lib/sync/broadcast-queue.d.ts +3 -4
  124. package/lib/sync/broadcast-queue.js +182 -1
  125. package/lib/sync/broadcast-sender.js +179 -1
  126. package/lib/sync/catalog-scope.d.ts +8 -7
  127. package/lib/sync/catalog-scope.js +84 -1
  128. package/lib/sync/errors.d.ts +12 -2
  129. package/lib/sync/errors.js +29 -1
  130. package/lib/sync/forwarder.d.ts +13 -19
  131. package/lib/sync/forwarder.js +271 -1
  132. package/lib/sync/handlers.js +200 -1
  133. package/lib/sync/hub-tunnel-sync-listener.d.ts +19 -5
  134. package/lib/sync/hub-tunnel-sync-listener.js +261 -1
  135. package/lib/sync/hub-tunnel-sync-provider.d.ts +34 -14
  136. package/lib/sync/hub-tunnel-sync-provider.js +113 -1
  137. package/lib/sync/merkle-apply.d.ts +5 -0
  138. package/lib/sync/merkle-apply.js +194 -1
  139. package/lib/sync/merkle-channel.d.ts +11 -3
  140. package/lib/sync/merkle-channel.js +0 -0
  141. package/lib/sync/merkle-tree.js +120 -1
  142. package/lib/sync/peer-registry.d.ts +15 -11
  143. package/lib/sync/peer-registry.js +82 -1
  144. package/lib/sync/receive-access-gate.js +24 -1
  145. package/lib/sync/scope-resolver.js +41 -1
  146. package/lib/sync/sync-client.d.ts +14 -4
  147. package/lib/sync/sync-client.js +254 -1
  148. package/lib/sync/sync-manager.d.ts +24 -6
  149. package/lib/sync/sync-manager.js +301 -1
  150. package/lib/sync/tunnel-listeners.d.ts +52 -0
  151. package/lib/sync/tunnel-listeners.js +175 -0
  152. package/lib/sync/tunnel-observability.d.ts +25 -0
  153. package/lib/sync/tunnel-observability.js +63 -0
  154. package/lib/sync/tunnel-topics.d.ts +20 -0
  155. package/lib/sync/tunnel-topics.js +28 -0
  156. package/lib/types.d.ts +704 -22
  157. package/lib/types.js +1 -1
  158. package/lib/util/handler-error.d.ts +16 -0
  159. package/lib/util/handler-error.js +64 -0
  160. package/lib/util/mutex.d.ts +14 -1
  161. package/lib/util/mutex.js +44 -1
  162. package/lib/utils.js +21 -1
  163. package/package.json +58 -47
  164. package/lib/groups/broadcast-service.d.ts +0 -263
  165. package/lib/groups/broadcast-service.js +0 -1
  166. package/lib/groups/rejoin-codec.d.ts +0 -14
  167. package/lib/groups/rejoin-codec.js +0 -1
  168. package/lib/groups/wire-frame.d.ts +0 -34
  169. package/lib/groups/wire-frame.js +0 -1
  170. package/lib/hub/circle-catchup-requester.d.ts +0 -58
  171. package/lib/hub/circle-catchup-requester.js +0 -1
  172. package/lib/hub/circle-catchup-responder.d.ts +0 -50
  173. package/lib/hub/circle-catchup-responder.js +0 -1
  174. package/lib/hub/connection-pool.d.ts +0 -43
  175. package/lib/hub/connection-pool.js +0 -1
  176. package/lib/hub/did-observing-transport.d.ts +0 -64
  177. package/lib/hub/did-observing-transport.js +0 -1
  178. package/lib/hub/epoch-stale-detector.d.ts +0 -18
  179. package/lib/hub/epoch-stale-detector.js +0 -1
  180. package/lib/hub/errors.d.ts +0 -30
  181. package/lib/hub/errors.js +0 -1
  182. package/lib/hub/forward-remote-broadcast.d.ts +0 -15
  183. package/lib/hub/forward-remote-broadcast.js +0 -1
  184. package/lib/hub/group-channel.d.ts +0 -89
  185. package/lib/hub/group-channel.js +0 -1
  186. package/lib/hub/hub-connection.d.ts +0 -96
  187. package/lib/hub/hub-connection.js +0 -1
  188. package/lib/hub/receive-handler.d.ts +0 -51
  189. package/lib/hub/receive-handler.js +0 -1
  190. package/lib/hub/rejoin-manager.d.ts +0 -78
  191. package/lib/hub/rejoin-manager.js +0 -1
  192. package/lib/hub/rejoin-responder.d.ts +0 -32
  193. package/lib/hub/rejoin-responder.js +0 -1
  194. package/lib/hub/relay-manager.d.ts +0 -142
  195. package/lib/hub/relay-manager.js +0 -1
  196. package/lib/hub/send-handler.d.ts +0 -40
  197. package/lib/hub/send-handler.js +0 -1
  198. package/lib/hub/tunnel-inbox.d.ts +0 -20
  199. package/lib/hub/tunnel-inbox.js +0 -1
  200. package/lib/hub/wait-for-gate.d.ts +0 -14
  201. package/lib/hub/wait-for-gate.js +0 -1
@@ -0,0 +1,301 @@
1
+ import type { ProcedureHandlers } from '@enkaku/server';
2
+ import type { OwnIdentity } from '@kokuin/token';
3
+ import type { StoreProvider } from '@kubun/db';
4
+ import type { DefaultAccessLevel, GraphInternals } from '@kubun/engine';
5
+ import type { HLC } from '@kubun/hlc';
6
+ import type { Logger } from '@kubun/logger';
7
+ import type { GraphStoreAPI } from '@kubun/store-graph';
8
+ import { type GroupPeer, type LaneResult, type PendingCommit } from '@kumiai/rpc';
9
+ import type { Runtime } from '@sozai/runtime';
10
+ import type { CreateHubClient } from '../hub/http-client.js';
11
+ import { type DeviceHub, type ReconnectingDeviceHub } from '../hub/hub-like.js';
12
+ import type { SyncProtocol } from '../protocol.js';
13
+ import type { ForwardingConfig } from '../sync/forwarder.js';
14
+ import type { LedgerCatchupOptions, LedgerCatchupSummary, RejoinResult, StoreUnreadableMode } from '../types.js';
15
+ import type { GroupBroadcastMessage } from './broadcast.js';
16
+ import { type SettleLostControlRequestDeps } from './commit-adoption.js';
17
+ import type { P2PEventEmitter } from './events.js';
18
+ import type { GroupHandleRegistry } from './group-handle-registry.js';
19
+ import { type GroupProtocols } from './group-protocols.js';
20
+ import { type PeerPresence } from './peer-presence.js';
21
+ /**
22
+ * Rebuild a fresh `ledger` commit carrying the given signed tokens, to re-drive
23
+ * a lost one under its original request id.
24
+ *
25
+ * A narrow capability, NOT the whole group manager: the lane may only ask for
26
+ * exactly this — a build closure over surviving ledger tokens — so it stays a
27
+ * consumer of the ledger write path, never its owner. Wired from
28
+ * `GroupManager.buildEnactLedgerCommit`. `requestID` is absent when the lost
29
+ * commit journalled none: the tokens are still the work and are re-driven, but
30
+ * the rebuilt commit settles nothing rather than settling a fabricated id.
31
+ */
32
+ export type BuildLedgerRedrive = (groupID: string, tokens: Array<string>, requestID?: string) => () => Promise<PendingCommit>;
33
+ export type GroupPeerManagerParams = {
34
+ /**
35
+ * Spawns a fresh `Client<HubProtocol>` for a hub URL. The manager wraps each
36
+ * URL's client in one reconnecting {@link createHubLike} (a single device
37
+ * receive drain), lazily on first peer creation for that hub.
38
+ */
39
+ createHubClient: CreateHubClient;
40
+ /**
41
+ * Rebuilds a lost `ledger` commit's surviving tokens into a fresh commit under
42
+ * the original request id, for the seam to re-drive once. Narrow by design —
43
+ * see {@link BuildLedgerRedrive}.
44
+ */
45
+ buildLedgerRedrive: BuildLedgerRedrive;
46
+ /** Single canonical access point for the device's MLS `GroupHandle` instances. */
47
+ registry: GroupHandleRegistry;
48
+ /**
49
+ * Store coordinator. Resolves the device's p2p store for the apply path,
50
+ * group↔hub binding reads, and the hub-DID cache; also passed to
51
+ * `createGroupMLS` for the receive-side commit transaction.
52
+ */
53
+ stores: StoreProvider;
54
+ graphStore: GraphStoreAPI;
55
+ /**
56
+ * Engine graph internals — threaded into the apply path so a `sync/mutationApply`
57
+ * frame routes peer-authored mutations through `applyVerifiedMutation` with
58
+ * `origin: 'peer'`.
59
+ */
60
+ graph: GraphInternals;
61
+ /** Device-wide monotonic clock shared with the engine and MLS receive path. */
62
+ hlc: HLC;
63
+ /** Authenticated DID of this device (normalized). */
64
+ localDID: string;
65
+ /**
66
+ * The device's own signing identity, forwarded to each peer's `GroupMLS` for
67
+ * the recovery members alone — the only lane work that must sign without a
68
+ * request behind it to take a key from.
69
+ */
70
+ identity: OwnIdentity;
71
+ emitter: P2PEventEmitter;
72
+ /**
73
+ * Host runtime; forwarded to each peer when set, which sources its fresh
74
+ * group-rpc correlation ids from it.
75
+ */
76
+ runtime?: Runtime;
77
+ logger?: Logger;
78
+ /** Receive-side storage mode. Forwarded to the apply path. Defaults to `'persist'`. */
79
+ storeUnreadable?: StoreUnreadableMode;
80
+ /** Server default access level — required when `storeUnreadable === 'drop'`. */
81
+ defaultAccessLevel?: DefaultAccessLevel;
82
+ /**
83
+ * Per-peer N+1 re-broadcast config for the apply path. Omitted or `false`
84
+ * skips the pipeline.
85
+ */
86
+ forwarding?: ForwardingConfig;
87
+ /**
88
+ * Hub hook a forward re-broadcasts through. The apply path gates on this AND
89
+ * `forwarding`, so supplying one alone leaves forwarding off.
90
+ */
91
+ scheduleBroadcast?: (groupID: string, message: GroupBroadcastMessage) => void | Promise<void>;
92
+ /**
93
+ * Reconnect-backoff overrides for every hub adapter this manager spawns. Only
94
+ * a test harness sets this — production runs on the adapter's defaults. Each
95
+ * field is forwarded verbatim to {@link createHubLike}.
96
+ */
97
+ hubReconnectBackoff?: {
98
+ baseMs?: number;
99
+ maxMs?: number;
100
+ jitter?: number;
101
+ };
102
+ /**
103
+ * Sync procedures served to a co-member that dials in over a hub tunnel. The
104
+ * same handlers the direct and HTTP transports serve — a tunnel is a route,
105
+ * so it must not reach a different implementation.
106
+ *
107
+ * Omitted, the device answers no tunnel session: a caller that has not built
108
+ * handlers has no sync surface to expose.
109
+ */
110
+ syncHandlers?: ProcedureHandlers<SyncProtocol>;
111
+ /** @see TunnelListenersParams.idleTimeoutMs */
112
+ tunnelIdleTimeoutMs?: number;
113
+ };
114
+ /**
115
+ * Coordinates the per-(group, hub) `GroupPeer`s for one device — full multi-hub.
116
+ *
117
+ * The manager owns one reconnecting `HubLike` per hub URL (created lazily on
118
+ * first use, shared across every group bound to that hub via the multi-subscriber
119
+ * adapter) and one `GroupPeer` per (group, hub) pair. A peer exists iff the group
120
+ * is joined AND bound to that hub. Lifecycle mirrors the old `HubRelayManager`,
121
+ * but per (group, hub) instead of single-hub: the wiring phase drives `addGroup`
122
+ * / `removeGroup` / `addBinding` / `removeBinding` from the emitter and holds the
123
+ * unsubscribes. The manager does not subscribe to the emitter itself.
124
+ */
125
+ export type GroupPeerManager = {
126
+ /** Bring up peers for each already-bound hub of each joined group. */
127
+ start: (groupIDs: Array<string>) => Promise<void>;
128
+ /** Mark a group joined and create a peer for each of its hub bindings. */
129
+ addGroup: (groupID: string) => Promise<void>;
130
+ /** Unmark a group and dispose all its peers (GC-ing now-idle hubs). */
131
+ removeGroup: (groupID: string) => Promise<void>;
132
+ /** Create the (group, hub) peer if the group is joined and none exists yet. */
133
+ addBinding: (groupID: string, hubURL: string) => Promise<void>;
134
+ /** Dispose the (group, hub) peer if present, GC-ing the hub if now idle. */
135
+ removeBinding: (groupID: string, hubURL: string) => Promise<void>;
136
+ /**
137
+ * Re-derive the group's tunnel listeners from its current roster.
138
+ *
139
+ * Driven by the membership projection rather than only by the epoch, because
140
+ * the epoch advances INSIDE the transaction that writes the new member: a
141
+ * reconcile scheduled there can read the roster as it was and stand up no
142
+ * listener for the device just admitted.
143
+ */
144
+ reconcileTunnelListeners: (groupID: string) => Promise<void>;
145
+ /** Fan a broadcast message out across every hub-peer of a group. */
146
+ broadcast: (groupID: string, message: GroupBroadcastMessage) => Promise<void>;
147
+ /**
148
+ * This device's presence on the peer lane: what it advertises, and who it asks.
149
+ * The manager owns it because every internal trigger fires from here — a hub
150
+ * connect, an epoch rotation, a pruned app window — and because a gather needs
151
+ * the group's live peers.
152
+ */
153
+ presence: PeerPresence;
154
+ /**
155
+ * The peer for the group's canonical commit hub — the single hub a group
156
+ * commits through. Resolves the designated commit hub; falls back to the live
157
+ * peer whose hub URL sorts first for a legacy group with no designation (and
158
+ * warns), then to the group's loopback peer when it has no hub-backed peer at
159
+ * all. `undefined` only when the group has no lane whatsoever.
160
+ */
161
+ selectCommitPeer: (groupID: string) => Promise<GroupPeer<GroupProtocols> | undefined>;
162
+ /**
163
+ * Drive a commit through the group's canonical commit hub: build against the
164
+ * live handle, publish to that hub's commit log, adopt only on acceptance.
165
+ * Throws when the group has no live commit peer.
166
+ */
167
+ commit: (groupID: string, build: () => Promise<PendingCommit>) => Promise<LaneResult>;
168
+ /**
169
+ * Deep recovery: rejoin a peer the group left behind, via `GroupPeer.recover()`
170
+ * on the group's canonical commit hub. The peer requests a member's sealed
171
+ * GroupInfo over the non-rotating rendezvous topic, publishes the external
172
+ * commit under a head compare-and-set, and bootstraps the ledger — reissuing
173
+ * any tokens the authenticated ledger lacked. Reports `recovered` once the
174
+ * rejoin landed, or `recovery-failed` (without throwing) when no live responder
175
+ * answers or the group has no lane.
176
+ */
177
+ rejoinGroup: (groupID: string) => Promise<RejoinResult>;
178
+ /**
179
+ * Gather the group's control ledger from its current members and adopt it
180
+ * locally. Sends a `control/ledgerCatchup` request on every live hub-peer of
181
+ * the group; each responder returns its WHOLE ledger in enactment order, and
182
+ * the first list that reproduces this device's authenticated head is installed
183
+ * — a responder that withholds or reorders entries is dropped, not merged. A
184
+ * drifted joiner thus backfills what its invite snapshot missed, or gets
185
+ * nothing. Returns what landed; a no-op summary when the group has no live
186
+ * peer or every responder was refused.
187
+ */
188
+ requestLedgerCatchup: (groupID: string, options?: LedgerCatchupOptions) => Promise<LedgerCatchupSummary>;
189
+ /**
190
+ * Ask co-members to restate their own model access-defaults, and apply what is
191
+ * newer than what this device holds. Returns how many rules landed.
192
+ */
193
+ requestPolicyCatchup: (groupID: string) => Promise<number>;
194
+ /** The peer for one (group, hub), or `undefined` (used by tests). */
195
+ peer: (groupID: string, hubURL: string) => GroupPeer<GroupProtocols> | undefined;
196
+ /**
197
+ * The shared reconnecting `HubLike` for a hub URL, creating it on first use.
198
+ * Lets a caller obtain the device-wide drain to pass into a directed sync
199
+ * transport (provider/listener) sharing the same hub connection.
200
+ */
201
+ getHubLike: (hubURL: string) => ReconnectingDeviceHub;
202
+ /**
203
+ * The device-wide drain a directed session to this group should ride, or
204
+ * `undefined` when the group has no live hub binding — which is what a caller
205
+ * building a tunnel needs to know before it builds one.
206
+ *
207
+ * The group's first binding. A second hub is a second route to the same
208
+ * mailbox, not a different peer, so choosing between them is a preference
209
+ * nothing here holds.
210
+ */
211
+ tunnelHub: (groupID: string) => DeviceHub | undefined;
212
+ /**
213
+ * Try every hub this device holds now, rather than when each one's backoff
214
+ * says so, and answer with whether any of them is connected afterwards.
215
+ */
216
+ retryHubs: () => Promise<boolean>;
217
+ /** Dispose every peer and hub, then clear all maps. */
218
+ stop: () => Promise<void>;
219
+ /** Alias for {@link stop}. */
220
+ dispose: () => Promise<void>;
221
+ };
222
+ /**
223
+ * Send-side union → procedure mapping — the inverse of `buildGroupHandlers`.
224
+ *
225
+ * Translates a {@link GroupBroadcastMessage} into the matching group-rpc
226
+ * `dispatch` on a peer's control/sync protocol surface. Variants with no carried
227
+ * procedure (catalog control) are logged and no-op'd, matching the receive side.
228
+ */
229
+ export declare function dispatchMessage(peer: GroupPeer<GroupProtocols>, message: GroupBroadcastMessage, logger?: Logger): Promise<void>;
230
+ /**
231
+ * Run one lane operation, retrying only while the peer's runtimes are mid-rebuild.
232
+ *
233
+ * Safe to retry because the throw happens BEFORE anything is sealed or published:
234
+ * `surfaceFor` is what fails, so a retry cannot duplicate a frame. Every other
235
+ * failure — a refused publish, an unrouted message type — propagates on the first
236
+ * attempt, which is what keeps this from papering over a real fault.
237
+ */
238
+ export declare function throughRotation<T>(op: () => Promise<T>, label: string, logger?: Logger): Promise<T>;
239
+ /**
240
+ * Everything the seam needs to act on a lost commit: the settle deps it shares
241
+ * with {@link settleLostControlRequest}, plus what a lost `ledger` re-drive
242
+ * takes — the group whose ledger is read for the never-re-append filter, the
243
+ * registry that read runs through, and the narrow builder that rebuilds a
244
+ * surviving-token commit.
245
+ */
246
+ export type CommitThroughPeerDeps = SettleLostControlRequestDeps & {
247
+ groupID: string;
248
+ /** Reads the group's current ledger tokens for the never-re-append filter. */
249
+ registry: Pick<GroupHandleRegistry, 'readHandle'>;
250
+ buildLedgerRedrive: BuildLedgerRedrive;
251
+ };
252
+ /**
253
+ * Publish a commit through the peer and act on what the lane hands back.
254
+ *
255
+ * A `LaneResult` can carry both a `lost` and a `reenact`; handle each
256
+ * independently. A lost `ledger` is re-issuable from its tokens, an `invite` or
257
+ * `remove` is not, so those settle `lost` here.
258
+ *
259
+ * The housekeeping is CONTAINED — never let it throw. By the time it runs THIS
260
+ * commit has landed and its request is settled, while `lost` and `reenact` name
261
+ * other work; an escaping throw would have the producer's per-request catch
262
+ * settle the terminal request `rejected`, writing a failure over a success and
263
+ * nulling the artifact for a member who really was added. That covers
264
+ * `RecoveryRequiredError` too: reaching {@link commitWithRecovery} would re-run
265
+ * the ORIGINAL `build` after its commit landed, publishing a second copy outside
266
+ * the never-re-append filter.
267
+ */
268
+ export declare function commitThroughPeer(peer: Pick<GroupPeer<GroupProtocols>, 'commit'>, build: () => Promise<PendingCommit>, deps: CommitThroughPeerDeps): Promise<LaneResult>;
269
+ export type CommitWithRecoveryParams = {
270
+ peer: Pick<GroupPeer<GroupProtocols>, 'commit' | 'recover'>;
271
+ build: () => Promise<PendingCommit>;
272
+ deps: CommitThroughPeerDeps;
273
+ /** Repair an incomplete ledger, the cheaper of the two remedies. */
274
+ gatherLedger: () => Promise<unknown>;
275
+ };
276
+ /**
277
+ * Publish a commit and, on the lane's stranded/incomplete-ledger gate, self-heal.
278
+ *
279
+ * The gate conflates an incomplete ledger — repaired by a plain ledger GATHER —
280
+ * with a true strand, repaired only by a full rejoin via `recover()`, so the
281
+ * cheaper remedy runs first: gather + retry once, then `recover()` + retry once,
282
+ * then propagate. Each remedy runs AT MOST ONCE (≤3 commit attempts): upstream
283
+ * forbids a tight retry loop, and `recover()` already bounds itself with its own
284
+ * deadline loop. When `recover()` cannot advance, rethrow the ORIGINAL gate error
285
+ * so the caller settles against the real cause. The retry carries the original
286
+ * `requestID`, so a healed commit settles `committed` through its own
287
+ * `onAccepted` rather than surfacing as a failure.
288
+ */
289
+ export declare function commitWithRecovery(params: CommitWithRecoveryParams): Promise<LaneResult>;
290
+ /**
291
+ * Rejoin the group through `GroupPeer.recover()` and map its outcome to a
292
+ * {@link RejoinResult}. `recover()` publishes the external commit under a head
293
+ * compare-and-set and bootstraps the ledger; it bounds itself, so it is never
294
+ * wrapped in a loop. Any `reenact` tokens it hands back — held here but absent
295
+ * from the authenticated ledger after the rejoin — are re-issued through the
296
+ * same {@link reissueLedgerTokens} filter every lane outcome uses. `advanced`
297
+ * maps to `recovered`; a peer that could not advance (no live responder) maps to
298
+ * `recovery-failed` without throwing.
299
+ */
300
+ export declare function recoverThroughPeer(peer: Pick<GroupPeer<GroupProtocols>, 'commit' | 'recover'>, deps: CommitThroughPeerDeps): Promise<RejoinResult>;
301
+ export declare function createGroupPeerManager(params: GroupPeerManagerParams): GroupPeerManager;