@hediet/linkrpc 0.0.2 → 0.0.3-next.20260922.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 +266 -31
- package/dist/chunks/{hub.interfaces-Bf4VfWNX.js → hub.interfaces-Deslgtgr.js} +2 -2
- package/dist/chunks/{hub.interfaces-Bf4VfWNX.js.map → hub.interfaces-Deslgtgr.js.map} +1 -1
- package/dist/chunks/{hubAccess-C06qAKao.d.ts → hubAccess-BmPvNNaM.d.ts} +2 -2
- package/dist/chunks/{hubAccess-C06qAKao.d.ts.map → hubAccess-BmPvNNaM.d.ts.map} +1 -1
- package/dist/chunks/{hubFacade-BIB9CoAv.js → hubFacade-BKTQXCdF.js} +2 -2
- package/dist/chunks/{hubFacade-BIB9CoAv.js.map → hubFacade-BKTQXCdF.js.map} +1 -1
- package/dist/chunks/{hubFacade-DtQpGpUy.d.ts → hubFacade-Bmh-SFWd.d.ts} +2 -2
- package/dist/chunks/{hubFacade-DtQpGpUy.d.ts.map → hubFacade-Bmh-SFWd.d.ts.map} +1 -1
- package/dist/chunks/{boundedTrafficSubscription-XZ1KwXZC.js → inspectionHost-BIkLKvr1.js} +1014 -32
- package/dist/chunks/inspectionHost-BIkLKvr1.js.map +1 -0
- package/dist/chunks/{linkRpcConnection-BadD37ok.d.ts → linkRpcConnection-Bbq20hQG.d.ts} +2215 -1699
- package/dist/chunks/linkRpcConnection-Bbq20hQG.d.ts.map +1 -0
- package/dist/chunks/{src-CAhXne71.js → src-DKjTceek.js} +1975 -2051
- package/dist/chunks/src-DKjTceek.js.map +1 -0
- package/dist/hub/client/index.d.ts +3 -3
- package/dist/hub/client/index.js +3 -3
- package/dist/hub/common/index.d.ts +2 -325
- package/dist/hub/common/index.d.ts.map +1 -1
- package/dist/hub/common/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/inspection/index.d.ts +87 -2
- package/dist/inspection/index.d.ts.map +1 -1
- package/dist/inspection/index.js +2 -2
- package/dist/node.d.ts +3 -3
- package/dist/node.js +4 -4
- package/dist/web.d.ts +2 -2
- package/dist/web.js +3 -3
- package/package.json +7 -2
- package/dist/chunks/boundedTrafficSubscription-XZ1KwXZC.js.map +0 -1
- package/dist/chunks/linkRpcConnection-BadD37ok.d.ts.map +0 -1
- package/dist/chunks/src-CAhXne71.js.map +0 -1
|
@@ -42,6 +42,8 @@ interface JsonRpcError {
|
|
|
42
42
|
type JsonRpcResponse = JsonRpcSuccess | JsonRpcError;
|
|
43
43
|
type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;
|
|
44
44
|
declare const ErrorCode: {
|
|
45
|
+
/** Default code for named LinkRPC application errors. */
|
|
46
|
+
readonly applicationError: 1;
|
|
45
47
|
readonly parseError: -32700;
|
|
46
48
|
readonly invalidRequest: -32600;
|
|
47
49
|
readonly methodNotFound: -32601;
|
|
@@ -204,7 +206,7 @@ interface MethodSchema {
|
|
|
204
206
|
* may not stream on this method.
|
|
205
207
|
*/
|
|
206
208
|
serverStream?: LinkRpcJsonSchema;
|
|
207
|
-
/**
|
|
209
|
+
/** Raw codes are exclusive; named and legacy declarations may form a union per code. */
|
|
208
210
|
errors?: ErrorSchema[];
|
|
209
211
|
summary?: string;
|
|
210
212
|
/**
|
|
@@ -262,14 +264,41 @@ interface MemberAnnotations {
|
|
|
262
264
|
*/
|
|
263
265
|
dangerous?: boolean;
|
|
264
266
|
}
|
|
265
|
-
|
|
267
|
+
type ErrorSchema = LegacyErrorSchema | RawErrorSchema;
|
|
268
|
+
interface RawErrorSchema {
|
|
269
|
+
code: number;
|
|
270
|
+
/** Schema of the wire body { message, data? }, excluding the outer code. */
|
|
271
|
+
schema: LinkRpcJsonSchema;
|
|
272
|
+
type?: never;
|
|
273
|
+
message?: never;
|
|
274
|
+
data?: never;
|
|
275
|
+
}
|
|
276
|
+
interface LegacyErrorSchema {
|
|
277
|
+
schema?: never;
|
|
278
|
+
/** Named error discriminator in `error.data.type`. Absent for legacy numeric errors. */
|
|
279
|
+
type?: string;
|
|
266
280
|
/** JSON-RPC error code. -32768..-32000 and LinkRPC cancellation code -32800 are reserved. */
|
|
267
281
|
code: number;
|
|
268
282
|
message: string;
|
|
269
|
-
/**
|
|
283
|
+
/** Payload schema: `error.data.data` for named errors, `error.data` for legacy errors. */
|
|
270
284
|
data?: LinkRpcJsonSchema;
|
|
271
285
|
}
|
|
272
286
|
//#endregion
|
|
287
|
+
//#region src/connection/rpcFailure.d.ts
|
|
288
|
+
declare const rpcFailureBrand: unique symbol;
|
|
289
|
+
/** A nominal failure wrapper: successful application objects can never collide with it. */
|
|
290
|
+
declare class RpcFailure<E> {
|
|
291
|
+
readonly error: E;
|
|
292
|
+
readonly [rpcFailureBrand] = true;
|
|
293
|
+
constructor(error: E);
|
|
294
|
+
}
|
|
295
|
+
type Result$1<T, E = never> = T | RpcFailure<E>;
|
|
296
|
+
declare function isRpcFailure<T, E>(value: Result$1<T, E>): value is RpcFailure<E>;
|
|
297
|
+
declare function isRpcFailure(value: unknown): value is RpcFailure<unknown>;
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/schema/applicationErrorBrand.d.ts
|
|
300
|
+
declare const applicationErrorBrand: unique symbol;
|
|
301
|
+
//#endregion
|
|
273
302
|
//#region src/schema/memberTypes.d.ts
|
|
274
303
|
/**
|
|
275
304
|
* The schema type linkrpc accepts everywhere: the zod *core* base shared by
|
|
@@ -286,8 +315,7 @@ type Schema<O = unknown> = $ZodType<O>;
|
|
|
286
315
|
* - propagate TS types up to the interface definition.
|
|
287
316
|
*/
|
|
288
317
|
type MemberType = RequestType<any, any, any, any, any, any, any> | NotificationType<any>;
|
|
289
|
-
|
|
290
|
-
type ApplicationErrorValue<TCode extends number = number, TMessage extends string = string, TData = never> = {
|
|
318
|
+
type ApplicationErrorValue<TCode extends number = number, TMessage extends string = string, TData = never, TType extends string | undefined = undefined> = {
|
|
291
319
|
readonly kind: 'application';
|
|
292
320
|
readonly code: TCode;
|
|
293
321
|
readonly message: TMessage;
|
|
@@ -295,33 +323,104 @@ type ApplicationErrorValue<TCode extends number = number, TMessage extends strin
|
|
|
295
323
|
readonly data?: never;
|
|
296
324
|
} : {
|
|
297
325
|
readonly data: TData;
|
|
326
|
+
}) & (TType extends string ? {
|
|
327
|
+
readonly type: TType;
|
|
328
|
+
} : {
|
|
329
|
+
readonly type?: never;
|
|
298
330
|
});
|
|
299
|
-
type CreatedApplicationErrorValue<TCode extends number = number, TMessage extends string = string, TData = never> = ApplicationErrorValue<TCode, TMessage, TData> & {
|
|
331
|
+
type CreatedApplicationErrorValue<TCode extends number = number, TMessage extends string = string, TData = never, TType extends string | undefined = undefined> = ApplicationErrorValue<TCode, TMessage, TData, TType> & {
|
|
300
332
|
readonly [applicationErrorBrand]: true;
|
|
301
333
|
};
|
|
302
|
-
interface ApplicationErrorDescriptor<TCode extends number = number, TMessage extends string = string, TData = never> {
|
|
334
|
+
interface ApplicationErrorDescriptor<TCode extends number = number, TMessage extends string = string, TData = never, TType extends string | undefined = undefined> {
|
|
303
335
|
readonly code: TCode;
|
|
304
336
|
readonly message: TMessage;
|
|
305
337
|
readonly dataSchema?: Schema<TData>;
|
|
306
|
-
readonly
|
|
338
|
+
readonly type: TType;
|
|
339
|
+
/** Match a validated application payload or its failure wrapper. */
|
|
340
|
+
is(value: RpcFailure<unknown>): value is RpcFailure<ApplicationErrorValue<TCode, string, TData, TType>>;
|
|
341
|
+
is(value: {
|
|
342
|
+
readonly kind: 'application';
|
|
343
|
+
}): value is ApplicationErrorValue<TCode, string, TData, TType>;
|
|
344
|
+
is(value: unknown): value is ApplicationErrorValue<TCode, string, TData, TType> | RpcFailure<ApplicationErrorValue<TCode, string, TData, TType>>;
|
|
345
|
+
readonly create: [TData] extends [never] ? () => CreatedApplicationErrorValue<TCode, TMessage, TData, TType> : (data: TData) => CreatedApplicationErrorValue<TCode, TMessage, TData, TType>;
|
|
307
346
|
}
|
|
308
347
|
interface ApplicationErrorDescriptorBase {
|
|
348
|
+
readonly type?: string;
|
|
309
349
|
readonly code: number;
|
|
310
|
-
readonly message
|
|
350
|
+
readonly message?: string;
|
|
351
|
+
readonly bodySchema?: Schema;
|
|
311
352
|
readonly dataSchema?: Schema<any>;
|
|
312
353
|
readonly create: (...args: any[]) => {
|
|
313
354
|
readonly kind: 'application';
|
|
314
355
|
readonly code: number;
|
|
315
356
|
readonly message: string;
|
|
316
357
|
readonly data?: unknown;
|
|
358
|
+
readonly type?: string;
|
|
317
359
|
readonly [applicationErrorBrand]: true;
|
|
318
360
|
};
|
|
319
361
|
}
|
|
320
|
-
type ApplicationErrorOf<T> = T extends ApplicationErrorDescriptor<infer C, infer M, infer D> ? CreatedApplicationErrorValue<C, M, D> : never;
|
|
321
|
-
type PublicApplicationErrorOf<T> = 0 extends (1 & T) ? never : T extends
|
|
362
|
+
type ApplicationErrorOf<T> = T extends RpcErrorDescriptor<infer C, infer B> ? CreatedRpcErrorValue<C, B> : T extends ApplicationErrorDescriptor<infer C, infer M, infer D, infer N> ? CreatedApplicationErrorValue<C, M, D, N> : never;
|
|
363
|
+
type PublicApplicationErrorOf<T> = 0 extends (1 & T) ? never : T extends {
|
|
364
|
+
readonly [rawErrorBrand]: true;
|
|
365
|
+
} ? Omit<T, typeof applicationErrorBrand | typeof rawErrorBrand> : T extends CreatedApplicationErrorValue<infer C, infer M, infer D, infer N> ? ApplicationErrorValue<C, N extends string ? string : M, D, N> : never;
|
|
322
366
|
type DeclaredApplicationErrorOf<T> = 0 extends (1 & T) ? never : Extract<T, ReturnType<ApplicationErrorDescriptorBase['create']>>;
|
|
323
367
|
type ApplicationErrorsOf<T extends readonly ApplicationErrorDescriptorBase[]> = ApplicationErrorOf<T[number]>;
|
|
368
|
+
declare const rawErrorBrand: unique symbol;
|
|
369
|
+
type RpcErrorBody = {
|
|
370
|
+
readonly message: string;
|
|
371
|
+
readonly data?: unknown;
|
|
372
|
+
};
|
|
373
|
+
type RpcErrorValue<C extends number, B extends RpcErrorBody> = B & {
|
|
374
|
+
readonly kind: 'application';
|
|
375
|
+
readonly code: C;
|
|
376
|
+
readonly type?: never;
|
|
377
|
+
};
|
|
378
|
+
type CreatedRpcErrorValue<C extends number, B extends RpcErrorBody> = RpcErrorValue<C, B> & {
|
|
379
|
+
readonly [applicationErrorBrand]: true;
|
|
380
|
+
readonly [rawErrorBrand]: true;
|
|
381
|
+
};
|
|
382
|
+
interface RpcErrorDescriptor<C extends number = number, B extends RpcErrorBody = RpcErrorBody> {
|
|
383
|
+
readonly code: C;
|
|
384
|
+
readonly bodySchema: Schema<B>;
|
|
385
|
+
readonly type?: never;
|
|
386
|
+
readonly message?: never;
|
|
387
|
+
readonly dataSchema?: never;
|
|
388
|
+
create(body: B): CreatedRpcErrorValue<C, B>;
|
|
389
|
+
is(value: RpcFailure<unknown>): value is RpcFailure<RpcErrorValue<C, B>>;
|
|
390
|
+
is(value: {
|
|
391
|
+
readonly kind: 'application';
|
|
392
|
+
}): value is RpcErrorValue<C, B>;
|
|
393
|
+
is(value: unknown): value is RpcErrorValue<C, B> | RpcFailure<RpcErrorValue<C, B>>;
|
|
394
|
+
}
|
|
395
|
+
type RawBody<M extends string, D extends Schema> = {
|
|
396
|
+
message: M;
|
|
397
|
+
} & (D['_zod']['optout'] extends 'optional' ? {
|
|
398
|
+
data?: output<D>;
|
|
399
|
+
} : {
|
|
400
|
+
data: output<D>;
|
|
401
|
+
});
|
|
402
|
+
/** Declare an error selected by numeric code; its schema validates the body afterwards. */
|
|
403
|
+
declare function rpcError<const C extends number, B>(code: C, schema: Schema<B>): RpcErrorDescriptor<C, unknown extends B ? RpcErrorBody : B & RpcErrorBody>;
|
|
404
|
+
declare function rpcError<const C extends number, M extends string = string, D extends Schema = Schema>(code: C, shape: {
|
|
405
|
+
message?: Schema<M>;
|
|
406
|
+
data: D;
|
|
407
|
+
}): RpcErrorDescriptor<C, RawBody<M, D>>;
|
|
408
|
+
declare function rpcError<const C extends number, M extends string = string>(code: C, shape: {
|
|
409
|
+
message?: Schema<M>;
|
|
410
|
+
}): RpcErrorDescriptor<C, {
|
|
411
|
+
message: M;
|
|
412
|
+
data?: never;
|
|
413
|
+
}>;
|
|
324
414
|
/** Declare one checked application error for use with {@link RequestType.withErrors}. */
|
|
415
|
+
declare function applicationError<const TType extends string, TData, const TCode extends number = typeof ErrorCode.applicationError>(type: TType, options: {
|
|
416
|
+
message?: string;
|
|
417
|
+
data: Schema<TData>;
|
|
418
|
+
code?: TCode;
|
|
419
|
+
}): ApplicationErrorDescriptor<TCode, string, TData, TType>;
|
|
420
|
+
declare function applicationError<const TType extends string, const TCode extends number = typeof ErrorCode.applicationError>(type: TType, options?: {
|
|
421
|
+
message?: string;
|
|
422
|
+
code?: TCode;
|
|
423
|
+
}): ApplicationErrorDescriptor<TCode, string, never, TType>;
|
|
325
424
|
declare function applicationError<const TCode extends number, const TMessage extends string>(code: TCode, message: TMessage): ApplicationErrorDescriptor<TCode, TMessage, never>;
|
|
326
425
|
declare function applicationError<const TCode extends number, const TMessage extends string, TData>(code: TCode, message: TMessage, data: Schema<TData>): ApplicationErrorDescriptor<TCode, TMessage, TData>;
|
|
327
426
|
/** Runtime nominal check for values produced by an application-error descriptor. */
|
|
@@ -432,6 +531,22 @@ interface ZodToSvcJsonSchemaOptions {
|
|
|
432
531
|
/** Convert a zod schema to our restricted SvcJsonSchema subset. */
|
|
433
532
|
declare function zodToSvcJsonSchema(schema: Schema, options?: ZodToSvcJsonSchemaOptions): LinkRpcJsonSchema;
|
|
434
533
|
//#endregion
|
|
534
|
+
//#region src/schema/validationIssue.d.ts
|
|
535
|
+
interface JsonSchemaValidationIssue {
|
|
536
|
+
readonly path: string;
|
|
537
|
+
readonly message: string;
|
|
538
|
+
}
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region src/connection/nonCompliantServerError.d.ts
|
|
541
|
+
/** JSON Pointer diagnostics relative to the original wire error. */
|
|
542
|
+
type RpcValidationIssue = JsonSchemaValidationIssue;
|
|
543
|
+
declare class NonCompliantServerError extends Error {
|
|
544
|
+
readonly original: JsonRpcError['error'];
|
|
545
|
+
readonly issues: readonly RpcValidationIssue[];
|
|
546
|
+
readonly kind: "nonCompliantServer";
|
|
547
|
+
constructor(original: JsonRpcError['error'], issues: readonly RpcValidationIssue[]);
|
|
548
|
+
}
|
|
549
|
+
//#endregion
|
|
435
550
|
//#region src/connection/interfaceDefinition.d.ts
|
|
436
551
|
/**
|
|
437
552
|
* Per-call stream API handed to a request handler as its third argument.
|
|
@@ -550,17 +665,28 @@ interface LocalRpcError {
|
|
|
550
665
|
readonly kind: 'local';
|
|
551
666
|
readonly cause: unknown;
|
|
552
667
|
}
|
|
668
|
+
interface TransportRpcError {
|
|
669
|
+
readonly kind: 'transport';
|
|
670
|
+
readonly cause: unknown;
|
|
671
|
+
}
|
|
672
|
+
type GenericRpcError = RemoteRpcError | LocalRpcError | TransportRpcError | NonCompliantServerError;
|
|
673
|
+
type RpcCallError<E = never> = {
|
|
674
|
+
readonly kind: 'application';
|
|
675
|
+
readonly error: E;
|
|
676
|
+
} | {
|
|
677
|
+
readonly kind: 'generic';
|
|
678
|
+
readonly error: GenericRpcError;
|
|
679
|
+
};
|
|
553
680
|
type CheckedCallResult<TResult, TApplicationError = never> = {
|
|
554
681
|
readonly ok: true;
|
|
555
682
|
readonly value: TResult;
|
|
556
683
|
} | {
|
|
557
684
|
readonly ok: false;
|
|
558
|
-
readonly error: TApplicationError |
|
|
685
|
+
readonly error: TApplicationError | GenericRpcError;
|
|
559
686
|
};
|
|
560
|
-
interface CheckedCall<TResult, TApplicationError = never> extends Promise<TResult
|
|
687
|
+
interface CheckedCall<TResult, TApplicationError = never> extends Promise<Result$1<TResult, TApplicationError>> {
|
|
561
688
|
/**
|
|
562
|
-
*
|
|
563
|
-
* promoted to a typed application error.
|
|
689
|
+
* @deprecated Use getResultClient() for values that include generic errors.
|
|
564
690
|
*/
|
|
565
691
|
result(): Promise<CheckedCallResult<TResult, TApplicationError>>;
|
|
566
692
|
}
|
|
@@ -572,6 +698,7 @@ interface CheckedCall<TResult, TApplicationError = never> extends Promise<TResul
|
|
|
572
698
|
*/
|
|
573
699
|
type _HasStream<TClient, TServer> = [TClient] extends [never] ? ([TServer] extends [never] ? false : true) : true;
|
|
574
700
|
type ClientCall<TResult, TApplicationError> = [TApplicationError] extends [never] ? Promise<TResult> : CheckedCall<TResult, TApplicationError>;
|
|
701
|
+
type ClientResult<R, E> = [E] extends [never] ? R : Result$1<R, E>;
|
|
575
702
|
/**
|
|
576
703
|
* Compile-time TypeScript shape of an interface — useful for typed
|
|
577
704
|
* client/server implementations on top of the runtime definition.
|
|
@@ -584,8 +711,10 @@ type ClientCall<TResult, TApplicationError> = [TApplicationError] extends [never
|
|
|
584
711
|
* type Client = InterfaceClient<typeof myInterface>;
|
|
585
712
|
* // => { bar(p: {...}): Promise<string>; foo(p: {...}): void; }
|
|
586
713
|
*/
|
|
587
|
-
type InterfaceClientMember<TMember> = TMember extends RequestType<infer P, infer R, infer E, infer TC, infer TS, any, any> ? (_HasStream<TC, TS> extends true ? (params: P, opts?: StreamCallOptions<TS>) => StreamingCall<R, TC> & ClientCall<R, PublicApplicationErrorOf<E>> : (params: P) => ClientCall<R, PublicApplicationErrorOf<E>>) : TMember extends NotificationType<infer P> ? (params: P) => void : never;
|
|
714
|
+
type InterfaceClientMember<TMember> = TMember extends RequestType<infer P, infer R, infer E, infer TC, infer TS, any, any> ? (_HasStream<TC, TS> extends true ? (params: P, opts?: StreamCallOptions<TS>) => StreamingCall<ClientResult<R, PublicApplicationErrorOf<E>>, TC> & ClientCall<R, PublicApplicationErrorOf<E>> : (params: P) => ClientCall<R, PublicApplicationErrorOf<E>>) : TMember extends NotificationType<infer P> ? (params: P) => void : never;
|
|
588
715
|
type InterfaceClient<TDef extends InterfaceDefinition<any>> = { [K in keyof TDef['members']]: InterfaceClientMember<TDef['members'][K]>; };
|
|
716
|
+
/** Every request returns failures as values, including methods with no declared errors. */
|
|
717
|
+
type InterfaceResultClient<TDef extends InterfaceDefinition<any>> = { [K in keyof TDef['members']]: TDef['members'][K] extends RequestType<infer P, infer R, infer E, infer TC, infer TS, any, any> ? _HasStream<TC, TS> extends true ? (params: P, opts?: StreamCallOptions<TS>) => StreamingCall<Result$1<R, RpcCallError<PublicApplicationErrorOf<E>>>, TC> : (params: P) => Promise<Result$1<R, RpcCallError<PublicApplicationErrorOf<E>>>> : TDef['members'][K] extends NotificationType<infer P> ? (params: P) => void : never; };
|
|
589
718
|
/**
|
|
590
719
|
* Compile-time shape of a server implementation for an interface — used by
|
|
591
720
|
* `LinkRpcConnection.register`. Request handlers may return synchronously or
|
|
@@ -653,8 +782,8 @@ declare function defineInterface<TMembers extends MemberMap>(info: InterfaceInfo
|
|
|
653
782
|
* streams use `z.any()` because no zod source is available — call-site
|
|
654
783
|
* validation is therefore a no-op and the caller is responsible for
|
|
655
784
|
* shape-checking inputs and outputs. Declared application-error payloads
|
|
656
|
-
* are materialized and validated
|
|
657
|
-
*
|
|
785
|
+
* are materialized and validated after code selection. A known code whose
|
|
786
|
+
* body fails all declared branches is a noncompliant-server failure.
|
|
658
787
|
*
|
|
659
788
|
* Methods with no `result` descriptor become notifications; methods with
|
|
660
789
|
* `clientStream` / `serverStream` get pass-through stream payload
|
|
@@ -737,6 +866,7 @@ interface Components {
|
|
|
737
866
|
}
|
|
738
867
|
/** Match one JSON value against the structural LinkRPC subset without transforming it. */
|
|
739
868
|
declare function matchesJsonSchema(value: JsonValue, schema: LinkRpcJsonSchema, components?: Components): boolean;
|
|
869
|
+
declare function validateJsonSchema(value: JsonValue, schema: LinkRpcJsonSchema, components?: Components): readonly JsonSchemaValidationIssue[];
|
|
740
870
|
//#endregion
|
|
741
871
|
//#region src/schema/assertSchemaReferences.d.ts
|
|
742
872
|
declare function componentSchemaRef(name: string): string;
|
|
@@ -777,6 +907,8 @@ declare function schemaToZod(schema: LinkRpcJsonSchema, components?: Record<stri
|
|
|
777
907
|
//#endregion
|
|
778
908
|
//#region src/schema/codegen/generateTsInterface.d.ts
|
|
779
909
|
interface GenerateInterfaceOptions {
|
|
910
|
+
/** Omit imports when composing definitions inside a generated module. */
|
|
911
|
+
omitImports?: boolean;
|
|
780
912
|
/**
|
|
781
913
|
* Module specifier from which `defineInterface`, `requestType`,
|
|
782
914
|
* `notificationType` are imported. Defaults to `@hediet/linkrpc`.
|
|
@@ -814,614 +946,283 @@ interface GenerateInterfaceOptions {
|
|
|
814
946
|
*/
|
|
815
947
|
declare function generateTsInterface(schema: LinkRpcInterfaceSchema, options?: GenerateInterfaceOptions): string;
|
|
816
948
|
//#endregion
|
|
817
|
-
//#region src/
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
declare const zTopologyTransportEndpoint: import("zod/mini").ZodMiniObject<{
|
|
875
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
876
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
877
|
-
}, import("zod/v4/core").$strip>;
|
|
949
|
+
//#region src/schema/staticHubSchema.d.ts
|
|
950
|
+
interface InterfaceRef {
|
|
951
|
+
interfaceId: string;
|
|
952
|
+
interfaceHash: string;
|
|
953
|
+
}
|
|
954
|
+
type StaticInterfaceReference = InterfaceRef;
|
|
955
|
+
interface StaticService {
|
|
956
|
+
serviceId: string;
|
|
957
|
+
interfaces: StaticInterfaceReference[];
|
|
958
|
+
}
|
|
959
|
+
interface StaticHubSchemaDocument {
|
|
960
|
+
services?: StaticService[];
|
|
961
|
+
defaultInterface?: StaticInterfaceReference;
|
|
962
|
+
bareInterfaces?: {
|
|
963
|
+
interface: InterfaceRef;
|
|
964
|
+
prefix: string;
|
|
965
|
+
}[];
|
|
966
|
+
interfaceSchemas: LinkRpcInterfaceSchema[];
|
|
967
|
+
}
|
|
968
|
+
type StaticHubSchema = StaticHubSchemaDocument;
|
|
969
|
+
declare function parseStaticHubSchema(value: unknown): StaticHubSchema;
|
|
970
|
+
//#endregion
|
|
971
|
+
//#region src/schema/codegen/generateTsContract.d.ts
|
|
972
|
+
interface GenerateContractOptions {
|
|
973
|
+
linkRpcImport?: string;
|
|
974
|
+
/** Exact `interfaceId@interfaceHash` keys; required when derived names collide. */
|
|
975
|
+
interfaceNames?: Readonly<Record<string, string>>;
|
|
976
|
+
/** Keys: `root:id@hash`, `service:serviceId:id@hash`, `default`, or `bare:prefix`. */
|
|
977
|
+
bindingNames?: Readonly<Record<string, string>>;
|
|
978
|
+
}
|
|
979
|
+
/** Generate one reusable definition per schema and immutable, typed route descriptors. */
|
|
980
|
+
declare function generateTsContract(document: StaticHubSchemaDocument, options?: GenerateContractOptions): string;
|
|
981
|
+
//#endregion
|
|
982
|
+
//#region src/disposable.d.ts
|
|
983
|
+
/** Minimal disposable handle; calling `dispose` releases the resource. */
|
|
984
|
+
interface IDisposable {
|
|
985
|
+
dispose(): void;
|
|
986
|
+
}
|
|
987
|
+
//#endregion
|
|
988
|
+
//#region src/transport/messageTransport.d.ts
|
|
989
|
+
interface IMessageTransport<TIncoming = JsonRpcMessage, TOutgoing = JsonRpcMessage> {
|
|
990
|
+
send(message: TOutgoing): void | Promise<void>;
|
|
991
|
+
/**
|
|
992
|
+
* Sets the listener for incoming messages. Setting `undefined` detaches.
|
|
993
|
+
* The transport buffers messages received before a listener is attached
|
|
994
|
+
* and delivers them the next tick when one is set.
|
|
995
|
+
* Forgetting to set a listener will cause the queue to leak.
|
|
996
|
+
*/
|
|
997
|
+
setListener(listener: ((message: TIncoming) => void) | undefined): void;
|
|
998
|
+
dispose(): void;
|
|
999
|
+
}
|
|
1000
|
+
type MessageWithContext<TCtx> = JsonRpcMessage & {
|
|
1001
|
+
context: TCtx;
|
|
1002
|
+
};
|
|
1003
|
+
type MessageTransportWithContext<TCtx> = IMessageTransport<JsonRpcMessage, MessageWithContext<TCtx>>;
|
|
1004
|
+
type MessageTransportDirection = 'send' | 'receive';
|
|
1005
|
+
type MessageTransportTrace = (direction: MessageTransportDirection, message: JsonRpcMessage) => void;
|
|
878
1006
|
/**
|
|
879
|
-
*
|
|
880
|
-
*
|
|
1007
|
+
* Observe every message crossing a transport without changing its buffering or
|
|
1008
|
+
* lifecycle behavior.
|
|
881
1009
|
*/
|
|
882
|
-
declare
|
|
883
|
-
type: import("zod/mini").ZodMiniString<string>;
|
|
884
|
-
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
885
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
886
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
887
|
-
}, import("zod/v4/core").$strip>>;
|
|
888
|
-
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
889
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
890
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
891
|
-
}, import("zod/v4/core").$strip>>;
|
|
892
|
-
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
893
|
-
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
894
|
-
}, import("zod/v4/core").$strip>;
|
|
895
|
-
declare const zTopologyLink: import("zod/mini").ZodMiniObject<{
|
|
896
|
-
from: import("zod/mini").ZodMiniObject<{
|
|
897
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
898
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
899
|
-
}, import("zod/v4/core").$strip>;
|
|
900
|
-
to: import("zod/mini").ZodMiniObject<{
|
|
901
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
902
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
903
|
-
}, import("zod/v4/core").$strip>;
|
|
904
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
905
|
-
peerState: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
906
|
-
identified: "identified";
|
|
907
|
-
pending: "pending";
|
|
908
|
-
unsupported: "unsupported";
|
|
909
|
-
error: "error";
|
|
910
|
-
}>>;
|
|
911
|
-
transport: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
912
|
-
type: import("zod/mini").ZodMiniString<string>;
|
|
913
|
-
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
914
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
915
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
916
|
-
}, import("zod/v4/core").$strip>>;
|
|
917
|
-
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
918
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
919
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
920
|
-
}, import("zod/v4/core").$strip>>;
|
|
921
|
-
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
922
|
-
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
923
|
-
}, import("zod/v4/core").$strip>>;
|
|
924
|
-
}, import("zod/v4/core").$strip>;
|
|
925
|
-
declare const zRouteClaim: import("zod/mini").ZodMiniObject<{
|
|
926
|
-
serviceId: import("zod/mini").ZodMiniString<string>;
|
|
927
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
928
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
929
|
-
match: import("zod/mini").ZodMiniEnum<{
|
|
930
|
-
exact: "exact";
|
|
931
|
-
prefix: "prefix";
|
|
932
|
-
}>;
|
|
933
|
-
}, import("zod/v4/core").$strip>;
|
|
934
|
-
declare const zTopologyGraph: import("zod/mini").ZodMiniObject<{
|
|
935
|
-
observerServiceId: import("zod/mini").ZodMiniString<string>;
|
|
936
|
-
entryNodeId: import("zod/mini").ZodMiniString<string>;
|
|
937
|
-
nodes: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
938
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
939
|
-
kind: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
940
|
-
endpoint: "endpoint";
|
|
941
|
-
hub: "hub";
|
|
942
|
-
}>>;
|
|
943
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
944
|
-
descriptors: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
945
|
-
source: import("zod/mini").ZodMiniEnum<{
|
|
946
|
-
self: "self";
|
|
947
|
-
attacher: "attacher";
|
|
948
|
-
}>;
|
|
949
|
-
descriptor: import("zod/mini").ZodMiniObject<{
|
|
950
|
-
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
951
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
952
|
-
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
953
|
-
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
954
|
-
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
955
|
-
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
956
|
-
}, import("zod/v4/core").$strip>;
|
|
957
|
-
}, import("zod/v4/core").$strip>>>;
|
|
958
|
-
ports: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
959
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
960
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
961
|
-
}, import("zod/v4/core").$strip>>;
|
|
962
|
-
}, import("zod/v4/core").$strip>>;
|
|
963
|
-
links: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
964
|
-
from: import("zod/mini").ZodMiniObject<{
|
|
965
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
966
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
967
|
-
}, import("zod/v4/core").$strip>;
|
|
968
|
-
to: import("zod/mini").ZodMiniObject<{
|
|
969
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
970
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
971
|
-
}, import("zod/v4/core").$strip>;
|
|
972
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
973
|
-
peerState: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
974
|
-
identified: "identified";
|
|
975
|
-
pending: "pending";
|
|
976
|
-
unsupported: "unsupported";
|
|
977
|
-
error: "error";
|
|
978
|
-
}>>;
|
|
979
|
-
transport: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
980
|
-
type: import("zod/mini").ZodMiniString<string>;
|
|
981
|
-
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
982
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
983
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
984
|
-
}, import("zod/v4/core").$strip>>;
|
|
985
|
-
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
986
|
-
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
987
|
-
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
988
|
-
}, import("zod/v4/core").$strip>>;
|
|
989
|
-
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
990
|
-
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
991
|
-
}, import("zod/v4/core").$strip>>;
|
|
992
|
-
}, import("zod/v4/core").$strip>>;
|
|
993
|
-
routes: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
994
|
-
serviceId: import("zod/mini").ZodMiniString<string>;
|
|
995
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
996
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
997
|
-
match: import("zod/mini").ZodMiniEnum<{
|
|
998
|
-
exact: "exact";
|
|
999
|
-
prefix: "prefix";
|
|
1000
|
-
}>;
|
|
1001
|
-
}, import("zod/v4/core").$strip>>;
|
|
1002
|
-
}, import("zod/v4/core").$strip>;
|
|
1003
|
-
type TopologyPort = output<typeof zTopologyPort>;
|
|
1004
|
-
type ParticipantDescriptor = output<typeof zParticipantDescriptor>;
|
|
1005
|
-
type ParticipantDescriptorSource = output<typeof zParticipantDescriptorSource>;
|
|
1006
|
-
type TopologyNode = output<typeof zTopologyNode>;
|
|
1007
|
-
type TopologyLinkEndpoint = output<typeof zTopologyLinkEndpoint>;
|
|
1008
|
-
type TopologyTransportEndpoint = output<typeof zTopologyTransportEndpoint>;
|
|
1009
|
-
type TopologyTransportInfo = output<typeof zTopologyTransportInfo>;
|
|
1010
|
-
type TopologyLink = output<typeof zTopologyLink>;
|
|
1011
|
-
type RouteClaim = output<typeof zRouteClaim>;
|
|
1012
|
-
type TopologyGraph = output<typeof zTopologyGraph>;
|
|
1013
|
-
declare const topologyInterface: InterfaceDefinition<{
|
|
1014
|
-
getGraph: RequestType<Record<string, never>, {
|
|
1015
|
-
observerServiceId: string;
|
|
1016
|
-
entryNodeId: string;
|
|
1017
|
-
nodes: {
|
|
1018
|
-
nodeId: string;
|
|
1019
|
-
ports: {
|
|
1020
|
-
portId: string;
|
|
1021
|
-
label?: string | undefined;
|
|
1022
|
-
}[];
|
|
1023
|
-
kind?: "endpoint" | "hub" | undefined;
|
|
1024
|
-
label?: string | undefined;
|
|
1025
|
-
descriptors?: {
|
|
1026
|
-
source: "self" | "attacher";
|
|
1027
|
-
descriptor: {
|
|
1028
|
-
type?: string | undefined;
|
|
1029
|
-
label?: string | undefined;
|
|
1030
|
-
processId?: number | undefined;
|
|
1031
|
-
processType?: string | undefined;
|
|
1032
|
-
nodeStatusServiceId?: string | undefined;
|
|
1033
|
-
metadata?: Record<string, string | number | boolean> | undefined;
|
|
1034
|
-
};
|
|
1035
|
-
}[] | undefined;
|
|
1036
|
-
}[];
|
|
1037
|
-
links: {
|
|
1038
|
-
from: {
|
|
1039
|
-
nodeId: string;
|
|
1040
|
-
portId: string;
|
|
1041
|
-
};
|
|
1042
|
-
to: {
|
|
1043
|
-
nodeId: string;
|
|
1044
|
-
portId: string;
|
|
1045
|
-
};
|
|
1046
|
-
label?: string | undefined;
|
|
1047
|
-
peerState?: "identified" | "pending" | "unsupported" | "error" | undefined;
|
|
1048
|
-
transport?: {
|
|
1049
|
-
type: string;
|
|
1050
|
-
local?: {
|
|
1051
|
-
address?: string | undefined;
|
|
1052
|
-
port?: number | undefined;
|
|
1053
|
-
} | undefined;
|
|
1054
|
-
remote?: {
|
|
1055
|
-
address?: string | undefined;
|
|
1056
|
-
port?: number | undefined;
|
|
1057
|
-
} | undefined;
|
|
1058
|
-
path?: string | undefined;
|
|
1059
|
-
metadata?: Record<string, string | number | boolean> | undefined;
|
|
1060
|
-
} | undefined;
|
|
1061
|
-
}[];
|
|
1062
|
-
routes: {
|
|
1063
|
-
serviceId: string;
|
|
1064
|
-
nodeId: string;
|
|
1065
|
-
portId: string;
|
|
1066
|
-
match: "exact" | "prefix";
|
|
1067
|
-
}[];
|
|
1068
|
-
}, void, NoInfer<Record<string, never>>, never, readonly ApplicationErrorDescriptorBase[], void>;
|
|
1069
|
-
watchGraph: RequestType<Record<string, never>, Record<string, never>, void, never, NoInfer<Record<string, never>>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
1070
|
-
}>;
|
|
1071
|
-
declare const zTrafficTransitEndpoint: import("zod/mini").ZodMiniObject<{
|
|
1072
|
-
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
1073
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1074
|
-
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
1075
|
-
}, import("zod/v4/core").$strip>;
|
|
1076
|
-
declare const zTrafficTransitEvent: import("zod/mini").ZodMiniObject<{
|
|
1077
|
-
type: import("zod/mini").ZodMiniLiteral<"transit">;
|
|
1078
|
-
timeMs: import("zod/mini").ZodMiniNumber<number>;
|
|
1079
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
1080
|
-
in: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1081
|
-
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
1082
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1083
|
-
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
1084
|
-
}, import("zod/v4/core").$strip>>;
|
|
1085
|
-
out: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1086
|
-
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
1087
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1088
|
-
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
1089
|
-
}, import("zod/v4/core").$strip>>;
|
|
1090
|
-
disposition: import("zod/mini").ZodMiniEnum<{
|
|
1091
|
-
forwarded: "forwarded";
|
|
1092
|
-
consumed: "consumed";
|
|
1093
|
-
dropped: "dropped";
|
|
1094
|
-
unroutable: "unroutable";
|
|
1095
|
-
}>;
|
|
1096
|
-
kind: import("zod/mini").ZodMiniEnum<{
|
|
1097
|
-
request: "request";
|
|
1098
|
-
notification: "notification";
|
|
1099
|
-
response: "response";
|
|
1100
|
-
stream: "stream";
|
|
1101
|
-
}>;
|
|
1102
|
-
method: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1103
|
-
params: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1104
|
-
result: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1105
|
-
error: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1106
|
-
code: import("zod/mini").ZodMiniNumber<number>;
|
|
1107
|
-
message: import("zod/mini").ZodMiniString<string>;
|
|
1108
|
-
data: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1109
|
-
}, import("zod/v4/core").$strip>>;
|
|
1110
|
-
}, import("zod/v4/core").$strip>;
|
|
1111
|
-
declare const zTrafficOverflowEvent: import("zod/mini").ZodMiniObject<{
|
|
1112
|
-
type: import("zod/mini").ZodMiniLiteral<"overflow">;
|
|
1113
|
-
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
1114
|
-
}, import("zod/v4/core").$strip>;
|
|
1115
|
-
declare const zTrafficEvent: import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniObject<{
|
|
1116
|
-
type: import("zod/mini").ZodMiniLiteral<"transit">;
|
|
1117
|
-
timeMs: import("zod/mini").ZodMiniNumber<number>;
|
|
1118
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
1119
|
-
in: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1120
|
-
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
1121
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1122
|
-
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
1123
|
-
}, import("zod/v4/core").$strip>>;
|
|
1124
|
-
out: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1125
|
-
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
1126
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1127
|
-
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
1128
|
-
}, import("zod/v4/core").$strip>>;
|
|
1129
|
-
disposition: import("zod/mini").ZodMiniEnum<{
|
|
1130
|
-
forwarded: "forwarded";
|
|
1131
|
-
consumed: "consumed";
|
|
1132
|
-
dropped: "dropped";
|
|
1133
|
-
unroutable: "unroutable";
|
|
1134
|
-
}>;
|
|
1135
|
-
kind: import("zod/mini").ZodMiniEnum<{
|
|
1136
|
-
request: "request";
|
|
1137
|
-
notification: "notification";
|
|
1138
|
-
response: "response";
|
|
1139
|
-
stream: "stream";
|
|
1140
|
-
}>;
|
|
1141
|
-
method: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1142
|
-
params: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1143
|
-
result: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1144
|
-
error: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
1145
|
-
code: import("zod/mini").ZodMiniNumber<number>;
|
|
1146
|
-
message: import("zod/mini").ZodMiniString<string>;
|
|
1147
|
-
data: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
1148
|
-
}, import("zod/v4/core").$strip>>;
|
|
1149
|
-
}, import("zod/v4/core").$strip>, import("zod/mini").ZodMiniObject<{
|
|
1150
|
-
type: import("zod/mini").ZodMiniLiteral<"overflow">;
|
|
1151
|
-
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
1152
|
-
}, import("zod/v4/core").$strip>]>;
|
|
1153
|
-
type TrafficTransitEndpoint = output<typeof zTrafficTransitEndpoint>;
|
|
1154
|
-
type TrafficTransitEvent = output<typeof zTrafficTransitEvent>;
|
|
1155
|
-
type TrafficOverflowEvent = output<typeof zTrafficOverflowEvent>;
|
|
1156
|
-
type TrafficEvent = output<typeof zTrafficEvent>;
|
|
1157
|
-
declare const zTrafficWatchResult: import("zod/mini").ZodMiniObject<{
|
|
1158
|
-
delivered: import("zod/mini").ZodMiniNumber<number>;
|
|
1159
|
-
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
1160
|
-
}, import("zod/v4/core").$strip>;
|
|
1161
|
-
type TrafficWatchResult = output<typeof zTrafficWatchResult>;
|
|
1010
|
+
declare function traceMessageTransport(transport: IMessageTransport, trace: MessageTransportTrace): IMessageTransport;
|
|
1162
1011
|
/**
|
|
1163
|
-
*
|
|
1164
|
-
*
|
|
1012
|
+
* Pipe two transports together: every message one receives is forwarded to
|
|
1013
|
+
* the other's `send`. Returns a disposable that detaches both listeners.
|
|
1014
|
+
*
|
|
1015
|
+
* Neither transport is disposed — the caller owns their lifecycle. This is
|
|
1016
|
+
* the building block for relays (e.g. bridging a `WindowMessageTransport`
|
|
1017
|
+
* for an iframe to a multiplexer channel).
|
|
1165
1018
|
*/
|
|
1166
|
-
declare
|
|
1167
|
-
watch: RequestType<{
|
|
1168
|
-
methodPrefix?: string | undefined;
|
|
1169
|
-
trafficIgnoreKey?: string | undefined;
|
|
1170
|
-
focusRequest?: {
|
|
1171
|
-
portId: string;
|
|
1172
|
-
requestId: string | number;
|
|
1173
|
-
} | undefined;
|
|
1174
|
-
}, {
|
|
1175
|
-
delivered: number;
|
|
1176
|
-
dropped: number;
|
|
1177
|
-
}, void, never, NoInfer<{
|
|
1178
|
-
type: "transit";
|
|
1179
|
-
timeMs: number;
|
|
1180
|
-
nodeId: string;
|
|
1181
|
-
disposition: "forwarded" | "consumed" | "dropped" | "unroutable";
|
|
1182
|
-
kind: "request" | "notification" | "response" | "stream";
|
|
1183
|
-
in?: {
|
|
1184
|
-
edgeId: string;
|
|
1185
|
-
portId: string;
|
|
1186
|
-
requestId?: string | number | undefined;
|
|
1187
|
-
} | undefined;
|
|
1188
|
-
out?: {
|
|
1189
|
-
edgeId: string;
|
|
1190
|
-
portId: string;
|
|
1191
|
-
requestId?: string | number | undefined;
|
|
1192
|
-
} | undefined;
|
|
1193
|
-
method?: string | undefined;
|
|
1194
|
-
params?: unknown;
|
|
1195
|
-
result?: unknown;
|
|
1196
|
-
error?: {
|
|
1197
|
-
code: number;
|
|
1198
|
-
message: string;
|
|
1199
|
-
data?: unknown;
|
|
1200
|
-
} | undefined;
|
|
1201
|
-
} | {
|
|
1202
|
-
type: "overflow";
|
|
1203
|
-
dropped: number;
|
|
1204
|
-
}>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
1205
|
-
watchWithPayloads: RequestType<{
|
|
1206
|
-
maxPayloadBytes: number;
|
|
1207
|
-
methodPrefix?: string | undefined;
|
|
1208
|
-
trafficIgnoreKey?: string | undefined;
|
|
1209
|
-
focusRequest?: {
|
|
1210
|
-
portId: string;
|
|
1211
|
-
requestId: string | number;
|
|
1212
|
-
} | undefined;
|
|
1213
|
-
}, {
|
|
1214
|
-
delivered: number;
|
|
1215
|
-
dropped: number;
|
|
1216
|
-
}, void, never, NoInfer<{
|
|
1217
|
-
type: "transit";
|
|
1218
|
-
timeMs: number;
|
|
1219
|
-
nodeId: string;
|
|
1220
|
-
disposition: "forwarded" | "consumed" | "dropped" | "unroutable";
|
|
1221
|
-
kind: "request" | "notification" | "response" | "stream";
|
|
1222
|
-
in?: {
|
|
1223
|
-
edgeId: string;
|
|
1224
|
-
portId: string;
|
|
1225
|
-
requestId?: string | number | undefined;
|
|
1226
|
-
} | undefined;
|
|
1227
|
-
out?: {
|
|
1228
|
-
edgeId: string;
|
|
1229
|
-
portId: string;
|
|
1230
|
-
requestId?: string | number | undefined;
|
|
1231
|
-
} | undefined;
|
|
1232
|
-
method?: string | undefined;
|
|
1233
|
-
params?: unknown;
|
|
1234
|
-
result?: unknown;
|
|
1235
|
-
error?: {
|
|
1236
|
-
code: number;
|
|
1237
|
-
message: string;
|
|
1238
|
-
data?: unknown;
|
|
1239
|
-
} | undefined;
|
|
1240
|
-
} | {
|
|
1241
|
-
type: "overflow";
|
|
1242
|
-
dropped: number;
|
|
1243
|
-
}>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
1244
|
-
}>;
|
|
1245
|
-
//#endregion
|
|
1246
|
-
//#region src/inspection/node.interfaces.d.ts
|
|
1247
|
-
declare const zNodeInfo: import("zod/mini").ZodMiniObject<{
|
|
1248
|
-
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
1249
|
-
portId: import("zod/mini").ZodMiniString<string>;
|
|
1250
|
-
descriptors: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
1251
|
-
source: import("zod/mini").ZodMiniEnum<{
|
|
1252
|
-
self: "self";
|
|
1253
|
-
attacher: "attacher";
|
|
1254
|
-
}>;
|
|
1255
|
-
descriptor: import("zod/mini").ZodMiniObject<{
|
|
1256
|
-
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1257
|
-
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1258
|
-
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
1259
|
-
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1260
|
-
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
1261
|
-
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
1262
|
-
}, import("zod/v4/core").$strip>;
|
|
1263
|
-
}, import("zod/v4/core").$strip>>>;
|
|
1264
|
-
}, import("zod/v4/core").$strip>;
|
|
1265
|
-
type NodeInfo = output<typeof zNodeInfo>;
|
|
1266
|
-
/**
|
|
1267
|
-
* Generates unique topology-correlation labels, not security identities.
|
|
1268
|
-
* Custom generators must avoid collisions across nodes and ports. Tests can
|
|
1269
|
-
* supply an independent deterministic sequence for each participant.
|
|
1270
|
-
*/
|
|
1271
|
-
type TopologyIdGenerator = (kind: 'node' | 'port') => string;
|
|
1019
|
+
declare function connectTransports<T extends JsonRpcMessage>(a: IMessageTransport<T>, b: IMessageTransport<T>): IDisposable;
|
|
1272
1020
|
/**
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1021
|
+
* Two in-memory transports wired back-to-back. Useful for tests and for
|
|
1022
|
+
* same-process bridges.
|
|
1023
|
+
*
|
|
1024
|
+
* Generic in the per-direction payload type so asymmetric pairs (e.g. one
|
|
1025
|
+
* side sends plain `JsonRpcMessage`, the other side sends
|
|
1026
|
+
* `JsonRpcMessage & { context: Participant }`) are expressible at the type
|
|
1027
|
+
* level. At runtime both halves just hand objects through by reference.
|
|
1275
1028
|
*/
|
|
1276
|
-
declare
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
source: "self" | "attacher";
|
|
1282
|
-
descriptor: {
|
|
1283
|
-
type?: string | undefined;
|
|
1284
|
-
label?: string | undefined;
|
|
1285
|
-
processId?: number | undefined;
|
|
1286
|
-
processType?: string | undefined;
|
|
1287
|
-
nodeStatusServiceId?: string | undefined;
|
|
1288
|
-
metadata?: Record<string, string | number | boolean> | undefined;
|
|
1289
|
-
};
|
|
1290
|
-
}[] | undefined;
|
|
1291
|
-
}, any, never, never, readonly ApplicationErrorDescriptorBase[], any>;
|
|
1292
|
-
}>;
|
|
1029
|
+
declare class TransportPair<TFromA = JsonRpcMessage, TFromB = JsonRpcMessage> {
|
|
1030
|
+
readonly a: IMessageTransport<TFromB, TFromA>;
|
|
1031
|
+
readonly b: IMessageTransport<TFromA, TFromB>;
|
|
1032
|
+
constructor();
|
|
1033
|
+
}
|
|
1293
1034
|
//#endregion
|
|
1294
|
-
//#region src/connection/
|
|
1035
|
+
//#region src/connection/channel.d.ts
|
|
1036
|
+
declare class Channel<TInCtx = undefined, TOutCtx = undefined> {
|
|
1037
|
+
readonly sender: IRequestSender<TOutCtx>;
|
|
1038
|
+
private readonly _setHandler;
|
|
1039
|
+
private readonly _setWireObserver?;
|
|
1040
|
+
constructor(sender: IRequestSender<TOutCtx>, _setHandler: (h: IRequestHandler<TInCtx> | undefined) => void, _setWireObserver?: ((observer: WireMessageObserver | undefined) => void) | undefined);
|
|
1041
|
+
/** Bind the inbound request/notification handler. May be called before or after construction of {@link LinkRpcConnection}. */
|
|
1042
|
+
setRequestHandler(handler: IRequestHandler<TInCtx> | undefined): void;
|
|
1043
|
+
/**
|
|
1044
|
+
* Install the endpoint inspection observer at the JSON-RPC wire boundary.
|
|
1045
|
+
* Intended for {@link LinkRpcConnection}; ordinary consumers should use the
|
|
1046
|
+
* public `hubrpc.traffic` service instead.
|
|
1047
|
+
*/
|
|
1048
|
+
setWireMessageObserver(observer: WireMessageObserver | undefined): void;
|
|
1049
|
+
/**
|
|
1050
|
+
* Compose this channel with a sender-side decorator (typically the
|
|
1051
|
+
* signing layer). The decorator wraps {@link sender} only; the
|
|
1052
|
+
* {@link setRequestHandler} binding is shared with the original channel
|
|
1053
|
+
* so the receive side is bound exactly once regardless of decoration depth.
|
|
1054
|
+
*/
|
|
1055
|
+
withSender<TNewOutCtx>(decorate: (raw: IRequestSender<TOutCtx>) => IRequestSender<TNewOutCtx>): Channel<TInCtx, TNewOutCtx>;
|
|
1056
|
+
}
|
|
1057
|
+
type WireMessageDirection = 'inbound' | 'outbound';
|
|
1058
|
+
type WireMessageObserver = (direction: WireMessageDirection, message: JsonRpcMessage) => void;
|
|
1059
|
+
interface IRequestHandler<TInCtx = undefined> {
|
|
1060
|
+
handleRequest(call: IncomingCall<TInCtx>): Promise<Result>;
|
|
1061
|
+
handleNotification(call: IncomingCall<TInCtx>): void;
|
|
1062
|
+
}
|
|
1295
1063
|
/**
|
|
1296
|
-
*
|
|
1297
|
-
*
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1300
|
-
* arrival link it could infer the direction from.
|
|
1064
|
+
* Inbound call observed by an {@link IRequestHandler}. `TInCtx` is the
|
|
1065
|
+
* per-call out-of-band context the transport attached on the receiving
|
|
1066
|
+
* side (e.g. the hub stamps `Participant` on overlay-bound messages).
|
|
1067
|
+
* For wire transports it's `undefined`.
|
|
1301
1068
|
*/
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
/**
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1069
|
+
interface IncomingCall<TInCtx = undefined> {
|
|
1070
|
+
method: string;
|
|
1071
|
+
params: JsonValue | undefined;
|
|
1072
|
+
/** Out-of-band context attached by the transport, if any. */
|
|
1073
|
+
context: TInCtx;
|
|
1074
|
+
/**
|
|
1075
|
+
* Per-call streaming handle. Both directions live on this object,
|
|
1076
|
+
* scoped to the request's lifetime. The inbound listener is auto-
|
|
1077
|
+
* detached when the handler's response settles. For notifications
|
|
1078
|
+
* (no request id) the handle is a no-op stub.
|
|
1079
|
+
*/
|
|
1080
|
+
stream: IncomingStream;
|
|
1081
|
+
/**
|
|
1082
|
+
* Aborts when the caller cancels this in-flight request (a
|
|
1083
|
+
* `toCallee` `cancel` control), or when the hub cancels it on the
|
|
1084
|
+
* caller's behalf (caller disconnect / idle timeout). The handler
|
|
1085
|
+
* should observe this and settle promptly — typically by throwing,
|
|
1086
|
+
* which surfaces as a `cancelled` error response. For notifications
|
|
1087
|
+
* this never aborts.
|
|
1088
|
+
*/
|
|
1089
|
+
signal: AbortSignal;
|
|
1090
|
+
}
|
|
1309
1091
|
/**
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1092
|
+
* Per-call streaming handle attached to {@link IncomingCall.stream}.
|
|
1093
|
+
* Scoped to a single in-flight request; the channel automatically
|
|
1094
|
+
* detaches the inbound listener when the handler's response settles.
|
|
1095
|
+
*
|
|
1096
|
+
* For notifications (which have no request id), `requestId` is
|
|
1097
|
+
* `undefined`, `send` is a no-op, and `onMessage` is a no-op.
|
|
1314
1098
|
*/
|
|
1315
|
-
|
|
1099
|
+
interface IncomingStream {
|
|
1100
|
+
/** Emit a server→client stream notification correlated with this call. */
|
|
1101
|
+
send(payload: JsonValue): Promise<void>;
|
|
1316
1102
|
/**
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1103
|
+
* Register a listener for client→server stream messages correlated
|
|
1104
|
+
* with this call. Pass `undefined` to detach. Replaces any prior
|
|
1105
|
+
* listener. The channel detaches the listener automatically when
|
|
1106
|
+
* the handler's response settles.
|
|
1321
1107
|
*/
|
|
1322
|
-
|
|
1108
|
+
onMessage(listener: ((payload: JsonValue) => void) | undefined): void;
|
|
1323
1109
|
/**
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
1328
|
-
* automatically (without awaiting a pong) by the channel for streaming
|
|
1329
|
-
* calls; see {@link STREAM_METHOD}.
|
|
1110
|
+
* Liveness probe toward the caller: emit a `toCaller` ping and
|
|
1111
|
+
* resolve once the caller's `pong` (matching nonce) returns. Rejects
|
|
1112
|
+
* if the request settles first. Independent of the channel's
|
|
1113
|
+
* automatic keepalive ping.
|
|
1330
1114
|
*/
|
|
1331
|
-
|
|
1115
|
+
ping(): Promise<void>;
|
|
1116
|
+
}
|
|
1117
|
+
type Result = {
|
|
1118
|
+
result: JsonValue;
|
|
1119
|
+
} | {
|
|
1120
|
+
error: {
|
|
1121
|
+
code: number;
|
|
1122
|
+
message: string;
|
|
1123
|
+
data?: JsonValue;
|
|
1124
|
+
};
|
|
1125
|
+
};
|
|
1126
|
+
/**
|
|
1127
|
+
* What callers use to send. The {@link Channel} factory binds an
|
|
1128
|
+
* {@link IRequestHandler} at construction (immutable for the channel's
|
|
1129
|
+
* lifetime) and hands the caller back an `IRequestSender`.
|
|
1130
|
+
*
|
|
1131
|
+
* `TOutCtx` is the per-call context bag this sender understands. For
|
|
1132
|
+
* the base {@link JsonRpcChannel} it's `undefined` (the channel
|
|
1133
|
+
* doesn't read any overrides). Decorators like `SigningSender`
|
|
1134
|
+
* parametrise it on their own ctx shape.
|
|
1135
|
+
*/
|
|
1136
|
+
interface IRequestSender<TOutCtx = undefined> {
|
|
1137
|
+
sendRequest(method: string, params: JsonValue | undefined, opts?: SendOpts<TOutCtx>): Promise<JsonValue>;
|
|
1138
|
+
sendNotification(method: string, params: JsonValue | undefined, opts?: SendOpts<TOutCtx>): Promise<void>;
|
|
1332
1139
|
/**
|
|
1333
|
-
*
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1140
|
+
* Issue a request that participates in the streaming sub-protocol.
|
|
1141
|
+
* Returns synchronously with the wire request id, the result
|
|
1142
|
+
* promise, and a `send` for emitting client→server stream messages.
|
|
1336
1143
|
*/
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1144
|
+
sendRequestWithStream(method: string, params: JsonValue | undefined, opts?: StreamSendOpts<TOutCtx>): RawStreamingCall;
|
|
1145
|
+
close(): void;
|
|
1146
|
+
}
|
|
1340
1147
|
/**
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1148
|
+
* Handle for a request issued via
|
|
1149
|
+
* {@link IRequestSender.sendRequestWithStream}. `send` emits
|
|
1150
|
+
* client→server stream messages correlated with this call. `result`
|
|
1151
|
+
* resolves with the call's response.
|
|
1343
1152
|
*/
|
|
1344
|
-
|
|
1153
|
+
interface RawStreamingCall {
|
|
1154
|
+
readonly result: Promise<JsonValue>;
|
|
1155
|
+
/** Emit a client→server (`toCallee`) stream message correlated with this call. */
|
|
1156
|
+
send(payload: JsonValue): void;
|
|
1345
1157
|
/**
|
|
1346
|
-
*
|
|
1347
|
-
*
|
|
1158
|
+
* Ask the callee to abort this in-flight request (a `toCallee`
|
|
1159
|
+
* `cancel` control). Advisory: the request settles via its normal
|
|
1160
|
+
* response (typically a `cancelled` error). `reason` is an open-set
|
|
1161
|
+
* diagnostic string (see `StreamControlReason`).
|
|
1348
1162
|
*/
|
|
1349
|
-
|
|
1163
|
+
cancel(reason?: string): void;
|
|
1350
1164
|
/**
|
|
1351
|
-
*
|
|
1352
|
-
*
|
|
1165
|
+
* Stop tracking this request locally and reject {@link result}. This does
|
|
1166
|
+
* not notify the callee; call {@link cancel} first when remote work should
|
|
1167
|
+
* also be cancelled. Safe to call after the request has already settled.
|
|
1353
1168
|
*/
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1169
|
+
dispose?(reason?: string): void;
|
|
1170
|
+
/**
|
|
1171
|
+
* Liveness probe toward the callee: emit a `toCallee` ping and
|
|
1172
|
+
* resolve once the callee's `pong` (matching nonce) returns. Rejects
|
|
1173
|
+
* if the request settles first. Independent of the channel's
|
|
1174
|
+
* automatic keepalive ping.
|
|
1175
|
+
*/
|
|
1176
|
+
ping(): Promise<void>;
|
|
1177
|
+
}
|
|
1357
1178
|
/**
|
|
1358
|
-
*
|
|
1359
|
-
* notifications correlated with the original call in either direction
|
|
1360
|
-
* (callee → caller progress, caller → callee input / cancellation /
|
|
1361
|
-
* keepalive).
|
|
1362
|
-
*
|
|
1363
|
-
* Wire form: a JSON-RPC notification whose method is
|
|
1364
|
-
* `${streamInterface.info.id}::send` and whose params match
|
|
1365
|
-
* `streamInterface.members.send.paramsSchema`. The hub routes purely on
|
|
1366
|
-
* `requestId` (following the originating request's established path, like
|
|
1367
|
-
* a response); the originating request's capability authorization covers
|
|
1368
|
-
* its full stream lifetime, so stream notifications carry no method /
|
|
1369
|
-
* interface namespace of their own. App `payload` contents are typed per
|
|
1370
|
-
* request via the originating method's
|
|
1371
|
-
* `RequestType.clientStreamSchema` / `serverStreamSchema`; reserved
|
|
1372
|
-
* `control` messages are schema-independent.
|
|
1179
|
+
* Per-send options.
|
|
1373
1180
|
*
|
|
1374
|
-
*
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
* opens requests and never completes them. Streaming-enabled calls keep
|
|
1380
|
-
* themselves alive by emitting a periodic {@link StreamControlType.ping}.
|
|
1181
|
+
* `interfaceHash` is interface-level call metadata: the schema hash of
|
|
1182
|
+
* the interface a typed proxy is calling. It is independent of
|
|
1183
|
+
* `TOutCtx` — the connection stamps it from the interface definition,
|
|
1184
|
+
* the base {@link JsonRpcChannel} ignores it, and signing decorators
|
|
1185
|
+
* bake it into the `$hubrpc` envelope.
|
|
1381
1186
|
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
nonce?: string | undefined;
|
|
1396
|
-
} | undefined;
|
|
1397
|
-
payload?: unknown;
|
|
1398
|
-
}>;
|
|
1399
|
-
}>;
|
|
1187
|
+
* `ctx` is the sender's `TOutCtx`-typed override / extension bag for
|
|
1188
|
+
* per-call decorator overrides (e.g. `signerOverride`, `capsOverride`).
|
|
1189
|
+
* The base {@link JsonRpcChannel} ignores `ctx` entirely; decorators
|
|
1190
|
+
* like `SigningSender` interpret it.
|
|
1191
|
+
*/
|
|
1192
|
+
interface SendOpts<TOutCtx = undefined> {
|
|
1193
|
+
readonly ctx?: TOutCtx;
|
|
1194
|
+
/** Interface schema hash for this call (interface-level metadata). */
|
|
1195
|
+
readonly interfaceHash?: string;
|
|
1196
|
+
}
|
|
1197
|
+
interface StreamSendOpts<TOutCtx = undefined> extends SendOpts<TOutCtx> {
|
|
1198
|
+
readonly onStreamMessage?: (payload: JsonValue) => void;
|
|
1199
|
+
}
|
|
1400
1200
|
/**
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1201
|
+
* Convenience: the transport type a {@link JsonRpcChannel} expects.
|
|
1202
|
+
* Outbound is plain `JsonRpcMessage` — the base channel does not
|
|
1203
|
+
* attach context to outgoing wire messages.
|
|
1403
1204
|
*/
|
|
1404
|
-
|
|
1405
|
-
/** Wire-level shape carried on `params` of {@link STREAM_METHOD}. */
|
|
1406
|
-
type StreamSendParams = output<typeof streamInterface.members.send.paramsSchema>;
|
|
1407
|
-
//#endregion
|
|
1408
|
-
//#region src/protocol/jcs.d.ts
|
|
1205
|
+
type ChannelTransport<TInCtx = undefined> = IMessageTransport<MessageWithCtx<TInCtx>>;
|
|
1409
1206
|
/**
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1416
|
-
* Implementation inlined from the `canonicalize` npm package (Apache-2.0,
|
|
1417
|
-
* https://github.com/erdtman/canonicalize) so this module stays
|
|
1418
|
-
* zero-dependency for browser bundlers that don't resolve transitive
|
|
1419
|
-
* npm specifiers (e.g. the in-house app-bundler).
|
|
1207
|
+
* Type of incoming messages on the channel's transport. With
|
|
1208
|
+
* `TInCtx = undefined` (default) this is just `JsonRpcMessage`. With a
|
|
1209
|
+
* concrete `TInCtx`, the transport carries a `context` field alongside
|
|
1210
|
+
* the message — out-of-band, never sent over a wire, set by the
|
|
1211
|
+
* in-process producer.
|
|
1420
1212
|
*/
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
declare
|
|
1213
|
+
type MessageWithCtx<TInCtx> = [TInCtx] extends [undefined] ? JsonRpcMessage : JsonRpcMessage & {
|
|
1214
|
+
context: TInCtx;
|
|
1215
|
+
};
|
|
1216
|
+
declare class RpcError extends Error {
|
|
1217
|
+
readonly code: number;
|
|
1218
|
+
/** Whether this error was decoded from a peer response. */
|
|
1219
|
+
readonly origin: 'local' | 'remote' | 'transport';
|
|
1220
|
+
readonly data?: JsonValue;
|
|
1221
|
+
readonly hasData: boolean;
|
|
1222
|
+
constructor(message: string, code: number, data?: JsonValue,
|
|
1223
|
+
/** Whether this error was decoded from a peer response. */
|
|
1224
|
+
origin?: 'local' | 'remote' | 'transport', hasData?: boolean);
|
|
1225
|
+
}
|
|
1425
1226
|
//#endregion
|
|
1426
1227
|
//#region src/crypto/cryptoProvider.d.ts
|
|
1427
1228
|
/**
|
|
@@ -1808,1257 +1609,1974 @@ declare function permissionPermits(call: Call, permission: Permission, ability:
|
|
|
1808
1609
|
*/
|
|
1809
1610
|
declare function capabilityPermits(call: Call, cap: Capability, ability: Ability): Verdict;
|
|
1810
1611
|
//#endregion
|
|
1811
|
-
//#region src/
|
|
1612
|
+
//#region src/identity/identity.d.ts
|
|
1613
|
+
/** JSON-serializable form of a {@link KeypairSigningIdentity} (base64url keys). */
|
|
1614
|
+
interface SerializedKeypairSigningIdentity {
|
|
1615
|
+
readonly privateKey: string;
|
|
1616
|
+
readonly publicKey: string;
|
|
1617
|
+
}
|
|
1812
1618
|
/**
|
|
1813
|
-
*
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
* - `"interfaceId::member"` — interface form (root service)
|
|
1818
|
-
* - `"::interfaceId::member"` — explicit root form
|
|
1819
|
-
* - `"serviceId::interfaceId::member"` — fully-qualified form
|
|
1820
|
-
*
|
|
1821
|
-
* The hub does not accept the `bare` form (it has no interface context
|
|
1822
|
-
* to route on). Connection-level dispatch accepts all three.
|
|
1619
|
+
* The public face of a signing identity: its stable {@link PrincipalId} name
|
|
1620
|
+
* and the {@link KeyId} its signatures are stamped with. In Phase 1 (perpetual
|
|
1621
|
+
* identities) the keyId is the genesis key embedded in the principal, so it is
|
|
1622
|
+
* derived by stripping the `id:` prefix.
|
|
1823
1623
|
*/
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
interfaceId: string;
|
|
1835
|
-
member: string;
|
|
1836
|
-
};
|
|
1624
|
+
declare class PublicSigningIdentity {
|
|
1625
|
+
readonly principal: PrincipalId;
|
|
1626
|
+
constructor(principal: PrincipalId);
|
|
1627
|
+
/** The {@link KeyId} this identity signs with (its genesis key, in Phase 1). */
|
|
1628
|
+
get keyId(): KeyId;
|
|
1629
|
+
}
|
|
1630
|
+
interface SigningIdentity {
|
|
1631
|
+
readonly publicSigningIdentity: PublicSigningIdentity;
|
|
1632
|
+
sign(bytes: Uint8Array): Promise<Uint8Array>;
|
|
1633
|
+
}
|
|
1837
1634
|
/**
|
|
1838
|
-
*
|
|
1839
|
-
*
|
|
1635
|
+
* {@link SigningIdentity} backed by an in-process keypair. For the common
|
|
1636
|
+
* case where the signing material lives in memory. For external HSM-style
|
|
1637
|
+
* backends, implement {@link SigningIdentity} directly.
|
|
1840
1638
|
*/
|
|
1841
|
-
declare
|
|
1639
|
+
declare class KeypairSigningIdentity implements SigningIdentity {
|
|
1640
|
+
private readonly _privateKey;
|
|
1641
|
+
readonly publicSigningIdentity: PublicSigningIdentity;
|
|
1642
|
+
constructor(principal: PrincipalId, _privateKey: PrivateKey);
|
|
1643
|
+
sign(message: Uint8Array): Promise<Signature>;
|
|
1644
|
+
static fromKeypair(keypair: Keypair): KeypairSigningIdentity;
|
|
1645
|
+
/** Generate a fresh signing identity (Ed25519 keypair). */
|
|
1646
|
+
static generateNew(): Promise<KeypairSigningIdentity>;
|
|
1647
|
+
/** Restore an identity from its {@link toJson} form. */
|
|
1648
|
+
static fromJson(json: SerializedKeypairSigningIdentity): KeypairSigningIdentity;
|
|
1649
|
+
/** Serialize the keypair to a JSON-friendly form (base64url keys). */
|
|
1650
|
+
toJson(): SerializedKeypairSigningIdentity;
|
|
1651
|
+
}
|
|
1652
|
+
declare class PublicWrappingIdentity {
|
|
1653
|
+
readonly wrapPublicKey: Uint8Array;
|
|
1654
|
+
constructor(wrapPublicKey: Uint8Array);
|
|
1655
|
+
}
|
|
1656
|
+
interface WrappingIdentity {
|
|
1657
|
+
readonly publicWrappingIdentity: PublicWrappingIdentity;
|
|
1658
|
+
wrap(domain: string, bytes: Uint8Array): Promise<Uint8Array>;
|
|
1659
|
+
unwrap(domain: string, blob: Uint8Array): Promise<Uint8Array>;
|
|
1660
|
+
}
|
|
1661
|
+
interface Identity extends SigningIdentity, WrappingIdentity {
|
|
1662
|
+
/** The identity's stable {@link PrincipalId} name. */
|
|
1663
|
+
readonly principal: PrincipalId;
|
|
1664
|
+
/** @deprecated */
|
|
1665
|
+
readonly wrapPublicKey: Uint8Array;
|
|
1666
|
+
}
|
|
1842
1667
|
/**
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1845
|
-
*
|
|
1846
|
-
*
|
|
1668
|
+
* Full {@link Identity} backed by in-process Ed25519 (signing) and X25519
|
|
1669
|
+
* (wrapping) keypairs. The local counterpart to a keystore/executor-backed
|
|
1670
|
+
* identity — used by self-managed principals that hold their own key
|
|
1671
|
+
* material (e.g. loaded from disk). For external HSM-style backends,
|
|
1672
|
+
* implement {@link Identity} directly.
|
|
1847
1673
|
*/
|
|
1848
|
-
declare
|
|
1674
|
+
declare class KeypairIdentity implements Identity {
|
|
1675
|
+
private readonly _privateKey;
|
|
1676
|
+
private readonly _wrap;
|
|
1677
|
+
readonly principal: PrincipalId;
|
|
1678
|
+
readonly wrapPublicKey: Uint8Array;
|
|
1679
|
+
readonly publicSigningIdentity: PublicSigningIdentity;
|
|
1680
|
+
readonly publicWrappingIdentity: PublicWrappingIdentity;
|
|
1681
|
+
constructor(principal: PrincipalId, _privateKey: PrivateKey, _wrap: X25519Keypair);
|
|
1682
|
+
sign(message: Uint8Array): Promise<Signature>;
|
|
1683
|
+
wrap(domain: string, bytes: Uint8Array): Promise<Uint8Array>;
|
|
1684
|
+
unwrap(domain: string, blob: Uint8Array): Promise<Uint8Array>;
|
|
1685
|
+
/** Generate a fresh identity (Ed25519 + X25519 keypairs). */
|
|
1686
|
+
static generate(): Promise<KeypairIdentity>;
|
|
1687
|
+
}
|
|
1849
1688
|
//#endregion
|
|
1850
|
-
//#region src/
|
|
1689
|
+
//#region src/identity/capability.d.ts
|
|
1851
1690
|
/**
|
|
1852
|
-
*
|
|
1853
|
-
*
|
|
1854
|
-
* (the latter omit {@link CallMeta.principal} and carry no `$hubrpcSignature`).
|
|
1691
|
+
* Pure freshness check for a single capability link: `true` when the cap never
|
|
1692
|
+
* expires, or its `expiresAtMs` is still in the future at `now + marginMs`.
|
|
1855
1693
|
*
|
|
1856
|
-
*
|
|
1857
|
-
*
|
|
1694
|
+
* Mirrors the gate's expiry rule in {@link verifyChain}'s link check
|
|
1695
|
+
* (`expiresAtMs < nowMs` ⇒ expired) so a producer can decide, *before signing*,
|
|
1696
|
+
* whether to re-acquire a cap rather than attach one the gate will reject as
|
|
1697
|
+
* `expired`. The `marginMs` safety window absorbs in-flight transit time and
|
|
1698
|
+
* client/hub clock skew — pass the call's `signedAtMs` as `now` so the check
|
|
1699
|
+
* evaluates expiry against the same instant baked into the envelope.
|
|
1700
|
+
*
|
|
1701
|
+
* This checks ONE link. Effective authority requires every link in a
|
|
1702
|
+
* delegation chain to be unexpired, so a producer attaching a bag should apply
|
|
1703
|
+
* this to every cap it would attach (see {@link capBagFreshAt}).
|
|
1858
1704
|
*/
|
|
1859
|
-
|
|
1860
|
-
/** Fully-qualified wire method. The verifier asserts it equals the JSON-RPC `method`. */
|
|
1861
|
-
readonly method: string;
|
|
1862
|
-
/** Replay-protection nonce (base64url). The gate dedups on this. */
|
|
1863
|
-
readonly nonce: string;
|
|
1864
|
-
/** Unix milliseconds. Skew window enforced by the verifier. */
|
|
1865
|
-
readonly signedAtMs: number;
|
|
1866
|
-
/** Identity wielding the call. Present iff signed; equals the audience of every presented cap. */
|
|
1867
|
-
readonly principal?: PrincipalId;
|
|
1868
|
-
/** Optional schema hash assertion. Matched against `TargetPattern.interfaceHash`. */
|
|
1869
|
-
readonly interfaceHash?: string;
|
|
1870
|
-
}
|
|
1705
|
+
declare function capabilityFreshAt(cap: Capability, now: number, marginMs?: number): boolean;
|
|
1871
1706
|
/**
|
|
1872
|
-
*
|
|
1873
|
-
*
|
|
1707
|
+
* Freshness over a whole presented bag: `true` only when every cap is fresh at
|
|
1708
|
+
* `now + marginMs` (see {@link capabilityFreshAt}). An empty bag is trivially
|
|
1709
|
+
* fresh. Use this at the cap-production point to decide whether to re-acquire.
|
|
1874
1710
|
*/
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1711
|
+
declare function capBagFreshAt(caps: readonly Capability[], now: number, marginMs?: number): boolean;
|
|
1712
|
+
type PermitResult = {
|
|
1713
|
+
ok: true;
|
|
1714
|
+
capabilityNonce: string;
|
|
1715
|
+
rootIssuer: PrincipalId;
|
|
1716
|
+
} | {
|
|
1717
|
+
ok: false;
|
|
1718
|
+
reason: string;
|
|
1719
|
+
};
|
|
1720
|
+
/**
|
|
1721
|
+
* A trust anchor accepted as a capability-chain root, plus whether it may be
|
|
1722
|
+
* named in authorization error messages.
|
|
1723
|
+
*/
|
|
1724
|
+
interface AcceptedRootIssuer {
|
|
1725
|
+
/** The principal accepted as a chain root for the queried service. */
|
|
1726
|
+
principal: PrincipalId;
|
|
1727
|
+
/**
|
|
1728
|
+
* Whether this issuer may be disclosed in `permits` rejection reasons.
|
|
1729
|
+
* Public anchors (e.g. a hub's well-known admin identity) are surfaced to
|
|
1730
|
+
* help diagnose "wrong root" failures; private ones are withheld so the
|
|
1731
|
+
* error never leaks the set of trusted issuers.
|
|
1732
|
+
*/
|
|
1733
|
+
isPublic: boolean;
|
|
1884
1734
|
}
|
|
1885
1735
|
/**
|
|
1886
|
-
*
|
|
1736
|
+
* **The** authorization predicate. A call is permitted iff some presented
|
|
1737
|
+
* capability (1) addresses the call, (2) has a genuine, well-delegated
|
|
1738
|
+
* chain whose leaf audience is the caller (`call.signer`), and (3) roots
|
|
1739
|
+
* at an issuer the verifier accepts **for the call's service**.
|
|
1887
1740
|
*
|
|
1888
|
-
*
|
|
1889
|
-
*
|
|
1890
|
-
*
|
|
1891
|
-
*
|
|
1892
|
-
*
|
|
1741
|
+
* Pure: it reports the verdict (and the `capabilityNonce` / `rootIssuer`
|
|
1742
|
+
* for audit) but performs no consumption. Replay is the caller's job — the
|
|
1743
|
+
* gate dedups `call.nonce`, so `callBind` grants are single-use for free.
|
|
1744
|
+
*
|
|
1745
|
+
* `acceptedRootIssuers` is consulted with the call's `serviceId` and returns
|
|
1746
|
+
* the accepted {@link AcceptedRootIssuer} anchors; an empty result rejects
|
|
1747
|
+
* every capability (fail closed) — trust is the verifier's, never the
|
|
1748
|
+
* token's. Anchors flagged `isPublic` are named in the rejection reason when
|
|
1749
|
+
* a chain roots at an unaccepted issuer.
|
|
1893
1750
|
*/
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
}
|
|
1897
|
-
[key: string]: JsonValue | undefined;
|
|
1898
|
-
}> = TUserParams & LinkRpcWireMeta;
|
|
1899
|
-
/** JSON-RPC request whose `params` carry the linkrpc wire meta. */
|
|
1900
|
-
type LinkRpcJsonRpcRequest<TUserParams extends {
|
|
1901
|
-
[key: string]: JsonValue | undefined;
|
|
1902
|
-
} = {
|
|
1903
|
-
[key: string]: JsonValue | undefined;
|
|
1904
|
-
}> = JsonRpcRequest<LinkRpcWireParams<TUserParams>>;
|
|
1905
|
-
/** JSON-RPC notification whose `params` carry the linkrpc wire meta. */
|
|
1906
|
-
type LinkRpcJsonRpcNotification<TUserParams extends {
|
|
1907
|
-
[key: string]: JsonValue | undefined;
|
|
1908
|
-
} = {
|
|
1909
|
-
[key: string]: JsonValue | undefined;
|
|
1910
|
-
}> = JsonRpcNotification<LinkRpcWireParams<TUserParams>>;
|
|
1911
|
-
/** Either of the two linkrpc-bearing JSON-RPC message shapes. */
|
|
1912
|
-
type LinkRpcJsonRpcMessage<TUserParams extends {
|
|
1913
|
-
[key: string]: JsonValue | undefined;
|
|
1914
|
-
} = {
|
|
1915
|
-
[key: string]: JsonValue | undefined;
|
|
1916
|
-
}> = LinkRpcJsonRpcRequest<TUserParams> | LinkRpcJsonRpcNotification<TUserParams>;
|
|
1751
|
+
declare function permits(call: Call, capabilities: readonly SignedCapability[], acceptedRootIssuers: (serviceId: string) => readonly AcceptedRootIssuer[], nowMs: number, opts?: {
|
|
1752
|
+
maxDepth?: number;
|
|
1753
|
+
}): Promise<PermitResult>;
|
|
1917
1754
|
/**
|
|
1918
|
-
*
|
|
1919
|
-
*
|
|
1920
|
-
* rest is the signed user params" stays unambiguous.
|
|
1755
|
+
* Sign a `Capability` with a {@link SigningIdentity}. The private key never
|
|
1756
|
+
* leaves the identity. The result verifies via {@link verifyChain}.
|
|
1921
1757
|
*/
|
|
1922
|
-
declare function
|
|
1758
|
+
declare function signCapability(capability: Capability, issuer: SigningIdentity): Promise<SignedCapability>;
|
|
1759
|
+
interface IssueCapabilityOptions {
|
|
1760
|
+
/** Identity allowed to present the capability. */
|
|
1761
|
+
readonly audience: PublicSigningIdentity;
|
|
1762
|
+
/** Authority granted to the audience. */
|
|
1763
|
+
readonly permissions: readonly Permission[];
|
|
1764
|
+
/** Optional expiration time as Unix milliseconds. */
|
|
1765
|
+
readonly expiresAtMs?: number;
|
|
1766
|
+
/** Optional parent whose authority this capability narrows. */
|
|
1767
|
+
readonly parent?: SignedCapability;
|
|
1768
|
+
}
|
|
1923
1769
|
/**
|
|
1924
|
-
*
|
|
1925
|
-
*
|
|
1926
|
-
*
|
|
1927
|
-
* every chained hub can independently verify the envelope. Terminal dispatch
|
|
1928
|
-
* may use this derived value for application-schema validation without mutating
|
|
1929
|
-
* or replacing the wire message.
|
|
1770
|
+
* Issue and sign a capability, deriving its issuer, nonce, and optional parent
|
|
1771
|
+
* hash. The result is plain JSON data and survives a JSON stringify/parse
|
|
1772
|
+
* round-trip without reconstruction.
|
|
1930
1773
|
*/
|
|
1931
|
-
declare function
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
}
|
|
1951
|
-
type MessageWithContext<TCtx> = JsonRpcMessage & {
|
|
1952
|
-
context: TCtx;
|
|
1774
|
+
declare function issueCapability(issuer: SigningIdentity, options: IssueCapabilityOptions): Promise<SignedCapability>;
|
|
1775
|
+
type ParamMatcherFor<T> = {
|
|
1776
|
+
exact: T;
|
|
1777
|
+
} | {
|
|
1778
|
+
enum: T[];
|
|
1779
|
+
} | {
|
|
1780
|
+
any: true;
|
|
1781
|
+
} | (T extends string ? {
|
|
1782
|
+
prefix: string;
|
|
1783
|
+
} : never) | (T extends readonly string[] ? {
|
|
1784
|
+
subsetOf: string[];
|
|
1785
|
+
} : never);
|
|
1786
|
+
/** Type-safe top-level parameter matchers for one interface member. */
|
|
1787
|
+
type ParamMatchers<T> = T extends Record<string, unknown> ? { [K in keyof T]: ParamMatcherFor<Exclude<T[K], undefined>>; } : never;
|
|
1788
|
+
type RequestMemberName<TMembers extends MemberMap> = { [K in keyof TMembers]: TMembers[K] extends RequestType<any, any, any, any, any, any, any> ? K : never; }[keyof TMembers] & string;
|
|
1789
|
+
type RequestParams<TMember> = TMember extends RequestType<infer TParams, any, any, any, any, any, any> ? TParams : never;
|
|
1790
|
+
/** Match a string parameter by prefix. */
|
|
1791
|
+
declare function prefix(value: string): {
|
|
1792
|
+
prefix: string;
|
|
1953
1793
|
};
|
|
1954
|
-
type MessageTransportWithContext<TCtx> = IMessageTransport<JsonRpcMessage, MessageWithContext<TCtx>>;
|
|
1955
|
-
type MessageTransportDirection = 'send' | 'receive';
|
|
1956
|
-
type MessageTransportTrace = (direction: MessageTransportDirection, message: JsonRpcMessage) => void;
|
|
1957
1794
|
/**
|
|
1958
|
-
*
|
|
1959
|
-
*
|
|
1795
|
+
* Build an invoke permission from a typed interface member. The helper derives
|
|
1796
|
+
* the interface id and schema hash and type-checks parameter matcher names and
|
|
1797
|
+
* values against the member's params.
|
|
1960
1798
|
*/
|
|
1961
|
-
declare function
|
|
1799
|
+
declare function invoke<TMembers extends MemberMap, TMember extends RequestMemberName<TMembers>>(serviceId: string, iface: InterfaceDefinition<TMembers>, member: TMember, params?: ParamMatchers<RequestParams<TMembers[TMember]>>): Permission;
|
|
1800
|
+
//#endregion
|
|
1801
|
+
//#region src/connection/jsonRpcChannel.d.ts
|
|
1962
1802
|
/**
|
|
1963
|
-
*
|
|
1964
|
-
*
|
|
1803
|
+
* Minimal JSON-RPC 2.0 channel: correlates requests with responses,
|
|
1804
|
+
* dispatches incoming requests/notifications to a handler.
|
|
1965
1805
|
*
|
|
1966
|
-
*
|
|
1967
|
-
*
|
|
1968
|
-
*
|
|
1969
|
-
|
|
1970
|
-
declare function connectTransports<T extends JsonRpcMessage>(a: IMessageTransport<T>, b: IMessageTransport<T>): IDisposable;
|
|
1971
|
-
/**
|
|
1972
|
-
* Two in-memory transports wired back-to-back. Useful for tests and for
|
|
1973
|
-
* same-process bridges.
|
|
1806
|
+
* Construct via {@link JsonRpcChannel.create}: it returns a
|
|
1807
|
+
* {@link Channel} factory which materialises the live channel once a
|
|
1808
|
+
* handler is supplied via `.connect(handler)`. The handler is fixed for
|
|
1809
|
+
* the channel's lifetime — no setter, no mid-flight swap.
|
|
1974
1810
|
*
|
|
1975
|
-
*
|
|
1976
|
-
*
|
|
1977
|
-
* `
|
|
1978
|
-
* level. At runtime both halves just hand objects through by reference.
|
|
1811
|
+
* The outbound `TOutCtx` of the produced sender is `unknown` — this
|
|
1812
|
+
* channel ignores per-call ctx entirely. Decorators (e.g.
|
|
1813
|
+
* `SigningSender`) lift it to a concrete shape.
|
|
1979
1814
|
*/
|
|
1980
|
-
declare class
|
|
1981
|
-
readonly
|
|
1982
|
-
readonly b: IMessageTransport<TFromA, TFromB>;
|
|
1983
|
-
constructor();
|
|
1984
|
-
}
|
|
1985
|
-
//#endregion
|
|
1986
|
-
//#region src/transport/multiplexedTransport.d.ts
|
|
1987
|
-
interface MuxEnvelope {
|
|
1988
|
-
readonly $mux: "v1";
|
|
1989
|
-
readonly ch: string;
|
|
1990
|
-
readonly m: JsonRpcMessage;
|
|
1991
|
-
}
|
|
1992
|
-
declare class MultiplexedTransport<TChannels extends Record<string, string>> implements IDisposable {
|
|
1993
|
-
static create<TChannels extends Record<string, string>>(base: IMessageTransport<MuxEnvelope, MuxEnvelope>, channels: TChannels): MultiplexedTransport<TChannels>;
|
|
1994
|
-
/** Logical transports keyed by the friendly channel names. */
|
|
1995
|
-
readonly transports: { readonly [K in keyof TChannels]: IMessageTransport; };
|
|
1996
|
-
private readonly _base;
|
|
1997
|
-
private readonly _byId;
|
|
1998
|
-
private readonly _usedIds;
|
|
1999
|
-
private _disposed;
|
|
2000
|
-
constructor(base: IMessageTransport<MuxEnvelope, MuxEnvelope>, channels: TChannels);
|
|
1815
|
+
declare class JsonRpcChannel<TInCtx = undefined> implements IRequestSender<unknown> {
|
|
1816
|
+
private readonly _transport;
|
|
2001
1817
|
/**
|
|
2002
|
-
*
|
|
2003
|
-
*
|
|
2004
|
-
*
|
|
2005
|
-
* envelope for an old iframe from being delivered to a replacement iframe.
|
|
1818
|
+
* Wrap a transport in a {@link Channel}. The channel's sender is live
|
|
1819
|
+
* immediately; call {@link Channel.setRequestHandler} (or pass the channel
|
|
1820
|
+
* to {@link LinkRpcConnection}) to bind the inbound handler.
|
|
2006
1821
|
*/
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
readonly
|
|
2015
|
-
private readonly _setHandler;
|
|
2016
|
-
private readonly _setWireObserver?;
|
|
2017
|
-
constructor(sender: IRequestSender<TOutCtx>, _setHandler: (h: IRequestHandler<TInCtx> | undefined) => void, _setWireObserver?: ((observer: WireMessageObserver | undefined) => void) | undefined);
|
|
2018
|
-
/** Bind the inbound request/notification handler. May be called before or after construction of {@link LinkRpcConnection}. */
|
|
2019
|
-
setRequestHandler(handler: IRequestHandler<TInCtx> | undefined): void;
|
|
1822
|
+
static create<TInCtx = undefined>(transport: ChannelTransport<TInCtx>): Channel<TInCtx, unknown>;
|
|
1823
|
+
/** Wrap a transport and retain an explicit lifecycle hook for its owner. */
|
|
1824
|
+
static createWithClose<TInCtx = undefined>(transport: ChannelTransport<TInCtx>): {
|
|
1825
|
+
channel: Channel<TInCtx, unknown>;
|
|
1826
|
+
close: () => void;
|
|
1827
|
+
};
|
|
1828
|
+
private _nextId;
|
|
1829
|
+
private readonly _pending;
|
|
2020
1830
|
/**
|
|
2021
|
-
*
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
1831
|
+
* Per-request callbacks invoked when a {@link STREAM_METHOD}
|
|
1832
|
+
* notification arrives with a matching `requestId`. Used in both
|
|
1833
|
+
* directions: outgoing-request callers register here keyed by the
|
|
1834
|
+
* id they sent; per-call incoming-request stream handles register
|
|
1835
|
+
* keyed by the id they observed. Entries are removed when the
|
|
1836
|
+
* corresponding request completes (response received for outgoing,
|
|
1837
|
+
* response sent for incoming).
|
|
2024
1838
|
*/
|
|
2025
|
-
|
|
1839
|
+
private readonly _streamListeners;
|
|
2026
1840
|
/**
|
|
2027
|
-
*
|
|
2028
|
-
*
|
|
2029
|
-
*
|
|
2030
|
-
* so the receive side is bound exactly once regardless of decoration depth.
|
|
1841
|
+
* Per-incoming-request handlers for reserved `control` messages
|
|
1842
|
+
* (cancel / ping / pong) arriving as stream notifications. Keyed
|
|
1843
|
+
* by the id observed; removed when the request settles.
|
|
2031
1844
|
*/
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
* side (e.g. the hub stamps `Participant` on overlay-bound messages).
|
|
2044
|
-
* For wire transports it's `undefined`.
|
|
2045
|
-
*/
|
|
2046
|
-
interface IncomingCall<TInCtx = undefined> {
|
|
2047
|
-
method: string;
|
|
2048
|
-
params: JsonValue | undefined;
|
|
2049
|
-
/** Out-of-band context attached by the transport, if any. */
|
|
2050
|
-
context: TInCtx;
|
|
1845
|
+
private readonly _streamControl;
|
|
1846
|
+
private readonly _incomingAborts;
|
|
1847
|
+
private _handler;
|
|
1848
|
+
private _wireObserver;
|
|
1849
|
+
private _closeError;
|
|
1850
|
+
setRequestHandler(handler: IRequestHandler<TInCtx> | undefined): void;
|
|
1851
|
+
setWireMessageObserver(observer: WireMessageObserver | undefined): void;
|
|
1852
|
+
private constructor();
|
|
1853
|
+
sendRequest(method: string, params: JsonValue | undefined, opts?: SendOpts<unknown>): Promise<JsonValue>;
|
|
1854
|
+
sendNotification(method: string, params: JsonValue | undefined, opts?: SendOpts<unknown>): Promise<void>;
|
|
1855
|
+
sendRequestWithStream(method: string, params: JsonValue | undefined, opts?: StreamSendOpts<unknown>): RawStreamingCall;
|
|
2051
1856
|
/**
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2054
|
-
*
|
|
2055
|
-
* (
|
|
1857
|
+
* Build the symmetric ping/pong machinery for one in-flight request.
|
|
1858
|
+
*
|
|
1859
|
+
* `outboundDir` is the direction *this* side emits controls in
|
|
1860
|
+
* (`toCallee` for the caller, `toCaller` for the callee). A received
|
|
1861
|
+
* ping is answered with a pong in that same direction, echoing the
|
|
1862
|
+
* ping's nonce; a received pong resolves the matching outstanding
|
|
1863
|
+
* {@link ping} probe.
|
|
2056
1864
|
*/
|
|
2057
|
-
|
|
1865
|
+
private _makePinger;
|
|
2058
1866
|
/**
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
2061
|
-
*
|
|
2062
|
-
*
|
|
2063
|
-
* which surfaces as a `cancelled` error response. For notifications
|
|
2064
|
-
* this never aborts.
|
|
1867
|
+
* Emit a stream notification ({@link STREAM_METHOD}) associated with
|
|
1868
|
+
* an in-flight request. Internal: outgoing-side callers reach this
|
|
1869
|
+
* via {@link RawStreamingCall.send} / `cancel`; incoming-side handlers
|
|
1870
|
+
* reach it via {@link IncomingStream.send}.
|
|
2065
1871
|
*/
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
1872
|
+
private _sendStream;
|
|
1873
|
+
close(): void;
|
|
1874
|
+
private _throwIfClosed;
|
|
1875
|
+
private _onMessage;
|
|
1876
|
+
private _handleStreamNotification;
|
|
1877
|
+
private _handleRequest;
|
|
1878
|
+
private _handleNotification;
|
|
1879
|
+
private _observeInbound;
|
|
1880
|
+
private _observeOutbound;
|
|
1881
|
+
private _observeSendFailure;
|
|
1882
|
+
}
|
|
1883
|
+
//#endregion
|
|
1884
|
+
//#region src/identity/managedIdentity.d.ts
|
|
1885
|
+
/**
|
|
1886
|
+
* Executor-side backing for `identity.storage::*`. Lifecycle tied to a
|
|
1887
|
+
* single managed-identity slot; the executor decides where bytes are
|
|
1888
|
+
* stored.
|
|
2075
1889
|
*/
|
|
2076
|
-
interface
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
/**
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
* listener. The channel detaches the listener automatically when
|
|
2083
|
-
* the handler's response settles.
|
|
2084
|
-
*/
|
|
2085
|
-
onMessage(listener: ((payload: JsonValue) => void) | undefined): void;
|
|
2086
|
-
/**
|
|
2087
|
-
* Liveness probe toward the caller: emit a `toCaller` ping and
|
|
2088
|
-
* resolve once the caller's `pong` (matching nonce) returns. Rejects
|
|
2089
|
-
* if the request settles first. Independent of the channel's
|
|
2090
|
-
* automatic keepalive ping.
|
|
2091
|
-
*/
|
|
2092
|
-
ping(): Promise<void>;
|
|
1890
|
+
interface ManagedIdentityStorageBackend {
|
|
1891
|
+
get(key: string): Promise<unknown | undefined>;
|
|
1892
|
+
set(key: string, value: unknown): Promise<void>;
|
|
1893
|
+
/** Returns `true` iff the key existed before this call. */
|
|
1894
|
+
delete(key: string): Promise<boolean>;
|
|
1895
|
+
list(prefix?: string): Promise<string[]>;
|
|
2093
1896
|
}
|
|
2094
|
-
type Result = {
|
|
2095
|
-
result: JsonValue;
|
|
2096
|
-
} | {
|
|
2097
|
-
error: {
|
|
2098
|
-
code: number;
|
|
2099
|
-
message: string;
|
|
2100
|
-
data?: JsonValue;
|
|
2101
|
-
};
|
|
2102
|
-
};
|
|
2103
1897
|
/**
|
|
2104
|
-
*
|
|
2105
|
-
*
|
|
2106
|
-
* lifetime) and hands the caller back an `IRequestSender`.
|
|
2107
|
-
*
|
|
2108
|
-
* `TOutCtx` is the per-call context bag this sender understands. For
|
|
2109
|
-
* the base {@link JsonRpcChannel} it's `undefined` (the channel
|
|
2110
|
-
* doesn't read any overrides). Decorators like `SigningSender`
|
|
2111
|
-
* parametrise it on their own ctx shape.
|
|
1898
|
+
* In-process storage backend. Used by tests and by any executor that
|
|
1899
|
+
* doesn't need at-rest persistence.
|
|
2112
1900
|
*/
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
* promise, and a `send` for emitting client→server stream messages.
|
|
2120
|
-
*/
|
|
2121
|
-
sendRequestWithStream(method: string, params: JsonValue | undefined, opts?: StreamSendOpts<TOutCtx>): RawStreamingCall;
|
|
2122
|
-
close(): void;
|
|
1901
|
+
declare class InMemoryManagedIdentityStorage implements ManagedIdentityStorageBackend {
|
|
1902
|
+
private readonly _data;
|
|
1903
|
+
get(key: string): Promise<unknown | undefined>;
|
|
1904
|
+
set(key: string, value: unknown): Promise<void>;
|
|
1905
|
+
delete(key: string): Promise<boolean>;
|
|
1906
|
+
list(prefix?: string): Promise<string[]>;
|
|
2123
1907
|
}
|
|
2124
1908
|
/**
|
|
2125
|
-
*
|
|
2126
|
-
*
|
|
2127
|
-
*
|
|
2128
|
-
* resolves with the call's response.
|
|
1909
|
+
* In-process `ManagedIdentity` that holds the private key in memory and
|
|
1910
|
+
* uses the package crypto API. Useful for tests and for hub-side features
|
|
1911
|
+
* that want a short-lived identity without touching disk.
|
|
2129
1912
|
*/
|
|
2130
|
-
|
|
2131
|
-
readonly
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
/**
|
|
2142
|
-
|
|
2143
|
-
* not notify the callee; call {@link cancel} first when remote work should
|
|
2144
|
-
* also be cancelled. Safe to call after the request has already settled.
|
|
2145
|
-
*/
|
|
2146
|
-
dispose?(reason?: string): void;
|
|
2147
|
-
/**
|
|
2148
|
-
* Liveness probe toward the callee: emit a `toCallee` ping and
|
|
2149
|
-
* resolve once the callee's `pong` (matching nonce) returns. Rejects
|
|
2150
|
-
* if the request settles first. Independent of the channel's
|
|
2151
|
-
* automatic keepalive ping.
|
|
2152
|
-
*/
|
|
2153
|
-
ping(): Promise<void>;
|
|
1913
|
+
declare class InMemoryManagedIdentity implements Identity {
|
|
1914
|
+
private readonly _ed;
|
|
1915
|
+
private readonly _wrap;
|
|
1916
|
+
readonly principal: PrincipalId;
|
|
1917
|
+
readonly wrapPublicKey: Uint8Array;
|
|
1918
|
+
constructor(_ed: Keypair, _wrap: X25519Keypair);
|
|
1919
|
+
get publicSigningIdentity(): PublicSigningIdentity;
|
|
1920
|
+
get publicWrappingIdentity(): PublicWrappingIdentity;
|
|
1921
|
+
sign(bytes: Uint8Array): Promise<Signature>;
|
|
1922
|
+
wrap(domain: string, bytes: Uint8Array): Promise<Uint8Array>;
|
|
1923
|
+
unwrap(domain: string, blob: Uint8Array): Promise<Uint8Array>;
|
|
1924
|
+
/** Generate a fresh in-memory identity (Ed25519 + X25519 keypairs). */
|
|
1925
|
+
static generate(): Promise<InMemoryManagedIdentity>;
|
|
2154
1926
|
}
|
|
2155
1927
|
/**
|
|
2156
|
-
*
|
|
1928
|
+
* Register the `identity` interface on `overlay` so the bound participant
|
|
1929
|
+
* can call `identity::sign` etc. on its root overlay. The overlay is
|
|
1930
|
+
* private to one participant — no other peer can reach these methods.
|
|
2157
1931
|
*
|
|
2158
|
-
* `
|
|
2159
|
-
*
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2162
|
-
* bake it into the `$hubrpc` envelope.
|
|
1932
|
+
* When `storage` is supplied, the `identity.storage` interface is
|
|
1933
|
+
* registered alongside `identity::*`. Lifetime/scope of the backend is
|
|
1934
|
+
* the executor's responsibility — for keystore-backed identities the
|
|
1935
|
+
* backend lives as long as the identity slot does.
|
|
2163
1936
|
*
|
|
2164
|
-
*
|
|
2165
|
-
*
|
|
2166
|
-
*
|
|
2167
|
-
* like `SigningSender` interpret it.
|
|
1937
|
+
* Typical caller: the executor (e.g. the VS Code extension), right after
|
|
1938
|
+
* `Hub.attachParticipant`, on the `rootOverlay` returned from the attach
|
|
1939
|
+
* handle.
|
|
2168
1940
|
*/
|
|
2169
|
-
|
|
2170
|
-
readonly ctx?: TOutCtx;
|
|
2171
|
-
/** Interface schema hash for this call (interface-level metadata). */
|
|
2172
|
-
readonly interfaceHash?: string;
|
|
2173
|
-
}
|
|
2174
|
-
interface StreamSendOpts<TOutCtx = undefined> extends SendOpts<TOutCtx> {
|
|
2175
|
-
readonly onStreamMessage?: (payload: JsonValue) => void;
|
|
2176
|
-
}
|
|
1941
|
+
declare function registerIdentityOnOverlay(overlay: LinkRpcConnection, identity: Identity, storage?: ManagedIdentityStorageBackend): void;
|
|
2177
1942
|
/**
|
|
2178
|
-
*
|
|
2179
|
-
*
|
|
2180
|
-
*
|
|
1943
|
+
* Like {@link registerIdentityOnOverlay}, but resolves the identity lazily on
|
|
1944
|
+
* first use via `resolveIdentity`. The identity is materialized only when the
|
|
1945
|
+
* bound participant actually calls `identity::*` — registering the overlay
|
|
1946
|
+
* does NOT create or load any identity.
|
|
1947
|
+
*
|
|
1948
|
+
* This is essential for the consent model: a host can serve `identity::*` on a
|
|
1949
|
+
* keystore slot without making the slot privileged (`hasState`) until the app
|
|
1950
|
+
* genuinely opts into an identity. `resolveIdentity` is expected to be cheap on
|
|
1951
|
+
* repeat calls (the keystore caches in memory), and to reflect lifecycle
|
|
1952
|
+
* changes — e.g. after a slot is wiped and re-created ("Reset Identity"), the
|
|
1953
|
+
* next call resolves the fresh identity.
|
|
1954
|
+
*
|
|
1955
|
+
* `storage` is registered eagerly because reading/writing storage is itself
|
|
1956
|
+
* the privileged act the app must perform to gain state — exposing the
|
|
1957
|
+
* interface costs nothing until used.
|
|
2181
1958
|
*/
|
|
2182
|
-
|
|
1959
|
+
declare function registerLazyIdentityOnOverlay(overlay: LinkRpcConnection<unknown>, resolveIdentity: () => Promise<Identity>, storage?: ManagedIdentityStorageBackend): void;
|
|
2183
1960
|
/**
|
|
2184
|
-
*
|
|
2185
|
-
*
|
|
2186
|
-
*
|
|
2187
|
-
*
|
|
2188
|
-
*
|
|
1961
|
+
* Client-side proxy for `identity.storage::*`. Methods round-trip through
|
|
1962
|
+
* the participant's root overlay; the executor enforces key-shape rules
|
|
1963
|
+
* server-side.
|
|
1964
|
+
*
|
|
1965
|
+
* Calls are unsigned (same recursion-guard rationale as
|
|
1966
|
+
* {@link createManagedIdentity} — the overlay is private to one
|
|
1967
|
+
* participant, so transport-level routing already authenticates).
|
|
2189
1968
|
*/
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
/** Whether this error was decoded from a peer response. */
|
|
2196
|
-
readonly origin: 'local' | 'remote';
|
|
2197
|
-
readonly data?: JsonValue;
|
|
2198
|
-
readonly hasData: boolean;
|
|
2199
|
-
constructor(message: string, code: number, data?: JsonValue,
|
|
2200
|
-
/** Whether this error was decoded from a peer response. */
|
|
2201
|
-
origin?: 'local' | 'remote', hasData?: boolean);
|
|
2202
|
-
}
|
|
2203
|
-
//#endregion
|
|
2204
|
-
//#region src/connection/bareInterfaceTarget.d.ts
|
|
2205
|
-
/** A metadata-free foreign-protocol interface and its wire-method prefix. */
|
|
2206
|
-
interface BareInterfaceTarget<TDef extends InterfaceDefinition<any>> {
|
|
2207
|
-
readonly mode: 'bare';
|
|
2208
|
-
readonly interface: TDef;
|
|
2209
|
-
readonly prefix: string;
|
|
1969
|
+
interface ManagedIdentityStorage {
|
|
1970
|
+
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
1971
|
+
set(key: string, value: unknown): Promise<void>;
|
|
1972
|
+
delete(key: string): Promise<boolean>;
|
|
1973
|
+
list(prefix?: string): Promise<string[]>;
|
|
2210
1974
|
}
|
|
2211
1975
|
/**
|
|
2212
|
-
*
|
|
2213
|
-
*
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
readonly prefix?: string;
|
|
2217
|
-
}): BareInterfaceTarget<TDef>;
|
|
2218
|
-
//#endregion
|
|
2219
|
-
//#region src/connection/channelConnector.d.ts
|
|
2220
|
-
/**
|
|
2221
|
-
* A raw channel that signals when it closes (and, when possible, can be torn
|
|
2222
|
-
* down). Both {@link openHubChannel}'s `HubChannel` and `openStdioChannel`'s
|
|
2223
|
-
* `StdioChannel` satisfy this shape.
|
|
1976
|
+
* A managed identity resolved from an executor's `identity::*` overlay: a
|
|
1977
|
+
* full {@link Identity} (signing + HPKE wrap/unwrap, all round-tripping
|
|
1978
|
+
* through the executor — private keys never leave it) plus the
|
|
1979
|
+
* per-identity {@link ManagedIdentityStorage}.
|
|
2224
1980
|
*/
|
|
2225
|
-
|
|
2226
|
-
/**
|
|
2227
|
-
* Fires once when the channel closes. Returns a disposable to unsubscribe.
|
|
2228
|
-
*
|
|
2229
|
-
* Ordering contract: when a close causes a sending method (e.g. a request
|
|
2230
|
-
* or notification) to reject/throw, {@link onClose} must fire *before* that
|
|
2231
|
-
* rejection surfaces to the caller. This lets consumers reliably tell a
|
|
2232
|
-
* close-induced failure (the channel is already observably closed) apart
|
|
2233
|
-
* from a genuine error (the channel is still open). See
|
|
2234
|
-
* {@link ChannelConnector.keepConnected}.
|
|
2235
|
-
*/
|
|
2236
|
-
onClose(listener: () => void): IDisposable;
|
|
2237
|
-
/** Tear the channel down. Optional — stdio channels have no explicit close. */
|
|
2238
|
-
close?(): void;
|
|
2239
|
-
};
|
|
2240
|
-
/** Handle returned by {@link ChannelConnector.keepConnected}. */
|
|
2241
|
-
interface KeepConnectedHandle {
|
|
1981
|
+
interface ManagedIdentity extends Identity {
|
|
2242
1982
|
/**
|
|
2243
|
-
*
|
|
2244
|
-
*
|
|
1983
|
+
* Per-identity persistent key/value store. Backed by the executor's
|
|
1984
|
+
* `identity.storage::*` overlay; calls throw when the executor did not
|
|
1985
|
+
* register storage for this slot (e.g. an in-process identity for tests).
|
|
2245
1986
|
*/
|
|
2246
|
-
readonly
|
|
2247
|
-
/** Stop redialing and close the current channel (if any). */
|
|
2248
|
-
stop(): void;
|
|
2249
|
-
}
|
|
2250
|
-
/** Callback run on every (re)connect. The channel is the raw, unsigned channel. */
|
|
2251
|
-
type OnChannelConnect<T extends ConnectableChannel> = (ctx: {
|
|
2252
|
-
channel: T;
|
|
2253
|
-
}) => void | Promise<void>;
|
|
2254
|
-
interface ExpBackoffOptions {
|
|
2255
|
-
readonly initialBackoffMs?: number;
|
|
2256
|
-
readonly maxBackoffMs?: number;
|
|
1987
|
+
readonly storage: ManagedIdentityStorage;
|
|
2257
1988
|
}
|
|
2258
1989
|
/**
|
|
2259
|
-
*
|
|
2260
|
-
*
|
|
2261
|
-
*
|
|
2262
|
-
*
|
|
2263
|
-
*
|
|
1990
|
+
* Bootstrap a {@link ManagedIdentity} from a sender (typically the raw
|
|
1991
|
+
* unsigned sender obtained via `channel.sender` before wrapping with
|
|
1992
|
+
* {@link SigningSender}). Makes `identity::*` calls unsigned — the
|
|
1993
|
+
* executor's overlay is private to one participant so routing already
|
|
1994
|
+
* identifies the caller, preventing signing recursion.
|
|
2264
1995
|
*
|
|
2265
|
-
*
|
|
2266
|
-
*
|
|
2267
|
-
*
|
|
1996
|
+
* The returned identity signs / wraps / unwraps by round-tripping through
|
|
1997
|
+
* the executor's `identity::*` overlay; the caller wires it into their
|
|
1998
|
+
* {@link SigningSender} configuration (e.g. as a {@link Principal}). No
|
|
1999
|
+
* side effects on any existing connection or holder.
|
|
2268
2000
|
*/
|
|
2269
|
-
declare
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
private readonly _maxBackoffMs;
|
|
2274
|
-
private constructor();
|
|
2275
|
-
/**
|
|
2276
|
-
* A connector over a single channel (or a promise of one). Never redials;
|
|
2277
|
-
* the loop ends when the channel closes or {@link KeepConnectedHandle.stop}
|
|
2278
|
-
* fires.
|
|
2279
|
-
*/
|
|
2280
|
-
static once<T extends ConnectableChannel>(channel: T | Promise<T>): ChannelConnector<T>;
|
|
2281
|
-
/**
|
|
2282
|
-
* A redialing connector: `open` is called once per attempt, and the loop
|
|
2283
|
-
* reconnects with exponential backoff after each close (or failed open).
|
|
2284
|
-
*/
|
|
2285
|
-
static expBackoff<T extends ConnectableChannel>(open: () => Promise<T>, opts?: ExpBackoffOptions): ChannelConnector<T>;
|
|
2001
|
+
declare function createManagedIdentity(sender: IRequestSender<unknown>): Promise<ManagedIdentity>;
|
|
2002
|
+
//#endregion
|
|
2003
|
+
//#region src/identity/capBag.d.ts
|
|
2004
|
+
interface CapBagOptions {
|
|
2286
2005
|
/**
|
|
2287
|
-
*
|
|
2288
|
-
*
|
|
2289
|
-
*
|
|
2006
|
+
* Per-identity persistent storage (e.g.
|
|
2007
|
+
* {@link ManagedIdentityHandle.storage}). Omit for a memory-only bag
|
|
2008
|
+
* that forgets its caps when the process exits.
|
|
2290
2009
|
*/
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2010
|
+
readonly storage?: ManagedIdentityStorage;
|
|
2011
|
+
/** Storage key. Defaults to `hubrpc.caps.v1`. */
|
|
2012
|
+
readonly storageKey?: string;
|
|
2013
|
+
/** Optional sink for non-fatal storage warnings. */
|
|
2014
|
+
readonly onWarn?: (message: string) => void;
|
|
2294
2015
|
}
|
|
2295
|
-
//#endregion
|
|
2296
|
-
//#region src/connection/jsonRpcChannel.d.ts
|
|
2297
2016
|
/**
|
|
2298
|
-
*
|
|
2299
|
-
*
|
|
2300
|
-
*
|
|
2301
|
-
*
|
|
2302
|
-
* {@link Channel} factory which materialises the live channel once a
|
|
2303
|
-
* handler is supplied via `.connect(handler)`. The handler is fixed for
|
|
2304
|
-
* the channel's lifetime — no setter, no mid-flight swap.
|
|
2017
|
+
* A process-lifetime bag of hub-issued capabilities. Plug
|
|
2018
|
+
* {@link CapBag.provider} straight into a connection's cap provider so every
|
|
2019
|
+
* outbound signed call carries whatever caps have been granted so far. The
|
|
2020
|
+
* hub picks whichever cap matches the call per dispatch.
|
|
2305
2021
|
*
|
|
2306
|
-
*
|
|
2307
|
-
*
|
|
2308
|
-
*
|
|
2022
|
+
* When constructed with {@link CapBagOptions.storage} the bag hydrates from
|
|
2023
|
+
* (and persists to) storage, so the next process spawn for the same identity
|
|
2024
|
+
* reuses its grants without re-prompting.
|
|
2309
2025
|
*/
|
|
2310
|
-
declare class
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
static create<TInCtx = undefined>(transport: ChannelTransport<TInCtx>): Channel<TInCtx, unknown>;
|
|
2318
|
-
/** Wrap a transport and retain an explicit lifecycle hook for its owner. */
|
|
2319
|
-
static createWithClose<TInCtx = undefined>(transport: ChannelTransport<TInCtx>): {
|
|
2320
|
-
channel: Channel<TInCtx, unknown>;
|
|
2321
|
-
close: () => void;
|
|
2322
|
-
};
|
|
2323
|
-
private _nextId;
|
|
2324
|
-
private readonly _pending;
|
|
2325
|
-
/**
|
|
2326
|
-
* Per-request callbacks invoked when a {@link STREAM_METHOD}
|
|
2327
|
-
* notification arrives with a matching `requestId`. Used in both
|
|
2328
|
-
* directions: outgoing-request callers register here keyed by the
|
|
2329
|
-
* id they sent; per-call incoming-request stream handles register
|
|
2330
|
-
* keyed by the id they observed. Entries are removed when the
|
|
2331
|
-
* corresponding request completes (response received for outgoing,
|
|
2332
|
-
* response sent for incoming).
|
|
2333
|
-
*/
|
|
2334
|
-
private readonly _streamListeners;
|
|
2335
|
-
/**
|
|
2336
|
-
* Per-incoming-request handlers for reserved `control` messages
|
|
2337
|
-
* (cancel / ping / pong) arriving as stream notifications. Keyed
|
|
2338
|
-
* by the id observed; removed when the request settles.
|
|
2339
|
-
*/
|
|
2340
|
-
private readonly _streamControl;
|
|
2341
|
-
private readonly _incomingAborts;
|
|
2342
|
-
private _handler;
|
|
2343
|
-
private _wireObserver;
|
|
2344
|
-
private _closeError;
|
|
2345
|
-
setRequestHandler(handler: IRequestHandler<TInCtx> | undefined): void;
|
|
2346
|
-
setWireMessageObserver(observer: WireMessageObserver | undefined): void;
|
|
2026
|
+
declare class CapBag {
|
|
2027
|
+
/** Create a bag, hydrating from storage when one was supplied. */
|
|
2028
|
+
static load(options?: CapBagOptions): Promise<CapBag>;
|
|
2029
|
+
private readonly _caps;
|
|
2030
|
+
private readonly _storage?;
|
|
2031
|
+
private readonly _storageKey;
|
|
2032
|
+
private readonly _onWarn;
|
|
2347
2033
|
private constructor();
|
|
2348
|
-
|
|
2349
|
-
sendNotification(method: string, params: JsonValue | undefined, opts?: SendOpts<unknown>): Promise<void>;
|
|
2350
|
-
sendRequestWithStream(method: string, params: JsonValue | undefined, opts?: StreamSendOpts<unknown>): RawStreamingCall;
|
|
2351
|
-
/**
|
|
2352
|
-
* Build the symmetric ping/pong machinery for one in-flight request.
|
|
2353
|
-
*
|
|
2354
|
-
* `outboundDir` is the direction *this* side emits controls in
|
|
2355
|
-
* (`toCallee` for the caller, `toCaller` for the callee). A received
|
|
2356
|
-
* ping is answered with a pong in that same direction, echoing the
|
|
2357
|
-
* ping's nonce; a received pong resolves the matching outstanding
|
|
2358
|
-
* {@link ping} probe.
|
|
2359
|
-
*/
|
|
2360
|
-
private _makePinger;
|
|
2034
|
+
get capabilities(): readonly SignedCapability[];
|
|
2361
2035
|
/**
|
|
2362
|
-
*
|
|
2363
|
-
*
|
|
2364
|
-
*
|
|
2365
|
-
* reach it via {@link IncomingStream.send}.
|
|
2036
|
+
* A {@link CapProvider} reflecting the bag at call-time. Assign it to
|
|
2037
|
+
* `HubClientHandle.signing.capProvider` or pass it through
|
|
2038
|
+
* `SigningSenderConfig.capProvider`.
|
|
2366
2039
|
*/
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
private
|
|
2373
|
-
private
|
|
2374
|
-
private _observeInbound;
|
|
2375
|
-
private _observeOutbound;
|
|
2376
|
-
private _observeSendFailure;
|
|
2377
|
-
}
|
|
2378
|
-
//#endregion
|
|
2379
|
-
//#region src/connection/requestTimeout.d.ts
|
|
2380
|
-
declare const DEFAULT_RPC_TIMEOUT_MS = 5000;
|
|
2381
|
-
interface CancellableRequest<T> extends Promise<T> {
|
|
2382
|
-
cancel(reason?: string): void | Promise<void>;
|
|
2383
|
-
dispose?(reason?: string): void;
|
|
2040
|
+
readonly provider: CapProvider;
|
|
2041
|
+
/** Append capabilities and persist (when backed by storage). */
|
|
2042
|
+
add(...caps: readonly SignedCapability[]): Promise<void>;
|
|
2043
|
+
/** Drop all capabilities and persist the empty bag. */
|
|
2044
|
+
clear(): Promise<void>;
|
|
2045
|
+
private _hydrate;
|
|
2046
|
+
private _persist;
|
|
2384
2047
|
}
|
|
2385
|
-
declare function withRpcTimeout<T>(request: CancellableRequest<T>, target: string, timeoutMs?: number): Promise<T>;
|
|
2386
2048
|
//#endregion
|
|
2387
|
-
//#region src/
|
|
2049
|
+
//#region src/identity/principal.d.ts
|
|
2388
2050
|
/**
|
|
2389
|
-
* A
|
|
2390
|
-
*
|
|
2391
|
-
* {@link
|
|
2392
|
-
*
|
|
2393
|
-
*
|
|
2394
|
-
* Supported schemes:
|
|
2395
|
-
* - `unix:/path/to.sock?token=…` → {@link SocketEndpoint}
|
|
2396
|
-
* - `npipe://./pipe/name?token=…` → {@link SocketEndpoint} (Windows)
|
|
2397
|
-
* - `ws://host:port?token=…` / `wss:…` → {@link WsEndpoint} (LinkRPC handshake)
|
|
2398
|
-
* - `ws-no-init://host:port?…` → {@link WsNoInitEndpoint}
|
|
2399
|
-
* - `cmd-stdio:?command=…` / `…?argv=…` → {@link CmdStdioEndpoint}
|
|
2400
|
-
* - `cmd:?command=…` / `…?argv=…` → {@link CmdEnvEndpoint}
|
|
2051
|
+
* A signing identity bundled with its durable capability set. The
|
|
2052
|
+
* {@link SigningIdentity} is fixed for the life of the principal; the
|
|
2053
|
+
* {@link CapBag} is mutable and extensible — caps accumulate as the peer grants
|
|
2054
|
+
* them.
|
|
2401
2055
|
*
|
|
2402
|
-
*
|
|
2403
|
-
*
|
|
2404
|
-
* - `?argv=node&argv=server.js` — repeated `argv` params, structure-preserving.
|
|
2056
|
+
* Transient, per-call (one-shot) grants are deliberately NOT part of a
|
|
2057
|
+
* principal: that is a separate policy, see `OneShotCapStaging`.
|
|
2405
2058
|
*
|
|
2406
|
-
*
|
|
2407
|
-
* `
|
|
2059
|
+
* Lives in its own module (rather than alongside `SigningSender`) so the
|
|
2060
|
+
* `SigningSender` ⇄ `createManagedPrincipal` factory cycle does not run through
|
|
2061
|
+
* a top-level `class … extends Principal`: such a cycle would hit a TDZ
|
|
2062
|
+
* ("Class extends value undefined") depending on module evaluation order.
|
|
2408
2063
|
*/
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
readonly
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
/** Named pipe / unix-domain-socket the server already listens on. */
|
|
2416
|
-
interface SocketEndpoint {
|
|
2417
|
-
readonly kind: 'socket';
|
|
2418
|
-
readonly path: string;
|
|
2419
|
-
readonly token?: string;
|
|
2420
|
-
/**
|
|
2421
|
-
* Present on sockets created by `hub connect`. Local framing still uses the
|
|
2422
|
-
* LinkRPC transport handshake; this describes whether forwarded application
|
|
2423
|
-
* calls target a LinkRPC or plain JSON-RPC peer.
|
|
2424
|
-
*/
|
|
2425
|
-
readonly brokerMode?: 'linkrpc' | 'raw';
|
|
2426
|
-
}
|
|
2427
|
-
/** A running WebSocket hub; `token` rides in the `hubrpc::initialize` handshake. */
|
|
2428
|
-
interface WsEndpoint {
|
|
2429
|
-
readonly kind: 'ws';
|
|
2430
|
-
readonly url: string;
|
|
2431
|
-
readonly token?: string;
|
|
2064
|
+
declare class Principal {
|
|
2065
|
+
readonly identity: SigningIdentity;
|
|
2066
|
+
readonly capBag: CapBag;
|
|
2067
|
+
static create(identity: SigningIdentity, capabilities?: readonly SignedCapability[]): Promise<Principal>;
|
|
2068
|
+
constructor(identity: SigningIdentity, capBag: CapBag);
|
|
2069
|
+
get id(): PrincipalId;
|
|
2432
2070
|
}
|
|
2071
|
+
//#endregion
|
|
2072
|
+
//#region src/identity/managedPrincipal.d.ts
|
|
2433
2073
|
/**
|
|
2434
|
-
* A
|
|
2435
|
-
*
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2074
|
+
* A {@link Principal} that also exposes the executor-backed per-identity
|
|
2075
|
+
* {@link ManagedIdentityStorage}. Returned by {@link createManagedPrincipal}
|
|
2076
|
+
* so callers can persist their own app state (e.g. a resolved serviceId)
|
|
2077
|
+
* alongside the granted capabilities, using the very same durable store the
|
|
2078
|
+
* {@link CapBag} hydrates from — no second storage wiring required.
|
|
2438
2079
|
*/
|
|
2439
|
-
|
|
2440
|
-
readonly
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
}
|
|
2444
|
-
/** Spawn a child and talk linkrpc over its stdin/stdout. */
|
|
2445
|
-
interface CmdStdioEndpoint {
|
|
2446
|
-
readonly kind: 'cmd-stdio';
|
|
2447
|
-
readonly command: EndpointCommand;
|
|
2448
|
-
/** Extra environment variables injected into the spawned child. */
|
|
2449
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
2450
|
-
/** Working directory for the spawned child. */
|
|
2451
|
-
readonly cwd?: string;
|
|
2080
|
+
declare class PrincipalWithStore extends Principal {
|
|
2081
|
+
readonly store: ManagedIdentityStorage;
|
|
2082
|
+
readonly identity: Identity;
|
|
2083
|
+
constructor(identity: Identity, capBag: CapBag, store: ManagedIdentityStorage);
|
|
2452
2084
|
}
|
|
2453
2085
|
/**
|
|
2454
|
-
*
|
|
2455
|
-
*
|
|
2456
|
-
* `
|
|
2457
|
-
*
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2086
|
+
* Executor-managed principal: the peer signs for us through its
|
|
2087
|
+
* `identity::sign` overlay (we never hold a private key). Bootstrapped purely
|
|
2088
|
+
* from the outbound `sender` — no side effects on any connection — and caps
|
|
2089
|
+
* persist in the executor-backed per-identity storage. Works over any
|
|
2090
|
+
* transport whose peer serves the identity overlay (hub *or* stdio).
|
|
2091
|
+
*
|
|
2092
|
+
* Call this exactly once per channel: it performs the `identity::*` handshake
|
|
2093
|
+
* and hydrates the {@link CapBag} from storage. The returned
|
|
2094
|
+
* {@link PrincipalWithStore} additionally surfaces that same durable
|
|
2095
|
+
* {@link ManagedIdentityStorage} as `store`.
|
|
2096
|
+
*/
|
|
2097
|
+
declare function createManagedPrincipal(sender: IRequestSender<unknown>): Promise<PrincipalWithStore>;
|
|
2098
|
+
//#endregion
|
|
2099
|
+
//#region src/identity/signingSender.d.ts
|
|
2100
|
+
/**
|
|
2101
|
+
* Per-outbound-call hook. Sees every signed call this sender makes,
|
|
2102
|
+
* and gets a chance to:
|
|
2103
|
+
* - attach capabilities (the common case),
|
|
2104
|
+
* - override `method` / `params` / `interfaceHash` (rewriting,
|
|
2105
|
+
* auditing, schema-pinning),
|
|
2106
|
+
* - advance `signedAtMs` (e.g. after a slow consent prompt that needs
|
|
2107
|
+
* to issue a cap bound to a fresher timestamp than the sender's
|
|
2108
|
+
* initial wall-clock).
|
|
2109
|
+
*
|
|
2110
|
+
* `signer` and `nonce` are NOT overridable. `signer` is the call's
|
|
2111
|
+
* identity; `nonce` ties any cap to this specific call attempt and must
|
|
2112
|
+
* not drift between the cap-issuance request and the call itself.
|
|
2113
|
+
*/
|
|
2114
|
+
type CapProvider = (req: {
|
|
2115
|
+
readonly method: string;
|
|
2116
|
+
readonly params: JsonValue | undefined;
|
|
2117
|
+
readonly signer: PrincipalId;
|
|
2118
|
+
readonly nonce: string;
|
|
2119
|
+
readonly signedAtMs: number;
|
|
2120
|
+
readonly interfaceHash?: string;
|
|
2121
|
+
}) => Promise<CapProviderResult>;
|
|
2122
|
+
interface CapProviderResult {
|
|
2123
|
+
readonly capabilities?: readonly SignedCapability[];
|
|
2124
|
+
/** Override the wire method this sender signs. Default: the original. */
|
|
2125
|
+
readonly method?: string;
|
|
2126
|
+
/** Override the params this sender signs. Default: the original. */
|
|
2127
|
+
readonly params?: JsonValue;
|
|
2128
|
+
/** Override the interfaceHash baked into the signed envelope. */
|
|
2129
|
+
readonly interfaceHash?: string;
|
|
2130
|
+
/** Advance the Unix-ms timestamp baked into the signed envelope. */
|
|
2131
|
+
readonly signedAtMs?: number;
|
|
2132
|
+
}
|
|
2133
|
+
/**
|
|
2134
|
+
* Per-call ctx the {@link SigningSender} consumes. All fields are
|
|
2135
|
+
* optional; the sender's persistent {@link SigningSenderConfig.principal} is
|
|
2136
|
+
* the default.
|
|
2137
|
+
*
|
|
2138
|
+
* To install a signer after the sender is already constructed (e.g. a
|
|
2139
|
+
* managed-identity bootstrap), mutate the caller-owned config object — it is
|
|
2140
|
+
* read fresh on every call. No setter on the sender itself.
|
|
2141
|
+
*/
|
|
2142
|
+
interface SigningCallCtx {
|
|
2143
|
+
/**
|
|
2144
|
+
* Override the signer for this call only. Pass `null` to skip
|
|
2145
|
+
* signing entirely (plain unsigned JSON-RPC). Bootstrap flows that
|
|
2146
|
+
* must talk to `identity::*` before a managed signer is available
|
|
2147
|
+
* use `signerOverride: null` for those calls.
|
|
2466
2148
|
*/
|
|
2467
|
-
readonly
|
|
2468
|
-
/**
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2149
|
+
readonly signerOverride?: SigningIdentity | null;
|
|
2150
|
+
/**
|
|
2151
|
+
* Replace whatever caps the persistent cap provider would attach.
|
|
2152
|
+
* Skips the persistent provider for this call.
|
|
2153
|
+
*/
|
|
2154
|
+
readonly capsOverride?: readonly SignedCapability[];
|
|
2155
|
+
/**
|
|
2156
|
+
* Reserved for the perm-denied / consent retry path. Currently a
|
|
2157
|
+
* passthrough — sender does not act on it yet.
|
|
2158
|
+
*/
|
|
2159
|
+
readonly requestPermissionWhenDenied?: boolean;
|
|
2472
2160
|
}
|
|
2473
|
-
type ResolvedEndpoint = SocketEndpoint | WsEndpoint | WsNoInitEndpoint | CmdStdioEndpoint | CmdEnvEndpoint;
|
|
2474
2161
|
/**
|
|
2475
|
-
*
|
|
2476
|
-
*
|
|
2477
|
-
* is
|
|
2162
|
+
* Persistent config for a {@link SigningSender}.
|
|
2163
|
+
*
|
|
2164
|
+
* `principal` is the call identity plus its durable, extensible capability
|
|
2165
|
+
* set. `oneShotCaps` is an optional side-policy that may stage a single-use
|
|
2166
|
+
* capability onto the very next call without touching the principal. Both
|
|
2167
|
+
* fields are read fresh on every call, so callers may install or swap them
|
|
2168
|
+
* after the sender has been constructed.
|
|
2169
|
+
*
|
|
2170
|
+
* A missing `principal` means "no signing / no caps" for that call, unless
|
|
2171
|
+
* overridden via {@link SigningCallCtx}.
|
|
2478
2172
|
*/
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2173
|
+
interface SigningSenderConfig {
|
|
2174
|
+
/** Identity + persistent (extensible) capabilities. */
|
|
2175
|
+
readonly principal?: Principal;
|
|
2176
|
+
/**
|
|
2177
|
+
* Optional per-call capability provider. Runs at sign-time with the
|
|
2178
|
+
* concrete method/params/nonce/timestamp and may return caps and/or
|
|
2179
|
+
* signing overrides.
|
|
2180
|
+
*/
|
|
2181
|
+
readonly capProvider?: CapProvider;
|
|
2182
|
+
/**
|
|
2183
|
+
* Optional one-shot capability staging policy. Independent of the
|
|
2184
|
+
* principal; drained per outbound signed call.
|
|
2185
|
+
*/
|
|
2186
|
+
readonly oneShotCaps?: OneShotCapStaging;
|
|
2483
2187
|
}
|
|
2484
2188
|
/**
|
|
2485
|
-
*
|
|
2486
|
-
*
|
|
2487
|
-
*
|
|
2189
|
+
* Side-policy for staging *one-shot* capabilities onto the next outbound
|
|
2190
|
+
* signed call, independent of any {@link Principal}. The {@link SigningSender}
|
|
2191
|
+
* drains the staged caps after attaching them once, so a spent cap never
|
|
2192
|
+
* leaks into a later call.
|
|
2193
|
+
*
|
|
2194
|
+
* Requesting the one-shot grant (prompting the user / hub) lives next to —
|
|
2195
|
+
* not inside — the principal: the principal owns identity and durable
|
|
2196
|
+
* capabilities; this owns the transient per-call grant.
|
|
2488
2197
|
*/
|
|
2489
|
-
declare
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
readonly
|
|
2198
|
+
declare class OneShotCapStaging {
|
|
2199
|
+
private _staged;
|
|
2200
|
+
/** Stage caps for the next signed call. Replaces any still-pending caps. */
|
|
2201
|
+
stage(caps: readonly SignedCapability[]): void;
|
|
2202
|
+
/**
|
|
2203
|
+
* Take (and clear) the staged caps. Called by {@link SigningSender} once
|
|
2204
|
+
* per outbound signed call.
|
|
2205
|
+
*/
|
|
2206
|
+
take(): readonly SignedCapability[];
|
|
2498
2207
|
}
|
|
2499
2208
|
/**
|
|
2500
|
-
*
|
|
2501
|
-
* and
|
|
2502
|
-
*
|
|
2503
|
-
*
|
|
2209
|
+
* Outbound sender decorator that wraps every call in a `$hubrpc` signed
|
|
2210
|
+
* envelope and (optionally) attaches capabilities. Stateless w.r.t. signing
|
|
2211
|
+
* config — the {@link Principal} and {@link OneShotCapStaging} are resolved
|
|
2212
|
+
* per-call from {@link SigningSenderConfig}, so the caller can install or
|
|
2213
|
+
* swap them after construction by mutating that object.
|
|
2504
2214
|
*/
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2215
|
+
/**
|
|
2216
|
+
* The result of {@link SigningSender.fromChannelWithManagedPrincipal} /
|
|
2217
|
+
* {@link SigningSender.fromTransportWithManagedPrincipal}: a signing
|
|
2218
|
+
* {@link Channel} ready for `LinkRpcConnection`, plus the executor-managed
|
|
2219
|
+
* {@link PrincipalWithStore} that drives it (caps, per-identity storage, nodeId).
|
|
2220
|
+
*/
|
|
2221
|
+
interface ManagedSigningChannel<TInCtx = undefined> {
|
|
2222
|
+
readonly channel: Channel<TInCtx, SigningCallCtx>;
|
|
2223
|
+
readonly principal: PrincipalWithStore;
|
|
2510
2224
|
}
|
|
2511
|
-
|
|
2512
|
-
readonly
|
|
2513
|
-
|
|
2225
|
+
declare class SigningSender<TInCtx = unknown> implements IRequestSender<SigningCallCtx> {
|
|
2226
|
+
private readonly _inner;
|
|
2227
|
+
private readonly _config;
|
|
2228
|
+
/**
|
|
2229
|
+
* Wrap an inner channel with signing. Composes via {@link Channel.withSender}
|
|
2230
|
+
* so the resulting `Channel<TInCtx, SigningCallCtx>` plugs into
|
|
2231
|
+
* `LinkRpcConnection`.
|
|
2232
|
+
*/
|
|
2233
|
+
static wrapChannel<TInCtx>(inner: Channel<TInCtx, unknown>, config: SigningSenderConfig): Channel<TInCtx, SigningCallCtx>;
|
|
2234
|
+
/**
|
|
2235
|
+
* Bootstrap an executor-managed {@link Principal} over the **unsigned**
|
|
2236
|
+
* `channel`, then wrap that same channel with signing driven by it.
|
|
2237
|
+
*
|
|
2238
|
+
* Crucially, the `identity::*` handshake that mints the managed principal
|
|
2239
|
+
* rides the *raw* channel (`channel.sender`), so those bootstrap calls are
|
|
2240
|
+
* themselves never signed — there is no "sign the sign call" recursion and
|
|
2241
|
+
* no reliance on threading `signerOverride: null` through every transport
|
|
2242
|
+
* layer. The returned signing {@link Channel} is what callers hand to
|
|
2243
|
+
* `LinkRpcConnection`; the {@link PrincipalWithStore} is returned alongside
|
|
2244
|
+
* for caps / per-identity storage / nodeId.
|
|
2245
|
+
*/
|
|
2246
|
+
static fromChannelWithManagedPrincipal<TInCtx>(channel: Channel<TInCtx, unknown>, config?: Omit<SigningSenderConfig, 'principal'>): Promise<ManagedSigningChannel<TInCtx>>;
|
|
2247
|
+
/**
|
|
2248
|
+
* Convenience over {@link fromChannelWithManagedPrincipal}: build the
|
|
2249
|
+
* unsigned {@link JsonRpcChannel} from `transport` first. The common entry
|
|
2250
|
+
* point for app hosts / services that own a raw {@link IMessageTransport}.
|
|
2251
|
+
*/
|
|
2252
|
+
static fromTransportWithManagedPrincipal(transport: IMessageTransport, config?: Omit<SigningSenderConfig, 'principal'>): Promise<ManagedSigningChannel<undefined>>;
|
|
2253
|
+
constructor(_inner: IRequestSender<unknown>, _config: SigningSenderConfig);
|
|
2254
|
+
sendRequest(method: string, params: JsonValue | undefined, opts?: SendOpts<SigningCallCtx>): Promise<JsonValue>;
|
|
2255
|
+
sendNotification(method: string, params: JsonValue | undefined, opts?: SendOpts<SigningCallCtx>): Promise<void>;
|
|
2256
|
+
sendRequestWithStream(method: string, params: JsonValue | undefined, opts?: StreamSendOpts<SigningCallCtx>): RawStreamingCall;
|
|
2257
|
+
close(): void;
|
|
2258
|
+
private _prepareOutbound;
|
|
2259
|
+
private _resolveSigner;
|
|
2260
|
+
private _createSigningCoordinates;
|
|
2261
|
+
private _resolveIntentAndCapabilities;
|
|
2262
|
+
private _signPreparedCall;
|
|
2514
2263
|
}
|
|
2264
|
+
//#endregion
|
|
2265
|
+
//#region src/hub/common/directoryWalk.d.ts
|
|
2515
2266
|
/**
|
|
2516
|
-
*
|
|
2517
|
-
*
|
|
2518
|
-
*
|
|
2267
|
+
* Portable reflection walk over the `hubrpc.directory` referral tree.
|
|
2268
|
+
*
|
|
2269
|
+
* A directory may explicitly list other `hubrpc.directory` services as
|
|
2270
|
+
* referrals. Flattening that graph into an interface inventory is the
|
|
2271
|
+
* consumer's job. Routing state is deliberately not part of this contract.
|
|
2519
2272
|
*/
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2273
|
+
/**
|
|
2274
|
+
* The sender reflection helpers speak over: the signing decorator that wraps
|
|
2275
|
+
* the live channel. Decoupled from the concrete `JsonRpcChannel` so reconnect
|
|
2276
|
+
* can swap the underlying channel transparently.
|
|
2277
|
+
*/
|
|
2278
|
+
type ReflectionChannel = IRequestSender<SigningCallCtx>;
|
|
2279
|
+
interface ServiceListing {
|
|
2280
|
+
readonly serviceId: string;
|
|
2281
|
+
readonly interfaceId: string;
|
|
2282
|
+
readonly hash: string;
|
|
2283
|
+
readonly path?: string;
|
|
2284
|
+
/** Optional non-normative description of the owning service. */
|
|
2285
|
+
readonly serviceDescription?: string;
|
|
2286
|
+
/**
|
|
2287
|
+
* Root node ids required to access the owning service, in CNF. Surfaced by
|
|
2288
|
+
* the directory; {@link walkHubDetailed} additionally folds transitive
|
|
2289
|
+
* requirements from ancestor directories onto descendants.
|
|
2290
|
+
*/
|
|
2291
|
+
readonly rootPrincipalSets?: readonly RootPrincipalSet[];
|
|
2292
|
+
/** Scope carried by a directory referral; omitted means its service-id subtree. */
|
|
2293
|
+
readonly reachableServiceIds?: readonly ServiceIdPattern[];
|
|
2532
2294
|
}
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2295
|
+
/**
|
|
2296
|
+
* A {@link ServiceListing} enriched with the service id of the directory that
|
|
2297
|
+
* reported it. This is provenance only: every listing is asserted reachable by
|
|
2298
|
+
* sending to the endpoint that answered the directory.
|
|
2299
|
+
*/
|
|
2300
|
+
interface DiscoveredListing extends ServiceListing {
|
|
2301
|
+
readonly discoveredFrom: string;
|
|
2536
2302
|
}
|
|
2537
|
-
interface
|
|
2538
|
-
readonly
|
|
2539
|
-
|
|
2540
|
-
|
|
2303
|
+
interface ListOptions {
|
|
2304
|
+
readonly interfaceId?: string;
|
|
2305
|
+
readonly interfaceIdPrefix?: string;
|
|
2306
|
+
readonly serviceId?: string;
|
|
2307
|
+
readonly serviceIdScopes?: readonly ServiceIdPattern[];
|
|
2308
|
+
readonly limit?: number;
|
|
2309
|
+
readonly timeoutMs?: number;
|
|
2310
|
+
/**
|
|
2311
|
+
* When set, send the reflection call to that service via form-3
|
|
2312
|
+
* (`<target>::hubrpc.directory::list`) instead of the implicit root
|
|
2313
|
+
* directory. Used when talking to a hub: the root directory is the hub
|
|
2314
|
+
* itself, but per-service reflection lives on each participant.
|
|
2315
|
+
*/
|
|
2316
|
+
readonly target?: string;
|
|
2541
2317
|
}
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2318
|
+
declare function fetchDirectory(channel: ReflectionChannel, opts?: ListOptions): Promise<ServiceListing[]>;
|
|
2319
|
+
declare function fetchSchema(channel: ReflectionChannel, interfaceId: string, hash: string | undefined,
|
|
2320
|
+
/**
|
|
2321
|
+
* Optional routing target. When set, the schema request is addressed to
|
|
2322
|
+
* `<target>::hubrpc.schemas::get` (form-3) so it reaches the service that
|
|
2323
|
+
* actually hosts this interface — needed when talking to a hub and the
|
|
2324
|
+
* interface lives behind a participant.
|
|
2325
|
+
*/
|
|
2326
|
+
target?: string): Promise<LinkRpcInterfaceSchema>;
|
|
2327
|
+
declare function findMethodInSchema(schema: LinkRpcInterfaceSchema, methodName: string): MethodSchema | undefined;
|
|
2328
|
+
/** Default recursion depth when walking the bus. */
|
|
2329
|
+
declare const DEFAULT_WALK_DEPTH = 5;
|
|
2330
|
+
/** Segment-aware service-id pattern matching (`foo` includes `foo/bar`, not `foobar`). */
|
|
2331
|
+
declare function serviceIdMatchesPattern(serviceId: string, pattern: ServiceIdPattern): boolean;
|
|
2332
|
+
/** Whether a service id is included by a union of patterns. `undefined` means unfiltered. */
|
|
2333
|
+
declare function serviceIdMatchesScopes(serviceId: string, scopes: readonly ServiceIdPattern[] | undefined): boolean;
|
|
2334
|
+
/** Canonicalize a pattern union by removing duplicates and contained patterns. */
|
|
2335
|
+
declare function normalizeServiceIdScopes(scopes: readonly ServiceIdPattern[]): ServiceIdPattern[];
|
|
2336
|
+
/** Pairwise intersection of two pattern unions. */
|
|
2337
|
+
declare function intersectServiceIdScopes(left: readonly ServiceIdPattern[], right: readonly ServiceIdPattern[]): ServiceIdPattern[];
|
|
2338
|
+
/**
|
|
2339
|
+
* A sub-directory the walk surfaced but could not enumerate — typically because
|
|
2340
|
+
* it is capability-gated (e.g. the `hub` directory, reachable only once the
|
|
2341
|
+
* connection holds a capability for it). The services it would have listed are
|
|
2342
|
+
* therefore absent from the walk; callers can surface `reason` to explain the
|
|
2343
|
+
* gap rather than silently dropping the branch.
|
|
2344
|
+
*/
|
|
2345
|
+
interface InaccessibleDirectory {
|
|
2346
|
+
/** The directory target (serviceId) that could not be enumerated. */
|
|
2347
|
+
readonly serviceId: string;
|
|
2348
|
+
/** The error message from the denied directory lookup. */
|
|
2349
|
+
readonly reason: string;
|
|
2350
|
+
}
|
|
2351
|
+
interface WalkHubResult {
|
|
2352
|
+
/** Every interface reachable from the directories the walk could read. */
|
|
2353
|
+
readonly listings: DiscoveredListing[];
|
|
2354
|
+
/**
|
|
2355
|
+
* Sub-directories that were referenced but could not be enumerated (e.g.
|
|
2356
|
+
* capability-gated). Their services are not present in `listings`.
|
|
2357
|
+
*/
|
|
2358
|
+
readonly inaccessible: InaccessibleDirectory[];
|
|
2547
2359
|
}
|
|
2548
2360
|
/**
|
|
2549
|
-
*
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2552
|
-
*
|
|
2553
|
-
*
|
|
2361
|
+
* Recursive graph walk: list a directory, intersect the accumulated service-id
|
|
2362
|
+
* scope with every explicit `hubrpc.directory` referral, and recurse. Bounded
|
|
2363
|
+
* by `maxDepth`.
|
|
2364
|
+
*
|
|
2365
|
+
* Every listing is tagged with `discoveredFrom` — the serviceId of the
|
|
2366
|
+
* directory that produced it. When the same `(serviceId, interfaceId, hash)`
|
|
2367
|
+
* shows up via several directories (e.g. once forwarded by the hub, once
|
|
2368
|
+
* directly from the participant), we keep the one whose `discoveredFrom`
|
|
2369
|
+
* matches the item's `serviceId`, since that's the directory that
|
|
2370
|
+
* authoritatively knows about it.
|
|
2371
|
+
*
|
|
2372
|
+
* Transitive root-node-id requirements flow down the tree: when the walk
|
|
2373
|
+
* recurses into a directory whose own `rootPrincipalSets` include `transitive`
|
|
2374
|
+
* reqs, every interface discovered at or below that directory inherits them (as
|
|
2375
|
+
* singleton AND-sets, kept transitive so they keep flowing further down). This
|
|
2376
|
+
* replaces the hub-side `applyTransitiveReqs` fold that the v1 aggregating
|
|
2377
|
+
* directory performed.
|
|
2378
|
+
*
|
|
2379
|
+
* A sub-directory the walk cannot read is recorded in
|
|
2380
|
+
* {@link WalkHubResult.inaccessible} rather than silently dropped. A failure to
|
|
2381
|
+
* read the *root* directory is left silent — there is no sub-tree to explain —
|
|
2382
|
+
* and simply yields empty results.
|
|
2383
|
+
*
|
|
2384
|
+
* When {@link WalkHubOptions.unlockGatedDirectory} is supplied, each gated
|
|
2385
|
+
* sub-directory is offered to the hook; if it returns `true` (a capability was
|
|
2386
|
+
* granted), that directory is re-queued and the walk continues into it — a
|
|
2387
|
+
* fixpoint that keeps unlocking newly-revealed gated branches until nothing
|
|
2388
|
+
* more can be opened (still bounded by `maxDepth`).
|
|
2389
|
+
*/
|
|
2390
|
+
interface WalkHubOptions {
|
|
2391
|
+
readonly maxDepth?: number;
|
|
2392
|
+
/** Hard deadline for each directory page request. Defaults to 5 seconds. */
|
|
2393
|
+
readonly timeoutMs?: number;
|
|
2394
|
+
/** Return only listings for this exact interface id after traversing directories. */
|
|
2395
|
+
readonly interfaceId?: string;
|
|
2396
|
+
/** Return only listings whose interface id starts with this prefix after traversal. */
|
|
2397
|
+
readonly interfaceIdPrefix?: string;
|
|
2398
|
+
/** Return only listings for this exact service id after traversal. */
|
|
2399
|
+
readonly serviceId?: string;
|
|
2400
|
+
/** Initial service-id scope. Defaults to the universal `{ prefix: "" }`. */
|
|
2401
|
+
readonly serviceIdScopes?: readonly ServiceIdPattern[];
|
|
2402
|
+
/**
|
|
2403
|
+
* The directory the walk starts from. Defaults to the implicit root
|
|
2404
|
+
* directory (form-2 `hubrpc.directory::list`). Pass a serviceId to start at
|
|
2405
|
+
* `<rootTarget>::hubrpc.directory::list` — e.g. the hub's own global
|
|
2406
|
+
* directory (`'hub'`) when walking from the hub's in-process connection.
|
|
2407
|
+
*/
|
|
2408
|
+
readonly rootTarget?: string;
|
|
2409
|
+
/**
|
|
2410
|
+
* Invoked once per gated sub-directory the walk encounters. Return `true`
|
|
2411
|
+
* if a capability for its `hubrpc.directory::list` was granted and the
|
|
2412
|
+
* directory should be re-listed; `false` (or omitted hook) leaves it in
|
|
2413
|
+
* {@link WalkHubResult.inaccessible}. Called at most once per `serviceId`.
|
|
2414
|
+
*/
|
|
2415
|
+
unlockGatedDirectory?: (serviceId: string) => Promise<boolean>;
|
|
2416
|
+
/** Optional diagnostic sink for inaccessible lists and ended watches. */
|
|
2417
|
+
readonly log?: (message: string) => void;
|
|
2418
|
+
}
|
|
2419
|
+
declare function walkHubDetailed(channel: ReflectionChannel, opts?: WalkHubOptions): Promise<WalkHubResult>;
|
|
2420
|
+
/**
|
|
2421
|
+
* Backward-compatible wrapper over {@link walkHubDetailed} that returns only the
|
|
2422
|
+
* reachable listings, dropping the inaccessible-directory report.
|
|
2423
|
+
*/
|
|
2424
|
+
declare function walkHub(channel: ReflectionChannel, opts?: WalkHubOptions): Promise<DiscoveredListing[]>;
|
|
2425
|
+
interface HubDirectoryChange {
|
|
2426
|
+
/** Directory that emitted the tick. `undefined` denotes the connection root. */
|
|
2427
|
+
readonly target: string | undefined;
|
|
2428
|
+
readonly result: WalkHubResult;
|
|
2429
|
+
}
|
|
2430
|
+
type HubDirectoryGraphTarget = {
|
|
2431
|
+
readonly kind: 'root';
|
|
2432
|
+
readonly serviceId?: string;
|
|
2433
|
+
} | {
|
|
2434
|
+
readonly kind: 'addressed';
|
|
2435
|
+
readonly serviceId: string;
|
|
2436
|
+
};
|
|
2437
|
+
type HubDirectoryNodeState = 'unexplored' | 'loading' | 'loaded' | 'inaccessible';
|
|
2438
|
+
interface HubDirectoryParentReport {
|
|
2439
|
+
readonly target: HubDirectoryGraphTarget;
|
|
2440
|
+
readonly scopes: readonly ServiceIdPattern[];
|
|
2441
|
+
/** Resulting depth for this incoming parent path. */
|
|
2442
|
+
readonly depth: number;
|
|
2443
|
+
}
|
|
2444
|
+
/** Stable public report for one native directory response. */
|
|
2445
|
+
interface HubDirectoryNodeReport {
|
|
2446
|
+
readonly target: HubDirectoryGraphTarget;
|
|
2447
|
+
readonly state: HubDirectoryNodeState;
|
|
2448
|
+
readonly effectiveScopes: readonly ServiceIdPattern[];
|
|
2449
|
+
readonly depth: number;
|
|
2450
|
+
readonly parents: readonly HubDirectoryParentReport[];
|
|
2451
|
+
/** Per-directory listings, normalized to `ServiceListing`, before inherited metadata is folded. */
|
|
2452
|
+
readonly nativeListings: readonly ServiceListing[];
|
|
2453
|
+
readonly inaccessibleReason?: string;
|
|
2454
|
+
readonly watching: boolean;
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Complete point-in-time graph document. `root` exists from construction in
|
|
2458
|
+
* the `unexplored` state, so consumers can render before exploration starts.
|
|
2459
|
+
*/
|
|
2460
|
+
interface HubDirectoryGraphSnapshot {
|
|
2461
|
+
readonly revision: number;
|
|
2462
|
+
readonly complete: boolean;
|
|
2463
|
+
readonly root: HubDirectoryNodeReport;
|
|
2464
|
+
readonly directories: readonly HubDirectoryNodeReport[];
|
|
2465
|
+
readonly result: WalkHubResult;
|
|
2466
|
+
}
|
|
2467
|
+
type HubDirectoryGraphEvent = {
|
|
2468
|
+
readonly type: 'snapshot';
|
|
2469
|
+
readonly reason: 'subscribed' | 'reconciliation-started' | 'reset';
|
|
2470
|
+
readonly snapshot: HubDirectoryGraphSnapshot;
|
|
2471
|
+
} | {
|
|
2472
|
+
readonly type: 'node-added';
|
|
2473
|
+
readonly reason: 'referral';
|
|
2474
|
+
readonly node: HubDirectoryNodeReport;
|
|
2475
|
+
readonly snapshot: HubDirectoryGraphSnapshot;
|
|
2476
|
+
} | {
|
|
2477
|
+
readonly type: 'node-updated';
|
|
2478
|
+
readonly reason: 'loading' | 'loaded' | 'inaccessible' | 'referral' | 'watch-started' | 'watch-stopped' | 'watch-ended' | 'reset';
|
|
2479
|
+
readonly previous: HubDirectoryNodeReport;
|
|
2480
|
+
readonly node: HubDirectoryNodeReport;
|
|
2481
|
+
readonly snapshot: HubDirectoryGraphSnapshot;
|
|
2482
|
+
} | {
|
|
2483
|
+
readonly type: 'node-removed';
|
|
2484
|
+
readonly reason: 'unreachable' | 'reset';
|
|
2485
|
+
readonly previous: HubDirectoryNodeReport;
|
|
2486
|
+
readonly snapshot: HubDirectoryGraphSnapshot;
|
|
2487
|
+
} | {
|
|
2488
|
+
readonly type: 'settled';
|
|
2489
|
+
readonly snapshot: HubDirectoryGraphSnapshot;
|
|
2490
|
+
};
|
|
2491
|
+
/**
|
|
2492
|
+
* Reusable directory graph explorer and watcher.
|
|
2493
|
+
*
|
|
2494
|
+
* The class keeps one native snapshot per directory target. A watch tick
|
|
2495
|
+
* re-lists only its source target; outgoing referral changes then propagate
|
|
2496
|
+
* through affected descendants. Unchanged siblings retain both their snapshot
|
|
2497
|
+
* and watch. Multi-parent targets are queried with the normalized union of all
|
|
2498
|
+
* incoming path scopes.
|
|
2499
|
+
*/
|
|
2500
|
+
declare class HubDirectoryExplorer {
|
|
2501
|
+
private readonly _channel;
|
|
2502
|
+
private readonly _options;
|
|
2503
|
+
private readonly _maxDepth;
|
|
2504
|
+
private readonly _initialScopes;
|
|
2505
|
+
private readonly _nodes;
|
|
2506
|
+
private readonly _unlockAttempted;
|
|
2507
|
+
private readonly _listeners;
|
|
2508
|
+
private readonly _graphListeners;
|
|
2509
|
+
private readonly _pendingTicks;
|
|
2510
|
+
private readonly _watchRetryTimers;
|
|
2511
|
+
private readonly _watchRetryDelays;
|
|
2512
|
+
private _initialized;
|
|
2513
|
+
private _disposed;
|
|
2514
|
+
private _watching;
|
|
2515
|
+
private _complete;
|
|
2516
|
+
private _revision;
|
|
2517
|
+
private _work;
|
|
2518
|
+
private _explorePromise;
|
|
2519
|
+
constructor(_channel: ReflectionChannel, _options?: WalkHubOptions);
|
|
2520
|
+
/** Perform a fresh bounded exploration without starting watches. */
|
|
2521
|
+
explore(): Promise<WalkHubResult>;
|
|
2522
|
+
private _explore;
|
|
2523
|
+
/** Current deduplicated graph snapshot. */
|
|
2524
|
+
get result(): WalkHubResult;
|
|
2525
|
+
/** Current complete-or-progressive directory graph report. */
|
|
2526
|
+
get graphSnapshot(): HubDirectoryGraphSnapshot;
|
|
2527
|
+
/**
|
|
2528
|
+
* Subscribe to progressive graph reports. The listener is registered before
|
|
2529
|
+
* receiving a synchronous current snapshot, avoiding the subscribe/explore
|
|
2530
|
+
* race for both idle and already-running explorers.
|
|
2531
|
+
*/
|
|
2532
|
+
subscribe(listener: (event: HubDirectoryGraphEvent) => void): () => void;
|
|
2533
|
+
/**
|
|
2534
|
+
* Explore once, then watch every reachable directory. Resolves after the
|
|
2535
|
+
* initial graph and watches are established.
|
|
2536
|
+
*/
|
|
2537
|
+
watch(listener: (change: HubDirectoryChange) => void): Promise<() => void>;
|
|
2538
|
+
/** Wait until all currently queued watch reconciliation has settled. */
|
|
2539
|
+
whenIdle(): Promise<void>;
|
|
2540
|
+
dispose(): void;
|
|
2541
|
+
private _loadNode;
|
|
2542
|
+
private _tryUnlock;
|
|
2543
|
+
private _reconcileOutgoing;
|
|
2544
|
+
private _outgoingFor;
|
|
2545
|
+
private _createRootNode;
|
|
2546
|
+
private _createNode;
|
|
2547
|
+
private _updateNodeFromParents;
|
|
2548
|
+
private _deriveNodeFromParents;
|
|
2549
|
+
private _derivedNodeState;
|
|
2550
|
+
/**
|
|
2551
|
+
* Rebuild incoming contributions from the root seed. Starting with no
|
|
2552
|
+
* non-root contributions computes the least fixed point, so a disconnected
|
|
2553
|
+
* or narrowed cycle cannot keep scopes contributed by its previous state.
|
|
2554
|
+
*/
|
|
2555
|
+
private _reconcileScopesFromRoot;
|
|
2556
|
+
private _computeScopeFixedPoint;
|
|
2557
|
+
private _pruneUnreachable;
|
|
2558
|
+
/**
|
|
2559
|
+
* Every changed watch scope uses list/watch/list: callers reach this method
|
|
2560
|
+
* only after a list under the current scope, then the replacement watch is
|
|
2561
|
+
* installed before a verification list. Either the verification sees a
|
|
2562
|
+
* handoff mutation or the new watch ticks for it.
|
|
2563
|
+
*/
|
|
2564
|
+
private _synchronizeWatches;
|
|
2565
|
+
private _replaceWatch;
|
|
2566
|
+
private _queueTick;
|
|
2567
|
+
private _stopWatch;
|
|
2568
|
+
private _stopAllWatches;
|
|
2569
|
+
private _scheduleWatchRetry;
|
|
2570
|
+
private _clearWatchRetry;
|
|
2571
|
+
private _clearNodes;
|
|
2572
|
+
private _resetForExplore;
|
|
2573
|
+
private _updateNode;
|
|
2574
|
+
private _nodeReport;
|
|
2575
|
+
private _targetForKey;
|
|
2576
|
+
private _emitNodeAdded;
|
|
2577
|
+
private _emitNodeUpdated;
|
|
2578
|
+
private _emitNodeRemoved;
|
|
2579
|
+
private _startReconciliation;
|
|
2580
|
+
private _settle;
|
|
2581
|
+
private _emitSnapshot;
|
|
2582
|
+
private _emitGraphEvent;
|
|
2583
|
+
private _deliverGraphEvent;
|
|
2584
|
+
private _nodeKeyForTarget;
|
|
2585
|
+
private _throwIfDisposed;
|
|
2586
|
+
}
|
|
2587
|
+
//#endregion
|
|
2588
|
+
//#region src/schema/exportStaticHubSchema.d.ts
|
|
2589
|
+
interface ExportStaticHubSchemaOptions {
|
|
2590
|
+
/** Directory and default-binding reflection scope; omitted means the connection root. */
|
|
2591
|
+
serviceId?: string;
|
|
2592
|
+
maxDepth?: number;
|
|
2593
|
+
timeoutMs?: number;
|
|
2594
|
+
}
|
|
2595
|
+
/** Export a complete static contract, failing on missing reflection, schemas, or truncated discovery. */
|
|
2596
|
+
declare function exportStaticHubSchema(channel: ReflectionChannel, options?: ExportStaticHubSchemaOptions): Promise<StaticHubSchemaDocument>;
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/inspection/inspection.interfaces.d.ts
|
|
2599
|
+
declare const zTopologyPort: import("zod/mini").ZodMiniObject<{
|
|
2600
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2601
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2602
|
+
}, import("zod/v4/core").$strip>;
|
|
2603
|
+
declare const zParticipantDescriptor: import("zod/mini").ZodMiniObject<{
|
|
2604
|
+
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2605
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2606
|
+
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2607
|
+
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2608
|
+
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2609
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2610
|
+
}, import("zod/v4/core").$strip>;
|
|
2611
|
+
declare const zParticipantDescriptorSource: import("zod/mini").ZodMiniObject<{
|
|
2612
|
+
source: import("zod/mini").ZodMiniEnum<{
|
|
2613
|
+
self: "self";
|
|
2614
|
+
attacher: "attacher";
|
|
2615
|
+
}>;
|
|
2616
|
+
descriptor: import("zod/mini").ZodMiniObject<{
|
|
2617
|
+
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2618
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2619
|
+
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2620
|
+
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2621
|
+
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2622
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2623
|
+
}, import("zod/v4/core").$strip>;
|
|
2624
|
+
}, import("zod/v4/core").$strip>;
|
|
2625
|
+
declare const zTopologyNode: import("zod/mini").ZodMiniObject<{
|
|
2626
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2627
|
+
kind: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
2628
|
+
endpoint: "endpoint";
|
|
2629
|
+
hub: "hub";
|
|
2630
|
+
}>>;
|
|
2631
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2632
|
+
descriptors: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2633
|
+
source: import("zod/mini").ZodMiniEnum<{
|
|
2634
|
+
self: "self";
|
|
2635
|
+
attacher: "attacher";
|
|
2636
|
+
}>;
|
|
2637
|
+
descriptor: import("zod/mini").ZodMiniObject<{
|
|
2638
|
+
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2639
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2640
|
+
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2641
|
+
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2642
|
+
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2643
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2644
|
+
}, import("zod/v4/core").$strip>;
|
|
2645
|
+
}, import("zod/v4/core").$strip>>>;
|
|
2646
|
+
ports: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2647
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2648
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2649
|
+
}, import("zod/v4/core").$strip>>;
|
|
2650
|
+
}, import("zod/v4/core").$strip>;
|
|
2651
|
+
declare const zTopologyLinkEndpoint: import("zod/mini").ZodMiniObject<{
|
|
2652
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2653
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2654
|
+
}, import("zod/v4/core").$strip>;
|
|
2655
|
+
declare const zTopologyTransportEndpoint: import("zod/mini").ZodMiniObject<{
|
|
2656
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2657
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2658
|
+
}, import("zod/v4/core").$strip>;
|
|
2659
|
+
/**
|
|
2660
|
+
* Transport details as observed at a topology link. `local` corresponds to the
|
|
2661
|
+
* link's `from` endpoint and `remote` to its `to` endpoint.
|
|
2662
|
+
*/
|
|
2663
|
+
declare const zTopologyTransportInfo: import("zod/mini").ZodMiniObject<{
|
|
2664
|
+
type: import("zod/mini").ZodMiniString<string>;
|
|
2665
|
+
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2666
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2667
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2668
|
+
}, import("zod/v4/core").$strip>>;
|
|
2669
|
+
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2670
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2671
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2672
|
+
}, import("zod/v4/core").$strip>>;
|
|
2673
|
+
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2674
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2675
|
+
}, import("zod/v4/core").$strip>;
|
|
2676
|
+
declare const zTopologyLink: import("zod/mini").ZodMiniObject<{
|
|
2677
|
+
from: import("zod/mini").ZodMiniObject<{
|
|
2678
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2679
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2680
|
+
}, import("zod/v4/core").$strip>;
|
|
2681
|
+
to: import("zod/mini").ZodMiniObject<{
|
|
2682
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2683
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2684
|
+
}, import("zod/v4/core").$strip>;
|
|
2685
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2686
|
+
peerState: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
2687
|
+
identified: "identified";
|
|
2688
|
+
pending: "pending";
|
|
2689
|
+
unsupported: "unsupported";
|
|
2690
|
+
error: "error";
|
|
2691
|
+
}>>;
|
|
2692
|
+
transport: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2693
|
+
type: import("zod/mini").ZodMiniString<string>;
|
|
2694
|
+
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2695
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2696
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2697
|
+
}, import("zod/v4/core").$strip>>;
|
|
2698
|
+
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2699
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2700
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2701
|
+
}, import("zod/v4/core").$strip>>;
|
|
2702
|
+
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2703
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2704
|
+
}, import("zod/v4/core").$strip>>;
|
|
2705
|
+
}, import("zod/v4/core").$strip>;
|
|
2706
|
+
declare const zRouteClaim: import("zod/mini").ZodMiniObject<{
|
|
2707
|
+
serviceId: import("zod/mini").ZodMiniString<string>;
|
|
2708
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2709
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2710
|
+
match: import("zod/mini").ZodMiniEnum<{
|
|
2711
|
+
exact: "exact";
|
|
2712
|
+
prefix: "prefix";
|
|
2713
|
+
}>;
|
|
2714
|
+
}, import("zod/v4/core").$strip>;
|
|
2715
|
+
declare const zTopologyGraph: import("zod/mini").ZodMiniObject<{
|
|
2716
|
+
observerServiceId: import("zod/mini").ZodMiniString<string>;
|
|
2717
|
+
entryNodeId: import("zod/mini").ZodMiniString<string>;
|
|
2718
|
+
nodes: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2719
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2720
|
+
kind: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
2721
|
+
endpoint: "endpoint";
|
|
2722
|
+
hub: "hub";
|
|
2723
|
+
}>>;
|
|
2724
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2725
|
+
descriptors: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2726
|
+
source: import("zod/mini").ZodMiniEnum<{
|
|
2727
|
+
self: "self";
|
|
2728
|
+
attacher: "attacher";
|
|
2729
|
+
}>;
|
|
2730
|
+
descriptor: import("zod/mini").ZodMiniObject<{
|
|
2731
|
+
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2732
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2733
|
+
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2734
|
+
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2735
|
+
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2736
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2737
|
+
}, import("zod/v4/core").$strip>;
|
|
2738
|
+
}, import("zod/v4/core").$strip>>>;
|
|
2739
|
+
ports: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2740
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2741
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2742
|
+
}, import("zod/v4/core").$strip>>;
|
|
2743
|
+
}, import("zod/v4/core").$strip>>;
|
|
2744
|
+
links: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2745
|
+
from: import("zod/mini").ZodMiniObject<{
|
|
2746
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2747
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2748
|
+
}, import("zod/v4/core").$strip>;
|
|
2749
|
+
to: import("zod/mini").ZodMiniObject<{
|
|
2750
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2751
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2752
|
+
}, import("zod/v4/core").$strip>;
|
|
2753
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2754
|
+
peerState: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniEnum<{
|
|
2755
|
+
identified: "identified";
|
|
2756
|
+
pending: "pending";
|
|
2757
|
+
unsupported: "unsupported";
|
|
2758
|
+
error: "error";
|
|
2759
|
+
}>>;
|
|
2760
|
+
transport: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2761
|
+
type: import("zod/mini").ZodMiniString<string>;
|
|
2762
|
+
local: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2763
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2764
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2765
|
+
}, import("zod/v4/core").$strip>>;
|
|
2766
|
+
remote: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2767
|
+
address: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2768
|
+
port: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
2769
|
+
}, import("zod/v4/core").$strip>>;
|
|
2770
|
+
path: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2771
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
2772
|
+
}, import("zod/v4/core").$strip>>;
|
|
2773
|
+
}, import("zod/v4/core").$strip>>;
|
|
2774
|
+
routes: import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
2775
|
+
serviceId: import("zod/mini").ZodMiniString<string>;
|
|
2776
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2777
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2778
|
+
match: import("zod/mini").ZodMiniEnum<{
|
|
2779
|
+
exact: "exact";
|
|
2780
|
+
prefix: "prefix";
|
|
2781
|
+
}>;
|
|
2782
|
+
}, import("zod/v4/core").$strip>>;
|
|
2783
|
+
}, import("zod/v4/core").$strip>;
|
|
2784
|
+
type TopologyPort = output<typeof zTopologyPort>;
|
|
2785
|
+
type ParticipantDescriptor = output<typeof zParticipantDescriptor>;
|
|
2786
|
+
type ParticipantDescriptorSource = output<typeof zParticipantDescriptorSource>;
|
|
2787
|
+
type TopologyNode = output<typeof zTopologyNode>;
|
|
2788
|
+
type TopologyLinkEndpoint = output<typeof zTopologyLinkEndpoint>;
|
|
2789
|
+
type TopologyTransportEndpoint = output<typeof zTopologyTransportEndpoint>;
|
|
2790
|
+
type TopologyTransportInfo = output<typeof zTopologyTransportInfo>;
|
|
2791
|
+
type TopologyLink = output<typeof zTopologyLink>;
|
|
2792
|
+
type RouteClaim = output<typeof zRouteClaim>;
|
|
2793
|
+
type TopologyGraph = output<typeof zTopologyGraph>;
|
|
2794
|
+
declare const topologyInterface: InterfaceDefinition<{
|
|
2795
|
+
getGraph: RequestType<Record<string, never>, {
|
|
2796
|
+
observerServiceId: string;
|
|
2797
|
+
entryNodeId: string;
|
|
2798
|
+
nodes: {
|
|
2799
|
+
nodeId: string;
|
|
2800
|
+
ports: {
|
|
2801
|
+
portId: string;
|
|
2802
|
+
label?: string | undefined;
|
|
2803
|
+
}[];
|
|
2804
|
+
kind?: "endpoint" | "hub" | undefined;
|
|
2805
|
+
label?: string | undefined;
|
|
2806
|
+
descriptors?: {
|
|
2807
|
+
source: "self" | "attacher";
|
|
2808
|
+
descriptor: {
|
|
2809
|
+
type?: string | undefined;
|
|
2810
|
+
label?: string | undefined;
|
|
2811
|
+
processId?: number | undefined;
|
|
2812
|
+
processType?: string | undefined;
|
|
2813
|
+
nodeStatusServiceId?: string | undefined;
|
|
2814
|
+
metadata?: Record<string, string | number | boolean> | undefined;
|
|
2815
|
+
};
|
|
2816
|
+
}[] | undefined;
|
|
2817
|
+
}[];
|
|
2818
|
+
links: {
|
|
2819
|
+
from: {
|
|
2820
|
+
nodeId: string;
|
|
2821
|
+
portId: string;
|
|
2822
|
+
};
|
|
2823
|
+
to: {
|
|
2824
|
+
nodeId: string;
|
|
2825
|
+
portId: string;
|
|
2826
|
+
};
|
|
2827
|
+
label?: string | undefined;
|
|
2828
|
+
peerState?: "identified" | "pending" | "unsupported" | "error" | undefined;
|
|
2829
|
+
transport?: {
|
|
2830
|
+
type: string;
|
|
2831
|
+
local?: {
|
|
2832
|
+
address?: string | undefined;
|
|
2833
|
+
port?: number | undefined;
|
|
2834
|
+
} | undefined;
|
|
2835
|
+
remote?: {
|
|
2836
|
+
address?: string | undefined;
|
|
2837
|
+
port?: number | undefined;
|
|
2838
|
+
} | undefined;
|
|
2839
|
+
path?: string | undefined;
|
|
2840
|
+
metadata?: Record<string, string | number | boolean> | undefined;
|
|
2841
|
+
} | undefined;
|
|
2842
|
+
}[];
|
|
2843
|
+
routes: {
|
|
2844
|
+
serviceId: string;
|
|
2845
|
+
nodeId: string;
|
|
2846
|
+
portId: string;
|
|
2847
|
+
match: "exact" | "prefix";
|
|
2848
|
+
}[];
|
|
2849
|
+
}, void, NoInfer<Record<string, never>>, never, readonly ApplicationErrorDescriptorBase[], void>;
|
|
2850
|
+
watchGraph: RequestType<Record<string, never>, Record<string, never>, void, never, NoInfer<Record<string, never>>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
2851
|
+
}>;
|
|
2852
|
+
declare const zTrafficTransitEndpoint: import("zod/mini").ZodMiniObject<{
|
|
2853
|
+
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
2854
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2855
|
+
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
2856
|
+
}, import("zod/v4/core").$strip>;
|
|
2857
|
+
declare const zTrafficTransitEvent: import("zod/mini").ZodMiniObject<{
|
|
2858
|
+
type: import("zod/mini").ZodMiniLiteral<"transit">;
|
|
2859
|
+
timeMs: import("zod/mini").ZodMiniNumber<number>;
|
|
2860
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2861
|
+
in: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2862
|
+
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
2863
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2864
|
+
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
2865
|
+
}, import("zod/v4/core").$strip>>;
|
|
2866
|
+
out: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2867
|
+
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
2868
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2869
|
+
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
2870
|
+
}, import("zod/v4/core").$strip>>;
|
|
2871
|
+
disposition: import("zod/mini").ZodMiniEnum<{
|
|
2872
|
+
forwarded: "forwarded";
|
|
2873
|
+
consumed: "consumed";
|
|
2874
|
+
dropped: "dropped";
|
|
2875
|
+
unroutable: "unroutable";
|
|
2876
|
+
}>;
|
|
2877
|
+
kind: import("zod/mini").ZodMiniEnum<{
|
|
2878
|
+
request: "request";
|
|
2879
|
+
notification: "notification";
|
|
2880
|
+
response: "response";
|
|
2881
|
+
stream: "stream";
|
|
2882
|
+
}>;
|
|
2883
|
+
method: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2884
|
+
params: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2885
|
+
result: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2886
|
+
error: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2887
|
+
code: import("zod/mini").ZodMiniNumber<number>;
|
|
2888
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2889
|
+
data: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2890
|
+
}, import("zod/v4/core").$strip>>;
|
|
2891
|
+
}, import("zod/v4/core").$strip>;
|
|
2892
|
+
declare const zTrafficOverflowEvent: import("zod/mini").ZodMiniObject<{
|
|
2893
|
+
type: import("zod/mini").ZodMiniLiteral<"overflow">;
|
|
2894
|
+
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
2895
|
+
}, import("zod/v4/core").$strip>;
|
|
2896
|
+
declare const zTrafficEvent: import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniObject<{
|
|
2897
|
+
type: import("zod/mini").ZodMiniLiteral<"transit">;
|
|
2898
|
+
timeMs: import("zod/mini").ZodMiniNumber<number>;
|
|
2899
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
2900
|
+
in: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2901
|
+
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
2902
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2903
|
+
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
2904
|
+
}, import("zod/v4/core").$strip>>;
|
|
2905
|
+
out: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2906
|
+
edgeId: import("zod/mini").ZodMiniString<string>;
|
|
2907
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
2908
|
+
requestId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniString<string>]>>;
|
|
2909
|
+
}, import("zod/v4/core").$strip>>;
|
|
2910
|
+
disposition: import("zod/mini").ZodMiniEnum<{
|
|
2911
|
+
forwarded: "forwarded";
|
|
2912
|
+
consumed: "consumed";
|
|
2913
|
+
dropped: "dropped";
|
|
2914
|
+
unroutable: "unroutable";
|
|
2915
|
+
}>;
|
|
2916
|
+
kind: import("zod/mini").ZodMiniEnum<{
|
|
2917
|
+
request: "request";
|
|
2918
|
+
notification: "notification";
|
|
2919
|
+
response: "response";
|
|
2920
|
+
stream: "stream";
|
|
2921
|
+
}>;
|
|
2922
|
+
method: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2923
|
+
params: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2924
|
+
result: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2925
|
+
error: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniObject<{
|
|
2926
|
+
code: import("zod/mini").ZodMiniNumber<number>;
|
|
2927
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2928
|
+
data: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniUnknown>;
|
|
2929
|
+
}, import("zod/v4/core").$strip>>;
|
|
2930
|
+
}, import("zod/v4/core").$strip>, import("zod/mini").ZodMiniObject<{
|
|
2931
|
+
type: import("zod/mini").ZodMiniLiteral<"overflow">;
|
|
2932
|
+
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
2933
|
+
}, import("zod/v4/core").$strip>]>;
|
|
2934
|
+
type TrafficTransitEndpoint = output<typeof zTrafficTransitEndpoint>;
|
|
2935
|
+
type TrafficTransitEvent = output<typeof zTrafficTransitEvent>;
|
|
2936
|
+
type TrafficOverflowEvent = output<typeof zTrafficOverflowEvent>;
|
|
2937
|
+
type TrafficEvent = output<typeof zTrafficEvent>;
|
|
2938
|
+
declare const zTrafficWatchResult: import("zod/mini").ZodMiniObject<{
|
|
2939
|
+
delivered: import("zod/mini").ZodMiniNumber<number>;
|
|
2940
|
+
dropped: import("zod/mini").ZodMiniNumber<number>;
|
|
2941
|
+
}, import("zod/v4/core").$strip>;
|
|
2942
|
+
type TrafficWatchResult = output<typeof zTrafficWatchResult>;
|
|
2943
|
+
/**
|
|
2944
|
+
* Observe raw message transits at the node hosting the addressed service.
|
|
2945
|
+
* Consumers may correlate adjacent transits by shared `(portId, requestId)`.
|
|
2554
2946
|
*/
|
|
2555
|
-
declare
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2947
|
+
declare const trafficInterface: InterfaceDefinition<{
|
|
2948
|
+
watch: RequestType<{
|
|
2949
|
+
methodPrefix?: string | undefined;
|
|
2950
|
+
trafficIgnoreKey?: string | undefined;
|
|
2951
|
+
focusRequest?: {
|
|
2952
|
+
portId: string;
|
|
2953
|
+
requestId: string | number;
|
|
2954
|
+
} | undefined;
|
|
2955
|
+
}, {
|
|
2956
|
+
delivered: number;
|
|
2957
|
+
dropped: number;
|
|
2958
|
+
}, void, never, NoInfer<{
|
|
2959
|
+
type: "transit";
|
|
2960
|
+
timeMs: number;
|
|
2961
|
+
nodeId: string;
|
|
2962
|
+
disposition: "forwarded" | "consumed" | "dropped" | "unroutable";
|
|
2963
|
+
kind: "request" | "notification" | "response" | "stream";
|
|
2964
|
+
in?: {
|
|
2965
|
+
edgeId: string;
|
|
2966
|
+
portId: string;
|
|
2967
|
+
requestId?: string | number | undefined;
|
|
2968
|
+
} | undefined;
|
|
2969
|
+
out?: {
|
|
2970
|
+
edgeId: string;
|
|
2971
|
+
portId: string;
|
|
2972
|
+
requestId?: string | number | undefined;
|
|
2973
|
+
} | undefined;
|
|
2974
|
+
method?: string | undefined;
|
|
2975
|
+
params?: unknown;
|
|
2976
|
+
result?: unknown;
|
|
2977
|
+
error?: {
|
|
2978
|
+
code: number;
|
|
2979
|
+
message: string;
|
|
2980
|
+
data?: unknown;
|
|
2981
|
+
} | undefined;
|
|
2982
|
+
} | {
|
|
2983
|
+
type: "overflow";
|
|
2984
|
+
dropped: number;
|
|
2985
|
+
}>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
2986
|
+
watchWithPayloads: RequestType<{
|
|
2987
|
+
maxPayloadBytes: number;
|
|
2988
|
+
methodPrefix?: string | undefined;
|
|
2989
|
+
trafficIgnoreKey?: string | undefined;
|
|
2990
|
+
focusRequest?: {
|
|
2991
|
+
portId: string;
|
|
2992
|
+
requestId: string | number;
|
|
2993
|
+
} | undefined;
|
|
2994
|
+
}, {
|
|
2995
|
+
delivered: number;
|
|
2996
|
+
dropped: number;
|
|
2997
|
+
}, void, never, NoInfer<{
|
|
2998
|
+
type: "transit";
|
|
2999
|
+
timeMs: number;
|
|
3000
|
+
nodeId: string;
|
|
3001
|
+
disposition: "forwarded" | "consumed" | "dropped" | "unroutable";
|
|
3002
|
+
kind: "request" | "notification" | "response" | "stream";
|
|
3003
|
+
in?: {
|
|
3004
|
+
edgeId: string;
|
|
3005
|
+
portId: string;
|
|
3006
|
+
requestId?: string | number | undefined;
|
|
3007
|
+
} | undefined;
|
|
3008
|
+
out?: {
|
|
3009
|
+
edgeId: string;
|
|
3010
|
+
portId: string;
|
|
3011
|
+
requestId?: string | number | undefined;
|
|
3012
|
+
} | undefined;
|
|
3013
|
+
method?: string | undefined;
|
|
3014
|
+
params?: unknown;
|
|
3015
|
+
result?: unknown;
|
|
3016
|
+
error?: {
|
|
3017
|
+
code: number;
|
|
3018
|
+
message: string;
|
|
3019
|
+
data?: unknown;
|
|
3020
|
+
} | undefined;
|
|
3021
|
+
} | {
|
|
3022
|
+
type: "overflow";
|
|
3023
|
+
dropped: number;
|
|
3024
|
+
}>, readonly ApplicationErrorDescriptorBase[], void>;
|
|
3025
|
+
}>;
|
|
2569
3026
|
//#endregion
|
|
2570
|
-
//#region src/
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
* fresh. Use this at the cap-production point to decide whether to re-acquire.
|
|
2591
|
-
*/
|
|
2592
|
-
declare function capBagFreshAt(caps: readonly Capability[], now: number, marginMs?: number): boolean;
|
|
2593
|
-
type PermitResult = {
|
|
2594
|
-
ok: true;
|
|
2595
|
-
capabilityNonce: string;
|
|
2596
|
-
rootIssuer: PrincipalId;
|
|
2597
|
-
} | {
|
|
2598
|
-
ok: false;
|
|
2599
|
-
reason: string;
|
|
2600
|
-
};
|
|
2601
|
-
/**
|
|
2602
|
-
* A trust anchor accepted as a capability-chain root, plus whether it may be
|
|
2603
|
-
* named in authorization error messages.
|
|
2604
|
-
*/
|
|
2605
|
-
interface AcceptedRootIssuer {
|
|
2606
|
-
/** The principal accepted as a chain root for the queried service. */
|
|
2607
|
-
principal: PrincipalId;
|
|
2608
|
-
/**
|
|
2609
|
-
* Whether this issuer may be disclosed in `permits` rejection reasons.
|
|
2610
|
-
* Public anchors (e.g. a hub's well-known admin identity) are surfaced to
|
|
2611
|
-
* help diagnose "wrong root" failures; private ones are withheld so the
|
|
2612
|
-
* error never leaks the set of trusted issuers.
|
|
2613
|
-
*/
|
|
2614
|
-
isPublic: boolean;
|
|
2615
|
-
}
|
|
2616
|
-
/**
|
|
2617
|
-
* **The** authorization predicate. A call is permitted iff some presented
|
|
2618
|
-
* capability (1) addresses the call, (2) has a genuine, well-delegated
|
|
2619
|
-
* chain whose leaf audience is the caller (`call.signer`), and (3) roots
|
|
2620
|
-
* at an issuer the verifier accepts **for the call's service**.
|
|
2621
|
-
*
|
|
2622
|
-
* Pure: it reports the verdict (and the `capabilityNonce` / `rootIssuer`
|
|
2623
|
-
* for audit) but performs no consumption. Replay is the caller's job — the
|
|
2624
|
-
* gate dedups `call.nonce`, so `callBind` grants are single-use for free.
|
|
2625
|
-
*
|
|
2626
|
-
* `acceptedRootIssuers` is consulted with the call's `serviceId` and returns
|
|
2627
|
-
* the accepted {@link AcceptedRootIssuer} anchors; an empty result rejects
|
|
2628
|
-
* every capability (fail closed) — trust is the verifier's, never the
|
|
2629
|
-
* token's. Anchors flagged `isPublic` are named in the rejection reason when
|
|
2630
|
-
* a chain roots at an unaccepted issuer.
|
|
2631
|
-
*/
|
|
2632
|
-
declare function permits(call: Call, capabilities: readonly SignedCapability[], acceptedRootIssuers: (serviceId: string) => readonly AcceptedRootIssuer[], nowMs: number, opts?: {
|
|
2633
|
-
maxDepth?: number;
|
|
2634
|
-
}): Promise<PermitResult>;
|
|
2635
|
-
/**
|
|
2636
|
-
* Sign a `Capability` with a {@link SigningIdentity}. The private key never
|
|
2637
|
-
* leaves the identity. The result verifies via {@link verifyChain}.
|
|
2638
|
-
*/
|
|
2639
|
-
declare function signCapability(capability: Capability, issuer: SigningIdentity): Promise<SignedCapability>;
|
|
2640
|
-
interface IssueCapabilityOptions {
|
|
2641
|
-
/** Identity allowed to present the capability. */
|
|
2642
|
-
readonly audience: PublicSigningIdentity;
|
|
2643
|
-
/** Authority granted to the audience. */
|
|
2644
|
-
readonly permissions: readonly Permission[];
|
|
2645
|
-
/** Optional expiration time as Unix milliseconds. */
|
|
2646
|
-
readonly expiresAtMs?: number;
|
|
2647
|
-
/** Optional parent whose authority this capability narrows. */
|
|
2648
|
-
readonly parent?: SignedCapability;
|
|
2649
|
-
}
|
|
2650
|
-
/**
|
|
2651
|
-
* Issue and sign a capability, deriving its issuer, nonce, and optional parent
|
|
2652
|
-
* hash. The result is plain JSON data and survives a JSON stringify/parse
|
|
2653
|
-
* round-trip without reconstruction.
|
|
2654
|
-
*/
|
|
2655
|
-
declare function issueCapability(issuer: SigningIdentity, options: IssueCapabilityOptions): Promise<SignedCapability>;
|
|
2656
|
-
type ParamMatcherFor<T> = {
|
|
2657
|
-
exact: T;
|
|
2658
|
-
} | {
|
|
2659
|
-
enum: T[];
|
|
2660
|
-
} | {
|
|
2661
|
-
any: true;
|
|
2662
|
-
} | (T extends string ? {
|
|
2663
|
-
prefix: string;
|
|
2664
|
-
} : never) | (T extends readonly string[] ? {
|
|
2665
|
-
subsetOf: string[];
|
|
2666
|
-
} : never);
|
|
2667
|
-
/** Type-safe top-level parameter matchers for one interface member. */
|
|
2668
|
-
type ParamMatchers<T> = T extends Record<string, unknown> ? { [K in keyof T]: ParamMatcherFor<Exclude<T[K], undefined>>; } : never;
|
|
2669
|
-
type RequestMemberName<TMembers extends MemberMap> = { [K in keyof TMembers]: TMembers[K] extends RequestType<any, any, any, any, any, any, any> ? K : never; }[keyof TMembers] & string;
|
|
2670
|
-
type RequestParams<TMember> = TMember extends RequestType<infer TParams, any, any, any, any, any, any> ? TParams : never;
|
|
2671
|
-
/** Match a string parameter by prefix. */
|
|
2672
|
-
declare function prefix(value: string): {
|
|
2673
|
-
prefix: string;
|
|
2674
|
-
};
|
|
3027
|
+
//#region src/inspection/node.interfaces.d.ts
|
|
3028
|
+
declare const zNodeInfo: import("zod/mini").ZodMiniObject<{
|
|
3029
|
+
nodeId: import("zod/mini").ZodMiniString<string>;
|
|
3030
|
+
portId: import("zod/mini").ZodMiniString<string>;
|
|
3031
|
+
descriptors: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniArray<import("zod/mini").ZodMiniObject<{
|
|
3032
|
+
source: import("zod/mini").ZodMiniEnum<{
|
|
3033
|
+
self: "self";
|
|
3034
|
+
attacher: "attacher";
|
|
3035
|
+
}>;
|
|
3036
|
+
descriptor: import("zod/mini").ZodMiniObject<{
|
|
3037
|
+
type: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
3038
|
+
label: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
3039
|
+
processId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
|
|
3040
|
+
processType: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
3041
|
+
nodeStatusServiceId: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
3042
|
+
metadata: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnion<readonly [import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniNumber<number>, import("zod/mini").ZodMiniBoolean<boolean>]>>>;
|
|
3043
|
+
}, import("zod/v4/core").$strip>;
|
|
3044
|
+
}, import("zod/v4/core").$strip>>>;
|
|
3045
|
+
}, import("zod/v4/core").$strip>;
|
|
3046
|
+
type NodeInfo = output<typeof zNodeInfo>;
|
|
2675
3047
|
/**
|
|
2676
|
-
*
|
|
2677
|
-
*
|
|
2678
|
-
*
|
|
3048
|
+
* Generates unique topology-correlation labels, not security identities.
|
|
3049
|
+
* Custom generators must avoid collisions across nodes and ports. Tests can
|
|
3050
|
+
* supply an independent deterministic sequence for each participant.
|
|
2679
3051
|
*/
|
|
2680
|
-
|
|
2681
|
-
//#endregion
|
|
2682
|
-
//#region src/identity/managedIdentity.d.ts
|
|
3052
|
+
type TopologyIdGenerator = (kind: 'node' | 'port') => string;
|
|
2683
3053
|
/**
|
|
2684
|
-
*
|
|
2685
|
-
*
|
|
2686
|
-
* stored.
|
|
3054
|
+
* Minimal root service for aligning the independently observed topologies at
|
|
3055
|
+
* both ends of a connection.
|
|
2687
3056
|
*/
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
3057
|
+
declare const nodeInterface: InterfaceDefinition<{
|
|
3058
|
+
getNodeId: RequestType<Record<string, never>, {
|
|
3059
|
+
nodeId: string;
|
|
3060
|
+
portId: string;
|
|
3061
|
+
descriptors?: {
|
|
3062
|
+
source: "self" | "attacher";
|
|
3063
|
+
descriptor: {
|
|
3064
|
+
type?: string | undefined;
|
|
3065
|
+
label?: string | undefined;
|
|
3066
|
+
processId?: number | undefined;
|
|
3067
|
+
processType?: string | undefined;
|
|
3068
|
+
nodeStatusServiceId?: string | undefined;
|
|
3069
|
+
metadata?: Record<string, string | number | boolean> | undefined;
|
|
3070
|
+
};
|
|
3071
|
+
}[] | undefined;
|
|
3072
|
+
}, any, never, never, readonly ApplicationErrorDescriptorBase[], any>;
|
|
3073
|
+
}>;
|
|
3074
|
+
//#endregion
|
|
3075
|
+
//#region src/connection/streaming.d.ts
|
|
2695
3076
|
/**
|
|
2696
|
-
*
|
|
2697
|
-
*
|
|
3077
|
+
* Direction a {@link STREAM_METHOD} message travels, relative to the
|
|
3078
|
+
* request it is correlated with. Made explicit on the wire so that a
|
|
3079
|
+
* middlebox (the hub) can *author* a stream message — e.g. inject a
|
|
3080
|
+
* cancel when a caller disconnects — without an inbound message whose
|
|
3081
|
+
* arrival link it could infer the direction from.
|
|
2698
3082
|
*/
|
|
2699
|
-
declare
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
3083
|
+
declare const StreamDir: {
|
|
3084
|
+
/** callee → caller: progress, partial results. Routes like a response. */
|
|
3085
|
+
readonly toCaller: "toCaller";
|
|
3086
|
+
/** caller → callee: input, cancellation, keepalive ping. */
|
|
3087
|
+
readonly toCallee: "toCallee";
|
|
3088
|
+
};
|
|
3089
|
+
type StreamDir = (typeof StreamDir)[keyof typeof StreamDir];
|
|
2706
3090
|
/**
|
|
2707
|
-
*
|
|
2708
|
-
*
|
|
2709
|
-
*
|
|
3091
|
+
* Reserved control verbs. A control message carries no app `payload`; it
|
|
3092
|
+
* is interpreted by the runtime / hub itself, independently of the
|
|
3093
|
+
* originating method's stream schemas, so *any* request is cancellable
|
|
3094
|
+
* and keep-alive-able even when it declares no app stream.
|
|
2710
3095
|
*/
|
|
2711
|
-
declare
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
3096
|
+
declare const StreamControlType: {
|
|
3097
|
+
/**
|
|
3098
|
+
* Ask the callee to abort the in-flight request. Always {@link
|
|
3099
|
+
* StreamDir.toCallee}. The callee surfaces this as an `AbortSignal`
|
|
3100
|
+
* and is expected to settle the request (typically with a
|
|
3101
|
+
* `cancelled` error response).
|
|
3102
|
+
*/
|
|
3103
|
+
readonly cancel: "cancel";
|
|
3104
|
+
/**
|
|
3105
|
+
* Keepalive / liveness probe. Resets the hub's per-request idle timer
|
|
3106
|
+
* so a long-running call is not reaped, and lets either side actively
|
|
3107
|
+
* probe the peer. Carries a `nonce` the peer echoes in its {@link
|
|
3108
|
+
* StreamControlType.pong}. May travel in either direction. Emitted
|
|
3109
|
+
* automatically (without awaiting a pong) by the channel for streaming
|
|
3110
|
+
* calls; see {@link STREAM_METHOD}.
|
|
3111
|
+
*/
|
|
3112
|
+
readonly ping: "ping";
|
|
3113
|
+
/**
|
|
3114
|
+
* Reply to a {@link StreamControlType.ping}, echoing the ping's
|
|
3115
|
+
* `nonce` so the prober can correlate it. Travels opposite the ping.
|
|
3116
|
+
* Carries no app effect — purely a liveness acknowledgement.
|
|
3117
|
+
*/
|
|
3118
|
+
readonly pong: "pong";
|
|
3119
|
+
};
|
|
3120
|
+
type StreamControlType = (typeof StreamControlType)[keyof typeof StreamControlType];
|
|
2725
3121
|
/**
|
|
2726
|
-
*
|
|
2727
|
-
*
|
|
2728
|
-
* private to one participant — no other peer can reach these methods.
|
|
2729
|
-
*
|
|
2730
|
-
* When `storage` is supplied, the `identity.storage` interface is
|
|
2731
|
-
* registered alongside `identity::*`. Lifetime/scope of the backend is
|
|
2732
|
-
* the executor's responsibility — for keystore-backed identities the
|
|
2733
|
-
* backend lives as long as the identity slot does.
|
|
2734
|
-
*
|
|
2735
|
-
* Typical caller: the executor (e.g. the VS Code extension), right after
|
|
2736
|
-
* `Hub.attachParticipant`, on the `rootOverlay` returned from the attach
|
|
2737
|
-
* handle.
|
|
3122
|
+
* Well-known `control.reason` strings. The set is **open** — any string
|
|
3123
|
+
* is valid on the wire; these are the reasons linkrpc itself emits.
|
|
2738
3124
|
*/
|
|
2739
|
-
declare
|
|
3125
|
+
declare const StreamControlReason: {
|
|
3126
|
+
/**
|
|
3127
|
+
* The caller's transport dropped while the request was in flight; the
|
|
3128
|
+
* hub cancels the callee's now-orphaned work.
|
|
3129
|
+
*/
|
|
3130
|
+
readonly clientDisconnected: "clientDisconnected";
|
|
3131
|
+
/**
|
|
3132
|
+
* The request exceeded the hub's idle timeout with no stream activity
|
|
3133
|
+
* (no ping, no stream message). See {@link STREAM_METHOD} docs.
|
|
3134
|
+
*/
|
|
3135
|
+
readonly idleTimeout: "idleTimeout";
|
|
3136
|
+
};
|
|
3137
|
+
type StreamControlReason = (typeof StreamControlReason)[keyof typeof StreamControlReason];
|
|
2740
3138
|
/**
|
|
2741
|
-
*
|
|
2742
|
-
*
|
|
2743
|
-
*
|
|
2744
|
-
*
|
|
3139
|
+
* Streaming sub-protocol. Long-running requests can emit additional
|
|
3140
|
+
* notifications correlated with the original call in either direction
|
|
3141
|
+
* (callee → caller progress, caller → callee input / cancellation /
|
|
3142
|
+
* keepalive).
|
|
2745
3143
|
*
|
|
2746
|
-
*
|
|
2747
|
-
*
|
|
2748
|
-
*
|
|
2749
|
-
*
|
|
2750
|
-
*
|
|
2751
|
-
*
|
|
3144
|
+
* Wire form: a JSON-RPC notification whose method is
|
|
3145
|
+
* `${streamInterface.info.id}::send` and whose params match
|
|
3146
|
+
* `streamInterface.members.send.paramsSchema`. The hub routes purely on
|
|
3147
|
+
* `requestId` (following the originating request's established path, like
|
|
3148
|
+
* a response); the originating request's capability authorization covers
|
|
3149
|
+
* its full stream lifetime, so stream notifications carry no method /
|
|
3150
|
+
* interface namespace of their own. App `payload` contents are typed per
|
|
3151
|
+
* request via the originating method's
|
|
3152
|
+
* `RequestType.clientStreamSchema` / `serverStreamSchema`; reserved
|
|
3153
|
+
* `control` messages are schema-independent.
|
|
2752
3154
|
*
|
|
2753
|
-
*
|
|
2754
|
-
*
|
|
2755
|
-
*
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
*
|
|
2760
|
-
* the participant's root overlay; the executor enforces key-shape rules
|
|
2761
|
-
* server-side.
|
|
3155
|
+
* Idle timeout: a request that never streams (no `control` ping, no
|
|
3156
|
+
* stream message) is subject to the hub's per-request idle timeout
|
|
3157
|
+
* (default 30 minutes) — at which point it is cancelled and its caller
|
|
3158
|
+
* gets a `requestTimeout` error. This bounds the hub's pending-request
|
|
3159
|
+
* table, which is also what protects it from a slow-loris / DDoS that
|
|
3160
|
+
* opens requests and never completes them. Streaming-enabled calls keep
|
|
3161
|
+
* themselves alive by emitting a periodic {@link StreamControlType.ping}.
|
|
2762
3162
|
*
|
|
2763
|
-
*
|
|
2764
|
-
*
|
|
2765
|
-
*
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
2769
|
-
set(key: string, value: unknown): Promise<void>;
|
|
2770
|
-
delete(key: string): Promise<boolean>;
|
|
2771
|
-
list(prefix?: string): Promise<string[]>;
|
|
2772
|
-
}
|
|
2773
|
-
/**
|
|
2774
|
-
* A managed identity resolved from an executor's `identity::*` overlay: a
|
|
2775
|
-
* full {@link Identity} (signing + HPKE wrap/unwrap, all round-tripping
|
|
2776
|
-
* through the executor — private keys never leave it) plus the
|
|
2777
|
-
* per-identity {@link ManagedIdentityStorage}.
|
|
3163
|
+
* The interface is declarative: nobody calls
|
|
3164
|
+
* `LinkRpcConnection.register(streamInterface, ...)`. The channel and the
|
|
3165
|
+
* hub intercept `$stream::send` directly. The definition exists so
|
|
3166
|
+
* reflection / consent UIs can describe the wire shape and so all wire
|
|
3167
|
+
* constants derive from one source.
|
|
2778
3168
|
*/
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
3169
|
+
declare const streamInterface: InterfaceDefinition<{
|
|
3170
|
+
send: NotificationType<{
|
|
3171
|
+
requestId: string | number;
|
|
3172
|
+
dir: "toCaller" | "toCallee";
|
|
3173
|
+
control?: {
|
|
3174
|
+
type: "cancel" | "ping" | "pong";
|
|
3175
|
+
reason?: string | undefined;
|
|
3176
|
+
nonce?: string | undefined;
|
|
3177
|
+
} | undefined;
|
|
3178
|
+
payload?: unknown;
|
|
3179
|
+
}>;
|
|
3180
|
+
}>;
|
|
2787
3181
|
/**
|
|
2788
|
-
*
|
|
2789
|
-
*
|
|
2790
|
-
* {@link SigningSender}). Makes `identity::*` calls unsigned — the
|
|
2791
|
-
* executor's overlay is private to one participant so routing already
|
|
2792
|
-
* identifies the caller, preventing signing recursion.
|
|
2793
|
-
*
|
|
2794
|
-
* The returned identity signs / wraps / unwraps by round-tripping through
|
|
2795
|
-
* the executor's `identity::*` overlay; the caller wires it into their
|
|
2796
|
-
* {@link SigningSender} configuration (e.g. as a {@link Principal}). No
|
|
2797
|
-
* side effects on any existing connection or holder.
|
|
3182
|
+
* Full wire method name for stream notifications. Pulled from the
|
|
3183
|
+
* interface object so we have a single source of truth.
|
|
2798
3184
|
*/
|
|
2799
|
-
declare
|
|
3185
|
+
declare const STREAM_METHOD: `${string}::send`;
|
|
3186
|
+
/** Wire-level shape carried on `params` of {@link STREAM_METHOD}. */
|
|
3187
|
+
type StreamSendParams = output<typeof streamInterface.members.send.paramsSchema>;
|
|
2800
3188
|
//#endregion
|
|
2801
|
-
//#region src/
|
|
2802
|
-
interface CapBagOptions {
|
|
2803
|
-
/**
|
|
2804
|
-
* Per-identity persistent storage (e.g.
|
|
2805
|
-
* {@link ManagedIdentityHandle.storage}). Omit for a memory-only bag
|
|
2806
|
-
* that forgets its caps when the process exits.
|
|
2807
|
-
*/
|
|
2808
|
-
readonly storage?: ManagedIdentityStorage;
|
|
2809
|
-
/** Storage key. Defaults to `hubrpc.caps.v1`. */
|
|
2810
|
-
readonly storageKey?: string;
|
|
2811
|
-
/** Optional sink for non-fatal storage warnings. */
|
|
2812
|
-
readonly onWarn?: (message: string) => void;
|
|
2813
|
-
}
|
|
3189
|
+
//#region src/protocol/jcs.d.ts
|
|
2814
3190
|
/**
|
|
2815
|
-
*
|
|
2816
|
-
*
|
|
2817
|
-
*
|
|
2818
|
-
*
|
|
3191
|
+
* RFC 8785 JSON Canonicalization Scheme (JCS).
|
|
3192
|
+
*
|
|
3193
|
+
* Used as the byte-deterministic encoding under every linkrpc signature
|
|
3194
|
+
* (RPC calls, capabilities, hub-signed previews). Both signer and verifier
|
|
3195
|
+
* canonicalize the same value object and obtain byte-identical UTF-8 bytes.
|
|
2819
3196
|
*
|
|
2820
|
-
*
|
|
2821
|
-
*
|
|
2822
|
-
*
|
|
3197
|
+
* Implementation inlined from the `canonicalize` npm package (Apache-2.0,
|
|
3198
|
+
* https://github.com/erdtman/canonicalize) so this module stays
|
|
3199
|
+
* zero-dependency for browser bundlers that don't resolve transitive
|
|
3200
|
+
* npm specifiers (e.g. the in-house app-bundler).
|
|
2823
3201
|
*/
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
private readonly _storage?;
|
|
2829
|
-
private readonly _storageKey;
|
|
2830
|
-
private readonly _onWarn;
|
|
2831
|
-
private constructor();
|
|
2832
|
-
get capabilities(): readonly SignedCapability[];
|
|
2833
|
-
/**
|
|
2834
|
-
* A {@link CapProvider} reflecting the bag at call-time. Assign it to
|
|
2835
|
-
* `HubClientHandle.signing.capProvider` or pass it through
|
|
2836
|
-
* `SigningSenderConfig.capProvider`.
|
|
2837
|
-
*/
|
|
2838
|
-
readonly provider: CapProvider;
|
|
2839
|
-
/** Append capabilities and persist (when backed by storage). */
|
|
2840
|
-
add(...caps: readonly SignedCapability[]): Promise<void>;
|
|
2841
|
-
/** Drop all capabilities and persist the empty bag. */
|
|
2842
|
-
clear(): Promise<void>;
|
|
2843
|
-
private _hydrate;
|
|
2844
|
-
private _persist;
|
|
2845
|
-
}
|
|
3202
|
+
/** RFC 8785 canonical JSON string for `value`. */
|
|
3203
|
+
declare function jcsCanonicalize(value: unknown): string;
|
|
3204
|
+
/** UTF-8 bytes of the RFC 8785 canonical JSON for `value`. The thing actually signed / hashed. */
|
|
3205
|
+
declare function jcsCanonicalizeBytes(value: unknown): Uint8Array;
|
|
2846
3206
|
//#endregion
|
|
2847
|
-
//#region src/
|
|
3207
|
+
//#region src/protocol/methodName.d.ts
|
|
2848
3208
|
/**
|
|
2849
|
-
*
|
|
2850
|
-
*
|
|
2851
|
-
* {@link CapBag} is mutable and extensible — caps accumulate as the peer grants
|
|
2852
|
-
* them.
|
|
3209
|
+
* Parsed JSON-RPC method string. The linkrpc dialect uses `::` to
|
|
3210
|
+
* separate up to three segments:
|
|
2853
3211
|
*
|
|
2854
|
-
*
|
|
2855
|
-
*
|
|
3212
|
+
* - `"member"` — bare (preset-bound dispatch)
|
|
3213
|
+
* - `"interfaceId::member"` — interface form (root service)
|
|
3214
|
+
* - `"::interfaceId::member"` — explicit root form
|
|
3215
|
+
* - `"serviceId::interfaceId::member"` — fully-qualified form
|
|
2856
3216
|
*
|
|
2857
|
-
*
|
|
2858
|
-
*
|
|
2859
|
-
* a top-level `class … extends Principal`: such a cycle would hit a TDZ
|
|
2860
|
-
* ("Class extends value undefined") depending on module evaluation order.
|
|
3217
|
+
* The hub does not accept the `bare` form (it has no interface context
|
|
3218
|
+
* to route on). Connection-level dispatch accepts all three.
|
|
2861
3219
|
*/
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
3220
|
+
type ParsedMethodName = {
|
|
3221
|
+
kind: "bare";
|
|
3222
|
+
member: string;
|
|
3223
|
+
} | {
|
|
3224
|
+
kind: "interface";
|
|
3225
|
+
interfaceId: string;
|
|
3226
|
+
member: string;
|
|
3227
|
+
} | {
|
|
3228
|
+
kind: "full";
|
|
3229
|
+
serviceId: string;
|
|
3230
|
+
interfaceId: string;
|
|
3231
|
+
member: string;
|
|
3232
|
+
};
|
|
2871
3233
|
/**
|
|
2872
|
-
*
|
|
2873
|
-
*
|
|
2874
|
-
* so callers can persist their own app state (e.g. a resolved serviceId)
|
|
2875
|
-
* alongside the granted capabilities, using the very same durable store the
|
|
2876
|
-
* {@link CapBag} hydrates from — no second storage wiring required.
|
|
3234
|
+
* Parse a JSON-RPC method string. Returns `undefined` if any segment is
|
|
3235
|
+
* empty or the segment count is out of range.
|
|
2877
3236
|
*/
|
|
2878
|
-
declare
|
|
2879
|
-
readonly store: ManagedIdentityStorage;
|
|
2880
|
-
readonly identity: Identity;
|
|
2881
|
-
constructor(identity: Identity, capBag: CapBag, store: ManagedIdentityStorage);
|
|
2882
|
-
}
|
|
3237
|
+
declare function parseMethodName(method: string): ParsedMethodName | undefined;
|
|
2883
3238
|
/**
|
|
2884
|
-
*
|
|
2885
|
-
*
|
|
2886
|
-
*
|
|
2887
|
-
*
|
|
2888
|
-
* transport whose peer serves the identity overlay (hub *or* stdio).
|
|
2889
|
-
*
|
|
2890
|
-
* Call this exactly once per channel: it performs the `identity::*` handshake
|
|
2891
|
-
* and hydrates the {@link CapBag} from storage. The returned
|
|
2892
|
-
* {@link PrincipalWithStore} additionally surfaces that same durable
|
|
2893
|
-
* {@link ManagedIdentityStorage} as `store`.
|
|
3239
|
+
* Convert a parsed method string to a {@link CallTarget} for capability
|
|
3240
|
+
* matching. Interface-form calls are addressed to the root service —
|
|
3241
|
+
* represented as an empty `serviceId`. Throws on `bare` form (no
|
|
3242
|
+
* interface context) and on malformed input.
|
|
2894
3243
|
*/
|
|
2895
|
-
declare function
|
|
3244
|
+
declare function methodNameToTarget(method: string): CallTarget;
|
|
2896
3245
|
//#endregion
|
|
2897
|
-
//#region src/
|
|
3246
|
+
//#region src/protocol/linkRpcEnvelope.d.ts
|
|
2898
3247
|
/**
|
|
2899
|
-
*
|
|
2900
|
-
*
|
|
2901
|
-
*
|
|
2902
|
-
* - override `method` / `params` / `interfaceHash` (rewriting,
|
|
2903
|
-
* auditing, schema-pinning),
|
|
2904
|
-
* - advance `signedAtMs` (e.g. after a slow consent prompt that needs
|
|
2905
|
-
* to issue a cap bound to a fresher timestamp than the sender's
|
|
2906
|
-
* initial wall-clock).
|
|
3248
|
+
* Signed call meta. Lives under `params.$hubrpc` so it can't collide with
|
|
3249
|
+
* the user's top-level param keys. Present on signed AND unsigned calls
|
|
3250
|
+
* (the latter omit {@link CallMeta.principal} and carry no `$hubrpcSignature`).
|
|
2907
3251
|
*
|
|
2908
|
-
*
|
|
2909
|
-
*
|
|
2910
|
-
* not drift between the cap-issuance request and the call itself.
|
|
3252
|
+
* Included verbatim in the bytes a call signature commits to — the
|
|
3253
|
+
* signature covers `signingInput("call", { ...userParams, $hubrpc })`.
|
|
2911
3254
|
*/
|
|
2912
|
-
|
|
3255
|
+
interface CallMeta {
|
|
3256
|
+
/** Fully-qualified wire method. The verifier asserts it equals the JSON-RPC `method`. */
|
|
2913
3257
|
readonly method: string;
|
|
2914
|
-
|
|
2915
|
-
readonly signer: PrincipalId;
|
|
3258
|
+
/** Replay-protection nonce (base64url). The gate dedups on this. */
|
|
2916
3259
|
readonly nonce: string;
|
|
3260
|
+
/** Unix milliseconds. Skew window enforced by the verifier. */
|
|
2917
3261
|
readonly signedAtMs: number;
|
|
3262
|
+
/** Identity wielding the call. Present iff signed; equals the audience of every presented cap. */
|
|
3263
|
+
readonly principal?: PrincipalId;
|
|
3264
|
+
/** Optional schema hash assertion. Matched against `TargetPattern.interfaceHash`. */
|
|
2918
3265
|
readonly interfaceHash?: string;
|
|
2919
|
-
}
|
|
2920
|
-
|
|
3266
|
+
}
|
|
3267
|
+
/**
|
|
3268
|
+
* Extrinsic, unsigned attachments carried under `params.$hubrpcUnsigned`.
|
|
3269
|
+
* Not covered by the call signature (they aren't authored by the signer).
|
|
3270
|
+
*/
|
|
3271
|
+
interface LinkRpcUnsigned {
|
|
3272
|
+
/** Caller's presented capability bag. Parents are resolved out of this by hash. */
|
|
2921
3273
|
readonly capabilities?: readonly SignedCapability[];
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
readonly
|
|
2926
|
-
|
|
2927
|
-
readonly
|
|
2928
|
-
/** Advance the Unix-ms timestamp baked into the signed envelope. */
|
|
2929
|
-
readonly signedAtMs?: number;
|
|
3274
|
+
}
|
|
3275
|
+
/** Reserved wire-key meta carried on a linkrpc call's params object. */
|
|
3276
|
+
interface LinkRpcWireMeta {
|
|
3277
|
+
readonly [HUBRPC_META_KEY]?: CallMeta;
|
|
3278
|
+
readonly [HUBRPC_SIGNATURE_KEY]?: Signatures;
|
|
3279
|
+
readonly [HUBRPC_UNSIGNED_KEY]?: LinkRpcUnsigned;
|
|
2930
3280
|
}
|
|
2931
3281
|
/**
|
|
2932
|
-
*
|
|
2933
|
-
* optional; the sender's persistent {@link SigningSenderConfig.principal} is
|
|
2934
|
-
* the default.
|
|
3282
|
+
* Wire shape of `params` on a linkrpc JSON-RPC call.
|
|
2935
3283
|
*
|
|
2936
|
-
*
|
|
2937
|
-
*
|
|
2938
|
-
*
|
|
3284
|
+
* The user's params object (if any) is spread as-is, with the
|
|
3285
|
+
* {@link LinkRpcWireMeta} keys attached on top. `TUserParams` carries the
|
|
3286
|
+
* user-visible param shape; defaults to an open object. User params MUST be
|
|
3287
|
+
* a plain object — enforced at signing/verification via
|
|
3288
|
+
* {@link requireObjectParams}.
|
|
2939
3289
|
*/
|
|
2940
|
-
|
|
3290
|
+
type LinkRpcWireParams<TUserParams extends {
|
|
3291
|
+
[key: string]: JsonValue | undefined;
|
|
3292
|
+
} = {
|
|
3293
|
+
[key: string]: JsonValue | undefined;
|
|
3294
|
+
}> = TUserParams & LinkRpcWireMeta;
|
|
3295
|
+
/** JSON-RPC request whose `params` carry the linkrpc wire meta. */
|
|
3296
|
+
type LinkRpcJsonRpcRequest<TUserParams extends {
|
|
3297
|
+
[key: string]: JsonValue | undefined;
|
|
3298
|
+
} = {
|
|
3299
|
+
[key: string]: JsonValue | undefined;
|
|
3300
|
+
}> = JsonRpcRequest<LinkRpcWireParams<TUserParams>>;
|
|
3301
|
+
/** JSON-RPC notification whose `params` carry the linkrpc wire meta. */
|
|
3302
|
+
type LinkRpcJsonRpcNotification<TUserParams extends {
|
|
3303
|
+
[key: string]: JsonValue | undefined;
|
|
3304
|
+
} = {
|
|
3305
|
+
[key: string]: JsonValue | undefined;
|
|
3306
|
+
}> = JsonRpcNotification<LinkRpcWireParams<TUserParams>>;
|
|
3307
|
+
/** Either of the two linkrpc-bearing JSON-RPC message shapes. */
|
|
3308
|
+
type LinkRpcJsonRpcMessage<TUserParams extends {
|
|
3309
|
+
[key: string]: JsonValue | undefined;
|
|
3310
|
+
} = {
|
|
3311
|
+
[key: string]: JsonValue | undefined;
|
|
3312
|
+
}> = LinkRpcJsonRpcRequest<TUserParams> | LinkRpcJsonRpcNotification<TUserParams>;
|
|
3313
|
+
/**
|
|
3314
|
+
* The linkrpc signing/cap system accepts only plain-object user params (or
|
|
3315
|
+
* none). Reject arrays/primitives at the boundary so "strip `$hubrpc*`, the
|
|
3316
|
+
* rest is the signed user params" stays unambiguous.
|
|
3317
|
+
*/
|
|
3318
|
+
declare function requireObjectParams(userParams: JsonValue | undefined): Record<string, JsonValue | undefined>;
|
|
3319
|
+
/**
|
|
3320
|
+
* Return the application-authored portion of a LinkRPC params value.
|
|
3321
|
+
*
|
|
3322
|
+
* Routing and gate layers must continue forwarding the original wire params so
|
|
3323
|
+
* every chained hub can independently verify the envelope. Terminal dispatch
|
|
3324
|
+
* may use this derived value for application-schema validation without mutating
|
|
3325
|
+
* or replacing the wire message.
|
|
3326
|
+
*/
|
|
3327
|
+
declare function stripLinkRpcWireMeta(wireParams: unknown): JsonValue | undefined;
|
|
3328
|
+
//#endregion
|
|
3329
|
+
//#region src/transport/multiplexedTransport.d.ts
|
|
3330
|
+
interface MuxEnvelope {
|
|
3331
|
+
readonly $mux: "v1";
|
|
3332
|
+
readonly ch: string;
|
|
3333
|
+
readonly m: JsonRpcMessage;
|
|
3334
|
+
}
|
|
3335
|
+
declare class MultiplexedTransport<TChannels extends Record<string, string>> implements IDisposable {
|
|
3336
|
+
static create<TChannels extends Record<string, string>>(base: IMessageTransport<MuxEnvelope, MuxEnvelope>, channels: TChannels): MultiplexedTransport<TChannels>;
|
|
3337
|
+
/** Logical transports keyed by the friendly channel names. */
|
|
3338
|
+
readonly transports: { readonly [K in keyof TChannels]: IMessageTransport; };
|
|
3339
|
+
private readonly _base;
|
|
3340
|
+
private readonly _byId;
|
|
3341
|
+
private readonly _usedIds;
|
|
3342
|
+
private _disposed;
|
|
3343
|
+
constructor(base: IMessageTransport<MuxEnvelope, MuxEnvelope>, channels: TChannels);
|
|
2941
3344
|
/**
|
|
2942
|
-
*
|
|
2943
|
-
*
|
|
2944
|
-
*
|
|
2945
|
-
*
|
|
3345
|
+
* Add a logical channel after the multiplexer has started.
|
|
3346
|
+
*
|
|
3347
|
+
* Channel ids are permanently retired when disposed. This prevents a late
|
|
3348
|
+
* envelope for an old iframe from being delivered to a replacement iframe.
|
|
2946
3349
|
*/
|
|
2947
|
-
|
|
3350
|
+
addChannel(id: string): IMessageTransport;
|
|
3351
|
+
dispose(): void;
|
|
3352
|
+
private _createChannel;
|
|
3353
|
+
}
|
|
3354
|
+
//#endregion
|
|
3355
|
+
//#region src/connection/bareInterfaceTarget.d.ts
|
|
3356
|
+
/** A metadata-free foreign-protocol interface and its wire-method prefix. */
|
|
3357
|
+
interface BareInterfaceTarget<TDef extends InterfaceDefinition<any>> {
|
|
3358
|
+
readonly mode: 'bare';
|
|
3359
|
+
readonly interface: TDef;
|
|
3360
|
+
readonly prefix: string;
|
|
3361
|
+
}
|
|
3362
|
+
/**
|
|
3363
|
+
* Bundle an interface definition with metadata-free foreign-protocol
|
|
3364
|
+
* addressing for use with `connection.get(target)` or
|
|
3365
|
+
* `connection.register(target, handlers)`.
|
|
3366
|
+
*/
|
|
3367
|
+
declare function bareInterfaceTarget<TDef extends InterfaceDefinition<any>>(iface: TDef, options?: {
|
|
3368
|
+
readonly prefix?: string;
|
|
3369
|
+
}): BareInterfaceTarget<TDef>;
|
|
3370
|
+
//#endregion
|
|
3371
|
+
//#region src/connection/interfaceTarget.d.ts
|
|
3372
|
+
/** A qualified LinkRPC route. An empty serviceId addresses the root interface. */
|
|
3373
|
+
interface QualifiedInterfaceTarget<TDef extends InterfaceDefinition<any>> {
|
|
3374
|
+
readonly mode: 'qualified';
|
|
3375
|
+
readonly interface: TDef;
|
|
3376
|
+
readonly serviceId: string;
|
|
3377
|
+
}
|
|
3378
|
+
/** The peer's preset form-1 route, retaining LinkRPC metadata and streaming. */
|
|
3379
|
+
interface DefaultInterfaceTarget<TDef extends InterfaceDefinition<any>> {
|
|
3380
|
+
readonly mode: 'default';
|
|
3381
|
+
readonly interface: TDef;
|
|
3382
|
+
}
|
|
3383
|
+
type InterfaceTarget<TDef extends InterfaceDefinition<any>> = QualifiedInterfaceTarget<TDef> | DefaultInterfaceTarget<TDef> | BareInterfaceTarget<TDef>;
|
|
3384
|
+
declare function interfaceTarget<TDef extends InterfaceDefinition<any>>(iface: TDef, options?: {
|
|
3385
|
+
readonly serviceId?: string;
|
|
3386
|
+
}): QualifiedInterfaceTarget<TDef>;
|
|
3387
|
+
declare function defaultInterfaceTarget<TDef extends InterfaceDefinition<any>>(iface: TDef): DefaultInterfaceTarget<TDef>;
|
|
3388
|
+
declare function isInterfaceTarget<TDef extends InterfaceDefinition<any>>(value: TDef | InterfaceTarget<TDef>): value is InterfaceTarget<TDef>;
|
|
3389
|
+
//#endregion
|
|
3390
|
+
//#region src/connection/channelConnector.d.ts
|
|
3391
|
+
/**
|
|
3392
|
+
* A raw channel that signals when it closes (and, when possible, can be torn
|
|
3393
|
+
* down). Both {@link openHubChannel}'s `HubChannel` and `openStdioChannel`'s
|
|
3394
|
+
* `StdioChannel` satisfy this shape.
|
|
3395
|
+
*/
|
|
3396
|
+
type ConnectableChannel = Channel<undefined, unknown> & {
|
|
2948
3397
|
/**
|
|
2949
|
-
*
|
|
2950
|
-
*
|
|
3398
|
+
* Fires once when the channel closes. Returns a disposable to unsubscribe.
|
|
3399
|
+
*
|
|
3400
|
+
* Ordering contract: when a close causes a sending method (e.g. a request
|
|
3401
|
+
* or notification) to reject/throw, {@link onClose} must fire *before* that
|
|
3402
|
+
* rejection surfaces to the caller. This lets consumers reliably tell a
|
|
3403
|
+
* close-induced failure (the channel is already observably closed) apart
|
|
3404
|
+
* from a genuine error (the channel is still open). See
|
|
3405
|
+
* {@link ChannelConnector.keepConnected}.
|
|
2951
3406
|
*/
|
|
2952
|
-
|
|
3407
|
+
onClose(listener: () => void): IDisposable;
|
|
3408
|
+
/** Tear the channel down. Optional — stdio channels have no explicit close. */
|
|
3409
|
+
close?(): void;
|
|
3410
|
+
};
|
|
3411
|
+
/** Handle returned by {@link ChannelConnector.keepConnected}. */
|
|
3412
|
+
interface KeepConnectedHandle {
|
|
2953
3413
|
/**
|
|
2954
|
-
*
|
|
2955
|
-
*
|
|
3414
|
+
* Resolves when the loop exits: the channel closed and the connector does
|
|
3415
|
+
* not redial, or {@link stop} (or the supplied signal) fired.
|
|
2956
3416
|
*/
|
|
2957
|
-
readonly
|
|
3417
|
+
readonly done: Promise<void>;
|
|
3418
|
+
/** Stop redialing and close the current channel (if any). */
|
|
3419
|
+
stop(): void;
|
|
3420
|
+
}
|
|
3421
|
+
/** Callback run on every (re)connect. The channel is the raw, unsigned channel. */
|
|
3422
|
+
type OnChannelConnect<T extends ConnectableChannel> = (ctx: {
|
|
3423
|
+
channel: T;
|
|
3424
|
+
}) => void | Promise<void>;
|
|
3425
|
+
interface ExpBackoffOptions {
|
|
3426
|
+
readonly initialBackoffMs?: number;
|
|
3427
|
+
readonly maxBackoffMs?: number;
|
|
2958
3428
|
}
|
|
2959
3429
|
/**
|
|
2960
|
-
*
|
|
3430
|
+
* Drives a connect / (re)connect loop over a raw {@link ConnectableChannel}.
|
|
2961
3431
|
*
|
|
2962
|
-
*
|
|
2963
|
-
*
|
|
2964
|
-
*
|
|
2965
|
-
* fields are read fresh on every call, so callers may install or swap them
|
|
2966
|
-
* after the sender has been constructed.
|
|
3432
|
+
* Unlike connection-level helpers, this works at the channel layer: the
|
|
3433
|
+
* caller composes identity / signing on top of the channel handed to
|
|
3434
|
+
* {@link keepConnected} (e.g. `SigningSender.wrapChannel(channel, { principal })`).
|
|
2967
3435
|
*
|
|
2968
|
-
*
|
|
2969
|
-
*
|
|
3436
|
+
* Construct via {@link ChannelConnector.once} (a single, already-open channel
|
|
3437
|
+
* that never redials) or {@link ChannelConnector.expBackoff} (re-open via a
|
|
3438
|
+
* factory with exponential backoff after each close).
|
|
2970
3439
|
*/
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
readonly
|
|
3440
|
+
declare class ChannelConnector<T extends ConnectableChannel> {
|
|
3441
|
+
private readonly _open;
|
|
3442
|
+
private readonly _redial;
|
|
3443
|
+
private readonly _initialBackoffMs;
|
|
3444
|
+
private readonly _maxBackoffMs;
|
|
3445
|
+
private constructor();
|
|
2974
3446
|
/**
|
|
2975
|
-
*
|
|
2976
|
-
*
|
|
2977
|
-
*
|
|
3447
|
+
* A connector over a single channel (or a promise of one). Never redials;
|
|
3448
|
+
* the loop ends when the channel closes or {@link KeepConnectedHandle.stop}
|
|
3449
|
+
* fires.
|
|
2978
3450
|
*/
|
|
2979
|
-
|
|
3451
|
+
static once<T extends ConnectableChannel>(channel: T | Promise<T>): ChannelConnector<T>;
|
|
2980
3452
|
/**
|
|
2981
|
-
*
|
|
2982
|
-
*
|
|
3453
|
+
* A redialing connector: `open` is called once per attempt, and the loop
|
|
3454
|
+
* reconnects with exponential backoff after each close (or failed open).
|
|
2983
3455
|
*/
|
|
2984
|
-
|
|
3456
|
+
static expBackoff<T extends ConnectableChannel>(open: () => Promise<T>, opts?: ExpBackoffOptions): ChannelConnector<T>;
|
|
3457
|
+
/**
|
|
3458
|
+
* Run `onConnect` on every (re)connect with the freshly opened channel.
|
|
3459
|
+
* The callback typically wraps the channel with signing and registers
|
|
3460
|
+
* handlers. Returns once the loop exits (see {@link KeepConnectedHandle}).
|
|
3461
|
+
*/
|
|
3462
|
+
keepConnected(onConnect: OnChannelConnect<T>, opts?: {
|
|
3463
|
+
signal?: AbortSignal;
|
|
3464
|
+
}): KeepConnectedHandle;
|
|
3465
|
+
}
|
|
3466
|
+
//#endregion
|
|
3467
|
+
//#region src/connection/requestTimeout.d.ts
|
|
3468
|
+
declare const DEFAULT_RPC_TIMEOUT_MS = 5000;
|
|
3469
|
+
interface CancellableRequest<T> extends Promise<T> {
|
|
3470
|
+
cancel(reason?: string): void | Promise<void>;
|
|
3471
|
+
dispose?(reason?: string): void;
|
|
2985
3472
|
}
|
|
3473
|
+
declare function withRpcTimeout<T>(request: CancellableRequest<T>, target: string, timeoutMs?: number): Promise<T>;
|
|
3474
|
+
//#endregion
|
|
3475
|
+
//#region src/connection/endpointUri.d.ts
|
|
2986
3476
|
/**
|
|
2987
|
-
*
|
|
2988
|
-
*
|
|
2989
|
-
*
|
|
2990
|
-
*
|
|
3477
|
+
* A strict, RFC-3986 URI vocabulary for "where the linkrpc server lives, and
|
|
3478
|
+
* how to reach (or start) it". Every endpoint round-trips through
|
|
3479
|
+
* {@link parseEndpointUri} / {@link formatEndpointUri} and is a valid `new URL()`
|
|
3480
|
+
* — safe to put in env vars, logs, and config.
|
|
2991
3481
|
*
|
|
2992
|
-
*
|
|
2993
|
-
*
|
|
2994
|
-
*
|
|
3482
|
+
* Supported schemes:
|
|
3483
|
+
* - `unix:/path/to.sock?token=…` → {@link SocketEndpoint}
|
|
3484
|
+
* - `npipe://./pipe/name?token=…` → {@link SocketEndpoint} (Windows)
|
|
3485
|
+
* - `ws://host:port?token=…` / `wss:…` → {@link WsEndpoint} (LinkRPC handshake)
|
|
3486
|
+
* - `ws-no-init://host:port?…` → {@link WsNoInitEndpoint}
|
|
3487
|
+
* - `cmd-stdio:?command=…` / `…?argv=…` → {@link CmdStdioEndpoint}
|
|
3488
|
+
* - `cmd:?command=…` / `…?argv=…` → {@link CmdEnvEndpoint}
|
|
3489
|
+
*
|
|
3490
|
+
* The command payload is `{ command: string } | { argv: string[] }`:
|
|
3491
|
+
* - `?command=node%20server.js` — one verbatim string, split by the OS shell.
|
|
3492
|
+
* - `?argv=node&argv=server.js` — repeated `argv` params, structure-preserving.
|
|
3493
|
+
*
|
|
3494
|
+
* A bare string with no scheme (legacy `LINKRPC_ENDPOINT`) is auto-detected: a
|
|
3495
|
+
* `ws://`/`wss://` URL stays WebSocket, anything else is a socket path.
|
|
2995
3496
|
*/
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3497
|
+
/** Verbatim command line (`{ command }`) or pre-split argv (`{ argv }`). */
|
|
3498
|
+
type EndpointCommand = {
|
|
3499
|
+
readonly command: string;
|
|
3500
|
+
} | {
|
|
3501
|
+
readonly argv: readonly string[];
|
|
3502
|
+
};
|
|
3503
|
+
/** Named pipe / unix-domain-socket the server already listens on. */
|
|
3504
|
+
interface SocketEndpoint {
|
|
3505
|
+
readonly kind: 'socket';
|
|
3506
|
+
readonly path: string;
|
|
3507
|
+
readonly token?: string;
|
|
3000
3508
|
/**
|
|
3001
|
-
*
|
|
3002
|
-
*
|
|
3509
|
+
* Present on sockets created by `hub connect`. Local framing still uses the
|
|
3510
|
+
* LinkRPC transport handshake; this describes whether forwarded application
|
|
3511
|
+
* calls target a LinkRPC or plain JSON-RPC peer.
|
|
3003
3512
|
*/
|
|
3004
|
-
|
|
3513
|
+
readonly brokerMode?: 'linkrpc' | 'raw';
|
|
3514
|
+
}
|
|
3515
|
+
/** A running WebSocket hub; `token` rides in the `hubrpc::initialize` handshake. */
|
|
3516
|
+
interface WsEndpoint {
|
|
3517
|
+
readonly kind: 'ws';
|
|
3518
|
+
readonly url: string;
|
|
3519
|
+
readonly token?: string;
|
|
3005
3520
|
}
|
|
3006
3521
|
/**
|
|
3007
|
-
*
|
|
3008
|
-
*
|
|
3009
|
-
*
|
|
3010
|
-
*
|
|
3011
|
-
* swap them after construction by mutating that object.
|
|
3522
|
+
* A running plain-JSON-RPC WebSocket endpoint. Unlike {@link WsEndpoint}, CLI
|
|
3523
|
+
* consumers use it without the `hubrpc::initialize` handshake or LinkRPC signing.
|
|
3524
|
+
* Query parameters are preserved verbatim for protocols that authenticate
|
|
3525
|
+
* during the WebSocket upgrade (for example AHP's `tkn` parameter).
|
|
3012
3526
|
*/
|
|
3527
|
+
interface WsNoInitEndpoint {
|
|
3528
|
+
readonly kind: 'ws-no-init';
|
|
3529
|
+
/** Actual `ws://` URL passed to the WebSocket constructor. */
|
|
3530
|
+
readonly url: string;
|
|
3531
|
+
}
|
|
3532
|
+
/** Spawn a child and talk linkrpc over its stdin/stdout. */
|
|
3533
|
+
interface CmdStdioEndpoint {
|
|
3534
|
+
readonly kind: 'cmd-stdio';
|
|
3535
|
+
readonly command: EndpointCommand;
|
|
3536
|
+
/** Extra environment variables injected into the spawned child. */
|
|
3537
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
3538
|
+
/** Working directory for the spawned child. */
|
|
3539
|
+
readonly cwd?: string;
|
|
3540
|
+
}
|
|
3013
3541
|
/**
|
|
3014
|
-
*
|
|
3015
|
-
*
|
|
3016
|
-
*
|
|
3017
|
-
*
|
|
3542
|
+
* Spawn a child against a freshly-started *local hub*: the parent listens on a
|
|
3543
|
+
* private socket, hands the child its address + token via `LINKRPC_ENDPOINT` /
|
|
3544
|
+
* `LINKRPC_TOKEN`, and the child dials in as a hub participant (registering its
|
|
3545
|
+
* services), exactly as it would against a remote hub.
|
|
3018
3546
|
*/
|
|
3019
|
-
interface
|
|
3020
|
-
readonly
|
|
3021
|
-
readonly
|
|
3022
|
-
}
|
|
3023
|
-
declare class SigningSender<TInCtx = unknown> implements IRequestSender<SigningCallCtx> {
|
|
3024
|
-
private readonly _inner;
|
|
3025
|
-
private readonly _config;
|
|
3026
|
-
/**
|
|
3027
|
-
* Wrap an inner channel with signing. Composes via {@link Channel.withSender}
|
|
3028
|
-
* so the resulting `Channel<TInCtx, SigningCallCtx>` plugs into
|
|
3029
|
-
* `LinkRpcConnection`.
|
|
3030
|
-
*/
|
|
3031
|
-
static wrapChannel<TInCtx>(inner: Channel<TInCtx, unknown>, config: SigningSenderConfig): Channel<TInCtx, SigningCallCtx>;
|
|
3032
|
-
/**
|
|
3033
|
-
* Bootstrap an executor-managed {@link Principal} over the **unsigned**
|
|
3034
|
-
* `channel`, then wrap that same channel with signing driven by it.
|
|
3035
|
-
*
|
|
3036
|
-
* Crucially, the `identity::*` handshake that mints the managed principal
|
|
3037
|
-
* rides the *raw* channel (`channel.sender`), so those bootstrap calls are
|
|
3038
|
-
* themselves never signed — there is no "sign the sign call" recursion and
|
|
3039
|
-
* no reliance on threading `signerOverride: null` through every transport
|
|
3040
|
-
* layer. The returned signing {@link Channel} is what callers hand to
|
|
3041
|
-
* `LinkRpcConnection`; the {@link PrincipalWithStore} is returned alongside
|
|
3042
|
-
* for caps / per-identity storage / nodeId.
|
|
3043
|
-
*/
|
|
3044
|
-
static fromChannelWithManagedPrincipal<TInCtx>(channel: Channel<TInCtx, unknown>, config?: Omit<SigningSenderConfig, 'principal'>): Promise<ManagedSigningChannel<TInCtx>>;
|
|
3547
|
+
interface CmdEnvEndpoint {
|
|
3548
|
+
readonly kind: 'cmd-env';
|
|
3549
|
+
readonly command: EndpointCommand;
|
|
3045
3550
|
/**
|
|
3046
|
-
*
|
|
3047
|
-
*
|
|
3048
|
-
*
|
|
3551
|
+
* When set, the local hub provisions (or reuses) a *persistent* managed
|
|
3552
|
+
* identity under this slot id, so the child's HPKE wrap/unwrap keys survive
|
|
3553
|
+
* across runs (sealed archives re-open).
|
|
3049
3554
|
*/
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3555
|
+
readonly provisionSlot?: string;
|
|
3556
|
+
/** Extra environment variables injected into the spawned child. */
|
|
3557
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
3558
|
+
/** Working directory for the spawned child. */
|
|
3559
|
+
readonly cwd?: string;
|
|
3560
|
+
}
|
|
3561
|
+
type ResolvedEndpoint = SocketEndpoint | WsEndpoint | WsNoInitEndpoint | CmdStdioEndpoint | CmdEnvEndpoint;
|
|
3562
|
+
/**
|
|
3563
|
+
* Parse a strict endpoint URI into an {@link ResolvedEndpoint}. Throws on an
|
|
3564
|
+
* unknown scheme or a malformed command endpoint. A bare (scheme-less) string
|
|
3565
|
+
* is auto-detected as `ws`/`wss` URL or a socket path.
|
|
3566
|
+
*/
|
|
3567
|
+
declare function parseEndpointUri(uri: string): ResolvedEndpoint;
|
|
3568
|
+
interface FormatEndpointOptions {
|
|
3569
|
+
/** Emit the real token instead of redacting it. Default: redact. */
|
|
3570
|
+
readonly revealToken?: boolean;
|
|
3061
3571
|
}
|
|
3572
|
+
/**
|
|
3573
|
+
* Render an {@link ResolvedEndpoint} back to a canonical strict URI. The token is
|
|
3574
|
+
* redacted (`***`) unless `revealToken` is set, so the result is paste-safe for
|
|
3575
|
+
* logs. Round-trips with {@link parseEndpointUri} when `revealToken` is true.
|
|
3576
|
+
*/
|
|
3577
|
+
declare function formatEndpointUri(spec: ResolvedEndpoint, options?: FormatEndpointOptions): string;
|
|
3578
|
+
/** True for endpoints that connect to existing, possibly-remote infrastructure. */
|
|
3579
|
+
declare function isHubEndpoint(spec: ResolvedEndpoint): spec is SocketEndpoint | WsEndpoint;
|
|
3062
3580
|
declare namespace crypto_d_exports {
|
|
3063
3581
|
export { generateKeypair, generateX25519Keypair, hpkeOpen, hpkeSeal, keypairFromSeed, sha256, sign, verify, x25519KeypairFromSeed };
|
|
3064
3582
|
}
|
|
@@ -3545,8 +4063,11 @@ declare class LinkRpcConnection<TInCtx = any, TOutCtx = any> {
|
|
|
3545
4063
|
private readonly _directoryWatchers;
|
|
3546
4064
|
private readonly _directoryListeners;
|
|
3547
4065
|
private _inspection;
|
|
3548
|
-
private
|
|
4066
|
+
private _inspectionHost;
|
|
3549
4067
|
private readonly _serviceInspectionRegistrations;
|
|
4068
|
+
private readonly _wireObservers;
|
|
4069
|
+
private readonly _closeListeners;
|
|
4070
|
+
private _closed;
|
|
3550
4071
|
private readonly _wireChannel;
|
|
3551
4072
|
private readonly _validateOutboundParams;
|
|
3552
4073
|
/** Bare-method bindings, keyed by their exact wire prefix. */
|
|
@@ -3559,35 +4080,31 @@ declare class LinkRpcConnection<TInCtx = any, TOutCtx = any> {
|
|
|
3559
4080
|
* useful for bootstrap flows like `createManagedIdentity`).
|
|
3560
4081
|
*/
|
|
3561
4082
|
constructor(channel: Channel<TInCtx, TOutCtx> | IRequestSender<TOutCtx>, options?: LinkRpcConnectionOptions);
|
|
3562
|
-
/** Get a typed
|
|
3563
|
-
get<TDef extends InterfaceDefinition<any>>(target:
|
|
4083
|
+
/** Get a typed client using a bundled qualified, default, or bare route. */
|
|
4084
|
+
get<TDef extends InterfaceDefinition<any>>(target: InterfaceTarget<TDef>): InterfaceClient<TDef>;
|
|
3564
4085
|
/** Get a typed client for `iface`, routed to the implicit (root) service. */
|
|
3565
4086
|
get<TDef extends InterfaceDefinition<any>>(iface: TDef, opts?: GetOptions<TOutCtx>): InterfaceClient<TDef>;
|
|
4087
|
+
private _getClient;
|
|
3566
4088
|
/**
|
|
3567
4089
|
* Get a typed client that emits foreign-protocol bare method names.
|
|
3568
4090
|
* Unlike {@link get}, these calls carry no LinkRPC interface metadata.
|
|
3569
4091
|
*/
|
|
3570
4092
|
getBare<TDef extends InterfaceDefinition<any>>(iface: TDef, opts?: BareGetOptions): InterfaceClient<TDef>;
|
|
4093
|
+
private _buildBareClient;
|
|
4094
|
+
/** Return request failures as values for a bundled qualified, default, or bare route. */
|
|
4095
|
+
getResultClient<TDef extends InterfaceDefinition<any>>(target: InterfaceTarget<TDef>): InterfaceResultClient<TDef>;
|
|
4096
|
+
/** Return application and generic request failures as values instead of throwing. */
|
|
4097
|
+
getResultClient<TDef extends InterfaceDefinition<any>>(iface: TDef, opts?: GetOptions<TOutCtx>): InterfaceResultClient<TDef>;
|
|
3571
4098
|
/** Get a service-scoped handle; all interfaces obtained from it route via `serviceId` (form 3). */
|
|
3572
4099
|
service(serviceId: string): ServiceHandle<TInCtx, TOutCtx>;
|
|
3573
|
-
/** Register handlers
|
|
3574
|
-
register<TDef extends InterfaceDefinition<any>>(
|
|
4100
|
+
/** Register handlers, adding preset routing when passed a default or bare target. */
|
|
4101
|
+
register<TDef extends InterfaceDefinition<any>>(ifaceOrTarget: TDef | InterfaceTarget<TDef>, handlers: InterfaceHandlers<TDef, TInCtx>, opts?: RegisterOptions): InterfaceRegistration;
|
|
4102
|
+
/** Register inspection contracts without recursively enabling service inspection. */
|
|
4103
|
+
registerInspection<TDef extends InterfaceDefinition<any>>(iface: TDef, handlers: InterfaceHandlers<TDef, TInCtx>, opts?: RegisterOptions): InterfaceRegistration;
|
|
4104
|
+
/** Observe this connection without replacing another inspection scope's observer. */
|
|
4105
|
+
observeWireMessages(observer: WireMessageObserver): InterfaceRegistration;
|
|
4106
|
+
onDidClose(listener: () => void): InterfaceRegistration;
|
|
3575
4107
|
private _register;
|
|
3576
|
-
/**
|
|
3577
|
-
* Declare the preset interface for form-1 (bare-method) dispatch. The
|
|
3578
|
-
* interface must already be registered under the root (no serviceId).
|
|
3579
|
-
* Surfaced via `hubrpc.defaults::get`.
|
|
3580
|
-
*/
|
|
3581
|
-
setPreset(iface: InterfaceDefinition<any>): void;
|
|
3582
|
-
/**
|
|
3583
|
-
* Bind foreign-protocol bare methods to an already registered interface.
|
|
3584
|
-
* Matching uses the longest prefix; once selected, a missing member does
|
|
3585
|
-
* not fall through to a shorter binding.
|
|
3586
|
-
*/
|
|
3587
|
-
bindBare(iface: InterfaceDefinition<any>, opts: {
|
|
3588
|
-
prefix: string;
|
|
3589
|
-
serviceId?: string;
|
|
3590
|
-
}): InterfaceRegistration;
|
|
3591
4108
|
/** Snapshot of every interface currently registered on this connection. */
|
|
3592
4109
|
listRegisteredInterfaces(): readonly {
|
|
3593
4110
|
readonly serviceId: string;
|
|
@@ -3640,8 +4157,6 @@ declare class LinkRpcConnection<TInCtx = any, TOutCtx = any> {
|
|
|
3640
4157
|
private _installServiceInspection;
|
|
3641
4158
|
private _removeServiceInspection;
|
|
3642
4159
|
private _hasBusinessServiceRegistration;
|
|
3643
|
-
private _endpointGraph;
|
|
3644
|
-
private _watchTraffic;
|
|
3645
4160
|
}
|
|
3646
4161
|
/**
|
|
3647
4162
|
* Options when obtaining a typed client for an interface.
|
|
@@ -3693,8 +4208,8 @@ interface InterfaceRegistration {
|
|
|
3693
4208
|
/** Generated topology identity and its live root-interface registration. */
|
|
3694
4209
|
interface InspectionRegistration extends InterfaceRegistration, NodeInfo {
|
|
3695
4210
|
/**
|
|
3696
|
-
* Observe this endpoint's full-payload traffic in-process.
|
|
3697
|
-
*
|
|
4211
|
+
* Observe this endpoint's full-payload traffic in-process. Watch-control
|
|
4212
|
+
* flows are tracked even when no public observations are active.
|
|
3698
4213
|
*/
|
|
3699
4214
|
observeTraffic(observer: (transit: TrafficTransitEvent) => void): InterfaceRegistration;
|
|
3700
4215
|
}
|
|
@@ -3703,9 +4218,10 @@ declare class ServiceHandle<TInCtx = undefined, TOutCtx = undefined> {
|
|
|
3703
4218
|
private readonly _connection;
|
|
3704
4219
|
private readonly _serviceId;
|
|
3705
4220
|
constructor(_connection: LinkRpcConnection<TInCtx, TOutCtx>, _serviceId: string);
|
|
4221
|
+
getResultClient<TDef extends InterfaceDefinition<any>>(iface: TDef, opts?: Partial<TOutCtx>): InterfaceResultClient<TDef>;
|
|
3706
4222
|
get<TDef extends InterfaceDefinition<any>>(iface: TDef, opts?: Partial<TOutCtx>): InterfaceClient<TDef>;
|
|
3707
|
-
register<TDef extends InterfaceDefinition<any>>(
|
|
4223
|
+
register<TDef extends InterfaceDefinition<any>>(ifaceOrTarget: TDef | BareInterfaceTarget<TDef>, handlers: InterfaceHandlers<TDef, TInCtx>, opts?: Omit<RegisterOptions, 'serviceId'>): InterfaceRegistration;
|
|
3708
4224
|
}
|
|
3709
4225
|
//#endregion
|
|
3710
|
-
export {
|
|
3711
|
-
//# sourceMappingURL=linkRpcConnection-
|
|
4226
|
+
export { ExpBackoffOptions as $, ZodToSvcJsonSchemaOptions as $a, createSchemaToZod as $i, InMemoryManagedIdentityStorage as $n, readSignature as $r, zParticipantDescriptorSource as $t, VerifyRpcCallResult as A, StreamingCall as Aa, RpcError as Ai, WalkHubResult as An, UnionSchema as Ao, CallTarget as Ar, StreamSendParams as At, FormatEndpointOptions as B, ApplicationErrorsOf as Ba, traceMessageTransport as Bi, CapProvider as Bn, isRequest as Bo, permissionMatchesTarget as Br, TopologyLinkEndpoint as Bt, VerifyCallOptions as C, InterfaceResultClient as Ca, IRequestHandler as Ci, HubDirectoryNodeState as Cn, NumberSchema as Co, PublicWrappingIdentity as Cr, parseMethodName as Ct, SignRpcCallOptions as D, RpcCallError as Da, MessageWithCtx as Di, ReflectionChannel as Dn, SchemaBase as Do, Ability as Dr, StreamControlReason as Dt, verifyCall as E, RemoteRpcError as Ea, IncomingStream as Ei, ListOptions as En, RefSchema as Eo, WrappingIdentity as Er, STREAM_METHOD as Et, identityStorageInterface as F, RpcValidationIssue as Fa, MessageTransportTrace as Fi, normalizeServiceIdScopes as Fn, JsonRpcRequest as Fo, SignedCapability as Fr, ParticipantDescriptor as Ft, formatEndpointUri as G, MemberType as Ga, StaticHubSchema as Gi, SigningSender as Gn, HUBRPC_UNSIGNED_KEY as Gr, TrafficEvent as Gt, SocketEndpoint as H, CreatedRpcErrorValue as Ha, GenerateContractOptions as Hi, ManagedSigningChannel as Hn, JsonValue as Ho, Base64Sha256 as Hr, TopologyPort as Ht, crypto_d_exports as I, ApplicationErrorDescriptor as Ia, MessageTransportWithContext as Ii, serviceIdMatchesPattern as In, JsonRpcResponse as Io, TargetPattern as Ir, ParticipantDescriptorSource as It, CancellableRequest as J, RequestType as Ja, StaticService as Ji, createManagedPrincipal as Jn, LINKRPC_UNSIGNED_KEY as Jr, TrafficTransitEvent as Jt, isHubEndpoint as K, NotificationType as Ka, StaticHubSchemaDocument as Ki, SigningSenderConfig as Kn, LINKRPC_META_KEY as Kr, TrafficOverflowEvent as Kt, CmdEnvEndpoint as L, ApplicationErrorDescriptorBase as La, MessageWithContext as Li, serviceIdMatchesScopes as Ln, JsonRpcSuccess as Lo, capabilityPermits as Lr, RouteClaim as Lt, signRpcCall as M, defineInterface as Ma, StreamSendOpts as Mi, fetchSchema as Mn, JsonRpcError as Mo, ParamMatcher as Mr, NodeInfo as Mt, verifyRpcCall as N, interfaceFromSchema as Na, IMessageTransport as Ni, findMethodInSchema as Nn, JsonRpcMessage as No, Pattern as Nr, TopologyIdGenerator as Nt, SignedRpcCall as O, StreamApi as Oa, RawStreamingCall as Oi, ServiceListing as On, StringSchema as Oo, Call as Or, StreamControlType as Ot, identityInterface as P, NonCompliantServerError as Pa, MessageTransportDirection as Pi, intersectServiceIdScopes as Pn, JsonRpcNotification as Po, Permission as Pr, nodeInterface as Pt, ConnectableChannel as Q, Schema as Qa, SchemaToZodContext as Qi, InMemoryManagedIdentity as Qn, getKeyId as Qr, zParticipantDescriptor as Qt, CmdStdioEndpoint as R, ApplicationErrorOf as Ra, TransportPair as Ri, walkHub as Rn, RequestId as Ro, hasSignedCapabilityShape as Rr, TopologyGraph as Rt, SignParamsOptions as S, InterfaceMemberRefMap as Sa, ChannelTransport as Si, HubDirectoryNodeReport as Sn, NullSchema as So, PublicSigningIdentity as Sr, methodNameToTarget as St, signParams as T, MemberMap as Ta, IncomingCall as Ti, InaccessibleDirectory as Tn, OneOfSchema as To, SigningIdentity as Tr, jcsCanonicalizeBytes as Tt, WsEndpoint as U, DeclaredApplicationErrorOf as Ua, generateTsContract as Ui, OneShotCapStaging as Un, HUBRPC_META_KEY as Ur, TopologyTransportEndpoint as Ut, ResolvedEndpoint as V, CreatedApplicationErrorValue as Va, IDisposable as Vi, CapProviderResult as Vn, isResponse as Vo, permissionPermits as Vr, TopologyNode as Vt, WsNoInitEndpoint as W, MemberDocs as Wa, InterfaceRef as Wi, SigningCallCtx as Wn, HUBRPC_SIGNATURE_KEY as Wr, TopologyTransportInfo as Wt, withRpcTimeout as X, RpcErrorDescriptor as Xa, GenerateInterfaceOptions as Xi, CapBag as Xn, SignatureEnvelope as Xr, topologyInterface as Xt, DEFAULT_RPC_TIMEOUT_MS as Y, RpcErrorBody as Ya, parseStaticHubSchema as Yi, Principal as Yn, SignDomain as Yr, TrafficWatchResult as Yt, ChannelConnector as Z, RpcErrorValue as Za, generateTsInterface as Zi, CapBagOptions as Zn, Signatures as Zr, trafficInterface as Zt, SeededPrincipalOptions as _, InterfaceDefinition as _a, keyIdForPublicKey as _i, HubDirectoryChange as _n, ConstSchema as _o, prefix as _r, LinkRpcWireMeta as _t, LinkRpcConnection as a, componentSchemaRef as aa, KeyId as ai, zTopologyPort as an, zodToSvcJsonSchema as ao, registerLazyIdentityOnOverlay as ar, defaultInterfaceTarget as at, createSeededSigningIdentity as b, InterfaceInfo as ba, resolveSigningKey as bi, HubDirectoryGraphSnapshot as bn, IntegerSchema as bo, KeypairIdentity as br, stripLinkRpcWireMeta as bt, ServiceHandle as c, matchesJsonSchema as ca, PrincipalId as ci, zTrafficEvent as cn, isRpcFailure as co, IssueCapabilityOptions as cr, BareInterfaceTarget as ct, ServiceIdPattern as d, EXTENSION_PREFIX as da, ResolveSigningKeyArgs as di, zTrafficTransitEvent as dn, LinkRpcInterfaceSchema as do, PermitResult as dr, MuxEnvelope as dt, schemaToZod as ea, signedHash as ei, zRouteClaim as en, applicationError as eo, ManagedIdentity as er, KeepConnectedHandle as et, defaultsInterface as f, computeInterfaceHash as fa, Signature as fi, zTrafficWatchResult as fn, MemberAnnotations as fo, capBagFreshAt as fr, CallMeta as ft, zServiceIdPattern as g, InterfaceClient as ga, keyIdForPrincipal as gi, DiscoveredListing as gn, BooleanSchema as go, permits as gr, LinkRpcUnsigned as gt, schemasInterface as h, GenericRpcError as ha, bytesToBase64Url as hi, DEFAULT_WALK_DEPTH as hn, ArraySchema as ho, issueCapability as hr, LinkRpcJsonRpcRequest as ht, InterfaceRegistration as i, componentSchemaName as ia, KEY_ID_PREFIX as ii, zTopologyNode as in, rpcError as io, registerIdentityOnOverlay as ir, QualifiedInterfaceTarget as it, attachCapabilities as j, TransportRpcError as ja, SendOpts as ji, fetchDirectory as jn, ErrorCode as jo, Capability as jr, streamInterface as jt, VerifyRpcCallOptions as k, StreamCallOptions as ka, Result as ki, WalkHubOptions as kn, TupleSchema as ko, CallBind as kr, StreamDir as kt, RootPrincipalReq as l, validateJsonSchema as la, PrivateKey as li, zTrafficOverflowEvent as ln, ErrorSchema as lo, ParamMatcherFor as lr, bareInterfaceTarget as lt, directoryWatchNever as m, CheckedCallResult as ma, base64UrlToBytes as mi, exportStaticHubSchema as mn, RawErrorSchema as mo, invoke as mr, LinkRpcJsonRpcNotification as mt, GetOptions as n, materializeJsonSchema as na, signingInput as ni, zTopologyLink as nn, notificationType as no, ManagedIdentityStorageBackend as nr, DefaultInterfaceTarget as nt, LinkRpcConnectionOptions as o, Components as oa, Keypair as oi, zTopologyTransportEndpoint as on, Result$1 as oo, JsonRpcChannel as or, interfaceTarget as ot, directoryInterface as p, CheckedCall as pa, X25519Keypair as pi, ExportStaticHubSchemaOptions as pn, MethodSchema as po, capabilityFreshAt as pr, LinkRpcJsonRpcMessage as pt, parseEndpointUri as q, PublicApplicationErrorOf as qa, StaticInterfaceReference as qi, PrincipalWithStore as qn, LINKRPC_SIGNATURE_KEY as qr, TrafficTransitEndpoint as qt, InspectionRegistration as r, assertSchemaReferences as ra, withSignature as ri, zTopologyLinkEndpoint as rn, requestType as ro, createManagedIdentity as rr, InterfaceTarget as rt, RegisterOptions as s, isAssignable as sa, PRINCIPAL_PREFIX as si, zTopologyTransportInfo as sn, RpcFailure as so, AcceptedRootIssuer as sr, isInterfaceTarget as st, BareGetOptions as t, MaterializedJsonSchema as ta, signingDomainValue as ti, zTopologyGraph as tn, isApplicationErrorValue as to, ManagedIdentityStorage as tr, OnChannelConnect as tt, RootPrincipalSet as u, normalizeJsonSchema as ua, PublicKey as ui, zTrafficTransitEndpoint as un, LegacyErrorSchema as uo, ParamMatchers as ur, MultiplexedTransport as ut, createMemoryPrincipal as v, InterfaceDefinitionOpts as va, principalForPublicKey as vi, HubDirectoryExplorer as vn, DiscriminatorSchema as vo, signCapability as vr, LinkRpcWireParams as vt, VerifyResult as w, LocalRpcError as wa, IRequestSender as wi, HubDirectoryParentReport as wn, ObjectSchema as wo, SerializedKeypairSigningIdentity as wr, jcsCanonicalize as wt, JsonObject as x, InterfaceMemberRef as xa, Channel as xi, HubDirectoryGraphTarget as xn, LinkRpcJsonSchema as xo, KeypairSigningIdentity as xr, ParsedMethodName as xt, createSeededMemoryPrincipal as y, InterfaceHandlers as ya, publicKeyForKeyId as yi, HubDirectoryGraphEvent as yn, EnumSchema as yo, Identity as yr, requireObjectParams as yt, EndpointCommand as z, ApplicationErrorValue as za, connectTransports as zi, walkHubDetailed as zn, isNotification as zo, matchParams as zr, TopologyLink as zt };
|
|
4227
|
+
//# sourceMappingURL=linkRpcConnection-Bbq20hQG.d.ts.map
|