@stigmer/server 3.31.0 → 3.33.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/model/data/authorization-model.json +16 -46
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +11 -1
- package/dist/boot/compose.js.map +1 -1
- package/dist/domain/agentexecution/create-execution-context-step.d.ts +7 -0
- package/dist/domain/agentexecution/create-execution-context-step.d.ts.map +1 -1
- package/dist/domain/agentexecution/create-execution-context-step.js +79 -4
- package/dist/domain/agentexecution/create-execution-context-step.js.map +1 -1
- package/dist/domain/apikey/controller.d.ts.map +1 -1
- package/dist/domain/apikey/controller.js +7 -2
- package/dist/domain/apikey/controller.js.map +1 -1
- package/dist/domain/apikey/verifier.d.ts +5 -0
- package/dist/domain/apikey/verifier.d.ts.map +1 -1
- package/dist/domain/apikey/verifier.js +32 -3
- package/dist/domain/apikey/verifier.js.map +1 -1
- package/dist/domain/iampolicy/constants.d.ts +11 -1
- package/dist/domain/iampolicy/constants.d.ts.map +1 -1
- package/dist/domain/iampolicy/constants.js +11 -1
- package/dist/domain/iampolicy/constants.js.map +1 -1
- package/dist/domain/iampolicy/controller.d.ts.map +1 -1
- package/dist/domain/iampolicy/controller.js +36 -12
- package/dist/domain/iampolicy/controller.js.map +1 -1
- package/dist/domain/iampolicy/steps.d.ts +98 -0
- package/dist/domain/iampolicy/steps.d.ts.map +1 -1
- package/dist/domain/iampolicy/steps.js +119 -4
- package/dist/domain/iampolicy/steps.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +11 -1
- package/dist/domain/platformclient/constants.d.ts.map +1 -1
- package/dist/domain/platformclient/constants.js +11 -1
- package/dist/domain/platformclient/constants.js.map +1 -1
- package/dist/domain/platformclient/mint.d.ts.map +1 -1
- package/dist/domain/platformclient/mint.js +28 -1
- package/dist/domain/platformclient/mint.js.map +1 -1
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -1
- package/dist/domain/platformclient/resource-store.js +13 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -1
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -1
- package/dist/domain/platformclient/store-contract.js +59 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -1
- package/dist/domain/platformclient/store.d.ts +20 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -1
- package/dist/domain/platformclient/store.js.map +1 -1
- package/dist/domain/platformclient/verifier.d.ts.map +1 -1
- package/dist/domain/platformclient/verifier.js +7 -2
- package/dist/domain/platformclient/verifier.js.map +1 -1
- package/dist/extensions/identity.d.ts +14 -0
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/identity/credential-use.d.ts +74 -0
- package/dist/identity/credential-use.d.ts.map +1 -0
- package/dist/identity/credential-use.js +59 -0
- package/dist/identity/credential-use.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/steps/defaults.d.ts +15 -1
- package/dist/pipeline/steps/defaults.d.ts.map +1 -1
- package/dist/pipeline/steps/defaults.js +31 -1
- package/dist/pipeline/steps/defaults.js.map +1 -1
- package/dist/temporal/schedule/activities.d.ts.map +1 -1
- package/dist/temporal/schedule/activities.js +2 -1
- package/dist/temporal/schedule/activities.js.map +1 -1
- package/dist/temporal/schedule/run-starter.d.ts.map +1 -1
- package/dist/temporal/schedule/run-starter.js +2 -1
- package/dist/temporal/schedule/run-starter.js.map +1 -1
- package/dist/temporal/schedule/status-writes.d.ts +0 -6
- package/dist/temporal/schedule/status-writes.d.ts.map +1 -1
- package/dist/temporal/schedule/status-writes.js +8 -27
- package/dist/temporal/schedule/status-writes.js.map +1 -1
- package/dist/temporal/schedule/syncer.d.ts.map +1 -1
- package/dist/temporal/schedule/syncer.js +2 -1
- package/dist/temporal/schedule/syncer.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/__tests__/store-tests.test.ts +1 -0
- package/src/authorization/model/data/authorization-model.json +16 -46
- package/src/boot/compose.ts +11 -1
- package/src/domain/agentexecution/__tests__/create-execution-context-step.test.ts +329 -0
- package/src/domain/agentexecution/__tests__/lifecycle.test.ts +7 -0
- package/src/domain/agentexecution/create-execution-context-step.ts +110 -4
- package/src/domain/apikey/__tests__/apikey.test.ts +17 -2
- package/src/domain/apikey/__tests__/verifier.test.ts +86 -3
- package/src/domain/apikey/controller.ts +12 -2
- package/src/domain/apikey/verifier.ts +46 -3
- package/src/domain/iampolicy/__tests__/controller.test.ts +99 -3
- package/src/domain/iampolicy/__tests__/steps.test.ts +179 -0
- package/src/domain/iampolicy/constants.ts +15 -1
- package/src/domain/iampolicy/controller.ts +43 -9
- package/src/domain/iampolicy/steps.ts +164 -4
- package/src/domain/platformclient/__tests__/mint.test.ts +104 -12
- package/src/domain/platformclient/__tests__/resource-store.test.ts +4 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +4 -2
- package/src/domain/platformclient/constants.ts +11 -1
- package/src/domain/platformclient/mint.ts +34 -1
- package/src/domain/platformclient/resource-store.ts +18 -0
- package/src/domain/platformclient/store-contract.ts +100 -0
- package/src/domain/platformclient/store.ts +23 -0
- package/src/domain/platformclient/verifier.ts +7 -2
- package/src/extensions/__tests__/role-reconciliation-composed.test.ts +18 -10
- package/src/extensions/identity.ts +14 -0
- package/src/identity/__tests__/credential-use.test.ts +186 -0
- package/src/identity/credential-use.ts +130 -0
- package/src/index.ts +5 -0
- package/src/pipeline/__tests__/steps.test.ts +72 -1
- package/src/pipeline/steps/defaults.ts +33 -1
- package/src/temporal/schedule/activities.ts +2 -1
- package/src/temporal/schedule/run-starter.ts +2 -1
- package/src/temporal/schedule/status-writes.ts +8 -31
- package/src/temporal/schedule/syncer.ts +2 -1
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The clock's status-write
|
|
3
|
-
*
|
|
2
|
+
* The clock's status-write helper — ports ensureStatus of
|
|
3
|
+
* pkg/domain/schedule/temporal/syncer.go.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* steps.SetAuditFieldsForUpdate from the clock's bump. Two flavors, two
|
|
12
|
-
* writers, both wire-visible — keep them distinct.
|
|
5
|
+
* The clock's audit stamp is the shared `bumpStatusAudit`
|
|
6
|
+
* (pipeline/steps/defaults.ts): status-audit updated_at + event only, never
|
|
7
|
+
* an actor — the clock is the platform, not an operator. Controller-side
|
|
8
|
+
* status writes (trigger's last_fire_at stamp, resume's clear) use the FULL
|
|
9
|
+
* setAuditFieldsForUpdate instead, exactly as Go splits
|
|
10
|
+
* steps.SetAuditFieldsForUpdate from the clock's bump.
|
|
13
11
|
*/
|
|
14
12
|
import { create } from "@bufbuild/protobuf";
|
|
15
|
-
import { timestampNow } from "@bufbuild/protobuf/wkt";
|
|
16
13
|
import { ScheduleStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/status_pb";
|
|
17
|
-
import { ApiResourceAuditInfoSchema, ApiResourceAuditSchema, } from "@stigmer/protos/ai/stigmer/commons/apiresource/status_pb";
|
|
18
14
|
/**
|
|
19
15
|
* Returns the schedule's status, materializing the nested message a fresh
|
|
20
16
|
* row may lack (Go ensureStatus).
|
|
@@ -25,19 +21,4 @@ export function ensureStatus(schedule) {
|
|
|
25
21
|
}
|
|
26
22
|
return schedule.status;
|
|
27
23
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Stamps the status-audit trail for a runtime write — updated_at + event
|
|
30
|
-
* "updated", nothing else (Go bumpStatusAudit; see the module header for
|
|
31
|
-
* why this is not setAuditFieldsForUpdate).
|
|
32
|
-
*/
|
|
33
|
-
export function bumpStatusAudit(status) {
|
|
34
|
-
if (status.audit === undefined) {
|
|
35
|
-
status.audit = create(ApiResourceAuditSchema);
|
|
36
|
-
}
|
|
37
|
-
if (status.audit.statusAudit === undefined) {
|
|
38
|
-
status.audit.statusAudit = create(ApiResourceAuditInfoSchema);
|
|
39
|
-
}
|
|
40
|
-
status.audit.statusAudit.updatedAt = timestampNow();
|
|
41
|
-
status.audit.statusAudit.event = "updated";
|
|
42
|
-
}
|
|
43
24
|
//# sourceMappingURL=status-writes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-writes.js","sourceRoot":"","sources":["../../../src/temporal/schedule/status-writes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"status-writes.js","sourceRoot":"","sources":["../../../src/temporal/schedule/status-writes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAGhG;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../src/temporal/schedule/syncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,oBAAoB,CAAC;AAKtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uDAAuD,CAAC;AAGtF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../src/temporal/schedule/syncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,oBAAoB,CAAC;AAKtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uDAAuD,CAAC;AAGtF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKtD;;;;GAIG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED,qBAAa,cAAc;IAEvB,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;;IAJvB,+DAA+D;IAC9C,cAAc,EAAE,MAAM,MAAM,GAAG,SAAS,EACxC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,MAAM;IAGjC;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IA+CpE;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAqBnE;;;;OAIG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBjD;;;;OAIG;YACW,gBAAgB;CA6B/B"}
|
|
@@ -2,10 +2,11 @@ import { ScheduleAlreadyRunning, ScheduleNotFoundError } from "@temporalio/clien
|
|
|
2
2
|
import { timestampFromDate } from "@bufbuild/protobuf/wkt";
|
|
3
3
|
import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
4
4
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
5
|
+
import { bumpStatusAudit } from "../../pipeline/steps/defaults.js";
|
|
5
6
|
import { ResourceNotFoundError } from "../../store/interface.js";
|
|
6
7
|
import { desiredPaused, note } from "./artifact.js";
|
|
7
8
|
import { artifactId } from "./names.js";
|
|
8
|
-
import {
|
|
9
|
+
import { ensureStatus } from "./status-writes.js";
|
|
9
10
|
/**
|
|
10
11
|
* The syncer's answer when no Temporal client exists right now (Go
|
|
11
12
|
* ErrTemporalUnavailable). Callers on the write path treat it as "converge
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncer.js","sourceRoot":"","sources":["../../../src/temporal/schedule/syncer.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,uDAAuD,CAAC;AAEvF,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AAGtH,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"syncer.js","sourceRoot":"","sources":["../../../src/temporal/schedule/syncer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stigmer/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.33.0",
|
|
4
4
|
"description": "The Stigmer OSS control plane as a composable library: composeServer, the extension registry and the driver seams a composition builds on. The self-contained deployable of the same server is @stigmer/server-slim.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -63,11 +63,11 @@
|
|
|
63
63
|
"@connectrpc/connect-node": "^2.0.0",
|
|
64
64
|
"@kubernetes/client-node": "2.0.0",
|
|
65
65
|
"@opentelemetry/api": "^1.9.0",
|
|
66
|
-
"@stigmer/outbound": "3.
|
|
67
|
-
"@stigmer/plugin-package": "3.
|
|
68
|
-
"@stigmer/protos": "3.
|
|
69
|
-
"@stigmer/temporal-codecs": "3.
|
|
70
|
-
"@stigmer/zip-structure": "3.
|
|
66
|
+
"@stigmer/outbound": "3.33.0",
|
|
67
|
+
"@stigmer/plugin-package": "3.33.0",
|
|
68
|
+
"@stigmer/protos": "3.33.0",
|
|
69
|
+
"@stigmer/temporal-codecs": "3.33.0",
|
|
70
|
+
"@stigmer/zip-structure": "3.33.0",
|
|
71
71
|
"@temporalio/activity": "1.16.2",
|
|
72
72
|
"@temporalio/client": "1.16.2",
|
|
73
73
|
"@temporalio/common": "1.16.2",
|
|
@@ -64,6 +64,7 @@ const DOCUMENTS = [
|
|
|
64
64
|
"memory-subject-only.fga.yaml",
|
|
65
65
|
"org-admin-owner-inheritance.fga.yaml",
|
|
66
66
|
"org-shared-environment.fga.yaml",
|
|
67
|
+
"organization-role-assignment.fga.yaml",
|
|
67
68
|
"platform-visibility.fga.yaml",
|
|
68
69
|
"plugin-owner.fga.yaml",
|
|
69
70
|
"provider-standing-viewer.fga.yaml",
|
|
@@ -199,13 +199,7 @@
|
|
|
199
199
|
}
|
|
200
200
|
]
|
|
201
201
|
},
|
|
202
|
-
"owner": {
|
|
203
|
-
"directly_related_user_types": [
|
|
204
|
-
{
|
|
205
|
-
"type": "identity_account"
|
|
206
|
-
}
|
|
207
|
-
]
|
|
208
|
-
},
|
|
202
|
+
"owner": {},
|
|
209
203
|
"platform_user": {},
|
|
210
204
|
"viewer": {
|
|
211
205
|
"directly_related_user_types": [
|
|
@@ -252,22 +246,13 @@
|
|
|
252
246
|
"this": {}
|
|
253
247
|
},
|
|
254
248
|
"owner": {
|
|
255
|
-
"
|
|
256
|
-
"
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
"computedUserset": {
|
|
263
|
-
"relation": "admin"
|
|
264
|
-
},
|
|
265
|
-
"tupleset": {
|
|
266
|
-
"relation": "organization"
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
]
|
|
249
|
+
"tupleToUserset": {
|
|
250
|
+
"computedUserset": {
|
|
251
|
+
"relation": "admin"
|
|
252
|
+
},
|
|
253
|
+
"tupleset": {
|
|
254
|
+
"relation": "organization"
|
|
255
|
+
}
|
|
271
256
|
}
|
|
272
257
|
},
|
|
273
258
|
"platform_user": {
|
|
@@ -660,13 +645,7 @@
|
|
|
660
645
|
}
|
|
661
646
|
]
|
|
662
647
|
},
|
|
663
|
-
"owner": {
|
|
664
|
-
"directly_related_user_types": [
|
|
665
|
-
{
|
|
666
|
-
"type": "identity_account"
|
|
667
|
-
}
|
|
668
|
-
]
|
|
669
|
-
},
|
|
648
|
+
"owner": {},
|
|
670
649
|
"viewer": {}
|
|
671
650
|
},
|
|
672
651
|
"source_info": {
|
|
@@ -693,22 +672,13 @@
|
|
|
693
672
|
"this": {}
|
|
694
673
|
},
|
|
695
674
|
"owner": {
|
|
696
|
-
"
|
|
697
|
-
"
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
"computedUserset": {
|
|
704
|
-
"relation": "admin"
|
|
705
|
-
},
|
|
706
|
-
"tupleset": {
|
|
707
|
-
"relation": "organization"
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
]
|
|
675
|
+
"tupleToUserset": {
|
|
676
|
+
"computedUserset": {
|
|
677
|
+
"relation": "admin"
|
|
678
|
+
},
|
|
679
|
+
"tupleset": {
|
|
680
|
+
"relation": "organization"
|
|
681
|
+
}
|
|
712
682
|
}
|
|
713
683
|
},
|
|
714
684
|
"viewer": {
|
package/src/boot/compose.ts
CHANGED
|
@@ -1492,6 +1492,9 @@ export async function composeServer(
|
|
|
1492
1492
|
executionContextCreator: () =>
|
|
1493
1493
|
requireInProcess().executionContextCreator,
|
|
1494
1494
|
managedEnvService,
|
|
1495
|
+
// The minting client's environment layer reads the client through
|
|
1496
|
+
// the port, which a composition's driver may serve (#1256).
|
|
1497
|
+
platformClients,
|
|
1495
1498
|
// The run-start token refresh dials the vendor's token endpoint;
|
|
1496
1499
|
// it rides the same egress-guarded fetch as every other OAuth call.
|
|
1497
1500
|
fetchImpl: asFetch(outboundFetch),
|
|
@@ -1690,7 +1693,14 @@ export async function composeServer(
|
|
|
1690
1693
|
// own (the cloud's sandbox lanes).
|
|
1691
1694
|
const identityVerifiers = [
|
|
1692
1695
|
...(requireAuthentication
|
|
1693
|
-
? [
|
|
1696
|
+
? [
|
|
1697
|
+
newApiKeyIdentityVerifier({
|
|
1698
|
+
store,
|
|
1699
|
+
accounts: identityAccounts,
|
|
1700
|
+
logger,
|
|
1701
|
+
now: () => new Date(),
|
|
1702
|
+
}),
|
|
1703
|
+
]
|
|
1694
1704
|
: []),
|
|
1695
1705
|
// The PlatformClient user-token lane rides the ring, which the keys
|
|
1696
1706
|
// stage resolves only under an authentication posture. It sits before
|
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
* agent's env united with the session servers' env, and a session
|
|
12
12
|
* server's saved key reaching the run from the personal environment — for
|
|
13
13
|
* an agent-bound run and for the built-in assistant alike.
|
|
14
|
+
*
|
|
15
|
+
* And the minting PlatformClient's layer (#1256): an execution whose audit
|
|
16
|
+
* names the client a minted user came through receives the client's
|
|
17
|
+
* environments BELOW the instance layer and runtime_env; a creator with no
|
|
18
|
+
* client reads no client at all; a deleted client or one of another
|
|
19
|
+
* organization contributes nothing; an unresolvable ref fails the create;
|
|
20
|
+
* and the layer survives the runner's status writes, so recovery — which
|
|
21
|
+
* rebuilds from the persisted execution with no minted caller — delivers
|
|
22
|
+
* it again.
|
|
14
23
|
*/
|
|
15
24
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
16
25
|
import { tmpdir } from "node:os";
|
|
@@ -22,7 +31,10 @@ import { afterAll, beforeAll, expect, it } from "vitest";
|
|
|
22
31
|
|
|
23
32
|
import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
24
33
|
import { AgentInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
|
|
34
|
+
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
25
35
|
import { AgentExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
36
|
+
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
37
|
+
import { AgentExecutionUpdateStatusInputSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
|
|
26
38
|
import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
27
39
|
import type { EnvironmentValue } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
|
|
28
40
|
import { EnvironmentValueSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
|
|
@@ -30,6 +42,9 @@ import type { ExecutionContext } from "@stigmer/protos/ai/stigmer/agentic/execut
|
|
|
30
42
|
import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
31
43
|
import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
32
44
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
45
|
+
import type { ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
46
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
47
|
+
import { PlatformClientSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
33
48
|
|
|
34
49
|
import { createLogger } from "../../../boot/logger.js";
|
|
35
50
|
import { SqliteStore } from "../../../store/sqlite/store.js";
|
|
@@ -38,6 +53,7 @@ import type { ManagedEnvironmentService } from "../../mcpserver/oauth/managed-en
|
|
|
38
53
|
|
|
39
54
|
import type { ExecutionContextBuilderDeps } from "../create-execution-context-step.js";
|
|
40
55
|
import { buildAndPersistExecutionContext } from "../create-execution-context-step.js";
|
|
56
|
+
import { applyUpdateStatusMerge } from "../update-status.js";
|
|
41
57
|
|
|
42
58
|
const silentLogger = createLogger({
|
|
43
59
|
level: "error",
|
|
@@ -45,6 +61,16 @@ const silentLogger = createLogger({
|
|
|
45
61
|
write: () => {},
|
|
46
62
|
});
|
|
47
63
|
|
|
64
|
+
/**
|
|
65
|
+
* The client port for every execution no minted user created: the layer
|
|
66
|
+
* answers from the execution's own audit, so reaching this is a failure.
|
|
67
|
+
*/
|
|
68
|
+
const unreadPlatformClients: ExecutionContextBuilderDeps["platformClients"] = {
|
|
69
|
+
findById: async () => {
|
|
70
|
+
throw new Error("no minting client: the client must not be read");
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
48
74
|
let dir: string;
|
|
49
75
|
let store: Store;
|
|
50
76
|
|
|
@@ -113,6 +139,7 @@ it("an unresolvable environment ref surfaces the inner status code with Go's wra
|
|
|
113
139
|
readSecretValue: async () => "",
|
|
114
140
|
updateSecrets: async () => {},
|
|
115
141
|
} as unknown as ManagedEnvironmentService,
|
|
142
|
+
platformClients: unreadPlatformClients,
|
|
116
143
|
};
|
|
117
144
|
|
|
118
145
|
const execution = create(AgentExecutionSchema, {
|
|
@@ -251,6 +278,7 @@ it("assembles merge → filter → OAuth injection → EC persist over a non-emp
|
|
|
251
278
|
},
|
|
252
279
|
}),
|
|
253
280
|
managedEnvService,
|
|
281
|
+
platformClients: unreadPlatformClients,
|
|
254
282
|
// The vendor's token endpoint: rotates the refresh token and issues
|
|
255
283
|
// a fresh access token.
|
|
256
284
|
fetchImpl: async () =>
|
|
@@ -394,6 +422,7 @@ it("a session-level server's declared key saved in the personal environment reac
|
|
|
394
422
|
readSecretValue: async () => "",
|
|
395
423
|
updateSecrets: async () => {},
|
|
396
424
|
} as unknown as ManagedEnvironmentService,
|
|
425
|
+
platformClients: unreadPlatformClients,
|
|
397
426
|
};
|
|
398
427
|
const execution = create(AgentExecutionSchema, {
|
|
399
428
|
metadata: { id: "aexec_rule", org: ORG },
|
|
@@ -480,6 +509,7 @@ it("the built-in assistant: no instance, no agent, the session's servers are the
|
|
|
480
509
|
readSecretValue: async () => "",
|
|
481
510
|
updateSecrets: async () => {},
|
|
482
511
|
} as unknown as ManagedEnvironmentService,
|
|
512
|
+
platformClients: unreadPlatformClients,
|
|
483
513
|
};
|
|
484
514
|
const execution = create(AgentExecutionSchema, {
|
|
485
515
|
metadata: { id: "aexec_assistant", org: ORG },
|
|
@@ -500,3 +530,302 @@ it("the built-in assistant: no instance, no agent, the session's servers are the
|
|
|
500
530
|
expect(data["STRAY"]).toBeUndefined();
|
|
501
531
|
expect(reads).toEqual(["NOTES_TOKEN"]);
|
|
502
532
|
});
|
|
533
|
+
|
|
534
|
+
// ---------------------------------------------------------------------------
|
|
535
|
+
// The minting PlatformClient's layer (#1256): keyed on the execution's
|
|
536
|
+
// audit created_by.platform_client_id, which the server stamped from the
|
|
537
|
+
// verified token, below every other layer.
|
|
538
|
+
// ---------------------------------------------------------------------------
|
|
539
|
+
|
|
540
|
+
const PC_ORG = "acme";
|
|
541
|
+
|
|
542
|
+
function environmentOf(
|
|
543
|
+
slug: string,
|
|
544
|
+
data: Record<string, string>,
|
|
545
|
+
org = PC_ORG,
|
|
546
|
+
): ReturnType<typeof create<typeof EnvironmentSchema>> {
|
|
547
|
+
return create(EnvironmentSchema, {
|
|
548
|
+
metadata: { id: `env_${slug}`, org, slug },
|
|
549
|
+
spec: {
|
|
550
|
+
data: Object.fromEntries(
|
|
551
|
+
Object.entries(data).map(([key, value]) => [key, { value, isSecret: true }]),
|
|
552
|
+
),
|
|
553
|
+
},
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** A PlatformClient of `org` whose environment_refs name `slugs`. */
|
|
558
|
+
function mintingClient(org: string, ...slugs: string[]): PlatformClient {
|
|
559
|
+
return create(PlatformClientSchema, {
|
|
560
|
+
metadata: { id: "pcl_dashboard", org, slug: "dashboard" },
|
|
561
|
+
spec: {
|
|
562
|
+
environmentRefs: slugs.map((slug) => ({
|
|
563
|
+
kind: ApiResourceKind.environment,
|
|
564
|
+
org,
|
|
565
|
+
slug,
|
|
566
|
+
})),
|
|
567
|
+
},
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/** An execution in PC_ORG created by an actor who came through `platformClientId`. */
|
|
572
|
+
function executionCreatedThrough(
|
|
573
|
+
id: string,
|
|
574
|
+
platformClientId: string,
|
|
575
|
+
runtimeEnv: Record<string, string> = {},
|
|
576
|
+
): AgentExecution {
|
|
577
|
+
return create(AgentExecutionSchema, {
|
|
578
|
+
metadata: { id, org: PC_ORG },
|
|
579
|
+
spec: {
|
|
580
|
+
sessionId: `ses_${id}`,
|
|
581
|
+
message: "hi",
|
|
582
|
+
runtimeEnv: Object.fromEntries(
|
|
583
|
+
Object.entries(runtimeEnv).map(([key, value]) => [key, { value, isSecret: true }]),
|
|
584
|
+
),
|
|
585
|
+
},
|
|
586
|
+
status: {
|
|
587
|
+
audit: {
|
|
588
|
+
specAudit: { createdBy: { id: "ida_pat", platformClientId } },
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Builder deps for an agent that declares nothing (every merged key passes
|
|
596
|
+
* the filter) over an instance whose one ref is `instance-secrets`. Every
|
|
597
|
+
* resolved reference and every client read is recorded.
|
|
598
|
+
*/
|
|
599
|
+
function platformClientLayerDeps(opts: {
|
|
600
|
+
readonly client: PlatformClient | undefined;
|
|
601
|
+
readonly environments: ReadonlyArray<ReturnType<typeof environmentOf>>;
|
|
602
|
+
readonly resolved: ApiResourceReference[];
|
|
603
|
+
readonly clientReads: string[];
|
|
604
|
+
readonly createdEcs: ExecutionContext[];
|
|
605
|
+
}): ExecutionContextBuilderDeps {
|
|
606
|
+
return {
|
|
607
|
+
store,
|
|
608
|
+
logger: silentLogger,
|
|
609
|
+
agentLoader: () => ({
|
|
610
|
+
get: async () =>
|
|
611
|
+
create(AgentSchema, { metadata: { id: "agt_pc", org: PC_ORG } }),
|
|
612
|
+
}),
|
|
613
|
+
agentInstanceLoader: () => ({
|
|
614
|
+
get: async (instanceId) =>
|
|
615
|
+
create(AgentInstanceSchema, {
|
|
616
|
+
metadata: { id: instanceId, org: PC_ORG },
|
|
617
|
+
spec: {
|
|
618
|
+
agentId: "agt_pc",
|
|
619
|
+
environmentRefs: [
|
|
620
|
+
{
|
|
621
|
+
kind: ApiResourceKind.environment,
|
|
622
|
+
org: PC_ORG,
|
|
623
|
+
slug: "instance-secrets",
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
},
|
|
627
|
+
}),
|
|
628
|
+
}),
|
|
629
|
+
sessionLoader: () => ({
|
|
630
|
+
get: async (sessionId) =>
|
|
631
|
+
create(SessionSchema, {
|
|
632
|
+
metadata: { id: sessionId, org: PC_ORG },
|
|
633
|
+
spec: { agentInstanceId: "agi_pc" },
|
|
634
|
+
}),
|
|
635
|
+
}),
|
|
636
|
+
environmentReader: () => ({
|
|
637
|
+
list: async () => {
|
|
638
|
+
throw new Error("personal-env lookup not needed in this test");
|
|
639
|
+
},
|
|
640
|
+
getSecretValue: async () => {
|
|
641
|
+
throw new Error("personal-env lookup not needed in this test");
|
|
642
|
+
},
|
|
643
|
+
}),
|
|
644
|
+
environmentResolution: {
|
|
645
|
+
resolveByReference: async (ref: ApiResourceReference) => {
|
|
646
|
+
opts.resolved.push(ref);
|
|
647
|
+
const found = opts.environments.find(
|
|
648
|
+
(env) => env.metadata?.slug === ref.slug && env.metadata?.org === ref.org,
|
|
649
|
+
);
|
|
650
|
+
if (found === undefined) {
|
|
651
|
+
throw new ConnectError(`environment not found: ${ref.slug}`, Code.NotFound);
|
|
652
|
+
}
|
|
653
|
+
return found;
|
|
654
|
+
},
|
|
655
|
+
} as unknown as ExecutionContextBuilderDeps["environmentResolution"],
|
|
656
|
+
executionContextCreator: () => ({
|
|
657
|
+
create: async (ec) => {
|
|
658
|
+
opts.createdEcs.push(ec);
|
|
659
|
+
return ec;
|
|
660
|
+
},
|
|
661
|
+
}),
|
|
662
|
+
managedEnvService: {
|
|
663
|
+
readSecretValue: async () => "",
|
|
664
|
+
updateSecrets: async () => {},
|
|
665
|
+
} as unknown as ManagedEnvironmentService,
|
|
666
|
+
platformClients: {
|
|
667
|
+
findById: async (id) => {
|
|
668
|
+
opts.clientReads.push(id);
|
|
669
|
+
return opts.client;
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
const instanceSecrets = environmentOf("instance-secrets", {
|
|
676
|
+
INSTANCE_WINS: "instance",
|
|
677
|
+
});
|
|
678
|
+
const clientSecrets = environmentOf("embed-secrets", {
|
|
679
|
+
SHARED_API_SECRET: "client-secret",
|
|
680
|
+
INSTANCE_WINS: "client",
|
|
681
|
+
RUNTIME_WINS: "client",
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
it("a minted user's execution receives its client's environments below the instance layer and runtime_env", async () => {
|
|
685
|
+
const resolved: ApiResourceReference[] = [];
|
|
686
|
+
const clientReads: string[] = [];
|
|
687
|
+
const createdEcs: ExecutionContext[] = [];
|
|
688
|
+
const deps = platformClientLayerDeps({
|
|
689
|
+
client: mintingClient(PC_ORG, "embed-secrets"),
|
|
690
|
+
environments: [instanceSecrets, clientSecrets],
|
|
691
|
+
resolved,
|
|
692
|
+
clientReads,
|
|
693
|
+
createdEcs,
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
await buildAndPersistExecutionContext(
|
|
697
|
+
deps,
|
|
698
|
+
executionCreatedThrough("aexec_pc_layer", "pcl_dashboard", {
|
|
699
|
+
RUNTIME_WINS: "runtime",
|
|
700
|
+
}),
|
|
701
|
+
"",
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
const data = createdEcs[0]?.spec?.data ?? {};
|
|
705
|
+
// The client's own key reaches the run.
|
|
706
|
+
expect(data["SHARED_API_SECRET"]?.value).toBe("client-secret");
|
|
707
|
+
// The precedence #1256 asks to pin: instance refs, then runtime_env,
|
|
708
|
+
// override the client on a key conflict.
|
|
709
|
+
expect(data["INSTANCE_WINS"]?.value).toBe("instance");
|
|
710
|
+
expect(data["RUNTIME_WINS"]?.value).toBe("runtime");
|
|
711
|
+
expect(clientReads).toEqual(["pcl_dashboard"]);
|
|
712
|
+
expect(resolved.map((ref) => `${ref.org}/${ref.slug}`)).toEqual([
|
|
713
|
+
"acme/instance-secrets",
|
|
714
|
+
"acme/embed-secrets",
|
|
715
|
+
]);
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
it("no client, a deleted client and a client of another organization contribute nothing", async () => {
|
|
719
|
+
// A creator who came through no client: no client is read at all.
|
|
720
|
+
const noClient: ExecutionContext[] = [];
|
|
721
|
+
await buildAndPersistExecutionContext(
|
|
722
|
+
{
|
|
723
|
+
...platformClientLayerDeps({
|
|
724
|
+
client: undefined,
|
|
725
|
+
environments: [instanceSecrets],
|
|
726
|
+
resolved: [],
|
|
727
|
+
clientReads: [],
|
|
728
|
+
createdEcs: noClient,
|
|
729
|
+
}),
|
|
730
|
+
platformClients: unreadPlatformClients,
|
|
731
|
+
},
|
|
732
|
+
executionCreatedThrough("aexec_pc_none", ""),
|
|
733
|
+
"",
|
|
734
|
+
);
|
|
735
|
+
expect(noClient[0]?.spec?.data["INSTANCE_WINS"]?.value).toBe("instance");
|
|
736
|
+
|
|
737
|
+
// The client was deleted since: the run proceeds without its layer.
|
|
738
|
+
const deleted: ExecutionContext[] = [];
|
|
739
|
+
const deletedReads: string[] = [];
|
|
740
|
+
await buildAndPersistExecutionContext(
|
|
741
|
+
platformClientLayerDeps({
|
|
742
|
+
client: undefined,
|
|
743
|
+
environments: [instanceSecrets, clientSecrets],
|
|
744
|
+
resolved: [],
|
|
745
|
+
clientReads: deletedReads,
|
|
746
|
+
createdEcs: deleted,
|
|
747
|
+
}),
|
|
748
|
+
executionCreatedThrough("aexec_pc_deleted", "pcl_dashboard"),
|
|
749
|
+
"",
|
|
750
|
+
);
|
|
751
|
+
expect(deletedReads).toEqual(["pcl_dashboard"]);
|
|
752
|
+
expect(deleted[0]?.spec?.data["SHARED_API_SECRET"]).toBeUndefined();
|
|
753
|
+
expect(deleted[0]?.spec?.data["INSTANCE_WINS"]?.value).toBe("instance");
|
|
754
|
+
|
|
755
|
+
// A client of another organization: no environment value crosses an
|
|
756
|
+
// organization, so its refs are never even resolved.
|
|
757
|
+
const foreign: ExecutionContext[] = [];
|
|
758
|
+
const foreignResolved: ApiResourceReference[] = [];
|
|
759
|
+
await buildAndPersistExecutionContext(
|
|
760
|
+
platformClientLayerDeps({
|
|
761
|
+
client: mintingClient("globex", "embed-secrets"),
|
|
762
|
+
environments: [instanceSecrets, environmentOf("embed-secrets", { SHARED_API_SECRET: "x" }, "globex")],
|
|
763
|
+
resolved: foreignResolved,
|
|
764
|
+
clientReads: [],
|
|
765
|
+
createdEcs: foreign,
|
|
766
|
+
}),
|
|
767
|
+
executionCreatedThrough("aexec_pc_foreign", "pcl_dashboard"),
|
|
768
|
+
"",
|
|
769
|
+
);
|
|
770
|
+
expect(foreign[0]?.spec?.data["SHARED_API_SECRET"]).toBeUndefined();
|
|
771
|
+
expect(foreignResolved.map((ref) => ref.org)).toEqual(["acme"]);
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
it("a client environment that no longer exists fails the create with the client named in the chain", async () => {
|
|
775
|
+
try {
|
|
776
|
+
await buildAndPersistExecutionContext(
|
|
777
|
+
platformClientLayerDeps({
|
|
778
|
+
client: mintingClient(PC_ORG, "gone-secrets"),
|
|
779
|
+
environments: [instanceSecrets],
|
|
780
|
+
resolved: [],
|
|
781
|
+
clientReads: [],
|
|
782
|
+
createdEcs: [],
|
|
783
|
+
}),
|
|
784
|
+
executionCreatedThrough("aexec_pc_gone", "pcl_dashboard"),
|
|
785
|
+
"",
|
|
786
|
+
);
|
|
787
|
+
expect.unreachable("expected NotFound");
|
|
788
|
+
} catch (error) {
|
|
789
|
+
const connectError = ConnectError.from(error);
|
|
790
|
+
expect(connectError.code).toBe(Code.NotFound);
|
|
791
|
+
expect(connectError.rawMessage).toBe(
|
|
792
|
+
"resolve platform client pcl_dashboard environment_refs: " +
|
|
793
|
+
"resolve environment ref (org=acme, slug=gone-secrets): " +
|
|
794
|
+
"rpc error: code = NotFound desc = environment not found: gone-secrets",
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
it("the layer survives the runner's status writes, so recovery delivers it again", async () => {
|
|
800
|
+
const execution = executionCreatedThrough("aexec_pc_recover", "pcl_dashboard");
|
|
801
|
+
// The runner's progressive status write, as UpdateStatus applies it.
|
|
802
|
+
applyUpdateStatusMerge(
|
|
803
|
+
execution,
|
|
804
|
+
create(AgentExecutionUpdateStatusInputSchema, {
|
|
805
|
+
executionId: "aexec_pc_recover",
|
|
806
|
+
status: { phase: ExecutionPhase.EXECUTION_FAILED, error: "boom" },
|
|
807
|
+
}),
|
|
808
|
+
silentLogger,
|
|
809
|
+
);
|
|
810
|
+
expect(
|
|
811
|
+
execution.status?.audit?.specAudit?.createdBy?.platformClientId,
|
|
812
|
+
).toBe("pcl_dashboard");
|
|
813
|
+
|
|
814
|
+
// Recover rebuilds from the persisted execution with no pre-resolved
|
|
815
|
+
// instance and no minted caller (lifecycle.ts's recreate step).
|
|
816
|
+
const createdEcs: ExecutionContext[] = [];
|
|
817
|
+
await buildAndPersistExecutionContext(
|
|
818
|
+
platformClientLayerDeps({
|
|
819
|
+
client: mintingClient(PC_ORG, "embed-secrets"),
|
|
820
|
+
environments: [instanceSecrets, clientSecrets],
|
|
821
|
+
resolved: [],
|
|
822
|
+
clientReads: [],
|
|
823
|
+
createdEcs,
|
|
824
|
+
}),
|
|
825
|
+
execution,
|
|
826
|
+
"",
|
|
827
|
+
);
|
|
828
|
+
expect(createdEcs[0]?.spec?.data["SHARED_API_SECRET"]?.value).toBe(
|
|
829
|
+
"client-secret",
|
|
830
|
+
);
|
|
831
|
+
});
|
|
@@ -434,6 +434,13 @@ function stubBuilderDeps(overrides?: {
|
|
|
434
434
|
readSecretValue: async () => "",
|
|
435
435
|
updateSecrets: async () => {},
|
|
436
436
|
} as unknown as ManagedEnvironmentService,
|
|
437
|
+
// No execution here was created by a minted user, so the minting
|
|
438
|
+
// client's layer answers from the audit without reading a client.
|
|
439
|
+
platformClients: {
|
|
440
|
+
findById: async () => {
|
|
441
|
+
throw new Error("no minting client in this test");
|
|
442
|
+
},
|
|
443
|
+
},
|
|
437
444
|
};
|
|
438
445
|
}
|
|
439
446
|
|