@statewalker/httpeers-member 0.1.4

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -0
  3. package/dist/browser-platform.d.ts +30 -0
  4. package/dist/browser-platform.d.ts.map +1 -0
  5. package/dist/browser-platform.js +30 -0
  6. package/dist/browser-profile.d.ts +85 -0
  7. package/dist/browser-profile.d.ts.map +1 -0
  8. package/dist/browser-profile.js +120 -0
  9. package/dist/browser.d.ts +48 -0
  10. package/dist/browser.d.ts.map +1 -0
  11. package/dist/browser.js +51 -0
  12. package/dist/connection-kind.d.ts +36 -0
  13. package/dist/connection-kind.d.ts.map +1 -0
  14. package/dist/connection-kind.js +52 -0
  15. package/dist/describe-error.d.ts +18 -0
  16. package/dist/describe-error.d.ts.map +1 -0
  17. package/dist/describe-error.js +72 -0
  18. package/dist/edge-control.d.ts +50 -0
  19. package/dist/edge-control.d.ts.map +1 -0
  20. package/dist/edge-control.js +69 -0
  21. package/dist/edge-dispatch.d.ts +188 -0
  22. package/dist/edge-dispatch.d.ts.map +1 -0
  23. package/dist/edge-dispatch.js +142 -0
  24. package/dist/edge-guard.d.ts +45 -0
  25. package/dist/edge-guard.d.ts.map +1 -0
  26. package/dist/edge-guard.js +62 -0
  27. package/dist/edge.d.ts +97 -0
  28. package/dist/edge.d.ts.map +1 -0
  29. package/dist/edge.js +104 -0
  30. package/dist/gateway.d.ts +49 -0
  31. package/dist/gateway.d.ts.map +1 -0
  32. package/dist/gateway.js +102 -0
  33. package/dist/identity.d.ts +78 -0
  34. package/dist/identity.d.ts.map +1 -0
  35. package/dist/identity.js +117 -0
  36. package/dist/index.d.ts +39 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +37 -0
  39. package/dist/join-blob.d.ts +125 -0
  40. package/dist/join-blob.d.ts.map +1 -0
  41. package/dist/join-blob.js +195 -0
  42. package/dist/join.d.ts +343 -0
  43. package/dist/join.d.ts.map +1 -0
  44. package/dist/join.js +409 -0
  45. package/dist/kv.d.ts +20 -0
  46. package/dist/kv.d.ts.map +1 -0
  47. package/dist/kv.js +10 -0
  48. package/dist/mesh-config.d.ts +26 -0
  49. package/dist/mesh-config.d.ts.map +1 -0
  50. package/dist/mesh-config.js +39 -0
  51. package/dist/mesh-memory.d.ts +55 -0
  52. package/dist/mesh-memory.d.ts.map +1 -0
  53. package/dist/mesh-memory.js +74 -0
  54. package/dist/node.d.ts +29 -0
  55. package/dist/node.d.ts.map +1 -0
  56. package/dist/node.js +42 -0
  57. package/dist/page-wake.d.ts +24 -0
  58. package/dist/page-wake.d.ts.map +1 -0
  59. package/dist/page-wake.js +31 -0
  60. package/dist/peer-request.d.ts +29 -0
  61. package/dist/peer-request.d.ts.map +1 -0
  62. package/dist/peer-request.js +11 -0
  63. package/dist/reset.d.ts +56 -0
  64. package/dist/reset.d.ts.map +1 -0
  65. package/dist/reset.js +103 -0
  66. package/dist/session.d.ts +214 -0
  67. package/dist/session.d.ts.map +1 -0
  68. package/dist/session.js +403 -0
  69. package/dist/start-member.d.ts +176 -0
  70. package/dist/start-member.d.ts.map +1 -0
  71. package/dist/start-member.js +307 -0
  72. package/package.json +120 -0
  73. package/src/browser-platform.ts +53 -0
  74. package/src/browser-profile.ts +179 -0
  75. package/src/browser.ts +103 -0
  76. package/src/connection-kind.ts +53 -0
  77. package/src/describe-error.ts +76 -0
  78. package/src/edge-control.ts +94 -0
  79. package/src/edge-dispatch.ts +295 -0
  80. package/src/edge-guard.ts +67 -0
  81. package/src/edge.ts +175 -0
  82. package/src/gateway.ts +141 -0
  83. package/src/identity.ts +146 -0
  84. package/src/index.ts +95 -0
  85. package/src/join-blob.ts +229 -0
  86. package/src/join.ts +632 -0
  87. package/src/kv.ts +21 -0
  88. package/src/mesh-config.ts +41 -0
  89. package/src/mesh-memory.ts +104 -0
  90. package/src/node.ts +49 -0
  91. package/src/page-wake.ts +59 -0
  92. package/src/peer-request.ts +39 -0
  93. package/src/reset.ts +127 -0
  94. package/src/session.ts +579 -0
  95. package/src/start-member.ts +476 -0
package/dist/join.d.ts ADDED
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Joining the mesh: the `/webrtc` pre-dial, invitation redemption, the
3
+ * membership RESUME probe, and the two timers this runtime owns itself (the
4
+ * third -- circuit-relay's own reservation refresh -- is libp2p-managed;
5
+ * there is no code for it here, on purpose, see `startJoin`'s doc comment).
6
+ *
7
+ * THERE ARE TWO WAYS INTO A MESH, NOT ONE (Task 28). `redeemInvitation` is
8
+ * the first join and can only ever happen once per invitation -- the id is
9
+ * moved to `spentInvitationIds` on redemption and the spent check runs
10
+ * first, unconditionally (`../hub/hub-state.ts`). A page that persists its
11
+ * identity and reloads is therefore NOT making a first join: it is already
12
+ * a member, and redeeming again would fail `already-redeemed` forever.
13
+ * `resumeMembership` below is the other way in, and it needs no new hub
14
+ * route because the hub already has one that answers exactly this question
15
+ * -- see that function.
16
+ */
17
+ import type { Libp2p } from "@libp2p/interface";
18
+ import type { RevocationCache, RuleSet } from "@statewalker/httpeers-access";
19
+ import type { MeshView, PeerIdStr } from "@statewalker/httpeers-core";
20
+ import type { Peer } from "@statewalker/httpeers-libp2p";
21
+ /**
22
+ * Dial `${relayAddr}/p2p-circuit/webrtc/p2p/${peerId}` explicitly, BEFORE
23
+ * opening any protocol against `peerId` (design note's Step 2; applies to
24
+ * the hub exactly as it does to any other peer -- spec §7, the hub
25
+ * declares no listen address of its own).
26
+ *
27
+ * WHY THIS IS NOT OPTIONAL. libp2p's auto-dial may already hold a
28
+ * relay-only LIMITED connection to `peerId` -- reachable, but not upgraded
29
+ * to WebRTC -- from nothing more than address exchange via `identify`.
30
+ * libp2p SILENTLY refuses to open a custom protocol (`/httpeers/1.0.0`)
31
+ * over a limited connection: the dial simply never completes, with no
32
+ * error naming a limited connection as the cause. Explicitly dialling the
33
+ * full `/webrtc/p2p/...` address forces the WebRTC upgrade before any
34
+ * `peer.call` is attempted, so that failure mode never has a chance to
35
+ * occur.
36
+ */
37
+ export declare function preDialPeer(node: Libp2p, relayAddr: string, peerId: PeerIdStr): Promise<void>;
38
+ export interface RouteEnsurerInit {
39
+ node: Libp2p;
40
+ /** `httpeers.json`'s `relayAddrs[0]` -- the fallback address composer, and the same string `preDialPeer` takes. */
41
+ relayAddr: string;
42
+ /** This peer's own id. A request addressed to it is served locally and must never be dialed. */
43
+ selfPeerId: PeerIdStr;
44
+ /** The current mesh view -- `JoinHandle.meshView`. Read per call, never snapshotted: a provider's addresses change when it re-reserves. */
45
+ meshView: () => MeshView | null;
46
+ /**
47
+ * This mesh's hub. When given -- on a member page -- every other member is
48
+ * reached THROUGH it (`../hub-link.ts`'s `hubRoute`), and what members
49
+ * advertise is ignored: since members reserve on their hub rather than on
50
+ * the public relay, their own addresses are double-circuit ones nothing
51
+ * can dial. Omitted on the hub page, which cannot relay through itself
52
+ * and reaches its members over the connections they already hold to it.
53
+ */
54
+ hubPeerId?: PeerIdStr;
55
+ }
56
+ /**
57
+ * "Make sure this peer can be called" -- the function
58
+ * `../browser/edge-dispatch.ts`'s `ensureRoute` hook wants, and the piece
59
+ * that was missing for browser-to-browser calls entirely (Task 15; see that
60
+ * module's job 4 for the symptom and the diagnosis).
61
+ *
62
+ * ADDRESSES COME FROM THE MESH VIEW, WHICH IS THE CONTRACT
63
+ * `../browser/peer-runtime.ts`'s module comment already stated and nothing
64
+ * had yet had to honour: the hub builds each member's `addrs` from that
65
+ * member's own most recent heartbeat, so it is the freshest source there
66
+ * is, and libp2p's peerStore -- what `remote()` falls back on when it dials
67
+ * by bare peer id -- is exactly the stale/absent one that comment warns
68
+ * about.
69
+ *
70
+ * ONLY THE `/webrtc` ENTRIES ARE DIALED. The same view also carries bare
71
+ * `/p2p-circuit` addresses for every member; connecting over one of those
72
+ * produces a LIMITED connection, on which libp2p silently refuses to open
73
+ * `/httpeers/1.0.0` (`preDialPeer`'s own comment, and Task 14's test that
74
+ * pins the refusal). Dialing them would therefore "succeed" and leave the
75
+ * call to fail anyway.
76
+ *
77
+ * THE COMPOSED ADDRESS IS THE FALLBACK, NOT THE PRIMARY. `preDialPeer`'s
78
+ * `<relay>/p2p-circuit/webrtc/p2p/<peer>` is right whenever every peer
79
+ * reserves on the one relay `httpeers.json` names -- true of this
80
+ * deployment, and how the hub itself is reached at startup, since the hub
81
+ * is not a mesh MEMBER and so never appears in the view at all. It is the
82
+ * fallback rather than the rule because a peer that reserved on a different
83
+ * relay is reachable only at the address it reported.
84
+ *
85
+ * THE HUB ITSELF IS NEVER DIALED HERE. `hubRoute(hub, hub)` routes the hub
86
+ * through itself, which cannot work; and a member on the relay fallback holds
87
+ * only a limited circuit to the hub, so without this every edge call to the
88
+ * hub would pay a doomed dial -- up to libp2p's dial timeout -- first. The
89
+ * hub link is `startMember`'s and the keepalive's to keep.
90
+ *
91
+ * AN EXISTING UNLIMITED CONNECTION SHORT-CIRCUITS. This runs on every
92
+ * outbound mesh call, including every `<img src>` in a gallery; re-dialing
93
+ * a peer that is already connected would add a round trip per image.
94
+ */
95
+ export declare function createRouteEnsurer(init: RouteEnsurerInit): (peerId: PeerIdStr) => Promise<void>;
96
+ interface InviteRedeemResponse {
97
+ token: string;
98
+ mesh: string;
99
+ roles: string[];
100
+ }
101
+ /** Redeem `invitationId` against the hub -- `POST /.well-known/invite`, `../hub/endpoints.ts`'s bootstrap handler. No token exists yet: this call is proven by the transport handshake alone. */
102
+ export declare function redeemInvitation(peer: Peer, hubPeerId: PeerIdStr, invitationId: string): Promise<InviteRedeemResponse>;
103
+ /** This peer's own advertisement, as carried on the heartbeat body -- `../hub/endpoints.ts`'s `PresenceBody.advertisements`. */
104
+ export interface AdvertisementInput {
105
+ id: string;
106
+ kind: string;
107
+ title: string;
108
+ }
109
+ /**
110
+ * Why a presence write was refused, named rather than left as a status
111
+ * code. Three outcomes, and they call for three different things on screen.
112
+ *
113
+ * `not-a-member` -- HTTP 403, `../hub/endpoints.ts`'s presence handler
114
+ * finding no `MemberRecord` for the transport-proven peer. It means one of:
115
+ * this identity has never joined this mesh, its membership was revoked
116
+ * (`/admin/members/{peerId}`), or the hub's own state was reset. All three
117
+ * are "this hub does not know you"; an invitation is the way back in.
118
+ * NOTE that a REVOKED member also lands here rather than on a token check:
119
+ * `usesTransportIdentity()` makes a presence POST a bootstrap request, so
120
+ * the token it carries is never examined and the revocation cache is never
121
+ * consulted -- membership itself is what the handler looks up.
122
+ *
123
+ * `duplicate-identity` -- HTTP 409 `stale-sequence`, and it is the one
124
+ * genuinely surprising diagnosis in this file, so here is why it is sound.
125
+ * The hub tracks the highest `seq` it ever accepted per peer and refuses
126
+ * anything at or below it (`lastSeqByPeer`, which the TTL sweep
127
+ * deliberately does not clear). This runtime's own sequence numbers are
128
+ * seeded from the wall clock (`nextInitialSeq`) and only ever increase, so
129
+ * NOTHING THIS PAGE HAS EVER SENT can be at or below the number it is
130
+ * sending now -- not an earlier beat, not an earlier page load, not a
131
+ * delayed duplicate of either. A 409 therefore means some OTHER live node
132
+ * posted a heartbeat under this peerId, which is to say two libp2p nodes
133
+ * are running one identity: two tabs of the same origin is the ordinary
134
+ * way to get there. That is a real failure (two nodes racing to be "the"
135
+ * peer for one id -- `./identity.ts`'s own note) and not a cosmetic one, so
136
+ * it is reported rather than retried into.
137
+ *
138
+ * `refused` -- anything else, carried verbatim for the page to render.
139
+ */
140
+ export type PresenceRefusal = {
141
+ kind: "not-a-member";
142
+ status: number;
143
+ message: string;
144
+ } | {
145
+ kind: "duplicate-identity";
146
+ status: number;
147
+ message: string;
148
+ } | {
149
+ kind: "refused";
150
+ status: number;
151
+ message: string;
152
+ };
153
+ /** Turn a refused presence response into one of the three cases above. Pure, so a test can pin the mapping without a hub. */
154
+ export declare function classifyPresenceRefusal(status: number, body: string): PresenceRefusal;
155
+ /**
156
+ * The sequence number a fresh run starts from: THE WALL CLOCK, not zero.
157
+ *
158
+ * THIS IS NOT A STYLE CHOICE, IT IS WHAT MAKES RESUMING POSSIBLE AT ALL.
159
+ * The hub keeps `lastSeqByPeer` for the life of the process and refuses any
160
+ * presence write at or below it (`../hub/endpoints.ts`). A page that
161
+ * persists its identity and starts counting from 1 again after a reload
162
+ * would be refused `stale-sequence` on every beat until it had climbed back
163
+ * past wherever its previous run left off -- minutes of a live, joined page
164
+ * silently failing to report presence, and a mesh view in which it never
165
+ * appears. Seeding from `Date.now()` makes every run start above every
166
+ * previous run's numbers by construction (a run advances its own counter by
167
+ * 1 per beat while the clock advances by thousands), which is also exactly
168
+ * the property `PresenceRefusal`'s duplicate-identity diagnosis rests on.
169
+ *
170
+ * The hub compares numbers and nothing else -- it never reads a seq as a
171
+ * time -- so this borrows the clock's monotonicity without giving the value
172
+ * any meaning it has to keep.
173
+ */
174
+ export declare function nextInitialSeq(): number;
175
+ /** What `resumeMembership` found. */
176
+ export type ResumeOutcome = {
177
+ status: "resumed";
178
+ token: string;
179
+ versions: HeartbeatVersions;
180
+ ttl: number;
181
+ } | {
182
+ status: "refused";
183
+ refusal: PresenceRefusal;
184
+ };
185
+ export interface ResumeMembershipInit {
186
+ peer: Peer;
187
+ hubPeerId: PeerIdStr;
188
+ /** This peer's own current multiaddrs, exactly as a heartbeat reports them -- see `startJoin`. */
189
+ addrs: string[];
190
+ /** This peer's own advertisements. Omitted (not `[]`) when absent: the hub's handler branches on `advertisements !== undefined`, and `[]` WITHDRAWS. */
191
+ advertisements?: AdvertisementInput[];
192
+ /** This probe's sequence number -- `nextInitialSeq()`, and the number `startJoin` must then continue from. */
193
+ seq: number;
194
+ }
195
+ /**
196
+ * "Does this hub still consider me a member?" -- asked, and answered,
197
+ * WITHOUT A TOKEN, and answered by an endpoint that already exists.
198
+ *
199
+ * THE ORDERING TRAP THIS WALKS AROUND. Proving membership normally needs a
200
+ * token, and a token is what joining produces; a page resuming a membership
201
+ * has neither, and every ordinary hub read (`/.well-known/mesh` included)
202
+ * is gated on claims it cannot yet present. But `POST
203
+ * /.well-known/presence` is one of exactly two BOOTSTRAP routes
204
+ * (`usesTransportIdentity()` in `../hub/endpoints.ts`): `httpeers.core`'s
205
+ * binding middleware sees it, skips the token check and the access tree
206
+ * entirely, and hands the handler the peer id the libp2p handshake itself
207
+ * proved. That handler then looks the peer up in the member store and
208
+ * either mints a fresh token or answers 403. Which is precisely the
209
+ * question, precisely the proof, and precisely the credential -- so this
210
+ * needs no new route, and adding one would have been adding a second,
211
+ * weaker answer to a question the hub already answers.
212
+ *
213
+ * IT IS ALSO THE FIRST HEARTBEAT, NOT A PROBE BESIDE ONE. The body is an
214
+ * ordinary presence write, so a successful resume has already reported this
215
+ * peer's addresses and advertisements and is already visible in the mesh
216
+ * view -- there is no window where the page is "resumed" but absent. Its
217
+ * `seq` is the one `startJoin` continues from (`JoinInit.initialSeq`).
218
+ *
219
+ * Transport failures are NOT caught here: a call that never reached the hub
220
+ * is a different fact from a hub that answered, and only the caller knows
221
+ * what to say about it (`./peer-runtime.ts` does).
222
+ */
223
+ export declare function resumeMembership(init: ResumeMembershipInit): Promise<ResumeOutcome>;
224
+ /** The three version counters a heartbeat response reports; each gates only its own section. See `startJoin`. */
225
+ export interface HeartbeatVersions {
226
+ mesh: number;
227
+ policy: number;
228
+ rules: number;
229
+ }
230
+ /** How often the presence heartbeat fires -- design note's Step 3, 5 s. */
231
+ export declare const HEARTBEAT_INTERVAL_MS = 5000;
232
+ /**
233
+ * How often the connection-keepalive timer checks the link to the hub.
234
+ * DELIBERATELY SEPARATE from `HEARTBEAT_INTERVAL_MS`: a heartbeat that
235
+ * fails to send says "the request failed," which could be the connection,
236
+ * the hub, or a revoked membership -- it does not by itself diagnose
237
+ * "the underlying libp2p connection to the hub is gone." This timer
238
+ * checks that fact directly (`node.getConnections(hubPeerId)`) and
239
+ * re-runs the `/webrtc` pre-dial when it finds nothing open, independent
240
+ * of whether a heartbeat happens to be in flight at the same moment.
241
+ * Matches the interval the validated p2p-demo prototype uses for the same
242
+ * purpose (`workspaces/webrun-wire/apps/p2p-demo/server-page/main.ts`,
243
+ * "relay link lost; re-dialing").
244
+ */
245
+ export declare const KEEPALIVE_INTERVAL_MS = 10000;
246
+ /**
247
+ * How long a pulled revocation snapshot may go unconfirmed before this
248
+ * peer refuses every token rather than trust one it can no longer vouch
249
+ * for (`RevocationCache`'s own `maxStalenessMs` -- "there is a case that
250
+ * no default is correct and this should be required," `revocation.ts`).
251
+ * Generous relative to `HEARTBEAT_INTERVAL_MS` deliberately: the cache's
252
+ * freshness clock is reset on EVERY successful heartbeat (see
253
+ * `startJoin` below), not only when `versions.policy` actually moves, so
254
+ * this bound is really "how many consecutive heartbeats may fail before
255
+ * this peer stops trusting its own revocation snapshot," not "how often
256
+ * the policy must change." Twelve missed 5 s heartbeats' worth of
257
+ * tolerance before a live peer starts refusing tokens on staleness alone.
258
+ */
259
+ export declare const REVOCATION_MAX_STALENESS_MS = 60000;
260
+ export interface JoinInit {
261
+ peer: Peer;
262
+ node: Libp2p;
263
+ hubPeerId: PeerIdStr;
264
+ relayAddr: string;
265
+ /** The token that got this peer in -- `redeemInvitation`'s, or `resumeMembership`'s. `startJoin` owns rotating it from here on; the heartbeat response mints a fresh one every call. */
266
+ initialToken: string;
267
+ /**
268
+ * The sequence number the FIRST heartbeat continues from -- the one
269
+ * `resumeMembership` already spent, when there was a resume. Defaults to
270
+ * `nextInitialSeq()`; see that function for why the default is the wall
271
+ * clock and not zero, and why passing the probe's own number here (rather
272
+ * than drawing a second one) is what keeps this run's sequence strictly
273
+ * increasing across the join itself.
274
+ */
275
+ initialSeq?: number;
276
+ revocationCache: RevocationCache;
277
+ /** This peer's own advertisements, read fresh on every heartbeat. Defaults to none. */
278
+ advertisements?: () => AdvertisementInput[];
279
+ heartbeatIntervalMs?: number;
280
+ keepaliveIntervalMs?: number;
281
+ /**
282
+ * How the keepalive restores a hub link it found gone. Defaults to
283
+ * `reachHub`. A member on the relay fallback passes its own -- a new kept
284
+ * circuit, and no WebRTC retry -- because `reachHub` would never bring the
285
+ * circuit back, and a retried upgrade would leave relay mode behind.
286
+ */
287
+ relinkHub?: () => Promise<void>;
288
+ /** Fired after each successful heartbeat, whether or not any version moved -- for a caller that wants to observe liveness, not just react to a version bump. */
289
+ onHeartbeat?: (versions: HeartbeatVersions) => void;
290
+ /**
291
+ * Fired when the hub REFUSED a heartbeat -- a membership that went away
292
+ * under a live page, or a second node running this identity. Both are
293
+ * things an operator has to be told rather than left to infer from a page
294
+ * that quietly stops appearing in the mesh; see `PresenceRefusal`.
295
+ * Transport failures do NOT come through here: those are the keepalive
296
+ * timer's business and the next tick retries them.
297
+ */
298
+ onPresenceRefused?: (refusal: PresenceRefusal) => void;
299
+ }
300
+ export interface JoinHandle {
301
+ /** The mesh view as of the last time `versions.mesh` moved -- `null` until the first heartbeat lands. Never fetched more often than that: re-fetching every heartbeat regardless of whether anything changed is exactly the design the version vector replaces. */
302
+ meshView(): MeshView | null;
303
+ /** The mesh's published rule set as of the last time `versions.rules` moved -- `null` until the first heartbeat lands. READ-ONLY in the strict sense (ADR-0016): what it returns influences no decision here or anywhere else; this page's own policy is its own value. */
304
+ rules(): RuleSet | null;
305
+ /**
306
+ * This peer's CURRENT membership token, read at call time.
307
+ *
308
+ * A GETTER, NOT A VALUE, AND THAT IS THE WHOLE POINT. The hub mints a
309
+ * fresh token on every heartbeat response (see `heartbeatOnce` below,
310
+ * `token = body.token`), so the token rotates roughly every
311
+ * `HEARTBEAT_INTERVAL_MS`. Anything that read this once and cached the
312
+ * string would be sending a stale token within seconds; a caller that
313
+ * calls this per outbound request always has the live one. This exists
314
+ * for `edge-dispatch.ts`, which attaches it to requests originating at
315
+ * this peer's own ServiceWorker edge -- see that module for why the PAGE
316
+ * is never handed a token of its own.
317
+ */
318
+ token(): string;
319
+ stop(): void;
320
+ }
321
+ /**
322
+ * Start the presence heartbeat and the connection-keepalive timer over an
323
+ * already-joined peer (post `redeemInvitation`). Fires an immediate
324
+ * heartbeat rather than waiting for the first interval tick, so a caller
325
+ * observing `meshView()` sees a populated view as soon as the network
326
+ * allows rather than up to `heartbeatIntervalMs` later.
327
+ *
328
+ * THREE TIMERS, KEPT APART (design note's Step 3 / note 07 §6). This
329
+ * function owns two of them -- the heartbeat and the keepalive, below.
330
+ * THE THIRD, the reservation on the relay, is NOT started here either:
331
+ * libp2p renews a reservation it holds on its own schedule, and restoring
332
+ * one lost with the relay link -- which libp2p attempts once and then never
333
+ * again -- is `../reservation.ts`'s `superviseRelay`, started by the
334
+ * runtime. The keepalive below is NOT that: it watches the HUB connection,
335
+ * which can stay up over WebRTC after the relay link is gone. Folding
336
+ * either into these two would conflate "is my reservation still valid"
337
+ * with "does the hub still consider me a member" or "is my connection to
338
+ * the hub still open" -- three questions this design keeps separate
339
+ * because they fail independently and mean different things.
340
+ */
341
+ export declare function startJoin(init: JoinInit): JoinHandle;
342
+ export {};
343
+ //# sourceMappingURL=join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../src/join.ts"],"names":[],"mappings":"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"}