@cortexkit/subc-client 0.20.0 → 0.21.0
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 +48 -1
- package/dist/client.d.ts +21 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +73 -11
- package/dist/client.js.map +1 -1
- package/dist/connection-file.d.ts +6 -1
- package/dist/connection-file.d.ts.map +1 -1
- package/dist/connection-file.js +32 -10
- package/dist/connection-file.js.map +1 -1
- package/dist/envelope.d.ts +11 -1
- package/dist/envelope.d.ts.map +1 -1
- package/dist/envelope.js +23 -7
- package/dist/envelope.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +3 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +17 -8
- package/dist/provider.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +88 -8
- package/src/connection-file.ts +37 -10
- package/src/envelope.ts +32 -13
- package/src/index.ts +1 -0
- package/src/provider.ts +19 -7
package/README.md
CHANGED
|
@@ -78,6 +78,45 @@ fails loud with an `AuthError` rather than connecting insecurely.
|
|
|
78
78
|
- **Connection-file security.** On unix the file must be owner-only (`0600`); a
|
|
79
79
|
group/world-readable file is rejected, because the key has effectively leaked.
|
|
80
80
|
|
|
81
|
+
### Scoped routes
|
|
82
|
+
|
|
83
|
+
Use a daemon advertising `scopes/v1` and pass a selector to `routeOpen()` or to
|
|
84
|
+
managed `call()` / `callBinary()` options:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const scope = {
|
|
88
|
+
owner: { kind: "reserved", module_id: "session-owner" } as const,
|
|
89
|
+
ref: "session-1",
|
|
90
|
+
scopeEpoch: 1,
|
|
91
|
+
};
|
|
92
|
+
const route = await client.routeOpen(target, identity, { scope });
|
|
93
|
+
await client.call("provider", "echo", {}, { scope });
|
|
94
|
+
// Close only this scoped managed route, not the unscoped or another scope's route.
|
|
95
|
+
await client.closeManagedRoute(target, identity, { scope });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The daemon checks who the caller is from its own connection record, not from the request: the caller must be the module that registered the scope (its owner), or a module the owner listed as a carrier on that scope record.
|
|
99
|
+
Passing `scope` does not grant that authority: use the supervised caller's
|
|
100
|
+
`consumerIdentity` (or its default environment identity) as usual. `owner` uses
|
|
101
|
+
the existing `Principal` type; the reserved form above is the normal case, and
|
|
102
|
+
the daemon refuses other owner kinds.
|
|
103
|
+
|
|
104
|
+
The exact wire selector is
|
|
105
|
+
`scope: { owner: { kind: "reserved", module_id: "session-owner" }, ref: "session-1", scope_epoch: 1 }`.
|
|
106
|
+
With no selector, there is no `scope` key. A reserved owner's module id and the
|
|
107
|
+
ref must be non-empty strings, and `scopeEpoch` must be present and a safe
|
|
108
|
+
non-negative integer (zero is valid); invalid selectors fail locally before I/O.
|
|
109
|
+
|
|
110
|
+
Managed routes are cached separately by target, bind and consumer identities,
|
|
111
|
+
reverse capabilities, and the whole scope selector (owner, ref, epoch). Scoped
|
|
112
|
+
and unscoped calls never share a route, nor do different scopes or daemon
|
|
113
|
+
incarnations. Reconnect opens a fresh handle under the same selector.
|
|
114
|
+
`scope_not_synced` and `scope_changed` refusals retain the managed path's retries
|
|
115
|
+
within the caller's deadline. A scope-revocation close (such as `scope_ended` or
|
|
116
|
+
`scope_carrier_removed`) is terminal: neither a later managed call nor a
|
|
117
|
+
reconnect automatically reopens that cache entry. Use a new selector for a new
|
|
118
|
+
session; reload and restart close reasons still permit reopens.
|
|
119
|
+
|
|
81
120
|
### Launch nonce
|
|
82
121
|
|
|
83
122
|
A module the daemon spawns proves who it is with a launch nonce. On macOS and
|
|
@@ -115,7 +154,9 @@ the environment copy. The environment copy is read only when
|
|
|
115
154
|
## Testing
|
|
116
155
|
|
|
117
156
|
```sh
|
|
118
|
-
bun
|
|
157
|
+
bun run typecheck
|
|
158
|
+
bun test # unit/mock suite; live tests are gated by RUN_SUBC_LIVE=1
|
|
159
|
+
RUN_SUBC_LIVE=1 bun test tests/live-scoped-open.test.ts
|
|
119
160
|
```
|
|
120
161
|
|
|
121
162
|
The live-handshake tests boot the real daemon binary
|
|
@@ -124,6 +165,12 @@ byte-identity authority for this client. They skip automatically when the binary
|
|
|
124
165
|
is not built; run `cargo build -p subc-core` first (the CI lane does this; the
|
|
125
166
|
package builds the `ck-subc` executable).
|
|
126
167
|
|
|
168
|
+
The scope admission test uses the same supervised `fake-aft-stub` fixture as the
|
|
169
|
+
Rust SDK (built by `cargo build -p subc-core --bins`) to sync an owner's scope and
|
|
170
|
+
observe the real provider bind. Live helpers hard-link the daemon as
|
|
171
|
+
`ckdev-subc` inside the scratch runtime directory before spawning it, and isolate
|
|
172
|
+
all three XDG homes so tests cannot reach the operator's daemon data or config.
|
|
173
|
+
|
|
127
174
|
## Layout
|
|
128
175
|
|
|
129
176
|
| File | Responsibility |
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ConnectionInfo } from "./connection-file.js";
|
|
2
2
|
import { AdmissionClass, Priority } from "./envelope.js";
|
|
3
|
+
import type { Principal } from "./provider.js";
|
|
3
4
|
import { ReverseRequestRegistry, RouteHandle } from "./route-handle.js";
|
|
4
5
|
export declare const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
5
6
|
export declare const TIMEOUT_ARBITRATION_GRACE_MS = 50;
|
|
@@ -29,7 +30,18 @@ export interface ConsumerIdentity {
|
|
|
29
30
|
module_id: string;
|
|
30
31
|
launch_nonce: string;
|
|
31
32
|
}
|
|
33
|
+
/** A scope selector; scopeEpoch is required even for the scope's owner. */
|
|
34
|
+
export interface RouteScope {
|
|
35
|
+
/** Owner principal, passed verbatim. The daemon decides which principal kinds may own scopes. */
|
|
36
|
+
owner: Principal;
|
|
37
|
+
/** Opaque, non-empty ref within the owner. */
|
|
38
|
+
ref: string;
|
|
39
|
+
/** Safe non-negative integer, including zero; serialized as scope_epoch. */
|
|
40
|
+
scopeEpoch: number;
|
|
41
|
+
}
|
|
32
42
|
export interface RouteOpenOptions {
|
|
43
|
+
/** Open under this scope. The caller must be its owner or a listed carrier; use a daemon advertising scopes/v1. Serialized as { owner, ref, scope_epoch }. */
|
|
44
|
+
scope?: RouteScope;
|
|
33
45
|
/** Optional override for the consumer identity; by default the SUBC_MODULE_ID environment variable and the process's launch nonce (see `launchNonce`) are used when both are non-empty; a refused launch-nonce descriptor counts as no nonce. Set null to send route.open without consumer_identity. */
|
|
34
46
|
consumerIdentity?: ConsumerIdentity | null;
|
|
35
47
|
/**
|
|
@@ -113,6 +125,8 @@ export interface RequestOptions {
|
|
|
113
125
|
signal?: AbortSignal;
|
|
114
126
|
}
|
|
115
127
|
export interface ManagedCallOptions extends RequestOptions {
|
|
128
|
+
/** Scope for the cached route and its reconnect reopens. The caller must be the scope's owner or a listed carrier; use a daemon advertising scopes/v1. Each owner/ref/epoch has a separate cache entry. */
|
|
129
|
+
scope?: RouteScope;
|
|
116
130
|
/** Overrides the per-client identity used for route.open before this call. */
|
|
117
131
|
identity?: BindIdentity;
|
|
118
132
|
/** Defaults to management_surface, matching the store/host management APIs. */
|
|
@@ -142,6 +156,8 @@ export interface CloseRouteOptions {
|
|
|
142
156
|
drain?: boolean;
|
|
143
157
|
}
|
|
144
158
|
export interface ManagedCloseRouteOptions extends CloseRouteOptions {
|
|
159
|
+
/** Scope selector used by the cached managed route; omitted selects only an unscoped route. */
|
|
160
|
+
scope?: RouteScope;
|
|
145
161
|
/** Consumer identity used by the cached managed route. */
|
|
146
162
|
consumerIdentity?: ConsumerIdentity | null;
|
|
147
163
|
/** The registry whose derived capability set identifies the cached route. */
|
|
@@ -343,6 +359,7 @@ export declare class SubcClient {
|
|
|
343
359
|
* Open a route and return its connection-bound immutable handle. At most
|
|
344
360
|
* MAX_ROUTE_OPENS_IN_FLIGHT opens are outstanding at once; further calls wait
|
|
345
361
|
* their turn.
|
|
362
|
+
* A scoped open requires the caller to be the scope's owner or a listed carrier.
|
|
346
363
|
*/
|
|
347
364
|
routeOpen(target: RouteTarget, identity: BindIdentity, opts?: RouteOpenOptions): Promise<RouteHandle>;
|
|
348
365
|
/** One route.open exchange. The caller holds a route-open gate slot. */
|
|
@@ -352,6 +369,8 @@ export declare class SubcClient {
|
|
|
352
369
|
/**
|
|
353
370
|
* Managed route + request convenience. Opens and caches a route for the module,
|
|
354
371
|
* reconnecting and re-opening cached routes after connection drops.
|
|
372
|
+
* Scoped routes are isolated by owner/ref/epoch and require owner or carrier authority.
|
|
373
|
+
* Terminal scope close reasons prevent automatic reopens under the same selector.
|
|
355
374
|
*/
|
|
356
375
|
call<Response = unknown>(moduleId: string, method: string, params?: unknown, opts?: ManagedCallOptions): Promise<Response>;
|
|
357
376
|
/**
|
|
@@ -464,6 +483,7 @@ export declare class SubcClient {
|
|
|
464
483
|
private reopenCachedRoutes;
|
|
465
484
|
private timeoutMessage;
|
|
466
485
|
private routeClosedDuringOpen;
|
|
486
|
+
private endedCachedRoute;
|
|
467
487
|
private readLoop;
|
|
468
488
|
private dispatch;
|
|
469
489
|
/**
|
|
@@ -483,6 +503,7 @@ export declare class SubcClient {
|
|
|
483
503
|
private errorFromFrame;
|
|
484
504
|
private evictRouteHandle;
|
|
485
505
|
private recordRouteEnd;
|
|
506
|
+
private preventRouteReopen;
|
|
486
507
|
private routeEndReason;
|
|
487
508
|
private failHandle;
|
|
488
509
|
private fail;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -346,12 +346,14 @@ export class SubcClient {
|
|
|
346
346
|
* Open a route and return its connection-bound immutable handle. At most
|
|
347
347
|
* MAX_ROUTE_OPENS_IN_FLIGHT opens are outstanding at once; further calls wait
|
|
348
348
|
* their turn.
|
|
349
|
+
* A scoped open requires the caller to be the scope's owner or a listed carrier.
|
|
349
350
|
*/
|
|
350
351
|
async routeOpen(target, identity, opts = {}) {
|
|
352
|
+
const scope = validatedRouteScope(opts.scope);
|
|
351
353
|
// Without a timeout the gate always grants a slot eventually.
|
|
352
354
|
const release = (await this.routeOpenGate.acquire());
|
|
353
355
|
try {
|
|
354
|
-
return await this.sendRouteOpen(target, identity, opts);
|
|
356
|
+
return await this.sendRouteOpen(target, identity, { ...opts, scope });
|
|
355
357
|
}
|
|
356
358
|
finally {
|
|
357
359
|
release();
|
|
@@ -359,6 +361,7 @@ export class SubcClient {
|
|
|
359
361
|
}
|
|
360
362
|
/** One route.open exchange. The caller holds a route-open gate slot. */
|
|
361
363
|
async sendRouteOpen(target, identity, opts = {}) {
|
|
364
|
+
const scope = validatedRouteScope(opts.scope);
|
|
362
365
|
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
363
366
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry();
|
|
364
367
|
reverseRequests.seal();
|
|
@@ -369,6 +372,7 @@ export class SubcClient {
|
|
|
369
372
|
identity,
|
|
370
373
|
...(consumerIdentity ? { consumer_identity: consumerIdentity } : {}),
|
|
371
374
|
...(consumerCapabilities.length > 0 ? { consumer_capabilities: consumerCapabilities } : {}),
|
|
375
|
+
...(scope ? { scope: { owner: scope.owner, ref: scope.ref, scope_epoch: scope.scopeEpoch } } : {}),
|
|
372
376
|
});
|
|
373
377
|
let installed = null;
|
|
374
378
|
const install = (frame) => {
|
|
@@ -416,6 +420,8 @@ export class SubcClient {
|
|
|
416
420
|
/**
|
|
417
421
|
* Managed route + request convenience. Opens and caches a route for the module,
|
|
418
422
|
* reconnecting and re-opening cached routes after connection drops.
|
|
423
|
+
* Scoped routes are isolated by owner/ref/epoch and require owner or carrier authority.
|
|
424
|
+
* Terminal scope close reasons prevent automatic reopens under the same selector.
|
|
419
425
|
*/
|
|
420
426
|
async call(moduleId, method, params, opts = {}) {
|
|
421
427
|
if (opts.binary) {
|
|
@@ -637,7 +643,7 @@ export class SubcClient {
|
|
|
637
643
|
}
|
|
638
644
|
/** Close a cached managed route by its route-open identity tuple. */
|
|
639
645
|
async closeManagedRoute(target, identity, opts = {}) {
|
|
640
|
-
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry()).capabilities());
|
|
646
|
+
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry()).capabilities(), validatedRouteScope(opts.scope));
|
|
641
647
|
const cached = this.routes.get(key);
|
|
642
648
|
if (!cached)
|
|
643
649
|
return;
|
|
@@ -734,13 +740,15 @@ export class SubcClient {
|
|
|
734
740
|
};
|
|
735
741
|
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
736
742
|
this.pending.set(key, pending);
|
|
737
|
-
if (signal)
|
|
738
|
-
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
739
743
|
writeBorrowed(this.sock, encodeFrame(frame), Date.now() + ms).catch((error) => {
|
|
740
744
|
const current = this.pending.get(key);
|
|
741
745
|
if (current)
|
|
742
746
|
this.rejectPending(key, current, error instanceof Error ? error : new SubcError(String(error)));
|
|
743
747
|
});
|
|
748
|
+
// Queue REQUEST first: an already-aborted signal emits CANCEL immediately,
|
|
749
|
+
// and the daemon can only cancel a correlation it has already received.
|
|
750
|
+
if (signal)
|
|
751
|
+
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
744
752
|
});
|
|
745
753
|
}
|
|
746
754
|
/**
|
|
@@ -832,8 +840,6 @@ export class SubcClient {
|
|
|
832
840
|
};
|
|
833
841
|
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
|
|
834
842
|
this.pending.set(key, pending);
|
|
835
|
-
if (signal)
|
|
836
|
-
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
837
843
|
const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
|
|
838
844
|
handedToSocket = write.queued;
|
|
839
845
|
write.completed.catch((error) => {
|
|
@@ -841,9 +847,13 @@ export class SubcClient {
|
|
|
841
847
|
if (current)
|
|
842
848
|
this.rejectPending(key, current, error instanceof Error ? error : new SubcError(String(error)));
|
|
843
849
|
});
|
|
850
|
+
// Preserve REQUEST/CANCEL order even when the signal was already aborted.
|
|
851
|
+
if (signal && write.queued)
|
|
852
|
+
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
844
853
|
});
|
|
845
854
|
}
|
|
846
855
|
async cachedRouteHandle(moduleId, opts) {
|
|
856
|
+
const scope = validatedRouteScope(opts.scope);
|
|
847
857
|
const identity = opts.identity ?? this.opts.identity;
|
|
848
858
|
if (!identity) {
|
|
849
859
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
@@ -852,7 +862,7 @@ export class SubcClient {
|
|
|
852
862
|
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
853
863
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry();
|
|
854
864
|
reverseRequests.seal();
|
|
855
|
-
const key = routeCacheKey(target, identity, consumerIdentity, reverseRequests.capabilities());
|
|
865
|
+
const key = routeCacheKey(target, identity, consumerIdentity, reverseRequests.capabilities(), scope);
|
|
856
866
|
let cached = this.routes.get(key);
|
|
857
867
|
if (!cached) {
|
|
858
868
|
cached = {
|
|
@@ -860,6 +870,7 @@ export class SubcClient {
|
|
|
860
870
|
moduleId,
|
|
861
871
|
target,
|
|
862
872
|
identity,
|
|
873
|
+
scope,
|
|
863
874
|
consumerIdentity,
|
|
864
875
|
reverseRequests,
|
|
865
876
|
handle: null,
|
|
@@ -867,6 +878,8 @@ export class SubcClient {
|
|
|
867
878
|
};
|
|
868
879
|
this.routes.set(key, cached);
|
|
869
880
|
}
|
|
881
|
+
if (cached.endReason !== undefined)
|
|
882
|
+
throw this.endedCachedRoute(cached.endReason);
|
|
870
883
|
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
871
884
|
return cached.handle;
|
|
872
885
|
// The retries end at the retry deadline or at the call's own timeoutMs,
|
|
@@ -907,6 +920,8 @@ export class SubcClient {
|
|
|
907
920
|
for (;;) {
|
|
908
921
|
if (cached.closed)
|
|
909
922
|
throw this.routeClosedDuringOpen();
|
|
923
|
+
if (cached.endReason !== undefined)
|
|
924
|
+
throw this.endedCachedRoute(cached.endReason);
|
|
910
925
|
try {
|
|
911
926
|
await this.ensureConnectedForManaged();
|
|
912
927
|
}
|
|
@@ -923,6 +938,7 @@ export class SubcClient {
|
|
|
923
938
|
try {
|
|
924
939
|
outcome = {
|
|
925
940
|
handle: await this.sendRouteOpen(cached.target, cached.identity, {
|
|
941
|
+
scope: cached.scope,
|
|
926
942
|
consumerIdentity: cached.consumerIdentity ?? null,
|
|
927
943
|
reverseRequests: cached.reverseRequests,
|
|
928
944
|
}),
|
|
@@ -1168,10 +1184,11 @@ export class SubcClient {
|
|
|
1168
1184
|
}
|
|
1169
1185
|
for (const key of routeKeys) {
|
|
1170
1186
|
const cached = this.routes.get(key);
|
|
1171
|
-
if (!cached || cached.closed)
|
|
1187
|
+
if (!cached || cached.closed || cached.endReason !== undefined)
|
|
1172
1188
|
continue;
|
|
1173
1189
|
try {
|
|
1174
1190
|
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
1191
|
+
scope: cached.scope,
|
|
1175
1192
|
consumerIdentity: cached.consumerIdentity ?? null,
|
|
1176
1193
|
reverseRequests: cached.reverseRequests,
|
|
1177
1194
|
});
|
|
@@ -1204,6 +1221,10 @@ export class SubcClient {
|
|
|
1204
1221
|
const cause = new SubcError("route was closed before route.open completed", "route_closed", undefined, "closed_by_caller");
|
|
1205
1222
|
return new SubcCallError("not_sent", cause.message, cause.code, cause);
|
|
1206
1223
|
}
|
|
1224
|
+
endedCachedRoute(reason) {
|
|
1225
|
+
const cause = new SubcError(`cached route closed by subc (${reason}); must not reopen`, "route_closed", undefined, reason);
|
|
1226
|
+
return this.terminalCallError(cause.message, cause);
|
|
1227
|
+
}
|
|
1207
1228
|
async readLoop(sock, generation) {
|
|
1208
1229
|
try {
|
|
1209
1230
|
for (;;) {
|
|
@@ -1342,6 +1363,7 @@ export class SubcClient {
|
|
|
1342
1363
|
// drop, and never the not_sent/unknown_channel class that call() retries.
|
|
1343
1364
|
// The code says WHICH route ended, not that it is safe to send again.
|
|
1344
1365
|
this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)", "route_closed", undefined, this.routeEndReason(handle.channel)));
|
|
1366
|
+
this.preventRouteReopen(handle.channel, this.routeEndReason(handle.channel));
|
|
1345
1367
|
if (this.liveRoutes.get(handle.channel) === handle)
|
|
1346
1368
|
this.liveRoutes.delete(handle.channel);
|
|
1347
1369
|
this.evictRouteHandle(handle);
|
|
@@ -1464,17 +1486,30 @@ export class SubcClient {
|
|
|
1464
1486
|
const final = push.op === "route.closed";
|
|
1465
1487
|
if (final || !this.routeEndReasons.get(channel)?.final) {
|
|
1466
1488
|
this.routeEndReasons.set(channel, { reason, final });
|
|
1489
|
+
if (final)
|
|
1490
|
+
this.preventRouteReopen(channel, reason);
|
|
1467
1491
|
}
|
|
1468
1492
|
}
|
|
1469
1493
|
}
|
|
1470
1494
|
}
|
|
1471
1495
|
else if (typeof push.body.module_id === "string") {
|
|
1472
1496
|
for (const [channel, module] of this.routeModules) {
|
|
1473
|
-
if (module === push.body.module_id)
|
|
1497
|
+
if (module === push.body.module_id) {
|
|
1474
1498
|
this.legacyChannelReasons.set(channel, reason);
|
|
1499
|
+
if (push.op === "route.closed")
|
|
1500
|
+
this.preventRouteReopen(channel, reason);
|
|
1501
|
+
}
|
|
1475
1502
|
}
|
|
1476
1503
|
}
|
|
1477
1504
|
}
|
|
1505
|
+
preventRouteReopen(channel, reason) {
|
|
1506
|
+
if (classifyRouteCloseReason(reason) !== "must_not_reopen")
|
|
1507
|
+
return;
|
|
1508
|
+
for (const cached of this.routes.values()) {
|
|
1509
|
+
if (cached.handle?.channel === channel)
|
|
1510
|
+
cached.endReason = reason;
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1478
1513
|
routeEndReason(channel) {
|
|
1479
1514
|
const specific = this.routeEndReasons.get(channel);
|
|
1480
1515
|
if (specific)
|
|
@@ -1623,6 +1658,9 @@ export function isRetryableRouteOpenCode(code) {
|
|
|
1623
1658
|
// A capability deny is policy, never a transient target-availability failure.
|
|
1624
1659
|
if (code === "capability_forbidden")
|
|
1625
1660
|
return false;
|
|
1661
|
+
// Decoding a flow stamp alone does not promise flow behaviour.
|
|
1662
|
+
if (code === "target_flow_unsupported")
|
|
1663
|
+
return false;
|
|
1626
1664
|
return (code === "module_reloading" ||
|
|
1627
1665
|
code === "module_warming" ||
|
|
1628
1666
|
code === "target_unavailable" ||
|
|
@@ -1739,12 +1777,36 @@ export function isValidCapabilityIdentifier(identifier) {
|
|
|
1739
1777
|
const numericVersion = Number(version);
|
|
1740
1778
|
return Number.isSafeInteger(numericVersion) && numericVersion >= 1 && numericVersion <= 0xffff_ffff;
|
|
1741
1779
|
}
|
|
1742
|
-
function routeCacheKey(target, identity, consumerIdentity, consumerCapabilities) {
|
|
1780
|
+
function routeCacheKey(target, identity, consumerIdentity, consumerCapabilities, scope) {
|
|
1743
1781
|
const consumerPart = consumerIdentity
|
|
1744
1782
|
? `${consumerIdentity.module_id}\0${consumerIdentity.launch_nonce}`
|
|
1745
1783
|
: "";
|
|
1746
1784
|
const capabilitiesPart = [...consumerCapabilities].sort().join("\0");
|
|
1747
|
-
|
|
1785
|
+
// A JSON tuple keeps opaque refs (including embedded separators) distinct.
|
|
1786
|
+
const scopePart = scope
|
|
1787
|
+
? JSON.stringify([scope.owner.kind, scope.owner.kind === "reserved" ? scope.owner.module_id : null, scope.ref, scope.scopeEpoch])
|
|
1788
|
+
: "";
|
|
1789
|
+
return `${target.kind}\0${target.module_id}\0${identity.project_root}\0${identity.harness}\0${identity.session}\0${consumerPart}\0${capabilitiesPart}\0${scopePart}`;
|
|
1790
|
+
}
|
|
1791
|
+
/** Validate before any route-open I/O, and snapshot caller-owned mutable values for reopens. */
|
|
1792
|
+
function validatedRouteScope(scope) {
|
|
1793
|
+
if (scope === undefined)
|
|
1794
|
+
return undefined;
|
|
1795
|
+
if (!scope || typeof scope.owner !== "object" || !scope.owner ||
|
|
1796
|
+
!["reserved", "direct", "unverified"].includes(scope.owner.kind) ||
|
|
1797
|
+
(scope.owner.kind === "reserved" && (typeof scope.owner.module_id !== "string" || scope.owner.module_id.length === 0))) {
|
|
1798
|
+
throw new SubcError("scope.owner must be a Principal with a non-empty reserved module_id", "invalid_scope");
|
|
1799
|
+
}
|
|
1800
|
+
if (typeof scope.ref !== "string" || scope.ref.length === 0) {
|
|
1801
|
+
throw new SubcError("scope.ref must be a non-empty string", "invalid_scope");
|
|
1802
|
+
}
|
|
1803
|
+
if (scope.scopeEpoch === undefined) {
|
|
1804
|
+
throw new SubcError("scope.scopeEpoch is required", "scope_epoch_required");
|
|
1805
|
+
}
|
|
1806
|
+
if (!Number.isSafeInteger(scope.scopeEpoch) || scope.scopeEpoch < 0) {
|
|
1807
|
+
throw new SubcError("scope.scopeEpoch must be a safe non-negative integer", "invalid_scope");
|
|
1808
|
+
}
|
|
1809
|
+
return { owner: { ...scope.owner }, ref: scope.ref, scopeEpoch: scope.scopeEpoch };
|
|
1748
1810
|
}
|
|
1749
1811
|
function routeOpenConsumerIdentity(opts = {}) {
|
|
1750
1812
|
if (opts.consumerIdentity !== undefined)
|