@stigmer/server 3.40.1 → 3.41.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.
Files changed (527) hide show
  1. package/dist/authorization/authorizer.d.ts +16 -10
  2. package/dist/authorization/authorizer.d.ts.map +1 -1
  3. package/dist/authorization/authorizer.js +17 -9
  4. package/dist/authorization/authorizer.js.map +1 -1
  5. package/dist/authorization/derived-tuples.d.ts +7 -3
  6. package/dist/authorization/derived-tuples.d.ts.map +1 -1
  7. package/dist/authorization/derived-tuples.js +62 -6
  8. package/dist/authorization/derived-tuples.js.map +1 -1
  9. package/dist/authorization/evaluator.d.ts +11 -7
  10. package/dist/authorization/evaluator.d.ts.map +1 -1
  11. package/dist/authorization/evaluator.js +16 -10
  12. package/dist/authorization/evaluator.js.map +1 -1
  13. package/dist/authorization/list-read-scope.d.ts +4 -0
  14. package/dist/authorization/list-read-scope.d.ts.map +1 -1
  15. package/dist/authorization/list-read-scope.js +1 -0
  16. package/dist/authorization/list-read-scope.js.map +1 -1
  17. package/dist/authorization/model/data/authorization-model.json +830 -67
  18. package/dist/authorization/model/execution-viewer.d.ts.map +1 -1
  19. package/dist/authorization/model/execution-viewer.js +26 -24
  20. package/dist/authorization/model/execution-viewer.js.map +1 -1
  21. package/dist/authorization/model/index.d.ts +4 -1
  22. package/dist/authorization/model/index.d.ts.map +1 -1
  23. package/dist/authorization/model/index.js +4 -1
  24. package/dist/authorization/model/index.js.map +1 -1
  25. package/dist/authorization/model/rewrite.d.ts +5 -3
  26. package/dist/authorization/model/rewrite.d.ts.map +1 -1
  27. package/dist/authorization/organization-directory.d.ts +44 -0
  28. package/dist/authorization/organization-directory.d.ts.map +1 -1
  29. package/dist/authorization/organization-directory.js +1 -0
  30. package/dist/authorization/organization-directory.js.map +1 -1
  31. package/dist/authorization/person.d.ts +14 -1
  32. package/dist/authorization/person.d.ts.map +1 -1
  33. package/dist/authorization/person.js +16 -0
  34. package/dist/authorization/person.js.map +1 -1
  35. package/dist/authorization/policy-check.d.ts +52 -0
  36. package/dist/authorization/policy-check.d.ts.map +1 -0
  37. package/dist/authorization/policy-check.js +35 -0
  38. package/dist/authorization/policy-check.js.map +1 -0
  39. package/dist/authorization/posture.d.ts +30 -4
  40. package/dist/authorization/posture.d.ts.map +1 -1
  41. package/dist/authorization/posture.js +58 -0
  42. package/dist/authorization/posture.js.map +1 -1
  43. package/dist/authorization/resource-creators.d.ts +4 -0
  44. package/dist/authorization/resource-creators.d.ts.map +1 -0
  45. package/dist/authorization/resource-creators.js +44 -0
  46. package/dist/authorization/resource-creators.js.map +1 -0
  47. package/dist/authorization/trusted-local-authorizer.d.ts +9 -0
  48. package/dist/authorization/trusted-local-authorizer.d.ts.map +1 -0
  49. package/dist/authorization/trusted-local-authorizer.js +70 -0
  50. package/dist/authorization/trusted-local-authorizer.js.map +1 -0
  51. package/dist/authorization/tuples.d.ts +12 -0
  52. package/dist/authorization/tuples.d.ts.map +1 -1
  53. package/dist/authorization/tuples.js +3 -0
  54. package/dist/authorization/tuples.js.map +1 -1
  55. package/dist/boot/compose.d.ts.map +1 -1
  56. package/dist/boot/compose.js +132 -43
  57. package/dist/boot/compose.js.map +1 -1
  58. package/dist/boot/config.d.ts +22 -7
  59. package/dist/boot/config.d.ts.map +1 -1
  60. package/dist/boot/config.js +2 -1
  61. package/dist/boot/config.js.map +1 -1
  62. package/dist/boot/inprocess.d.ts.map +1 -1
  63. package/dist/boot/inprocess.js +10 -4
  64. package/dist/boot/inprocess.js.map +1 -1
  65. package/dist/boot/list-indexes.d.ts.map +1 -1
  66. package/dist/boot/list-indexes.js +6 -1
  67. package/dist/boot/list-indexes.js.map +1 -1
  68. package/dist/boot/logger.d.ts +3 -1
  69. package/dist/boot/logger.d.ts.map +1 -1
  70. package/dist/boot/logger.js +3 -1
  71. package/dist/boot/logger.js.map +1 -1
  72. package/dist/boot/oauth-redirect-uri.d.ts +33 -12
  73. package/dist/boot/oauth-redirect-uri.d.ts.map +1 -1
  74. package/dist/boot/oauth-redirect-uri.js +43 -14
  75. package/dist/boot/oauth-redirect-uri.js.map +1 -1
  76. package/dist/boot/skill-transfer-origin.d.ts +46 -14
  77. package/dist/boot/skill-transfer-origin.d.ts.map +1 -1
  78. package/dist/boot/skill-transfer-origin.js +53 -13
  79. package/dist/boot/skill-transfer-origin.js.map +1 -1
  80. package/dist/domain/agentchannel/steps.d.ts +8 -6
  81. package/dist/domain/agentchannel/steps.d.ts.map +1 -1
  82. package/dist/domain/agentchannel/steps.js +9 -7
  83. package/dist/domain/agentchannel/steps.js.map +1 -1
  84. package/dist/domain/agentexecution/controller.d.ts +7 -0
  85. package/dist/domain/agentexecution/controller.d.ts.map +1 -1
  86. package/dist/domain/agentexecution/controller.js +1 -1
  87. package/dist/domain/agentexecution/controller.js.map +1 -1
  88. package/dist/domain/agentexecution/create-steps.d.ts +26 -12
  89. package/dist/domain/agentexecution/create-steps.d.ts.map +1 -1
  90. package/dist/domain/agentexecution/create-steps.js +61 -43
  91. package/dist/domain/agentexecution/create-steps.js.map +1 -1
  92. package/dist/domain/agentexecution/submit-approval.d.ts.map +1 -1
  93. package/dist/domain/agentexecution/submit-approval.js +9 -6
  94. package/dist/domain/agentexecution/submit-approval.js.map +1 -1
  95. package/dist/domain/agentexecution/submit-file-decision.d.ts.map +1 -1
  96. package/dist/domain/agentexecution/submit-file-decision.js +5 -4
  97. package/dist/domain/agentexecution/submit-file-decision.js.map +1 -1
  98. package/dist/domain/agentshare/steps.d.ts +5 -3
  99. package/dist/domain/agentshare/steps.d.ts.map +1 -1
  100. package/dist/domain/agentshare/steps.js +6 -4
  101. package/dist/domain/agentshare/steps.js.map +1 -1
  102. package/dist/domain/apikey/verifier.d.ts +7 -0
  103. package/dist/domain/apikey/verifier.d.ts.map +1 -1
  104. package/dist/domain/apikey/verifier.js +34 -1
  105. package/dist/domain/apikey/verifier.js.map +1 -1
  106. package/dist/domain/channelapp/controller.d.ts +4 -3
  107. package/dist/domain/channelapp/controller.d.ts.map +1 -1
  108. package/dist/domain/channelapp/controller.js.map +1 -1
  109. package/dist/domain/executioncontext/steps.d.ts +2 -1
  110. package/dist/domain/executioncontext/steps.d.ts.map +1 -1
  111. package/dist/domain/executioncontext/steps.js +2 -1
  112. package/dist/domain/executioncontext/steps.js.map +1 -1
  113. package/dist/domain/iampolicy/access-lists.d.ts.map +1 -1
  114. package/dist/domain/iampolicy/access-lists.js +57 -2
  115. package/dist/domain/iampolicy/access-lists.js.map +1 -1
  116. package/dist/domain/iampolicy/change.d.ts +53 -0
  117. package/dist/domain/iampolicy/change.d.ts.map +1 -0
  118. package/dist/domain/iampolicy/change.js +44 -0
  119. package/dist/domain/iampolicy/change.js.map +1 -0
  120. package/dist/domain/iampolicy/constants.d.ts +6 -0
  121. package/dist/domain/iampolicy/constants.d.ts.map +1 -1
  122. package/dist/domain/iampolicy/constants.js +6 -0
  123. package/dist/domain/iampolicy/constants.js.map +1 -1
  124. package/dist/domain/iampolicy/controller.d.ts.map +1 -1
  125. package/dist/domain/iampolicy/controller.js +9 -5
  126. package/dist/domain/iampolicy/controller.js.map +1 -1
  127. package/dist/domain/iampolicy/grant-path.d.ts +31 -13
  128. package/dist/domain/iampolicy/grant-path.d.ts.map +1 -1
  129. package/dist/domain/iampolicy/grant-path.js +216 -19
  130. package/dist/domain/iampolicy/grant-path.js.map +1 -1
  131. package/dist/domain/iampolicy/membership.d.ts +11 -3
  132. package/dist/domain/iampolicy/membership.d.ts.map +1 -1
  133. package/dist/domain/iampolicy/membership.js +18 -13
  134. package/dist/domain/iampolicy/membership.js.map +1 -1
  135. package/dist/domain/iampolicy/resource-store.d.ts.map +1 -1
  136. package/dist/domain/iampolicy/resource-store.js +4 -0
  137. package/dist/domain/iampolicy/resource-store.js.map +1 -1
  138. package/dist/domain/iampolicy/role-lifecycle.d.ts.map +1 -1
  139. package/dist/domain/iampolicy/role-lifecycle.js +2 -2
  140. package/dist/domain/iampolicy/role-lifecycle.js.map +1 -1
  141. package/dist/domain/iampolicy/roles.d.ts.map +1 -1
  142. package/dist/domain/iampolicy/roles.js +7 -0
  143. package/dist/domain/iampolicy/roles.js.map +1 -1
  144. package/dist/domain/iampolicy/steps.d.ts +4 -3
  145. package/dist/domain/iampolicy/steps.d.ts.map +1 -1
  146. package/dist/domain/iampolicy/steps.js +7 -7
  147. package/dist/domain/iampolicy/steps.js.map +1 -1
  148. package/dist/domain/iampolicy/store-contract.d.ts.map +1 -1
  149. package/dist/domain/iampolicy/store-contract.js +22 -1
  150. package/dist/domain/iampolicy/store-contract.js.map +1 -1
  151. package/dist/domain/iampolicy/store.d.ts +18 -5
  152. package/dist/domain/iampolicy/store.d.ts.map +1 -1
  153. package/dist/domain/iampolicy/store.js.map +1 -1
  154. package/dist/domain/identityaccount/constants.d.ts +15 -0
  155. package/dist/domain/identityaccount/constants.d.ts.map +1 -1
  156. package/dist/domain/identityaccount/constants.js +17 -0
  157. package/dist/domain/identityaccount/constants.js.map +1 -1
  158. package/dist/domain/identityaccount/controller.d.ts.map +1 -1
  159. package/dist/domain/identityaccount/controller.js +17 -6
  160. package/dist/domain/identityaccount/controller.js.map +1 -1
  161. package/dist/domain/identityaccount/resolve.d.ts +47 -0
  162. package/dist/domain/identityaccount/resolve.d.ts.map +1 -1
  163. package/dist/domain/identityaccount/resolve.js +38 -1
  164. package/dist/domain/identityaccount/resolve.js.map +1 -1
  165. package/dist/domain/identityaccount/resource-store.d.ts.map +1 -1
  166. package/dist/domain/identityaccount/resource-store.js +11 -1
  167. package/dist/domain/identityaccount/resource-store.js.map +1 -1
  168. package/dist/domain/identityaccount/steps.d.ts +2 -1
  169. package/dist/domain/identityaccount/steps.d.ts.map +1 -1
  170. package/dist/domain/identityaccount/steps.js +4 -3
  171. package/dist/domain/identityaccount/steps.js.map +1 -1
  172. package/dist/domain/identityaccount/store-contract.js +2 -2
  173. package/dist/domain/identityaccount/store-contract.js.map +1 -1
  174. package/dist/domain/identityaccount/store.d.ts +6 -1
  175. package/dist/domain/identityaccount/store.d.ts.map +1 -1
  176. package/dist/domain/mcpserver/connect-sandbox.d.ts +67 -0
  177. package/dist/domain/mcpserver/connect-sandbox.d.ts.map +1 -0
  178. package/dist/domain/mcpserver/connect-sandbox.js +64 -0
  179. package/dist/domain/mcpserver/connect-sandbox.js.map +1 -0
  180. package/dist/domain/mcpserver/connect.d.ts +42 -10
  181. package/dist/domain/mcpserver/connect.d.ts.map +1 -1
  182. package/dist/domain/mcpserver/connect.js +147 -40
  183. package/dist/domain/mcpserver/connect.js.map +1 -1
  184. package/dist/domain/mcpserver/controller.js +4 -2
  185. package/dist/domain/mcpserver/controller.js.map +1 -1
  186. package/dist/domain/mcpserver/engine.d.ts +26 -7
  187. package/dist/domain/mcpserver/engine.d.ts.map +1 -1
  188. package/dist/domain/mcpserver/engine.js.map +1 -1
  189. package/dist/domain/mcpserver/start-connect.d.ts +5 -0
  190. package/dist/domain/mcpserver/start-connect.d.ts.map +1 -1
  191. package/dist/domain/mcpserver/start-connect.js +38 -15
  192. package/dist/domain/mcpserver/start-connect.js.map +1 -1
  193. package/dist/domain/memory/controller.js +2 -1
  194. package/dist/domain/memory/controller.js.map +1 -1
  195. package/dist/domain/memory/list-index.d.ts +2 -0
  196. package/dist/domain/memory/list-index.d.ts.map +1 -0
  197. package/dist/domain/memory/list-index.js +31 -0
  198. package/dist/domain/memory/list-index.js.map +1 -0
  199. package/dist/domain/memory/queries.d.ts +10 -0
  200. package/dist/domain/memory/queries.d.ts.map +1 -0
  201. package/dist/domain/memory/queries.js +54 -0
  202. package/dist/domain/memory/queries.js.map +1 -0
  203. package/dist/domain/memory/steps.d.ts +13 -11
  204. package/dist/domain/memory/steps.d.ts.map +1 -1
  205. package/dist/domain/memory/steps.js +26 -57
  206. package/dist/domain/memory/steps.js.map +1 -1
  207. package/dist/domain/organization/steps.d.ts.map +1 -1
  208. package/dist/domain/organization/steps.js +1 -1
  209. package/dist/domain/organization/steps.js.map +1 -1
  210. package/dist/domain/platformclient/mint.d.ts.map +1 -1
  211. package/dist/domain/platformclient/mint.js +2 -2
  212. package/dist/domain/platformclient/mint.js.map +1 -1
  213. package/dist/domain/platformclient/verifier.d.ts.map +1 -1
  214. package/dist/domain/platformclient/verifier.js +6 -3
  215. package/dist/domain/platformclient/verifier.js.map +1 -1
  216. package/dist/domain/plugin/push.d.ts.map +1 -1
  217. package/dist/domain/plugin/push.js +1 -0
  218. package/dist/domain/plugin/push.js.map +1 -1
  219. package/dist/domain/schedule/steps.d.ts +3 -1
  220. package/dist/domain/schedule/steps.d.ts.map +1 -1
  221. package/dist/domain/schedule/steps.js +3 -1
  222. package/dist/domain/schedule/steps.js.map +1 -1
  223. package/dist/domain/skill/push.d.ts.map +1 -1
  224. package/dist/domain/skill/push.js +1 -0
  225. package/dist/domain/skill/push.js.map +1 -1
  226. package/dist/domain/workflow/registry/data/task-kind-registry.json +27 -1
  227. package/dist/domain/workflowexecution/submit-approval.d.ts +5 -2
  228. package/dist/domain/workflowexecution/submit-approval.d.ts.map +1 -1
  229. package/dist/domain/workflowexecution/submit-approval.js +1 -1
  230. package/dist/domain/workflowexecution/submit-approval.js.map +1 -1
  231. package/dist/domain/workflowexecution/submit-file-decision.d.ts +5 -2
  232. package/dist/domain/workflowexecution/submit-file-decision.d.ts.map +1 -1
  233. package/dist/domain/workflowexecution/submit-file-decision.js +1 -1
  234. package/dist/domain/workflowexecution/submit-file-decision.js.map +1 -1
  235. package/dist/domain/workflowexecution/submit-workflow-task-approval.d.ts.map +1 -1
  236. package/dist/domain/workflowexecution/submit-workflow-task-approval.js +12 -1
  237. package/dist/domain/workflowexecution/submit-workflow-task-approval.js.map +1 -1
  238. package/dist/domain/workflowinstance/controller.d.ts +6 -3
  239. package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
  240. package/dist/domain/workflowinstance/controller.js +12 -7
  241. package/dist/domain/workflowinstance/controller.js.map +1 -1
  242. package/dist/domain/workflowinstance/steps.d.ts +31 -0
  243. package/dist/domain/workflowinstance/steps.d.ts.map +1 -1
  244. package/dist/domain/workflowinstance/steps.js +88 -1
  245. package/dist/domain/workflowinstance/steps.js.map +1 -1
  246. package/dist/extensions/composed-services.d.ts +56 -0
  247. package/dist/extensions/composed-services.d.ts.map +1 -0
  248. package/dist/extensions/composed-services.js +2 -0
  249. package/dist/extensions/composed-services.js.map +1 -0
  250. package/dist/extensions/drivers.d.ts +32 -1
  251. package/dist/extensions/drivers.d.ts.map +1 -1
  252. package/dist/extensions/identity.d.ts +4 -1
  253. package/dist/extensions/identity.d.ts.map +1 -1
  254. package/dist/extensions/identity.js +4 -1
  255. package/dist/extensions/identity.js.map +1 -1
  256. package/dist/extensions/registry.d.ts +37 -0
  257. package/dist/extensions/registry.d.ts.map +1 -1
  258. package/dist/extensions/registry.js +50 -0
  259. package/dist/extensions/registry.js.map +1 -1
  260. package/dist/extensions/resource-authorization.d.ts +78 -0
  261. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  262. package/dist/extensions/resource-row-reader.d.ts +43 -0
  263. package/dist/extensions/resource-row-reader.d.ts.map +1 -0
  264. package/dist/extensions/resource-row-reader.js +2 -0
  265. package/dist/extensions/resource-row-reader.js.map +1 -0
  266. package/dist/extensions/visitor-classifier.d.ts +41 -0
  267. package/dist/extensions/visitor-classifier.d.ts.map +1 -0
  268. package/dist/extensions/visitor-classifier.js +2 -0
  269. package/dist/extensions/visitor-classifier.js.map +1 -0
  270. package/dist/identity/oidc-userinfo.d.ts +6 -1
  271. package/dist/identity/oidc-userinfo.d.ts.map +1 -1
  272. package/dist/identity/oidc-userinfo.js.map +1 -1
  273. package/dist/identity/oidc-verifier.d.ts.map +1 -1
  274. package/dist/identity/oidc-verifier.js +37 -8
  275. package/dist/identity/oidc-verifier.js.map +1 -1
  276. package/dist/index.d.ts +14 -6
  277. package/dist/index.d.ts.map +1 -1
  278. package/dist/index.js +25 -9
  279. package/dist/index.js.map +1 -1
  280. package/dist/pipeline/errors.d.ts +8 -0
  281. package/dist/pipeline/errors.d.ts.map +1 -1
  282. package/dist/pipeline/errors.js +25 -16
  283. package/dist/pipeline/errors.js.map +1 -1
  284. package/dist/pipeline/interceptors/auth.d.ts +17 -9
  285. package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
  286. package/dist/pipeline/interceptors/auth.js +17 -9
  287. package/dist/pipeline/interceptors/auth.js.map +1 -1
  288. package/dist/pipeline/steps/authorization-tuples.d.ts +23 -1
  289. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  290. package/dist/pipeline/steps/authorization-tuples.js +42 -0
  291. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  292. package/dist/pipeline/steps/authorize.d.ts +6 -5
  293. package/dist/pipeline/steps/authorize.d.ts.map +1 -1
  294. package/dist/pipeline/steps/authorize.js +6 -5
  295. package/dist/pipeline/steps/authorize.js.map +1 -1
  296. package/dist/pipeline/steps/defaults.d.ts +12 -0
  297. package/dist/pipeline/steps/defaults.d.ts.map +1 -1
  298. package/dist/pipeline/steps/defaults.js +42 -7
  299. package/dist/pipeline/steps/defaults.js.map +1 -1
  300. package/dist/pipeline/steps/guard-memory-capture.d.ts +13 -15
  301. package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
  302. package/dist/pipeline/steps/guard-memory-capture.js +2 -3
  303. package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
  304. package/dist/runnerauth/built-in-runner-credential-provider.d.ts +0 -2
  305. package/dist/runnerauth/built-in-runner-credential-provider.d.ts.map +1 -1
  306. package/dist/runnerauth/built-in-runner-credential-provider.js +8 -17
  307. package/dist/runnerauth/built-in-runner-credential-provider.js.map +1 -1
  308. package/dist/runnerauth/runner-credential-provider.d.ts +17 -7
  309. package/dist/runnerauth/runner-credential-provider.d.ts.map +1 -1
  310. package/dist/runnerauth/runner-credential-provider.js.map +1 -1
  311. package/dist/sandbox/docker.d.ts.map +1 -1
  312. package/dist/sandbox/docker.js +3 -0
  313. package/dist/sandbox/docker.js.map +1 -1
  314. package/dist/sandbox/kubernetes.d.ts.map +1 -1
  315. package/dist/sandbox/kubernetes.js +3 -0
  316. package/dist/sandbox/kubernetes.js.map +1 -1
  317. package/dist/sandbox/local-process.d.ts.map +1 -1
  318. package/dist/sandbox/local-process.js +4 -0
  319. package/dist/sandbox/local-process.js.map +1 -1
  320. package/dist/sandbox/provisioner.d.ts +18 -6
  321. package/dist/sandbox/provisioner.d.ts.map +1 -1
  322. package/dist/sandbox/provisioner.js.map +1 -1
  323. package/dist/temporal/manager.d.ts +5 -0
  324. package/dist/temporal/manager.d.ts.map +1 -1
  325. package/dist/temporal/manager.js +9 -0
  326. package/dist/temporal/manager.js.map +1 -1
  327. package/dist/temporal/mcpserver/engine-client.d.ts +2 -2
  328. package/dist/temporal/mcpserver/engine-client.d.ts.map +1 -1
  329. package/dist/temporal/mcpserver/engine-client.js +6 -4
  330. package/dist/temporal/mcpserver/engine-client.js.map +1 -1
  331. package/dist/temporal/mcpserver/names.d.ts +13 -2
  332. package/dist/temporal/mcpserver/names.d.ts.map +1 -1
  333. package/dist/temporal/mcpserver/names.js +15 -2
  334. package/dist/temporal/mcpserver/names.js.map +1 -1
  335. package/dist/temporal/sdk-logger.d.ts +74 -0
  336. package/dist/temporal/sdk-logger.d.ts.map +1 -0
  337. package/dist/temporal/sdk-logger.js +143 -0
  338. package/dist/temporal/sdk-logger.js.map +1 -0
  339. package/package.json +6 -6
  340. package/src/authorization/README.md +18 -6
  341. package/src/authorization/__tests__/authorizer.test.ts +5 -1
  342. package/src/authorization/__tests__/derived-tuples.test.ts +26 -0
  343. package/src/authorization/__tests__/evaluator.test.ts +4 -0
  344. package/src/authorization/__tests__/list-read-scope.test.ts +11 -5
  345. package/src/authorization/__tests__/store-tests.test.ts +3 -1
  346. package/src/authorization/__tests__/trusted-local-authorizer.test.ts +155 -0
  347. package/src/authorization/__tests__/unit-owned-kinds.test.ts +420 -0
  348. package/src/authorization/__tests__/wire-permissions.test.ts +31 -2
  349. package/src/authorization/authorizer.ts +21 -10
  350. package/src/authorization/derived-tuples.ts +92 -18
  351. package/src/authorization/evaluator.ts +30 -15
  352. package/src/authorization/list-read-scope.ts +4 -0
  353. package/src/authorization/model/__tests__/registry.test.ts +23 -0
  354. package/src/authorization/model/data/authorization-model.json +830 -67
  355. package/src/authorization/model/execution-viewer.ts +32 -27
  356. package/src/authorization/model/index.ts +4 -1
  357. package/src/authorization/model/rewrite.ts +5 -3
  358. package/src/authorization/organization-directory.ts +4 -0
  359. package/src/authorization/person.ts +32 -1
  360. package/src/authorization/policy-check.ts +105 -0
  361. package/src/authorization/posture.ts +45 -4
  362. package/src/authorization/resource-creators.ts +48 -0
  363. package/src/authorization/trusted-local-authorizer.ts +91 -0
  364. package/src/authorization/tuples.ts +17 -0
  365. package/src/boot/__tests__/compose.test.ts +120 -4
  366. package/src/boot/__tests__/list-indexes.test.ts +4 -0
  367. package/src/boot/__tests__/oauth-redirect-uri.test.ts +121 -10
  368. package/src/boot/__tests__/skill-transfer-origin.test.ts +96 -25
  369. package/src/boot/compose.ts +153 -61
  370. package/src/boot/config.ts +28 -12
  371. package/src/boot/inprocess.ts +18 -4
  372. package/src/boot/list-indexes.ts +6 -1
  373. package/src/boot/logger.ts +3 -1
  374. package/src/boot/oauth-redirect-uri.ts +62 -17
  375. package/src/boot/skill-transfer-origin.ts +71 -16
  376. package/src/domain/agent/__tests__/agent.test.ts +42 -1
  377. package/src/domain/agentchannel/__tests__/agentchannel.test.ts +9 -0
  378. package/src/domain/agentchannel/__tests__/channel-runtime.test.ts +2 -0
  379. package/src/domain/agentchannel/__tests__/create-authorization.test.ts +7 -6
  380. package/src/domain/agentchannel/steps.ts +9 -7
  381. package/src/domain/agentexecution/__tests__/agentexecution.test.ts +148 -56
  382. package/src/domain/agentexecution/__tests__/create-steps.test.ts +175 -12
  383. package/src/domain/agentexecution/__tests__/file-review-seed.ts +91 -0
  384. package/src/domain/agentexecution/controller.ts +8 -0
  385. package/src/domain/agentexecution/create-steps.ts +74 -44
  386. package/src/domain/agentexecution/submit-approval.ts +9 -6
  387. package/src/domain/agentexecution/submit-file-decision.ts +5 -4
  388. package/src/domain/agentinstance/__tests__/agentinstance.test.ts +2 -0
  389. package/src/domain/agentshare/__tests__/agentshare.test.ts +17 -0
  390. package/src/domain/agentshare/__tests__/create-authorization.test.ts +5 -4
  391. package/src/domain/agentshare/steps.ts +6 -4
  392. package/src/domain/apikey/__tests__/verifier.test.ts +73 -1
  393. package/src/domain/apikey/verifier.ts +45 -1
  394. package/src/domain/artifact/__tests__/artifact.test.ts +13 -24
  395. package/src/domain/channelapp/__tests__/channelapp.test.ts +7 -0
  396. package/src/domain/channelapp/controller.ts +4 -3
  397. package/src/domain/environment/__tests__/environment.test.ts +13 -0
  398. package/src/domain/executioncontext/__tests__/executioncontext.test.ts +2 -0
  399. package/src/domain/executioncontext/steps.ts +2 -1
  400. package/src/domain/iampolicy/__tests__/access-lists.test.ts +79 -0
  401. package/src/domain/iampolicy/__tests__/change.test.ts +63 -0
  402. package/src/domain/iampolicy/__tests__/controller.test.ts +39 -3
  403. package/src/domain/iampolicy/__tests__/grant-path.test.ts +595 -27
  404. package/src/domain/iampolicy/__tests__/iampolicy.test.ts +33 -2
  405. package/src/domain/iampolicy/__tests__/membership.test.ts +47 -5
  406. package/src/domain/iampolicy/__tests__/resource-store.test.ts +1 -0
  407. package/src/domain/iampolicy/__tests__/role-lifecycle.test.ts +41 -8
  408. package/src/domain/iampolicy/__tests__/roles.test.ts +3 -2
  409. package/src/domain/iampolicy/__tests__/steps.test.ts +75 -6
  410. package/src/domain/iampolicy/__tests__/support.ts +68 -4
  411. package/src/domain/iampolicy/access-lists.ts +70 -2
  412. package/src/domain/iampolicy/change.ts +109 -0
  413. package/src/domain/iampolicy/constants.ts +8 -0
  414. package/src/domain/iampolicy/controller.ts +17 -3
  415. package/src/domain/iampolicy/grant-path.ts +349 -31
  416. package/src/domain/iampolicy/membership.ts +32 -12
  417. package/src/domain/iampolicy/resource-store.ts +4 -0
  418. package/src/domain/iampolicy/role-lifecycle.ts +2 -0
  419. package/src/domain/iampolicy/roles.ts +8 -0
  420. package/src/domain/iampolicy/steps.ts +15 -5
  421. package/src/domain/iampolicy/store-contract.ts +37 -1
  422. package/src/domain/iampolicy/store.ts +19 -5
  423. package/src/domain/identityaccount/__tests__/resolve.test.ts +246 -2
  424. package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -1
  425. package/src/domain/identityaccount/constants.ts +20 -0
  426. package/src/domain/identityaccount/controller.ts +20 -5
  427. package/src/domain/identityaccount/resolve.ts +80 -1
  428. package/src/domain/identityaccount/resource-store.ts +14 -1
  429. package/src/domain/identityaccount/steps.ts +4 -3
  430. package/src/domain/identityaccount/store-contract.ts +4 -4
  431. package/src/domain/identityaccount/store.ts +6 -1
  432. package/src/domain/mcpserver/__tests__/connect-authorization.test.ts +1 -0
  433. package/src/domain/mcpserver/__tests__/connect.test.ts +358 -15
  434. package/src/domain/mcpserver/__tests__/mcpserver.test.ts +2 -0
  435. package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +2 -0
  436. package/src/domain/mcpserver/__tests__/store-faults.test.ts +2 -0
  437. package/src/domain/mcpserver/connect-sandbox.ts +135 -0
  438. package/src/domain/mcpserver/connect.ts +226 -56
  439. package/src/domain/mcpserver/controller.ts +8 -2
  440. package/src/domain/mcpserver/engine.ts +24 -6
  441. package/src/domain/mcpserver/start-connect.ts +49 -10
  442. package/src/domain/memory/__tests__/memory.test.ts +92 -22
  443. package/src/domain/memory/__tests__/queries.test.ts +173 -0
  444. package/src/domain/memory/controller.ts +2 -1
  445. package/src/domain/memory/list-index.ts +32 -0
  446. package/src/domain/memory/queries.ts +72 -0
  447. package/src/domain/memory/steps.ts +26 -63
  448. package/src/domain/oauthapp/__tests__/oauthapp.test.ts +14 -0
  449. package/src/domain/organization/__tests__/support.ts +41 -0
  450. package/src/domain/organization/steps.ts +1 -0
  451. package/src/domain/platformclient/mint.ts +6 -2
  452. package/src/domain/platformclient/verifier.ts +6 -3
  453. package/src/domain/plugin/__tests__/plugin.test.ts +11 -24
  454. package/src/domain/plugin/push.ts +1 -0
  455. package/src/domain/schedule/__tests__/schedule.composed.test.ts +2 -0
  456. package/src/domain/schedule/steps.ts +3 -1
  457. package/src/domain/session/__tests__/session.test.ts +2 -0
  458. package/src/domain/skill/__tests__/skill.test.ts +7 -25
  459. package/src/domain/skill/push.ts +1 -0
  460. package/src/domain/workflow/__tests__/workflow.test.ts +2 -0
  461. package/src/domain/workflow/registry/data/task-kind-registry.json +27 -1
  462. package/src/domain/workflowexecution/__tests__/forward-attribution-composed.test.ts +270 -0
  463. package/src/domain/workflowexecution/__tests__/submit-workflow-task-approval.test.ts +196 -0
  464. package/src/domain/workflowexecution/__tests__/workflowexecution.test.ts +3 -57
  465. package/src/domain/workflowexecution/submit-approval.ts +9 -2
  466. package/src/domain/workflowexecution/submit-file-decision.ts +6 -1
  467. package/src/domain/workflowexecution/submit-workflow-task-approval.ts +23 -5
  468. package/src/domain/workflowinstance/controller.ts +27 -9
  469. package/src/domain/workflowinstance/steps.ts +123 -1
  470. package/src/extensions/__tests__/apikey-before-sign-in-composed.test.ts +172 -0
  471. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +80 -1
  472. package/src/extensions/__tests__/composed-services-composed.test.ts +236 -0
  473. package/src/extensions/__tests__/extension-composition.test.ts +229 -16
  474. package/src/extensions/__tests__/identity-account-composed.test.ts +84 -4
  475. package/src/extensions/__tests__/list-read-scope-composed.test.ts +2 -0
  476. package/src/extensions/__tests__/registry.test.ts +147 -1
  477. package/src/extensions/__tests__/secret-cleanup-composed.test.ts +2 -0
  478. package/src/extensions/__tests__/visitor-classifier-points.test.ts +42 -0
  479. package/src/extensions/composed-services.ts +61 -0
  480. package/src/extensions/drivers.ts +33 -1
  481. package/src/extensions/identity.ts +4 -1
  482. package/src/extensions/registry.ts +105 -0
  483. package/src/extensions/resource-authorization.ts +87 -0
  484. package/src/extensions/resource-row-reader.ts +43 -0
  485. package/src/extensions/visitor-classifier.ts +41 -0
  486. package/src/identity/__tests__/oidc-verifier.test.ts +38 -12
  487. package/src/identity/oidc-userinfo.ts +6 -1
  488. package/src/identity/oidc-verifier.ts +42 -8
  489. package/src/index.ts +61 -6
  490. package/src/pipeline/__tests__/steps.test.ts +31 -4
  491. package/src/pipeline/errors.ts +30 -16
  492. package/src/pipeline/interceptors/auth.ts +17 -9
  493. package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +20 -0
  494. package/src/pipeline/steps/__tests__/guard-memory-capture.test.ts +72 -15
  495. package/src/pipeline/steps/authorization-tuples.ts +54 -0
  496. package/src/pipeline/steps/authorize.ts +6 -5
  497. package/src/pipeline/steps/defaults.ts +52 -7
  498. package/src/pipeline/steps/guard-memory-capture.ts +15 -20
  499. package/src/runnerauth/__tests__/built-in-runner-credential-provider.test.ts +1 -1
  500. package/src/runnerauth/__tests__/runner-subject-composed.test.ts +13 -0
  501. package/src/runnerauth/bound-execution.ts +2 -2
  502. package/src/runnerauth/built-in-runner-credential-provider.ts +8 -21
  503. package/src/runnerauth/runner-credential-provider.ts +17 -7
  504. package/src/sandbox/__tests__/docker.integration.test.ts +4 -0
  505. package/src/sandbox/__tests__/kubernetes.test.ts +18 -1
  506. package/src/sandbox/__tests__/local-process.integration.test.ts +4 -0
  507. package/src/sandbox/__tests__/provisioner.test.ts +1 -0
  508. package/src/sandbox/docker.ts +3 -0
  509. package/src/sandbox/kubernetes.ts +3 -0
  510. package/src/sandbox/local-process.ts +4 -0
  511. package/src/sandbox/provisioner.ts +18 -6
  512. package/src/store/postgres/__tests__/support.ts +11 -2
  513. package/src/temporal/README.md +1 -0
  514. package/src/temporal/__tests__/manager.test.ts +56 -4
  515. package/src/temporal/__tests__/sdk-log-workflows.ts +26 -0
  516. package/src/temporal/__tests__/sdk-logger.e2e.test.ts +150 -0
  517. package/src/temporal/__tests__/sdk-logger.test.ts +238 -0
  518. package/src/temporal/manager.ts +9 -0
  519. package/src/temporal/mcpserver/engine-client.ts +8 -3
  520. package/src/temporal/mcpserver/names.ts +16 -2
  521. package/src/temporal/sdk-logger.ts +173 -0
  522. package/dist/authorization/lane-admission.d.ts +0 -50
  523. package/dist/authorization/lane-admission.d.ts.map +0 -1
  524. package/dist/authorization/lane-admission.js +0 -13
  525. package/dist/authorization/lane-admission.js.map +0 -1
  526. package/src/authorization/__tests__/lane-admission.test.ts +0 -115
  527. package/src/authorization/lane-admission.ts +0 -73
@@ -20,7 +20,8 @@
20
20
  * - DeriveAccountId (A1): `metadata.id = accountIdFor(spec.idp_id)`,
21
21
  * replacing whatever the caller sent (the organization's CopySlugToId
22
22
  * precedent, `metadata.proto`'s documented exception). Runs BEFORE
23
- * BuildNewState, which mints only when the id is empty.
23
+ * BuildNewState and claims the id through `assignServerId`, the one
24
+ * way an id survives that step (stigmer/stigmer#1266).
24
25
  * - CheckDuplicate: by SUBJECT, a primary-key read of the derived id —
25
26
  * two accounts may share an email; the account's uniqueness is its
26
27
  * subject, never its slug (the guideline's "domains with different
@@ -59,6 +60,7 @@ import {
59
60
  } from "../../pipeline/errors.js";
60
61
  import type { PipelineStep } from "../../pipeline/pipeline.js";
61
62
  import type { RequestContext } from "../../pipeline/request-context.js";
63
+ import { assignServerId } from "../../pipeline/steps/defaults.js";
62
64
  import { RESOURCE_ID_KEY } from "../../pipeline/steps/delete.js";
63
65
  import { EXISTING_RESOURCE_KEY } from "../../pipeline/steps/load-existing.js";
64
66
  import { TARGET_RESOURCE_KEY } from "../../pipeline/steps/load-target.js";
@@ -108,7 +110,6 @@ export function newDeriveAccountIdStep(): AccountStep {
108
110
  return {
109
111
  name: "DeriveAccountId",
110
112
  execute(ctx: AccountContext): void {
111
- const metadata = requireMetadata(ctx, "derive account id");
112
113
  // ValidateProto ran upstream (idp_id is required), so an empty
113
114
  // subject here is a pipeline-ordering bug, not bad client input.
114
115
  const idpId = specOf(ctx).idpId;
@@ -118,7 +119,7 @@ export function newDeriveAccountIdStep(): AccountStep {
118
119
  "derive account id",
119
120
  );
120
121
  }
121
- metadata.id = accountIdFor(idpId);
122
+ assignServerId(ctx, accountIdFor(idpId));
122
123
  },
123
124
  };
124
125
  }
@@ -360,7 +360,7 @@ const CASES: ReadonlyArray<PortContractDeclaration<IdentityAccountStore>> = [
360
360
  },
361
361
  ],
362
362
  [
363
- "findDirectByIdpId and findDirectByEmail never answer a federated account, while findByIdpId (any mode) does",
363
+ "no subject lookup answers a federated account: its subject is its identity provider's",
364
364
  async ({ store }) => {
365
365
  await store.save(
366
366
  federatedAccount({ idpId: "auth0|fed", email: "fed@example.com" }),
@@ -376,9 +376,9 @@ const CASES: ReadonlyArray<PortContractDeclaration<IdentityAccountStore>> = [
376
376
  "the direct-email lookup must not resolve to a federated account",
377
377
  );
378
378
  assert.equal(
379
- (await store.findByIdpId("auth0|fed"))?.spec?.provisioningMode,
380
- IdentityAccountProvisioningMode.federated,
381
- "the any-mode subject lookup must answer the federated account",
379
+ await store.findByIdpId("auth0|fed"),
380
+ undefined,
381
+ "the subject lookup must not resolve to a federated account: a provider chooses its subjects, so one equal to a platform person's or a platform client user's would otherwise answer for them",
382
382
  );
383
383
  },
384
384
  ],
@@ -59,7 +59,12 @@ export interface IdentityAccountStore {
59
59
  /** Removes the row; no error when it does not exist. */
60
60
  deleteById(id: string): Promise<void>;
61
61
  findById(id: string): Promise<IdentityAccount | undefined>;
62
- /** Any provisioning mode — the getByIdpId RPC's lookup. */
62
+ /**
63
+ * The account under a subject in any mode but federated — the getByIdpId
64
+ * RPC's lookup and the platform-client mint's. A federated subject is its
65
+ * identity provider's to choose, so it is reached only through the
66
+ * federated natural key (provider and subject), never by a bare subject.
67
+ */
63
68
  findByIdpId(idpId: string): Promise<IdentityAccount | undefined>;
64
69
  /** The platform's own subjects only (no federated, no platform-client) — the verifiers' and whoAmI's lookup. */
65
70
  findDirectByIdpId(idpId: string): Promise<IdentityAccount | undefined>;
@@ -118,6 +118,7 @@ function deps(authorizer: Authorizer): McpServerConnectDeps {
118
118
  pendingOAuthStates: store.pendingOAuthStates,
119
119
  secretService: unreachable("secretService"),
120
120
  oauthRedirectUri: "http://localhost:7233/oauth/callback",
121
+ sandboxLane: { enabled: false },
121
122
  outboundFetch: async () => {
122
123
  throw new Error("no outbound fetch in this harness");
123
124
  },
@@ -6,7 +6,11 @@
6
6
  * connect_status bookkeeping (attach skips CONNECTING; results and the
7
7
  * terminal phase ride ONE atomic write; failure_code in CamelCase),
8
8
  * tool-approval preserve-on-empty, the ephemeral EC lifecycle, and
9
- * startConnect's two-layer idempotency + dead-runner warning.
9
+ * startConnect's two-layer idempotency + dead-runner warning, and the
10
+ * connect route (connect-sandbox.ts, stigmer/stigmer#1474): the shared
11
+ * runner queue without a sandbox lane, and with one a connect sandbox
12
+ * per connect, acting as the person through an always-created
13
+ * ExecutionContext row and released exactly once on every exit.
10
14
  *
11
15
  * The wire-level halves are pinned by
12
16
  * mcpserver-connect.conformance.test.ts on local-execution.
@@ -30,7 +34,19 @@ import { createLogger } from "../../../boot/logger.js";
30
34
  import { SecretService } from "../../../encryption/encryption.js";
31
35
  import type { CallerIdentity } from "../../../extensions/identity.js";
32
36
  import { newExecutionScopedRunnerCredentialProvider } from "../../../runnerauth/runner-credential-provider.js";
33
- import { RunnerAuthService } from "../../../runnerauth/runnerauth.js";
37
+ import type {
38
+ RunnerCredentialProvider,
39
+ SandboxCredentialRequest,
40
+ } from "../../../runnerauth/runner-credential-provider.js";
41
+ import {
42
+ RunnerAuthService,
43
+ TOKEN_TYPE_EXECUTION_SCOPED,
44
+ } from "../../../runnerauth/runnerauth.js";
45
+ import type { SandboxLane } from "../../../sandbox/lane.js";
46
+ import type {
47
+ SandboxEnvironment,
48
+ SandboxProvisioner,
49
+ } from "../../../sandbox/provisioner.js";
34
50
  import { SqliteStore } from "../../../store/sqlite/store.js";
35
51
  import { newPermissiveSingleTeamAuthorizer } from "../../../pipeline/steps/authorize.js";
36
52
  import { testCallerIdentity } from "../../../pipeline/__tests__/support.js";
@@ -48,8 +64,10 @@ import {
48
64
  RUNNER_QUEUE_WARNING,
49
65
  startConnect as startConnectRpc,
50
66
  } from "../start-connect.js";
67
+ import { CONNECT_SANDBOX_PROVISIONING_FAILED } from "../connect-sandbox.js";
51
68
  import type {
52
69
  ConnectRunOutcome,
70
+ ConnectTaskQueue,
53
71
  ConnectWorkflowInput,
54
72
  ConnectWorkflowOutput,
55
73
  McpServerConnectEngine,
@@ -82,35 +100,93 @@ interface FakeEngineOptions {
82
100
  attached?: boolean;
83
101
  running?: boolean;
84
102
  pollers?: boolean | undefined;
103
+ /** The start itself fails (Temporal refused the start). */
104
+ startError?: Error;
105
+ /** Runs when a lane begins awaiting the run — the moment an attached lane must already hold nothing. */
106
+ onAwait?: () => void;
85
107
  }
86
108
 
87
109
  interface FakeEngine extends McpServerConnectEngine {
88
110
  readonly startedInputs: ConnectWorkflowInput[];
89
111
  readonly startedTimeouts: number[];
112
+ readonly startedQueues: ConnectTaskQueue[];
113
+ pollerProbes: number;
90
114
  }
91
115
 
92
116
  function fakeEngine(options: FakeEngineOptions = {}): FakeEngine {
93
117
  const startedInputs: ConnectWorkflowInput[] = [];
94
118
  const startedTimeouts: number[] = [];
95
- return {
119
+ const startedQueues: ConnectTaskQueue[] = [];
120
+ const engine: FakeEngine = {
96
121
  startedInputs,
97
122
  startedTimeouts,
98
- async startOrAttachConnect(mcpServerId, input, runTimeoutMs) {
123
+ startedQueues,
124
+ pollerProbes: 0,
125
+ async startOrAttachConnect(mcpServerId, input, runTimeoutMs, taskQueue) {
126
+ if (options.startError !== undefined) {
127
+ throw options.startError;
128
+ }
99
129
  startedInputs.push(input);
100
130
  startedTimeouts.push(runTimeoutMs);
131
+ startedQueues.push(taskQueue);
101
132
  return {
102
133
  workflowId: `stigmer/mcp-server/connect/${mcpServerId}`,
103
134
  attached: options.attached ?? false,
104
- result: async () => options.outcome ?? { ok: true, output: OK_OUTPUT },
135
+ result: async () => {
136
+ options.onAwait?.();
137
+ return options.outcome ?? { ok: true, output: OK_OUTPUT };
138
+ },
105
139
  };
106
140
  },
107
141
  async isConnectRunRunning() {
108
142
  return options.running ?? false;
109
143
  },
110
144
  async hasRunnerQueuePollers() {
145
+ engine.pollerProbes += 1;
111
146
  return options.pollers;
112
147
  },
113
148
  };
149
+ return engine;
150
+ }
151
+
152
+ /** A connect-scope provisioner that records every call; the other scopes are unreachable here. */
153
+ interface FakeConnectProvisioner extends SandboxProvisioner {
154
+ readonly created: Array<{ id: string; env: SandboxEnvironment }>;
155
+ readonly deprovisioned: string[];
156
+ }
157
+
158
+ function fakeConnectProvisioner(options: { createError?: Error } = {}): FakeConnectProvisioner {
159
+ const created: Array<{ id: string; env: SandboxEnvironment }> = [];
160
+ const deprovisioned: string[] = [];
161
+ const unreachable = async (): Promise<never> => {
162
+ throw new Error("only the connect scope is reachable from the connect lanes");
163
+ };
164
+ return {
165
+ created,
166
+ deprovisioned,
167
+ ensureSessionSandbox: unreachable,
168
+ deprovisionSessionSandbox: unreachable,
169
+ ensureWorkflowSandbox: unreachable,
170
+ deprovisionWorkflowSandbox: unreachable,
171
+ async createConnectSandbox(id, env) {
172
+ if (options.createError !== undefined) {
173
+ throw options.createError;
174
+ }
175
+ created.push({ id, env });
176
+ return `sbx-${id}`;
177
+ },
178
+ async deprovisionConnectSandbox(sandboxId) {
179
+ deprovisioned.push(sandboxId);
180
+ },
181
+ probe: unreachable,
182
+ };
183
+ }
184
+
185
+ interface HarnessOptions extends FakeEngineOptions {
186
+ /** Compose a sandbox lane over this provisioner (absent: the external-runner posture). */
187
+ provisioner?: SandboxProvisioner;
188
+ /** The lane's credential provider (default: the harness's execution-scoped runnerAuth). */
189
+ credentials?: RunnerCredentialProvider;
114
190
  }
115
191
 
116
192
  interface Harness {
@@ -149,8 +225,19 @@ const startConnect = (
149
225
  input: Parameters<typeof startConnectRpc>[1],
150
226
  ) => startConnectRpc(deps, input, testCaller);
151
227
 
152
- function makeHarness(options: FakeEngineOptions = {}): Harness {
228
+ function makeHarness(options: HarnessOptions = {}): Harness {
153
229
  const engine = fakeEngine(options);
230
+ const runnerAuth = newExecutionScopedRunnerCredentialProvider(
231
+ RunnerAuthService.fromEnv(),
232
+ );
233
+ const sandboxLane: SandboxLane =
234
+ options.provisioner === undefined
235
+ ? { enabled: false }
236
+ : {
237
+ enabled: true,
238
+ provisioner: options.provisioner,
239
+ credentials: options.credentials ?? runnerAuth,
240
+ };
154
241
  const harness: Harness = {
155
242
  engine,
156
243
  ecCreates: 0,
@@ -182,9 +269,7 @@ function makeHarness(options: FakeEngineOptions = {}): Harness {
182
269
  return create(ExecutionContextSchema);
183
270
  },
184
271
  },
185
- runnerAuth: newExecutionScopedRunnerCredentialProvider(
186
- RunnerAuthService.fromEnv(),
187
- ),
272
+ runnerAuth,
188
273
  // The REAL service over a client backed by nothing: the refresh
189
274
  // pre-flight arms that need it are exercised in the handshake
190
275
  // composed test; here every read throws, which the pre-flight
@@ -210,6 +295,7 @@ function makeHarness(options: FakeEngineOptions = {}): Harness {
210
295
  pendingOAuthStates: store.pendingOAuthStates,
211
296
  secretService: SecretService.create(undefined),
212
297
  oauthRedirectUri: "http://127.0.0.1:8234/auth/oauth/callback",
298
+ sandboxLane,
213
299
  // No arm in this harness dials out; a call is a test bug, not a network.
214
300
  outboundFetch: async () => {
215
301
  throw new Error("no outbound fetch in this harness");
@@ -346,6 +432,8 @@ describe("connect (blocking lane)", () => {
346
432
  expect(result.status?.connectStatus?.failureCode).toBe("");
347
433
  // The sync lane passes the 420s budget to the engine.
348
434
  expect(harness.engine.startedTimeouts[0]).toBe(CONNECT_TIMEOUT.ms);
435
+ // No sandbox lane: the shared runner queue, as always.
436
+ expect(harness.engine.startedQueues).toEqual([{ kind: "runner" }]);
349
437
  });
350
438
 
351
439
  it("preserves existing tool approvals when a reconnect returns none (a degraded runner cannot disarm gates)", async () => {
@@ -613,21 +701,21 @@ describe("startBestEffortConnect (apply tail)", () => {
613
701
  const engine = harness.engine;
614
702
  harness.deps = { ...harness.deps, engineState: () => MCP_SERVER_ENGINE_DISCONNECTED };
615
703
  const server = await seedServer();
616
- await startBestEffortConnect(harness.deps, server);
704
+ await startBestEffortConnect(harness.deps, server, testCaller);
617
705
  expect(engine.startedInputs).toHaveLength(0);
618
706
  });
619
707
 
620
- it("skips servers with env declarations (no caller identity in the background)", async () => {
708
+ it("skips servers with env declarations (their credentials are the connecting person's, not the applier's)", async () => {
621
709
  const harness = makeHarness();
622
710
  const server = await seedServer({ env: true });
623
- await startBestEffortConnect(harness.deps, server);
711
+ await startBestEffortConnect(harness.deps, server, testCaller);
624
712
  expect(harness.engine.startedInputs).toHaveLength(0);
625
713
  });
626
714
 
627
715
  it("connects an env-less server and persists the result", async () => {
628
716
  const harness = makeHarness();
629
717
  const server = await seedServer();
630
- await startBestEffortConnect(harness.deps, server);
718
+ await startBestEffortConnect(harness.deps, server, testCaller);
631
719
  const after = await store.getResource(
632
720
  ApiResourceKind.mcp_server,
633
721
  server.metadata!.id,
@@ -642,7 +730,7 @@ describe("startBestEffortConnect (apply tail)", () => {
642
730
  const server = await seedServer();
643
731
  await store.deleteResource(ApiResourceKind.mcp_server, server.metadata!.id);
644
732
  await expect(
645
- startBestEffortConnect(harness.deps, server),
733
+ startBestEffortConnect(harness.deps, server, testCaller),
646
734
  ).resolves.toBeUndefined();
647
735
  });
648
736
 
@@ -657,7 +745,7 @@ describe("startBestEffortConnect (apply tail)", () => {
657
745
  },
658
746
  });
659
747
  const server = await seedServer({ stdio: false });
660
- await startBestEffortConnect(harness.deps, server);
748
+ await startBestEffortConnect(harness.deps, server, testCaller);
661
749
  const after = await store.getResource(
662
750
  ApiResourceKind.mcp_server,
663
751
  server.metadata!.id,
@@ -673,3 +761,258 @@ describe("startBestEffortConnect (apply tail)", () => {
673
761
  );
674
762
  });
675
763
  });
764
+
765
+ describe("the connect route with a sandbox lane composed (stigmer/stigmer#1474)", () => {
766
+ /** The connect id every lane derives the sandbox, its queue and its credential from. */
767
+ function connectIdOf(harness: Harness): string {
768
+ const created = harness.engine.startedQueues[0];
769
+ expect(created?.kind).toBe("sandbox");
770
+ const name = created?.kind === "sandbox" ? created.name : "";
771
+ expect(name).toMatch(/^mcpconnect:connect-mcps_test_/);
772
+ return name.slice("mcpconnect:".length);
773
+ }
774
+
775
+ it("blocking connect of an env-less server: a binding-only row as the person, a sandbox on the connect's own queue, released once", async () => {
776
+ const provisioner = fakeConnectProvisioner();
777
+ const harness = makeHarness({ provisioner });
778
+ const server = await seedServer();
779
+
780
+ const result = await connect(harness.deps, connectInput(server.metadata!.id));
781
+ expect(result.status?.connectStatus?.phase).toBe(ConnectPhase.succeeded);
782
+
783
+ const connectId = connectIdOf(harness);
784
+ expect(isConnectExecutionId(connectId)).toBe(true);
785
+ // The row the sandbox credential binds through exists, created AS the
786
+ // person, even though the server declares no env.
787
+ expect(harness.ecCreators).toEqual([testCaller]);
788
+ // It is binding-only: the runner is handed no context to read and no
789
+ // payload token, the same no-env discovery path as without a lane.
790
+ expect(harness.engine.startedInputs[0]).toEqual({
791
+ mcp_server_id: server.metadata!.id,
792
+ });
793
+
794
+ expect(provisioner.created).toHaveLength(1);
795
+ const sandbox = provisioner.created[0]!;
796
+ expect(sandbox.id).toBe(connectId);
797
+ expect(sandbox.env.taskQueue).toBe(`mcpconnect:${connectId}`);
798
+ expect(sandbox.env.callerClass).toBe(testCaller.callerClass);
799
+ // The OSS execution-scoped mint, bound to this one connect.
800
+ expect(
801
+ harness.deps.runnerAuth.verify(
802
+ TOKEN_TYPE_EXECUTION_SCOPED,
803
+ sandbox.env.stigmerToken,
804
+ ),
805
+ ).toBe(connectId);
806
+
807
+ expect(provisioner.deprovisioned).toEqual([`sbx-${connectId}`]);
808
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
809
+ });
810
+
811
+ it("blocking connect with runtime_env: the row carries the values and the payload names it, and the sandbox is released once", async () => {
812
+ const provisioner = fakeConnectProvisioner();
813
+ const harness = makeHarness({ provisioner });
814
+ const server = await seedServer();
815
+ await connect(
816
+ harness.deps,
817
+ connectInput(server.metadata!.id, { API_KEY: { value: "k", isSecret: true } }),
818
+ );
819
+ const connectId = connectIdOf(harness);
820
+ const input = harness.engine.startedInputs[0];
821
+ expect(input?.execution_context_id).toBe(connectId);
822
+ expect(input?.execution_context_token).toBeTruthy();
823
+ expect(provisioner.deprovisioned).toEqual([`sbx-${connectId}`]);
824
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
825
+ });
826
+
827
+ it("hands a composed mintSandboxCredential the connect scope, the person and the org", async () => {
828
+ const provisioner = fakeConnectProvisioner();
829
+ const base = newExecutionScopedRunnerCredentialProvider(RunnerAuthService.fromEnv());
830
+ const requests: SandboxCredentialRequest[] = [];
831
+ const credentials: RunnerCredentialProvider = {
832
+ ...base,
833
+ isEnabled: (lane) => base.isEnabled(lane),
834
+ mint: (lane, binding, ttl) => base.mint(lane, binding, ttl),
835
+ verify: (lane, token) => base.verify(lane, token),
836
+ mintSandboxCredential(request) {
837
+ requests.push(request);
838
+ return "edition-connect-token";
839
+ },
840
+ };
841
+ const harness = makeHarness({ provisioner, credentials });
842
+ const server = await seedServer();
843
+ await connect(harness.deps, connectInput(server.metadata!.id));
844
+ const connectId = connectIdOf(harness);
845
+ expect(requests).toEqual([
846
+ {
847
+ scope: "connect",
848
+ sessionId: "",
849
+ executionId: connectId,
850
+ org: "acme",
851
+ callerIdentityId: testCaller.identityId,
852
+ },
853
+ ]);
854
+ expect(provisioner.created[0]?.env.stigmerToken).toBe("edition-connect-token");
855
+ });
856
+
857
+ it("releases the sandbox once when the run fails", async () => {
858
+ const provisioner = fakeConnectProvisioner();
859
+ const harness = makeHarness({
860
+ provisioner,
861
+ outcome: { ok: false, failure: { kind: "application", message: "401" } },
862
+ });
863
+ const server = await seedServer({ stdio: false });
864
+ await expectConnectError(
865
+ connect(harness.deps, connectInput(server.metadata!.id)),
866
+ Code.FailedPrecondition,
867
+ "401",
868
+ );
869
+ expect(provisioner.deprovisioned).toHaveLength(1);
870
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
871
+ });
872
+
873
+ it("gives its own sandbox back before awaiting another lane's run it attached to", async () => {
874
+ const provisioner = fakeConnectProvisioner();
875
+ const heldWhileAwaiting: number[] = [];
876
+ const harness = makeHarness({
877
+ provisioner,
878
+ attached: true,
879
+ onAwait: () =>
880
+ heldWhileAwaiting.push(provisioner.created.length - provisioner.deprovisioned.length),
881
+ });
882
+ const server = await seedServer();
883
+ await connect(harness.deps, connectInput(server.metadata!.id));
884
+ // Nothing idles for the other lane's whole run...
885
+ expect(heldWhileAwaiting).toEqual([0]);
886
+ // ...and the release stays exactly once.
887
+ expect(provisioner.deprovisioned).toHaveLength(1);
888
+ });
889
+
890
+ it("releases the sandbox once when the start itself fails", async () => {
891
+ const provisioner = fakeConnectProvisioner();
892
+ const harness = makeHarness({ provisioner, startError: new Error("frontend down") });
893
+ const server = await seedServer();
894
+ await expectConnectError(
895
+ connect(harness.deps, connectInput(server.metadata!.id)),
896
+ Code.Internal,
897
+ "failed to start connect workflow",
898
+ );
899
+ expect(provisioner.deprovisioned).toHaveLength(1);
900
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
901
+ });
902
+
903
+ it("fails fast with Unavailable, recorded on connect_status, when the sandbox cannot be provisioned", async () => {
904
+ const provisioner = fakeConnectProvisioner({ createError: new Error("quota exceeded") });
905
+ const harness = makeHarness({ provisioner });
906
+ const server = await seedServer();
907
+ await expectConnectError(
908
+ connect(harness.deps, connectInput(server.metadata!.id)),
909
+ Code.Unavailable,
910
+ CONNECT_SANDBOX_PROVISIONING_FAILED,
911
+ );
912
+ // No run was started, so nothing waits on a queue nobody serves.
913
+ expect(harness.engine.startedInputs).toHaveLength(0);
914
+ expect(provisioner.deprovisioned).toHaveLength(0);
915
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
916
+ const after = await store.getResource(
917
+ ApiResourceKind.mcp_server,
918
+ server.metadata!.id,
919
+ McpServerSchema,
920
+ );
921
+ expect(after.status?.connectStatus?.phase).toBe(ConnectPhase.failed);
922
+ expect(after.status?.connectStatus?.failureCode).toBe("Unavailable");
923
+ expect(after.status?.connectStatus?.failureMessage).toBe(
924
+ CONNECT_SANDBOX_PROVISIONING_FAILED,
925
+ );
926
+ });
927
+
928
+ it("startConnect: never probes the sandbox's fresh queue, and the settle releases the sandbox once", async () => {
929
+ const provisioner = fakeConnectProvisioner();
930
+ const harness = makeHarness({ provisioner, pollers: false });
931
+ const server = await seedServer();
932
+ const result = await startConnect(harness.deps, connectInput(server.metadata!.id));
933
+ expect(result.status?.connectStatus?.phase).toBe(ConnectPhase.connecting);
934
+ // The advisory describes the shared queue only; a sandbox created a
935
+ // moment ago has no poller by construction.
936
+ expect(result.status?.connectStatus?.warning).toBe("");
937
+ expect(harness.engine.pollerProbes).toBe(0);
938
+ const connectId = connectIdOf(harness);
939
+ await vi.waitFor(() =>
940
+ expect(provisioner.deprovisioned).toEqual([`sbx-${connectId}`]),
941
+ );
942
+ await vi.waitFor(() => expect(harness.ecDeletes).toEqual(["ectx_1"]));
943
+ });
944
+
945
+ it("startConnect: an attach releases the unused sandbox at once", async () => {
946
+ const provisioner = fakeConnectProvisioner();
947
+ const harness = makeHarness({ provisioner, attached: true });
948
+ const server = await seedServer();
949
+ await startConnect(harness.deps, connectInput(server.metadata!.id));
950
+ expect(provisioner.deprovisioned).toHaveLength(1);
951
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
952
+ });
953
+
954
+ it("startConnect: a sandbox that cannot be provisioned fails the RPC fast and deletes the row", async () => {
955
+ const provisioner = fakeConnectProvisioner({ createError: new Error("quota exceeded") });
956
+ const harness = makeHarness({ provisioner });
957
+ const server = await seedServer();
958
+ await expectConnectError(
959
+ startConnect(harness.deps, connectInput(server.metadata!.id)),
960
+ Code.Unavailable,
961
+ CONNECT_SANDBOX_PROVISIONING_FAILED,
962
+ );
963
+ expect(harness.engine.startedInputs).toHaveLength(0);
964
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
965
+ });
966
+
967
+ it("best-effort connect acts as the applier: its binding row, its sandbox, released once", async () => {
968
+ const provisioner = fakeConnectProvisioner();
969
+ const harness = makeHarness({ provisioner });
970
+ const server = await seedServer();
971
+ const applier = testCallerIdentity({ identityId: "the-applier" });
972
+ await startBestEffortConnect(harness.deps, server, applier);
973
+
974
+ expect(harness.ecCreators).toEqual([applier]);
975
+ const connectId = connectIdOf(harness);
976
+ expect(
977
+ harness.deps.runnerAuth.verify(
978
+ TOKEN_TYPE_EXECUTION_SCOPED,
979
+ provisioner.created[0]!.env.stigmerToken,
980
+ ),
981
+ ).toBe(connectId);
982
+ expect(provisioner.deprovisioned).toEqual([`sbx-${connectId}`]);
983
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
984
+ const after = await store.getResource(
985
+ ApiResourceKind.mcp_server,
986
+ server.metadata!.id,
987
+ McpServerSchema,
988
+ );
989
+ expect(after.status?.connectStatus?.phase).toBe(ConnectPhase.succeeded);
990
+ });
991
+
992
+ it("best-effort connect gives its sandbox back before awaiting a run it attached to", async () => {
993
+ const provisioner = fakeConnectProvisioner();
994
+ const heldWhileAwaiting: number[] = [];
995
+ const harness = makeHarness({
996
+ provisioner,
997
+ attached: true,
998
+ onAwait: () =>
999
+ heldWhileAwaiting.push(provisioner.created.length - provisioner.deprovisioned.length),
1000
+ });
1001
+ const server = await seedServer();
1002
+ await startBestEffortConnect(harness.deps, server, testCaller);
1003
+ expect(heldWhileAwaiting).toEqual([0]);
1004
+ expect(provisioner.deprovisioned).toHaveLength(1);
1005
+ expect(harness.ecDeletes).toEqual(["ectx_1"]);
1006
+ });
1007
+
1008
+ it("best-effort connect without a lane creates no row and runs on the shared queue, as before", async () => {
1009
+ const harness = makeHarness();
1010
+ const server = await seedServer();
1011
+ await startBestEffortConnect(harness.deps, server, testCaller);
1012
+ expect(harness.ecCreates).toBe(0);
1013
+ expect(harness.engine.startedInputs).toEqual([
1014
+ { mcp_server_id: server.metadata!.id },
1015
+ ]);
1016
+ expect(harness.engine.startedQueues).toEqual([{ kind: "runner" }]);
1017
+ });
1018
+ });
@@ -40,6 +40,7 @@ import { loadConfig } from "../../../boot/config.js";
40
40
  import { composeServer } from "../../../boot/compose.js";
41
41
  import type { ComposedServer } from "../../../boot/compose.js";
42
42
  import { createLogger } from "../../../boot/logger.js";
43
+ import { seedOrganizations } from "../../organization/__tests__/support.js";
43
44
 
44
45
  const silentLogger = createLogger({
45
46
  level: "error",
@@ -80,6 +81,7 @@ beforeAll(async () => {
80
81
  const transport: Transport = createGrpcTransport({
81
82
  baseUrl: `http://127.0.0.1:${port}`,
82
83
  });
84
+ await seedOrganizations(transport, [ORG, "other-org"]);
83
85
  command = createClient(McpServerCommandController, transport);
84
86
  query = createClient(McpServerQueryController, transport);
85
87
  });
@@ -40,6 +40,7 @@ import { loadConfig } from "../../../boot/config.js";
40
40
  import { composeServer } from "../../../boot/compose.js";
41
41
  import type { ComposedServer } from "../../../boot/compose.js";
42
42
  import { createLogger } from "../../../boot/logger.js";
43
+ import { seedOrganizations } from "../../organization/__tests__/support.js";
43
44
 
44
45
  const silentLogger = createLogger({
45
46
  level: "error",
@@ -177,6 +178,7 @@ beforeAll(async () => {
177
178
  const transport: Transport = createGrpcTransport({
178
179
  baseUrl: `http://127.0.0.1:${port}`,
179
180
  });
181
+ await seedOrganizations(transport, [ORG]);
180
182
  command = createClient(McpServerCommandController, transport);
181
183
  query = createClient(McpServerQueryController, transport);
182
184
  });
@@ -98,6 +98,8 @@ function connectDeps(
98
98
  oauthGrants: untouchable("oauthGrants"),
99
99
  pendingOAuthStates: untouchable("pendingOAuthStates"),
100
100
  secretService: untouchable("secretService"),
101
+ // The external-runner posture: no connect sandbox is provisioned.
102
+ sandboxLane: { enabled: false },
101
103
  oauthRedirectUri: "http://127.0.0.1:8234/auth/oauth/callback",
102
104
  outboundFetch: untouchable("outboundFetch"),
103
105
  ...overrides,