@hediet/linkrpc-hub 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 (50) hide show
  1. package/README.md +101 -0
  2. package/dist/chunks/config-BCvkg7jv.d.ts +566 -0
  3. package/dist/chunks/configFile-y6Phntqu.d.ts +9 -0
  4. package/dist/chunks/connectionTokenBinder.interfaces-B-beCg06.js +40 -0
  5. package/dist/chunks/connectionTokenBinder.interfaces-B-beCg06.js.map +1 -0
  6. package/dist/chunks/connectionTokenBinder.interfaces-BhzQ1DTS.d.ts +36 -0
  7. package/dist/chunks/hubConnectionAcceptor-B5-8JsFY.js +2768 -0
  8. package/dist/chunks/hubConnectionAcceptor-B5-8JsFY.js.map +1 -0
  9. package/dist/chunks/hubConnectionAcceptor-BwydvFa4.d.ts +1560 -0
  10. package/dist/chunks/index-CLIUrV88.d.ts +481 -0
  11. package/dist/chunks/node-CTXsQ6oa.js +460 -0
  12. package/dist/chunks/node-CTXsQ6oa.js.map +1 -0
  13. package/dist/chunks/nodeTransit-CWeFnbwt.js +444 -0
  14. package/dist/chunks/nodeTransit-CWeFnbwt.js.map +1 -0
  15. package/dist/chunks/nodeTransit-cmtZgdpW.d.ts +226 -0
  16. package/dist/chunks/runHub-P3YUwwdv.js +1797 -0
  17. package/dist/chunks/runHub-P3YUwwdv.js.map +1 -0
  18. package/dist/chunks/server-BAxchQhy.js +1368 -0
  19. package/dist/chunks/server-BAxchQhy.js.map +1 -0
  20. package/dist/cli.d.ts +1 -0
  21. package/dist/cli.js +38 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/config.d.ts +2 -0
  24. package/dist/config.js +305 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/configFile.d.ts +2 -0
  27. package/dist/configFile.js +27 -0
  28. package/dist/configFile.js.map +1 -0
  29. package/dist/engine/runHub.d.ts +42 -0
  30. package/dist/engine/runHub.js +2 -0
  31. package/dist/hub/server/client.d.ts +2 -0
  32. package/dist/hub/server/client.js +2 -0
  33. package/dist/hub/server/connectionTokenBinder.d.ts +2 -0
  34. package/dist/hub/server/connectionTokenBinder.js +2 -0
  35. package/dist/hub/server/index.d.ts +5 -0
  36. package/dist/hub/server/index.js +5 -0
  37. package/dist/hub/server/node/index.d.ts +218 -0
  38. package/dist/hub/server/node/index.js +2 -0
  39. package/dist/hub/server/transit.d.ts +2 -0
  40. package/dist/hub/server/transit.js +2 -0
  41. package/dist/index.d.ts +512 -0
  42. package/dist/index.js +309 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/serve.d.ts +14 -0
  45. package/dist/serve.js +31 -0
  46. package/dist/serve.js.map +1 -0
  47. package/dist/spawn.d.ts +12 -0
  48. package/dist/spawn.js +25 -0
  49. package/dist/spawn.js.map +1 -0
  50. package/package.json +83 -0
@@ -0,0 +1,512 @@
1
+ import { _ as ProvisionConfig, a as ConsentApproverConfig, c as EndpointConfigSchema, d as HubConfig, f as HubConfigSchema, g as ParticipantConnectorConfigSchema, h as ParticipantConnectorConfig, i as ConnectionTokenBinderSchema, l as ForwardCheckingConfig, m as ListenerConfigSchema, n as ConnectionHandlerSchema, o as ConsentApproverSchema, p as ListenerConfig, r as ConnectionTokenBinderConfig, s as EndpointConfig, t as ConnectionHandlerConfig, u as ForwardCheckingSchema, v as hubConfigJsonSchema, y as parseHubConfig } from "./chunks/config-BCvkg7jv.js";
2
+ import { n as printHubConfigSchema, t as loadHubConfig } from "./chunks/configFile-y6Phntqu.js";
3
+ import { a as IdentityKeystore, c as IdentitySnooze, d as SlotByIdAndTimeResult, f as SlotId, l as SlotAccessKey, o as IdentityKeystoreOptions, p as createIdentityKeystore, s as IdentitySlot, u as SlotByIdAndKeyResult } from "./chunks/index-CLIUrV88.js";
4
+ import { _ as formatFlowSummary, a as FlowSummary, c as TrafficFlowAggregator } from "./chunks/nodeTransit-cmtZgdpW.js";
5
+ import { A as AccessCallIntent, F as AccessDirectPermission, I as AccessDuration, et as DirectoryEntry, j as AccessConsumer, q as CapabilityProposalIssuer, t as HubAccessConfig } from "./chunks/hubConnectionAcceptor-BwydvFa4.js";
6
+ import { ListenerInfo, RunHubOptions, RunningHub, runHub } from "./engine/runHub.js";
7
+ import { ServeHubOptions, serveHub } from "./serve.js";
8
+ import { spawnCommand } from "./spawn.js";
9
+ import { IMessageTransport, JsonValue, LinkRpcConnection, Pattern, Permission, PrincipalId, SignedCapability, SigningIdentity } from "@hediet/linkrpc";
10
+ import { HubAccessManifestDecision, HubAccessManifestRequest, IHubAccessManifest } from "@hediet/linkrpc/hub/common";
11
+ import { IObservable } from "@vscode/observables";
12
+ //#region src/engine/consent.d.ts
13
+ /**
14
+ * The outcome of a single consent prompt.
15
+ *
16
+ * - `{ grant: false }` — deny (optionally with a reason).
17
+ * - `{ grant: true, capabilities }` — approve. The approver minted the
18
+ * capabilities itself (with its own accepted-root identity); the keyless
19
+ * {@link HubAccessManifestHost} relays them verbatim. On a grant the
20
+ * capabilities are **required** — the host has no signing identity of its
21
+ * own.
22
+ */
23
+ type ConsentDecision = {
24
+ readonly grant: false;
25
+ readonly reason?: string;
26
+ } | {
27
+ readonly grant: true;
28
+ readonly capabilities?: readonly SignedCapability[];
29
+ };
30
+ /**
31
+ * Asks an approver to decide a single access request. Injected so different
32
+ * approvers (the terminal prompt, the hub-served manifest, tests) can supply the
33
+ * decision. May be aborted via {@link ConsentPromptRequest.signal} when another
34
+ * racing prompt settles first — implementations should stop waiting and clean up.
35
+ */
36
+ type ConsentPrompt = (request: ConsentPromptRequest) => Promise<ConsentDecision>;
37
+ interface ConsentPromptRequest {
38
+ /** Correlates the prompt with the blocked `hubAccess` call. */
39
+ readonly requestId: string;
40
+ /** Which `hubAccess` method is blocked on this request. */
41
+ readonly kind: 'request' | 'extend' | 'requestAccess';
42
+ /** Human-friendly description of who is asking. */
43
+ readonly consumer: {
44
+ readonly name: string;
45
+ readonly origin?: string;
46
+ readonly purpose?: string;
47
+ };
48
+ /** Verified PrincipalId of the calling consumer (the capability audience). */
49
+ readonly consumerPrincipalId: PrincipalId;
50
+ /**
51
+ * The exact authority requested. Each permission may carry the consent-only
52
+ * `callIntent` preview, so an approver can mint a byte-bound one-shot
53
+ * ("Allow once") capability.
54
+ */
55
+ readonly permissions: readonly AccessDirectPermission[];
56
+ /** One line per authority being requested (`serviceId::interfaceId member`). */
57
+ readonly grants: readonly string[];
58
+ /** `once` / `session` / `persistent`, when the consumer expressed one. */
59
+ readonly duration: string | undefined;
60
+ /** Aborts when another racing prompt has already settled this request. */
61
+ readonly signal: AbortSignal;
62
+ }
63
+ /** One human-readable line per permission, for an approver's UI / prompt. */
64
+ declare function describePermissions(permissions: readonly Permission[]): string[];
65
+ /**
66
+ * Strip the consent-only `callIntent` from each requested permission and, for a
67
+ * one-shot (`duration: 'once'`) grant whose intent declares a concrete call,
68
+ * pin the permission to that exact call via `callBind.payloadHash`. The result
69
+ * is the `Permission[]` to sign into the capability. Shared by the hub-issuer
70
+ * mint path and any inbox approver that wants to honor "Allow once".
71
+ *
72
+ * `callIntent` is never itself signed — only the derived `callBind` is.
73
+ */
74
+ declare function toSignedPermissions(permissions: readonly AccessDirectPermission[], consumerPrincipalId: PrincipalId, duration: string | undefined): Promise<Permission[]>;
75
+ /**
76
+ * Compute `callBind.payloadHash` for a grant bound to one consumer-declared
77
+ * call. Builds the SAME signed params the consumer commits to at sign time
78
+ * (`signedHash('call', { ...params, $hubrpc: meta })`); the forwarded-call gate
79
+ * re-derives this on the inbound call and checks the hash matches. The consumer
80
+ * owns `nonce`/`signedAtMs`, supplied via `callIntent`.
81
+ */
82
+ declare function computeCallBindHash(intent: AccessCallIntent, consumerPrincipalId: PrincipalId): Promise<string>;
83
+ /**
84
+ * A terminal yes/no consent prompt on stdin.
85
+ *
86
+ * When stdin is not a TTY (no operator to answer) it **abstains** — it never
87
+ * settles, parking until {@link ConsentPromptRequest.signal} aborts. This keeps
88
+ * it safe inside {@link raceConsent}: a non-interactive terminal must not win
89
+ * the race with an instant deny, or a hub-served inbox approval could never
90
+ * land. A headless hub should simply not install this prompt at all (or pair it
91
+ * with an inbox); on its own it grants nothing.
92
+ *
93
+ * When interactive, it resolves on the operator's answer, and abandons the
94
+ * readline prompt if the request is aborted (another prompt decided first).
95
+ */
96
+ declare function createTerminalConsentPrompt(): ConsentPrompt;
97
+ /**
98
+ * Compose several {@link ConsentPrompt}s into one that presents each request to
99
+ * **all** of them and takes the **first** to settle (first responder wins,
100
+ * including a deny). Once one settles, the rest are aborted via a shared signal
101
+ * so they can tear down (close the readline, drop the inbox entry). The
102
+ * incoming request's own signal is honored too: if the consumer cancels, every
103
+ * child prompt is aborted.
104
+ *
105
+ * This is what lets a single `hubAccess` request reach the hub operator's
106
+ * terminal prompt and a hub-served inbox at the same time.
107
+ */
108
+ declare function raceConsent(prompts: readonly ConsentPrompt[]): ConsentPrompt;
109
+ //#endregion
110
+ //#region src/engine/hubAccessConfig.d.ts
111
+ /** The normalized request every `hubAccess` shape collapses to before deciding. */
112
+ interface AccessRequestContext {
113
+ readonly kind: 'request' | 'extend' | 'requestAccess';
114
+ readonly consumer: AccessConsumer;
115
+ /** Capability audience — the consumer's own PrincipalId. */
116
+ readonly consumerPrincipalId: string;
117
+ /** The requested authority; permissions may carry a consent-only `callIntent`. */
118
+ readonly permissions: readonly AccessDirectPermission[];
119
+ readonly duration: AccessDuration | undefined;
120
+ }
121
+ /** Decides one normalized request, returning the approver-signed capabilities to relay. */
122
+ type AccessDecider = (ctx: AccessRequestContext) => Promise<ConsentDecision>;
123
+ /**
124
+ * Build the `hubAccess` front-door config from a single {@link AccessDecider}.
125
+ * The returned {@link HubAccessConfig} is what `registerHubAccessService`
126
+ * installs at a participant's overlay root.
127
+ */
128
+ declare function createHubAccessConfig(decide: AccessDecider, fetchDirectory?: () => Promise<readonly DirectoryEntry[]>): HubAccessConfig;
129
+ /** A one-line human summary of a request, for a decider's log. */
130
+ declare function describeRequest(ctx: AccessRequestContext): string;
131
+ /** Build one permission per requested interface, scoped to `serviceId`. */
132
+ declare function buildSlotPermissions(serviceId: string, interfaces: readonly {
133
+ id: string;
134
+ hash?: string;
135
+ }[], members: readonly {
136
+ interfaceId: string;
137
+ member: Pattern;
138
+ }[], present: ReadonlySet<string>): Permission[];
139
+ //#endregion
140
+ //#region src/engine/hubAccessGrantSigner.d.ts
141
+ /** A grant policy's verdict on one request. */
142
+ type GrantVerdict = {
143
+ readonly result: 'permitted';
144
+ } | {
145
+ readonly result: 'rejected';
146
+ readonly reason?: string;
147
+ };
148
+ /** Decides whether to grant a normalized request. May be sync or async. */
149
+ type GrantPolicy = (request: AccessRequestContext) => GrantVerdict | Promise<GrantVerdict>;
150
+ declare class HubAccessGrantSigner {
151
+ private readonly _grant;
152
+ private readonly _issuer;
153
+ constructor(signingIdentity: SigningIdentity, _grant: GrantPolicy);
154
+ /**
155
+ * The {@link AccessDecider}: consult the grant policy and, on `permitted`,
156
+ * mint a capability with the held identity (audience = the consumer,
157
+ * honoring "Allow once" `callBind` byte-binding for one-shot durations).
158
+ */
159
+ readonly decide: AccessDecider;
160
+ private _mint;
161
+ }
162
+ //#endregion
163
+ //#region src/engine/hubAccessManifest.d.ts
164
+ /** One interface a discover slot's chosen service must implement. */
165
+ interface ManifestInterfaceReq {
166
+ readonly id: string;
167
+ readonly hash?: string;
168
+ readonly required?: boolean;
169
+ }
170
+ /** One member a discover slot's consumer intends to call. */
171
+ interface ManifestMemberReq {
172
+ readonly interfaceId: string;
173
+ readonly member: Pattern;
174
+ readonly required?: boolean;
175
+ }
176
+ interface PendingBase {
177
+ readonly requestId: string;
178
+ readonly consumer: {
179
+ readonly name: string;
180
+ readonly origin?: string;
181
+ readonly purpose?: string;
182
+ };
183
+ readonly consumerPrincipalId: string;
184
+ readonly duration: string | undefined;
185
+ /**
186
+ * Host-authored provenance bag, bound per transport at
187
+ * {@link HubAccessManifestHost.registerHubAccessAtRoot} — never read from the
188
+ * request params. Relayed verbatim in `getDesired`; the host does not
189
+ * interpret it.
190
+ */
191
+ readonly origin?: Record<string, unknown>;
192
+ }
193
+ /** A parked, undecided request — the host's view of one desired entry. */
194
+ type PendingManifestEntry = (PendingBase & {
195
+ readonly kind: 'direct';
196
+ /** Verbatim requested authority; permissions may carry a `callIntent`. */
197
+ readonly permissions: readonly AccessDirectPermission[];
198
+ }) | (PendingBase & {
199
+ readonly kind: 'discover';
200
+ /** The interfaces the chosen service must implement (unresolved). */
201
+ readonly interfaces: readonly ManifestInterfaceReq[];
202
+ /** The members the consumer intends to call. */
203
+ readonly members: readonly ManifestMemberReq[];
204
+ });
205
+ /**
206
+ * The approver's decision for one parked entry, delivered via `setCurrent`.
207
+ * A `discover` grant additionally names the chosen service (`resolvedSlot`).
208
+ */
209
+ type ManifestEntryDecision = {
210
+ readonly grant: false;
211
+ readonly reason?: string;
212
+ } | {
213
+ readonly grant: true;
214
+ readonly capabilities: readonly SignedCapability[];
215
+ /** Present for a `discover` grant: which service the approver picked. */
216
+ readonly resolvedSlot?: {
217
+ readonly serviceId: string;
218
+ readonly satisfiedInterfaces: readonly string[];
219
+ };
220
+ };
221
+ interface HubAccessManifestHostOptions {
222
+ /**
223
+ * Root issuer principals the hub's forwarded-call gate accepts. Published as
224
+ * each desired entry's `acceptableRootIds`, so an approver only acts on
225
+ * entries it can satisfy (it is — or chains to — one of these). Omit/empty to
226
+ * leave the roots unspecified (approver decides).
227
+ */
228
+ readonly acceptableRootIds?: readonly string[];
229
+ /** Human log sink for incoming requests. Defaults to stderr. */
230
+ readonly log?: (line: string) => void;
231
+ }
232
+ declare class HubAccessManifestHost {
233
+ private readonly _pending;
234
+ private readonly _listeners;
235
+ private readonly _acceptableRootIds;
236
+ private readonly _log;
237
+ private _revision;
238
+ constructor(options?: HubAccessManifestHostOptions);
239
+ /**
240
+ * Register `hubAccess::{request,extend,requestAccess}` directly at a
241
+ * participant's overlay root (root form, never forwarded → never gated).
242
+ * Unlike `registerHubAccessService` this consults **no** hub-side directory:
243
+ * `request` forwards raw slots as `discover` entries for the approver to
244
+ * resolve.
245
+ *
246
+ * `options.origin` is a host-authored provenance bag bound to THIS
247
+ * connection and stamped onto every entry parked here. It is bound
248
+ * server-side (not read from the consumer's request params) so a consumer
249
+ * cannot spoof another transport's origin. The host relays it verbatim; it
250
+ * does not interpret it.
251
+ */
252
+ registerHubAccessAtRoot(connection: LinkRpcConnection<unknown>, options?: {
253
+ readonly origin?: Record<string, unknown>;
254
+ }): void;
255
+ /** Park a desired entry and await the approver's decision (via `setCurrent`). */
256
+ private _park;
257
+ /** Snapshot of the desired document (entryId → desired entry) + revision. */
258
+ getDesired(): {
259
+ entries: PendingManifestEntry[];
260
+ acceptableRootIds: readonly string[];
261
+ revision: number;
262
+ };
263
+ /**
264
+ * Resolve a parked entry from a `setCurrent` decision. Returns `false` when
265
+ * no entry with that id is pending (already decided / cancelled).
266
+ */
267
+ resolve(requestId: string, decision: ManifestEntryDecision): boolean;
268
+ /** Subscribe to coarse "desired set may have changed" notifications. */
269
+ onDidChange(listener: () => void): () => void;
270
+ private _bump;
271
+ }
272
+ /**
273
+ * Serve `hubAccessManifest::*` on `connection`, mounted under `serviceId` (the
274
+ * hub's own service prefix). Reachable only through the forwarded-call gate, so
275
+ * authorization (an accepted-root capability) is enforced upstream — no gate is
276
+ * applied here.
277
+ *
278
+ * `getCurrent`/`watchCurrent` are vestigial for the hub broker: granted caps are
279
+ * delivered as the blocked `hubAccess` call's result, not read back through
280
+ * `current`. They are served (empty) to satisfy the interface.
281
+ */
282
+ declare function registerHubAccessManifest(connection: LinkRpcConnection<unknown>, host: HubAccessManifestHost, options: {
283
+ readonly serviceId: string;
284
+ }): void;
285
+ //#endregion
286
+ //#region src/engine/manifestApprover.d.ts
287
+ interface ManifestApproverOptions {
288
+ /**
289
+ * The manifest to consume. Just the typed client of
290
+ * {@link hubAccessManifestInterface} — obtained over any connection
291
+ * (`connection.service(id).get(hubAccessManifestInterface)`), in-memory or
292
+ * remote. The approver never touches a raw connection for the manifest
293
+ * surface.
294
+ */
295
+ readonly manifest: IHubAccessManifest;
296
+ /**
297
+ * Resolve `discover` entries against the participant directory. Supplied by
298
+ * the caller because directory access needs the approver's own signed
299
+ * connection (the approver holds the key). Omit if this approver never
300
+ * expects `discover` entries — such entries are then denied.
301
+ */
302
+ readonly fetchDirectory?: () => Promise<readonly DirectoryEntry[]>;
303
+ /** Mints the approver's own capabilities (audience = the entry's consumer). */
304
+ readonly issuer: CapabilityProposalIssuer;
305
+ /**
306
+ * This approver's own root principal. An entry is acted on only if its
307
+ * `acceptableRootIds` is absent or includes this id —
308
+ * otherwise the approver's signature would be useless to the consumer.
309
+ * Defaults to the issuer's principal.
310
+ */
311
+ readonly ownPrincipalId?: string;
312
+ /** Decision source. Defaults to a terminal y/N prompt on stdin. */
313
+ readonly prompt?: ConsentPrompt;
314
+ /** Human log sink. Defaults to stderr. */
315
+ readonly log?: (line: string) => void;
316
+ }
317
+ interface ManifestApprover {
318
+ /** Stop watching and abort any in-flight prompt. */
319
+ dispose(): void;
320
+ }
321
+ /**
322
+ * Start consuming the manifest at `options.serviceId` over `options.connection`.
323
+ * Runs until {@link ManifestApprover.dispose}.
324
+ */
325
+ declare function runManifestApprover(options: ManifestApproverOptions): ManifestApprover;
326
+ //#endregion
327
+ //#region src/engine/approveClient.d.ts
328
+ interface CapRequest {
329
+ readonly id: string;
330
+ readonly request: HubAccessManifestRequest;
331
+ readonly revision: number;
332
+ }
333
+ type ApproveClientState = 'connecting' | 'live' | 'stale';
334
+ interface ApproveClientOptions {
335
+ readonly manifest: IHubAccessManifest;
336
+ /** Only expose requests this root can satisfy. Omit to expose every request. */
337
+ readonly ownPrincipalId?: string;
338
+ readonly log?: (line: string) => void;
339
+ readonly reconnectDelayMs?: number;
340
+ readonly timeoutMs?: number;
341
+ }
342
+ /**
343
+ * Authoritative, typed frontend for a `hubAccessManifest`.
344
+ *
345
+ * Consumers render {@link requests}; coarse watch ticks are reconciled through
346
+ * one serialized full-snapshot loop, so older reads cannot overwrite newer
347
+ * state. A completed watch is re-opened and a failed read keeps the last known
348
+ * snapshot while {@link state} reports `stale`.
349
+ */
350
+ declare class ApproveClient {
351
+ private readonly _requests;
352
+ readonly requests: IObservable<readonly CapRequest[]>;
353
+ private readonly _state;
354
+ readonly state: IObservable<ApproveClientState>;
355
+ private readonly _manifest;
356
+ private readonly _ownPrincipalId;
357
+ private readonly _log;
358
+ private readonly _reconnectDelayMs;
359
+ private readonly _timeoutMs;
360
+ private _watch;
361
+ private _watchGeneration;
362
+ private _retryTimer;
363
+ private _refreshPending;
364
+ private _refreshPromise;
365
+ private _disposed;
366
+ constructor(options: ApproveClientOptions);
367
+ /** Reconcile the observable with the latest complete desired snapshot. */
368
+ refresh(): Promise<void>;
369
+ /**
370
+ * Write a decision only for a request in the current snapshot, then reconcile
371
+ * with the next authoritative snapshot. A successful write can still leave a
372
+ * matching id pending when a federated snapshot lags or the consumer retries;
373
+ * callers receive `still-pending` so they can report that state honestly.
374
+ */
375
+ decide(id: string, decision: HubAccessManifestDecision): Promise<'applied' | 'gone' | 'still-pending'>;
376
+ dispose(): void;
377
+ private _drainRefreshes;
378
+ private _openWatch;
379
+ private _watchEnded;
380
+ private _scheduleReconnect;
381
+ }
382
+ //#endregion
383
+ //#region src/engine/aggregatingManifest.d.ts
384
+ /** The `{ requested, revision }` document `hubAccessManifest::getDesired` returns. */
385
+ type GetDesiredResult = Awaited<ReturnType<IHubAccessManifest['getDesired']>>;
386
+ /** A single `hubAccessManifest::setCurrent` patch. */
387
+ type ManifestPatch = Parameters<IHubAccessManifest['setCurrent']>[0]['patches'][number];
388
+ /** A manifest the aggregator merges, tagged and origin-policied. */
389
+ interface AggregatorSource {
390
+ /**
391
+ * Stable id that namespaces this source's entryIds in the merged document
392
+ * (and routes `setCurrent` back). For a discovered source, its serviceId.
393
+ */
394
+ readonly tag: string;
395
+ /** The source manifest client. */
396
+ readonly manifest: IHubAccessManifest;
397
+ /**
398
+ * Pass each entry's `origin` bag through verbatim (true) or strip it
399
+ * (false, default). Set true ONLY for a trusted-local source whose
400
+ * `sourceTransportId` addresses a local UI; a remote source's origin must be
401
+ * stripped so it can never address a local iframe.
402
+ */
403
+ readonly preserveOrigin?: boolean;
404
+ }
405
+ interface AggregatingManifestOptions {
406
+ /**
407
+ * Resolve the current set of source manifests (the local loopback plus
408
+ * whatever the caller discovers by scanning the hub). Re-invoked on every
409
+ * {@link AggregatingHubAccessManifest.getDesired}, so newly-appeared sources
410
+ * are picked up.
411
+ */
412
+ readonly resolveSources: () => Promise<readonly AggregatorSource[]> | readonly AggregatorSource[];
413
+ /**
414
+ * Optional: subscribe to "the *set* of sources may have changed" — e.g. the
415
+ * hub's `hubrpc.directory::watch`, which ticks when a service appears or
416
+ * disappears. Each tick re-emits a change (so a watching approver re-`getDesired`,
417
+ * which re-runs {@link resolveSources} and discovers the new/removed source).
418
+ * Without it, a brand-new manifest is only noticed when some *already-known*
419
+ * source ticks or the approver polls. Returns a teardown.
420
+ */
421
+ readonly watchSources?: (onChange: () => void) => () => void;
422
+ /** Human log sink. */
423
+ readonly log?: (line: string) => void;
424
+ /** Hard deadline for each source request. Defaults to 5 seconds. */
425
+ readonly timeoutMs?: number;
426
+ }
427
+ declare class AggregatingHubAccessManifest {
428
+ private readonly _options;
429
+ private readonly _listeners;
430
+ private _revision;
431
+ /** tag → source, refreshed on every {@link _refresh}. Used to route `setCurrent`. */
432
+ private _byTag;
433
+ /** tag → resilient watch for that exact source incarnation. */
434
+ private readonly _watches;
435
+ /** Teardown for the source-set watch (e.g. directory watch), started lazily. */
436
+ private _sourcesWatchOff;
437
+ private _refreshPromise;
438
+ private _disposed;
439
+ constructor(_options: AggregatingManifestOptions);
440
+ /** Fire whenever any source's desired set may have changed (drives `watchDesired`). */
441
+ onDidChange(cb: () => void): () => void;
442
+ private _emit;
443
+ /** Resolve the source set, (un)subscribing watches to match, and cache it by tag. */
444
+ private _refresh;
445
+ private _doRefresh;
446
+ private _openWatch;
447
+ private _startWatch;
448
+ private _watchEnded;
449
+ private _closeWatch;
450
+ /** Merge every source's desired document into one, namespacing ids by source tag. */
451
+ getDesired(): Promise<GetDesiredResult>;
452
+ /** Route each decision patch back to the source that parked the entry. */
453
+ setCurrent(patches: readonly ManifestPatch[]): Promise<void>;
454
+ dispose(): void;
455
+ }
456
+ /**
457
+ * Serve an {@link AggregatingHubAccessManifest} over `connection` as an ordinary
458
+ * `hubAccessManifest` — so an approver consumes it via
459
+ * `connection.service(serviceId).get(hubAccessManifestInterface)` with no idea it
460
+ * is an aggregate. `current` is never read back (decisions flow through
461
+ * `setCurrent` to the sources), so `getCurrent`/`watchCurrent` are served empty.
462
+ */
463
+ declare function registerAggregatingManifest(connection: LinkRpcConnection<unknown>, aggregator: AggregatingHubAccessManifest, options: {
464
+ readonly serviceId: string;
465
+ }): void;
466
+ //#endregion
467
+ //#region src/engine/watchHubDirectoryTree.d.ts
468
+ interface WatchHubDirectoryTreeOptions {
469
+ /** Bound the referral recursion (forwarded to {@link walkHubDetailed}). */
470
+ readonly maxDepth?: number;
471
+ /** Human log sink for watch/reconciliation failures. */
472
+ readonly log?: (line: string) => void;
473
+ }
474
+ declare function watchHubDirectoryTree(connection: LinkRpcConnection, rootTarget: string, onChange: () => void, options?: WatchHubDirectoryTreeOptions): () => void;
475
+ //#endregion
476
+ //#region src/engine/configuredParticipants.d.ts
477
+ interface ConfiguredParticipant {
478
+ readonly name: string;
479
+ readonly config: ParticipantConnectorConfig;
480
+ }
481
+ interface ConfigureParticipantsOptions {
482
+ readonly participants: readonly ConfiguredParticipant[];
483
+ /**
484
+ * Attach a connected transport at the host's trust boundary. Standalone
485
+ * hubs attach directly; embedded hosts can insert their capability gate.
486
+ */
487
+ readonly attachParticipant: (transport: IMessageTransport) => ConfiguredParticipantAttachment;
488
+ readonly log?: (line: string) => void;
489
+ /** Forward stdin to the single cmd-stdio participant. */
490
+ readonly cmdInteractive?: boolean;
491
+ }
492
+ interface ConfiguredParticipants {
493
+ dispose(): void;
494
+ }
495
+ interface ConfiguredParticipantAttachment {
496
+ claimPrefix(prefix: string): void;
497
+ setDefaultRoute(): void;
498
+ request(method: string, params: JsonValue, timeoutMs?: number): Promise<JsonValue | undefined>;
499
+ dispose(): void;
500
+ }
501
+ /**
502
+ * Attach settings/config-defined outbound participants to an existing Hub.
503
+ *
504
+ * Each participant is supervised independently: it connects in the background,
505
+ * claims its configured service ids on the far end, installs its local routes,
506
+ * and reconnects with exponential backoff after a disconnect.
507
+ */
508
+ declare function configureParticipants(options: ConfigureParticipantsOptions): ConfiguredParticipants;
509
+ declare function validateConfiguredParticipants(participants: readonly ConfiguredParticipant[]): void;
510
+ //#endregion
511
+ export { type AccessDecider, type AccessRequestContext, AggregatingHubAccessManifest, type AggregatingManifestOptions, type AggregatorSource, ApproveClient, type ApproveClientOptions, type ApproveClientState, type CapRequest, type ConfigureParticipantsOptions, type ConfiguredParticipant, type ConfiguredParticipantAttachment, type ConfiguredParticipants, type ConnectionHandlerConfig, ConnectionHandlerSchema, type ConnectionTokenBinderConfig, ConnectionTokenBinderSchema, type ConsentApproverConfig, ConsentApproverSchema, type ConsentDecision, type ConsentPrompt, type ConsentPromptRequest, type EndpointConfig, EndpointConfigSchema, type FlowSummary, type ForwardCheckingConfig, ForwardCheckingSchema, type GrantPolicy, type GrantVerdict, HubAccessGrantSigner, HubAccessManifestHost, type HubAccessManifestHostOptions, type HubConfig, HubConfigSchema, type IdentityKeystore, type IdentityKeystoreOptions, type IdentitySlot, type IdentitySnooze, type ListenerConfig, ListenerConfigSchema, type ListenerInfo, type ManifestApprover, type ManifestApproverOptions, type ManifestEntryDecision, type ManifestInterfaceReq, type ManifestMemberReq, type ParticipantConnectorConfig, ParticipantConnectorConfigSchema, type PendingManifestEntry, type ProvisionConfig, type RunHubOptions, type RunningHub, type ServeHubOptions, type SlotAccessKey, type SlotByIdAndKeyResult, type SlotByIdAndTimeResult, type SlotId, TrafficFlowAggregator, type WatchHubDirectoryTreeOptions, buildSlotPermissions, computeCallBindHash, configureParticipants, createHubAccessConfig, createIdentityKeystore, createTerminalConsentPrompt, describePermissions, describeRequest, formatFlowSummary, hubConfigJsonSchema, loadHubConfig, parseHubConfig, printHubConfigSchema, raceConsent, registerAggregatingManifest, registerHubAccessManifest, runHub, runManifestApprover, serveHub, spawnCommand, toSignedPermissions, validateConfiguredParticipants, watchHubDirectoryTree };
512
+ //# sourceMappingURL=index.d.ts.map