@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
  * on the in-process transport (the `internal` class);
21
21
  * - checkMyPermission's three arms: an enterprise-tiered kind is false
22
22
  * with the Authorizer never consulted (the settings navigation stays
23
- * hidden); can_grant_access outside the scope is false; an
23
+ * hidden); can_grant_access outside the scope is false, while
24
+ * can_manage_audience is the Authorizer's answer on every kind; an
24
25
  * organization permission is the composed Authorizer's answer; an
25
26
  * unknown permission is INVALID_ARGUMENT;
26
27
  * - the tuple-half queries are UNIMPLEMENTED with the edition named;
@@ -65,6 +66,7 @@ import {
65
66
  roleNotGrantableMessage,
66
67
  unknownPermissionMessage,
67
68
  } from "../constants.js";
69
+ import { seedOrganizations } from "../../organization/__tests__/support.js";
68
70
  import { orgRole, triple } from "./support.js";
69
71
 
70
72
  const OPERATOR_EMAIL = "operator@example.com";
@@ -115,6 +117,7 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
115
117
  });
116
118
  const port = await server.start();
117
119
  transport = createGrpcTransport({ baseUrl: `http://127.0.0.1:${port}` });
120
+ await seedOrganizations(transport, ["acme"]);
118
121
  command = createClient(IamPolicyCommandController, transport);
119
122
  query = createClient(IamPolicyQueryController, transport);
120
123
  organizations = createClient(OrganizationCommandController, transport);
@@ -191,7 +194,21 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
191
194
  it("deleting the organization cleans its rows", async () => {
192
195
  const org = await newOrganization();
193
196
  await organizations.delete({ value: org });
194
- const count = await query.getPrincipalsCount({
197
+ // The wire now refuses a count of an Organization that is gone
198
+ // (stigmer#1163), so the rows are counted by the server itself: the
199
+ // in-process caller skips authorization.
200
+ const wire = await grpcError(() =>
201
+ query.getPrincipalsCount({
202
+ orgId: org,
203
+ principalKind: "identity_account",
204
+ }),
205
+ );
206
+ expect(wire.code).toBe(Code.NotFound);
207
+ expect(wire.rawMessage).toBe(`Organization not found: ${org}`);
208
+ const count = await createClient(
209
+ IamPolicyQueryController,
210
+ server.inProcessTransport,
211
+ ).getPrincipalsCount({
195
212
  orgId: org,
196
213
  principalKind: "identity_account",
197
214
  });
@@ -468,6 +485,20 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
468
485
  expect(viewAgent.isAuthorized).toBe(true);
469
486
  });
470
487
 
488
+ it("can_manage_audience is the Authorizer's answer on every kind, where can_grant_access is false outside the scope — the console's audience controls stay the owner's on open source (stigmer#1495)", async () => {
489
+ for (const [kind, id] of [
490
+ ["agent", "agt_01hzzzzzzzzzzzzzzzzzzzzzzz"],
491
+ ["workflow_instance", "win_01hzzzzzzzzzzzzzzzzzzzzzzz"],
492
+ ] as const) {
493
+ const resource = create(ApiResourceRefSchema, { kind, id });
494
+ const audience = await query.checkMyPermission({ resource, relation: "can_manage_audience" });
495
+ const grant = await query.checkMyPermission({ resource, relation: "can_grant_access" });
496
+ // The permissive single-team Authorizer allows everything it is asked.
497
+ expect(audience.isAuthorized, kind).toBe(true);
498
+ expect(grant.isAuthorized, kind).toBe(false);
499
+ }
500
+ });
501
+
471
502
  it("an unknown permission is INVALID_ARGUMENT, quoted", async () => {
472
503
  const error = await grpcError(() =>
473
504
  query.checkMyPermission({
@@ -21,7 +21,11 @@
21
21
  * - `member` otherwise;
22
22
  * - nothing for a non-`user` caller class; nothing on an organization
23
23
  * the account already holds a row on (idempotent by construction), so
24
- * a run that faulted midway converges on the next.
24
+ * a run that faulted midway converges on the next;
25
+ * - nothing, in the reconciliation, for a federated account, whose
26
+ * subject and email its identity provider chose: one asserting a
27
+ * founder's subject and the operator's email earns neither `owner`
28
+ * nor `admin`, nor `member` anywhere.
25
29
  *
26
30
  * ensureOperatorOwnership(operator): `owner` on every organization that
27
31
  * has NO owner row (Q-S4-3: a boot-time write never overrides a recorded
@@ -60,6 +64,7 @@ import { TimestampSchema } from "@bufbuild/protobuf/wkt";
60
64
  import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
61
65
  import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
62
66
  import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
67
+ import { ApiResourceReferenceSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
63
68
  import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
64
69
  import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
65
70
  import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
@@ -81,7 +86,7 @@ import {
81
86
  } from "../membership.js";
82
87
  import type { MembershipRules, ScannedResource } from "../membership.js";
83
88
  import type { IamPolicyStore } from "../store.js";
84
- import { fakeIamPolicyStore } from "./support.js";
89
+ import { NO_RECORDED_CREATORS, fakeIamPolicyStore } from "./support.js";
85
90
  import type { FakeIamPolicyStore } from "./support.js";
86
91
 
87
92
  const OPERATOR_EMAIL = "operator@example.com";
@@ -124,6 +129,7 @@ describe("membership rules", () => {
124
129
  ): MembershipRules {
125
130
  return newMembershipRules({
126
131
  grantPath: newIamPolicyGrantPath({
132
+ creators: NO_RECORDED_CREATORS,
127
133
  policies: port,
128
134
  lifecycle: undefined,
129
135
  logger: silentLogger,
@@ -139,6 +145,7 @@ describe("membership rules", () => {
139
145
  store = temp.store;
140
146
  policies = fakeIamPolicyStore();
141
147
  grantPath = newIamPolicyGrantPath({
148
+ creators: NO_RECORDED_CREATORS,
142
149
  policies,
143
150
  lifecycle: undefined,
144
151
  logger: silentLogger,
@@ -242,10 +249,18 @@ describe("membership rules", () => {
242
249
  sub: string,
243
250
  email: string,
244
251
  createdAtSeconds: number,
245
- overrides: { isMachineAccount?: boolean } = {},
252
+ overrides: { isMachineAccount?: boolean; federated?: boolean } = {},
246
253
  ): Promise<IdentityAccount> {
247
254
  const row = account(sub, email);
248
255
  row.spec!.isMachineAccount = overrides.isMachineAccount ?? false;
256
+ if (overrides.federated === true) {
257
+ row.spec!.provisioningMode = IdentityAccountProvisioningMode.federated;
258
+ row.spec!.identityProviderRef = create(ApiResourceReferenceSchema, {
259
+ org: "acme",
260
+ kind: ApiResourceKind.identity_provider,
261
+ slug: "acme-okta",
262
+ });
263
+ }
249
264
  row.status = create(IdentityAccountSchema, {
250
265
  status: {
251
266
  audit: {
@@ -321,7 +336,11 @@ describe("membership rules", () => {
321
336
  const alice = account("auth0|alice", "alice@example.com");
322
337
  await rules.onAccountCreated(alice, userCaller(alice.metadata!.id));
323
338
  // The organization was bootstrapped; its owner is then revoked.
324
- await grantPath.revokeOrgAccess(alice.metadata!.id, "acme");
339
+ await grantPath.revokeOrgAccess(
340
+ alice.metadata!.id,
341
+ "acme",
342
+ userCaller(alice.metadata!.id),
343
+ );
325
344
  expect(policies.rows.size).toBe(0);
326
345
  // A second creator stamp keeps the "no other person created anything here" arm from firing on its own.
327
346
  await seedAgent("agt_alice", "acme", alice.metadata!.id);
@@ -336,7 +355,11 @@ describe("membership rules", () => {
336
355
  await seedOrg("acme", "auth0|alice");
337
356
  const alice = account("auth0|alice", "alice@example.com");
338
357
  await rules.onAccountCreated(alice, userCaller(alice.metadata!.id));
339
- await grantPath.revokeOrgAccess(alice.metadata!.id, "acme");
358
+ await grantPath.revokeOrgAccess(
359
+ alice.metadata!.id,
360
+ "acme",
361
+ userCaller(alice.metadata!.id),
362
+ );
340
363
  expect(policies.rows.size).toBe(0);
341
364
  // No blueprint at all: only the organization's own creator stamp stands between mallory and admin.
342
365
  const mallory = account("auth0|mallory", "mallory@example.com");
@@ -646,6 +669,13 @@ describe("membership rules", () => {
646
669
  IdentityAccountProvisioningMode.platform_client;
647
670
  expect(isPersonAccount(endUser)).toBe(false);
648
671
  });
672
+
673
+ it("a federated account is not: its subject and its email are the ones its identity provider asserted", () => {
674
+ const federated = account("okta|00u1", OPERATOR_EMAIL);
675
+ federated.spec!.provisioningMode =
676
+ IdentityAccountProvisioningMode.federated;
677
+ expect(isPersonAccount(federated)).toBe(false);
678
+ });
649
679
  });
650
680
 
651
681
  describe("ensureRolesForExistingAccounts", () => {
@@ -671,6 +701,18 @@ describe("membership rules", () => {
671
701
  );
672
702
  });
673
703
 
704
+ it("a federated account earns no role, though its provider asserted the founder's subject and the operator's email", async () => {
705
+ await seedOrg("acme", "auth0|alice");
706
+ await seedOrg("globex", "auth0|carol");
707
+ const federated = await seedAccount("auth0|alice", OPERATOR_EMAIL, 100, {
708
+ federated: true,
709
+ });
710
+
711
+ await rules.ensureRolesForExistingAccounts();
712
+
713
+ expect(rolesOf(federated.metadata!.id)).toEqual([]);
714
+ });
715
+
674
716
  it("a second call is a no-op — the marker short-circuits before any read", async () => {
675
717
  await seedOrg("acme", "auth0|alice");
676
718
  await seedAccount("auth0|alice", "alice@example.com", 100);
@@ -52,6 +52,7 @@ const CONTRACT_CASE_NAMES = [
52
52
  "countDistinctPrincipalsByResource counts (kind, id) pairs, not rows, optionally by principal kind",
53
53
  "findScopeTuple skips identity_account and team principals and owner and creator relations",
54
54
  "deleteById removes the row; the triple is free to be granted again",
55
+ "a change record changes nothing about the row: save and deleteById behave as without one",
55
56
  "deleteById of an unknown id resolves",
56
57
  "a disconnected store is an infrastructure fault, never 'not found'",
57
58
  "two concurrent saves of one triple end in one row and DuplicatePolicyErrors only",
@@ -61,7 +61,12 @@ import { policyIdFor } from "../constants.js";
61
61
  import { newIamPolicyGrantPath } from "../grant-path.js";
62
62
  import { newBuiltInRoleLifecycle } from "../role-lifecycle.js";
63
63
  import type { IamPolicyStore } from "../store.js";
64
- import { fakeIamPolicyStore, orgRole, triple } from "./support.js";
64
+ import {
65
+ NO_RECORDED_CREATORS,
66
+ fakeIamPolicyStore,
67
+ orgRole,
68
+ triple,
69
+ } from "./support.js";
65
70
  import type { RecordedEvent } from "./support.js";
66
71
 
67
72
  const ALICE_SUBJECT = "auth0|alice";
@@ -129,6 +134,7 @@ function lifecycleOver(
129
134
  }),
130
135
  );
131
136
  const grantPath = newIamPolicyGrantPath({
137
+ creators: NO_RECORDED_CREATORS,
132
138
  policies: store,
133
139
  lifecycle: undefined,
134
140
  logger: silentLogger,
@@ -230,17 +236,26 @@ describe("onResourceDeleted: the rows die with the resource", () => {
230
236
  it("an organization's deletion removes every row on it, as resource and as principal", async () => {
231
237
  const recorded: RecordedEvent[] = [];
232
238
  const { lifecycle, grantPath, store } = lifecycleOver(recorded);
233
- await grantPath.grant(orgRole(ALICE, "owner", "acme"), caller(ALICE));
234
- await grantPath.grant(orgRole(ALICE, "member", "acme"), caller(ALICE));
239
+ await grantPath.grant(
240
+ orgRole(ALICE, "owner", "acme"),
241
+ caller(ALICE),
242
+ "grant",
243
+ );
244
+ await grantPath.grant(
245
+ orgRole(ALICE, "member", "acme"),
246
+ caller(ALICE),
247
+ "grant",
248
+ );
235
249
  await grantPath.grant(
236
250
  triple({ kind: "organization", id: "acme" }, "organization", {
237
251
  kind: "agent",
238
252
  id: AGENT,
239
253
  }),
240
254
  caller(ALICE),
255
+ "structural",
241
256
  );
242
257
  const unrelated = orgRole(ALICE, "member", "globex");
243
- await grantPath.grant(unrelated, caller(ALICE));
258
+ await grantPath.grant(unrelated, caller(ALICE), "grant");
244
259
  recorded.length = 0;
245
260
 
246
261
  await lifecycle.onResourceDeleted(
@@ -263,10 +278,22 @@ describe("onResourceDeleted: the rows die with the resource", () => {
263
278
  it("an identity account's deletion removes every row it holds anywhere", async () => {
264
279
  const recorded: RecordedEvent[] = [];
265
280
  const { lifecycle, grantPath, store } = lifecycleOver(recorded);
266
- await grantPath.grant(orgRole(ALICE, "owner", "acme"), caller(ALICE));
267
- await grantPath.grant(orgRole(ALICE, "member", "globex"), caller(ALICE));
281
+ await grantPath.grant(
282
+ orgRole(ALICE, "owner", "acme"),
283
+ caller(ALICE),
284
+ "grant",
285
+ );
286
+ await grantPath.grant(
287
+ orgRole(ALICE, "member", "globex"),
288
+ caller(ALICE),
289
+ "grant",
290
+ );
268
291
  const bob = accountIdFor("auth0|bob");
269
- await grantPath.grant(orgRole(bob, "member", "acme"), caller(ALICE));
292
+ await grantPath.grant(
293
+ orgRole(bob, "member", "acme"),
294
+ caller(ALICE),
295
+ "grant",
296
+ );
270
297
  recorded.length = 0;
271
298
 
272
299
  await lifecycle.onResourceDeleted(
@@ -296,6 +323,7 @@ describe("onResourceDeleted: the rows die with the resource", () => {
296
323
  id: AGENT,
297
324
  }),
298
325
  caller(ALICE),
326
+ "grant",
299
327
  );
300
328
  recorded.length = 0;
301
329
 
@@ -315,6 +343,7 @@ describe("the rest of the contract", () => {
315
343
  kind: ApiResourceKind.agent,
316
344
  resourceId: AGENT,
317
345
  orgId: "acme",
346
+ caller: caller(ALICE),
318
347
  shapesToCreate: ["org-viewer"],
319
348
  shapesToDelete: [],
320
349
  });
@@ -349,7 +378,11 @@ describe("the rest of the contract", () => {
349
378
  deleteById: () => Promise.reject(new Error("disk full")),
350
379
  };
351
380
  const { lifecycle, grantPath } = lifecycleOver([], faulty);
352
- await grantPath.grant(orgRole(ALICE, "owner", "acme"), caller(ALICE));
381
+ await grantPath.grant(
382
+ orgRole(ALICE, "owner", "acme"),
383
+ caller(ALICE),
384
+ "grant",
385
+ );
353
386
 
354
387
  await expect(
355
388
  lifecycle.onResourceDeleted(
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Pins roles.ts (20260913.01 slice 5): the five assignable roles' display
2
+ * Pins roles.ts (20260913.01 slice 5): the six assignable roles' display
3
3
  * metadata and the allowlist that keeps structural relations out of every
4
4
  * access listing — moved from the cloud's iam/policy/roles.ts (the Java
5
5
  * IamRoleMetadata port). The allowlist is proven by construction here:
@@ -15,13 +15,14 @@ import {
15
15
  } from "../roles.js";
16
16
 
17
17
  describe("the assignable-role allowlist", () => {
18
- it("is exactly the five roles a person can hold, in display order", () => {
18
+ it("is exactly the six roles a person can hold, in display order", () => {
19
19
  expect(assignableRelations()).toEqual([
20
20
  "owner",
21
21
  "admin",
22
22
  "member",
23
23
  "viewer",
24
24
  "participant",
25
+ "editor",
25
26
  ]);
26
27
  });
27
28
 
@@ -12,6 +12,9 @@
12
12
  * names no relation qualifier; a team is granted only its kind's team
13
13
  * roles (never ownership, never on a kind that lists none), always as its
14
14
  * members, and nothing at all under open source's organization-only scope.
15
+ * The editor role is granted on the three blueprints to a person or a team
16
+ * where the scope passes the proto through, refused on a kind that does not
17
+ * list it, and granted nowhere under open source's scope.
15
18
  *
16
19
  * Grant and Revoke are proven for the one thing a step adds over the
17
20
  * grant path: the result they leave under POLICY_RESULT_KEY (the revoke
@@ -44,6 +47,7 @@ import type { Authorizer, AuthzCheck } from "../../../extensions/authorizer.js";
44
47
  import type { CallerIdentity } from "../../../extensions/identity.js";
45
48
  import type { PolicyGrantScope } from "../../../extensions/policy-grant-scope.js";
46
49
  import { trustedLocalIdentityFor } from "../../../pipeline/interceptors/auth.js";
50
+ import { grantableRolesFor } from "../../../pipeline/apiresource-meta.js";
47
51
  import { RequestContext } from "../../../pipeline/request-context.js";
48
52
  import {
49
53
  LAST_OWNER_MESSAGE,
@@ -71,7 +75,12 @@ import {
71
75
  orgAccessOwnerRoleChange,
72
76
  specOwnerRoleChange,
73
77
  } from "../steps.js";
74
- import { fakeIamPolicyStore, orgRole, triple } from "./support.js";
78
+ import {
79
+ NO_RECORDED_CREATORS,
80
+ fakeIamPolicyStore,
81
+ orgRole,
82
+ triple,
83
+ } from "./support.js";
75
84
 
76
85
  const caller = trustedLocalIdentityFor({
77
86
  email: "operator@example.com",
@@ -333,6 +342,60 @@ describe("ValidateGrantableRole", () => {
333
342
  });
334
343
  });
335
344
 
345
+ describe("the editor role", () => {
346
+ // The hosted edition's scope narrows nothing: every role the proto lists
347
+ // is grantable (the cloud's policy grant scope).
348
+ const everyProtoRole = newValidateGrantableRoleStep({
349
+ grantableRoles: (kind) => grantableRolesFor(kind),
350
+ });
351
+ const person = { kind: "identity_account", id: "ida_bob" };
352
+ const team = { kind: "team", id: "tm_sre", relation: "member" };
353
+ const blueprints = [
354
+ ["agent", "agt_1"],
355
+ ["workflow", "wfl_1"],
356
+ ["mcp_server", "mcp_1"],
357
+ ] as const;
358
+
359
+ it("is granted on an agent, a workflow and an MCP server, to a person and to a team", () => {
360
+ for (const [kind, id] of blueprints) {
361
+ for (const principal of [person, team]) {
362
+ expect(
363
+ everyProtoRole.execute(
364
+ contextOf(triple(principal, "editor", { kind, id })),
365
+ ),
366
+ `${principal.kind} on ${kind}`,
367
+ ).toBeUndefined();
368
+ }
369
+ }
370
+ });
371
+
372
+ it("is refused on a kind that does not list it, with the kind's own roles named", async () => {
373
+ const error = await refusal(() =>
374
+ everyProtoRole.execute(
375
+ contextOf(triple(person, "editor", { kind: "skill", id: "skl_1" })),
376
+ ),
377
+ );
378
+ expect(error.code).toBe(Code.InvalidArgument);
379
+ expect(error.rawMessage).toBe(
380
+ roleNotGrantableMessage("editor", "skill", ["owner", "viewer"]),
381
+ );
382
+ });
383
+
384
+ it("is granted nowhere under open source's organization-only scope", async () => {
385
+ for (const [kind, id] of blueprints) {
386
+ const error = await refusal(() =>
387
+ organizationOnly.execute(
388
+ contextOf(triple(person, "editor", { kind, id })),
389
+ ),
390
+ );
391
+ expect(error.code, kind).toBe(Code.Unimplemented);
392
+ expect(error.rawMessage, kind).toBe(
393
+ PER_RESOURCE_GRANTS_UNIMPLEMENTED_MESSAGE,
394
+ );
395
+ }
396
+ });
397
+ });
398
+
336
399
  it("a scope can only NARROW the proto: a role it adds is clipped from the list", async () => {
337
400
  const widening = newValidateGrantableRoleStep(
338
401
  scopeOf(
@@ -382,6 +445,7 @@ describe("ValidateGrantableRole", () => {
382
445
  describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
383
446
  function pathOverFreshStore() {
384
447
  return newIamPolicyGrantPath({
448
+ creators: NO_RECORDED_CREATORS,
385
449
  policies: fakeIamPolicyStore(),
386
450
  lifecycle: undefined,
387
451
  logger: silent,
@@ -392,9 +456,9 @@ describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
392
456
  const path = pathOverFreshStore();
393
457
  const spec = orgRole("ida_bob", "member", "acme");
394
458
  const first = contextOf(spec);
395
- await newGrantStep(path).execute(first);
459
+ await newGrantStep(path, "grant").execute(first);
396
460
  const second = contextOf(spec);
397
- await newGrantStep(path).execute(second);
461
+ await newGrantStep(path, "grant").execute(second);
398
462
  expect((first.get(POLICY_RESULT_KEY) as IamPolicy).metadata?.id).toBe(
399
463
  policyIdFor(spec),
400
464
  );
@@ -406,7 +470,7 @@ describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
406
470
  it("Revoke leaves the revoked row, or the default instance when there was none (Java's idempotent delete)", async () => {
407
471
  const path = pathOverFreshStore();
408
472
  const spec = orgRole("ida_bob", "member", "acme");
409
- await path.grant(spec, caller);
473
+ await path.grant(spec, caller, "grant");
410
474
  const revoked = contextOf(spec);
411
475
  await newRevokeStep(path).execute(revoked);
412
476
  expect((revoked.get(POLICY_RESULT_KEY) as IamPolicy).metadata?.id).toBe(
@@ -468,9 +532,14 @@ describe("owner is assigned by owners", () => {
468
532
  roles: ReadonlyArray<readonly [string, string]>,
469
533
  ): Promise<ReturnType<typeof fakeIamPolicyStore> & { readonly ownerReads: () => number }> {
470
534
  const store = fakeIamPolicyStore();
471
- const path = newIamPolicyGrantPath({ policies: store, lifecycle: undefined, logger: silent });
535
+ const path = newIamPolicyGrantPath({
536
+ creators: NO_RECORDED_CREATORS,
537
+ policies: store,
538
+ lifecycle: undefined,
539
+ logger: silent,
540
+ });
472
541
  for (const [account, role] of roles) {
473
- await path.grant(orgRole(account, role, "acme"), caller);
542
+ await path.grant(orgRole(account, role, "acme"), caller, "grant");
474
543
  }
475
544
  let reads = 0;
476
545
  const read = store.findByResourceWithRelations.bind(store);
@@ -16,9 +16,12 @@ import { IamPolicySpecSchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1
16
16
 
17
17
  import type {
18
18
  PolicyGrantedEvent,
19
+ OrganizationAffiliationEvent,
19
20
  PolicyRevokedEvent,
20
21
  ResourceAuthorizationLifecycle,
21
22
  } from "../../../extensions/resource-authorization.js";
23
+ import type { PolicyChangeRecord } from "../change.js";
24
+ import type { ResourceCreators } from "../grant-path.js";
22
25
  import { DuplicatePolicyError } from "../store.js";
23
26
  import type { IamPolicyStore } from "../store.js";
24
27
 
@@ -52,6 +55,24 @@ export function triple(
52
55
  });
53
56
  }
54
57
 
58
+ /** A server that stores no resource rows: nothing the sweep meets is anyone's authorship. */
59
+ export const NO_RECORDED_CREATORS: ResourceCreators = {
60
+ async creatorOf() {
61
+ return undefined;
62
+ },
63
+ };
64
+
65
+ /** Recorded creators by `kind:id`, the removal sweep's authorship read. */
66
+ export function recordedCreators(
67
+ creators: Readonly<Record<string, string>>,
68
+ ): ResourceCreators {
69
+ return {
70
+ async creatorOf(kind, id) {
71
+ return creators[`${kind}:${id}`];
72
+ },
73
+ };
74
+ }
75
+
55
76
  /** What a recording fixture saw, in order. */
56
77
  export type RecordedEvent =
57
78
  | { readonly kind: "row-save"; readonly id: string }
@@ -65,10 +86,23 @@ export type RecordedEvent =
65
86
  readonly kind: "revoked";
66
87
  readonly id: string | undefined;
67
88
  readonly relation: string;
89
+ }
90
+ | {
91
+ readonly kind: "affiliation-changing" | "affiliation-changed";
92
+ readonly pair: string;
68
93
  };
69
94
 
95
+ /** A change record the fake store was handed, beside the write it came with. */
96
+ export interface RecordedChange {
97
+ readonly op: "save" | "delete";
98
+ readonly id: string;
99
+ readonly record: PolicyChangeRecord | undefined;
100
+ }
101
+
70
102
  export interface FakeIamPolicyStore extends IamPolicyStore {
71
103
  readonly rows: Map<string, IamPolicy>;
104
+ /** Every save and delete that changed a row, with the record it carried. */
105
+ readonly changes: RecordedChange[];
72
106
  }
73
107
 
74
108
  /** An in-memory store with the adapter's primary-key semantics; writes are recorded when a log is given. */
@@ -76,6 +110,7 @@ export function fakeIamPolicyStore(
76
110
  recorded?: RecordedEvent[],
77
111
  ): FakeIamPolicyStore {
78
112
  const rows = new Map<string, IamPolicy>();
113
+ const changes: RecordedChange[] = [];
79
114
  const all = (): IamPolicy[] => [...rows.values()];
80
115
  const matches = (
81
116
  policy: IamPolicy,
@@ -92,16 +127,20 @@ export function fakeIamPolicyStore(
92
127
  (resourceId === undefined || policy.spec?.resource?.id === resourceId);
93
128
  return {
94
129
  rows,
95
- async save(policy) {
130
+ changes,
131
+ async save(policy, record) {
96
132
  const id = policy.metadata?.id ?? "";
97
133
  if (rows.has(id)) {
98
134
  throw new DuplicatePolicyError(`IAM policy '${id}' already exists`);
99
135
  }
100
136
  rows.set(id, policy);
137
+ changes.push({ op: "save", id, record });
101
138
  recorded?.push({ kind: "row-save", id });
102
139
  },
103
- async deleteById(id) {
104
- rows.delete(id);
140
+ async deleteById(id, record) {
141
+ if (rows.delete(id)) {
142
+ changes.push({ op: "delete", id, record });
143
+ }
105
144
  recorded?.push({ kind: "row-delete", id });
106
145
  },
107
146
  async findById(id) {
@@ -165,9 +204,34 @@ export function fakeIamPolicyStore(
165
204
  /** A lifecycle that records the two policy hooks and can be told to fail either. */
166
205
  export function recordingLifecycle(
167
206
  recorded: RecordedEvent[],
168
- faults: { readonly granted?: Error; readonly revoked?: Error } = {},
207
+ faults: {
208
+ readonly granted?: Error;
209
+ readonly revoked?: Error;
210
+ readonly changing?: Error;
211
+ } = {},
212
+ options: { readonly affiliation?: boolean } = {},
169
213
  ): ResourceAuthorizationLifecycle {
214
+ const pair = (event: OrganizationAffiliationEvent): string =>
215
+ `${event.identityAccountId}@${event.organizationId}`;
216
+ const affiliation: Pick<
217
+ ResourceAuthorizationLifecycle,
218
+ "onOrganizationAffiliationChanging" | "onOrganizationAffiliationChanged"
219
+ > =
220
+ options.affiliation === true
221
+ ? {
222
+ async onOrganizationAffiliationChanging(event) {
223
+ if (faults.changing !== undefined) {
224
+ throw faults.changing;
225
+ }
226
+ recorded.push({ kind: "affiliation-changing", pair: pair(event) });
227
+ },
228
+ async onOrganizationAffiliationChanged(event) {
229
+ recorded.push({ kind: "affiliation-changed", pair: pair(event) });
230
+ },
231
+ }
232
+ : {};
170
233
  return {
234
+ ...affiliation,
171
235
  async onResourceCreated() {},
172
236
  async onResourceDeleted() {},
173
237
  async onVisibilityChanged() {},