@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.
- package/README.md +101 -0
- package/dist/chunks/config-BCvkg7jv.d.ts +566 -0
- package/dist/chunks/configFile-y6Phntqu.d.ts +9 -0
- package/dist/chunks/connectionTokenBinder.interfaces-B-beCg06.js +40 -0
- package/dist/chunks/connectionTokenBinder.interfaces-B-beCg06.js.map +1 -0
- package/dist/chunks/connectionTokenBinder.interfaces-BhzQ1DTS.d.ts +36 -0
- package/dist/chunks/hubConnectionAcceptor-B5-8JsFY.js +2768 -0
- package/dist/chunks/hubConnectionAcceptor-B5-8JsFY.js.map +1 -0
- package/dist/chunks/hubConnectionAcceptor-BwydvFa4.d.ts +1560 -0
- package/dist/chunks/index-CLIUrV88.d.ts +481 -0
- package/dist/chunks/node-CTXsQ6oa.js +460 -0
- package/dist/chunks/node-CTXsQ6oa.js.map +1 -0
- package/dist/chunks/nodeTransit-CWeFnbwt.js +444 -0
- package/dist/chunks/nodeTransit-CWeFnbwt.js.map +1 -0
- package/dist/chunks/nodeTransit-cmtZgdpW.d.ts +226 -0
- package/dist/chunks/runHub-P3YUwwdv.js +1797 -0
- package/dist/chunks/runHub-P3YUwwdv.js.map +1 -0
- package/dist/chunks/server-BAxchQhy.js +1368 -0
- package/dist/chunks/server-BAxchQhy.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +38 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +305 -0
- package/dist/config.js.map +1 -0
- package/dist/configFile.d.ts +2 -0
- package/dist/configFile.js +27 -0
- package/dist/configFile.js.map +1 -0
- package/dist/engine/runHub.d.ts +42 -0
- package/dist/engine/runHub.js +2 -0
- package/dist/hub/server/client.d.ts +2 -0
- package/dist/hub/server/client.js +2 -0
- package/dist/hub/server/connectionTokenBinder.d.ts +2 -0
- package/dist/hub/server/connectionTokenBinder.js +2 -0
- package/dist/hub/server/index.d.ts +5 -0
- package/dist/hub/server/index.js +5 -0
- package/dist/hub/server/node/index.d.ts +218 -0
- package/dist/hub/server/node/index.js +2 -0
- package/dist/hub/server/transit.d.ts +2 -0
- package/dist/hub/server/transit.js +2 -0
- package/dist/index.d.ts +512 -0
- package/dist/index.js +309 -0
- package/dist/index.js.map +1 -0
- package/dist/serve.d.ts +14 -0
- package/dist/serve.js +31 -0
- package/dist/serve.js.map +1 -0
- package/dist/spawn.d.ts +12 -0
- package/dist/spawn.js +25 -0
- package/dist/spawn.js.map +1 -0
- package/package.json +83 -0
package/dist/index.d.ts
ADDED
|
@@ -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
|