@stigmer/server 3.15.3-dev.20260914100347 → 3.15.3-dev.20260916211208

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 (570) hide show
  1. package/README.md +3 -3
  2. package/dist/archive/content-store.d.ts +35 -0
  3. package/dist/archive/content-store.d.ts.map +1 -0
  4. package/dist/archive/content-store.js +98 -0
  5. package/dist/archive/content-store.js.map +1 -0
  6. package/dist/archive/inflate.d.ts +22 -0
  7. package/dist/archive/inflate.d.ts.map +1 -0
  8. package/dist/archive/inflate.js +75 -0
  9. package/dist/archive/inflate.js.map +1 -0
  10. package/dist/archive/limits.d.ts +33 -0
  11. package/dist/archive/limits.d.ts.map +1 -0
  12. package/dist/archive/limits.js +31 -0
  13. package/dist/archive/limits.js.map +1 -0
  14. package/dist/archive/open.d.ts +24 -0
  15. package/dist/archive/open.d.ts.map +1 -0
  16. package/dist/archive/open.js +93 -0
  17. package/dist/archive/open.js.map +1 -0
  18. package/dist/{domain/skill/storage → archive}/prefilter.d.ts +5 -0
  19. package/dist/archive/prefilter.d.ts.map +1 -0
  20. package/dist/archive/prefilter.js.map +1 -0
  21. package/dist/archive/write.d.ts +8 -0
  22. package/dist/archive/write.d.ts.map +1 -0
  23. package/dist/archive/write.js +44 -0
  24. package/dist/archive/write.js.map +1 -0
  25. package/dist/authorization/authorizer.d.ts +98 -0
  26. package/dist/authorization/authorizer.d.ts.map +1 -0
  27. package/dist/authorization/authorizer.js +156 -0
  28. package/dist/authorization/authorizer.js.map +1 -0
  29. package/dist/authorization/derived-tuples.d.ts +42 -0
  30. package/dist/authorization/derived-tuples.d.ts.map +1 -0
  31. package/dist/authorization/derived-tuples.js +240 -0
  32. package/dist/authorization/derived-tuples.js.map +1 -0
  33. package/dist/authorization/evaluator.d.ts +66 -0
  34. package/dist/authorization/evaluator.d.ts.map +1 -0
  35. package/dist/authorization/evaluator.js +153 -0
  36. package/dist/authorization/evaluator.js.map +1 -0
  37. package/dist/authorization/facts.d.ts +29 -0
  38. package/dist/authorization/facts.d.ts.map +1 -0
  39. package/dist/authorization/facts.js +17 -0
  40. package/dist/authorization/facts.js.map +1 -0
  41. package/dist/authorization/list-read-scope.d.ts +18 -0
  42. package/dist/authorization/list-read-scope.d.ts.map +1 -0
  43. package/dist/authorization/list-read-scope.js +155 -0
  44. package/dist/authorization/list-read-scope.js.map +1 -0
  45. package/dist/authorization/model/agent.d.ts +2 -0
  46. package/dist/authorization/model/agent.d.ts.map +1 -0
  47. package/dist/authorization/model/agent.js +42 -0
  48. package/dist/authorization/model/agent.js.map +1 -0
  49. package/dist/authorization/model/agent_channel.d.ts +2 -0
  50. package/dist/authorization/model/agent_channel.d.ts.map +1 -0
  51. package/dist/authorization/model/agent_channel.js +38 -0
  52. package/dist/authorization/model/agent_channel.js.map +1 -0
  53. package/dist/authorization/model/agent_execution.d.ts +2 -0
  54. package/dist/authorization/model/agent_execution.d.ts.map +1 -0
  55. package/dist/authorization/model/agent_execution.js +25 -0
  56. package/dist/authorization/model/agent_execution.js.map +1 -0
  57. package/dist/authorization/model/agent_instance.d.ts +2 -0
  58. package/dist/authorization/model/agent_instance.d.ts.map +1 -0
  59. package/dist/authorization/model/agent_instance.js +47 -0
  60. package/dist/authorization/model/agent_instance.js.map +1 -0
  61. package/dist/authorization/model/agent_share.d.ts +2 -0
  62. package/dist/authorization/model/agent_share.d.ts.map +1 -0
  63. package/dist/authorization/model/agent_share.js +29 -0
  64. package/dist/authorization/model/agent_share.js.map +1 -0
  65. package/dist/authorization/model/api_key.d.ts +2 -0
  66. package/dist/authorization/model/api_key.d.ts.map +1 -0
  67. package/dist/authorization/model/api_key.js +27 -0
  68. package/dist/authorization/model/api_key.js.map +1 -0
  69. package/dist/authorization/model/artifact.d.ts +2 -0
  70. package/dist/authorization/model/artifact.d.ts.map +1 -0
  71. package/dist/authorization/model/artifact.js +27 -0
  72. package/dist/authorization/model/artifact.js.map +1 -0
  73. package/dist/authorization/model/channel_app.d.ts +2 -0
  74. package/dist/authorization/model/channel_app.d.ts.map +1 -0
  75. package/dist/authorization/model/channel_app.js +28 -0
  76. package/dist/authorization/model/channel_app.js.map +1 -0
  77. package/dist/authorization/model/default-of.d.ts +38 -0
  78. package/dist/authorization/model/default-of.d.ts.map +1 -0
  79. package/dist/authorization/model/default-of.js +39 -0
  80. package/dist/authorization/model/default-of.js.map +1 -0
  81. package/dist/authorization/model/environment.d.ts +2 -0
  82. package/dist/authorization/model/environment.d.ts.map +1 -0
  83. package/dist/authorization/model/environment.js +33 -0
  84. package/dist/authorization/model/environment.js.map +1 -0
  85. package/dist/authorization/model/execution_context.d.ts +2 -0
  86. package/dist/authorization/model/execution_context.d.ts.map +1 -0
  87. package/dist/authorization/model/execution_context.js +19 -0
  88. package/dist/authorization/model/execution_context.js.map +1 -0
  89. package/dist/authorization/model/iam_policy.d.ts +2 -0
  90. package/dist/authorization/model/iam_policy.d.ts.map +1 -0
  91. package/dist/authorization/model/iam_policy.js +31 -0
  92. package/dist/authorization/model/iam_policy.js.map +1 -0
  93. package/dist/authorization/model/identity_account.d.ts +2 -0
  94. package/dist/authorization/model/identity_account.d.ts.map +1 -0
  95. package/dist/authorization/model/identity_account.js +25 -0
  96. package/dist/authorization/model/identity_account.js.map +1 -0
  97. package/dist/authorization/model/index.d.ts +36 -0
  98. package/dist/authorization/model/index.d.ts.map +1 -0
  99. package/dist/authorization/model/index.js +72 -0
  100. package/dist/authorization/model/index.js.map +1 -0
  101. package/dist/authorization/model/mcp_server.d.ts +2 -0
  102. package/dist/authorization/model/mcp_server.d.ts.map +1 -0
  103. package/dist/authorization/model/mcp_server.js +37 -0
  104. package/dist/authorization/model/mcp_server.js.map +1 -0
  105. package/dist/authorization/model/memory.d.ts +2 -0
  106. package/dist/authorization/model/memory.d.ts.map +1 -0
  107. package/dist/authorization/model/memory.js +26 -0
  108. package/dist/authorization/model/memory.js.map +1 -0
  109. package/dist/authorization/model/oauth_app.d.ts +2 -0
  110. package/dist/authorization/model/oauth_app.d.ts.map +1 -0
  111. package/dist/authorization/model/oauth_app.js +30 -0
  112. package/dist/authorization/model/oauth_app.js.map +1 -0
  113. package/dist/authorization/model/organization.d.ts +2 -0
  114. package/dist/authorization/model/organization.d.ts.map +1 -0
  115. package/dist/authorization/model/organization.js +54 -0
  116. package/dist/authorization/model/organization.js.map +1 -0
  117. package/dist/authorization/model/plugin.d.ts +2 -0
  118. package/dist/authorization/model/plugin.d.ts.map +1 -0
  119. package/dist/authorization/model/plugin.js +44 -0
  120. package/dist/authorization/model/plugin.js.map +1 -0
  121. package/dist/authorization/model/project.d.ts +2 -0
  122. package/dist/authorization/model/project.d.ts.map +1 -0
  123. package/dist/authorization/model/project.js +32 -0
  124. package/dist/authorization/model/project.js.map +1 -0
  125. package/dist/authorization/model/rewrite.d.ts +127 -0
  126. package/dist/authorization/model/rewrite.d.ts.map +1 -0
  127. package/dist/authorization/model/rewrite.js +82 -0
  128. package/dist/authorization/model/rewrite.js.map +1 -0
  129. package/dist/authorization/model/schedule.d.ts +2 -0
  130. package/dist/authorization/model/schedule.d.ts.map +1 -0
  131. package/dist/authorization/model/schedule.js +29 -0
  132. package/dist/authorization/model/schedule.js.map +1 -0
  133. package/dist/authorization/model/session.d.ts +2 -0
  134. package/dist/authorization/model/session.d.ts.map +1 -0
  135. package/dist/authorization/model/session.js +38 -0
  136. package/dist/authorization/model/session.js.map +1 -0
  137. package/dist/authorization/model/skill.d.ts +2 -0
  138. package/dist/authorization/model/skill.d.ts.map +1 -0
  139. package/dist/authorization/model/skill.js +38 -0
  140. package/dist/authorization/model/skill.js.map +1 -0
  141. package/dist/authorization/model/workflow.d.ts +2 -0
  142. package/dist/authorization/model/workflow.d.ts.map +1 -0
  143. package/dist/authorization/model/workflow.js +38 -0
  144. package/dist/authorization/model/workflow.js.map +1 -0
  145. package/dist/authorization/model/workflow_execution.d.ts +2 -0
  146. package/dist/authorization/model/workflow_execution.d.ts.map +1 -0
  147. package/dist/authorization/model/workflow_execution.js +32 -0
  148. package/dist/authorization/model/workflow_execution.js.map +1 -0
  149. package/dist/authorization/model/workflow_instance.d.ts +2 -0
  150. package/dist/authorization/model/workflow_instance.d.ts.map +1 -0
  151. package/dist/authorization/model/workflow_instance.js +92 -0
  152. package/dist/authorization/model/workflow_instance.js.map +1 -0
  153. package/dist/authorization/organization-directory.d.ts +13 -0
  154. package/dist/authorization/organization-directory.d.ts.map +1 -0
  155. package/dist/authorization/organization-directory.js +83 -0
  156. package/dist/authorization/organization-directory.js.map +1 -0
  157. package/dist/authorization/person.d.ts +42 -0
  158. package/dist/authorization/person.d.ts.map +1 -0
  159. package/dist/authorization/person.js +19 -0
  160. package/dist/authorization/person.js.map +1 -0
  161. package/dist/authorization/posture.d.ts +38 -0
  162. package/dist/authorization/posture.d.ts.map +1 -0
  163. package/dist/authorization/posture.js +7 -0
  164. package/dist/authorization/posture.js.map +1 -0
  165. package/dist/authorization/schedule-fire-caller.d.ts +12 -0
  166. package/dist/authorization/schedule-fire-caller.d.ts.map +1 -0
  167. package/dist/authorization/schedule-fire-caller.js +67 -0
  168. package/dist/authorization/schedule-fire-caller.js.map +1 -0
  169. package/dist/authorization/store-test-kit.d.ts +68 -0
  170. package/dist/authorization/store-test-kit.d.ts.map +1 -0
  171. package/dist/authorization/store-test-kit.js +311 -0
  172. package/dist/authorization/store-test-kit.js.map +1 -0
  173. package/dist/authorization/tuples.d.ts +115 -0
  174. package/dist/authorization/tuples.d.ts.map +1 -0
  175. package/dist/authorization/tuples.js +83 -0
  176. package/dist/authorization/tuples.js.map +1 -0
  177. package/dist/boot/compose.d.ts.map +1 -1
  178. package/dist/boot/compose.js +157 -32
  179. package/dist/boot/compose.js.map +1 -1
  180. package/dist/boot/inprocess.d.ts +12 -0
  181. package/dist/boot/inprocess.d.ts.map +1 -1
  182. package/dist/boot/inprocess.js +62 -20
  183. package/dist/boot/inprocess.js.map +1 -1
  184. package/dist/domain/agent/controller.d.ts.map +1 -1
  185. package/dist/domain/agent/controller.js +9 -0
  186. package/dist/domain/agent/controller.js.map +1 -1
  187. package/dist/domain/iampolicy/constants.d.ts +11 -0
  188. package/dist/domain/iampolicy/constants.d.ts.map +1 -1
  189. package/dist/domain/iampolicy/constants.js +11 -0
  190. package/dist/domain/iampolicy/constants.js.map +1 -1
  191. package/dist/domain/iampolicy/membership.d.ts +72 -1
  192. package/dist/domain/iampolicy/membership.d.ts.map +1 -1
  193. package/dist/domain/iampolicy/membership.js +141 -56
  194. package/dist/domain/iampolicy/membership.js.map +1 -1
  195. package/dist/domain/identityaccount/actor.d.ts +26 -0
  196. package/dist/domain/identityaccount/actor.d.ts.map +1 -0
  197. package/dist/domain/identityaccount/actor.js +17 -0
  198. package/dist/domain/identityaccount/actor.js.map +1 -0
  199. package/dist/domain/mcpserver/controller.d.ts.map +1 -1
  200. package/dist/domain/mcpserver/controller.js +9 -0
  201. package/dist/domain/mcpserver/controller.js.map +1 -1
  202. package/dist/domain/plugin/archive.d.ts +37 -0
  203. package/dist/domain/plugin/archive.d.ts.map +1 -0
  204. package/dist/domain/plugin/archive.js +50 -0
  205. package/dist/domain/plugin/archive.js.map +1 -0
  206. package/dist/domain/plugin/constants.d.ts +38 -0
  207. package/dist/domain/plugin/constants.d.ts.map +1 -0
  208. package/dist/domain/plugin/constants.js +46 -0
  209. package/dist/domain/plugin/constants.js.map +1 -0
  210. package/dist/domain/plugin/controller.d.ts +25 -0
  211. package/dist/domain/plugin/controller.d.ts.map +1 -0
  212. package/dist/domain/plugin/controller.js +493 -0
  213. package/dist/domain/plugin/controller.js.map +1 -0
  214. package/dist/domain/plugin/materialize/agent.d.ts +13 -0
  215. package/dist/domain/plugin/materialize/agent.d.ts.map +1 -0
  216. package/dist/domain/plugin/materialize/agent.js +128 -0
  217. package/dist/domain/plugin/materialize/agent.js.map +1 -0
  218. package/dist/domain/plugin/materialize/default-agent-instructions.d.ts +22 -0
  219. package/dist/domain/plugin/materialize/default-agent-instructions.d.ts.map +1 -0
  220. package/dist/domain/plugin/materialize/default-agent-instructions.js +31 -0
  221. package/dist/domain/plugin/materialize/default-agent-instructions.js.map +1 -0
  222. package/dist/domain/plugin/materialize/identity.d.ts +28 -0
  223. package/dist/domain/plugin/materialize/identity.d.ts.map +1 -0
  224. package/dist/domain/plugin/materialize/identity.js +40 -0
  225. package/dist/domain/plugin/materialize/identity.js.map +1 -0
  226. package/dist/domain/plugin/materialize/mcp-servers.d.ts +15 -0
  227. package/dist/domain/plugin/materialize/mcp-servers.d.ts.map +1 -0
  228. package/dist/domain/plugin/materialize/mcp-servers.js +131 -0
  229. package/dist/domain/plugin/materialize/mcp-servers.js.map +1 -0
  230. package/dist/domain/plugin/materialize/plan.d.ts +24 -0
  231. package/dist/domain/plugin/materialize/plan.d.ts.map +1 -0
  232. package/dist/domain/plugin/materialize/plan.js +77 -0
  233. package/dist/domain/plugin/materialize/plan.js.map +1 -0
  234. package/dist/domain/plugin/materialize/ports.d.ts +42 -0
  235. package/dist/domain/plugin/materialize/ports.d.ts.map +1 -0
  236. package/dist/domain/plugin/materialize/ports.js +2 -0
  237. package/dist/domain/plugin/materialize/ports.js.map +1 -0
  238. package/dist/domain/plugin/materialize/skills.d.ts +12 -0
  239. package/dist/domain/plugin/materialize/skills.d.ts.map +1 -0
  240. package/dist/domain/plugin/materialize/skills.js +44 -0
  241. package/dist/domain/plugin/materialize/skills.js.map +1 -0
  242. package/dist/domain/plugin/materialize/workflows.d.ts +15 -0
  243. package/dist/domain/plugin/materialize/workflows.d.ts.map +1 -0
  244. package/dist/domain/plugin/materialize/workflows.js +31 -0
  245. package/dist/domain/plugin/materialize/workflows.js.map +1 -0
  246. package/dist/domain/plugin/members.d.ts +42 -0
  247. package/dist/domain/plugin/members.d.ts.map +1 -0
  248. package/dist/domain/plugin/members.js +97 -0
  249. package/dist/domain/plugin/members.js.map +1 -0
  250. package/dist/domain/plugin/overlay/documents.d.ts +31 -0
  251. package/dist/domain/plugin/overlay/documents.d.ts.map +1 -0
  252. package/dist/domain/plugin/overlay/documents.js +38 -0
  253. package/dist/domain/plugin/overlay/documents.js.map +1 -0
  254. package/dist/domain/plugin/overlay/parse.d.ts +16 -0
  255. package/dist/domain/plugin/overlay/parse.d.ts.map +1 -0
  256. package/dist/domain/plugin/overlay/parse.js +79 -0
  257. package/dist/domain/plugin/overlay/parse.js.map +1 -0
  258. package/dist/domain/plugin/overlay/sanitize.d.ts +10 -0
  259. package/dist/domain/plugin/overlay/sanitize.d.ts.map +1 -0
  260. package/dist/domain/plugin/overlay/sanitize.js +101 -0
  261. package/dist/domain/plugin/overlay/sanitize.js.map +1 -0
  262. package/dist/domain/plugin/push.d.ts +133 -0
  263. package/dist/domain/plugin/push.d.ts.map +1 -0
  264. package/dist/domain/plugin/push.js +800 -0
  265. package/dist/domain/plugin/push.js.map +1 -0
  266. package/dist/domain/plugin/search-extractor.d.ts +3 -0
  267. package/dist/domain/plugin/search-extractor.d.ts.map +1 -0
  268. package/dist/domain/plugin/search-extractor.js +41 -0
  269. package/dist/domain/plugin/search-extractor.js.map +1 -0
  270. package/dist/domain/skill/constants.d.ts +6 -11
  271. package/dist/domain/skill/constants.d.ts.map +1 -1
  272. package/dist/domain/skill/constants.js +6 -11
  273. package/dist/domain/skill/constants.js.map +1 -1
  274. package/dist/domain/skill/controller.d.ts.map +1 -1
  275. package/dist/domain/skill/controller.js +33 -30
  276. package/dist/domain/skill/controller.js.map +1 -1
  277. package/dist/domain/skill/push.d.ts +9 -10
  278. package/dist/domain/skill/push.d.ts.map +1 -1
  279. package/dist/domain/skill/push.js +53 -122
  280. package/dist/domain/skill/push.js.map +1 -1
  281. package/dist/domain/skill/search-extractor.d.ts.map +1 -1
  282. package/dist/domain/skill/search-extractor.js.map +1 -1
  283. package/dist/domain/skill/storage/artifact-storage.d.ts +26 -29
  284. package/dist/domain/skill/storage/artifact-storage.d.ts.map +1 -1
  285. package/dist/domain/skill/storage/artifact-storage.js +6 -103
  286. package/dist/domain/skill/storage/artifact-storage.js.map +1 -1
  287. package/dist/domain/skill/storage/zip-gate.d.ts +1 -2
  288. package/dist/domain/skill/storage/zip-gate.d.ts.map +1 -1
  289. package/dist/domain/skill/storage/zip-gate.js +56 -126
  290. package/dist/domain/skill/storage/zip-gate.js.map +1 -1
  291. package/dist/domain/skill/version-resolution.d.ts +5 -5
  292. package/dist/domain/skill/version-resolution.d.ts.map +1 -1
  293. package/dist/domain/skill/version-resolution.js +34 -216
  294. package/dist/domain/skill/version-resolution.js.map +1 -1
  295. package/dist/domain/workflow/controller.d.ts.map +1 -1
  296. package/dist/domain/workflow/controller.js +30 -3
  297. package/dist/domain/workflow/controller.js.map +1 -1
  298. package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -0
  299. package/dist/extensions/authorizer.d.ts +10 -5
  300. package/dist/extensions/authorizer.d.ts.map +1 -1
  301. package/dist/extensions/drivers.d.ts +4 -1
  302. package/dist/extensions/drivers.d.ts.map +1 -1
  303. package/dist/extensions/list-read-scope.d.ts +75 -11
  304. package/dist/extensions/list-read-scope.d.ts.map +1 -1
  305. package/dist/extensions/list-read-scope.js +40 -7
  306. package/dist/extensions/list-read-scope.js.map +1 -1
  307. package/dist/extensions/organization-directory.d.ts +13 -9
  308. package/dist/extensions/organization-directory.d.ts.map +1 -1
  309. package/dist/extensions/organization-directory.js.map +1 -1
  310. package/dist/extensions/resource-authorization.d.ts +33 -0
  311. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  312. package/dist/extensions/schedule-fire-caller.d.ts +45 -18
  313. package/dist/extensions/schedule-fire-caller.d.ts.map +1 -1
  314. package/dist/extensions/schedule-fire-caller.js +12 -1
  315. package/dist/extensions/schedule-fire-caller.js.map +1 -1
  316. package/dist/index.d.ts +10 -0
  317. package/dist/index.d.ts.map +1 -1
  318. package/dist/index.js +8 -0
  319. package/dist/index.js.map +1 -1
  320. package/dist/pipeline/apiresource-labels.d.ts +23 -3
  321. package/dist/pipeline/apiresource-labels.d.ts.map +1 -1
  322. package/dist/pipeline/apiresource-labels.js +20 -0
  323. package/dist/pipeline/apiresource-labels.js.map +1 -1
  324. package/dist/pipeline/apiresource-meta.d.ts +21 -0
  325. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  326. package/dist/pipeline/apiresource-meta.js +28 -0
  327. package/dist/pipeline/apiresource-meta.js.map +1 -1
  328. package/dist/pipeline/errors.d.ts.map +1 -1
  329. package/dist/pipeline/errors.js.map +1 -1
  330. package/dist/pipeline/steps/authorization-facts.d.ts +12 -0
  331. package/dist/pipeline/steps/authorization-facts.d.ts.map +1 -0
  332. package/dist/pipeline/steps/authorization-facts.js +100 -0
  333. package/dist/pipeline/steps/authorization-facts.js.map +1 -0
  334. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  335. package/dist/pipeline/steps/authorization-tuples.js +7 -26
  336. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  337. package/dist/pipeline/steps/delete.d.ts.map +1 -1
  338. package/dist/pipeline/steps/delete.js +1 -1
  339. package/dist/pipeline/steps/delete.js.map +1 -1
  340. package/dist/pipeline/steps/duplicate.d.ts.map +1 -1
  341. package/dist/pipeline/steps/duplicate.js.map +1 -1
  342. package/dist/pipeline/steps/guard-plugin-managed.d.ts +12 -0
  343. package/dist/pipeline/steps/guard-plugin-managed.d.ts.map +1 -0
  344. package/dist/pipeline/steps/guard-plugin-managed.js +96 -0
  345. package/dist/pipeline/steps/guard-plugin-managed.js.map +1 -0
  346. package/dist/pipeline/steps/guard-reserved-labels.d.ts +16 -2
  347. package/dist/pipeline/steps/guard-reserved-labels.d.ts.map +1 -1
  348. package/dist/pipeline/steps/guard-reserved-labels.js +11 -7
  349. package/dist/pipeline/steps/guard-reserved-labels.js.map +1 -1
  350. package/dist/pipeline/steps/helpers.d.ts.map +1 -1
  351. package/dist/pipeline/steps/helpers.js.map +1 -1
  352. package/dist/pipeline/steps/index-search.d.ts.map +1 -1
  353. package/dist/pipeline/steps/index-search.js.map +1 -1
  354. package/dist/pipeline/steps/load-existing.d.ts.map +1 -1
  355. package/dist/pipeline/steps/load-existing.js +1 -1
  356. package/dist/pipeline/steps/load-existing.js.map +1 -1
  357. package/dist/pipeline/steps/references.d.ts +16 -0
  358. package/dist/pipeline/steps/references.d.ts.map +1 -1
  359. package/dist/pipeline/steps/references.js +18 -0
  360. package/dist/pipeline/steps/references.js.map +1 -1
  361. package/dist/pipeline/steps/resolve-artifact-source.d.ts +35 -0
  362. package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -0
  363. package/dist/pipeline/steps/resolve-artifact-source.js +27 -0
  364. package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -0
  365. package/dist/pipeline/steps/server-stamped-reserved-labels.d.ts.map +1 -1
  366. package/dist/pipeline/steps/server-stamped-reserved-labels.js.map +1 -1
  367. package/dist/pipeline/steps/shapes.d.ts +18 -0
  368. package/dist/pipeline/steps/shapes.d.ts.map +1 -1
  369. package/dist/pipeline/steps/shapes.js +29 -0
  370. package/dist/pipeline/steps/shapes.js.map +1 -1
  371. package/dist/pipeline/steps/slug.d.ts.map +1 -1
  372. package/dist/pipeline/steps/slug.js.map +1 -1
  373. package/dist/pipeline/steps/validate-visibility.d.ts +9 -0
  374. package/dist/pipeline/steps/validate-visibility.d.ts.map +1 -1
  375. package/dist/pipeline/steps/validate-visibility.js +6 -1
  376. package/dist/pipeline/steps/validate-visibility.js.map +1 -1
  377. package/dist/pipeline/steps/validation.d.ts.map +1 -1
  378. package/dist/pipeline/steps/validation.js.map +1 -1
  379. package/dist/pipeline/steps/version-archive.d.ts +63 -0
  380. package/dist/pipeline/steps/version-archive.d.ts.map +1 -0
  381. package/dist/pipeline/steps/version-archive.js +129 -0
  382. package/dist/pipeline/steps/version-archive.js.map +1 -0
  383. package/dist/pipeline/steps/version-history.d.ts +49 -0
  384. package/dist/pipeline/steps/version-history.d.ts.map +1 -0
  385. package/dist/pipeline/steps/version-history.js +229 -0
  386. package/dist/pipeline/steps/version-history.js.map +1 -0
  387. package/dist/pipeline/steps/visibility-gates.d.ts +8 -0
  388. package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -1
  389. package/dist/pipeline/steps/visibility-gates.js +7 -2
  390. package/dist/pipeline/steps/visibility-gates.js.map +1 -1
  391. package/dist/query/search/registry.d.ts.map +1 -1
  392. package/dist/query/search/registry.js +2 -0
  393. package/dist/query/search/registry.js.map +1 -1
  394. package/dist/temporal/schedule/run-starter.d.ts +1 -1
  395. package/dist/temporal/schedule/run-starter.d.ts.map +1 -1
  396. package/dist/temporal/schedule/run-starter.js +14 -1
  397. package/dist/temporal/schedule/run-starter.js.map +1 -1
  398. package/package.json +5 -4
  399. package/src/archive/__tests__/archive.test.ts +233 -0
  400. package/src/{domain/skill → archive}/__tests__/prefilter.test.ts +1 -1
  401. package/src/archive/content-store.ts +132 -0
  402. package/src/archive/inflate.ts +107 -0
  403. package/src/archive/limits.ts +42 -0
  404. package/src/archive/open.ts +131 -0
  405. package/src/{domain/skill/storage → archive}/prefilter.ts +5 -0
  406. package/src/archive/write.ts +54 -0
  407. package/src/authorization/README.md +124 -0
  408. package/src/authorization/__tests__/authorizer.test.ts +719 -0
  409. package/src/authorization/__tests__/derived-tuples.test.ts +802 -0
  410. package/src/authorization/__tests__/drivers.ts +70 -0
  411. package/src/authorization/__tests__/evaluator.test.ts +359 -0
  412. package/src/authorization/__tests__/facts.test.ts +155 -0
  413. package/src/authorization/__tests__/fixtures/fga/agent-channel-owner.fga.yaml +112 -0
  414. package/src/authorization/__tests__/fixtures/fga/agent-share-owner.fga.yaml +109 -0
  415. package/src/authorization/__tests__/fixtures/fga/artifact-org-and-owner.fga.yaml +128 -0
  416. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +410 -0
  417. package/src/authorization/__tests__/fixtures/fga/channel-app-owner.fga.yaml +125 -0
  418. package/src/authorization/__tests__/fixtures/fga/channel-participation.fga.yaml +201 -0
  419. package/src/authorization/__tests__/fixtures/fga/channel-session-visibility.fga.yaml +187 -0
  420. package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
  421. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +271 -0
  422. package/src/authorization/__tests__/fixtures/fga/memory-subject-only.fga.yaml +72 -0
  423. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +328 -0
  424. package/src/authorization/__tests__/fixtures/fga/org-shared-environment.fga.yaml +144 -0
  425. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +223 -0
  426. package/src/authorization/__tests__/fixtures/fga/provider-standing-viewer.fga.yaml +40 -0
  427. package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
  428. package/src/authorization/__tests__/fixtures/fga/reserved-label-writer.fga.yaml +41 -0
  429. package/src/authorization/__tests__/fixtures/fga/schedule-owner.fga.yaml +113 -0
  430. package/src/authorization/__tests__/fixtures/fga/schedule-session-visibility.fga.yaml +214 -0
  431. package/src/authorization/__tests__/fixtures/fga/session-personal-resource.fga.yaml +117 -0
  432. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +192 -0
  433. package/src/authorization/__tests__/list-read-scope.measure.test.ts +317 -0
  434. package/src/authorization/__tests__/list-read-scope.test.ts +796 -0
  435. package/src/authorization/__tests__/organization-directory.test.ts +236 -0
  436. package/src/authorization/__tests__/person.test.ts +114 -0
  437. package/src/authorization/__tests__/posture.test.ts +25 -0
  438. package/src/authorization/__tests__/schedule-fire-caller.test.ts +134 -0
  439. package/src/authorization/__tests__/store-tests.test.ts +306 -0
  440. package/src/authorization/__tests__/support.ts +101 -0
  441. package/src/authorization/__tests__/tuples.test.ts +62 -0
  442. package/src/authorization/__tests__/wire-permissions.test.ts +154 -0
  443. package/src/authorization/authorizer.ts +208 -0
  444. package/src/authorization/derived-tuples.ts +384 -0
  445. package/src/authorization/evaluator.ts +283 -0
  446. package/src/authorization/facts.ts +47 -0
  447. package/src/authorization/list-read-scope.ts +216 -0
  448. package/src/authorization/model/__tests__/registry.test.ts +317 -0
  449. package/src/authorization/model/agent.ts +64 -0
  450. package/src/authorization/model/agent_channel.ts +49 -0
  451. package/src/authorization/model/agent_execution.ts +33 -0
  452. package/src/authorization/model/agent_instance.ts +66 -0
  453. package/src/authorization/model/agent_share.ts +40 -0
  454. package/src/authorization/model/api_key.ts +28 -0
  455. package/src/authorization/model/artifact.ts +38 -0
  456. package/src/authorization/model/channel_app.ts +39 -0
  457. package/src/authorization/model/default-of.ts +99 -0
  458. package/src/authorization/model/environment.ts +48 -0
  459. package/src/authorization/model/execution_context.ts +20 -0
  460. package/src/authorization/model/iam_policy.ts +42 -0
  461. package/src/authorization/model/identity_account.ts +26 -0
  462. package/src/authorization/model/index.ts +108 -0
  463. package/src/authorization/model/mcp_server.ts +59 -0
  464. package/src/authorization/model/memory.ts +27 -0
  465. package/src/authorization/model/oauth_app.ts +42 -0
  466. package/src/authorization/model/organization.ts +55 -0
  467. package/src/authorization/model/plugin.ts +66 -0
  468. package/src/authorization/model/project.ts +47 -0
  469. package/src/authorization/model/rewrite.ts +213 -0
  470. package/src/authorization/model/schedule.ts +40 -0
  471. package/src/authorization/model/session.ts +50 -0
  472. package/src/authorization/model/skill.ts +60 -0
  473. package/src/authorization/model/workflow.ts +60 -0
  474. package/src/authorization/model/workflow_execution.ts +44 -0
  475. package/src/authorization/model/workflow_instance.ts +122 -0
  476. package/src/authorization/organization-directory.ts +114 -0
  477. package/src/authorization/person.ts +68 -0
  478. package/src/authorization/posture.ts +49 -0
  479. package/src/authorization/schedule-fire-caller.ts +91 -0
  480. package/src/authorization/store-test-kit.ts +454 -0
  481. package/src/authorization/tuples.ts +190 -0
  482. package/src/boot/compose.ts +175 -38
  483. package/src/boot/inprocess.ts +108 -30
  484. package/src/domain/agent/controller.ts +11 -0
  485. package/src/domain/iampolicy/__tests__/membership.test.ts +357 -3
  486. package/src/domain/iampolicy/constants.ts +12 -0
  487. package/src/domain/iampolicy/membership.ts +221 -66
  488. package/src/domain/identityaccount/actor.ts +44 -0
  489. package/src/domain/mcpserver/controller.ts +11 -0
  490. package/src/domain/plugin/__tests__/materialize.test.ts +303 -0
  491. package/src/domain/plugin/__tests__/overlay-parse.test.ts +85 -0
  492. package/src/domain/plugin/__tests__/plugin.test.ts +681 -0
  493. package/src/domain/plugin/__tests__/sanitize.test.ts +174 -0
  494. package/src/domain/plugin/archive.ts +89 -0
  495. package/src/domain/plugin/constants.ts +53 -0
  496. package/src/domain/plugin/controller.ts +913 -0
  497. package/src/domain/plugin/materialize/agent.ts +186 -0
  498. package/src/domain/plugin/materialize/default-agent-instructions.ts +59 -0
  499. package/src/domain/plugin/materialize/identity.ts +67 -0
  500. package/src/domain/plugin/materialize/mcp-servers.ts +175 -0
  501. package/src/domain/plugin/materialize/plan.ts +124 -0
  502. package/src/domain/plugin/materialize/ports.ts +53 -0
  503. package/src/domain/plugin/materialize/skills.ts +68 -0
  504. package/src/domain/plugin/materialize/workflows.ts +51 -0
  505. package/src/domain/plugin/members.ts +180 -0
  506. package/src/domain/plugin/overlay/documents.ts +78 -0
  507. package/src/domain/plugin/overlay/parse.ts +115 -0
  508. package/src/domain/plugin/overlay/sanitize.ts +149 -0
  509. package/src/domain/plugin/push.ts +1062 -0
  510. package/src/domain/plugin/search-extractor.ts +60 -0
  511. package/src/domain/skill/constants.ts +11 -14
  512. package/src/domain/skill/controller.ts +44 -36
  513. package/src/domain/skill/push.ts +61 -156
  514. package/src/domain/skill/search-extractor.ts +3 -1
  515. package/src/domain/skill/storage/artifact-storage.ts +23 -124
  516. package/src/domain/skill/storage/zip-gate.ts +58 -154
  517. package/src/domain/skill/version-resolution.ts +67 -269
  518. package/src/domain/workflow/controller.ts +38 -4
  519. package/src/domain/workflow/registry/data/task-kind-registry.json +1 -0
  520. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +835 -0
  521. package/src/extensions/__tests__/composed-support.ts +32 -1
  522. package/src/extensions/__tests__/extension-composition.test.ts +35 -0
  523. package/src/extensions/__tests__/list-read-scope.test.ts +245 -3
  524. package/src/extensions/__tests__/role-reconciliation-composed.test.ts +209 -0
  525. package/src/extensions/__tests__/tier-truthfulness.test.ts +6 -14
  526. package/src/extensions/authorizer.ts +10 -5
  527. package/src/extensions/drivers.ts +4 -1
  528. package/src/extensions/list-read-scope.ts +116 -16
  529. package/src/extensions/organization-directory.ts +13 -9
  530. package/src/extensions/resource-authorization.ts +34 -0
  531. package/src/extensions/schedule-fire-caller.ts +49 -18
  532. package/src/index.ts +51 -1
  533. package/src/pipeline/__tests__/inherited-authorization-parent.test.ts +51 -0
  534. package/src/pipeline/__tests__/router-transport.test.ts +1 -3
  535. package/src/pipeline/apiresource-labels.ts +31 -3
  536. package/src/pipeline/apiresource-meta.ts +37 -0
  537. package/src/pipeline/errors.ts +5 -5
  538. package/src/pipeline/steps/__tests__/authorize-annotation-completeness.test.ts +1 -20
  539. package/src/pipeline/steps/__tests__/guard-memory-capture.test.ts +3 -9
  540. package/src/pipeline/steps/__tests__/guard-plugin-managed.test.ts +151 -0
  541. package/src/pipeline/steps/__tests__/guard-reserved-labels.test.ts +83 -8
  542. package/src/pipeline/steps/authorization-facts.ts +131 -0
  543. package/src/pipeline/steps/authorization-tuples.ts +7 -28
  544. package/src/pipeline/steps/delete.ts +11 -3
  545. package/src/pipeline/steps/duplicate.ts +8 -2
  546. package/src/pipeline/steps/guard-plugin-managed.ts +133 -0
  547. package/src/pipeline/steps/guard-reserved-labels.ts +29 -8
  548. package/src/pipeline/steps/helpers.ts +4 -1
  549. package/src/pipeline/steps/index-search.ts +28 -15
  550. package/src/pipeline/steps/load-existing.ts +12 -3
  551. package/src/pipeline/steps/references.ts +36 -2
  552. package/src/pipeline/steps/resolve-artifact-source.ts +66 -0
  553. package/src/pipeline/steps/server-stamped-reserved-labels.ts +2 -1
  554. package/src/pipeline/steps/shapes.ts +31 -0
  555. package/src/pipeline/steps/slug.ts +7 -2
  556. package/src/pipeline/steps/validate-visibility.ts +9 -2
  557. package/src/pipeline/steps/validation.ts +3 -1
  558. package/src/pipeline/steps/version-archive.ts +225 -0
  559. package/src/pipeline/steps/version-history.ts +362 -0
  560. package/src/pipeline/steps/visibility-gates.ts +12 -9
  561. package/src/query/README.md +1 -1
  562. package/src/query/search/__tests__/criteria.test.ts +6 -7
  563. package/src/query/search/__tests__/query-store.test.ts +9 -2
  564. package/src/query/search/__tests__/registry.test.ts +6 -4
  565. package/src/query/search/registry.ts +6 -1
  566. package/src/temporal/schedule/__tests__/run-starter.test.ts +86 -24
  567. package/src/temporal/schedule/run-starter.ts +31 -8
  568. package/dist/domain/skill/storage/prefilter.d.ts.map +0 -1
  569. package/dist/domain/skill/storage/prefilter.js.map +0 -1
  570. /package/dist/{domain/skill/storage → archive}/prefilter.js +0 -0
@@ -0,0 +1,802 @@
1
+ /**
2
+ * Pins the derivation — the ONE place edition knowledge lives in the
3
+ * built-in authorizer: which tuples a stored row stands for, in exactly
4
+ * the shapes the cloud's tuple driver writes (stigmer-cloud
5
+ * iam/tuple-lifecycle.ts: `organization:<org>#viewer` for the org level,
6
+ * the conditional `identity_account:*` for public, the owner by the
7
+ * kind's attribution, the parent links by `kind_meta`). Two facts are the
8
+ * OSS edition's own and are pinned here by name: the organization's owner
9
+ * is a ROW (2b's role lifecycle), never derived from its creator stamp,
10
+ * or a revoked founder would stay owner; and a stamp that names no person
11
+ * (`""`, `"system"`) becomes no tuple at all.
12
+ *
13
+ * The second half runs the tuple SOURCE over both store drivers: rows and
14
+ * derived tuples unioned per object, the person's rows read once per
15
+ * source, an absent object answering nothing, a store fault propagating
16
+ * as the fault it is — the ratified store-fault mapping, which is what
17
+ * lets the driver above fold it to `unavailable` and never to a denial.
18
+ */
19
+ import { create } from "@bufbuild/protobuf";
20
+ import { afterAll, afterEach, beforeEach, describe, expect, it } from "vitest";
21
+
22
+ import { WorkflowExecutionVisibility } from "@stigmer/protos/ai/stigmer/agentic/workflowinstance/v1/spec_pb";
23
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
24
+ import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
25
+ import { IamPolicySchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
26
+ import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
27
+ import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
28
+
29
+ import {
30
+ IAM_POLICY_API_VERSION,
31
+ IAM_POLICY_KIND,
32
+ policyIdFor,
33
+ } from "../../domain/iampolicy/constants.js";
34
+ import { newResourceIamPolicyStore } from "../../domain/iampolicy/resource-store.js";
35
+ import type { IamPolicyStore } from "../../domain/iampolicy/store.js";
36
+ import { orgRole, triple } from "../../domain/iampolicy/__tests__/support.js";
37
+ import { fakeIdentityAccountStore } from "../../domain/identityaccount/__tests__/support.js";
38
+ import { newResourceIdentityAccountStore } from "../../domain/identityaccount/resource-store.js";
39
+ import type { IdentityAccountStore } from "../../domain/identityaccount/store.js";
40
+ import { deriveTuples, newDerivedTupleSource } from "../derived-tuples.js";
41
+ import { checkRelation } from "../evaluator.js";
42
+ import { rowFactsOf } from "../facts.js";
43
+ import { builtInModel } from "../model/index.js";
44
+ import type { KindDeclaration } from "../model/rewrite.js";
45
+ import type { Person } from "../tuples.js";
46
+ import { formatTuple, parseObjectRef } from "../tuples.js";
47
+ import { driverFixtures, dropPostgresFixture } from "./drivers.js";
48
+ import type { OpenedStore } from "./drivers.js";
49
+ import { fixtureRow } from "./support.js";
50
+
51
+ function declared(type: string): KindDeclaration {
52
+ const declaration = builtInModel.byType(type);
53
+ if (declaration === undefined) {
54
+ throw new Error(`${type} is declared in this slice`);
55
+ }
56
+ return declaration;
57
+ }
58
+
59
+ function derivedFor(
60
+ type: string,
61
+ facts: {
62
+ org?: string;
63
+ visibility?: ApiResourceVisibility;
64
+ createdBy?: string;
65
+ spec?: Readonly<Record<string, unknown>>;
66
+ },
67
+ ): string[] {
68
+ const declaration = declared(type);
69
+ const row = fixtureRow(declaration, {
70
+ id: `${type}-1`,
71
+ org: facts.org ?? "acme",
72
+ visibility: facts.visibility ?? ApiResourceVisibility.visibility_private,
73
+ createdBy: facts.createdBy ?? "ida_carol",
74
+ ...(facts.spec === undefined ? {} : { spec: facts.spec }),
75
+ });
76
+ return deriveTuples(rowFactsOf(declaration.kind, row)).map(formatTuple);
77
+ }
78
+
79
+ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
80
+ it("a private agent: its organization link and its creator as owner, nothing else", () => {
81
+ expect(derivedFor("agent", {})).toEqual([
82
+ "agent:agent-1#organization@organization:acme",
83
+ "agent:agent-1#owner@identity_account:ida_carol",
84
+ ]);
85
+ });
86
+
87
+ it("an org-visible blueprint adds the organization's VIEWER userset (cloud#257's shape, not `#member`)", () => {
88
+ expect(
89
+ derivedFor("workflow", {
90
+ visibility: ApiResourceVisibility.visibility_org,
91
+ }),
92
+ ).toEqual([
93
+ "workflow:workflow-1#organization@organization:acme",
94
+ "workflow:workflow-1#owner@identity_account:ida_carol",
95
+ "workflow:workflow-1#viewer@organization:acme#viewer",
96
+ ]);
97
+ });
98
+
99
+ it("a public blueprint adds the conditional wildcard AND keeps the org floor", () => {
100
+ expect(
101
+ derivedFor("skill", {
102
+ visibility: ApiResourceVisibility.visibility_public,
103
+ }),
104
+ ).toEqual([
105
+ "skill:skill-1#organization@organization:acme",
106
+ "skill:skill-1#owner@identity_account:ida_carol",
107
+ "skill:skill-1#viewer@identity_account:* with allow_public",
108
+ "skill:skill-1#viewer@organization:acme#viewer",
109
+ ]);
110
+ });
111
+
112
+ it("an unspecified level derives no visibility tuple — a legacy row reads private in both editions", () => {
113
+ expect(
114
+ derivedFor("mcp_server", {
115
+ visibility: ApiResourceVisibility.api_resource_visibility_unspecified,
116
+ }),
117
+ ).toEqual([
118
+ "mcp_server:mcp_server-1#organization@organization:acme",
119
+ "mcp_server:mcp_server-1#owner@identity_account:ida_carol",
120
+ ]);
121
+ });
122
+
123
+ it("the organization derives NOTHING: no scope (OWNER_ONLY) and its owner is 2b's row, never its creator stamp", () => {
124
+ expect(derivedFor("organization", { org: "" })).toEqual([]);
125
+ });
126
+
127
+ it("a stamp that names no person is no owner: the empty stamp and the unconfigured laptop's placeholder", () => {
128
+ expect(derivedFor("agent", { createdBy: "" })).toEqual([
129
+ "agent:agent-1#organization@organization:acme",
130
+ ]);
131
+ expect(derivedFor("agent", { createdBy: "system" })).toEqual([
132
+ "agent:agent-1#organization@organization:acme",
133
+ ]);
134
+ });
135
+
136
+ it("a row naming no organization has no scope link and no org-viewer userset to point at", () => {
137
+ expect(
138
+ derivedFor("agent", {
139
+ org: "",
140
+ visibility: ApiResourceVisibility.visibility_org,
141
+ }),
142
+ ).toEqual(["agent:agent-1#owner@identity_account:ida_carol"]);
143
+ });
144
+
145
+ it("a run is its session's: the session link (PARENT scope) and NO owner of its own (INHERITED attribution)", () => {
146
+ expect(derivedFor("agent_execution", {})).toEqual([
147
+ "agent_execution:agent_execution-1#session@session:session-1",
148
+ ]);
149
+ });
150
+
151
+ it("an account owns itself (SELF attribution) and has no scope link", () => {
152
+ expect(derivedFor("identity_account", { org: "" })).toEqual([
153
+ "identity_account:identity_account-1#owner@identity_account:identity_account-1",
154
+ ]);
155
+ });
156
+
157
+ it("a memory's one principal is its subject, from the spec field; an EMPTY subject derives no principal at all", () => {
158
+ expect(derivedFor("memory", {})).toEqual([
159
+ "memory:memory-1#organization@organization:acme",
160
+ "memory:memory-1#subject@identity_account:identity_account-1",
161
+ ]);
162
+ // Open source stores "" today (no capture credential fills the field):
163
+ // such a row is nobody's under an enforcing evaluator — stated, not hidden.
164
+ expect(
165
+ derivedFor("memory", { spec: { subjectIdentityAccountId: "" } }),
166
+ ).toEqual(["memory:memory-1#organization@organization:acme"]);
167
+ });
168
+
169
+ it("an environment carries its creator tuple, an org-viewer at org level, and NO public wildcard (the kind's ceiling)", () => {
170
+ expect(
171
+ derivedFor("environment", {
172
+ visibility: ApiResourceVisibility.visibility_org,
173
+ }),
174
+ ).toEqual([
175
+ "environment:environment-1#organization@organization:acme",
176
+ "environment:environment-1#owner@identity_account:ida_carol",
177
+ "environment:environment-1#creator@identity_account:ida_carol",
178
+ "environment:environment-1#viewer@organization:acme#viewer",
179
+ ]);
180
+ expect(
181
+ derivedFor("environment", {
182
+ visibility: ApiResourceVisibility.visibility_public,
183
+ }),
184
+ ).toEqual([
185
+ "environment:environment-1#organization@organization:acme",
186
+ "environment:environment-1#owner@identity_account:ida_carol",
187
+ "environment:environment-1#creator@identity_account:ida_carol",
188
+ ]);
189
+ });
190
+
191
+ it("kinds with no visibility axis derive no viewer tuple at any level — their audience is the model's own line", () => {
192
+ for (const type of ["artifact", "schedule", "project", "session"]) {
193
+ expect(
194
+ derivedFor(type, {
195
+ visibility: ApiResourceVisibility.visibility_org,
196
+ }),
197
+ type,
198
+ ).toEqual([
199
+ `${type}:${type}-1#organization@organization:acme`,
200
+ `${type}:${type}-1#owner@identity_account:ida_carol`,
201
+ ]);
202
+ }
203
+ });
204
+
205
+ it("owner-only kinds carry no scope link whatever metadata.org says", () => {
206
+ expect(derivedFor("api_key", {})).toEqual([
207
+ "api_key:api_key-1#owner@identity_account:ida_carol",
208
+ ]);
209
+ expect(derivedFor("execution_context", {})).toEqual([
210
+ "execution_context:execution_context-1#owner@identity_account:ida_carol",
211
+ ]);
212
+ });
213
+
214
+ it("an instance carries its blueprint link and a run its instance link (additional parents); a user-created instance at org level adds the #viewer userset", () => {
215
+ expect(
216
+ derivedFor("agent_instance", {
217
+ visibility: ApiResourceVisibility.visibility_org,
218
+ }),
219
+ ).toEqual([
220
+ "agent_instance:agent_instance-1#organization@organization:acme",
221
+ "agent_instance:agent_instance-1#agent@agent:agent-1",
222
+ "agent_instance:agent_instance-1#owner@identity_account:ida_carol",
223
+ "agent_instance:agent_instance-1#viewer@organization:acme#viewer",
224
+ ]);
225
+ expect(
226
+ derivedFor("workflow_execution", {
227
+ visibility: ApiResourceVisibility.api_resource_visibility_unspecified,
228
+ }),
229
+ ).toEqual([
230
+ "workflow_execution:workflow_execution-1#organization@organization:acme",
231
+ "workflow_execution:workflow_execution-1#workflow_instance@workflow_instance:workflow_instance-1",
232
+ "workflow_execution:workflow_execution-1#owner@identity_account:ida_carol",
233
+ ]);
234
+ });
235
+ });
236
+
237
+ // ---------------------------------------------------------------------------
238
+ // The source over both drivers.
239
+ // ---------------------------------------------------------------------------
240
+
241
+ /** Every kind a driver arm below seeds — cleared before each test on the shared Postgres database. */
242
+ const SEEDED_KINDS: ReadonlyArray<ApiResourceKind> = [
243
+ ApiResourceKind.iam_policy,
244
+ ApiResourceKind.organization,
245
+ ApiResourceKind.agent,
246
+ ApiResourceKind.agent_instance,
247
+ ApiResourceKind.workflow_instance,
248
+ ApiResourceKind.workflow_execution,
249
+ ApiResourceKind.identity_account,
250
+ ];
251
+
252
+ afterAll(dropPostgresFixture);
253
+
254
+ const ROOT: Person = { accountId: "ida_root", aliases: new Set(["ida_root"]) };
255
+ const DAVE: Person = { accountId: "ida_dave", aliases: new Set(["ida_dave"]) };
256
+
257
+ async function grant(
258
+ policies: IamPolicyStore,
259
+ spec: ReturnType<typeof orgRole>,
260
+ ): Promise<void> {
261
+ await policies.save(
262
+ create(IamPolicySchema, {
263
+ apiVersion: IAM_POLICY_API_VERSION,
264
+ kind: IAM_POLICY_KIND,
265
+ metadata: { id: policyIdFor(spec) },
266
+ spec,
267
+ }),
268
+ );
269
+ }
270
+
271
+ /** Wraps the port so the test can count the one read the source is allowed. */
272
+ function countingPolicies(inner: IamPolicyStore): {
273
+ readonly policies: IamPolicyStore;
274
+ reads(): number;
275
+ } {
276
+ let reads = 0;
277
+ return {
278
+ policies: {
279
+ ...inner,
280
+ findByPrincipal(principalKind, principalId) {
281
+ reads += 1;
282
+ return inner.findByPrincipal(principalKind, principalId);
283
+ },
284
+ },
285
+ reads: () => reads,
286
+ };
287
+ }
288
+
289
+ describe.each(driverFixtures(SEEDED_KINDS))(
290
+ "the derived tuple source on $name",
291
+ (fixture) => {
292
+ describe.skipIf(fixture.skip)("rows and derived tuples", () => {
293
+ let opened: OpenedStore;
294
+ let counted: ReturnType<typeof countingPolicies>;
295
+ let accounts: IdentityAccountStore;
296
+
297
+ beforeEach(async () => {
298
+ opened = await fixture.open();
299
+ counted = countingPolicies(newResourceIamPolicyStore(opened.store));
300
+ accounts = newResourceIdentityAccountStore(opened.store);
301
+ const organization = declared("organization");
302
+ await opened.store.saveResource(
303
+ ApiResourceKind.organization,
304
+ "acme",
305
+ organization.schema,
306
+ fixtureRow(organization, {
307
+ id: "acme",
308
+ org: "",
309
+ visibility: ApiResourceVisibility.visibility_private,
310
+ createdBy: ROOT.accountId,
311
+ }),
312
+ );
313
+ const agent = declared("agent");
314
+ await opened.store.saveResource(
315
+ ApiResourceKind.agent,
316
+ "agt_team",
317
+ agent.schema,
318
+ fixtureRow(agent, {
319
+ id: "agt_team",
320
+ org: "acme",
321
+ visibility: ApiResourceVisibility.visibility_org,
322
+ createdBy: "ida_carol",
323
+ }),
324
+ );
325
+ await grant(counted.policies, orgRole(ROOT.accountId, "owner", "acme"));
326
+ await grant(
327
+ counted.policies,
328
+ orgRole(DAVE.accountId, "member", "acme"),
329
+ );
330
+ // A structural row (the cloud's `bootstrapPolicy` shape): a
331
+ // userset principal, carried as a userset subject.
332
+ await grant(
333
+ counted.policies,
334
+ triple(
335
+ { kind: "organization", id: "partner", relation: "member" },
336
+ "viewer",
337
+ { kind: "organization", id: "acme" },
338
+ ),
339
+ );
340
+ });
341
+
342
+ afterEach(async () => {
343
+ await opened.close();
344
+ });
345
+
346
+ function sourceFor(person: Person) {
347
+ return newDerivedTupleSource(
348
+ { store: opened.store, policies: counted.policies, accounts },
349
+ person,
350
+ );
351
+ }
352
+
353
+ it("an identity_account object is read through the account PORT, so a person owns their own row wherever accounts live", async () => {
354
+ // A port that is NOT the generic store: the row lives in memory
355
+ // only, so a read around the port would miss it. The source must
356
+ // read it through the port.
357
+ const detached = fakeIdentityAccountStore();
358
+ detached.rows.set(
359
+ ROOT.accountId,
360
+ create(IdentityAccountSchema, {
361
+ metadata: { id: ROOT.accountId, name: "auth0|root" },
362
+ spec: {
363
+ idpId: "auth0|root",
364
+ provisioningMode: IdentityAccountProvisioningMode.direct,
365
+ },
366
+ }),
367
+ );
368
+ const source = newDerivedTupleSource(
369
+ {
370
+ store: opened.store,
371
+ policies: counted.policies,
372
+ accounts: detached,
373
+ },
374
+ ROOT,
375
+ );
376
+ const self = parseObjectRef(`identity_account:${ROOT.accountId}`);
377
+ expect((await source.tuplesOf(self, "owner")).map(formatTuple)).toEqual(
378
+ [`identity_account:ida_root#owner@identity_account:ida_root`],
379
+ );
380
+ expect(
381
+ await source.tuplesOf(
382
+ parseObjectRef("identity_account:ida_ghost"),
383
+ "owner",
384
+ ),
385
+ ).toEqual([]);
386
+ });
387
+
388
+ it("answers the person's own rows on the organization, and nobody else's", async () => {
389
+ const source = sourceFor(ROOT);
390
+ expect(
391
+ (
392
+ await source.tuplesOf(parseObjectRef("organization:acme"), "owner")
393
+ ).map(formatTuple),
394
+ ).toEqual(["organization:acme#owner@identity_account:ida_root"]);
395
+ expect(
396
+ await source.tuplesOf(parseObjectRef("organization:acme"), "member"),
397
+ ).toEqual([]);
398
+ expect(
399
+ (
400
+ await sourceFor(DAVE).tuplesOf(
401
+ parseObjectRef("organization:acme"),
402
+ "member",
403
+ )
404
+ ).map(formatTuple),
405
+ ).toEqual(["organization:acme#member@identity_account:ida_dave"]);
406
+ });
407
+
408
+ it("reads the person's rows ONCE, however many objects and relations are asked", async () => {
409
+ const source = sourceFor(ROOT);
410
+ await source.tuplesOf(parseObjectRef("organization:acme"), "owner");
411
+ await source.tuplesOf(parseObjectRef("organization:acme"), "admin");
412
+ await source.tuplesOf(parseObjectRef("organization:other"), "owner");
413
+ await source.tuplesOf(parseObjectRef("agent:agt_team"), "owner");
414
+ expect(counted.reads()).toBe(1);
415
+ });
416
+
417
+ it("derives a stored row's tuples and unions them with rows, per relation", async () => {
418
+ const source = sourceFor(DAVE);
419
+ const agent = parseObjectRef("agent:agt_team");
420
+ expect(
421
+ (await source.tuplesOf(agent, "organization")).map(formatTuple),
422
+ ).toEqual(["agent:agt_team#organization@organization:acme"]);
423
+ expect(
424
+ (await source.tuplesOf(agent, "owner")).map(formatTuple),
425
+ ).toEqual(["agent:agt_team#owner@identity_account:ida_carol"]);
426
+ expect(
427
+ (await source.tuplesOf(agent, "viewer")).map(formatTuple),
428
+ ).toEqual(["agent:agt_team#viewer@organization:acme#viewer"]);
429
+ expect(await source.tuplesOf(agent, "can_view")).toEqual([]);
430
+ });
431
+
432
+ it("rows naming another principal never enter a person's source — the structural `organization:partner#member` row is nobody's here", async () => {
433
+ const source = sourceFor(ROOT);
434
+ expect(
435
+ await source.tuplesOf(parseObjectRef("organization:acme"), "viewer"),
436
+ ).toEqual([]);
437
+ });
438
+
439
+ it("an absent object, or an object of a kind this edition does not declare, answers no tuples", async () => {
440
+ const source = sourceFor(ROOT);
441
+ expect(
442
+ await source.tuplesOf(parseObjectRef("agent:agt_missing"), "owner"),
443
+ ).toEqual([]);
444
+ expect(
445
+ await source.tuplesOf(
446
+ parseObjectRef("identity_provider:idp"),
447
+ "owner",
448
+ ),
449
+ ).toEqual([]);
450
+ expect(
451
+ await source.tuplesOf(parseObjectRef("nonsense:x"), "owner"),
452
+ ).toEqual([]);
453
+ });
454
+
455
+ it("loads a row once and serves every relation from it — the loader hands back the same decoded row", async () => {
456
+ const source = sourceFor(ROOT);
457
+ const agent = parseObjectRef("agent:agt_team");
458
+ await source.tuplesOf(agent, "organization");
459
+ const first = await source.loader.load(agent);
460
+ await source.tuplesOf(agent, "owner");
461
+ const second = await source.loader.load(agent);
462
+ expect(first).toBeDefined();
463
+ expect(second).toBe(first);
464
+ });
465
+
466
+ it("a source seeded with a candidate's facts derives that object's tuples WITHOUT loading its row; the parent hop still loads", async () => {
467
+ let rowReads = 0;
468
+ const agent = declared("agent");
469
+ const seeded = newDerivedTupleSource(
470
+ {
471
+ store: {
472
+ ...opened.store,
473
+ getResource(kind, id, schema) {
474
+ rowReads += 1;
475
+ return opened.store.getResource(kind, id, schema);
476
+ },
477
+ },
478
+ policies: counted.policies,
479
+ accounts,
480
+ },
481
+ DAVE,
482
+ {
483
+ facts: [
484
+ rowFactsOf(
485
+ agent.kind,
486
+ fixtureRow(agent, {
487
+ id: "agt_team",
488
+ org: "acme",
489
+ visibility: ApiResourceVisibility.visibility_org,
490
+ createdBy: "ida_carol",
491
+ }),
492
+ ),
493
+ ],
494
+ },
495
+ );
496
+ const object = parseObjectRef("agent:agt_team");
497
+ expect(
498
+ (await seeded.tuplesOf(object, "viewer")).map(formatTuple),
499
+ ).toEqual(["agent:agt_team#viewer@organization:acme#viewer"]);
500
+ expect(
501
+ (await seeded.tuplesOf(object, "owner")).map(formatTuple),
502
+ ).toEqual(["agent:agt_team#owner@identity_account:ida_carol"]);
503
+ expect(rowReads, "the seeded object's row is never read").toBe(0);
504
+ // The member reads the org-visible agent through the organization,
505
+ // whose row the walk loads — the one read a seeded check makes.
506
+ expect(
507
+ await checkRelation(
508
+ { model: builtInModel, source: seeded },
509
+ object,
510
+ "can_view",
511
+ DAVE,
512
+ {
513
+ allow: false,
514
+ },
515
+ ),
516
+ ).toBe(true);
517
+ expect(rowReads).toBe(1);
518
+ });
519
+
520
+ it("a seeded fact stands in for the row only where the row would have been read for FACTS: a `derived` rule still reads the row it needs", async () => {
521
+ // A seeded instance: `default_of` reads the instance's blueprint
522
+ // pointer from the row's spec, which a candidate's facts do not
523
+ // carry, so the rule loads the row — one read, stated in the list
524
+ // scope's cost pin as well.
525
+ let rowReads = 0;
526
+ const instance = declared("agent_instance");
527
+ const row = fixtureRow(instance, {
528
+ id: "ai_seeded",
529
+ org: "acme",
530
+ visibility: ApiResourceVisibility.visibility_private,
531
+ createdBy: "ida_carol",
532
+ spec: { agentId: "agt_team" },
533
+ });
534
+ await opened.store.saveResource(
535
+ instance.kind,
536
+ "ai_seeded",
537
+ instance.schema,
538
+ row,
539
+ );
540
+ const seeded = newDerivedTupleSource(
541
+ {
542
+ store: {
543
+ ...opened.store,
544
+ getResource(kind, id, schema) {
545
+ rowReads += 1;
546
+ return opened.store.getResource(kind, id, schema);
547
+ },
548
+ },
549
+ policies: counted.policies,
550
+ accounts,
551
+ },
552
+ DAVE,
553
+ { facts: [rowFactsOf(instance.kind, row)] },
554
+ );
555
+ const object = parseObjectRef("agent_instance:ai_seeded");
556
+ await seeded.tuplesOf(object, "owner");
557
+ expect(rowReads, "facts alone serve the derived tuples").toBe(0);
558
+ await seeded.tuplesOf(object, "default_of");
559
+ expect(rowReads, "the rule reads the instance and the blueprint").toBe(
560
+ 2,
561
+ );
562
+ });
563
+
564
+ it("a store fault propagates as the fault it is — never as 'no tuples'", async () => {
565
+ const source = sourceFor(ROOT);
566
+ await opened.store.close();
567
+ await expect(
568
+ source.tuplesOf(parseObjectRef("agent:agt_team"), "owner"),
569
+ ).rejects.toThrow();
570
+ await expect(
571
+ source.tuplesOf(parseObjectRef("organization:acme"), "owner"),
572
+ ).rejects.toThrow();
573
+ });
574
+ });
575
+
576
+ /**
577
+ * The two derived rules through the real source and the evaluator:
578
+ * `default_of` from the blueprint's pointer, `execution_viewer` from
579
+ * the instance's run-observability level. Seeded: `agt_team` (org-
580
+ * visible, its pointer at `ai_default`), `ai_default` (no level of its
581
+ * own) and `ai_personal` (private) both naming it; `agt_other` whose
582
+ * pointer names a row that is not `ai_stale`; `ai_orphan` naming a
583
+ * blueprint that does not exist; `wi_shared` (organization level) and
584
+ * `wi_private`, each with one run of Carol's.
585
+ */
586
+ describe.skipIf(fixture.skip)("the derived rules", () => {
587
+ let opened: OpenedStore;
588
+ const CAROL: Person = {
589
+ accountId: "ida_carol",
590
+ aliases: new Set(["ida_carol"]),
591
+ };
592
+
593
+ async function seed(
594
+ type: string,
595
+ id: string,
596
+ facts: Omit<Parameters<typeof fixtureRow>[1], "id">,
597
+ ): Promise<void> {
598
+ const declaration = declared(type);
599
+ await opened.store.saveResource(
600
+ declaration.kind,
601
+ id,
602
+ declaration.schema,
603
+ fixtureRow(declaration, { id, ...facts }),
604
+ );
605
+ }
606
+
607
+ beforeEach(async () => {
608
+ opened = await fixture.open();
609
+ const policies = newResourceIamPolicyStore(opened.store);
610
+ await grant(policies, orgRole(ROOT.accountId, "owner", "acme"));
611
+ await grant(policies, orgRole(DAVE.accountId, "member", "acme"));
612
+ await seed("organization", "acme", {
613
+ org: "",
614
+ visibility: ApiResourceVisibility.visibility_private,
615
+ createdBy: ROOT.accountId,
616
+ });
617
+ await seed("agent", "agt_team", {
618
+ org: "acme",
619
+ visibility: ApiResourceVisibility.visibility_org,
620
+ createdBy: CAROL.accountId,
621
+ status: { defaultInstanceId: "ai_default" },
622
+ });
623
+ await seed("agent", "agt_other", {
624
+ org: "acme",
625
+ visibility: ApiResourceVisibility.visibility_org,
626
+ createdBy: CAROL.accountId,
627
+ status: { defaultInstanceId: "ai_elsewhere" },
628
+ });
629
+ for (const [id, agentId, visibility] of [
630
+ [
631
+ "ai_default",
632
+ "agt_team",
633
+ ApiResourceVisibility.api_resource_visibility_unspecified,
634
+ ],
635
+ ["ai_personal", "agt_team", ApiResourceVisibility.visibility_private],
636
+ ["ai_stale", "agt_other", ApiResourceVisibility.visibility_private],
637
+ [
638
+ "ai_orphan",
639
+ "agt_missing",
640
+ ApiResourceVisibility.visibility_private,
641
+ ],
642
+ ] as const) {
643
+ await seed("agent_instance", id, {
644
+ org: "acme",
645
+ visibility,
646
+ createdBy: CAROL.accountId,
647
+ spec: { agentId },
648
+ });
649
+ }
650
+ for (const [id, executionVisibility] of [
651
+ ["wi_shared", WorkflowExecutionVisibility.organization],
652
+ ["wi_private", WorkflowExecutionVisibility.private],
653
+ ] as const) {
654
+ await seed("workflow_instance", id, {
655
+ org: "acme",
656
+ visibility: ApiResourceVisibility.visibility_private,
657
+ createdBy: CAROL.accountId,
658
+ spec: { executionVisibility },
659
+ });
660
+ }
661
+ for (const [id, workflowInstanceId] of [
662
+ ["we_shared", "wi_shared"],
663
+ ["we_private", "wi_private"],
664
+ ] as const) {
665
+ await seed("workflow_execution", id, {
666
+ org: "acme",
667
+ visibility:
668
+ ApiResourceVisibility.api_resource_visibility_unspecified,
669
+ createdBy: CAROL.accountId,
670
+ spec: { workflowInstanceId },
671
+ });
672
+ }
673
+ });
674
+
675
+ afterEach(async () => {
676
+ await opened.close();
677
+ });
678
+
679
+ function sourceFor(person: Person) {
680
+ return newDerivedTupleSource(
681
+ {
682
+ store: opened.store,
683
+ policies: newResourceIamPolicyStore(opened.store),
684
+ accounts: newResourceIdentityAccountStore(opened.store),
685
+ },
686
+ person,
687
+ );
688
+ }
689
+
690
+ async function tuplesOf(
691
+ person: Person,
692
+ object: string,
693
+ relation: string,
694
+ ): Promise<string[]> {
695
+ return (
696
+ await sourceFor(person).tuplesOf(parseObjectRef(object), relation)
697
+ ).map(formatTuple);
698
+ }
699
+
700
+ async function allowed(
701
+ person: Person,
702
+ object: string,
703
+ relation: string,
704
+ ): Promise<boolean> {
705
+ return checkRelation(
706
+ { model: builtInModel, source: sourceFor(person) },
707
+ parseObjectRef(object),
708
+ relation,
709
+ person,
710
+ { allow: true },
711
+ );
712
+ }
713
+
714
+ it("default_of derives iff the blueprint's pointer names the instance: the default has it, a personal, a stale and an orphaned instance do not", async () => {
715
+ expect(
716
+ await tuplesOf(DAVE, "agent_instance:ai_default", "default_of"),
717
+ ).toEqual(["agent_instance:ai_default#default_of@agent:agt_team"]);
718
+ for (const instance of ["ai_personal", "ai_stale", "ai_orphan"]) {
719
+ expect(
720
+ await tuplesOf(DAVE, `agent_instance:${instance}`, "default_of"),
721
+ instance,
722
+ ).toEqual([]);
723
+ }
724
+ });
725
+
726
+ it("the rule's blueprint read is the loader's: `viewer from default_of` then resolves the blueprint on the same decoded row", async () => {
727
+ const source = sourceFor(DAVE);
728
+ await source.tuplesOf(
729
+ parseObjectRef("agent_instance:ai_default"),
730
+ "default_of",
731
+ );
732
+ const viaRule = await source.loader.load(
733
+ parseObjectRef("agent:agt_team"),
734
+ );
735
+ await source.tuplesOf(parseObjectRef("agent:agt_team"), "viewer");
736
+ const viaWalk = await source.loader.load(
737
+ parseObjectRef("agent:agt_team"),
738
+ );
739
+ expect(viaRule).toBeDefined();
740
+ expect(viaWalk).toBe(viaRule);
741
+ });
742
+
743
+ it("an organization member reads the default instance of an org-visible agent through the blueprint, and NOT a personal instance of the same agent — nor does the organization's owner", async () => {
744
+ expect(
745
+ await allowed(DAVE, "agent_instance:ai_default", "can_view"),
746
+ ).toBe(true);
747
+ expect(
748
+ await allowed(DAVE, "agent_instance:ai_default", "can_execute"),
749
+ ).toBe(true);
750
+ expect(
751
+ await allowed(DAVE, "agent_instance:ai_personal", "can_view"),
752
+ ).toBe(false);
753
+ expect(
754
+ await allowed(ROOT, "agent_instance:ai_personal", "can_view"),
755
+ ).toBe(false);
756
+ expect(
757
+ await allowed(CAROL, "agent_instance:ai_personal", "can_view"),
758
+ ).toBe(true);
759
+ expect(
760
+ await allowed(DAVE, "agent_instance:ai_default", "can_edit"),
761
+ ).toBe(false);
762
+ });
763
+
764
+ it("execution_viewer derives the organization's #viewer userset at the organization level and nothing at private", async () => {
765
+ expect(
766
+ await tuplesOf(
767
+ DAVE,
768
+ "workflow_instance:wi_shared",
769
+ "execution_viewer",
770
+ ),
771
+ ).toEqual([
772
+ "workflow_instance:wi_shared#execution_viewer@organization:acme#viewer",
773
+ ]);
774
+ expect(
775
+ await tuplesOf(
776
+ DAVE,
777
+ "workflow_instance:wi_private",
778
+ "execution_viewer",
779
+ ),
780
+ ).toEqual([]);
781
+ });
782
+
783
+ it("an organization member reads a run whose instance is org-observable and not one whose instance is private; the triggerer reads both", async () => {
784
+ expect(
785
+ await allowed(DAVE, "workflow_execution:we_shared", "can_view"),
786
+ ).toBe(true);
787
+ expect(
788
+ await allowed(DAVE, "workflow_execution:we_private", "can_view"),
789
+ ).toBe(false);
790
+ expect(
791
+ await allowed(CAROL, "workflow_execution:we_shared", "can_view"),
792
+ ).toBe(true);
793
+ expect(
794
+ await allowed(CAROL, "workflow_execution:we_private", "can_view"),
795
+ ).toBe(true);
796
+ expect(
797
+ await allowed(DAVE, "workflow_execution:we_shared", "can_edit"),
798
+ ).toBe(false);
799
+ });
800
+ });
801
+ },
802
+ );