@stigmer/server 3.21.0 → 3.22.1-dev.20260922095755

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 (383) hide show
  1. package/dist/authorization/authorizer.d.ts +4 -8
  2. package/dist/authorization/authorizer.d.ts.map +1 -1
  3. package/dist/authorization/authorizer.js +5 -9
  4. package/dist/authorization/authorizer.js.map +1 -1
  5. package/dist/authorization/derived-tuples.d.ts.map +1 -1
  6. package/dist/authorization/derived-tuples.js +10 -25
  7. package/dist/authorization/derived-tuples.js.map +1 -1
  8. package/dist/authorization/evaluator.d.ts +13 -8
  9. package/dist/authorization/evaluator.d.ts.map +1 -1
  10. package/dist/authorization/evaluator.js +4 -20
  11. package/dist/authorization/evaluator.js.map +1 -1
  12. package/dist/authorization/list-read-scope.d.ts.map +1 -1
  13. package/dist/authorization/list-read-scope.js +24 -20
  14. package/dist/authorization/list-read-scope.js.map +1 -1
  15. package/dist/authorization/model/agent.d.ts.map +1 -1
  16. package/dist/authorization/model/agent.js +4 -5
  17. package/dist/authorization/model/agent.js.map +1 -1
  18. package/dist/authorization/model/agent_instance.d.ts.map +1 -1
  19. package/dist/authorization/model/agent_instance.js +2 -2
  20. package/dist/authorization/model/agent_instance.js.map +1 -1
  21. package/dist/authorization/model/mcp_server.d.ts.map +1 -1
  22. package/dist/authorization/model/mcp_server.js +2 -2
  23. package/dist/authorization/model/mcp_server.js.map +1 -1
  24. package/dist/authorization/model/organization.d.ts.map +1 -1
  25. package/dist/authorization/model/organization.js +2 -0
  26. package/dist/authorization/model/organization.js.map +1 -1
  27. package/dist/authorization/model/plugin.d.ts.map +1 -1
  28. package/dist/authorization/model/plugin.js +3 -4
  29. package/dist/authorization/model/plugin.js.map +1 -1
  30. package/dist/authorization/model/rewrite.d.ts +8 -10
  31. package/dist/authorization/model/rewrite.d.ts.map +1 -1
  32. package/dist/authorization/model/rewrite.js +0 -3
  33. package/dist/authorization/model/rewrite.js.map +1 -1
  34. package/dist/authorization/model/skill.d.ts.map +1 -1
  35. package/dist/authorization/model/skill.js +2 -2
  36. package/dist/authorization/model/skill.js.map +1 -1
  37. package/dist/authorization/model/workflow.d.ts.map +1 -1
  38. package/dist/authorization/model/workflow.js +2 -2
  39. package/dist/authorization/model/workflow.js.map +1 -1
  40. package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
  41. package/dist/authorization/model/workflow_instance.js +2 -2
  42. package/dist/authorization/model/workflow_instance.js.map +1 -1
  43. package/dist/authorization/organization-directory.d.ts.map +1 -1
  44. package/dist/authorization/organization-directory.js +2 -3
  45. package/dist/authorization/organization-directory.js.map +1 -1
  46. package/dist/authorization/store-test-kit.d.ts +0 -6
  47. package/dist/authorization/store-test-kit.d.ts.map +1 -1
  48. package/dist/authorization/store-test-kit.js +16 -62
  49. package/dist/authorization/store-test-kit.js.map +1 -1
  50. package/dist/authorization/tuples.d.ts +13 -32
  51. package/dist/authorization/tuples.d.ts.map +1 -1
  52. package/dist/authorization/tuples.js +3 -11
  53. package/dist/authorization/tuples.js.map +1 -1
  54. package/dist/domain/agent/controller.d.ts.map +1 -1
  55. package/dist/domain/agent/controller.js +6 -4
  56. package/dist/domain/agent/controller.js.map +1 -1
  57. package/dist/domain/agentchannel/controller.d.ts.map +1 -1
  58. package/dist/domain/agentchannel/controller.js +9 -2
  59. package/dist/domain/agentchannel/controller.js.map +1 -1
  60. package/dist/domain/agentchannel/steps.d.ts +19 -0
  61. package/dist/domain/agentchannel/steps.d.ts.map +1 -1
  62. package/dist/domain/agentchannel/steps.js +32 -0
  63. package/dist/domain/agentchannel/steps.js.map +1 -1
  64. package/dist/domain/agentexecution/controller.d.ts.map +1 -1
  65. package/dist/domain/agentexecution/controller.js +3 -1
  66. package/dist/domain/agentexecution/controller.js.map +1 -1
  67. package/dist/domain/agentinstance/controller.d.ts +5 -5
  68. package/dist/domain/agentinstance/controller.d.ts.map +1 -1
  69. package/dist/domain/agentinstance/controller.js +9 -5
  70. package/dist/domain/agentinstance/controller.js.map +1 -1
  71. package/dist/domain/agentinstance/steps.d.ts +43 -8
  72. package/dist/domain/agentinstance/steps.d.ts.map +1 -1
  73. package/dist/domain/agentinstance/steps.js +71 -8
  74. package/dist/domain/agentinstance/steps.js.map +1 -1
  75. package/dist/domain/agentshare/constants.d.ts +6 -11
  76. package/dist/domain/agentshare/constants.d.ts.map +1 -1
  77. package/dist/domain/agentshare/constants.js +8 -16
  78. package/dist/domain/agentshare/constants.js.map +1 -1
  79. package/dist/domain/agentshare/controller.d.ts.map +1 -1
  80. package/dist/domain/agentshare/controller.js +10 -2
  81. package/dist/domain/agentshare/controller.js.map +1 -1
  82. package/dist/domain/agentshare/steps.d.ts +61 -10
  83. package/dist/domain/agentshare/steps.d.ts.map +1 -1
  84. package/dist/domain/agentshare/steps.js +121 -117
  85. package/dist/domain/agentshare/steps.js.map +1 -1
  86. package/dist/domain/artifact/controller.js +21 -25
  87. package/dist/domain/artifact/controller.js.map +1 -1
  88. package/dist/domain/channelapp/controller.d.ts.map +1 -1
  89. package/dist/domain/channelapp/controller.js +2 -0
  90. package/dist/domain/channelapp/controller.js.map +1 -1
  91. package/dist/domain/environment/controller.d.ts.map +1 -1
  92. package/dist/domain/environment/controller.js +4 -3
  93. package/dist/domain/environment/controller.js.map +1 -1
  94. package/dist/domain/executioncontext/controller.d.ts.map +1 -1
  95. package/dist/domain/executioncontext/controller.js +4 -1
  96. package/dist/domain/executioncontext/controller.js.map +1 -1
  97. package/dist/domain/executioncontext/steps.d.ts.map +1 -1
  98. package/dist/domain/executioncontext/steps.js +2 -1
  99. package/dist/domain/executioncontext/steps.js.map +1 -1
  100. package/dist/domain/mcpserver/connect.d.ts.map +1 -1
  101. package/dist/domain/mcpserver/connect.js +8 -7
  102. package/dist/domain/mcpserver/connect.js.map +1 -1
  103. package/dist/domain/mcpserver/controller.d.ts.map +1 -1
  104. package/dist/domain/mcpserver/controller.js +5 -4
  105. package/dist/domain/mcpserver/controller.js.map +1 -1
  106. package/dist/domain/mcpserver/start-connect.d.ts.map +1 -1
  107. package/dist/domain/mcpserver/start-connect.js +8 -7
  108. package/dist/domain/mcpserver/start-connect.js.map +1 -1
  109. package/dist/domain/memory/controller.d.ts.map +1 -1
  110. package/dist/domain/memory/controller.js +6 -1
  111. package/dist/domain/memory/controller.js.map +1 -1
  112. package/dist/domain/memory/steps.d.ts +23 -0
  113. package/dist/domain/memory/steps.d.ts.map +1 -1
  114. package/dist/domain/memory/steps.js +35 -0
  115. package/dist/domain/memory/steps.js.map +1 -1
  116. package/dist/domain/oauthapp/controller.d.ts.map +1 -1
  117. package/dist/domain/oauthapp/controller.js +2 -0
  118. package/dist/domain/oauthapp/controller.js.map +1 -1
  119. package/dist/domain/plugin/controller.d.ts.map +1 -1
  120. package/dist/domain/plugin/controller.js +6 -27
  121. package/dist/domain/plugin/controller.js.map +1 -1
  122. package/dist/domain/plugin/push.d.ts +7 -5
  123. package/dist/domain/plugin/push.d.ts.map +1 -1
  124. package/dist/domain/plugin/push.js +8 -14
  125. package/dist/domain/plugin/push.js.map +1 -1
  126. package/dist/domain/schedule/controller.d.ts.map +1 -1
  127. package/dist/domain/schedule/controller.js +10 -2
  128. package/dist/domain/schedule/controller.js.map +1 -1
  129. package/dist/domain/schedule/steps.d.ts +19 -0
  130. package/dist/domain/schedule/steps.d.ts.map +1 -1
  131. package/dist/domain/schedule/steps.js +32 -0
  132. package/dist/domain/schedule/steps.js.map +1 -1
  133. package/dist/domain/session/controller.d.ts.map +1 -1
  134. package/dist/domain/session/controller.js +3 -2
  135. package/dist/domain/session/controller.js.map +1 -1
  136. package/dist/domain/session/steps.d.ts +8 -9
  137. package/dist/domain/session/steps.d.ts.map +1 -1
  138. package/dist/domain/session/steps.js +17 -21
  139. package/dist/domain/session/steps.js.map +1 -1
  140. package/dist/domain/skill/controller.d.ts.map +1 -1
  141. package/dist/domain/skill/controller.js +8 -19
  142. package/dist/domain/skill/controller.js.map +1 -1
  143. package/dist/domain/workflow/agent-call-references.d.ts +54 -0
  144. package/dist/domain/workflow/agent-call-references.d.ts.map +1 -0
  145. package/dist/domain/workflow/agent-call-references.js +97 -0
  146. package/dist/domain/workflow/agent-call-references.js.map +1 -0
  147. package/dist/domain/workflow/controller.d.ts.map +1 -1
  148. package/dist/domain/workflow/controller.js +44 -113
  149. package/dist/domain/workflow/controller.js.map +1 -1
  150. package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
  151. package/dist/domain/workflow/validation/task-config-constraints.d.ts +10 -1
  152. package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
  153. package/dist/domain/workflow/validation/task-config-constraints.js +3 -2
  154. package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
  155. package/dist/domain/workflow/version-resolution.d.ts +5 -0
  156. package/dist/domain/workflow/version-resolution.d.ts.map +1 -0
  157. package/dist/domain/workflow/version-resolution.js +113 -0
  158. package/dist/domain/workflow/version-resolution.js.map +1 -0
  159. package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
  160. package/dist/domain/workflowexecution/controller.js +4 -2
  161. package/dist/domain/workflowexecution/controller.js.map +1 -1
  162. package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
  163. package/dist/domain/workflowinstance/controller.js +9 -5
  164. package/dist/domain/workflowinstance/controller.js.map +1 -1
  165. package/dist/domain/workflowinstance/steps.d.ts +20 -0
  166. package/dist/domain/workflowinstance/steps.d.ts.map +1 -1
  167. package/dist/domain/workflowinstance/steps.js +39 -0
  168. package/dist/domain/workflowinstance/steps.js.map +1 -1
  169. package/dist/extensions/authorization-queries.d.ts +6 -5
  170. package/dist/extensions/authorization-queries.d.ts.map +1 -1
  171. package/dist/extensions/identity.d.ts +19 -0
  172. package/dist/extensions/identity.d.ts.map +1 -1
  173. package/dist/extensions/identity.js +22 -3
  174. package/dist/extensions/identity.js.map +1 -1
  175. package/dist/extensions/list-read-scope.d.ts +42 -8
  176. package/dist/extensions/list-read-scope.d.ts.map +1 -1
  177. package/dist/extensions/list-read-scope.js +13 -2
  178. package/dist/extensions/list-read-scope.js.map +1 -1
  179. package/dist/extensions/resource-authorization.d.ts +3 -2
  180. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  181. package/dist/index.d.ts +1 -1
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js.map +1 -1
  184. package/dist/pipeline/apiresource-meta.d.ts +12 -3
  185. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  186. package/dist/pipeline/apiresource-meta.js +21 -10
  187. package/dist/pipeline/apiresource-meta.js.map +1 -1
  188. package/dist/pipeline/steps/authorization-tuples.d.ts +9 -3
  189. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  190. package/dist/pipeline/steps/authorization-tuples.js +9 -11
  191. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  192. package/dist/pipeline/steps/authorize-resolved-target.d.ts +88 -0
  193. package/dist/pipeline/steps/authorize-resolved-target.d.ts.map +1 -0
  194. package/dist/pipeline/steps/authorize-resolved-target.js +36 -0
  195. package/dist/pipeline/steps/authorize-resolved-target.js.map +1 -0
  196. package/dist/pipeline/steps/authorize.d.ts +27 -0
  197. package/dist/pipeline/steps/authorize.d.ts.map +1 -1
  198. package/dist/pipeline/steps/authorize.js +49 -10
  199. package/dist/pipeline/steps/authorize.js.map +1 -1
  200. package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
  201. package/dist/pipeline/steps/guard-memory-capture.js +2 -1
  202. package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
  203. package/dist/pipeline/steps/guard-reserved-labels.d.ts.map +1 -1
  204. package/dist/pipeline/steps/guard-reserved-labels.js +6 -7
  205. package/dist/pipeline/steps/guard-reserved-labels.js.map +1 -1
  206. package/dist/pipeline/steps/helpers.d.ts +9 -5
  207. package/dist/pipeline/steps/helpers.d.ts.map +1 -1
  208. package/dist/pipeline/steps/helpers.js +11 -15
  209. package/dist/pipeline/steps/helpers.js.map +1 -1
  210. package/dist/pipeline/steps/references.d.ts +178 -20
  211. package/dist/pipeline/steps/references.d.ts.map +1 -1
  212. package/dist/pipeline/steps/references.js +344 -43
  213. package/dist/pipeline/steps/references.js.map +1 -1
  214. package/dist/pipeline/steps/version-history.d.ts +11 -0
  215. package/dist/pipeline/steps/version-history.d.ts.map +1 -1
  216. package/dist/pipeline/steps/version-history.js +26 -0
  217. package/dist/pipeline/steps/version-history.js.map +1 -1
  218. package/dist/query/search/controller.js +0 -1
  219. package/dist/query/search/controller.js.map +1 -1
  220. package/dist/query/search/criteria.d.ts +1 -5
  221. package/dist/query/search/criteria.d.ts.map +1 -1
  222. package/dist/query/search/criteria.js +3 -13
  223. package/dist/query/search/criteria.js.map +1 -1
  224. package/dist/query/search/handler.d.ts +5 -4
  225. package/dist/query/search/handler.d.ts.map +1 -1
  226. package/dist/query/search/handler.js +7 -6
  227. package/dist/query/search/handler.js.map +1 -1
  228. package/dist/query/search/query-store.d.ts.map +1 -1
  229. package/dist/query/search/query-store.js +0 -2
  230. package/dist/query/search/query-store.js.map +1 -1
  231. package/dist/store/interface.d.ts +3 -6
  232. package/dist/store/interface.d.ts.map +1 -1
  233. package/dist/store/interface.js.map +1 -1
  234. package/dist/store/postgres/migrations.d.ts +3 -1
  235. package/dist/store/postgres/migrations.d.ts.map +1 -1
  236. package/dist/store/postgres/migrations.js +35 -1
  237. package/dist/store/postgres/migrations.js.map +1 -1
  238. package/dist/store/postgres/store.d.ts.map +1 -1
  239. package/dist/store/postgres/store.js +4 -9
  240. package/dist/store/postgres/store.js.map +1 -1
  241. package/dist/store/public-visibility-retired.d.ts +67 -0
  242. package/dist/store/public-visibility-retired.d.ts.map +1 -0
  243. package/dist/store/public-visibility-retired.js +55 -0
  244. package/dist/store/public-visibility-retired.js.map +1 -0
  245. package/dist/store/sqlite/migrations.d.ts +3 -1
  246. package/dist/store/sqlite/migrations.d.ts.map +1 -1
  247. package/dist/store/sqlite/migrations.js +36 -1
  248. package/dist/store/sqlite/migrations.js.map +1 -1
  249. package/dist/store/sqlite/store.d.ts.map +1 -1
  250. package/dist/store/sqlite/store.js +4 -8
  251. package/dist/store/sqlite/store.js.map +1 -1
  252. package/package.json +6 -6
  253. package/src/authorization/README.md +24 -26
  254. package/src/authorization/__tests__/authorizer.test.ts +10 -9
  255. package/src/authorization/__tests__/derived-tuples.test.ts +4 -11
  256. package/src/authorization/__tests__/evaluator.test.ts +14 -73
  257. package/src/authorization/__tests__/facts.test.ts +2 -2
  258. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +6 -98
  259. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +4 -61
  260. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +1 -21
  261. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +1 -25
  262. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +1 -3
  263. package/src/authorization/__tests__/list-read-scope.test.ts +41 -29
  264. package/src/authorization/__tests__/skip-lane-inventory.test.ts +160 -0
  265. package/src/authorization/__tests__/store-tests.test.ts +1 -6
  266. package/src/authorization/__tests__/tuples.test.ts +12 -11
  267. package/src/authorization/__tests__/wire-permissions.test.ts +5 -5
  268. package/src/authorization/authorizer.ts +4 -9
  269. package/src/authorization/derived-tuples.ts +14 -31
  270. package/src/authorization/evaluator.ts +15 -44
  271. package/src/authorization/list-read-scope.ts +27 -22
  272. package/src/authorization/model/__tests__/registry.test.ts +2 -0
  273. package/src/authorization/model/agent.ts +2 -5
  274. package/src/authorization/model/agent_instance.ts +0 -2
  275. package/src/authorization/model/mcp_server.ts +0 -2
  276. package/src/authorization/model/organization.ts +2 -0
  277. package/src/authorization/model/plugin.ts +1 -4
  278. package/src/authorization/model/rewrite.ts +8 -13
  279. package/src/authorization/model/skill.ts +0 -2
  280. package/src/authorization/model/workflow.ts +0 -2
  281. package/src/authorization/model/workflow_instance.ts +0 -2
  282. package/src/authorization/organization-directory.ts +1 -3
  283. package/src/authorization/store-test-kit.ts +16 -75
  284. package/src/authorization/tuples.ts +16 -39
  285. package/src/domain/agent/__tests__/agent.test.ts +11 -4
  286. package/src/domain/agent/controller.ts +17 -7
  287. package/src/domain/agentchannel/__tests__/agentchannel.test.ts +223 -48
  288. package/src/domain/agentchannel/__tests__/create-authorization.test.ts +58 -0
  289. package/src/domain/agentchannel/controller.ts +25 -1
  290. package/src/domain/agentchannel/steps.ts +40 -0
  291. package/src/domain/agentexecution/controller.ts +6 -1
  292. package/src/domain/agentinstance/__tests__/create-authorization.composed.test.ts +243 -0
  293. package/src/domain/agentinstance/__tests__/create-authorization.test.ts +144 -0
  294. package/src/domain/agentinstance/controller.ts +30 -17
  295. package/src/domain/agentinstance/steps.ts +82 -8
  296. package/src/domain/agentshare/__tests__/agentshare.test.ts +196 -172
  297. package/src/domain/agentshare/__tests__/create-authorization.test.ts +71 -0
  298. package/src/domain/agentshare/__tests__/member-audience.test.ts +113 -0
  299. package/src/domain/agentshare/constants.ts +14 -26
  300. package/src/domain/agentshare/controller.ts +27 -1
  301. package/src/domain/agentshare/steps.ts +168 -155
  302. package/src/domain/artifact/controller.ts +18 -22
  303. package/src/domain/channelapp/controller.ts +10 -0
  304. package/src/domain/environment/controller.ts +15 -8
  305. package/src/domain/executioncontext/__tests__/executioncontext.test.ts +1 -0
  306. package/src/domain/executioncontext/controller.ts +15 -1
  307. package/src/domain/executioncontext/steps.ts +2 -1
  308. package/src/domain/mcpserver/__tests__/mcpserver.test.ts +115 -28
  309. package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +53 -18
  310. package/src/domain/mcpserver/connect.ts +11 -10
  311. package/src/domain/mcpserver/controller.ts +19 -13
  312. package/src/domain/mcpserver/start-connect.ts +17 -11
  313. package/src/domain/memory/__tests__/create-authorization.test.ts +59 -0
  314. package/src/domain/memory/controller.ts +11 -0
  315. package/src/domain/memory/steps.ts +41 -0
  316. package/src/domain/oauthapp/controller.ts +10 -0
  317. package/src/domain/plugin/controller.ts +23 -44
  318. package/src/domain/plugin/push.ts +8 -16
  319. package/src/domain/schedule/__tests__/create-authorization.test.ts +58 -0
  320. package/src/domain/schedule/controller.ts +26 -1
  321. package/src/domain/schedule/steps.ts +45 -2
  322. package/src/domain/session/controller.ts +12 -4
  323. package/src/domain/session/steps.ts +24 -32
  324. package/src/domain/skill/controller.ts +24 -30
  325. package/src/domain/workflow/__tests__/agent-call-references.test.ts +222 -0
  326. package/src/domain/workflow/agent-call-references.ts +157 -0
  327. package/src/domain/workflow/controller.ts +86 -155
  328. package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
  329. package/src/domain/workflow/validation/task-config-constraints.ts +7 -3
  330. package/src/domain/workflow/version-resolution.ts +166 -0
  331. package/src/domain/workflowexecution/controller.ts +7 -2
  332. package/src/domain/workflowinstance/__tests__/create-authorization.test.ts +109 -0
  333. package/src/domain/workflowinstance/controller.ts +25 -12
  334. package/src/domain/workflowinstance/steps.ts +49 -1
  335. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +32 -19
  336. package/src/extensions/__tests__/composed-support.ts +38 -4
  337. package/src/extensions/__tests__/extension-composition.test.ts +4 -4
  338. package/src/extensions/__tests__/identity.test.ts +44 -1
  339. package/src/extensions/__tests__/list-read-scope-composed.test.ts +96 -7
  340. package/src/extensions/__tests__/list-read-scope.test.ts +63 -0
  341. package/src/extensions/authorization-queries.ts +6 -5
  342. package/src/extensions/identity.ts +23 -5
  343. package/src/extensions/list-read-scope.ts +48 -8
  344. package/src/extensions/resource-authorization.ts +3 -5
  345. package/src/index.ts +0 -1
  346. package/src/pipeline/__tests__/supports-visibility.test.ts +112 -0
  347. package/src/pipeline/apiresource-meta.ts +21 -10
  348. package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +18 -31
  349. package/src/pipeline/steps/__tests__/authorize-resolved-target.test.ts +285 -0
  350. package/src/pipeline/steps/__tests__/references.test.ts +703 -0
  351. package/src/pipeline/steps/authorization-tuples.ts +9 -11
  352. package/src/pipeline/steps/authorize-resolved-target.ts +129 -0
  353. package/src/pipeline/steps/authorize.ts +70 -13
  354. package/src/pipeline/steps/guard-memory-capture.ts +2 -1
  355. package/src/pipeline/steps/guard-reserved-labels.ts +6 -9
  356. package/src/pipeline/steps/helpers.ts +11 -15
  357. package/src/pipeline/steps/references.ts +578 -70
  358. package/src/pipeline/steps/version-history.ts +34 -0
  359. package/src/query/search/__tests__/criteria.test.ts +0 -4
  360. package/src/query/search/__tests__/query-store.test.ts +11 -40
  361. package/src/query/search/controller.ts +0 -1
  362. package/src/query/search/criteria.ts +0 -14
  363. package/src/query/search/handler.ts +6 -7
  364. package/src/query/search/query-store.ts +0 -2
  365. package/src/store/__tests__/public-visibility-retired.test.ts +127 -0
  366. package/src/store/__tests__/store-contract.ts +6 -51
  367. package/src/store/interface.ts +3 -6
  368. package/src/store/postgres/__tests__/migrations.test.ts +187 -6
  369. package/src/store/postgres/__tests__/store-contract.test.ts +0 -2
  370. package/src/store/postgres/migrations.ts +48 -1
  371. package/src/store/postgres/store.ts +4 -11
  372. package/src/store/public-visibility-retired.ts +119 -0
  373. package/src/store/sqlite/__tests__/migrations.test.ts +191 -5
  374. package/src/store/sqlite/migrations.ts +45 -1
  375. package/src/store/sqlite/store.ts +4 -10
  376. package/dist/pipeline/steps/visibility-gates.d.ts +0 -27
  377. package/dist/pipeline/steps/visibility-gates.d.ts.map +0 -1
  378. package/dist/pipeline/steps/visibility-gates.js +0 -139
  379. package/dist/pipeline/steps/visibility-gates.js.map +0 -1
  380. package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +0 -98
  381. package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +0 -52
  382. package/src/pipeline/steps/__tests__/visibility-gates.test.ts +0 -187
  383. package/src/pipeline/steps/visibility-gates.ts +0 -174
@@ -21,7 +21,9 @@ import {
21
21
  AgentChannelStatusSchema,
22
22
  } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/status_pb";
23
23
  import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
24
+ import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
24
25
  import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
26
+ import { IamPermission } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
25
27
 
26
28
  import {
27
29
  failedPreconditionError,
@@ -31,6 +33,7 @@ import {
31
33
  } from "../../pipeline/errors.js";
32
34
  import type { PipelineStep } from "../../pipeline/pipeline.js";
33
35
  import type { RequestContext } from "../../pipeline/request-context.js";
36
+ import type { AuthorizationTarget } from "../../pipeline/steps/authorize.js";
34
37
  import { findResourceBySlug } from "../../pipeline/steps/helpers.js";
35
38
  import { EXISTING_RESOURCE_KEY } from "../../pipeline/steps/load-existing.js";
36
39
  import type { Store } from "../../store/interface.js";
@@ -161,6 +164,7 @@ export function newResolveChannelDefaultsStep(
161
164
  }
162
165
 
163
166
  agentRef!.org = refOrg;
167
+ ctx.set(REFERENCED_AGENT_KEY, agent);
164
168
 
165
169
  // Write-time constraints only a serving runtime can state (the
166
170
  // pin-REQUIRED rule and its successors — channel-runtime.ts).
@@ -174,6 +178,42 @@ export function newResolveChannelDefaultsStep(
174
178
  };
175
179
  }
176
180
 
181
+ /**
182
+ * Context key for the agent ResolveChannelDefaults resolved from
183
+ * spec.agent_ref, read by the create lane's authorization step.
184
+ */
185
+ export const REFERENCED_AGENT_KEY = "agentChannelReferencedAgent";
186
+
187
+ /** The deny copy of the create bar, the Java AgentChannelCreateHandler's. */
188
+ export const CHANNEL_CREATE_DENIED_MESSAGE =
189
+ "You don't have permission to connect this agent to a channel";
190
+
191
+ /**
192
+ * The create lane's authorization question, for AuthorizeResolvedTarget
193
+ * after ResolveChannelDefaults: can_edit on the REFERENCED AGENT. The RPC
194
+ * is is_skip_authorization because its target is that agent, resolved from
195
+ * a slug, not a request field. Binding an agent to a channel puts it in
196
+ * front of a wider audience, an editor's act; the same-org invariant the
197
+ * resolve step enforces already binds the channel's organization to the
198
+ * agent's, so there is no separate organization bar (command.proto).
199
+ */
200
+ export function resolveChannelCreateTargets(
201
+ ctx: RequestContext<AgentChannelDesc>,
202
+ ): ReadonlyArray<AuthorizationTarget> {
203
+ const agent = ctx.get(REFERENCED_AGENT_KEY) as Agent | undefined;
204
+ if (agent === undefined) {
205
+ throw new Error("referenced agent not found in context");
206
+ }
207
+ return [
208
+ {
209
+ permission: IamPermission.can_edit,
210
+ resourceKind: ApiResourceKind.agent,
211
+ resourceId: agent.metadata?.id ?? "",
212
+ deniedMessage: CHANNEL_CREATE_DENIED_MESSAGE,
213
+ },
214
+ ];
215
+ }
216
+
177
217
  /**
178
218
  * InitInstallState — Go initInstallStateStep: writes
179
219
  * status.install_state = pending_install; the channel exists but serves
@@ -66,7 +66,10 @@ import {
66
66
  TARGET_RESOURCE_KEY,
67
67
  newLoadTargetStep,
68
68
  } from "../../pipeline/steps/load-target.js";
69
- import { newNormalizeReferencesStep } from "../../pipeline/steps/references.js";
69
+ import {
70
+ newNormalizeReferencesStep,
71
+ newValidateReferencesStep,
72
+ } from "../../pipeline/steps/references.js";
70
73
  import {
71
74
  newCleanupIamPoliciesStep,
72
75
  newCreateAuthorizationTuplesStep,
@@ -328,6 +331,7 @@ async function createExecution(
328
331
  .addStep(newRecordRunnerLineageLabelsStep(deps.runnerCredentialProvider))
329
332
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
330
333
  .addStep(newNormalizeReferencesStep())
334
+ .addStep(newValidateReferencesStep(deps.store))
331
335
  .addStep(newEnsureEngineAvailableStep(deps.engineState));
332
336
  // The ratified pre-side-effect gate slot (blueprint 03 §3a; O4): after
333
337
  // every pure validation/resolution step, before the first side-effecting
@@ -433,6 +437,7 @@ async function update(
433
437
  .addStep(newLoadExistingStep(deps.store))
434
438
  .addStep(newBuildUpdateStateStep())
435
439
  .addStep(newNormalizeReferencesStep())
440
+ .addStep(newValidateReferencesStep(deps.store))
436
441
  .addStep(newPersistStep(deps.store))
437
442
  .addStep(
438
443
  newIndexSearchStep(
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Pins the instance create lane's authorization at the wire, on a real boot
3
+ * under the require-authentication posture with no unit Authorizer (the
4
+ * self-host's shape, the built-in Authorizer composed):
5
+ *
6
+ * - a member creates a personal instance of an org-visible agent in their
7
+ * organization (can_create_agent_instance is member-level; the parent's
8
+ * can_create_instance is its viewer set);
9
+ * - a member is refused an instance of a PRIVATE agent with the parent's
10
+ * copy — the organization's bar passed, the agent's did not;
11
+ * - an outsider naming an organization they hold no row in is refused
12
+ * with the organization's copy, before anything about the agent;
13
+ * - a member's wire request carrying the reserved default-instance label
14
+ * is refused: the label buys nothing from the wire (the reserved-label
15
+ * guard refuses it after the caller passes the personal bar);
16
+ * - the SAME labelled request the server composes in-process for the
17
+ * member (the default-instance self-heal's exact shape: the in-process
18
+ * transport, the propagated caller, the parent's organization) is
19
+ * admitted with no caller check and attributed to the member — the
20
+ * arm that keeps every lane whose run was already admitted (a guest, a
21
+ * channel turn, a schedule fire) working when the agent has no default
22
+ * instance yet.
23
+ *
24
+ * Every negative arm sits beside a positive one so the file cannot pass
25
+ * vacuously. The resolver's own table is create-authorization.test.ts.
26
+ */
27
+ import { mkdtempSync, rmSync } from "node:fs";
28
+ import { tmpdir } from "node:os";
29
+ import path from "node:path";
30
+
31
+ import { Code, ConnectError, createClient } from "@connectrpc/connect";
32
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
33
+
34
+ import { AgentCommandController } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/command_pb";
35
+ import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
36
+ import { AgentInstanceCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/command_pb";
37
+ import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
38
+ import { IdentityAccountCommandController } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/command_pb";
39
+ import { OrganizationCommandController } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/command_pb";
40
+
41
+ import { loadConfig } from "../../../boot/config.js";
42
+ import { composeServer } from "../../../boot/compose.js";
43
+ import type { ComposedServer } from "../../../boot/compose.js";
44
+ import type { ServerExtension } from "../../../extensions/registry.js";
45
+ import {
46
+ baseConfig,
47
+ fakeJwt,
48
+ fakeVerifier,
49
+ silentLogger,
50
+ transportFor,
51
+ } from "../../../extensions/__tests__/composed-support.js";
52
+ import {
53
+ DEFAULT_INSTANCE_LABEL,
54
+ RESERVED_LABEL_TRUE,
55
+ } from "../../../pipeline/apiresource-labels.js";
56
+ import {
57
+ IN_PROCESS_CALLER_HEADER,
58
+ encodeInProcessCaller,
59
+ } from "../../../pipeline/interceptors/auth.js";
60
+ import { buildDefaultInstanceRequest } from "../defaultinstance.js";
61
+ import {
62
+ INSTANCE_ORGANIZATION_DENIED_MESSAGE,
63
+ INSTANCE_PARENT_DENIED_MESSAGE,
64
+ } from "../steps.js";
65
+
66
+ const FOUNDER = "fake|founder";
67
+ const MEMBER = "fake|member";
68
+ const STRANGER = "fake|stranger";
69
+ const ORG = "instance-authz-org";
70
+
71
+ function organizationInput(slug: string) {
72
+ return {
73
+ apiVersion: "tenancy.stigmer.ai/v1",
74
+ kind: "Organization",
75
+ metadata: { name: slug, slug, org: "" },
76
+ spec: { description: slug },
77
+ };
78
+ }
79
+
80
+ function agentInput(name: string, visibility: ApiResourceVisibility) {
81
+ return {
82
+ apiVersion: "agentic.stigmer.ai/v1",
83
+ kind: "Agent",
84
+ metadata: { name, org: ORG, visibility },
85
+ spec: { instructions: "a conformant instruction body" },
86
+ };
87
+ }
88
+
89
+ function instanceInput(
90
+ name: string,
91
+ agentId: string,
92
+ org: string = ORG,
93
+ labels: Record<string, string> = {},
94
+ ) {
95
+ return {
96
+ apiVersion: "agentic.stigmer.ai/v1",
97
+ kind: "AgentInstance",
98
+ metadata: { name, org, labels },
99
+ spec: { agentId, description: name },
100
+ };
101
+ }
102
+
103
+ async function failureOf(promise: Promise<unknown>): Promise<ConnectError> {
104
+ try {
105
+ await promise;
106
+ } catch (error) {
107
+ return ConnectError.from(error);
108
+ }
109
+ throw new Error("expected the call to fail");
110
+ }
111
+
112
+ describe("agent instance create under the built-in authorizer", () => {
113
+ let dir: string;
114
+ let server: ComposedServer;
115
+ let port: number;
116
+ let orgAgent: Agent;
117
+ let privateAgent: Agent;
118
+
119
+ const asFounder = () =>
120
+ transportFor(port, fakeJwt(FOUNDER, "founder@example.com"));
121
+ const asMember = () =>
122
+ transportFor(port, fakeJwt(MEMBER, "member@example.com"));
123
+ const asStranger = () =>
124
+ transportFor(port, fakeJwt(STRANGER, "stranger@example.com"));
125
+
126
+ beforeAll(async () => {
127
+ dir = mkdtempSync(path.join(tmpdir(), "instance-create-authz-"));
128
+ const unit: ServerExtension = {
129
+ name: "fake-oidc-only",
130
+ requireAuthentication: true,
131
+ identityVerifiers: [fakeVerifier],
132
+ };
133
+ server = await composeServer({
134
+ config: loadConfig(baseConfig(dir)),
135
+ logger: silentLogger,
136
+ extensions: [unit],
137
+ portOverride: 0,
138
+ host: "127.0.0.1",
139
+ });
140
+ port = await server.start();
141
+
142
+ // The membership rules of a self-host: a person who provisions while
143
+ // the organization exists joins it as a member; a person provisioned
144
+ // BEFORE it was founded holds no row on it. So the stranger provisions
145
+ // first, the founder founds, and the member provisions after.
146
+ await createClient(
147
+ IdentityAccountCommandController,
148
+ asFounder(),
149
+ ).provisionMyAccount({});
150
+ await createClient(
151
+ IdentityAccountCommandController,
152
+ asStranger(),
153
+ ).provisionMyAccount({});
154
+ await createClient(OrganizationCommandController, asFounder()).create(
155
+ organizationInput(ORG),
156
+ );
157
+ await createClient(
158
+ IdentityAccountCommandController,
159
+ asMember(),
160
+ ).provisionMyAccount({});
161
+
162
+ const founderAgents = createClient(AgentCommandController, asFounder());
163
+ orgAgent = await founderAgents.create(
164
+ agentInput("Org Agent", ApiResourceVisibility.visibility_org),
165
+ );
166
+ privateAgent = await founderAgents.create(
167
+ agentInput("Private Agent", ApiResourceVisibility.visibility_private),
168
+ );
169
+ });
170
+
171
+ afterAll(async () => {
172
+ await server.shutdown();
173
+ rmSync(dir, { recursive: true, force: true });
174
+ });
175
+
176
+ it("a member creates a personal instance of an org-visible agent in their organization", async () => {
177
+ const created = await createClient(
178
+ AgentInstanceCommandController,
179
+ asMember(),
180
+ ).create(instanceInput("member-personal", orgAgent.metadata!.id));
181
+ expect(created.metadata?.org).toBe(ORG);
182
+ expect(created.status?.audit?.specAudit?.createdBy?.id).toBe(MEMBER);
183
+ });
184
+
185
+ it("a member is refused an instance of a PRIVATE agent with the parent's copy", async () => {
186
+ const error = await failureOf(
187
+ createClient(AgentInstanceCommandController, asMember()).create(
188
+ instanceInput("member-on-private", privateAgent.metadata!.id),
189
+ ),
190
+ );
191
+ expect(error.code).toBe(Code.PermissionDenied);
192
+ expect(error.rawMessage).toBe(INSTANCE_PARENT_DENIED_MESSAGE);
193
+ });
194
+
195
+ it("an outsider naming the organization is refused with the organization's copy, before the agent is named", async () => {
196
+ const error = await failureOf(
197
+ createClient(AgentInstanceCommandController, asStranger()).create(
198
+ instanceInput("stranger-instance", orgAgent.metadata!.id),
199
+ ),
200
+ );
201
+ expect(error.code).toBe(Code.PermissionDenied);
202
+ expect(error.rawMessage).toBe(INSTANCE_ORGANIZATION_DENIED_MESSAGE);
203
+ });
204
+
205
+ it("the reserved default-instance label buys nothing from the wire", async () => {
206
+ const error = await failureOf(
207
+ createClient(AgentInstanceCommandController, asMember()).create(
208
+ instanceInput("wire-default", orgAgent.metadata!.id, ORG, {
209
+ [DEFAULT_INSTANCE_LABEL]: RESERVED_LABEL_TRUE,
210
+ }),
211
+ ),
212
+ );
213
+ // The personal bar admits a member on an org-visible agent; the label
214
+ // guard then refuses the reserved label a wire caller may not write.
215
+ expect(error.code).toBe(Code.InvalidArgument);
216
+ expect(error.rawMessage).toContain(DEFAULT_INSTANCE_LABEL);
217
+ });
218
+
219
+ it("the same labelled request composed in-process for the member is admitted and attributed to them (the self-heal's shape)", async () => {
220
+ const member = await fakeVerifier.verify(
221
+ fakeJwt(MEMBER, "member@example.com"),
222
+ );
223
+ if (member === null) {
224
+ throw new Error("the fake verifier must admit the member");
225
+ }
226
+ // The agent's own default instance already exists (agent create made
227
+ // it); the self-heal's request is the same shape under a slug the store
228
+ // does not hold yet, which is what a legacy agent without one presents.
229
+ const request = buildDefaultInstanceRequest(orgAgent.metadata!);
230
+ request.metadata!.name = "org-agent-default-healed";
231
+ const created = await createClient(
232
+ AgentInstanceCommandController,
233
+ server.inProcessTransport,
234
+ ).create(request, {
235
+ headers: { [IN_PROCESS_CALLER_HEADER]: encodeInProcessCaller(member) },
236
+ });
237
+ expect(created.metadata?.labels?.[DEFAULT_INSTANCE_LABEL]).toBe(
238
+ RESERVED_LABEL_TRUE,
239
+ );
240
+ expect(created.metadata?.org).toBe(ORG);
241
+ expect(created.status?.audit?.specAudit?.createdBy?.id).toBe(MEMBER);
242
+ });
243
+ });
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Pins the create lane's authorization questions (steps.ts,
3
+ * resolveInstanceCreateTargets): a personal instance asks the
4
+ * organization's bar (can_create_agent_instance on metadata.org) and then
5
+ * the parent's (can_create_instance on the agent), each with its own copy;
6
+ * a default instance the server composed in-process for the parent's
7
+ * organization asks nothing; a labelled request that arrived on the wire,
8
+ * or that names another organization, takes the personal bar in full; a
9
+ * missing parent is a thrown chain invariant, never an open lane.
10
+ */
11
+ import { describe, expect, it } from "vitest";
12
+ import { create } from "@bufbuild/protobuf";
13
+
14
+ import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
15
+ import { AgentInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
16
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
17
+ import { IamPermission } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
18
+
19
+ import type { CallerIdentity } from "../../../extensions/identity.js";
20
+ import {
21
+ DEFAULT_INSTANCE_LABEL,
22
+ RESERVED_LABEL_TRUE,
23
+ } from "../../../pipeline/apiresource-labels.js";
24
+ import { testCallerIdentity } from "../../../pipeline/__tests__/support.js";
25
+ import { RequestContext } from "../../../pipeline/request-context.js";
26
+ import {
27
+ INSTANCE_ORGANIZATION_DENIED_MESSAGE,
28
+ INSTANCE_PARENT_DENIED_MESSAGE,
29
+ PARENT_AGENT_KEY,
30
+ resolveInstanceCreateTargets,
31
+ } from "../steps.js";
32
+
33
+ const parent = create(AgentSchema, {
34
+ metadata: { id: "agt_01parent", name: "helper", org: "acme" },
35
+ });
36
+
37
+ function ctxFor(
38
+ org: string,
39
+ caller: CallerIdentity,
40
+ labels: Record<string, string> = {},
41
+ stashParent = true,
42
+ ) {
43
+ const ctx = new RequestContext(
44
+ AgentInstanceSchema,
45
+ create(AgentInstanceSchema, {
46
+ metadata: { name: "mine", org, labels },
47
+ spec: { agentId: parent.metadata!.id },
48
+ }),
49
+ caller,
50
+ ApiResourceKind.agent_instance,
51
+ );
52
+ if (stashParent) {
53
+ ctx.set(PARENT_AGENT_KEY, parent);
54
+ }
55
+ return ctx;
56
+ }
57
+
58
+ const DEFAULT_LABELS = { [DEFAULT_INSTANCE_LABEL]: RESERVED_LABEL_TRUE };
59
+
60
+ describe("resolveInstanceCreateTargets", () => {
61
+ it("a personal instance asks the organization's bar first, then the parent's, each with its own copy", () => {
62
+ expect(
63
+ resolveInstanceCreateTargets(ctxFor("acme", testCallerIdentity())),
64
+ ).toEqual([
65
+ {
66
+ permission: IamPermission.can_create_agent_instance,
67
+ resourceKind: ApiResourceKind.organization,
68
+ resourceId: "acme",
69
+ deniedMessage: INSTANCE_ORGANIZATION_DENIED_MESSAGE,
70
+ },
71
+ {
72
+ permission: IamPermission.can_create_instance,
73
+ resourceKind: ApiResourceKind.agent,
74
+ resourceId: "agt_01parent",
75
+ deniedMessage: INSTANCE_PARENT_DENIED_MESSAGE,
76
+ },
77
+ ]);
78
+ });
79
+
80
+ it("a cross-org personal instance asks about ITS organization, not the parent's (the marketplace case)", () => {
81
+ const [orgBar] = resolveInstanceCreateTargets(
82
+ ctxFor("consumer-org", testCallerIdentity()),
83
+ );
84
+ expect(orgBar?.resourceId).toBe("consumer-org");
85
+ });
86
+
87
+ it("a default instance the server composed in-process for the parent's organization asks nothing", () => {
88
+ expect(
89
+ resolveInstanceCreateTargets(
90
+ ctxFor(
91
+ "acme",
92
+ testCallerIdentity({ callerClass: "user", origin: "in-process" }),
93
+ DEFAULT_LABELS,
94
+ ),
95
+ ),
96
+ ).toEqual([]);
97
+ expect(
98
+ resolveInstanceCreateTargets(
99
+ ctxFor(
100
+ "acme",
101
+ testCallerIdentity({ callerClass: "channel", origin: "in-process" }),
102
+ DEFAULT_LABELS,
103
+ ),
104
+ ),
105
+ ).toEqual([]);
106
+ });
107
+
108
+ it("the label alone buys nothing: a labelled request from the wire takes the personal bar in full, the machine class included", () => {
109
+ expect(
110
+ resolveInstanceCreateTargets(
111
+ ctxFor("acme", testCallerIdentity(), DEFAULT_LABELS),
112
+ ),
113
+ ).toHaveLength(2);
114
+ expect(
115
+ resolveInstanceCreateTargets(
116
+ ctxFor(
117
+ "acme",
118
+ testCallerIdentity({ callerClass: "machine" }),
119
+ DEFAULT_LABELS,
120
+ ),
121
+ ),
122
+ ).toHaveLength(2);
123
+ });
124
+
125
+ it("a labelled in-process request for another organization is not a default instance to this step", () => {
126
+ expect(
127
+ resolveInstanceCreateTargets(
128
+ ctxFor(
129
+ "other-org",
130
+ testCallerIdentity({ callerClass: "user", origin: "in-process" }),
131
+ DEFAULT_LABELS,
132
+ ),
133
+ ),
134
+ ).toHaveLength(2);
135
+ });
136
+
137
+ it("a missing parent is a broken chain invariant and throws", () => {
138
+ expect(() =>
139
+ resolveInstanceCreateTargets(
140
+ ctxFor("acme", testCallerIdentity(), {}, false),
141
+ ),
142
+ ).toThrow("parent agent not found in context");
143
+ });
144
+ });
@@ -10,13 +10,13 @@
10
10
  * Proven by agentinstance.conformance.test.ts (CONFORMANCE_TARGET=local)
11
11
  * and __tests__/agentinstance.test.ts.
12
12
  *
13
- * Versus Stigmer Cloud, OSS excludes the Authorize (FGA
14
- * can_create_instance on the parent agent), CreateIamPolicies, and Publish
13
+ * Versus Stigmer Cloud, OSS excludes the CreateIamPolicies and Publish
15
14
  * steps. Deliberately NO same-org rule on create, unlike WorkflowInstance:
16
15
  * an agent is a shareable blueprint, and one agent legitimately has
17
- * instances in several orgs (the marketplace case) — cloud governs
18
- * cross-org creation with FGA on the parent agent; OSS has no
19
- * authorization layer, so cross-org creation is allowed.
16
+ * instances in several orgs (the marketplace case). What governs a
17
+ * cross-org instance in both editions is the create lane's authorization
18
+ * (steps.ts, resolveInstanceCreateTargets): the caller's standing in the
19
+ * instance's organization and on the parent agent.
20
20
  */
21
21
  import type { ConnectRouter, HandlerContext } from "@connectrpc/connect";
22
22
 
@@ -47,11 +47,11 @@ import type { PipelineStep } from "../../pipeline/pipeline.js";
47
47
  import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
48
48
  import { RequestContext } from "../../pipeline/request-context.js";
49
49
  import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
50
- import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
51
50
  import {
52
- newAuthorizeVisibilityTransitionStep,
53
- newGuardPublicVisibilityStep,
54
- } from "../../pipeline/steps/visibility-gates.js";
51
+ loadedTargetAsMethod,
52
+ newAuthorizeResolvedTargetStep,
53
+ } from "../../pipeline/steps/authorize-resolved-target.js";
54
+ import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
55
55
  import {
56
56
  newBuildNewStateStep,
57
57
  setAuditFieldsForUpdate,
@@ -81,7 +81,10 @@ import {
81
81
  TARGET_RESOURCE_KEY,
82
82
  newLoadTargetStep,
83
83
  } from "../../pipeline/steps/load-target.js";
84
- import { newNormalizeReferencesStep } from "../../pipeline/steps/references.js";
84
+ import {
85
+ newNormalizeReferencesStep,
86
+ newValidateReferencesStep,
87
+ } from "../../pipeline/steps/references.js";
85
88
  import {
86
89
  newCleanupIamPoliciesStep,
87
90
  newCreateAuthorizationTuplesStep,
@@ -106,6 +109,7 @@ import {
106
109
  newLoadParentAgentStep,
107
110
  newRejectDefaultInstanceVisibilityUpdateStep,
108
111
  newValidateInstanceUpdateStep,
112
+ resolveInstanceCreateTargets,
109
113
  } from "./steps.js";
110
114
  import type { ParentAgentLoaderProvider } from "./steps.js";
111
115
 
@@ -181,11 +185,19 @@ async function createInstance(
181
185
  .addStep(newValidateVisibilityStep())
182
186
  .addStep(newResolveSlugStep())
183
187
  .addStep(newLoadParentAgentStep(deps.parentAgentLoader, deps.logger))
188
+ // Before the duplicate check, so a refused caller learns nothing about
189
+ // which slugs exist (steps.ts, resolveInstanceCreateTargets).
190
+ .addStep(
191
+ newAuthorizeResolvedTargetStep(
192
+ deps.authorizer,
193
+ resolveInstanceCreateTargets,
194
+ ),
195
+ )
184
196
  .addStep(newCheckDuplicateStep(deps.store))
185
197
  .addStep(newBuildNewStateStep())
186
- .addStep(newGuardPublicVisibilityStep(deps.authorizer))
187
198
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
188
199
  .addStep(newNormalizeReferencesStep())
200
+ .addStep(newValidateReferencesStep(deps.store))
189
201
  .addStep(newPersistStep(deps.store))
190
202
  .addStep(
191
203
  newCreateAuthorizationTuplesStep(
@@ -230,6 +242,7 @@ async function update(
230
242
  .addStep(newBuildUpdateStateStep())
231
243
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
232
244
  .addStep(newNormalizeReferencesStep())
245
+ .addStep(newValidateReferencesStep(deps.store))
233
246
  .addStep(newPersistStep(deps.store))
234
247
  .addStep(
235
248
  newIndexSearchStep(deps.store, agentInstanceSearchExtractor, deps.logger),
@@ -370,12 +383,6 @@ async function updateVisibility(
370
383
  )
371
384
  .addStep(newRejectDefaultInstanceVisibilityUpdateStep(deps.store))
372
385
  .addStep(newValidateVisibilityUpdateStep())
373
- .addStep(
374
- newAuthorizeVisibilityTransitionStep(
375
- UPDATE_VISIBILITY_INSTANCE_KEY,
376
- deps.authorizer,
377
- ),
378
- )
379
386
  .addStep(newSetInstanceVisibilityStep())
380
387
  .addStep(newPersistInstanceForVisibilityUpdateStep(deps.store))
381
388
  .addStep(
@@ -548,6 +555,12 @@ async function getByReference(
548
555
  )
549
556
  .addStep(newValidateProtoStep())
550
557
  .addStep(newLoadByReferenceStep(deps.store, AgentInstanceSchema))
558
+ .addStep(
559
+ newAuthorizeResolvedTargetStep(
560
+ deps.authorizer,
561
+ loadedTargetAsMethod(AgentInstanceQueryController.method.get),
562
+ ),
563
+ )
551
564
  .build()
552
565
  .execute(reqCtx);
553
566
  return reqCtx.get(TARGET_RESOURCE_KEY) as AgentInstance;