@stigmer/server 3.23.1-dev.20260923075205 → 3.25.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/dist/authorization/authorizer.d.ts +10 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +11 -4
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -4
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +2 -0
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/oauth_app.d.ts.map +1 -1
- package/dist/authorization/model/oauth_app.js +3 -2
- package/dist/authorization/model/oauth_app.js.map +1 -1
- package/dist/authorization/model/platform_client.d.ts +2 -0
- package/dist/authorization/model/platform_client.d.ts.map +1 -0
- package/dist/authorization/model/platform_client.js +31 -0
- package/dist/authorization/model/platform_client.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +88 -5
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/route-shadowing.d.ts +25 -0
- package/dist/boot/route-shadowing.d.ts.map +1 -0
- package/dist/boot/route-shadowing.js +17 -0
- package/dist/boot/route-shadowing.js.map +1 -0
- package/dist/domain/iampolicy/membership.d.ts +6 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +8 -2
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +13 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts +3 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +15 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/operator.d.ts.map +1 -1
- package/dist/domain/identityaccount/operator.js +1 -0
- package/dist/domain/identityaccount/operator.js.map +1 -1
- package/dist/domain/identityaccount/provisioning.d.ts +18 -0
- package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
- package/dist/domain/identityaccount/provisioning.js +1 -0
- package/dist/domain/identityaccount/provisioning.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +9 -5
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +11 -2
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +42 -4
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +33 -0
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +7 -5
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/identityaccount/store.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +10 -0
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js +2 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +60 -0
- package/dist/domain/platformclient/constants.d.ts.map +1 -0
- package/dist/domain/platformclient/constants.js +78 -0
- package/dist/domain/platformclient/constants.js.map +1 -0
- package/dist/domain/platformclient/controller.d.ts +59 -0
- package/dist/domain/platformclient/controller.d.ts.map +1 -0
- package/dist/domain/platformclient/controller.js +191 -0
- package/dist/domain/platformclient/controller.js.map +1 -0
- package/dist/domain/platformclient/credentials.d.ts +13 -0
- package/dist/domain/platformclient/credentials.d.ts.map +1 -0
- package/dist/domain/platformclient/credentials.js +56 -0
- package/dist/domain/platformclient/credentials.js.map +1 -0
- package/dist/domain/platformclient/mint.d.ts +23 -0
- package/dist/domain/platformclient/mint.d.ts.map +1 -0
- package/dist/domain/platformclient/mint.js +254 -0
- package/dist/domain/platformclient/mint.js.map +1 -0
- package/dist/domain/platformclient/origin-guard.d.ts +9 -0
- package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
- package/dist/domain/platformclient/origin-guard.js +81 -0
- package/dist/domain/platformclient/origin-guard.js.map +1 -0
- package/dist/domain/platformclient/resource-store.d.ts +4 -0
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
- package/dist/domain/platformclient/resource-store.js +117 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -0
- package/dist/domain/platformclient/steps.d.ts +51 -0
- package/dist/domain/platformclient/steps.d.ts.map +1 -0
- package/dist/domain/platformclient/steps.js +339 -0
- package/dist/domain/platformclient/steps.js.map +1 -0
- package/dist/domain/platformclient/store-contract.d.ts +8 -0
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
- package/dist/domain/platformclient/store-contract.js +208 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -0
- package/dist/domain/platformclient/store.d.ts +58 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -0
- package/dist/domain/platformclient/store.js +13 -0
- package/dist/domain/platformclient/store.js.map +1 -0
- package/dist/domain/platformclient/system-managed.d.ts +18 -0
- package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
- package/dist/domain/platformclient/system-managed.js +80 -0
- package/dist/domain/platformclient/system-managed.js.map +1 -0
- package/dist/domain/platformclient/token-controller.d.ts +11 -0
- package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
- package/dist/domain/platformclient/token-controller.js +32 -0
- package/dist/domain/platformclient/token-controller.js.map +1 -0
- package/dist/domain/platformclient/verifier.d.ts +10 -0
- package/dist/domain/platformclient/verifier.d.ts.map +1 -0
- package/dist/domain/platformclient/verifier.js +76 -0
- package/dist/domain/platformclient/verifier.js.map +1 -0
- package/dist/domain/workflow/agent-call-references.d.ts +60 -33
- package/dist/domain/workflow/agent-call-references.d.ts.map +1 -1
- package/dist/domain/workflow/agent-call-references.js +43 -23
- package/dist/domain/workflow/agent-call-references.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +2 -2
- package/dist/encryption/key-manager.d.ts +20 -3
- package/dist/encryption/key-manager.d.ts.map +1 -1
- package/dist/encryption/key-manager.js +64 -42
- package/dist/encryption/key-manager.js.map +1 -1
- package/dist/extensions/caller-guards.d.ts +8 -3
- package/dist/extensions/caller-guards.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +37 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/guest-token-minting.d.ts +26 -0
- package/dist/extensions/guest-token-minting.d.ts.map +1 -0
- package/dist/extensions/guest-token-minting.js +2 -0
- package/dist/extensions/guest-token-minting.js.map +1 -0
- package/dist/extensions/identity.d.ts +6 -4
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/registry.d.ts +30 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +34 -1
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-labels.d.ts +10 -9
- package/dist/pipeline/apiresource-labels.d.ts.map +1 -1
- package/dist/pipeline/apiresource-labels.js +10 -9
- package/dist/pipeline/apiresource-labels.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +14 -0
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +24 -0
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/build-update-state.d.ts +11 -1
- package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
- package/dist/pipeline/steps/build-update-state.js +5 -2
- package/dist/pipeline/steps/build-update-state.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +30 -4
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +13 -1
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/platformtoken/envelope.d.ts +100 -0
- package/dist/platformtoken/envelope.d.ts.map +1 -0
- package/dist/platformtoken/envelope.js +184 -0
- package/dist/platformtoken/envelope.js.map +1 -0
- package/dist/platformtoken/key-ring.d.ts +85 -0
- package/dist/platformtoken/key-ring.d.ts.map +1 -0
- package/dist/platformtoken/key-ring.js +164 -0
- package/dist/platformtoken/key-ring.js.map +1 -0
- package/package.json +6 -6
- package/src/authorization/README.md +1 -1
- package/src/authorization/__tests__/authorizer.test.ts +6 -2
- package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
- package/src/authorization/authorizer.ts +11 -4
- package/src/authorization/model/__tests__/registry.test.ts +8 -1
- package/src/authorization/model/index.ts +6 -4
- package/src/authorization/model/oauth_app.ts +3 -2
- package/src/authorization/model/platform_client.ts +43 -0
- package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
- package/src/boot/__tests__/route-shadowing.test.ts +67 -0
- package/src/boot/compose.ts +90 -5
- package/src/boot/route-shadowing.ts +47 -0
- package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
- package/src/domain/iampolicy/membership.ts +8 -2
- package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +16 -4
- package/src/domain/identityaccount/operator.ts +1 -0
- package/src/domain/identityaccount/provisioning.ts +17 -0
- package/src/domain/identityaccount/resource-store.ts +9 -5
- package/src/domain/identityaccount/steps.ts +58 -3
- package/src/domain/identityaccount/store-contract.ts +51 -0
- package/src/domain/identityaccount/store.ts +7 -5
- package/src/domain/platform/__tests__/platform.test.ts +7 -1
- package/src/domain/platform/controller.ts +12 -1
- package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
- package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
- package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
- package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
- package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
- package/src/domain/platformclient/constants.ts +120 -0
- package/src/domain/platformclient/controller.ts +449 -0
- package/src/domain/platformclient/credentials.ts +68 -0
- package/src/domain/platformclient/mint.ts +412 -0
- package/src/domain/platformclient/origin-guard.ts +117 -0
- package/src/domain/platformclient/resource-store.ts +150 -0
- package/src/domain/platformclient/steps.ts +472 -0
- package/src/domain/platformclient/store-contract.ts +318 -0
- package/src/domain/platformclient/store.ts +63 -0
- package/src/domain/platformclient/system-managed.ts +115 -0
- package/src/domain/platformclient/token-controller.ts +49 -0
- package/src/domain/platformclient/verifier.ts +106 -0
- package/src/domain/workflow/__tests__/agent-call-references.test.ts +178 -27
- package/src/domain/workflow/agent-call-references.ts +95 -48
- package/src/domain/workflow/registry/data/task-kind-registry.json +2 -2
- package/src/encryption/key-manager.ts +87 -44
- package/src/extensions/__tests__/extension-composition.test.ts +3 -2
- package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
- package/src/extensions/__tests__/registry.test.ts +4 -1
- package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
- package/src/extensions/caller-guards.ts +8 -3
- package/src/extensions/drivers.ts +37 -0
- package/src/extensions/guest-token-minting.ts +32 -0
- package/src/extensions/identity.ts +6 -4
- package/src/extensions/registry.ts +77 -3
- package/src/index.ts +55 -0
- package/src/pipeline/apiresource-labels.ts +10 -9
- package/src/pipeline/interceptors/auth.ts +27 -0
- package/src/pipeline/steps/__tests__/references.test.ts +37 -1
- package/src/pipeline/steps/build-update-state.ts +5 -2
- package/src/pipeline/steps/references.ts +49 -5
- package/src/platformtoken/__tests__/envelope.test.ts +277 -0
- package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
- package/src/platformtoken/envelope.ts +276 -0
- package/src/platformtoken/key-ring.ts +266 -0
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +9 -3
|
@@ -49,9 +49,12 @@ import { BUILT_IN_STORAGE_TYPES } from "../artifactstorage/artifact-storage.js";
|
|
|
49
49
|
import type { ChannelRuntime } from "../domain/agentchannel/channel-runtime.js";
|
|
50
50
|
import type { IdentityAccountStore } from "../domain/identityaccount/store.js";
|
|
51
51
|
import type { IamPolicyStore } from "../domain/iampolicy/store.js";
|
|
52
|
+
import type { PlatformClientStore } from "../domain/platformclient/store.js";
|
|
52
53
|
import type { SecretCodec } from "../encryption/codec.js";
|
|
53
54
|
import { V1_VERSION } from "../encryption/v1-codec.js";
|
|
55
|
+
import type { PlatformTokenKeyRing } from "../platformtoken/key-ring.js";
|
|
54
56
|
import type { AuthorizationQueryEngine } from "./authorization-queries.js";
|
|
57
|
+
import type { GuestTokenMinting } from "./guest-token-minting.js";
|
|
55
58
|
import type { IdentityFederation } from "./identity-federation.js";
|
|
56
59
|
import type { LicenseStatusProvider } from "./license-status.js";
|
|
57
60
|
import type { OutboundEgressPolicy } from "./outbound-egress.js";
|
|
@@ -88,6 +91,17 @@ import type {
|
|
|
88
91
|
*/
|
|
89
92
|
export type ExtensionServiceRegistration = (router: ConnectRouter) => void;
|
|
90
93
|
|
|
94
|
+
/**
|
|
95
|
+
* A service registration with the unit that contributed it, so the routes
|
|
96
|
+
* stage can name the unit when a registration shadows a core route
|
|
97
|
+
* (compose.ts refuses that at boot: Connect's router keys handlers by
|
|
98
|
+
* request path and the last registration wins, silently).
|
|
99
|
+
*/
|
|
100
|
+
export interface ResolvedServiceRegistration {
|
|
101
|
+
readonly unit: string;
|
|
102
|
+
readonly register: ExtensionServiceRegistration;
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
/**
|
|
92
106
|
* One named extension unit — a package's whole contribution to the server
|
|
93
107
|
* composition. All fields but `name` are optional; an omitted field is
|
|
@@ -191,7 +205,7 @@ export interface ResolvedExtensions {
|
|
|
191
205
|
readonly statusObservers: ReadonlyArray<AgentExecutionStatusObserver>;
|
|
192
206
|
readonly responseDecorators: ReadonlyArray<AgentExecutionResponseDecorator>;
|
|
193
207
|
readonly drivers: ResolvedExtensionDrivers;
|
|
194
|
-
readonly services: ReadonlyArray<
|
|
208
|
+
readonly services: ReadonlyArray<ResolvedServiceRegistration>;
|
|
195
209
|
readonly workers: ReadonlyArray<WorkerFactory>;
|
|
196
210
|
}
|
|
197
211
|
|
|
@@ -284,6 +298,22 @@ export interface ResolvedExtensionDrivers {
|
|
|
284
298
|
* source's relaxed posture (only the link-local range refused).
|
|
285
299
|
*/
|
|
286
300
|
readonly outboundEgress: OutboundEgressPolicy | undefined;
|
|
301
|
+
/**
|
|
302
|
+
* The platform-client store driver — undefined = compose.ts installs the
|
|
303
|
+
* OSS adapter over the generic Store.
|
|
304
|
+
*/
|
|
305
|
+
readonly platformClientStore: PlatformClientStore | undefined;
|
|
306
|
+
/**
|
|
307
|
+
* The platform-token key ring — undefined = compose.ts composes open
|
|
308
|
+
* source's ring under an authentication posture, and refuses to boot a
|
|
309
|
+
* non-open-source edition that supplied none.
|
|
310
|
+
*/
|
|
311
|
+
readonly platformTokenKeys: PlatformTokenKeyRing | undefined;
|
|
312
|
+
/**
|
|
313
|
+
* The guest-token capability — undefined = `mintGuestToken` refuses
|
|
314
|
+
* UNIMPLEMENTED with the edition sentence.
|
|
315
|
+
*/
|
|
316
|
+
readonly guestTokenMinting: GuestTokenMinting | undefined;
|
|
287
317
|
}
|
|
288
318
|
|
|
289
319
|
/**
|
|
@@ -301,7 +331,7 @@ export function resolveExtensions(
|
|
|
301
331
|
const gateSteps = new Map<string, ReadonlyArray<PipelineStep<DescMessage>>>();
|
|
302
332
|
const statusObservers: AgentExecutionStatusObserver[] = [];
|
|
303
333
|
const responseDecorators: AgentExecutionResponseDecorator[] = [];
|
|
304
|
-
const services:
|
|
334
|
+
const services: ResolvedServiceRegistration[] = [];
|
|
305
335
|
const workers: WorkerFactory[] = [];
|
|
306
336
|
|
|
307
337
|
let edition: ServerEdition | undefined;
|
|
@@ -341,6 +371,12 @@ export function resolveExtensions(
|
|
|
341
371
|
let licenseStatusDeclaredBy: string | undefined;
|
|
342
372
|
let outboundEgress: OutboundEgressPolicy | undefined;
|
|
343
373
|
let outboundEgressDeclaredBy: string | undefined;
|
|
374
|
+
let platformClientStore: PlatformClientStore | undefined;
|
|
375
|
+
let platformClientStoreDeclaredBy: string | undefined;
|
|
376
|
+
let platformTokenKeys: PlatformTokenKeyRing | undefined;
|
|
377
|
+
let platformTokenKeysDeclaredBy: string | undefined;
|
|
378
|
+
let guestTokenMinting: GuestTokenMinting | undefined;
|
|
379
|
+
let guestTokenMintingDeclaredBy: string | undefined;
|
|
344
380
|
const artifactStorageDrivers = new Map<
|
|
345
381
|
string,
|
|
346
382
|
ArtifactStorageDriverFactory
|
|
@@ -552,6 +588,36 @@ export function resolveExtensions(
|
|
|
552
588
|
outboundEgressDeclaredBy = unit.name;
|
|
553
589
|
}
|
|
554
590
|
|
|
591
|
+
if (unit.drivers?.platformClientStore !== undefined) {
|
|
592
|
+
if (platformClientStoreDeclaredBy !== undefined) {
|
|
593
|
+
throw new Error(
|
|
594
|
+
`extension '${unit.name}' registers a PlatformClientStore, but '${platformClientStoreDeclaredBy}' already did — exactly one may be composed`,
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
platformClientStore = unit.drivers.platformClientStore;
|
|
598
|
+
platformClientStoreDeclaredBy = unit.name;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (unit.drivers?.platformTokenKeys !== undefined) {
|
|
602
|
+
if (platformTokenKeysDeclaredBy !== undefined) {
|
|
603
|
+
throw new Error(
|
|
604
|
+
`extension '${unit.name}' registers a PlatformTokenKeyRing, but '${platformTokenKeysDeclaredBy}' already did — exactly one may be composed`,
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
platformTokenKeys = unit.drivers.platformTokenKeys;
|
|
608
|
+
platformTokenKeysDeclaredBy = unit.name;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (unit.drivers?.guestTokenMinting !== undefined) {
|
|
612
|
+
if (guestTokenMintingDeclaredBy !== undefined) {
|
|
613
|
+
throw new Error(
|
|
614
|
+
`extension '${unit.name}' registers a GuestTokenMinting capability, but '${guestTokenMintingDeclaredBy}' already did — exactly one may be composed`,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
guestTokenMinting = unit.drivers.guestTokenMinting;
|
|
618
|
+
guestTokenMintingDeclaredBy = unit.name;
|
|
619
|
+
}
|
|
620
|
+
|
|
555
621
|
if (unit.drivers?.artifactStorageDrivers !== undefined) {
|
|
556
622
|
for (const [name, factory] of unit.drivers.artifactStorageDrivers) {
|
|
557
623
|
if ((BUILT_IN_STORAGE_TYPES as ReadonlyArray<string>).includes(name)) {
|
|
@@ -643,7 +709,12 @@ export function resolveExtensions(
|
|
|
643
709
|
responseDecorators.push(
|
|
644
710
|
...(unit.statusTransitionHooks?.responseDecorators ?? []),
|
|
645
711
|
);
|
|
646
|
-
services.push(
|
|
712
|
+
services.push(
|
|
713
|
+
...(unit.services ?? []).map((register) => ({
|
|
714
|
+
unit: unit.name,
|
|
715
|
+
register,
|
|
716
|
+
})),
|
|
717
|
+
);
|
|
647
718
|
workers.push(...(unit.workers ?? []));
|
|
648
719
|
}
|
|
649
720
|
|
|
@@ -679,6 +750,9 @@ export function resolveExtensions(
|
|
|
679
750
|
authorizationQueries,
|
|
680
751
|
licenseStatus,
|
|
681
752
|
outboundEgress,
|
|
753
|
+
platformClientStore,
|
|
754
|
+
platformTokenKeys,
|
|
755
|
+
guestTokenMinting,
|
|
682
756
|
},
|
|
683
757
|
services,
|
|
684
758
|
workers,
|
package/src/index.ts
CHANGED
|
@@ -59,6 +59,7 @@ export type {
|
|
|
59
59
|
export type {
|
|
60
60
|
ExtensionServiceRegistration,
|
|
61
61
|
ResolvedExtensions,
|
|
62
|
+
ResolvedServiceRegistration,
|
|
62
63
|
ServerExtension,
|
|
63
64
|
} from "./extensions/registry.js";
|
|
64
65
|
export type {
|
|
@@ -166,6 +167,60 @@ export type { AuthorizationQueryEngine } from "./extensions/authorization-querie
|
|
|
166
167
|
export type { IdentityFederation } from "./extensions/identity-federation.js";
|
|
167
168
|
export type { AccountsBySubject } from "./domain/identityaccount/resolve.js";
|
|
168
169
|
export { identityIdForSubject } from "./domain/identityaccount/resolve.js";
|
|
170
|
+
// The PlatformClient seams: the store PORT a composition drives the domain
|
|
171
|
+
// through (drivers.platformClientStore; a driver throws
|
|
172
|
+
// DuplicatePlatformClientError for a held id, slug or client_id) and its
|
|
173
|
+
// vitest-free contract kit; the guest-token capability
|
|
174
|
+
// (drivers.guestTokenMinting — the one token method only an edition that
|
|
175
|
+
// hosts shared-agent pages serves); and the builder of the system-managed
|
|
176
|
+
// client such an edition keeps per organization under the reserved slug,
|
|
177
|
+
// so the tokens it signs for guests and schedule fires name a real client.
|
|
178
|
+
export type { PlatformClientStore } from "./domain/platformclient/store.js";
|
|
179
|
+
export { DuplicatePlatformClientError } from "./domain/platformclient/store.js";
|
|
180
|
+
export type {
|
|
181
|
+
PlatformClientStoreContractCase,
|
|
182
|
+
PlatformClientStoreContractFixture,
|
|
183
|
+
} from "./domain/platformclient/store-contract.js";
|
|
184
|
+
export { platformClientStoreContract } from "./domain/platformclient/store-contract.js";
|
|
185
|
+
export type { GuestTokenMinting } from "./extensions/guest-token-minting.js";
|
|
186
|
+
export type { SystemManagedPlatformClientInput } from "./domain/platformclient/system-managed.js";
|
|
187
|
+
export { newSystemManagedPlatformClient } from "./domain/platformclient/system-managed.js";
|
|
188
|
+
export { SYSTEM_SHARE_CLIENT_SLUG } from "./domain/platformclient/constants.js";
|
|
189
|
+
// The platform-token envelope and its key ring: the RS256 JWT every token
|
|
190
|
+
// the server signs for itself rides. A composition supplies its ring
|
|
191
|
+
// (drivers.platformTokenKeys, built from its PEMs), signs its own typed
|
|
192
|
+
// lanes through the envelope — each with its own lifetime when it is not
|
|
193
|
+
// the ring's default, the expiry handed back — and verifies them with the
|
|
194
|
+
// same function and refusal copy open source's user-token lane uses.
|
|
195
|
+
export type {
|
|
196
|
+
PlatformTokenClaimValue,
|
|
197
|
+
PlatformTokenRefusal,
|
|
198
|
+
PlatformTokenSigningOptions,
|
|
199
|
+
PlatformTokenVerification,
|
|
200
|
+
SignedPlatformToken,
|
|
201
|
+
VerifiedPlatformToken,
|
|
202
|
+
} from "./platformtoken/envelope.js";
|
|
203
|
+
export {
|
|
204
|
+
PLATFORM_TOKEN_ISSUER,
|
|
205
|
+
PLATFORM_TOKEN_REFUSAL_MESSAGES,
|
|
206
|
+
TOKEN_TYPE_CLAIM,
|
|
207
|
+
decodeVerifiedPlatformTokenPayload,
|
|
208
|
+
platformTokenRefusalError,
|
|
209
|
+
signPlatformToken,
|
|
210
|
+
stringClaim,
|
|
211
|
+
verifyPlatformToken,
|
|
212
|
+
} from "./platformtoken/envelope.js";
|
|
213
|
+
export type {
|
|
214
|
+
PlatformTokenKeyMaterial,
|
|
215
|
+
PlatformTokenKeyRing,
|
|
216
|
+
PlatformTokenSigner,
|
|
217
|
+
SigningPlatformTokenKeyRing,
|
|
218
|
+
} from "./platformtoken/key-ring.js";
|
|
219
|
+
export {
|
|
220
|
+
DEFAULT_PLATFORM_TOKEN_TTL_SECONDS,
|
|
221
|
+
canSign,
|
|
222
|
+
platformTokenKeyRingFromPem,
|
|
223
|
+
} from "./platformtoken/key-ring.js";
|
|
169
224
|
// The built-in authorizer's model seams: the kind
|
|
170
225
|
// declarations (transcripts of the cloud's `.fga` files), the evaluator,
|
|
171
226
|
// and the OpenFGA store-test kit — exported so the cloud's drift test
|
|
@@ -45,15 +45,16 @@ export const SYSTEM_MANAGED_LABEL = `${RESERVED_LABEL_PREFIX}system-managed`;
|
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Marks system content: a resource the platform itself seeded rather than a
|
|
48
|
-
* user authored
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
48
|
+
* user authored. The retired seedpack wrote it on every row it applied, and
|
|
49
|
+
* CLIs before the bootstrap stopped labelling stamped it on the `stigmer`
|
|
50
|
+
* organization they created. A plugin overlay may still carry it on a
|
|
51
|
+
* member (a reserved label, so the push charges the platform permission for
|
|
52
|
+
* it). It has one server-side meaning: a plugin
|
|
53
|
+
* push may adopt a system-content row that holds a slug the plugin needs,
|
|
54
|
+
* keeping the row's id and everything bound to it, instead of refusing the
|
|
55
|
+
* slug as taken. It never marks a user's resource, so a user's row is never
|
|
56
|
+
* adopted (domain/plugin/members.ts, judgeSlug); on an organization it is
|
|
57
|
+
* inert.
|
|
57
58
|
*/
|
|
58
59
|
export const SYSTEM_LABEL = `${RESERVED_LABEL_PREFIX}system`;
|
|
59
60
|
|
|
@@ -216,6 +216,33 @@ export function trustedLocalIdentityFor(operator: {
|
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
/**
|
|
220
|
+
* The server acting for a principal it has authenticated some other way —
|
|
221
|
+
* the one construction of an `internal` caller outside the in-process
|
|
222
|
+
* transport's own stamp. Its consumer is the PlatformClient mint
|
|
223
|
+
* (domain/platformclient/mint.ts): the request is public and tokenless
|
|
224
|
+
* (so the chain stamped the trusted-local operator), the client proved
|
|
225
|
+
* itself with its secret, and the end-user account and role the mint
|
|
226
|
+
* creates must name the CLIENT as their actor, never the operator.
|
|
227
|
+
* `internal` because the server is the one acting — the create path's
|
|
228
|
+
* Authorize skips it, as for every server-composed request — and never
|
|
229
|
+
* reachable from the wire: no verifier produces it, and the serving
|
|
230
|
+
* chassis overwrites position 1 on every request.
|
|
231
|
+
*/
|
|
232
|
+
export function serverActingFor(principalId: string): CallerIdentity {
|
|
233
|
+
if (principalId === "") {
|
|
234
|
+
throw new Error(
|
|
235
|
+
"the server acts for a named principal — refusing to build an internal caller with none",
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
identityId: principalId,
|
|
240
|
+
callerClass: "internal",
|
|
241
|
+
issuer: "",
|
|
242
|
+
rawToken: "",
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
219
246
|
/**
|
|
220
247
|
* The serving chain's position-1 identity source: walks the composed
|
|
221
248
|
* verifiers in order (OSS entries first, extension entries after, in
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* task config, through the `reference_kind` field option); each clause on
|
|
6
6
|
* each kind — no org refused, a same-organization target must exist, the
|
|
7
7
|
* floor applies to the kinds the run reads as the person and to no other,
|
|
8
|
-
* a
|
|
8
|
+
* a relative reference's floor is capped at org and its target must still
|
|
9
|
+
* exist in the resource's organization, a cross-organization target is admitted only at platform visibility with
|
|
9
10
|
* ONE sentence whether it is missing or merely not shared; the MCP-server
|
|
10
11
|
* copy that predates the rule is byte-identical and its siblings take its
|
|
11
12
|
* shape; the walk reads a reference's kind from its field, not from the
|
|
@@ -38,6 +39,7 @@ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/
|
|
|
38
39
|
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
39
40
|
import { reference_kind } from "@stigmer/protos/ai/stigmer/commons/apiresource/field_options_pb";
|
|
40
41
|
import { UpdateVisibilityInputSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
42
|
+
import { PlatformClientSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
41
43
|
|
|
42
44
|
import type { Store } from "../../../store/interface.js";
|
|
43
45
|
import { SqliteStore } from "../../../store/sqlite/store.js";
|
|
@@ -96,6 +98,7 @@ const SCHEMAS_UNDER_THE_RULE: ReadonlyArray<DescMessage> = [
|
|
|
96
98
|
AgentExecutionSchema,
|
|
97
99
|
WorkflowExecutionSchema,
|
|
98
100
|
ExecutionContextSchema,
|
|
101
|
+
PlatformClientSchema,
|
|
99
102
|
AgentCallTaskConfigSchema,
|
|
100
103
|
];
|
|
101
104
|
|
|
@@ -289,6 +292,39 @@ describe("checkReference", () => {
|
|
|
289
292
|
).toEqual({ kind: "below-floor", targetVisibility: V.visibility_org });
|
|
290
293
|
});
|
|
291
294
|
|
|
295
|
+
it("(ii) a relative reference's floor is capped at org: a platform resource may run with its organization's org-visible target, never a private one, and the target must exist", () => {
|
|
296
|
+
const relative = (slug: string): SpecReference => ({
|
|
297
|
+
...ref(K.mcp_server, "acme", slug),
|
|
298
|
+
resolvesIn: "running-organization",
|
|
299
|
+
});
|
|
300
|
+
const privateTarget: SpecReference = {
|
|
301
|
+
...ref(K.skill, "acme", "my-skill"),
|
|
302
|
+
resolvesIn: "running-organization",
|
|
303
|
+
};
|
|
304
|
+
const ACME_PLATFORM: ReferenceParent = {
|
|
305
|
+
org: "acme",
|
|
306
|
+
visibility: V.visibility_platform,
|
|
307
|
+
};
|
|
308
|
+
expect(checkReference(targets, ACME_PLATFORM, relative("github"))).toEqual({
|
|
309
|
+
kind: "ok",
|
|
310
|
+
});
|
|
311
|
+
expect(checkReference(targets, ACME_PLATFORM, privateTarget)).toEqual({
|
|
312
|
+
kind: "below-floor",
|
|
313
|
+
targetVisibility: V.visibility_private,
|
|
314
|
+
});
|
|
315
|
+
expect(checkReference(targets, ACME_PLATFORM, relative("ghost"))).toEqual({
|
|
316
|
+
kind: "missing",
|
|
317
|
+
});
|
|
318
|
+
// Below the cap the resource's own level decides, as for any reference.
|
|
319
|
+
expect(checkReference(targets, ACME_ORG, privateTarget)).toEqual({
|
|
320
|
+
kind: "below-floor",
|
|
321
|
+
targetVisibility: V.visibility_private,
|
|
322
|
+
});
|
|
323
|
+
expect(checkReference(targets, ACME_PRIVATE, privateTarget)).toEqual({
|
|
324
|
+
kind: "ok",
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
292
328
|
it("(ii) the floor does not apply to what the server resolves on the run's behalf", () => {
|
|
293
329
|
// An org-visible instance over a private personal environment: the
|
|
294
330
|
// ordinary shape of a personal instance, admitted.
|
|
@@ -115,9 +115,12 @@ function copyStatusFromExisting(
|
|
|
115
115
|
/**
|
|
116
116
|
* Go updateAuditFieldsReflect: spec_audit keeps the existing creation
|
|
117
117
|
* identity with a fresh update stamp; status_audit is fully current (the
|
|
118
|
-
* status was rebuilt); both carry event "updated".
|
|
118
|
+
* status was rebuilt); both carry event "updated". Exported for the one
|
|
119
|
+
* write that changes a stored resource outside this step — a
|
|
120
|
+
* PlatformClient secret rotation (domain/platformclient/steps.ts) — so an
|
|
121
|
+
* update's audit has one shape whichever step writes it.
|
|
119
122
|
*/
|
|
120
|
-
function updateAuditFields(
|
|
123
|
+
export function updateAuditFields(
|
|
121
124
|
schema: DescMessage,
|
|
122
125
|
resource: Message,
|
|
123
126
|
existing: Message,
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* channel apps are resolved by the server on the run's behalf and
|
|
29
29
|
* never read by the person, so their level is not a leak the floor
|
|
30
30
|
* closes, and an org-visible instance may hold a private personal
|
|
31
|
-
* environment as it always has.
|
|
31
|
+
* environment as it always has. A RELATIVE reference (below) is
|
|
32
|
+
* compared against the resource's level capped at org.
|
|
32
33
|
* (iii) Another organization: the target must exist AND be
|
|
33
34
|
* platform-visible, answered with ONE sentence that does not say
|
|
34
35
|
* which failed. The caller has no standing to learn what another
|
|
@@ -48,14 +49,32 @@
|
|
|
48
49
|
* the rule must agree with the runtime. A reference with an empty slug is
|
|
49
50
|
* unset and skipped (the field-level CEL rules own "required").
|
|
50
51
|
*
|
|
52
|
+
* A reference is RELATIVE when it names no organization of its own and
|
|
53
|
+
* the runtime resolves it in the organization the resource RUNS in, not
|
|
54
|
+
* the one it is stored in. Exactly one exists: a workflow `agent_call`
|
|
55
|
+
* task's bare slug (domain/workflow/agent-call-references.ts), which the
|
|
56
|
+
* runner resolves in the execution's organization; any workflow a person
|
|
57
|
+
* may execute can run from another organization by id. The rule judges
|
|
58
|
+
* it in the resource's own organization — the one its author can see, so
|
|
59
|
+
* the target must exist there — and caps its floor at org: only the
|
|
60
|
+
* running organization's own people ever read a target through it, and
|
|
61
|
+
* they can read an org-visible one. The cap changes nothing for a
|
|
62
|
+
* private or org resource and lets a platform-visible workflow call its
|
|
63
|
+
* organization's org-visible agent. A value fixed only at run (an
|
|
64
|
+
* `agent_call` agent holding a runtime expression) is not a reference at
|
|
65
|
+
* all: the collector yields nothing for it, and the run reads the
|
|
66
|
+
* resolved target as the person the run acts as, as it reads every
|
|
67
|
+
* id-bound binding.
|
|
68
|
+
*
|
|
51
69
|
* The floor has a second door. Raising a resource's level through
|
|
52
70
|
* updateVisibility could open the same gap a create cannot, so
|
|
53
71
|
* GuardReferenceFloorOnEscalation runs on the two chains whose rows carry
|
|
54
72
|
* run-read references (agent, workflow) after ValidateVisibilityUpdate:
|
|
55
73
|
* when the requested level is above the stored one, every run-read
|
|
56
|
-
* reference the STORED row carries must be at least the requested level
|
|
57
|
-
*
|
|
58
|
-
*
|
|
74
|
+
* reference the STORED row carries must be at least the requested level
|
|
75
|
+
* (a relative one, at least the requested level capped at org), judged by
|
|
76
|
+
* the same function over the same collectors, else the escalation is
|
|
77
|
+
* refused naming the dependencies. Only the floor is asked at
|
|
59
78
|
* that door — a dependency that has since left or stopped being shared was
|
|
60
79
|
* judged when the row was written and is the run's to refuse.
|
|
61
80
|
*
|
|
@@ -182,6 +201,13 @@ export interface SpecReference {
|
|
|
182
201
|
readonly kind: ApiResourceKind;
|
|
183
202
|
readonly slug: string;
|
|
184
203
|
readonly org: string;
|
|
204
|
+
/**
|
|
205
|
+
* Present only on a RELATIVE reference (the module header): `org` is the
|
|
206
|
+
* resource's own, filled by the collector, and the runtime resolves the
|
|
207
|
+
* slug in the organization the resource runs in. The generic walker
|
|
208
|
+
* never sets it; only the `agent_call` collector does.
|
|
209
|
+
*/
|
|
210
|
+
readonly resolvesIn?: "running-organization";
|
|
185
211
|
}
|
|
186
212
|
|
|
187
213
|
/** The resource the references belong to, as the rule needs it. */
|
|
@@ -279,13 +305,31 @@ export function checkReference(
|
|
|
279
305
|
const entry = referenceTargetKind(ref.kind);
|
|
280
306
|
if (
|
|
281
307
|
entry?.readByRun === true &&
|
|
282
|
-
visibilityRank(target) < visibilityRank(parent
|
|
308
|
+
visibilityRank(target) < visibilityRank(floorOf(parent, ref))
|
|
283
309
|
) {
|
|
284
310
|
return { kind: "below-floor", targetVisibility: target };
|
|
285
311
|
}
|
|
286
312
|
return { kind: "ok" };
|
|
287
313
|
}
|
|
288
314
|
|
|
315
|
+
/**
|
|
316
|
+
* The level a same-organization target must reach: the resource's own,
|
|
317
|
+
* capped at org for a relative reference (the module header).
|
|
318
|
+
*/
|
|
319
|
+
function floorOf(
|
|
320
|
+
parent: ReferenceParent,
|
|
321
|
+
ref: SpecReference,
|
|
322
|
+
): ApiResourceVisibility {
|
|
323
|
+
if (
|
|
324
|
+
ref.resolvesIn === "running-organization" &&
|
|
325
|
+
visibilityRank(parent.visibility) >
|
|
326
|
+
visibilityRank(ApiResourceVisibility.visibility_org)
|
|
327
|
+
) {
|
|
328
|
+
return ApiResourceVisibility.visibility_org;
|
|
329
|
+
}
|
|
330
|
+
return parent.visibility;
|
|
331
|
+
}
|
|
332
|
+
|
|
289
333
|
/**
|
|
290
334
|
* The order the floor compares on: private < org < platform, an unset
|
|
291
335
|
* level reading as private (the level a row with no config holds). The
|