@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.
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/browser-platform.d.ts +30 -0
- package/dist/browser-platform.d.ts.map +1 -0
- package/dist/browser-platform.js +30 -0
- package/dist/browser-profile.d.ts +85 -0
- package/dist/browser-profile.d.ts.map +1 -0
- package/dist/browser-profile.js +120 -0
- package/dist/browser.d.ts +48 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +51 -0
- package/dist/connection-kind.d.ts +36 -0
- package/dist/connection-kind.d.ts.map +1 -0
- package/dist/connection-kind.js +52 -0
- package/dist/describe-error.d.ts +18 -0
- package/dist/describe-error.d.ts.map +1 -0
- package/dist/describe-error.js +72 -0
- package/dist/edge-control.d.ts +50 -0
- package/dist/edge-control.d.ts.map +1 -0
- package/dist/edge-control.js +69 -0
- package/dist/edge-dispatch.d.ts +188 -0
- package/dist/edge-dispatch.d.ts.map +1 -0
- package/dist/edge-dispatch.js +142 -0
- package/dist/edge-guard.d.ts +45 -0
- package/dist/edge-guard.d.ts.map +1 -0
- package/dist/edge-guard.js +62 -0
- package/dist/edge.d.ts +97 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +104 -0
- package/dist/gateway.d.ts +49 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +102 -0
- package/dist/identity.d.ts +78 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +117 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/join-blob.d.ts +125 -0
- package/dist/join-blob.d.ts.map +1 -0
- package/dist/join-blob.js +195 -0
- package/dist/join.d.ts +343 -0
- package/dist/join.d.ts.map +1 -0
- package/dist/join.js +409 -0
- package/dist/kv.d.ts +20 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +10 -0
- package/dist/mesh-config.d.ts +26 -0
- package/dist/mesh-config.d.ts.map +1 -0
- package/dist/mesh-config.js +39 -0
- package/dist/mesh-memory.d.ts +55 -0
- package/dist/mesh-memory.d.ts.map +1 -0
- package/dist/mesh-memory.js +74 -0
- package/dist/node.d.ts +29 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +42 -0
- package/dist/page-wake.d.ts +24 -0
- package/dist/page-wake.d.ts.map +1 -0
- package/dist/page-wake.js +31 -0
- package/dist/peer-request.d.ts +29 -0
- package/dist/peer-request.d.ts.map +1 -0
- package/dist/peer-request.js +11 -0
- package/dist/reset.d.ts +56 -0
- package/dist/reset.d.ts.map +1 -0
- package/dist/reset.js +103 -0
- package/dist/session.d.ts +214 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +403 -0
- package/dist/start-member.d.ts +176 -0
- package/dist/start-member.d.ts.map +1 -0
- package/dist/start-member.js +307 -0
- package/package.json +120 -0
- package/src/browser-platform.ts +53 -0
- package/src/browser-profile.ts +179 -0
- package/src/browser.ts +103 -0
- package/src/connection-kind.ts +53 -0
- package/src/describe-error.ts +76 -0
- package/src/edge-control.ts +94 -0
- package/src/edge-dispatch.ts +295 -0
- package/src/edge-guard.ts +67 -0
- package/src/edge.ts +175 -0
- package/src/gateway.ts +141 -0
- package/src/identity.ts +146 -0
- package/src/index.ts +95 -0
- package/src/join-blob.ts +229 -0
- package/src/join.ts +632 -0
- package/src/kv.ts +21 -0
- package/src/mesh-config.ts +41 -0
- package/src/mesh-memory.ts +104 -0
- package/src/node.ts +49 -0
- package/src/page-wake.ts +59 -0
- package/src/peer-request.ts +39 -0
- package/src/reset.ts +127 -0
- package/src/session.ts +579 -0
- 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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"}
|