@procedures/client 0.52.1 → 0.52.3
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/CHANGELOG.md +18 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/client/batch.d.ts.map +1 -1
- package/dist/adapters/http/client/batch.js +9 -5
- package/dist/adapters/http/client/batch.js.map +1 -1
- package/dist/events/bus.d.ts +7 -0
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +22 -4
- package/dist/events/bus.js.map +1 -1
- package/dist/events/publisher.d.ts.map +1 -1
- package/dist/events/publisher.js +4 -3
- package/dist/events/publisher.js.map +1 -1
- package/dist/frame-encoding.d.ts +8 -5
- package/dist/frame-encoding.d.ts.map +1 -1
- package/dist/frame-encoding.js +13 -8
- package/dist/frame-encoding.js.map +1 -1
- package/dist/procedures/module.d.ts.map +1 -1
- package/dist/procedures/module.js +7 -2
- package/dist/procedures/module.js.map +1 -1
- package/dist/server/host-policy.d.ts.map +1 -1
- package/dist/server/host-policy.js +12 -2
- package/dist/server/host-policy.js.map +1 -1
- package/dist/server/procedure-server.d.ts +9 -1
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +33 -3
- package/dist/server/procedure-server.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/http/client/batch.ts +8 -5
- package/src/events/bus.ts +25 -4
- package/src/events/publisher.ts +6 -3
- package/src/frame-encoding.ts +15 -8
- package/src/procedures/module.ts +10 -2
- package/src/server/host-policy.ts +13 -2
- package/src/server/procedure-server.ts +33 -4
|
@@ -59,11 +59,22 @@ export function exposePatterns(patterns: readonly string[]): (path: ProcedurePat
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* This function tells if a list of excluded keys names a path. An entry can be the key of the path
|
|
64
|
+
* (`collections.e2e%2Etabs.delete`) or its segments joined with plain dots
|
|
65
|
+
* (`collections.e2e.tabs.delete`), the form before CLI-75. So an exclusion of the old form still
|
|
66
|
+
* hides its procedure (audit 2026-11-08). The plain form can hide one more path, but not one less.
|
|
67
|
+
*/
|
|
68
|
+
function isExcluded(excluded: ReadonlySet<string>, path: ProcedurePath): boolean {
|
|
69
|
+
// path-check: the raw form of an exclude entry before CLI-75, compared as text, not decoded.
|
|
70
|
+
return excluded.has(pathToKey(path)) || excluded.has(path.join("."));
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
/** The rule of a tool surface: the namespaces, less the excluded keys. */
|
|
63
74
|
export function surfaceRule(surface: ToolSurface): (path: ProcedurePath) => boolean {
|
|
64
75
|
const namespaces = new Set(surface.namespaces);
|
|
65
76
|
const excluded = new Set(surface.exclude ?? []);
|
|
66
|
-
return (path) => namespaces.has(path[0] ?? "") && !excluded
|
|
77
|
+
return (path) => namespaces.has(path[0] ?? "") && !isExcluded(excluded, path);
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
/** The options of `hostPolicy()`. */
|
|
@@ -163,7 +174,7 @@ function exposeOf(options: HostPolicyOptions): ((path: ProcedurePath) => boolean
|
|
|
163
174
|
: surfaceRule(expose as ToolSurface);
|
|
164
175
|
const excluded = new Set(options.exclude ?? []);
|
|
165
176
|
if (excluded.size === 0) return rule;
|
|
166
|
-
return (path) => !excluded
|
|
177
|
+
return (path) => !isExcluded(excluded, path) && (rule ? rule(path) : true);
|
|
167
178
|
}
|
|
168
179
|
|
|
169
180
|
/** This function builds the policy of a host from its options. */
|
|
@@ -460,6 +460,11 @@ export class ProcedureServer extends Server implements RepositoryProvider, StopP
|
|
|
460
460
|
* that `admission()` gave. Only this server adds an entry, so a request cannot claim one.
|
|
461
461
|
*/
|
|
462
462
|
private readonly admissions = new WeakMap<Credentials, { readonly principal: Principal | undefined; readonly narrowing: ServerRequest<unknown>["narrowing"] }>();
|
|
463
|
+
/**
|
|
464
|
+
* The admission of each request object. The late lookup of a lazy registry admits a request
|
|
465
|
+
* before it loads packages, and the call of the same request uses that result again.
|
|
466
|
+
*/
|
|
467
|
+
private readonly admitted = new WeakMap<ServerRequest<unknown>, Promise<ServerResponse<unknown> | undefined>>();
|
|
463
468
|
/** The functions that `drain()` waits on: each one runs when no call is in flight */
|
|
464
469
|
private idleWaiters: Array<() => void> = [];
|
|
465
470
|
/** The publisher of the remote events, from the option `events`, or undefined. */
|
|
@@ -847,7 +852,20 @@ export class ProcedureServer extends Server implements RepositoryProvider, StopP
|
|
|
847
852
|
*/
|
|
848
853
|
protected override findLateHandler(method: Method, request: ServerRequest<unknown>): Promise<ServerHandler | null> | null {
|
|
849
854
|
if (!this.servesRegistry || !this.procedureRegistry.lazy) return null;
|
|
850
|
-
|
|
855
|
+
const path = methodToPath(method);
|
|
856
|
+
// A path outside the expose rule of the face loads nothing, as findHandler() gives it no handler
|
|
857
|
+
if (request.expose !== undefined) {
|
|
858
|
+
const rule: unknown = request.expose;
|
|
859
|
+
if (typeof rule !== "function" || rule(path) !== true) return null;
|
|
860
|
+
}
|
|
861
|
+
return (async (): Promise<ServerHandler | null> => {
|
|
862
|
+
// Only an admitted request loads packages (audit 2026-11-08). Before, a caller with no
|
|
863
|
+
// credentials loaded packages, and got the load errors of the packages.
|
|
864
|
+
const refusal = await this.admit(request);
|
|
865
|
+
if (refusal) return () => Promise.resolve(refusal);
|
|
866
|
+
await this.procedureRegistry.resolve(path);
|
|
867
|
+
return this.findHandler(method, request);
|
|
868
|
+
})();
|
|
851
869
|
}
|
|
852
870
|
|
|
853
871
|
/**
|
|
@@ -896,9 +914,20 @@ export class ProcedureServer extends Server implements RepositoryProvider, StopP
|
|
|
896
914
|
* request hook refuses it, and the hook does not run (CLI-1). The authenticate function gives
|
|
897
915
|
* the principal. The credentials of an admission of this server (`admission()`) skip the
|
|
898
916
|
* checks: the request gets the principal and the narrowing of that admission (CLI-2b). The
|
|
899
|
-
* function gives an UNAUTHORIZED response, or undefined when the request passes.
|
|
900
|
-
|
|
901
|
-
|
|
917
|
+
* function gives an UNAUTHORIZED response, or undefined when the request passes. The checks
|
|
918
|
+
* run one time for each request object.
|
|
919
|
+
*/
|
|
920
|
+
private admit(request: ServerRequest<unknown>): Promise<ServerResponse<unknown> | undefined> {
|
|
921
|
+
let result = this.admitted.get(request);
|
|
922
|
+
if (result === undefined) {
|
|
923
|
+
result = this.checkRequest(request);
|
|
924
|
+
this.admitted.set(request, result);
|
|
925
|
+
}
|
|
926
|
+
return result;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/** The checks of `admit()` for one request object. */
|
|
930
|
+
private async checkRequest(request: ServerRequest<unknown>): Promise<ServerResponse<unknown> | undefined> {
|
|
902
931
|
const unauthorized = (message: string): ServerResponse<unknown> => ({
|
|
903
932
|
id: request.id,
|
|
904
933
|
status: { type: "error", code: "UNAUTHORIZED", message, retryable: false },
|