@hediet/linkrpc 0.0.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.
Files changed (39) hide show
  1. package/README.md +383 -0
  2. package/dist/chunks/_empty-crypto-Bi0tGx5K.js +8 -0
  3. package/dist/chunks/boundedTrafficSubscription-1L592xc7.js +1126 -0
  4. package/dist/chunks/boundedTrafficSubscription-1L592xc7.js.map +1 -0
  5. package/dist/chunks/hub.interfaces-BzWfsVT2.js +526 -0
  6. package/dist/chunks/hub.interfaces-BzWfsVT2.js.map +1 -0
  7. package/dist/chunks/hubAccess-DwTZPiI8.d.ts +79 -0
  8. package/dist/chunks/hubAccess-DwTZPiI8.d.ts.map +1 -0
  9. package/dist/chunks/hubFacade-CQflVkVC.js +85 -0
  10. package/dist/chunks/hubFacade-CQflVkVC.js.map +1 -0
  11. package/dist/chunks/hubFacade-Dkgw2pTi.d.ts +101 -0
  12. package/dist/chunks/hubFacade-Dkgw2pTi.d.ts.map +1 -0
  13. package/dist/chunks/linkRpcConnection-CtlQmetO.d.ts +3623 -0
  14. package/dist/chunks/linkRpcConnection-CtlQmetO.d.ts.map +1 -0
  15. package/dist/chunks/rolldown-runtime-4LSo1kEK.js +17 -0
  16. package/dist/chunks/src-D3NUIwyo.js +7795 -0
  17. package/dist/chunks/src-D3NUIwyo.js.map +1 -0
  18. package/dist/hub/client/index.d.ts +50 -0
  19. package/dist/hub/client/index.d.ts.map +1 -0
  20. package/dist/hub/client/index.js +97 -0
  21. package/dist/hub/client/index.js.map +1 -0
  22. package/dist/hub/common/index.d.ts +1189 -0
  23. package/dist/hub/common/index.d.ts.map +1 -0
  24. package/dist/hub/common/index.js +267 -0
  25. package/dist/hub/common/index.js.map +1 -0
  26. package/dist/index.d.ts +6 -0
  27. package/dist/index.js +7 -0
  28. package/dist/inspection/index.d.ts +66 -0
  29. package/dist/inspection/index.d.ts.map +1 -0
  30. package/dist/inspection/index.js +6 -0
  31. package/dist/node.d.ts +548 -0
  32. package/dist/node.d.ts.map +1 -0
  33. package/dist/node.js +1087 -0
  34. package/dist/node.js.map +1 -0
  35. package/dist/web.d.ts +44 -0
  36. package/dist/web.d.ts.map +1 -0
  37. package/dist/web.js +58 -0
  38. package/dist/web.js.map +1 -0
  39. package/package.json +59 -0
@@ -0,0 +1,1189 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { Bi as RequestType, Br as TopologyTransportInfo, Gt as Channel, Jt as IRequestSender, K as Principal, L as CapProvider, Ti as InterfaceDefinition, V as SigningCallCtx, Yi as MethodSchema, an as IMessageTransport, d as ServiceIdPattern, qi as LinkRpcInterfaceSchema, u as RootPrincipalSet, wi as InterfaceClient, z as ManagedSigningChannel } from "../../chunks/linkRpcConnection-CtlQmetO.js";
6
+ import { a as HubAccessResult, i as HubAccessRequest, n as HubAccessPattern, o as findCoveringCapabilities, r as HubAccessPermission, t as HubAccessDuration } from "../../chunks/hubAccess-DwTZPiI8.js";
7
+ //#region src/hub/common/serviceId.d.ts
8
+ /**
9
+ * A **ServiceId** is a `'/'`-segmented address naming a routing destination
10
+ * on a {@link Hub}. The empty string is the **root** (the hub's own / local
11
+ * services); every other id is one or more non-empty segments joined by
12
+ * `'/'`.
13
+ *
14
+ * Examples:
15
+ * - `""` → root (valid)
16
+ * - `"foo"` → valid
17
+ * - `"foo/bar"` → valid
18
+ * - `"/"` → invalid (empty segments)
19
+ * - `"/foo"` → invalid (leading separator)
20
+ * - `"foo/"` → invalid (trailing separator)
21
+ * - `"foo//bar"` → invalid (empty interior segment)
22
+ *
23
+ * It is a plain `string` alias — the name exists only to mark the role at
24
+ * call sites. Use {@link isValidServiceId} / {@link splitServiceId} to work
25
+ * with it structurally.
26
+ */
27
+ type ServiceId = string;
28
+ /** The root service id — the hub's own local services. */
29
+ declare const ROOT_SERVICE_ID: ServiceId;
30
+ /** The separator between service id segments. */
31
+ declare const SERVICE_ID_SEPARATOR = "/";
32
+ /**
33
+ * Whether `id` is a well-formed {@link ServiceId}. The root (`""`) is
34
+ * valid; any other value must be non-empty segments joined by single
35
+ * `'/'`s, with no leading, trailing, or empty segments.
36
+ */
37
+ declare function isValidServiceId(id: string): boolean;
38
+ /**
39
+ * Split a {@link ServiceId} into its segments. The root (`""`) yields the
40
+ * empty array; `"foo/bar"` yields `["foo", "bar"]`.
41
+ *
42
+ * Does not validate — pair with {@link isValidServiceId} when the input is
43
+ * untrusted.
44
+ */
45
+ declare function splitServiceId(id: ServiceId): string[];
46
+ /**
47
+ * Whether `serviceId` is equal to or nested beneath `prefix` (segment-aware):
48
+ * `"a/b"` covers `"a/b"` and `"a/b/c"` but **not** `"a/bc"`. The root prefix
49
+ * (`""`) covers everything.
50
+ */
51
+ declare function isServiceIdUnder(serviceId: ServiceId, prefix: ServiceId): boolean;
52
+ //#endregion
53
+ //#region src/hub/common/transportServer.d.ts
54
+ /**
55
+ * A link the hub can route, plus a close signal. {@link IMessageTransport}
56
+ * on its own has no "closed" event (it only learns of teardown through its
57
+ * own `dispose`), but a *server*-produced connection must be able to tell
58
+ * downstream consumers when the remote end goes away so overlays can be torn
59
+ * down and prefixes released. {@link Transport} adds exactly that.
60
+ */
61
+ interface Transport extends IMessageTransport {
62
+ /** Optional diagnostics surfaced on the corresponding topology link. Never include credentials or payloads. */
63
+ readonly topologyInfo?: TopologyTransportInfo;
64
+ /**
65
+ * Register a handler fired exactly once when the transport closes (remote
66
+ * hang-up or local {@link IMessageTransport.dispose}). Handlers added
67
+ * after close fire on the next microtask.
68
+ */
69
+ onDidClose(handler: () => void): void;
70
+ }
71
+ /**
72
+ * A source of inbound {@link Transport}s — the single seam every transport
73
+ * backend (UDS socket, websocket, iframe postMessage, in-process pair)
74
+ * implements. The hub side consumes only this; it never names `net.Socket`
75
+ * or any backend-specific type.
76
+ */
77
+ interface ITransportServer<T extends Transport> {
78
+ /**
79
+ * Install the handler invoked once per accepted transport. Replacing the
80
+ * handler is allowed; only the most recent one receives new connections.
81
+ */
82
+ setConnectionHandler(handler: (transport: T) => void): void;
83
+ dispose(): void;
84
+ }
85
+ /**
86
+ * Lift a transport server from emitting `T1` to emitting `T2`. The `map` may
87
+ * be async (e.g. to attest a peer before exposing it) and may return
88
+ * `undefined` to **drop** a connection — the downstream handler is simply not
89
+ * invoked for it. The transport's identity is preserved when the map returns
90
+ * the same object (important: the hub keys routing state on the transport
91
+ * reference), so prefer annotating in place over wrapping.
92
+ */
93
+ declare function mapTransport<T1 extends Transport, T2 extends Transport>(source: ITransportServer<T1>, map: (transport: T1) => T2 | undefined | Promise<T2 | undefined>): ITransportServer<T2>;
94
+ //#endregion
95
+ //#region src/hub/common/hub.interfaces.d.ts
96
+ /**
97
+ * `hubServiceIdRegistry::registerServiceId` — a participant claims a prefix
98
+ * **outside** its provenance-granted namespace.
99
+ *
100
+ * Reached under the hub's own service id (form-3
101
+ * `<hubServiceId>::hubServiceIdRegistry::registerServiceId`) and gated by an
102
+ * admin-rooted capability. For claims **within** the connection's granted
103
+ * namespace, use the cheaper, capability-free `hubGrantedServiceId::register`
104
+ * instead.
105
+ */
106
+ declare const hubServiceIdRegistryInterface: InterfaceDefinition<{
107
+ registerServiceId: RequestType<{
108
+ requestedPrefix: string;
109
+ }, Record<string, never>, any, never, never>;
110
+ }>;
111
+ /**
112
+ * `hubGrantedServiceId` — the ungated connection surface, served at the
113
+ * connection root on each participant's overlay (so it is reachable directly,
114
+ * never forwarded, and needs no capability of its own). Two jobs:
115
+ *
116
+ * - `get` (unsigned) reports the topology facts the hub decided for this
117
+ * connection — where it is and what it may claim.
118
+ * - `register` (provenance-gated) claims a prefix **within**
119
+ * this connection's granted namespace — the capability-free claim path.
120
+ * Claims outside the namespace go through the admin-gated
121
+ * `<hubServiceId>::hubServiceIdRegistry::registerServiceId` door instead.
122
+ * - `getHubServiceId` (unsigned) reports the serviceId prefix the hub mounts
123
+ * its own global services under — the prefix to address the admin-gated
124
+ * registry and reflection endpoints through. Served at the connection root
125
+ * so a participant can discover it **before** it knows where the hub lives.
126
+ *
127
+ * The hub's consent front door (`hubAccess::*`) is served at the connection
128
+ * root too, so it needs no bootstrap capability and is reached directly.
129
+ */
130
+ declare const hubGrantedServiceIdInterface: InterfaceDefinition<{
131
+ /**
132
+ * Connection facts (unsigned). The participant pulls, on each
133
+ * (re)connect, the topology facts the hub has decided for this
134
+ * connection:
135
+ *
136
+ * - `grantedServiceIdNamespace` — the absolute serviceId region this
137
+ * connection's provenance may claim (anything at/under it). May be
138
+ * the empty string, meaning "claim nothing freely".
139
+ */
140
+ get: RequestType<Record<string, never>, {
141
+ grantedServiceIdNamespace: string;
142
+ }, any, never, never>;
143
+ /**
144
+ * The serviceId prefix the hub mounts its own global services under
145
+ * (default `'hub'`). Use it to address the admin-gated
146
+ * `<hubServiceId>::hubServiceIdRegistry::registerServiceId` door and the
147
+ * hub's reflection endpoints. Served at the connection root (unsigned),
148
+ * so a participant can learn it without first knowing where the hub
149
+ * lives.
150
+ */
151
+ getHubServiceId: RequestType<Record<string, never>, {
152
+ hubServiceId: string;
153
+ }, any, never, never>;
154
+ /**
155
+ * Claim a serviceId prefix **within** this connection's provenance-
156
+ * granted namespace (see `get().grantedServiceIdNamespace`). No
157
+ * capability needed — the grant already happened out-of-band at attach
158
+ * time. The requested `serviceId` must equal the granted namespace or be
159
+ * nested beneath it; anything else is rejected (claim it through the
160
+ * admin-gated `<hubServiceId>::hubServiceIdRegistry::registerServiceId`
161
+ * door instead).
162
+ */
163
+ register: RequestType<{
164
+ serviceId: string;
165
+ }, Record<string, never>, any, never, never>;
166
+ }>;
167
+ /**
168
+ * `hubAccess::request` — a consumer (e.g. a sandboxed web editor) asks the
169
+ * hub for scoped access to one or more services.
170
+ *
171
+ * Consumers describe their needs as named *dependencies* ("slots"): each
172
+ * slot lists the interfaces the chosen service must implement and the
173
+ * methods the consumer wants to call. The hub resolves candidate services
174
+ * from its participant directory, then forwards the bundle to a host-
175
+ * supplied handler (see `Hub` options) that shows the user a single
176
+ * prompt. The handler picks a concrete service per slot and approves a
177
+ * subset of the requested methods.
178
+ *
179
+ * In v1 the response carries only the resolution (which serviceId was
180
+ * chosen per slot). Once the hub holds a signing identity it will also
181
+ * return a `SignedCapability` the consumer attaches to subsequent calls.
182
+ * Until then, dispatch is not gated on the grant — see plan-access.md.
183
+ */
184
+ declare const hubAccessInterface: InterfaceDefinition<{
185
+ request: RequestType<{
186
+ consumer: {
187
+ name: string;
188
+ principal: string;
189
+ origin?: string | undefined;
190
+ purpose?: string | undefined;
191
+ };
192
+ dependencies: Record<string, {
193
+ interfaces: {
194
+ id: string;
195
+ hash?: string | undefined;
196
+ required?: boolean | undefined;
197
+ }[];
198
+ members?: {
199
+ interfaceId: string;
200
+ member: {
201
+ exact: string;
202
+ } | {
203
+ prefix: string;
204
+ };
205
+ required?: boolean | undefined;
206
+ }[] | undefined;
207
+ }>;
208
+ duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
209
+ }, {
210
+ status: "granted";
211
+ slots: Record<string, {
212
+ serviceId: string;
213
+ satisfiedInterfaces: string[];
214
+ }>;
215
+ capabilities: {
216
+ issuer: string;
217
+ audience: string;
218
+ permissions: {
219
+ target: {
220
+ serviceId: {
221
+ exact: string;
222
+ } | {
223
+ prefix: string;
224
+ };
225
+ interfaceId: {
226
+ exact: string;
227
+ } | {
228
+ prefix: string;
229
+ };
230
+ members: ({
231
+ exact: string;
232
+ } | {
233
+ prefix: string;
234
+ })[];
235
+ interfaceHash?: string | undefined;
236
+ };
237
+ canInvoke?: boolean | undefined;
238
+ canDelegate?: boolean | undefined;
239
+ params?: Record<string, {
240
+ exact: unknown;
241
+ } | {
242
+ enum: unknown[];
243
+ } | {
244
+ prefix: string;
245
+ } | {
246
+ subsetOf: string[];
247
+ } | {
248
+ any: true;
249
+ }> | undefined;
250
+ callBind?: {
251
+ alg: "sha256";
252
+ payloadHash: string;
253
+ } | undefined;
254
+ }[];
255
+ nonce: string;
256
+ $hubrpcSignature: {
257
+ capability?: {
258
+ keyId: string;
259
+ sig: string;
260
+ } | undefined;
261
+ call?: {
262
+ keyId: string;
263
+ sig: string;
264
+ } | undefined;
265
+ };
266
+ expiresAtMs?: number | undefined;
267
+ parentHash?: string | undefined;
268
+ }[];
269
+ } | {
270
+ status: "denied";
271
+ reason?: string | undefined;
272
+ } | {
273
+ status: "noCandidates";
274
+ slots: string[];
275
+ }, any, never, never>;
276
+ /**
277
+ * Service-pinned widening of an existing grant. The consumer asks
278
+ * the hub for additional members on a `serviceId` they already
279
+ * deal with — same audience (their NodeId) and (intended) same
280
+ * `rootIssuer` as the prior grant. The hub never picks the service
281
+ * for the consumer here: `serviceId` is an input, not a result.
282
+ *
283
+ * On grant the response carries a fresh `SignedCapability` whose
284
+ * attenuations cover **only** the granted delta. Bag-compatible
285
+ * with the prior cap; combine via `merge` (when it exists) or
286
+ * just keep both in `$hubrpc.capabilities`.
287
+ *
288
+ * Distinguished from `request` so the consent UI can render a
289
+ * different affordance ("X already has read access on `github`,
290
+ * grant `update` as well?" instead of from-zero selection).
291
+ *
292
+ * TODO(hub-ledger): enforce "consumer has prior history on this
293
+ * service" — see `hub.ts:_handleAccessExtend`. v1 forwards
294
+ * directly to the host's `onAccessExtend` without consulting the
295
+ * `_grants` ledger; this is by design while we settle on the
296
+ * persistence model.
297
+ */
298
+ extend: RequestType<{
299
+ consumer: {
300
+ name: string;
301
+ principal: string;
302
+ origin?: string | undefined;
303
+ purpose?: string | undefined;
304
+ };
305
+ serviceId: string;
306
+ added: {
307
+ interfaceId: string;
308
+ member: {
309
+ exact: string;
310
+ } | {
311
+ prefix: string;
312
+ };
313
+ required?: boolean | undefined;
314
+ }[];
315
+ duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
316
+ }, {
317
+ status: "granted";
318
+ serviceId: string;
319
+ granted: {
320
+ interfaceId: string;
321
+ member: {
322
+ exact: string;
323
+ } | {
324
+ prefix: string;
325
+ };
326
+ }[];
327
+ capabilities?: {
328
+ issuer: string;
329
+ audience: string;
330
+ permissions: {
331
+ target: {
332
+ serviceId: {
333
+ exact: string;
334
+ } | {
335
+ prefix: string;
336
+ };
337
+ interfaceId: {
338
+ exact: string;
339
+ } | {
340
+ prefix: string;
341
+ };
342
+ members: ({
343
+ exact: string;
344
+ } | {
345
+ prefix: string;
346
+ })[];
347
+ interfaceHash?: string | undefined;
348
+ };
349
+ canInvoke?: boolean | undefined;
350
+ canDelegate?: boolean | undefined;
351
+ params?: Record<string, {
352
+ exact: unknown;
353
+ } | {
354
+ enum: unknown[];
355
+ } | {
356
+ prefix: string;
357
+ } | {
358
+ subsetOf: string[];
359
+ } | {
360
+ any: true;
361
+ }> | undefined;
362
+ callBind?: {
363
+ alg: "sha256";
364
+ payloadHash: string;
365
+ } | undefined;
366
+ }[];
367
+ nonce: string;
368
+ $hubrpcSignature: {
369
+ capability?: {
370
+ keyId: string;
371
+ sig: string;
372
+ } | undefined;
373
+ call?: {
374
+ keyId: string;
375
+ sig: string;
376
+ } | undefined;
377
+ };
378
+ expiresAtMs?: number | undefined;
379
+ parentHash?: string | undefined;
380
+ }[] | undefined;
381
+ } | {
382
+ status: "denied";
383
+ reason?: string | undefined;
384
+ }, any, never, never>;
385
+ /**
386
+ * `hubAccess::requestAccess` — direct capability request. The
387
+ * consumer specifies the exact attenuations it wants. No
388
+ * service-discovery, no candidate resolution: the consumer
389
+ * already knows which `(serviceId, interfaceId, members)` it
390
+ * needs, including wildcards (e.g. `serviceId: { prefix: "" }`
391
+ * to ask for an interface anywhere).
392
+ *
393
+ * Compared to `request`:
394
+ * - `request` does directory-based discovery, picks one service
395
+ * per slot, and returns a cap pinned to that service. Use
396
+ * when the consumer says "give me SOME service that does X".
397
+ * - `requestAccess` is verbatim. Use when the consumer says
398
+ * "give me exactly these attenuations". Especially useful for
399
+ * reflection (`hubrpc.directory::list` on any service) and
400
+ * for on-demand per-method grants from an explorer-style UI.
401
+ *
402
+ * The user prompt shows the exact `Capability` the hub will sign
403
+ * on Allow, same byte-equality guarantee as `request`/`extend`.
404
+ */
405
+ requestAccess: RequestType<{
406
+ consumer: {
407
+ name: string;
408
+ principal: string;
409
+ origin?: string | undefined;
410
+ purpose?: string | undefined;
411
+ };
412
+ permissions: {
413
+ target: {
414
+ serviceId: {
415
+ exact: string;
416
+ } | {
417
+ prefix: string;
418
+ };
419
+ interfaceId: {
420
+ exact: string;
421
+ } | {
422
+ prefix: string;
423
+ };
424
+ members: ({
425
+ exact: string;
426
+ } | {
427
+ prefix: string;
428
+ })[];
429
+ interfaceHash?: string | undefined;
430
+ };
431
+ canInvoke?: boolean | undefined;
432
+ canDelegate?: boolean | undefined;
433
+ params?: Record<string, {
434
+ exact: unknown;
435
+ } | {
436
+ enum: unknown[];
437
+ } | {
438
+ prefix: string;
439
+ } | {
440
+ subsetOf: string[];
441
+ } | {
442
+ any: true;
443
+ }> | undefined;
444
+ callBind?: {
445
+ alg: "sha256";
446
+ payloadHash: string;
447
+ } | undefined;
448
+ callIntent?: {
449
+ method: string;
450
+ nonce: string;
451
+ signedAtMs: number;
452
+ params?: unknown;
453
+ interfaceHash?: string | undefined;
454
+ summary?: string | undefined;
455
+ suggestion?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
456
+ } | undefined;
457
+ }[];
458
+ duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
459
+ }, {
460
+ status: "granted";
461
+ capabilities: {
462
+ issuer: string;
463
+ audience: string;
464
+ permissions: {
465
+ target: {
466
+ serviceId: {
467
+ exact: string;
468
+ } | {
469
+ prefix: string;
470
+ };
471
+ interfaceId: {
472
+ exact: string;
473
+ } | {
474
+ prefix: string;
475
+ };
476
+ members: ({
477
+ exact: string;
478
+ } | {
479
+ prefix: string;
480
+ })[];
481
+ interfaceHash?: string | undefined;
482
+ };
483
+ canInvoke?: boolean | undefined;
484
+ canDelegate?: boolean | undefined;
485
+ params?: Record<string, {
486
+ exact: unknown;
487
+ } | {
488
+ enum: unknown[];
489
+ } | {
490
+ prefix: string;
491
+ } | {
492
+ subsetOf: string[];
493
+ } | {
494
+ any: true;
495
+ }> | undefined;
496
+ callBind?: {
497
+ alg: "sha256";
498
+ payloadHash: string;
499
+ } | undefined;
500
+ }[];
501
+ nonce: string;
502
+ $hubrpcSignature: {
503
+ capability?: {
504
+ keyId: string;
505
+ sig: string;
506
+ } | undefined;
507
+ call?: {
508
+ keyId: string;
509
+ sig: string;
510
+ } | undefined;
511
+ };
512
+ expiresAtMs?: number | undefined;
513
+ parentHash?: string | undefined;
514
+ }[];
515
+ } | {
516
+ status: "denied";
517
+ reason?: string | undefined;
518
+ }, any, never, never>;
519
+ }>;
520
+ /**
521
+ * `hubAccessManifest` — the declarative twin of {@link hubAccessInterface}.
522
+ *
523
+ * Where `hubAccess` is the imperative, just-in-time door a consumer *calls* (and
524
+ * the hub serves at the connection root), `hubAccessManifest` is **served by the
525
+ * participant** under its own serviceId, so it appears in `hubrpc.directory::list`
526
+ * — its very presence is the request. A participant publishes its DESIRED access
527
+ * entries (keyed by id, like `request`'s `dependencies`); an admin discovers
528
+ * them via the directory, mints capabilities **with its own identity** (a
529
+ * configured hub capability root), and writes the CURRENT/granted state back via
530
+ * patches. The participant reads the granted entries and attaches the caps to
531
+ * its later calls.
532
+ *
533
+ * Reconcile model (desired vs. current), aligned with the hub's other surfaces:
534
+ * - `getDesired` / `watchDesired` — the participant's declared needs.
535
+ * - `getCurrent` / `setCurrent` / `watchCurrent` — the admin-written grants.
536
+ *
537
+ * `watch*` follows the coarse empty-tick convention of `hubrpc.directory::watch`:
538
+ * a tick means "re-`get` now", keeping the server stateless (no per-item deltas).
539
+ */
540
+ declare const hubAccessManifestInterface: InterfaceDefinition<{
541
+ /** The full desired document: who is asking and the entries it wants. */
542
+ getDesired: RequestType<Record<string, never>, {
543
+ requested: Record<string, {
544
+ interfaces: {
545
+ id: string;
546
+ hash?: string | undefined;
547
+ required?: boolean | undefined;
548
+ }[];
549
+ kind: "discover";
550
+ consumer: {
551
+ name: string;
552
+ principal: string;
553
+ origin?: string | undefined;
554
+ purpose?: string | undefined;
555
+ };
556
+ members?: {
557
+ interfaceId: string;
558
+ member: {
559
+ exact: string;
560
+ } | {
561
+ prefix: string;
562
+ };
563
+ required?: boolean | undefined;
564
+ }[] | undefined;
565
+ reason?: string | undefined;
566
+ duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
567
+ acceptableRootIds?: string[] | undefined;
568
+ origin?: Record<string, unknown> | undefined;
569
+ } | {
570
+ kind: "direct";
571
+ consumer: {
572
+ name: string;
573
+ principal: string;
574
+ origin?: string | undefined;
575
+ purpose?: string | undefined;
576
+ };
577
+ permissions: {
578
+ target: {
579
+ serviceId: {
580
+ exact: string;
581
+ } | {
582
+ prefix: string;
583
+ };
584
+ interfaceId: {
585
+ exact: string;
586
+ } | {
587
+ prefix: string;
588
+ };
589
+ members: ({
590
+ exact: string;
591
+ } | {
592
+ prefix: string;
593
+ })[];
594
+ interfaceHash?: string | undefined;
595
+ };
596
+ canInvoke?: boolean | undefined;
597
+ canDelegate?: boolean | undefined;
598
+ params?: Record<string, {
599
+ exact: unknown;
600
+ } | {
601
+ enum: unknown[];
602
+ } | {
603
+ prefix: string;
604
+ } | {
605
+ subsetOf: string[];
606
+ } | {
607
+ any: true;
608
+ }> | undefined;
609
+ callBind?: {
610
+ alg: "sha256";
611
+ payloadHash: string;
612
+ } | undefined;
613
+ callIntent?: {
614
+ method: string;
615
+ nonce: string;
616
+ signedAtMs: number;
617
+ params?: unknown;
618
+ interfaceHash?: string | undefined;
619
+ summary?: string | undefined;
620
+ suggestion?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
621
+ } | undefined;
622
+ }[];
623
+ reason?: string | undefined;
624
+ duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined;
625
+ acceptableRootIds?: string[] | undefined;
626
+ origin?: Record<string, unknown> | undefined;
627
+ }>;
628
+ revision: number;
629
+ }, void, Record<string, never>, any>;
630
+ /**
631
+ * Coarse change tap on the desired document. Emits an empty tick when
632
+ * `requested` may have changed; the caller re-`getDesired`. Resolves when
633
+ * the caller cancels. Mirrors `hubrpc.directory::watch`.
634
+ */
635
+ watchDesired: RequestType<Record<string, never>, Record<string, never>, void, any, Record<string, never>>;
636
+ /** The full current document: entryId → granted/denied (absent ⇒ undecided). */
637
+ getCurrent: RequestType<Record<string, never>, {
638
+ current: Record<string, {
639
+ status: "granted";
640
+ granted: {
641
+ serviceId: string;
642
+ satisfiedInterfaces: string[];
643
+ kind: "discover";
644
+ capabilities: {
645
+ issuer: string;
646
+ audience: string;
647
+ permissions: {
648
+ target: {
649
+ serviceId: {
650
+ exact: string;
651
+ } | {
652
+ prefix: string;
653
+ };
654
+ interfaceId: {
655
+ exact: string;
656
+ } | {
657
+ prefix: string;
658
+ };
659
+ members: ({
660
+ exact: string;
661
+ } | {
662
+ prefix: string;
663
+ })[];
664
+ interfaceHash?: string | undefined;
665
+ };
666
+ canInvoke?: boolean | undefined;
667
+ canDelegate?: boolean | undefined;
668
+ params?: Record<string, {
669
+ exact: unknown;
670
+ } | {
671
+ enum: unknown[];
672
+ } | {
673
+ prefix: string;
674
+ } | {
675
+ subsetOf: string[];
676
+ } | {
677
+ any: true;
678
+ }> | undefined;
679
+ callBind?: {
680
+ alg: "sha256";
681
+ payloadHash: string;
682
+ } | undefined;
683
+ }[];
684
+ nonce: string;
685
+ $hubrpcSignature: {
686
+ capability?: {
687
+ keyId: string;
688
+ sig: string;
689
+ } | undefined;
690
+ call?: {
691
+ keyId: string;
692
+ sig: string;
693
+ } | undefined;
694
+ };
695
+ expiresAtMs?: number | undefined;
696
+ parentHash?: string | undefined;
697
+ }[];
698
+ } | {
699
+ kind: "direct";
700
+ capabilities: {
701
+ issuer: string;
702
+ audience: string;
703
+ permissions: {
704
+ target: {
705
+ serviceId: {
706
+ exact: string;
707
+ } | {
708
+ prefix: string;
709
+ };
710
+ interfaceId: {
711
+ exact: string;
712
+ } | {
713
+ prefix: string;
714
+ };
715
+ members: ({
716
+ exact: string;
717
+ } | {
718
+ prefix: string;
719
+ })[];
720
+ interfaceHash?: string | undefined;
721
+ };
722
+ canInvoke?: boolean | undefined;
723
+ canDelegate?: boolean | undefined;
724
+ params?: Record<string, {
725
+ exact: unknown;
726
+ } | {
727
+ enum: unknown[];
728
+ } | {
729
+ prefix: string;
730
+ } | {
731
+ subsetOf: string[];
732
+ } | {
733
+ any: true;
734
+ }> | undefined;
735
+ callBind?: {
736
+ alg: "sha256";
737
+ payloadHash: string;
738
+ } | undefined;
739
+ }[];
740
+ nonce: string;
741
+ $hubrpcSignature: {
742
+ capability?: {
743
+ keyId: string;
744
+ sig: string;
745
+ } | undefined;
746
+ call?: {
747
+ keyId: string;
748
+ sig: string;
749
+ } | undefined;
750
+ };
751
+ expiresAtMs?: number | undefined;
752
+ parentHash?: string | undefined;
753
+ }[];
754
+ };
755
+ } | {
756
+ status: "denied";
757
+ reason?: string | undefined;
758
+ }>;
759
+ revision: number;
760
+ }, any, never, never>;
761
+ /**
762
+ * Apply patches to the current document. Replace the whole document with
763
+ * `{ op: 'set', path: '', value }`, or a single entry with
764
+ * `{ op: 'set', path: '/current/<entryId>', value }` (a `zCurrentEntry`:
765
+ * granted or denied). Admin-only in practice (gated by a capability
766
+ * rooted at an accepted issuer).
767
+ */
768
+ setCurrent: RequestType<{
769
+ patches: ({
770
+ op: "set";
771
+ path: string;
772
+ value: unknown;
773
+ } | {
774
+ op: "remove";
775
+ path: string;
776
+ })[];
777
+ }, {
778
+ revision: number;
779
+ }, void, Record<string, never>, any>;
780
+ /**
781
+ * Coarse change tap on the current document. Emits an empty tick when
782
+ * `current` may have changed; the participant re-`getCurrent` and applies
783
+ * any new capabilities. Resolves when the caller cancels.
784
+ */
785
+ watchCurrent: RequestType<Record<string, never>, Record<string, never>, void, any, Record<string, never>>;
786
+ }>;
787
+ /**
788
+ * The typed client shape of {@link hubAccessManifestInterface} — the exact
789
+ * object `connection.get(hubAccessManifestInterface)` (or
790
+ * `connection.service(id).get(...)`) returns. Approvers depend on this contract,
791
+ * not on a concrete connection: the same approver runs against a local in-memory
792
+ * host (loopback connection), a remote hub's served manifest, or a future
793
+ * aggregating implementation with no code change.
794
+ */
795
+ type IHubAccessManifest = InterfaceClient<typeof hubAccessManifestInterface>;
796
+ /** One typed entry from `hubAccessManifest::getDesired().requested`. */
797
+ type HubAccessManifestRequest = Awaited<ReturnType<IHubAccessManifest['getDesired']>>['requested'][string];
798
+ /** One typed value accepted at `/current/<entryId>` by `setCurrent`. */
799
+ type HubAccessManifestDecision = Awaited<ReturnType<IHubAccessManifest['getCurrent']>>['current'][string];
800
+ //#endregion
801
+ //#region src/hub/common/baseCapabilities.d.ts
802
+ /**
803
+ * Claim a serviceId prefix within this connection's provenance-granted
804
+ * namespace via `hubGrantedServiceId::register` (no capability needed).
805
+ * Resolves once the claim is registered. Rejects when the prefix is outside
806
+ * the granted namespace or already owned.
807
+ */
808
+ declare function registerGrantedServiceId(sender: IRequestSender<SigningCallCtx>, serviceId: string): Promise<void>;
809
+ //#endregion
810
+ //#region src/hub/common/managedSigning.d.ts
811
+ /** Who is asking — surfaced in the hub's consent prompt. */
812
+ interface AutoNegotiateConsumer {
813
+ readonly name: string;
814
+ readonly origin?: string;
815
+ readonly purpose?: string;
816
+ }
817
+ /** Options for {@link createManagedSigningChannel}. */
818
+ interface ManagedSigningOptions {
819
+ /**
820
+ * When set, install a sign-time {@link CapProvider} that lazily negotiates
821
+ * the capability each gated call needs through the hub's `hubAccess`
822
+ * consent front door. Durable grants are absorbed into the principal's cap
823
+ * bag so later calls present them automatically; one-shot grants are
824
+ * attached to just the call that prompted them.
825
+ *
826
+ * Without it, the channel signs every call but presents no capabilities —
827
+ * gated calls then fail with `permissionRequired` unless the caller has
828
+ * arranged a capability some other way.
829
+ */
830
+ readonly autoNegotiateCaps?: boolean;
831
+ /** Consumer identity shown in the consent prompt. */
832
+ readonly consumer?: AutoNegotiateConsumer;
833
+ }
834
+ /**
835
+ * Build a managed-identity signing {@link Channel} from a raw channel, with
836
+ * optional per-call capability auto-negotiation.
837
+ *
838
+ * Like {@link SigningSender.fromChannelWithManagedPrincipal}, the
839
+ * `identity::*` bootstrap rides the raw (unsigned) sender, and the returned
840
+ * signing channel is what callers hand to `LinkRpcConnection`. When
841
+ * {@link ManagedSigningOptions.autoNegotiateCaps} is set, the returned
842
+ * channel additionally negotiates capabilities on demand — the browser-safe
843
+ * equivalent of the CLI's `setupSigning({ autoNegotiatePerCall: true })`.
844
+ */
845
+ declare function createManagedSigningChannel(channel: Channel<undefined>, opts?: ManagedSigningOptions): Promise<ManagedSigningChannel<undefined>>;
846
+ /**
847
+ * A sign-time {@link CapProvider} that negotiates access per gated call.
848
+ *
849
+ * For each outbound call it: presents any fresh caps already in the bag; if
850
+ * none cover the call, bootstraps the root `hubAccess` capability (once), then
851
+ * asks `hubAccess::requestAccess` for a grant scoped to exactly this call
852
+ * (`callIntent` pinned to the method/params/nonce). Durable grants are added to
853
+ * the bag; a one-shot grant is attached to just this call.
854
+ *
855
+ * Fail-soft: any negotiation error (open hub, denied consent, unreachable front
856
+ * door) falls back to presenting the current bag, letting the call surface
857
+ * `permissionRequired` if it is truly gated.
858
+ */
859
+ declare function createAutoNegotiatingCapProvider(opts: {
860
+ readonly sender: IRequestSender<SigningCallCtx>;
861
+ readonly principal: Principal;
862
+ readonly consumer: AutoNegotiateConsumer;
863
+ }): CapProvider;
864
+ //#endregion
865
+ //#region src/hub/common/directoryWalk.d.ts
866
+ /**
867
+ * Portable reflection walk over the `hubrpc.directory` referral tree.
868
+ *
869
+ * A directory may explicitly list other `hubrpc.directory` services as
870
+ * referrals. Flattening that graph into an interface inventory is the
871
+ * consumer's job. Routing state is deliberately not part of this contract.
872
+ */
873
+ /**
874
+ * The sender reflection helpers speak over: the signing decorator that wraps
875
+ * the live channel. Decoupled from the concrete `JsonRpcChannel` so reconnect
876
+ * can swap the underlying channel transparently.
877
+ */
878
+ type ReflectionChannel = IRequestSender<SigningCallCtx>;
879
+ interface ServiceListing {
880
+ readonly serviceId: string;
881
+ readonly interfaceId: string;
882
+ readonly hash: string;
883
+ readonly path?: string;
884
+ /** Optional non-normative description of the owning service. */
885
+ readonly serviceDescription?: string;
886
+ /**
887
+ * Root node ids required to access the owning service, in CNF. Surfaced by
888
+ * the directory; {@link walkHubDetailed} additionally folds transitive
889
+ * requirements from ancestor directories onto descendants.
890
+ */
891
+ readonly rootPrincipalSets?: readonly RootPrincipalSet[];
892
+ /** Scope carried by a directory referral; omitted means its service-id subtree. */
893
+ readonly reachableServiceIds?: readonly ServiceIdPattern[];
894
+ }
895
+ /**
896
+ * A {@link ServiceListing} enriched with the service id of the directory that
897
+ * reported it. This is provenance only: every listing is asserted reachable by
898
+ * sending to the endpoint that answered the directory.
899
+ */
900
+ interface DiscoveredListing extends ServiceListing {
901
+ readonly discoveredFrom: string;
902
+ }
903
+ interface ListOptions {
904
+ readonly interfaceId?: string;
905
+ readonly interfaceIdPrefix?: string;
906
+ readonly serviceId?: string;
907
+ readonly serviceIdScopes?: readonly ServiceIdPattern[];
908
+ readonly limit?: number;
909
+ readonly timeoutMs?: number;
910
+ /**
911
+ * When set, send the reflection call to that service via form-3
912
+ * (`<target>::hubrpc.directory::list`) instead of the implicit root
913
+ * directory. Used when talking to a hub: the root directory is the hub
914
+ * itself, but per-service reflection lives on each participant.
915
+ */
916
+ readonly target?: string;
917
+ }
918
+ declare function fetchDirectory(channel: ReflectionChannel, opts?: ListOptions): Promise<ServiceListing[]>;
919
+ declare function fetchSchema(channel: ReflectionChannel, interfaceId: string, hash: string | undefined,
920
+ /**
921
+ * Optional routing target. When set, the schema request is addressed to
922
+ * `<target>::hubrpc.schemas::get` (form-3) so it reaches the service that
923
+ * actually hosts this interface — needed when talking to a hub and the
924
+ * interface lives behind a participant.
925
+ */
926
+ target?: string): Promise<LinkRpcInterfaceSchema>;
927
+ declare function findMethodInSchema(schema: LinkRpcInterfaceSchema, methodName: string): MethodSchema | undefined;
928
+ /** Default recursion depth when walking the bus. */
929
+ declare const DEFAULT_WALK_DEPTH = 5;
930
+ /** Segment-aware service-id pattern matching (`foo` includes `foo/bar`, not `foobar`). */
931
+ declare function serviceIdMatchesPattern(serviceId: string, pattern: ServiceIdPattern): boolean;
932
+ /** Whether a service id is included by a union of patterns. `undefined` means unfiltered. */
933
+ declare function serviceIdMatchesScopes(serviceId: string, scopes: readonly ServiceIdPattern[] | undefined): boolean;
934
+ /** Canonicalize a pattern union by removing duplicates and contained patterns. */
935
+ declare function normalizeServiceIdScopes(scopes: readonly ServiceIdPattern[]): ServiceIdPattern[];
936
+ /** Pairwise intersection of two pattern unions. */
937
+ declare function intersectServiceIdScopes(left: readonly ServiceIdPattern[], right: readonly ServiceIdPattern[]): ServiceIdPattern[];
938
+ /**
939
+ * A sub-directory the walk surfaced but could not enumerate — typically because
940
+ * it is capability-gated (e.g. the `hub` directory, reachable only once the
941
+ * connection holds a capability for it). The services it would have listed are
942
+ * therefore absent from the walk; callers can surface `reason` to explain the
943
+ * gap rather than silently dropping the branch.
944
+ */
945
+ interface InaccessibleDirectory {
946
+ /** The directory target (serviceId) that could not be enumerated. */
947
+ readonly serviceId: string;
948
+ /** The error message from the denied directory lookup. */
949
+ readonly reason: string;
950
+ }
951
+ interface WalkHubResult {
952
+ /** Every interface reachable from the directories the walk could read. */
953
+ readonly listings: DiscoveredListing[];
954
+ /**
955
+ * Sub-directories that were referenced but could not be enumerated (e.g.
956
+ * capability-gated). Their services are not present in `listings`.
957
+ */
958
+ readonly inaccessible: InaccessibleDirectory[];
959
+ }
960
+ /**
961
+ * Recursive graph walk: list a directory, intersect the accumulated service-id
962
+ * scope with every explicit `hubrpc.directory` referral, and recurse. Bounded
963
+ * by `maxDepth`.
964
+ *
965
+ * Every listing is tagged with `discoveredFrom` — the serviceId of the
966
+ * directory that produced it. When the same `(serviceId, interfaceId, hash)`
967
+ * shows up via several directories (e.g. once forwarded by the hub, once
968
+ * directly from the participant), we keep the one whose `discoveredFrom`
969
+ * matches the item's `serviceId`, since that's the directory that
970
+ * authoritatively knows about it.
971
+ *
972
+ * Transitive root-node-id requirements flow down the tree: when the walk
973
+ * recurses into a directory whose own `rootPrincipalSets` include `transitive`
974
+ * reqs, every interface discovered at or below that directory inherits them (as
975
+ * singleton AND-sets, kept transitive so they keep flowing further down). This
976
+ * replaces the hub-side `applyTransitiveReqs` fold that the v1 aggregating
977
+ * directory performed.
978
+ *
979
+ * A sub-directory the walk cannot read is recorded in
980
+ * {@link WalkHubResult.inaccessible} rather than silently dropped. A failure to
981
+ * read the *root* directory is left silent — there is no sub-tree to explain —
982
+ * and simply yields empty results.
983
+ *
984
+ * When {@link WalkHubOptions.unlockGatedDirectory} is supplied, each gated
985
+ * sub-directory is offered to the hook; if it returns `true` (a capability was
986
+ * granted), that directory is re-queued and the walk continues into it — a
987
+ * fixpoint that keeps unlocking newly-revealed gated branches until nothing
988
+ * more can be opened (still bounded by `maxDepth`).
989
+ */
990
+ interface WalkHubOptions {
991
+ readonly maxDepth?: number;
992
+ /** Hard deadline for each directory page request. Defaults to 5 seconds. */
993
+ readonly timeoutMs?: number;
994
+ /** Return only listings for this exact interface id after traversing directories. */
995
+ readonly interfaceId?: string;
996
+ /** Return only listings whose interface id starts with this prefix after traversal. */
997
+ readonly interfaceIdPrefix?: string;
998
+ /** Return only listings for this exact service id after traversal. */
999
+ readonly serviceId?: string;
1000
+ /** Initial service-id scope. Defaults to the universal `{ prefix: "" }`. */
1001
+ readonly serviceIdScopes?: readonly ServiceIdPattern[];
1002
+ /**
1003
+ * The directory the walk starts from. Defaults to the implicit root
1004
+ * directory (form-2 `hubrpc.directory::list`). Pass a serviceId to start at
1005
+ * `<rootTarget>::hubrpc.directory::list` — e.g. the hub's own global
1006
+ * directory (`'hub'`) when walking from the hub's in-process connection.
1007
+ */
1008
+ readonly rootTarget?: string;
1009
+ /**
1010
+ * Invoked once per gated sub-directory the walk encounters. Return `true`
1011
+ * if a capability for its `hubrpc.directory::list` was granted and the
1012
+ * directory should be re-listed; `false` (or omitted hook) leaves it in
1013
+ * {@link WalkHubResult.inaccessible}. Called at most once per `serviceId`.
1014
+ */
1015
+ unlockGatedDirectory?: (serviceId: string) => Promise<boolean>;
1016
+ /** Optional diagnostic sink for inaccessible lists and ended watches. */
1017
+ readonly log?: (message: string) => void;
1018
+ }
1019
+ declare function walkHubDetailed(channel: ReflectionChannel, opts?: WalkHubOptions): Promise<WalkHubResult>;
1020
+ /**
1021
+ * Backward-compatible wrapper over {@link walkHubDetailed} that returns only the
1022
+ * reachable listings, dropping the inaccessible-directory report.
1023
+ */
1024
+ declare function walkHub(channel: ReflectionChannel, opts?: WalkHubOptions): Promise<DiscoveredListing[]>;
1025
+ interface HubDirectoryChange {
1026
+ /** Directory that emitted the tick. `undefined` denotes the connection root. */
1027
+ readonly target: string | undefined;
1028
+ readonly result: WalkHubResult;
1029
+ }
1030
+ type HubDirectoryGraphTarget = {
1031
+ readonly kind: 'root';
1032
+ readonly serviceId?: string;
1033
+ } | {
1034
+ readonly kind: 'addressed';
1035
+ readonly serviceId: string;
1036
+ };
1037
+ type HubDirectoryNodeState = 'unexplored' | 'loading' | 'loaded' | 'inaccessible';
1038
+ interface HubDirectoryParentReport {
1039
+ readonly target: HubDirectoryGraphTarget;
1040
+ readonly scopes: readonly ServiceIdPattern[];
1041
+ /** Resulting depth for this incoming parent path. */
1042
+ readonly depth: number;
1043
+ }
1044
+ /** Stable public report for one native directory response. */
1045
+ interface HubDirectoryNodeReport {
1046
+ readonly target: HubDirectoryGraphTarget;
1047
+ readonly state: HubDirectoryNodeState;
1048
+ readonly effectiveScopes: readonly ServiceIdPattern[];
1049
+ readonly depth: number;
1050
+ readonly parents: readonly HubDirectoryParentReport[];
1051
+ /** Per-directory listings, normalized to `ServiceListing`, before inherited metadata is folded. */
1052
+ readonly nativeListings: readonly ServiceListing[];
1053
+ readonly inaccessibleReason?: string;
1054
+ readonly watching: boolean;
1055
+ }
1056
+ /**
1057
+ * Complete point-in-time graph document. `root` exists from construction in
1058
+ * the `unexplored` state, so consumers can render before exploration starts.
1059
+ */
1060
+ interface HubDirectoryGraphSnapshot {
1061
+ readonly revision: number;
1062
+ readonly complete: boolean;
1063
+ readonly root: HubDirectoryNodeReport;
1064
+ readonly directories: readonly HubDirectoryNodeReport[];
1065
+ readonly result: WalkHubResult;
1066
+ }
1067
+ type HubDirectoryGraphEvent = {
1068
+ readonly type: 'snapshot';
1069
+ readonly reason: 'subscribed' | 'reconciliation-started' | 'reset';
1070
+ readonly snapshot: HubDirectoryGraphSnapshot;
1071
+ } | {
1072
+ readonly type: 'node-added';
1073
+ readonly reason: 'referral';
1074
+ readonly node: HubDirectoryNodeReport;
1075
+ readonly snapshot: HubDirectoryGraphSnapshot;
1076
+ } | {
1077
+ readonly type: 'node-updated';
1078
+ readonly reason: 'loading' | 'loaded' | 'inaccessible' | 'referral' | 'watch-started' | 'watch-stopped' | 'watch-ended' | 'reset';
1079
+ readonly previous: HubDirectoryNodeReport;
1080
+ readonly node: HubDirectoryNodeReport;
1081
+ readonly snapshot: HubDirectoryGraphSnapshot;
1082
+ } | {
1083
+ readonly type: 'node-removed';
1084
+ readonly reason: 'unreachable' | 'reset';
1085
+ readonly previous: HubDirectoryNodeReport;
1086
+ readonly snapshot: HubDirectoryGraphSnapshot;
1087
+ } | {
1088
+ readonly type: 'settled';
1089
+ readonly snapshot: HubDirectoryGraphSnapshot;
1090
+ };
1091
+ /**
1092
+ * Reusable directory graph explorer and watcher.
1093
+ *
1094
+ * The class keeps one native snapshot per directory target. A watch tick
1095
+ * re-lists only its source target; outgoing referral changes then propagate
1096
+ * through affected descendants. Unchanged siblings retain both their snapshot
1097
+ * and watch. Multi-parent targets are queried with the normalized union of all
1098
+ * incoming path scopes.
1099
+ */
1100
+ declare class HubDirectoryExplorer {
1101
+ private readonly _channel;
1102
+ private readonly _options;
1103
+ private readonly _maxDepth;
1104
+ private readonly _initialScopes;
1105
+ private readonly _nodes;
1106
+ private readonly _unlockAttempted;
1107
+ private readonly _listeners;
1108
+ private readonly _graphListeners;
1109
+ private readonly _pendingTicks;
1110
+ private readonly _watchRetryTimers;
1111
+ private readonly _watchRetryDelays;
1112
+ private _initialized;
1113
+ private _disposed;
1114
+ private _watching;
1115
+ private _complete;
1116
+ private _revision;
1117
+ private _work;
1118
+ private _explorePromise;
1119
+ constructor(_channel: ReflectionChannel, _options?: WalkHubOptions);
1120
+ /** Perform a fresh bounded exploration without starting watches. */
1121
+ explore(): Promise<WalkHubResult>;
1122
+ private _explore;
1123
+ /** Current deduplicated graph snapshot. */
1124
+ get result(): WalkHubResult;
1125
+ /** Current complete-or-progressive directory graph report. */
1126
+ get graphSnapshot(): HubDirectoryGraphSnapshot;
1127
+ /**
1128
+ * Subscribe to progressive graph reports. The listener is registered before
1129
+ * receiving a synchronous current snapshot, avoiding the subscribe/explore
1130
+ * race for both idle and already-running explorers.
1131
+ */
1132
+ subscribe(listener: (event: HubDirectoryGraphEvent) => void): () => void;
1133
+ /**
1134
+ * Explore once, then watch every reachable directory. Resolves after the
1135
+ * initial graph and watches are established.
1136
+ */
1137
+ watch(listener: (change: HubDirectoryChange) => void): Promise<() => void>;
1138
+ /** Wait until all currently queued watch reconciliation has settled. */
1139
+ whenIdle(): Promise<void>;
1140
+ dispose(): void;
1141
+ private _loadNode;
1142
+ private _tryUnlock;
1143
+ private _reconcileOutgoing;
1144
+ private _outgoingFor;
1145
+ private _createRootNode;
1146
+ private _createNode;
1147
+ private _updateNodeFromParents;
1148
+ private _deriveNodeFromParents;
1149
+ private _derivedNodeState;
1150
+ /**
1151
+ * Rebuild incoming contributions from the root seed. Starting with no
1152
+ * non-root contributions computes the least fixed point, so a disconnected
1153
+ * or narrowed cycle cannot keep scopes contributed by its previous state.
1154
+ */
1155
+ private _reconcileScopesFromRoot;
1156
+ private _computeScopeFixedPoint;
1157
+ private _pruneUnreachable;
1158
+ /**
1159
+ * Every changed watch scope uses list/watch/list: callers reach this method
1160
+ * only after a list under the current scope, then the replacement watch is
1161
+ * installed before a verification list. Either the verification sees a
1162
+ * handoff mutation or the new watch ticks for it.
1163
+ */
1164
+ private _synchronizeWatches;
1165
+ private _replaceWatch;
1166
+ private _queueTick;
1167
+ private _stopWatch;
1168
+ private _stopAllWatches;
1169
+ private _scheduleWatchRetry;
1170
+ private _clearWatchRetry;
1171
+ private _clearNodes;
1172
+ private _resetForExplore;
1173
+ private _updateNode;
1174
+ private _nodeReport;
1175
+ private _targetForKey;
1176
+ private _emitNodeAdded;
1177
+ private _emitNodeUpdated;
1178
+ private _emitNodeRemoved;
1179
+ private _startReconciliation;
1180
+ private _settle;
1181
+ private _emitSnapshot;
1182
+ private _emitGraphEvent;
1183
+ private _deliverGraphEvent;
1184
+ private _nodeKeyForTarget;
1185
+ private _throwIfDisposed;
1186
+ }
1187
+ //#endregion
1188
+ export { type AutoNegotiateConsumer, DEFAULT_WALK_DEPTH, type DiscoveredListing, type HubAccessDuration, type HubAccessManifestDecision, type HubAccessManifestRequest, type HubAccessPattern, type HubAccessPermission, type HubAccessRequest, type HubAccessResult, type HubDirectoryChange, HubDirectoryExplorer, type HubDirectoryGraphEvent, type HubDirectoryGraphSnapshot, type HubDirectoryGraphTarget, type HubDirectoryNodeReport, type HubDirectoryNodeState, type HubDirectoryParentReport, type IHubAccessManifest, type ITransportServer, type InaccessibleDirectory, type ListOptions, type ManagedSigningOptions, ROOT_SERVICE_ID, type ReflectionChannel, SERVICE_ID_SEPARATOR, type ServiceId, type ServiceListing, type Transport, type WalkHubOptions, type WalkHubResult, createAutoNegotiatingCapProvider, createManagedSigningChannel, fetchDirectory, fetchSchema, findCoveringCapabilities, findMethodInSchema, hubAccessInterface, hubAccessManifestInterface, hubGrantedServiceIdInterface, hubServiceIdRegistryInterface, intersectServiceIdScopes, isServiceIdUnder, isValidServiceId, mapTransport, normalizeServiceIdScopes, registerGrantedServiceId, serviceIdMatchesPattern, serviceIdMatchesScopes, splitServiceId, walkHub, walkHubDetailed };
1189
+ //# sourceMappingURL=index.d.ts.map