@stigmer/server 3.22.1-dev.20260922095755 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/dist/artifactstorage/artifact-storage.d.ts +29 -31
  2. package/dist/artifactstorage/artifact-storage.d.ts.map +1 -1
  3. package/dist/artifactstorage/artifact-storage.js +5 -7
  4. package/dist/artifactstorage/artifact-storage.js.map +1 -1
  5. package/dist/artifactstorage/r2-storage.d.ts +12 -7
  6. package/dist/artifactstorage/r2-storage.d.ts.map +1 -1
  7. package/dist/artifactstorage/r2-storage.js +6 -14
  8. package/dist/artifactstorage/r2-storage.js.map +1 -1
  9. package/dist/authorization/authorizer.d.ts +8 -4
  10. package/dist/authorization/authorizer.d.ts.map +1 -1
  11. package/dist/authorization/authorizer.js +9 -5
  12. package/dist/authorization/authorizer.js.map +1 -1
  13. package/dist/authorization/derived-tuples.d.ts.map +1 -1
  14. package/dist/authorization/derived-tuples.js +25 -10
  15. package/dist/authorization/derived-tuples.js.map +1 -1
  16. package/dist/authorization/evaluator.d.ts +8 -7
  17. package/dist/authorization/evaluator.d.ts.map +1 -1
  18. package/dist/authorization/evaluator.js +20 -4
  19. package/dist/authorization/evaluator.js.map +1 -1
  20. package/dist/authorization/list-read-scope.d.ts.map +1 -1
  21. package/dist/authorization/list-read-scope.js +9 -5
  22. package/dist/authorization/list-read-scope.js.map +1 -1
  23. package/dist/authorization/model/agent.d.ts.map +1 -1
  24. package/dist/authorization/model/agent.js +5 -4
  25. package/dist/authorization/model/agent.js.map +1 -1
  26. package/dist/authorization/model/agent_instance.d.ts.map +1 -1
  27. package/dist/authorization/model/agent_instance.js +2 -2
  28. package/dist/authorization/model/agent_instance.js.map +1 -1
  29. package/dist/authorization/model/mcp_server.d.ts.map +1 -1
  30. package/dist/authorization/model/mcp_server.js +2 -2
  31. package/dist/authorization/model/mcp_server.js.map +1 -1
  32. package/dist/authorization/model/plugin.d.ts.map +1 -1
  33. package/dist/authorization/model/plugin.js +4 -3
  34. package/dist/authorization/model/plugin.js.map +1 -1
  35. package/dist/authorization/model/rewrite.d.ts +10 -8
  36. package/dist/authorization/model/rewrite.d.ts.map +1 -1
  37. package/dist/authorization/model/rewrite.js +3 -0
  38. package/dist/authorization/model/rewrite.js.map +1 -1
  39. package/dist/authorization/model/skill.d.ts.map +1 -1
  40. package/dist/authorization/model/skill.js +2 -2
  41. package/dist/authorization/model/skill.js.map +1 -1
  42. package/dist/authorization/model/workflow.d.ts.map +1 -1
  43. package/dist/authorization/model/workflow.js +2 -2
  44. package/dist/authorization/model/workflow.js.map +1 -1
  45. package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
  46. package/dist/authorization/model/workflow_instance.js +2 -2
  47. package/dist/authorization/model/workflow_instance.js.map +1 -1
  48. package/dist/authorization/organization-directory.d.ts.map +1 -1
  49. package/dist/authorization/organization-directory.js +3 -2
  50. package/dist/authorization/organization-directory.js.map +1 -1
  51. package/dist/authorization/store-test-kit.d.ts +6 -0
  52. package/dist/authorization/store-test-kit.d.ts.map +1 -1
  53. package/dist/authorization/store-test-kit.js +62 -16
  54. package/dist/authorization/store-test-kit.js.map +1 -1
  55. package/dist/authorization/tuples.d.ts +32 -13
  56. package/dist/authorization/tuples.d.ts.map +1 -1
  57. package/dist/authorization/tuples.js +11 -3
  58. package/dist/authorization/tuples.js.map +1 -1
  59. package/dist/boot/compose.d.ts.map +1 -1
  60. package/dist/boot/compose.js +49 -24
  61. package/dist/boot/compose.js.map +1 -1
  62. package/dist/boot/config.d.ts +4 -3
  63. package/dist/boot/config.d.ts.map +1 -1
  64. package/dist/boot/config.js.map +1 -1
  65. package/dist/boot/skill-transfer-origin.d.ts +52 -0
  66. package/dist/boot/skill-transfer-origin.d.ts.map +1 -0
  67. package/dist/boot/skill-transfer-origin.js +54 -0
  68. package/dist/boot/skill-transfer-origin.js.map +1 -0
  69. package/dist/domain/agent/controller.d.ts.map +1 -1
  70. package/dist/domain/agent/controller.js +4 -4
  71. package/dist/domain/agent/controller.js.map +1 -1
  72. package/dist/domain/agentchannel/controller.d.ts.map +1 -1
  73. package/dist/domain/agentchannel/controller.js +1 -3
  74. package/dist/domain/agentchannel/controller.js.map +1 -1
  75. package/dist/domain/agentexecution/controller.d.ts.map +1 -1
  76. package/dist/domain/agentexecution/controller.js +1 -3
  77. package/dist/domain/agentexecution/controller.js.map +1 -1
  78. package/dist/domain/agentinstance/controller.d.ts.map +1 -1
  79. package/dist/domain/agentinstance/controller.js +4 -3
  80. package/dist/domain/agentinstance/controller.js.map +1 -1
  81. package/dist/domain/agentshare/constants.d.ts +11 -6
  82. package/dist/domain/agentshare/constants.d.ts.map +1 -1
  83. package/dist/domain/agentshare/constants.js +16 -8
  84. package/dist/domain/agentshare/constants.js.map +1 -1
  85. package/dist/domain/agentshare/controller.d.ts.map +1 -1
  86. package/dist/domain/agentshare/controller.js +1 -3
  87. package/dist/domain/agentshare/controller.js.map +1 -1
  88. package/dist/domain/agentshare/steps.d.ts +25 -18
  89. package/dist/domain/agentshare/steps.d.ts.map +1 -1
  90. package/dist/domain/agentshare/steps.js +142 -41
  91. package/dist/domain/agentshare/steps.js.map +1 -1
  92. package/dist/domain/environment/controller.d.ts.map +1 -1
  93. package/dist/domain/environment/controller.js +3 -2
  94. package/dist/domain/environment/controller.js.map +1 -1
  95. package/dist/domain/executioncontext/controller.d.ts.map +1 -1
  96. package/dist/domain/executioncontext/controller.js +1 -2
  97. package/dist/domain/executioncontext/controller.js.map +1 -1
  98. package/dist/domain/mcpserver/controller.d.ts.map +1 -1
  99. package/dist/domain/mcpserver/controller.js +4 -3
  100. package/dist/domain/mcpserver/controller.js.map +1 -1
  101. package/dist/domain/plugin/controller.d.ts +3 -7
  102. package/dist/domain/plugin/controller.d.ts.map +1 -1
  103. package/dist/domain/plugin/controller.js +11 -9
  104. package/dist/domain/plugin/controller.js.map +1 -1
  105. package/dist/domain/plugin/push.d.ts +5 -7
  106. package/dist/domain/plugin/push.d.ts.map +1 -1
  107. package/dist/domain/plugin/push.js +14 -8
  108. package/dist/domain/plugin/push.js.map +1 -1
  109. package/dist/domain/schedule/controller.d.ts.map +1 -1
  110. package/dist/domain/schedule/controller.js +1 -3
  111. package/dist/domain/schedule/controller.js.map +1 -1
  112. package/dist/domain/session/controller.d.ts.map +1 -1
  113. package/dist/domain/session/controller.js +2 -3
  114. package/dist/domain/session/controller.js.map +1 -1
  115. package/dist/domain/skill/constants.d.ts +26 -3
  116. package/dist/domain/skill/constants.d.ts.map +1 -1
  117. package/dist/domain/skill/constants.js +26 -3
  118. package/dist/domain/skill/constants.js.map +1 -1
  119. package/dist/domain/skill/controller.d.ts +6 -11
  120. package/dist/domain/skill/controller.d.ts.map +1 -1
  121. package/dist/domain/skill/controller.js +35 -22
  122. package/dist/domain/skill/controller.js.map +1 -1
  123. package/dist/domain/skill/push.d.ts +2 -2
  124. package/dist/domain/skill/push.d.ts.map +1 -1
  125. package/dist/domain/skill/push.js +2 -2
  126. package/dist/domain/skill/push.js.map +1 -1
  127. package/dist/domain/skill/transfer/handler.d.ts +17 -9
  128. package/dist/domain/skill/transfer/handler.d.ts.map +1 -1
  129. package/dist/domain/skill/transfer/handler.js +19 -8
  130. package/dist/domain/skill/transfer/handler.js.map +1 -1
  131. package/dist/domain/skill/transfer/slots.d.ts +26 -41
  132. package/dist/domain/skill/transfer/slots.d.ts.map +1 -1
  133. package/dist/domain/skill/transfer/slots.js +80 -87
  134. package/dist/domain/skill/transfer/slots.js.map +1 -1
  135. package/dist/domain/skill/transfer/staging.d.ts +48 -0
  136. package/dist/domain/skill/transfer/staging.d.ts.map +1 -0
  137. package/dist/domain/skill/transfer/staging.js +127 -0
  138. package/dist/domain/skill/transfer/staging.js.map +1 -0
  139. package/dist/domain/workflow/controller.d.ts.map +1 -1
  140. package/dist/domain/workflow/controller.js +6 -14
  141. package/dist/domain/workflow/controller.js.map +1 -1
  142. package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
  143. package/dist/domain/workflow/validation/task-config-constraints.d.ts +1 -10
  144. package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
  145. package/dist/domain/workflow/validation/task-config-constraints.js +2 -3
  146. package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
  147. package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
  148. package/dist/domain/workflowexecution/controller.js +2 -4
  149. package/dist/domain/workflowexecution/controller.js.map +1 -1
  150. package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
  151. package/dist/domain/workflowinstance/controller.js +4 -3
  152. package/dist/domain/workflowinstance/controller.js.map +1 -1
  153. package/dist/extensions/authorization-queries.d.ts +5 -6
  154. package/dist/extensions/authorization-queries.d.ts.map +1 -1
  155. package/dist/extensions/list-read-scope.d.ts +1 -1
  156. package/dist/extensions/resource-authorization.d.ts +2 -3
  157. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  158. package/dist/index.d.ts +3 -1
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js +13 -0
  161. package/dist/index.js.map +1 -1
  162. package/dist/pipeline/apiresource-meta.d.ts +3 -12
  163. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  164. package/dist/pipeline/apiresource-meta.js +10 -21
  165. package/dist/pipeline/apiresource-meta.js.map +1 -1
  166. package/dist/pipeline/steps/authorization-tuples.d.ts +3 -9
  167. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  168. package/dist/pipeline/steps/authorization-tuples.js +11 -9
  169. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  170. package/dist/pipeline/steps/references.d.ts +20 -178
  171. package/dist/pipeline/steps/references.d.ts.map +1 -1
  172. package/dist/pipeline/steps/references.js +43 -344
  173. package/dist/pipeline/steps/references.js.map +1 -1
  174. package/dist/pipeline/steps/resolve-artifact-source.d.ts +11 -8
  175. package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -1
  176. package/dist/pipeline/steps/resolve-artifact-source.js +8 -4
  177. package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -1
  178. package/dist/pipeline/steps/visibility-gates.d.ts +27 -0
  179. package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -0
  180. package/dist/pipeline/steps/visibility-gates.js +139 -0
  181. package/dist/pipeline/steps/visibility-gates.js.map +1 -0
  182. package/dist/query/search/controller.js +1 -0
  183. package/dist/query/search/controller.js.map +1 -1
  184. package/dist/query/search/criteria.d.ts +5 -1
  185. package/dist/query/search/criteria.d.ts.map +1 -1
  186. package/dist/query/search/criteria.js +13 -3
  187. package/dist/query/search/criteria.js.map +1 -1
  188. package/dist/query/search/handler.d.ts +4 -5
  189. package/dist/query/search/handler.d.ts.map +1 -1
  190. package/dist/query/search/handler.js +6 -7
  191. package/dist/query/search/handler.js.map +1 -1
  192. package/dist/query/search/query-store.d.ts.map +1 -1
  193. package/dist/query/search/query-store.js +2 -0
  194. package/dist/query/search/query-store.js.map +1 -1
  195. package/dist/store/interface.d.ts +6 -3
  196. package/dist/store/interface.d.ts.map +1 -1
  197. package/dist/store/interface.js.map +1 -1
  198. package/dist/store/postgres/migrations.d.ts +1 -3
  199. package/dist/store/postgres/migrations.d.ts.map +1 -1
  200. package/dist/store/postgres/migrations.js +1 -35
  201. package/dist/store/postgres/migrations.js.map +1 -1
  202. package/dist/store/postgres/store.d.ts.map +1 -1
  203. package/dist/store/postgres/store.js +9 -4
  204. package/dist/store/postgres/store.js.map +1 -1
  205. package/dist/store/sqlite/migrations.d.ts +1 -3
  206. package/dist/store/sqlite/migrations.d.ts.map +1 -1
  207. package/dist/store/sqlite/migrations.js +1 -36
  208. package/dist/store/sqlite/migrations.js.map +1 -1
  209. package/dist/store/sqlite/store.d.ts.map +1 -1
  210. package/dist/store/sqlite/store.js +8 -4
  211. package/dist/store/sqlite/store.js.map +1 -1
  212. package/package.json +6 -6
  213. package/src/artifactstorage/__tests__/artifact-storage.test.ts +36 -33
  214. package/src/artifactstorage/__tests__/r2-storage.test.ts +11 -13
  215. package/src/artifactstorage/artifact-storage.ts +37 -33
  216. package/src/artifactstorage/r2-storage.ts +6 -15
  217. package/src/authorization/README.md +26 -24
  218. package/src/authorization/__tests__/authorizer.test.ts +9 -10
  219. package/src/authorization/__tests__/derived-tuples.test.ts +11 -4
  220. package/src/authorization/__tests__/evaluator.test.ts +73 -14
  221. package/src/authorization/__tests__/facts.test.ts +2 -2
  222. package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +185 -0
  223. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +98 -6
  224. package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
  225. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +61 -4
  226. package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +143 -0
  227. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +21 -1
  228. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +25 -1
  229. package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
  230. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +3 -1
  231. package/src/authorization/__tests__/list-read-scope.test.ts +17 -18
  232. package/src/authorization/__tests__/store-tests.test.ts +8 -1
  233. package/src/authorization/__tests__/tuples.test.ts +11 -12
  234. package/src/authorization/authorizer.ts +9 -4
  235. package/src/authorization/derived-tuples.ts +31 -14
  236. package/src/authorization/evaluator.ts +44 -8
  237. package/src/authorization/list-read-scope.ts +11 -5
  238. package/src/authorization/model/agent.ts +5 -2
  239. package/src/authorization/model/agent_instance.ts +2 -0
  240. package/src/authorization/model/mcp_server.ts +2 -0
  241. package/src/authorization/model/plugin.ts +4 -1
  242. package/src/authorization/model/rewrite.ts +13 -8
  243. package/src/authorization/model/skill.ts +2 -0
  244. package/src/authorization/model/workflow.ts +2 -0
  245. package/src/authorization/model/workflow_instance.ts +2 -0
  246. package/src/authorization/organization-directory.ts +3 -1
  247. package/src/authorization/store-test-kit.ts +75 -16
  248. package/src/authorization/tuples.ts +39 -16
  249. package/src/boot/__tests__/skill-transfer-origin.test.ts +72 -0
  250. package/src/boot/compose.ts +62 -25
  251. package/src/boot/config.ts +4 -3
  252. package/src/boot/skill-transfer-origin.ts +76 -0
  253. package/src/domain/agent/__tests__/agent.test.ts +4 -11
  254. package/src/domain/agent/controller.ts +7 -7
  255. package/src/domain/agentchannel/__tests__/agentchannel.test.ts +48 -223
  256. package/src/domain/agentchannel/controller.ts +1 -6
  257. package/src/domain/agentexecution/controller.ts +1 -6
  258. package/src/domain/agentinstance/controller.ts +12 -6
  259. package/src/domain/agentshare/__tests__/agentshare.test.ts +172 -196
  260. package/src/domain/agentshare/__tests__/create-authorization.test.ts +31 -16
  261. package/src/domain/agentshare/constants.ts +26 -14
  262. package/src/domain/agentshare/controller.ts +1 -6
  263. package/src/domain/agentshare/steps.ts +194 -41
  264. package/src/domain/environment/controller.ts +8 -5
  265. package/src/domain/executioncontext/controller.ts +1 -5
  266. package/src/domain/mcpserver/__tests__/mcpserver.test.ts +28 -115
  267. package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +18 -53
  268. package/src/domain/mcpserver/controller.ts +12 -6
  269. package/src/domain/plugin/controller.ts +23 -18
  270. package/src/domain/plugin/push.ts +16 -8
  271. package/src/domain/schedule/controller.ts +1 -6
  272. package/src/domain/session/controller.ts +4 -12
  273. package/src/domain/skill/__tests__/skill.test.ts +5 -3
  274. package/src/domain/skill/__tests__/slots.test.ts +113 -60
  275. package/src/domain/skill/__tests__/staging.test.ts +304 -0
  276. package/src/domain/skill/constants.ts +28 -3
  277. package/src/domain/skill/controller.ts +51 -35
  278. package/src/domain/skill/push.ts +3 -3
  279. package/src/domain/skill/transfer/handler.ts +33 -15
  280. package/src/domain/skill/transfer/slots.ts +89 -100
  281. package/src/domain/skill/transfer/staging.ts +191 -0
  282. package/src/domain/workflow/controller.ts +10 -28
  283. package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
  284. package/src/domain/workflow/validation/task-config-constraints.ts +3 -7
  285. package/src/domain/workflowexecution/controller.ts +2 -7
  286. package/src/domain/workflowinstance/controller.ts +12 -6
  287. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +19 -32
  288. package/src/extensions/__tests__/extension-composition.test.ts +4 -4
  289. package/src/extensions/__tests__/list-read-scope-composed.test.ts +6 -9
  290. package/src/extensions/authorization-queries.ts +5 -6
  291. package/src/extensions/list-read-scope.ts +1 -1
  292. package/src/extensions/resource-authorization.ts +5 -3
  293. package/src/index.ts +14 -0
  294. package/src/pipeline/apiresource-meta.ts +10 -21
  295. package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +31 -18
  296. package/src/pipeline/steps/__tests__/visibility-gates.test.ts +187 -0
  297. package/src/pipeline/steps/authorization-tuples.ts +11 -9
  298. package/src/pipeline/steps/references.ts +70 -578
  299. package/src/pipeline/steps/resolve-artifact-source.ts +20 -13
  300. package/src/pipeline/steps/visibility-gates.ts +174 -0
  301. package/src/query/search/__tests__/criteria.test.ts +4 -0
  302. package/src/query/search/__tests__/query-store.test.ts +40 -11
  303. package/src/query/search/controller.ts +1 -0
  304. package/src/query/search/criteria.ts +14 -0
  305. package/src/query/search/handler.ts +7 -6
  306. package/src/query/search/query-store.ts +2 -0
  307. package/src/store/__tests__/store-contract.ts +51 -6
  308. package/src/store/interface.ts +6 -3
  309. package/src/store/postgres/__tests__/migrations.test.ts +6 -187
  310. package/src/store/postgres/__tests__/store-contract.test.ts +2 -0
  311. package/src/store/postgres/migrations.ts +1 -48
  312. package/src/store/postgres/store.ts +11 -4
  313. package/src/store/sqlite/__tests__/migrations.test.ts +5 -191
  314. package/src/store/sqlite/migrations.ts +1 -45
  315. package/src/store/sqlite/store.ts +10 -4
  316. package/src/transport/registry/__tests__/lanes.test.ts +1 -1
  317. package/dist/domain/workflow/agent-call-references.d.ts +0 -54
  318. package/dist/domain/workflow/agent-call-references.d.ts.map +0 -1
  319. package/dist/domain/workflow/agent-call-references.js +0 -97
  320. package/dist/domain/workflow/agent-call-references.js.map +0 -1
  321. package/dist/store/public-visibility-retired.d.ts +0 -67
  322. package/dist/store/public-visibility-retired.d.ts.map +0 -1
  323. package/dist/store/public-visibility-retired.js +0 -55
  324. package/dist/store/public-visibility-retired.js.map +0 -1
  325. package/src/domain/workflow/__tests__/agent-call-references.test.ts +0 -222
  326. package/src/domain/workflow/agent-call-references.ts +0 -157
  327. package/src/pipeline/__tests__/supports-visibility.test.ts +0 -112
  328. package/src/pipeline/steps/__tests__/references.test.ts +0 -703
  329. package/src/store/__tests__/public-visibility-retired.test.ts +0 -127
  330. package/src/store/public-visibility-retired.ts +0 -119
@@ -58,17 +58,15 @@ export class ArtifactStorageNotFoundError extends Error {
58
58
  }
59
59
 
60
60
  /**
61
- * A staged upload minted by presignPut: the URL receives the bytes, the
62
- * stagingKey reads them back through the same driver. Staged blobs are
63
- * short-lived by contract — the local lane sweeps them on TTL expiry and
64
- * boot; R2 deployments configure a bucket lifecycle rule on the staging
65
- * prefix (the §6b driver-side sweep expectation).
61
+ * A staged upload minted by presignPut: the URL receives the bytes, which
62
+ * the caller reads back through download() under the key IT named. Staged
63
+ * blobs are short-lived by contract — the local lane sweeps them on TTL
64
+ * expiry and boot; a bucket deployment configures a lifecycle rule on the
65
+ * domain's staging prefix (the §6b driver-side sweep expectation).
66
66
  */
67
67
  export interface PresignedUpload {
68
- /** Accepts one HTTP PUT of exactly the declared byte count. */
68
+ /** Accepts an HTTP PUT of exactly the declared byte count. */
69
69
  readonly url: string;
70
- /** Driver key where the staged bytes land, readable via download(). */
71
- readonly stagingKey: string;
72
70
  /** The TTL actually granted, after per-driver clamping. */
73
71
  readonly ttlMs: number;
74
72
  }
@@ -98,18 +96,25 @@ export interface ArtifactStorage {
98
96
  downloadFilename: string,
99
97
  ): Promise<string>;
100
98
  /**
101
- * A time-limited upload URL for a staging-prefixed blob of exactly
102
- * declaredSizeBytes (§6b). Per-driver semantics differ DELIBERATELY and
103
- * are contract, not accident: the local backend rides the skill transfer
104
- * lane's URL-as-credential slot mechanism (single-use, exact-size
105
- * enforced by the lane, TTL clamped to the lane's slot TTL) and answers
106
- * only on instances with a staged-upload lane wired — unwired instances
107
- * throw the explicit not-configured error, never a silent no-op. The R2
108
- * backend presigns a PUT (repeatable within its TTL, size enforced by
109
- * the signed Content-Length header, TTL clamped to the 7-day R2
110
- * maximum).
99
+ * A time-limited upload URL for a blob of exactly declaredSizeBytes at
100
+ * the key the CALLER names (§6b). The key is the domain's: it chooses
101
+ * the staging prefix its sweep targets and the mapping from its wire
102
+ * reference, and reads the bytes back through download(key) — the
103
+ * driver never invents a key of its own. Per-driver semantics differ
104
+ * DELIBERATELY and are contract, not accident: the local backend rides
105
+ * the skill transfer lane's URL-as-credential slot mechanism
106
+ * (single-use, exact-size enforced by the lane, TTL clamped to the
107
+ * lane's slot TTL) and answers only on instances with a staged-upload
108
+ * lane wired — unwired instances throw the explicit not-configured
109
+ * error, never a silent no-op. The R2 backend presigns a PUT
110
+ * (repeatable within its TTL, size enforced by the signed
111
+ * Content-Length header, TTL clamped to the 7-day R2 maximum).
111
112
  */
112
- presignPut(declaredSizeBytes: number, ttlMs: number): Promise<PresignedUpload>;
113
+ presignPut(
114
+ key: string,
115
+ declaredSizeBytes: number,
116
+ ttlMs: number,
117
+ ): Promise<PresignedUpload>;
113
118
  /** Removes the artifact; missing is not an error. */
114
119
  delete(key: string): Promise<void>;
115
120
  /** Whether an artifact with the key exists. */
@@ -136,16 +141,16 @@ export type ArtifactStorageDriverFactory = () => ArtifactStorage;
136
141
  * the shape it needs and stays ignorant of who provides it.
137
142
  */
138
143
  export interface StagedUploadLane {
139
- /** Reserves a single-use upload slot; returns its reference + TTL. */
140
- mint(declaredSizeBytes: number): { ref: string; ttlMs: number };
141
- /** The externally-reachable PUT URL for a minted reference. */
142
- uploadUrl(ref: string): string;
143
144
  /**
144
- * The driver key where the reference's staged bytes land — MUST resolve
145
- * inside the driver instance's root, or download(stagingKey) could
146
- * never read what the lane received.
145
+ * Reserves a single-use upload slot whose bytes land at `key` under this
146
+ * driver instance's root — the lane stages into the driver's own tree,
147
+ * so download(key) reads exactly what the lane received. Returns the
148
+ * externally-reachable PUT URL and the TTL the lane grants.
147
149
  */
148
- stagedKey(ref: string): string;
150
+ reserve(
151
+ key: string,
152
+ declaredSizeBytes: number,
153
+ ): { url: string; ttlMs: number };
149
154
  }
150
155
 
151
156
  export interface ArtifactStorageConfig {
@@ -259,6 +264,7 @@ export class LocalArtifactStorage implements ArtifactStorage {
259
264
  }
260
265
 
261
266
  async presignPut(
267
+ key: string,
262
268
  declaredSizeBytes: number,
263
269
  _ttlMs: number,
264
270
  ): Promise<PresignedUpload> {
@@ -267,15 +273,13 @@ export class LocalArtifactStorage implements ArtifactStorage {
267
273
  "local presigned uploads not configured - no staged-upload lane is wired to this store instance",
268
274
  );
269
275
  }
276
+ // The key must be one this instance can read back, or the lane would
277
+ // stage bytes download(key) can never reach.
278
+ this.resolveWithinRoot(key);
270
279
  // The lane's slot TTL governs, not the caller's ask — the slot
271
280
  // registry sweeps on ITS clock, and a URL outliving its slot would be
272
281
  // a credential for nothing.
273
- const { ref, ttlMs } = this.stagedUploadLane.mint(declaredSizeBytes);
274
- return {
275
- url: this.stagedUploadLane.uploadUrl(ref),
276
- stagingKey: this.stagedUploadLane.stagedKey(ref),
277
- ttlMs,
278
- };
282
+ return this.stagedUploadLane.reserve(key, declaredSizeBytes);
279
283
  }
280
284
 
281
285
  async getSignedUrl(
@@ -9,8 +9,6 @@
9
9
  * that have logic: config validation copy, the 7-day presign clamp, the
10
10
  * signed Content-Disposition, and the not-found mapping.
11
11
  */
12
- import { randomBytes } from "node:crypto";
13
-
14
12
  import {
15
13
  DeleteObjectCommand,
16
14
  GetObjectCommand,
@@ -30,13 +28,6 @@ import {
30
28
  /** Go: "R2 has a maximum expiration of 7 days" — presigns clamp here. */
31
29
  export const R2_MAX_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000;
32
30
 
33
- /**
34
- * Key prefix for presignPut staging blobs (§6b). Pinned as the surface a
35
- * deployment's bucket lifecycle rule targets: the driver mints under it,
36
- * operations sweeps it — changing it orphans staged blobs from the sweep.
37
- */
38
- export const R2_STAGING_PREFIX = "staging/";
39
-
40
31
  /**
41
32
  * Go get_content/get_download_url wrap their storage calls in a 30s
42
33
  * context timeout. The TS ArtifactStorage interface carries no signal, so
@@ -167,17 +158,17 @@ export class R2ArtifactStorage implements ArtifactStorage {
167
158
  }
168
159
 
169
160
  async presignPut(
161
+ key: string,
170
162
  declaredSizeBytes: number,
171
163
  ttlMs: number,
172
164
  ): Promise<PresignedUpload> {
173
165
  const clampedMs = Math.min(ttlMs, R2_MAX_EXPIRATION_MS);
174
- // Random staging key: the URL is the credential (unguessable), and the
175
- // prefix is the contract surface a bucket lifecycle rule sweeps (§6b —
176
- // staged uploads the domain never committed must not accrete forever).
177
- const stagingKey = `${R2_STAGING_PREFIX}${randomBytes(16).toString("hex")}`;
166
+ // The key is the caller's: the domain names its staging prefix (the
167
+ // surface a bucket lifecycle rule sweeps) and keeps the unguessable
168
+ // part of the URL-as-credential in the reference it hands the client.
178
169
  const command = new PutObjectCommand({
179
170
  Bucket: this.bucket,
180
- Key: stagingKey,
171
+ Key: key,
181
172
  // Signed into the URL: a PUT whose body disagrees with the declared
182
173
  // size fails the signature check — R2's arm of the exact-size
183
174
  // contract the local lane enforces by counting bytes.
@@ -187,7 +178,7 @@ export class R2ArtifactStorage implements ArtifactStorage {
187
178
  const url = await this.presign(this.client, command, {
188
179
  expiresIn: Math.floor(clampedMs / 1000),
189
180
  });
190
- return { url, stagingKey, ttlMs: clampedMs };
181
+ return { url, ttlMs: clampedMs };
191
182
  } catch (error) {
192
183
  throw new Error(`r2 presign failed: ${errorText(error)}`, { cause: error });
193
184
  }
@@ -34,9 +34,9 @@ editions; the cloud stores what open source computes.
34
34
  `spec.execution_visibility`).
35
35
  - `tuples.ts` — the tuple vocabulary (object, relation, subject; the string
36
36
  notation), the `Person` type (the caller as the model sees them: account id
37
- plus the aliases a creator stamp may carry). The model declares no wildcard
38
- subject and no condition, so a check carries no context and the parser refuses
39
- the `type:*` notation.
37
+ plus the aliases a creator stamp may carry), `CheckContext` (the
38
+ `allow_public` parameter: `allow: true` on a point check, `false` in a listing
39
+ — the cloud's own posture).
40
40
  - `person.ts` — the one construction of a `Person`: `resolvePerson` reads the
41
41
  caller's account through the port the way whoAmI does, `personFor` builds the
42
42
  aliases (the account id and the issuer subject; an email is nobody's) and
@@ -70,8 +70,8 @@ editions; the cloud stores what open source computes.
70
70
 
71
71
  - `authorizer.ts` — the `Authorizer` driver, arm for arm the cloud's
72
72
  (`stigmer-cloud src/authorizer/fga-authorizer.ts`): the four pre-check denials
73
- with the Java copy; a kind this edition does not serve denied (a platform
74
- capability no self-host holds); the target loaded once through the source;
73
+ with the Java copy; a kind this edition does not serve denied (so nobody sets
74
+ public visibility on a self-host); the target loaded once through the source;
75
75
  `not-found` for a missing row except on the kinds the cloud never probes
76
76
  (`NOT_FOUND_EXEMPT_KINDS`: `identity_account`, `iam_policy` — account ids
77
77
  cannot be enumerated); the model's answer with an empty reason on a denial so
@@ -87,14 +87,15 @@ editions; the cloud stores what open source computes.
87
87
  counts against the schedule instead of retrying forever.
88
88
  - `list-read-scope.ts` — the `ListReadScope` driver, the cloud's twin
89
89
  (`stigmer-cloud src/iam/list-read-scope.ts`): every candidate a list lane
90
- offers is answered by `can_view`, the same question a get asks — one evaluator
91
- walk per candidate over one source seeded with the candidates' facts, so no
92
- candidate row is read twice and a parent hop reads each distinct parent once;
93
- the enumeration verb (search, recent activity, the two execution summaries —
94
- the console library rides it) scans the kind and evaluates the same way, a row
95
- that does not decode skipped; the `internal` class keeps everything (the
96
- in-process skip); a fault throws and is never an empty answer; an undeclared
97
- kind is a consumer bug, loud.
90
+ offers is answered by `can_view` under the listing context (`allow: false`,
91
+ the public wildcard suppressed) — one evaluator walk per candidate over one
92
+ source seeded with the candidates' facts, so no candidate row is read twice
93
+ and a parent hop reads each distinct parent once; the enumeration verb
94
+ (search, recent activity, the two execution summaries — the console library
95
+ rides it) scans the kind and evaluates the same way, a row that does not
96
+ decode skipped; the `internal` class keeps everything (the in-process skip); a
97
+ fault throws and is never an empty answer; an undeclared kind is a consumer
98
+ bug, loud.
98
99
  - `posture.ts` — the three postures, named once for the composition root and the
99
100
  boot log.
100
101
 
@@ -109,14 +110,15 @@ kind. `model/__tests__/registry.test.ts` pins the declared set to the
109
110
  open-source tier and each kind's wire permissions to its file;
110
111
  `__tests__/wire-permissions.test.ts` pins that every static `(kind, permission)`
111
112
  a served RPC asks about is a declared relation. The rest pin the machinery:
112
- alias matching, the memo, the bounds, the source and the two derived rules on
113
- both store drivers. The four drivers are pinned arm by arm on both store drivers
114
- (`__tests__/authorizer.test.ts`, `organization-directory.test.ts`,
115
- `schedule-fire-caller.test.ts`, `list-read-scope.test.ts` — the adversarial
116
- cells first: the outsider, the viewer rung, the admin who does not read members'
117
- conversations, the orphaned execution, the memory with no subject), the posture
118
- at the wire over three real boots
119
- (`extensions/__tests__/built-in-authorization-composed.test.ts`, the list lanes
120
- included, and the two-boot proof that the sole person's lists are byte-identical
121
- with and without the scope), and the scope's cost is measured rather than
122
- assumed (`list-read-scope.measure.test.ts`, gated on `AUTHORIZATION_MEASURE=1`).
113
+ alias matching, the wildcard's condition, the memo, the bounds, the source and
114
+ the two derived rules on both store drivers. The four drivers are pinned arm by
115
+ arm on both store drivers (`__tests__/authorizer.test.ts`,
116
+ `organization-directory.test.ts`, `schedule-fire-caller.test.ts`,
117
+ `list-read-scope.test.ts` — the adversarial cells first: the outsider, the
118
+ viewer rung, the admin who does not read members' conversations, the orphaned
119
+ execution, the memory with no subject), the posture at the wire over three real
120
+ boots (`extensions/__tests__/built-in-authorization-composed.test.ts`, the list
121
+ lanes included, and the two-boot proof that the sole person's lists are
122
+ byte-identical with and without the scope), and the scope's cost is measured
123
+ rather than assumed (`list-read-scope.measure.test.ts`, gated on
124
+ `AUTHORIZATION_MEASURE=1`).
@@ -2,7 +2,8 @@
2
2
  * Pins the built-in Authorizer arm by arm, on both store drivers, against
3
3
  * the cloud's driver it mirrors (stigmer-cloud src/authorizer/
4
4
  * fga-authorizer.ts): the four pre-check denials with the Java copy; the
5
- * unserved-kind denial (a platform capability no self-host holds); not-found for a
5
+ * unserved-kind denial (the server-side half of "nobody sets public
6
+ visibility on a self-host"); not-found for a
6
7
  * missing target and a DENIAL for a missing row of an exempt kind (the
7
8
  * cloud's probe scope, so account ids cannot be enumerated); allow and
8
9
  * deny from the model over a seeded organization — the owner, an admin, a
@@ -221,11 +222,9 @@ describe.each(driverFixtures(SEEDED_KINDS))(
221
222
  await grant(orgRole(FOUNDER.accountId, "owner", "acme"));
222
223
  await grant(orgRole(ADMIN.accountId, "admin", "acme"));
223
224
  await grant(orgRole(MEMBER.accountId, "member", "acme"));
224
- // The founder's blueprints: one private, one org-visible, and one
225
- // still carrying the retired public level (a row the store
226
- // migration has not met); the org-visible one stamped with the
227
- // founder's RAW subject (a row a 3.14.x verifier wrote), the
228
- // others with the id.
225
+ // The founder's blueprints: one private, one org-visible, one
226
+ // public; the org-visible one stamped with the founder's RAW
227
+ // subject (a row a 3.14.x verifier wrote), the others with the id.
229
228
  await seed("agent", "agt_private", {
230
229
  org: "acme",
231
230
  visibility: ApiResourceVisibility.visibility_private,
@@ -288,10 +287,10 @@ describe.each(driverFixtures(SEEDED_KINDS))(
288
287
  UNKNOWN_KIND_DENY_REASON,
289
288
  ],
290
289
  [
291
- "a kind this edition does not serve (platform — nobody holds an operator capability)",
290
+ "a kind this edition does not serve (platform — nobody sets public visibility)",
292
291
  resolved(FOUNDER),
293
292
  check(
294
- IamPermission.can_view_provider_standing,
293
+ IamPermission.can_set_public_visibility,
295
294
  ApiResourceKind.platform,
296
295
  "stigmer",
297
296
  ),
@@ -466,7 +465,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
466
465
  });
467
466
  });
468
467
 
469
- it("an unprovisioned subject reads nothing — not a private agent, and not a row still carrying the retired public level, which grants no one anything", async () => {
468
+ it("an unprovisioned subject reads a PUBLIC agent (the point-check context honours the wildcard) and nothing private", async () => {
470
469
  const auth = authorizer();
471
470
  expect(
472
471
  await auth.authorize(
@@ -477,7 +476,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
477
476
  "agt_public",
478
477
  ),
479
478
  ),
480
- ).toEqual({ kind: "deny", reason: "" });
479
+ ).toEqual({ kind: "allow" });
481
480
  expect(
482
481
  await auth.authorize(
483
482
  idpShaped(STRANGER),
@@ -3,7 +3,8 @@
3
3
  * built-in authorizer: which tuples a stored row stands for, in exactly
4
4
  * the shapes the cloud's tuple driver writes (stigmer-cloud
5
5
  * iam/tuple-lifecycle.ts: `organization:<org>#viewer` for the org level,
6
- * the owner by the kind's attribution, the parent links by `kind_meta`). Two facts are the
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
7
8
  * OSS edition's own and are pinned here by name: the organization's owner
8
9
  * is a ROW (2b's role lifecycle), never derived from its creator stamp,
9
10
  * or a revoked founder would stay owner; and a stamp that names no person
@@ -95,7 +96,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
95
96
  ]);
96
97
  });
97
98
 
98
- it("a row that still carries the retired public level derives no viewer tuple at all — no shape reaches every account, and the level's own org floor left with it", () => {
99
+ it("a public blueprint adds the conditional wildcard AND keeps the org floor", () => {
99
100
  expect(
100
101
  derivedFor("skill", {
101
102
  visibility: ApiResourceVisibility.visibility_public,
@@ -103,6 +104,8 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
103
104
  ).toEqual([
104
105
  "skill:skill-1#organization@organization:acme",
105
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",
106
109
  ]);
107
110
  });
108
111
 
@@ -163,7 +166,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
163
166
  ).toEqual(["memory:memory-1#organization@organization:acme"]);
164
167
  });
165
168
 
166
- it("an environment carries its creator tuple and an org-viewer at org level, and nothing beyond its org ceiling", () => {
169
+ it("an environment carries its creator tuple, an org-viewer at org level, and NO public wildcard (the kind's ceiling)", () => {
167
170
  expect(
168
171
  derivedFor("environment", {
169
172
  visibility: ApiResourceVisibility.visibility_org,
@@ -176,7 +179,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
176
179
  ]);
177
180
  expect(
178
181
  derivedFor("environment", {
179
- visibility: ApiResourceVisibility.visibility_platform,
182
+ visibility: ApiResourceVisibility.visibility_public,
180
183
  }),
181
184
  ).toEqual([
182
185
  "environment:environment-1#organization@organization:acme",
@@ -506,6 +509,9 @@ describe.each(driverFixtures(SEEDED_KINDS))(
506
509
  object,
507
510
  "can_view",
508
511
  DAVE,
512
+ {
513
+ allow: false,
514
+ },
509
515
  ),
510
516
  ).toBe(true);
511
517
  expect(rowReads).toBe(1);
@@ -701,6 +707,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
701
707
  parseObjectRef(object),
702
708
  relation,
703
709
  person,
710
+ { allow: true },
704
711
  );
705
712
  }
706
713
 
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Pins the evaluator's semantics the store tests cannot express (the
3
3
  * cloud's `.fga.yaml` documents prove the model's answers; this file
4
- * proves the machinery under them): how a person matches a tuple, that a
5
- * direct tuple outside the line's type restriction is ignored (model drift
6
- * fails closed), how far a resolution may walk, and that a declaration
7
- * cycle or an undeclared target is a thrown fault and never a silent deny.
4
+ * proves the machinery under them): how a person matches a tuple, what
5
+ * the `allow_public` context does, that a direct tuple outside the line's
6
+ * type restriction is ignored (model drift fails closed), how far a
7
+ * resolution may walk, and that a declaration cycle or an undeclared
8
+ * target is a thrown fault and never a silent deny.
8
9
  *
9
10
  * The fixture source is the in-memory one the store-test kit uses, so the
10
11
  * two proofs share one tuple vocabulary. Where a case needs a shape the
@@ -29,6 +30,7 @@ import {
29
30
  direct,
30
31
  from,
31
32
  objectOf,
33
+ publicWith,
32
34
  union,
33
35
  usersetOf,
34
36
  } from "../model/rewrite.js";
@@ -54,17 +56,22 @@ function person(accountId: string, ...aliases: string[]): Person {
54
56
  return { accountId, aliases: new Set([accountId, ...aliases]) };
55
57
  }
56
58
 
59
+ const RESOLVE = { allow: true };
60
+ const LIST = { allow: false };
61
+
57
62
  async function allowed(
58
63
  source: TupleSource,
59
64
  object: string,
60
65
  relation: string,
61
66
  who: Person,
67
+ context = RESOLVE,
62
68
  ): Promise<boolean> {
63
69
  return checkRelation(
64
70
  { model: builtInModel, source },
65
71
  parseObjectRef(object),
66
72
  relation,
67
73
  who,
74
+ context,
68
75
  );
69
76
  }
70
77
 
@@ -93,17 +100,67 @@ describe("a person against a direct tuple", () => {
93
100
  });
94
101
  });
95
102
 
96
- describe("a stranger against a row with no grant that names them", () => {
97
- it("reads nothing: no subject form reaches every account, so a stranger holds no relation on a row they were not granted", async () => {
98
- const source = newInMemoryTupleSource([
99
- tuple("agent:open#organization@organization:acme"),
100
- tuple("agent:open#owner@identity_account:ida_carol"),
101
- tuple("agent:open#viewer@organization:acme#viewer"),
102
- ]);
103
- const stranger = person("ida_mallory");
103
+ describe("the public wildcard and its condition", () => {
104
+ const publicViewer = (object: string): Tuple => ({
105
+ object: parseObjectRef(object),
106
+ relation: "viewer",
107
+ subject: {
108
+ form: "wildcard",
109
+ type: "identity_account",
110
+ condition: "allow_public",
111
+ },
112
+ });
113
+ const source = newInMemoryTupleSource([
114
+ tuple("agent:open#organization@organization:acme"),
115
+ publicViewer("agent:open"),
116
+ ]);
117
+ const stranger = person("ida_mallory");
118
+
119
+ it("reads for anyone on a point check (the cloud's `allow: true`) and for nobody in a listing (`allow: false`)", async () => {
104
120
  expect(await allowed(source, "agent:open", "can_view", stranger)).toBe(
105
- false,
121
+ true,
106
122
  );
123
+ expect(
124
+ await allowed(source, "agent:open", "can_view", stranger, LIST),
125
+ ).toBe(false);
126
+ });
127
+
128
+ it("ignores a wildcard tuple that carries no condition where the line demands one — a tuple the cloud could never have written", async () => {
129
+ const bare = newInMemoryTupleSource([
130
+ tuple("agent:open#viewer@identity_account:*"),
131
+ ]);
132
+ expect(await allowed(bare, "agent:open", "can_view", stranger)).toBe(false);
133
+ });
134
+
135
+ it("is a thrown fault under a condition the transcript names but the evaluator does not know — a model that grew a condition", async () => {
136
+ const grown = declareKind({
137
+ kind: ApiResourceKind.agent,
138
+ schema: AgentSchema,
139
+ source: "test/grown.fga",
140
+ relations: [
141
+ ["viewer", direct(publicWith("identity_account", "after_hours"))],
142
+ ],
143
+ });
144
+ const afterHours = newInMemoryTupleSource([
145
+ {
146
+ object: parseObjectRef("agent:open"),
147
+ relation: "viewer",
148
+ subject: {
149
+ form: "wildcard",
150
+ type: "identity_account",
151
+ condition: "after_hours",
152
+ },
153
+ },
154
+ ]);
155
+ await expect(
156
+ checkRelation(
157
+ { model: newModel([grown]), source: afterHours },
158
+ parseObjectRef("agent:open"),
159
+ "viewer",
160
+ stranger,
161
+ RESOLVE,
162
+ ),
163
+ ).rejects.toMatchObject({ reason: "unknown-condition" });
107
164
  });
108
165
  });
109
166
 
@@ -220,6 +277,7 @@ describe("the walk itself", () => {
220
277
  parseObjectRef("agent:n0"),
221
278
  "next",
222
279
  person("ida_nobody"),
280
+ RESOLVE,
223
281
  ),
224
282
  ).rejects.toMatchObject({ reason: "resolution-depth-exceeded" });
225
283
  });
@@ -240,6 +298,7 @@ describe("the walk itself", () => {
240
298
  parseObjectRef("agent:x"),
241
299
  "a",
242
300
  person("ida_nobody"),
301
+ RESOLVE,
243
302
  ),
244
303
  ).rejects.toBeInstanceOf(AuthorizationEvaluationError);
245
304
  });
@@ -273,7 +332,7 @@ describe("declareKind validates a transcript at load", () => {
273
332
  source: "test/bad.fga",
274
333
  relations: [
275
334
  ["viewer", direct(objectOf("identity_account"))],
276
- ["viewer", direct(usersetOf("organization", "viewer"))],
335
+ ["viewer", direct(publicWith("identity_account", "allow_public"))],
277
336
  ],
278
337
  }),
279
338
  ).toThrow("declared twice");
@@ -50,7 +50,7 @@ describe("rowFactsOf against the tuple lifecycle's own resolution", () => {
50
50
  for (const visibility of [
51
51
  ApiResourceVisibility.visibility_private,
52
52
  ApiResourceVisibility.visibility_org,
53
- ApiResourceVisibility.visibility_platform,
53
+ ApiResourceVisibility.visibility_public,
54
54
  ]) {
55
55
  it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the same parent links and visibility shapes`, () => {
56
56
  const row = fixtureRow(declaration, {
@@ -133,7 +133,7 @@ describe("a list candidate against the loaded row — the facts' two producers",
133
133
  for (const visibility of [
134
134
  ApiResourceVisibility.visibility_private,
135
135
  ApiResourceVisibility.visibility_org,
136
- ApiResourceVisibility.visibility_platform,
136
+ ApiResourceVisibility.visibility_public,
137
137
  ]) {
138
138
  it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the candidate the helper builds carries the facts the driver derives from`, async () => {
139
139
  const row = fixtureRow(declaration, {