@stigmer/server 3.22.1 → 3.23.1-dev.20260923075205

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 (329) 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 +4 -8
  10. package/dist/authorization/authorizer.d.ts.map +1 -1
  11. package/dist/authorization/authorizer.js +5 -9
  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 +10 -25
  15. package/dist/authorization/derived-tuples.js.map +1 -1
  16. package/dist/authorization/evaluator.d.ts +7 -8
  17. package/dist/authorization/evaluator.d.ts.map +1 -1
  18. package/dist/authorization/evaluator.js +4 -20
  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 +5 -9
  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 +4 -5
  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 +3 -4
  34. package/dist/authorization/model/plugin.js.map +1 -1
  35. package/dist/authorization/model/rewrite.d.ts +8 -10
  36. package/dist/authorization/model/rewrite.d.ts.map +1 -1
  37. package/dist/authorization/model/rewrite.js +0 -3
  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 +2 -3
  50. package/dist/authorization/organization-directory.js.map +1 -1
  51. package/dist/authorization/store-test-kit.d.ts +0 -6
  52. package/dist/authorization/store-test-kit.d.ts.map +1 -1
  53. package/dist/authorization/store-test-kit.js +16 -62
  54. package/dist/authorization/store-test-kit.js.map +1 -1
  55. package/dist/authorization/tuples.d.ts +13 -32
  56. package/dist/authorization/tuples.d.ts.map +1 -1
  57. package/dist/authorization/tuples.js +3 -11
  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 +3 -1
  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 +3 -1
  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 +3 -4
  80. package/dist/domain/agentinstance/controller.js.map +1 -1
  81. package/dist/domain/agentshare/constants.d.ts +6 -11
  82. package/dist/domain/agentshare/constants.d.ts.map +1 -1
  83. package/dist/domain/agentshare/constants.js +8 -16
  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 +3 -1
  87. package/dist/domain/agentshare/controller.js.map +1 -1
  88. package/dist/domain/agentshare/steps.d.ts +18 -25
  89. package/dist/domain/agentshare/steps.d.ts.map +1 -1
  90. package/dist/domain/agentshare/steps.js +41 -142
  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 +2 -3
  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 +2 -1
  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 +3 -4
  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 +9 -11
  104. package/dist/domain/plugin/controller.js.map +1 -1
  105. package/dist/domain/plugin/push.d.ts +7 -5
  106. package/dist/domain/plugin/push.d.ts.map +1 -1
  107. package/dist/domain/plugin/push.js +8 -14
  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 +3 -1
  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 +3 -2
  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 +33 -24
  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/agent-call-references.d.ts +54 -0
  140. package/dist/domain/workflow/agent-call-references.d.ts.map +1 -0
  141. package/dist/domain/workflow/agent-call-references.js +97 -0
  142. package/dist/domain/workflow/agent-call-references.js.map +1 -0
  143. package/dist/domain/workflow/controller.d.ts.map +1 -1
  144. package/dist/domain/workflow/controller.js +14 -6
  145. package/dist/domain/workflow/controller.js.map +1 -1
  146. package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
  147. package/dist/domain/workflow/validation/task-config-constraints.d.ts +10 -1
  148. package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
  149. package/dist/domain/workflow/validation/task-config-constraints.js +3 -2
  150. package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
  151. package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
  152. package/dist/domain/workflowexecution/controller.js +4 -2
  153. package/dist/domain/workflowexecution/controller.js.map +1 -1
  154. package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
  155. package/dist/domain/workflowinstance/controller.js +3 -4
  156. package/dist/domain/workflowinstance/controller.js.map +1 -1
  157. package/dist/extensions/authorization-queries.d.ts +6 -5
  158. package/dist/extensions/authorization-queries.d.ts.map +1 -1
  159. package/dist/extensions/list-read-scope.d.ts +1 -1
  160. package/dist/extensions/resource-authorization.d.ts +3 -2
  161. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  162. package/dist/index.d.ts +1 -1
  163. package/dist/index.d.ts.map +1 -1
  164. package/dist/index.js.map +1 -1
  165. package/dist/pipeline/apiresource-meta.d.ts +12 -3
  166. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  167. package/dist/pipeline/apiresource-meta.js +21 -10
  168. package/dist/pipeline/apiresource-meta.js.map +1 -1
  169. package/dist/pipeline/steps/authorization-tuples.d.ts +9 -3
  170. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  171. package/dist/pipeline/steps/authorization-tuples.js +9 -11
  172. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  173. package/dist/pipeline/steps/references.d.ts +178 -20
  174. package/dist/pipeline/steps/references.d.ts.map +1 -1
  175. package/dist/pipeline/steps/references.js +344 -43
  176. package/dist/pipeline/steps/references.js.map +1 -1
  177. package/dist/pipeline/steps/resolve-artifact-source.d.ts +11 -8
  178. package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -1
  179. package/dist/pipeline/steps/resolve-artifact-source.js +8 -4
  180. package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -1
  181. package/dist/query/search/controller.js +0 -1
  182. package/dist/query/search/controller.js.map +1 -1
  183. package/dist/query/search/criteria.d.ts +1 -5
  184. package/dist/query/search/criteria.d.ts.map +1 -1
  185. package/dist/query/search/criteria.js +3 -13
  186. package/dist/query/search/criteria.js.map +1 -1
  187. package/dist/query/search/handler.d.ts +5 -4
  188. package/dist/query/search/handler.d.ts.map +1 -1
  189. package/dist/query/search/handler.js +7 -6
  190. package/dist/query/search/handler.js.map +1 -1
  191. package/dist/query/search/query-store.d.ts.map +1 -1
  192. package/dist/query/search/query-store.js +0 -2
  193. package/dist/query/search/query-store.js.map +1 -1
  194. package/dist/store/interface.d.ts +3 -6
  195. package/dist/store/interface.d.ts.map +1 -1
  196. package/dist/store/interface.js.map +1 -1
  197. package/dist/store/postgres/migrations.d.ts +3 -1
  198. package/dist/store/postgres/migrations.d.ts.map +1 -1
  199. package/dist/store/postgres/migrations.js +35 -1
  200. package/dist/store/postgres/migrations.js.map +1 -1
  201. package/dist/store/postgres/store.d.ts.map +1 -1
  202. package/dist/store/postgres/store.js +4 -9
  203. package/dist/store/postgres/store.js.map +1 -1
  204. package/dist/store/public-visibility-retired.d.ts +67 -0
  205. package/dist/store/public-visibility-retired.d.ts.map +1 -0
  206. package/dist/store/public-visibility-retired.js +55 -0
  207. package/dist/store/public-visibility-retired.js.map +1 -0
  208. package/dist/store/sqlite/migrations.d.ts +3 -1
  209. package/dist/store/sqlite/migrations.d.ts.map +1 -1
  210. package/dist/store/sqlite/migrations.js +36 -1
  211. package/dist/store/sqlite/migrations.js.map +1 -1
  212. package/dist/store/sqlite/store.d.ts.map +1 -1
  213. package/dist/store/sqlite/store.js +4 -8
  214. package/dist/store/sqlite/store.js.map +1 -1
  215. package/package.json +6 -6
  216. package/src/artifactstorage/__tests__/artifact-storage.test.ts +36 -33
  217. package/src/artifactstorage/__tests__/r2-storage.test.ts +11 -13
  218. package/src/artifactstorage/artifact-storage.ts +37 -33
  219. package/src/artifactstorage/r2-storage.ts +6 -15
  220. package/src/authorization/README.md +24 -26
  221. package/src/authorization/__tests__/authorizer.test.ts +10 -9
  222. package/src/authorization/__tests__/derived-tuples.test.ts +4 -11
  223. package/src/authorization/__tests__/evaluator.test.ts +14 -73
  224. package/src/authorization/__tests__/facts.test.ts +2 -2
  225. package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +19 -27
  226. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +6 -98
  227. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +4 -61
  228. package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +1 -15
  229. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +1 -21
  230. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +1 -25
  231. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +1 -3
  232. package/src/authorization/__tests__/list-read-scope.test.ts +18 -17
  233. package/src/authorization/__tests__/store-tests.test.ts +2 -6
  234. package/src/authorization/__tests__/tuples.test.ts +12 -11
  235. package/src/authorization/authorizer.ts +4 -9
  236. package/src/authorization/derived-tuples.ts +14 -31
  237. package/src/authorization/evaluator.ts +8 -44
  238. package/src/authorization/list-read-scope.ts +5 -11
  239. package/src/authorization/model/agent.ts +2 -5
  240. package/src/authorization/model/agent_instance.ts +0 -2
  241. package/src/authorization/model/mcp_server.ts +0 -2
  242. package/src/authorization/model/plugin.ts +1 -4
  243. package/src/authorization/model/rewrite.ts +8 -13
  244. package/src/authorization/model/skill.ts +0 -2
  245. package/src/authorization/model/workflow.ts +0 -2
  246. package/src/authorization/model/workflow_instance.ts +0 -2
  247. package/src/authorization/organization-directory.ts +1 -3
  248. package/src/authorization/store-test-kit.ts +16 -75
  249. package/src/authorization/tuples.ts +16 -39
  250. package/src/boot/__tests__/skill-transfer-origin.test.ts +72 -0
  251. package/src/boot/compose.ts +62 -25
  252. package/src/boot/config.ts +4 -3
  253. package/src/boot/skill-transfer-origin.ts +76 -0
  254. package/src/domain/agent/__tests__/agent.test.ts +11 -4
  255. package/src/domain/agent/controller.ts +7 -7
  256. package/src/domain/agentchannel/__tests__/agentchannel.test.ts +223 -48
  257. package/src/domain/agentchannel/controller.ts +6 -1
  258. package/src/domain/agentexecution/controller.ts +6 -1
  259. package/src/domain/agentinstance/controller.ts +6 -12
  260. package/src/domain/agentshare/__tests__/agentshare.test.ts +196 -172
  261. package/src/domain/agentshare/__tests__/create-authorization.test.ts +16 -31
  262. package/src/domain/agentshare/constants.ts +14 -26
  263. package/src/domain/agentshare/controller.ts +6 -1
  264. package/src/domain/agentshare/steps.ts +41 -194
  265. package/src/domain/environment/controller.ts +5 -8
  266. package/src/domain/executioncontext/controller.ts +5 -1
  267. package/src/domain/mcpserver/__tests__/mcpserver.test.ts +115 -28
  268. package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +53 -18
  269. package/src/domain/mcpserver/controller.ts +6 -12
  270. package/src/domain/plugin/controller.ts +16 -25
  271. package/src/domain/plugin/push.ts +8 -16
  272. package/src/domain/schedule/controller.ts +6 -1
  273. package/src/domain/session/controller.ts +12 -4
  274. package/src/domain/skill/__tests__/skill.test.ts +5 -3
  275. package/src/domain/skill/__tests__/slots.test.ts +113 -60
  276. package/src/domain/skill/__tests__/staging.test.ts +304 -0
  277. package/src/domain/skill/constants.ts +28 -3
  278. package/src/domain/skill/controller.ts +44 -42
  279. package/src/domain/skill/push.ts +3 -3
  280. package/src/domain/skill/transfer/handler.ts +33 -15
  281. package/src/domain/skill/transfer/slots.ts +89 -100
  282. package/src/domain/skill/transfer/staging.ts +191 -0
  283. package/src/domain/workflow/__tests__/agent-call-references.test.ts +222 -0
  284. package/src/domain/workflow/agent-call-references.ts +157 -0
  285. package/src/domain/workflow/controller.ts +28 -10
  286. package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
  287. package/src/domain/workflow/validation/task-config-constraints.ts +7 -3
  288. package/src/domain/workflowexecution/controller.ts +7 -2
  289. package/src/domain/workflowinstance/controller.ts +6 -12
  290. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +32 -19
  291. package/src/extensions/__tests__/extension-composition.test.ts +4 -4
  292. package/src/extensions/__tests__/list-read-scope-composed.test.ts +9 -6
  293. package/src/extensions/authorization-queries.ts +6 -5
  294. package/src/extensions/list-read-scope.ts +1 -1
  295. package/src/extensions/resource-authorization.ts +3 -5
  296. package/src/index.ts +0 -1
  297. package/src/pipeline/__tests__/supports-visibility.test.ts +112 -0
  298. package/src/pipeline/apiresource-meta.ts +21 -10
  299. package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +18 -31
  300. package/src/pipeline/steps/__tests__/references.test.ts +703 -0
  301. package/src/pipeline/steps/authorization-tuples.ts +9 -11
  302. package/src/pipeline/steps/references.ts +578 -70
  303. package/src/pipeline/steps/resolve-artifact-source.ts +20 -13
  304. package/src/query/search/__tests__/criteria.test.ts +0 -4
  305. package/src/query/search/__tests__/query-store.test.ts +11 -40
  306. package/src/query/search/controller.ts +0 -1
  307. package/src/query/search/criteria.ts +0 -14
  308. package/src/query/search/handler.ts +6 -7
  309. package/src/query/search/query-store.ts +0 -2
  310. package/src/store/__tests__/public-visibility-retired.test.ts +127 -0
  311. package/src/store/__tests__/store-contract.ts +6 -51
  312. package/src/store/interface.ts +3 -6
  313. package/src/store/postgres/__tests__/migrations.test.ts +187 -6
  314. package/src/store/postgres/__tests__/store-contract.test.ts +0 -2
  315. package/src/store/postgres/migrations.ts +48 -1
  316. package/src/store/postgres/store.ts +4 -11
  317. package/src/store/public-visibility-retired.ts +119 -0
  318. package/src/store/sqlite/__tests__/migrations.test.ts +191 -5
  319. package/src/store/sqlite/migrations.ts +45 -1
  320. package/src/store/sqlite/store.ts +4 -10
  321. package/src/transport/registry/__tests__/lanes.test.ts +1 -1
  322. package/dist/pipeline/steps/visibility-gates.d.ts +0 -27
  323. package/dist/pipeline/steps/visibility-gates.d.ts.map +0 -1
  324. package/dist/pipeline/steps/visibility-gates.js +0 -139
  325. package/dist/pipeline/steps/visibility-gates.js.map +0 -1
  326. package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +0 -98
  327. package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +0 -52
  328. package/src/pipeline/steps/__tests__/visibility-gates.test.ts +0 -187
  329. package/src/pipeline/steps/visibility-gates.ts +0 -174
@@ -41,7 +41,11 @@ import { composeServer } from "../../../boot/compose.js";
41
41
  import type { ComposedServer } from "../../../boot/compose.js";
42
42
  import { createLogger } from "../../../boot/logger.js";
43
43
 
44
- const silentLogger = createLogger({ level: "error", pretty: false, write: () => {} });
44
+ const silentLogger = createLogger({
45
+ level: "error",
46
+ pretty: false,
47
+ write: () => {},
48
+ });
45
49
 
46
50
  const API_VERSION = "agentic.stigmer.ai/v1";
47
51
  const KIND = "McpServer";
@@ -128,7 +132,11 @@ function serverInput(overrides?: {
128
132
  };
129
133
  }
130
134
 
131
- async function expectCode(promise: Promise<unknown>, code: Code, arm: string): Promise<ConnectError> {
135
+ async function expectCode(
136
+ promise: Promise<unknown>,
137
+ code: Code,
138
+ arm: string,
139
+ ): Promise<ConnectError> {
132
140
  try {
133
141
  await promise;
134
142
  } catch (error) {
@@ -157,7 +165,10 @@ async function seedCapabilities(
157
165
  serverId,
158
166
  McpServerSchema,
159
167
  );
160
- const patched = fromBinary(McpServerSchema, toBinary(McpServerSchema, stored));
168
+ const patched = fromBinary(
169
+ McpServerSchema,
170
+ toBinary(McpServerSchema, stored),
171
+ );
161
172
  patched.status ??= create(McpServerStatusSchema, {});
162
173
  patched.status.discoveredCapabilities = create(DiscoveredCapabilitiesSchema, {
163
174
  tools: tools.map((name) => ({ name })),
@@ -176,13 +187,19 @@ describe("CRUD", () => {
176
187
  const created = await command.create(serverInput({ name: "GitHub Tools" }));
177
188
  expect(created.metadata?.id).toMatch(/^mcp_[0-9a-z]{26}$/);
178
189
  expect(created.metadata?.slug).toBe("github-tools");
179
- expect(created.metadata?.visibility).toBe(ApiResourceVisibility.visibility_org);
190
+ expect(created.metadata?.visibility).toBe(
191
+ ApiResourceVisibility.visibility_org,
192
+ );
180
193
  });
181
194
 
182
195
  it("rejects a duplicate create by slug within the org; a different org reuses the slug", async () => {
183
196
  const name = `Dup Target ${++counter}`;
184
197
  await command.create(serverInput({ name }));
185
- await expectCode(command.create(serverInput({ name })), Code.AlreadyExists, "duplicate create");
198
+ await expectCode(
199
+ command.create(serverInput({ name })),
200
+ Code.AlreadyExists,
201
+ "duplicate create",
202
+ );
186
203
  const other = await command.create(serverInput({ name, org: "other-org" }));
187
204
  expect(other.metadata?.org).toBe("other-org");
188
205
  });
@@ -201,10 +218,17 @@ describe("CRUD", () => {
201
218
  it("get and getByReference resolve the same resource; unknowns answer NotFound", async () => {
202
219
  const created = await command.create(serverInput());
203
220
  const byId = await query.get({ value: created.metadata!.id });
204
- const byRef = await query.getByReference({ org: ORG, slug: created.metadata!.slug });
221
+ const byRef = await query.getByReference({
222
+ org: ORG,
223
+ slug: created.metadata!.slug,
224
+ });
205
225
  expect(byId.metadata?.id).toBe(created.metadata?.id);
206
226
  expect(byRef.metadata?.id).toBe(created.metadata?.id);
207
- await expectCode(query.get({ value: "mcps_missing" }), Code.NotFound, "get unknown");
227
+ await expectCode(
228
+ query.get({ value: "mcps_missing" }),
229
+ Code.NotFound,
230
+ "get unknown",
231
+ );
208
232
  await expectCode(
209
233
  query.getByReference({ org: ORG, slug: "never-created" }),
210
234
  Code.NotFound,
@@ -216,7 +240,11 @@ describe("CRUD", () => {
216
240
  const created = await command.create(serverInput());
217
241
  const deleted = await command.delete({ resourceId: created.metadata!.id });
218
242
  expect(deleted.metadata?.id).toBe(created.metadata?.id);
219
- await expectCode(query.get({ value: created.metadata!.id }), Code.NotFound, "get after delete");
243
+ await expectCode(
244
+ query.get({ value: created.metadata!.id }),
245
+ Code.NotFound,
246
+ "get after delete",
247
+ );
220
248
  });
221
249
 
222
250
  it("update of a non-existent server and delete of a non-existent server answer NotFound; delete with an empty id is InvalidArgument", async () => {
@@ -233,7 +261,11 @@ describe("CRUD", () => {
233
261
  Code.NotFound,
234
262
  "delete non-existent",
235
263
  );
236
- await expectCode(command.delete({}), Code.InvalidArgument, "delete empty id");
264
+ await expectCode(
265
+ command.delete({}),
266
+ Code.InvalidArgument,
267
+ "delete empty id",
268
+ );
237
269
  });
238
270
  });
239
271
 
@@ -244,13 +276,17 @@ describe("updateVisibility (no conformance coverage for this domain — the D4-d
244
276
  resourceId: created.metadata!.id,
245
277
  visibility: ApiResourceVisibility.visibility_private,
246
278
  });
247
- expect(updated.metadata?.visibility).toBe(ApiResourceVisibility.visibility_private);
279
+ expect(updated.metadata?.visibility).toBe(
280
+ ApiResourceVisibility.visibility_private,
281
+ );
248
282
  expect(updated.spec?.description).toBe(created.spec?.description);
249
283
  // A visibility change is a STATUS mutation: status_audit re-stamped
250
284
  // (updated event, fresh timestamp bounds are creation-or-later),
251
285
  // spec_audit byte-untouched.
252
286
  expect(updated.status?.audit?.statusAudit?.event).toBe("updated");
253
- expect(updated.status?.audit?.specAudit).toEqual(created.status?.audit?.specAudit);
287
+ expect(updated.status?.audit?.specAudit).toEqual(
288
+ created.status?.audit?.specAudit,
289
+ );
254
290
  });
255
291
 
256
292
  it("answers NotFound for an unknown id", async () => {
@@ -296,7 +332,9 @@ describe("ValidateDefaultEnabledTools (#402)", () => {
296
332
  it("accepts names the server exposes; skips when the list is empty or the server never connected", async () => {
297
333
  // Never connected: any names pass (no authoritative toolset yet).
298
334
  const fresh = await command.create(serverInput());
299
- const freshUpdate = await command.update(updateInput(fresh, ["anything-goes"]));
335
+ const freshUpdate = await command.update(
336
+ updateInput(fresh, ["anything-goes"]),
337
+ );
300
338
  expect(freshUpdate.spec?.defaultEnabledTools).toEqual(["anything-goes"]);
301
339
 
302
340
  // Connected: valid names pass.
@@ -308,7 +346,11 @@ describe("ValidateDefaultEnabledTools (#402)", () => {
308
346
 
309
347
  it("rejects unknown tools and resource templates with the byte-pinned teaching copy", async () => {
310
348
  const created = await command.create(serverInput());
311
- await seedCapabilities(created.metadata!.id, ["search", "fetch"], ["files"]);
349
+ await seedCapabilities(
350
+ created.metadata!.id,
351
+ ["search", "fetch"],
352
+ ["files"],
353
+ );
312
354
 
313
355
  const err = await expectCode(
314
356
  command.update(updateInput(created, ["serch", "files"])),
@@ -334,7 +376,10 @@ describe("EnrichOAuthStatus (#523) — response-only oauth_status", () => {
334
376
  OAuthAppSchema,
335
377
  create(OAuthAppSchema, {
336
378
  metadata: { id, org: ORG, slug, name: slug },
337
- spec: { vendorApprovalStatus: approval, vendorApprovalDocsUrl: docsUrl },
379
+ spec: {
380
+ vendorApprovalStatus: approval,
381
+ vendorApprovalDocsUrl: docsUrl,
382
+ },
338
383
  }),
339
384
  );
340
385
  }
@@ -346,14 +391,25 @@ describe("EnrichOAuthStatus (#523) — response-only oauth_status", () => {
346
391
  });
347
392
 
348
393
  it("a missing OAuthApp skips enrichment (the initiate path owns refusing)", async () => {
349
- const created = await command.create(serverInput({ oauthAppSlug: "never-applied" }));
394
+ // The app must exist when the server is written (the reference rule);
395
+ // a reference dangles when its target leaves afterwards.
396
+ await seedOAuthApp("never-applied", VendorApprovalStatus.UNSPECIFIED, "");
397
+ const created = await command.create(
398
+ serverInput({ oauthAppSlug: "never-applied" }),
399
+ );
400
+ await server.store.deleteResource(
401
+ ApiResourceKind.oauth_app,
402
+ "oaa_neverapplied",
403
+ );
350
404
  const got = await query.get({ value: created.metadata!.id });
351
405
  expect(got.status?.oauthStatus).toBeUndefined();
352
406
  });
353
407
 
354
408
  it("nothing-to-report means ABSENT — presence itself is the SDK's signal", async () => {
355
409
  await seedOAuthApp("plain-app", VendorApprovalStatus.UNSPECIFIED, "");
356
- const created = await command.create(serverInput({ oauthAppSlug: "plain-app" }));
410
+ const created = await command.create(
411
+ serverInput({ oauthAppSlug: "plain-app" }),
412
+ );
357
413
  const got = await query.get({ value: created.metadata!.id });
358
414
  expect(got.status?.oauthStatus).toBeUndefined();
359
415
  });
@@ -363,24 +419,42 @@ describe("EnrichOAuthStatus (#523) — response-only oauth_status", () => {
363
419
  // alone must enrich (Go enrich_oauth_status_test.go's docs-only and
364
420
  // status-only arms — the executable spec of the #523 shared contract).
365
421
  it("a docs URL ALONE enriches, even with an UNSPECIFIED approval status", async () => {
366
- await seedOAuthApp("docs-only-app", VendorApprovalStatus.UNSPECIFIED, "https://vendor.example/setup");
367
- const created = await command.create(serverInput({ oauthAppSlug: "docs-only-app" }));
422
+ await seedOAuthApp(
423
+ "docs-only-app",
424
+ VendorApprovalStatus.UNSPECIFIED,
425
+ "https://vendor.example/setup",
426
+ );
427
+ const created = await command.create(
428
+ serverInput({ oauthAppSlug: "docs-only-app" }),
429
+ );
368
430
  const got = await query.get({ value: created.metadata!.id });
369
- expect(got.status?.oauthStatus?.vendorApprovalStatus).toBe(VendorApprovalStatus.UNSPECIFIED);
370
- expect(got.status?.oauthStatus?.vendorApprovalDocsUrl).toBe("https://vendor.example/setup");
431
+ expect(got.status?.oauthStatus?.vendorApprovalStatus).toBe(
432
+ VendorApprovalStatus.UNSPECIFIED,
433
+ );
434
+ expect(got.status?.oauthStatus?.vendorApprovalDocsUrl).toBe(
435
+ "https://vendor.example/setup",
436
+ );
371
437
  });
372
438
 
373
439
  it("a non-default approval status ALONE enriches — REJECTED and even APPROVED are reported", async () => {
374
440
  await seedOAuthApp("rejected-app", VendorApprovalStatus.REJECTED, "");
375
- const rejected = await command.create(serverInput({ oauthAppSlug: "rejected-app" }));
441
+ const rejected = await command.create(
442
+ serverInput({ oauthAppSlug: "rejected-app" }),
443
+ );
376
444
  const gotRejected = await query.get({ value: rejected.metadata!.id });
377
- expect(gotRejected.status?.oauthStatus?.vendorApprovalStatus).toBe(VendorApprovalStatus.REJECTED);
445
+ expect(gotRejected.status?.oauthStatus?.vendorApprovalStatus).toBe(
446
+ VendorApprovalStatus.REJECTED,
447
+ );
378
448
  expect(gotRejected.status?.oauthStatus?.vendorApprovalDocsUrl).toBe("");
379
449
 
380
450
  await seedOAuthApp("approved-app", VendorApprovalStatus.APPROVED, "");
381
- const approved = await command.create(serverInput({ oauthAppSlug: "approved-app" }));
451
+ const approved = await command.create(
452
+ serverInput({ oauthAppSlug: "approved-app" }),
453
+ );
382
454
  const gotApproved = await query.get({ value: approved.metadata!.id });
383
- expect(gotApproved.status?.oauthStatus?.vendorApprovalStatus).toBe(VendorApprovalStatus.APPROVED);
455
+ expect(gotApproved.status?.oauthStatus?.vendorApprovalStatus).toBe(
456
+ VendorApprovalStatus.APPROVED,
457
+ );
384
458
  });
385
459
 
386
460
  it("an auth block WITHOUT an oauth_app_ref (the DCR arm) is untouched", async () => {
@@ -391,8 +465,14 @@ describe("EnrichOAuthStatus (#523) — response-only oauth_status", () => {
391
465
  });
392
466
 
393
467
  it("a gating approval status or docs URL enriches BOTH read paths, response-only", async () => {
394
- await seedOAuthApp("gated-app", VendorApprovalStatus.PENDING, "https://vendor.example/approval");
395
- const created = await command.create(serverInput({ oauthAppSlug: "gated-app" }));
468
+ await seedOAuthApp(
469
+ "gated-app",
470
+ VendorApprovalStatus.PENDING,
471
+ "https://vendor.example/approval",
472
+ );
473
+ const created = await command.create(
474
+ serverInput({ oauthAppSlug: "gated-app" }),
475
+ );
396
476
 
397
477
  for (const loaded of [
398
478
  await query.get({ value: created.metadata!.id }),
@@ -430,7 +510,12 @@ describe("org-OAuth-app surface — UNIMPLEMENTED by design (#558, DD-019)", ()
430
510
  expect(getErr.rawMessage).toBe("method GetOrgOAuthApp not implemented");
431
511
 
432
512
  const setErr = await expectCode(
433
- command.setOrgOAuthApp({ resourceId: "mcps_test", org: ORG, clientId: "x", clientSecret: "y" }),
513
+ command.setOrgOAuthApp({
514
+ resourceId: "mcps_test",
515
+ org: ORG,
516
+ clientId: "x",
517
+ clientSecret: "y",
518
+ }),
434
519
  Code.Unimplemented,
435
520
  "setOrgOAuthApp",
436
521
  );
@@ -441,6 +526,8 @@ describe("org-OAuth-app surface — UNIMPLEMENTED by design (#558, DD-019)", ()
441
526
  Code.Unimplemented,
442
527
  "deleteOrgOAuthApp",
443
528
  );
444
- expect(deleteErr.rawMessage).toBe("method DeleteOrgOAuthApp not implemented");
529
+ expect(deleteErr.rawMessage).toBe(
530
+ "method DeleteOrgOAuthApp not implemented",
531
+ );
445
532
  });
446
533
  });
@@ -41,7 +41,11 @@ import { composeServer } from "../../../boot/compose.js";
41
41
  import type { ComposedServer } from "../../../boot/compose.js";
42
42
  import { createLogger } from "../../../boot/logger.js";
43
43
 
44
- const silentLogger = createLogger({ level: "error", pretty: false, write: () => {} });
44
+ const silentLogger = createLogger({
45
+ level: "error",
46
+ pretty: false,
47
+ write: () => {},
48
+ });
45
49
 
46
50
  const REDIRECT_URI = "http://127.0.0.1:8234/auth/oauth/callback";
47
51
  const ORG = "acme";
@@ -368,20 +372,30 @@ describe("initiateOAuthConnect", () => {
368
372
  "OAuth sign-in is unavailable: the platform's OAuth app for 'exampleco' is pending approval by the vendor. This server only accepts OAuth sign-in; an org admin can configure your own OAuth app instead.",
369
373
  ],
370
374
  ];
371
- it.each(refusals)("vendor arm refuses %s", async (_label, status, oauthOnly, copy) => {
372
- const slug = `vendor-${status}-${oauthOnly ? "only" : "manual"}`;
373
- await seedOAuthApp(slug, status);
374
- const id = await applyServer({ vendorSlug: slug, oauthOnly });
375
- const error = await expectCode(
376
- command.initiateOAuthConnect({ mcpServerId: id, org: ORG }),
377
- Code.FailedPrecondition,
378
- copy,
379
- );
380
- expect(error.rawMessage).toBe(copy);
381
- });
375
+ it.each(refusals)(
376
+ "vendor arm refuses %s",
377
+ async (_label, status, oauthOnly, copy) => {
378
+ const slug = `vendor-${status}-${oauthOnly ? "only" : "manual"}`;
379
+ await seedOAuthApp(slug, status);
380
+ const id = await applyServer({ vendorSlug: slug, oauthOnly });
381
+ const error = await expectCode(
382
+ command.initiateOAuthConnect({ mcpServerId: id, org: ORG }),
383
+ Code.FailedPrecondition,
384
+ copy,
385
+ );
386
+ expect(error.rawMessage).toBe(copy);
387
+ },
388
+ );
382
389
 
383
390
  it("vendor arm answers NotFound for an unresolvable oauth_app_ref", async () => {
391
+ // The app must exist when the server is written (the reference rule);
392
+ // the reference becomes unresolvable when its target leaves afterwards.
393
+ await seedOAuthApp("no-such-app", VendorApprovalStatus.APPROVED);
384
394
  const id = await applyServer({ vendorSlug: "no-such-app" });
395
+ await server.store.deleteResource(
396
+ ApiResourceKind.oauth_app,
397
+ "oap_no-such-app",
398
+ );
385
399
  await expectCode(
386
400
  command.initiateOAuthConnect({ mcpServerId: id, org: ORG }),
387
401
  Code.NotFound,
@@ -406,17 +420,29 @@ describe("initiateOAuthConnect", () => {
406
420
  describe("completeOAuthConnect → grant → disconnect (the full lifecycle)", () => {
407
421
  it("guards its inputs (proto rules answer first, exactly as on Go)", async () => {
408
422
  await expectCode(
409
- command.completeOAuthConnect({ mcpServerId: "", state: "s", authorizationCode: "c" }),
423
+ command.completeOAuthConnect({
424
+ mcpServerId: "",
425
+ state: "s",
426
+ authorizationCode: "c",
427
+ }),
410
428
  Code.InvalidArgument,
411
429
  "mcp_server_id: value is required [required]",
412
430
  );
413
431
  await expectCode(
414
- command.completeOAuthConnect({ mcpServerId: "m", state: "", authorizationCode: "c" }),
432
+ command.completeOAuthConnect({
433
+ mcpServerId: "m",
434
+ state: "",
435
+ authorizationCode: "c",
436
+ }),
415
437
  Code.InvalidArgument,
416
438
  "state:",
417
439
  );
418
440
  await expectCode(
419
- command.completeOAuthConnect({ mcpServerId: "m", state: "s", authorizationCode: "" }),
441
+ command.completeOAuthConnect({
442
+ mcpServerId: "m",
443
+ state: "s",
444
+ authorizationCode: "",
445
+ }),
420
446
  Code.InvalidArgument,
421
447
  "authorization_code:",
422
448
  );
@@ -500,7 +526,10 @@ describe("completeOAuthConnect → grant → disconnect (the full lifecycle)", (
500
526
 
501
527
  // The grant is queryable and HEALTHY; the refresh-token env var is
502
528
  // stamped unconditionally (oss#863's precondition, ported as-is).
503
- const status = await query.getOAuthGrantStatus({ resourceId: id, org: ORG });
529
+ const status = await query.getOAuthGrantStatus({
530
+ resourceId: id,
531
+ org: ORG,
532
+ });
504
533
  expect(status.connected).toBe(true);
505
534
  expect(status.targetEnvVar).toBe("EXAMPLE_TOKEN");
506
535
  expect(status.authMethod).toBe("mcp_oauth");
@@ -514,7 +543,10 @@ describe("completeOAuthConnect → grant → disconnect (the full lifecycle)", (
514
543
  expect(firstEnvId).not.toBe("");
515
544
 
516
545
  // Re-connect reuses the managed environment.
517
- const again = await command.initiateOAuthConnect({ mcpServerId: id, org: ORG });
546
+ const again = await command.initiateOAuthConnect({
547
+ mcpServerId: id,
548
+ org: ORG,
549
+ });
518
550
  await command.completeOAuthConnect({
519
551
  mcpServerId: id,
520
552
  state: again.state,
@@ -525,7 +557,10 @@ describe("completeOAuthConnect → grant → disconnect (the full lifecycle)", (
525
557
 
526
558
  // Disconnect tears down grant + environment; a second disconnect is
527
559
  // the idempotent no-grant arm.
528
- const disconnected = await command.disconnectOAuth({ resourceId: id, org: ORG });
560
+ const disconnected = await command.disconnectOAuth({
561
+ resourceId: id,
562
+ org: ORG,
563
+ });
529
564
  expect(disconnected.disconnected).toBe(true);
530
565
  expect(await server.store.oauthGrants.find("", id, ORG)).toBeUndefined();
531
566
  const againDisconnected = await command.disconnectOAuth({
@@ -58,10 +58,6 @@ import {
58
58
  newAuthorizeResolvedTargetStep,
59
59
  } from "../../pipeline/steps/authorize-resolved-target.js";
60
60
  import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
61
- import {
62
- newAuthorizeVisibilityTransitionStep,
63
- newGuardPublicVisibilityStep,
64
- } from "../../pipeline/steps/visibility-gates.js";
65
61
  import {
66
62
  setAuditFieldsForUpdate,
67
63
  newBuildNewStateStep,
@@ -92,7 +88,10 @@ import {
92
88
  TARGET_RESOURCE_KEY,
93
89
  newLoadTargetStep,
94
90
  } from "../../pipeline/steps/load-target.js";
95
- import { newNormalizeReferencesStep } from "../../pipeline/steps/references.js";
91
+ import {
92
+ newNormalizeReferencesStep,
93
+ newValidateReferencesStep,
94
+ } from "../../pipeline/steps/references.js";
96
95
  import {
97
96
  newCleanupIamPoliciesStep,
98
97
  newCreateAuthorizationTuplesStep,
@@ -241,13 +240,13 @@ async function createMcpServer(
241
240
  .addStep(newResolveSlugStep())
242
241
  .addStep(newCheckDuplicateStep(deps.store))
243
242
  .addStep(newBuildNewStateStep())
244
- .addStep(newGuardPublicVisibilityStep(deps.authorizer))
245
243
  // A URL-only server is asked once whether it wants OAuth and completed
246
244
  // when it does; immediately before GuardReservedLabels because the
247
245
  // provenance label it stamps is one the guard diffs.
248
246
  .addStep(newCompleteEndpointAuthStep(endpointAuthDeps(deps)))
249
247
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
250
248
  .addStep(newNormalizeReferencesStep())
249
+ .addStep(newValidateReferencesStep(deps.store))
251
250
  .addStep(newPersistStep(deps.store))
252
251
  .addStep(
253
252
  newCreateAuthorizationTuplesStep(
@@ -300,6 +299,7 @@ async function update(
300
299
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
301
300
  .addStep(newValidateDefaultEnabledToolsStep())
302
301
  .addStep(newNormalizeReferencesStep())
302
+ .addStep(newValidateReferencesStep(deps.store))
303
303
  .addStep(newPersistStep(deps.store))
304
304
  .addStep(
305
305
  newIndexSearchStep(deps.store, mcpServerSearchExtractor, deps.logger),
@@ -463,12 +463,6 @@ async function updateVisibility(
463
463
  newRecordVisibilityBeforeUpdateStep(UPDATE_VISIBILITY_MCP_SERVER_KEY),
464
464
  )
465
465
  .addStep(newValidateVisibilityUpdateStep())
466
- .addStep(
467
- newAuthorizeVisibilityTransitionStep(
468
- UPDATE_VISIBILITY_MCP_SERVER_KEY,
469
- deps.authorizer,
470
- ),
471
- )
472
466
  .addStep(newSetMcpServerVisibilityStep())
473
467
  .addStep(newPersistMcpServerForVisibilityUpdateStep(deps.store))
474
468
  .addStep(
@@ -103,11 +103,12 @@ import {
103
103
  newAuthorizeResolvedTargetStep,
104
104
  } from "../../pipeline/steps/authorize-resolved-target.js";
105
105
  import type { VersionHistoryBinding } from "../../pipeline/steps/version-history.js";
106
- import { newAuthorizeVisibilityTransitionStep } from "../../pipeline/steps/visibility-gates.js";
107
106
  import { metadataOf } from "../../pipeline/steps/shapes.js";
108
107
  import type { Store } from "../../store/interface.js";
109
- import { uploadUrl } from "../skill/transfer/handler.js";
110
- import type { UploadSlots } from "../skill/transfer/slots.js";
108
+ import type {
109
+ ArchiveStaging,
110
+ StagedUpload,
111
+ } from "../skill/transfer/staging.js";
111
112
  import { TRANSFER_LANE_NOT_CONFIGURED } from "./constants.js";
112
113
  import type { PluginMaterializerProvider } from "./materialize/ports.js";
113
114
  import { findMembers } from "./members.js";
@@ -140,12 +141,6 @@ import {
140
141
  } from "./push.js";
141
142
  import { pluginSearchExtractor } from "./search-extractor.js";
142
143
 
143
- /** The transfer lane's controller-side pair; the slots are the skill lane's (one upload surface). */
144
- export interface PluginTransferLaneDeps {
145
- readonly slots: UploadSlots;
146
- readonly baseUrl: string;
147
- }
148
-
149
144
  export interface PluginControllerDeps {
150
145
  readonly store: Store;
151
146
  readonly logger: Logger;
@@ -153,7 +148,8 @@ export interface PluginControllerDeps {
153
148
  readonly authorizationLifecycle: ResourceAuthorizationLifecycle | undefined;
154
149
  readonly artifactStorage: ContentAddressedArchiveStore;
155
150
  readonly materializerProvider: PluginMaterializerProvider;
156
- readonly transferLane?: PluginTransferLaneDeps;
151
+ /** The skill lane's staging port (one upload surface for every archive); absent, the lane answers FailedPrecondition. */
152
+ readonly staging?: ArchiveStaging;
157
153
  }
158
154
 
159
155
  /** Registers both plugin services on the router (routes stage). */
@@ -208,7 +204,7 @@ async function push(
208
204
  .addStep(newValidateProtoStep())
209
205
  .addStep(
210
206
  newResolveArtifactSourceStep<typeof PushPluginRequestSchema>(
211
- deps.transferLane?.slots,
207
+ deps.staging,
212
208
  {
213
209
  source: (input) => ({
214
210
  artifact: input.artifact,
@@ -226,7 +222,7 @@ async function push(
226
222
  .addStep(newParseOverlayDocumentsStep())
227
223
  .addStep(newSanitizePluginMetadataStep(deps.authorizer))
228
224
  .addStep(newPlanMaterializationStep(deps.store, deps.authorizer))
229
- .addStep(newGuardPluginVisibilityStep(deps.authorizer))
225
+ .addStep(newGuardPluginVisibilityStep())
230
226
  .addStep(newResolveConvergenceStep())
231
227
  .build()
232
228
  .execute(reqCtx);
@@ -274,16 +270,17 @@ async function push(
274
270
  // ─── createArtifactUploadUrl ─────────────────────────────────────────────
275
271
 
276
272
  /**
277
- * Mints a short-lived, single-use upload URL over the shared slots; an
278
- * over-limit declaration is refused with the limit BEFORE any bytes move.
273
+ * Mints a short-lived, single-use upload URL through the shared staging
274
+ * port; an over-limit declaration is refused with the limit BEFORE any
275
+ * bytes move.
279
276
  */
280
277
  async function createArtifactUploadUrl(
281
278
  deps: PluginControllerDeps,
282
279
  req: CreatePluginArtifactUploadUrlRequest,
283
280
  ctx: HandlerContext,
284
281
  ): Promise<PluginArtifactUploadUrl> {
285
- const lane = deps.transferLane;
286
- if (lane === undefined) {
282
+ const staging = deps.staging;
283
+ if (staging === undefined) {
287
284
  throw failedPreconditionError(TRANSFER_LANE_NOT_CONFIGURED);
288
285
  }
289
286
  const reqCtx = new RequestContext(
@@ -310,14 +307,14 @@ async function createArtifactUploadUrl(
310
307
  `plugin archive size ${req.sizeBytes} bytes exceeds the ${MAX_ZIP_SIZE}-byte (100MB) archive limit`,
311
308
  );
312
309
  }
313
- let minted: { ref: string; ttlMs: number };
310
+ let minted: StagedUpload;
314
311
  try {
315
- minted = lane.slots.mint(Number(req.sizeBytes));
312
+ minted = await staging.mint(Number(req.sizeBytes));
316
313
  } catch (error) {
317
314
  throw internalError(error, "failed to mint upload reference");
318
315
  }
319
316
  return create(PluginArtifactUploadUrlSchema, {
320
- url: uploadUrl(lane.baseUrl, minted.ref),
317
+ url: minted.url,
321
318
  artifactUploadRef: minted.ref,
322
319
  ttlSeconds: Math.trunc(minted.ttlMs / 1000),
323
320
  });
@@ -359,12 +356,6 @@ async function updateVisibility(
359
356
  .addStep(newLoadPluginByIdStep(deps.store, UPDATE_VISIBILITY_PLUGIN_KEY))
360
357
  .addStep(newRecordVisibilityBeforeUpdateStep(UPDATE_VISIBILITY_PLUGIN_KEY))
361
358
  .addStep(newValidateVisibilityUpdateStep())
362
- .addStep(
363
- newAuthorizeVisibilityTransitionStep(
364
- UPDATE_VISIBILITY_PLUGIN_KEY,
365
- deps.authorizer,
366
- ),
367
- )
368
359
  .addStep(newSetPluginVisibilityStep())
369
360
  .addStep(
370
361
  newPersistPluginStep(
@@ -94,7 +94,6 @@ import { ARTIFACT_BYTES_KEY } from "../../pipeline/steps/resolve-artifact-source
94
94
  import { generateSlug } from "../../pipeline/steps/slug.js";
95
95
  import { rejectUnsupportedVisibility } from "../../pipeline/steps/validate-visibility.js";
96
96
  import { newArchiveCurrentVersionStep } from "../../pipeline/steps/version-archive.js";
97
- import { requireOperatorMaySetPublic } from "../../pipeline/steps/visibility-gates.js";
98
97
  import { ResourceNotFoundError } from "../../store/interface.js";
99
98
  import type { Store } from "../../store/interface.js";
100
99
  import { openPluginArchive } from "./archive.js";
@@ -493,30 +492,23 @@ export function newPlanMaterializationStep(
493
492
 
494
493
  /**
495
494
  * GuardPluginVisibility — the requested level must be one the plugin and
496
- * every planned member kind support, and PUBLIC needs the operator grant
497
- * (the one owner of that question, shared with every other create door).
498
- * Each member's own chain will check again in-process; refusing here keeps
499
- * the head from being written before the answer is known.
495
+ * every planned member kind support: the push chain's counterpart of the
496
+ * ValidateVisibility step on the resource create chains, asked here for
497
+ * the head and for each member kind before anything is written, so a
498
+ * plugin cannot be installed at a level one of its members may not hold.
499
+ * Each member's own chain checks again in-process; refusing here keeps the
500
+ * head from being written before the answer is known.
500
501
  */
501
- export function newGuardPluginVisibilityStep(
502
- authorizer: Authorizer,
503
- ): PipelineStep<PushDesc> {
502
+ export function newGuardPluginVisibilityStep(): PipelineStep<PushDesc> {
504
503
  return {
505
504
  name: "GuardPluginVisibility",
506
- async execute(ctx: RequestContext<PushDesc>): Promise<void> {
505
+ execute(ctx: RequestContext<PushDesc>): void {
507
506
  const level = requestedVisibility(ctx);
508
507
  const plan = ctx.get(PLUGIN_PLAN_KEY) as MaterializationPlan;
509
508
  rejectUnsupportedVisibility(ctx.apiResourceKind, level);
510
509
  for (const kind of new Set(plan.members.map((member) => member.kind))) {
511
510
  rejectUnsupportedVisibility(kind, level);
512
511
  }
513
- if (level !== ApiResourceVisibility.visibility_public) {
514
- return;
515
- }
516
- if (ctx.callerIdentity.callerClass === "internal") {
517
- return;
518
- }
519
- await requireOperatorMaySetPublic(authorizer, ctx.callerIdentity);
520
512
  },
521
513
  };
522
514
  }
@@ -97,7 +97,10 @@ import {
97
97
  newCreateAuthorizationTuplesStep,
98
98
  } from "../../pipeline/steps/authorization-tuples.js";
99
99
  import { newPersistStep } from "../../pipeline/steps/persist.js";
100
- import { newNormalizeReferencesStep } from "../../pipeline/steps/references.js";
100
+ import {
101
+ newNormalizeReferencesStep,
102
+ newValidateReferencesStep,
103
+ } from "../../pipeline/steps/references.js";
101
104
  import { newResolveSlugStep } from "../../pipeline/steps/slug.js";
102
105
  import { newValidateProtoStep } from "../../pipeline/steps/validation.js";
103
106
  import { newValidateVisibilityStep } from "../../pipeline/steps/validate-visibility.js";
@@ -220,6 +223,7 @@ async function createSchedule(
220
223
  .addStep(newBuildNewStateStep())
221
224
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
222
225
  .addStep(newNormalizeReferencesStep())
226
+ .addStep(newValidateReferencesStep(deps.store))
223
227
  .addStep(newPersistStep(deps.store))
224
228
  .addStep(
225
229
  newCreateAuthorizationTuplesStep(
@@ -259,6 +263,7 @@ async function update(
259
263
  .addStep(newBuildUpdateStateStep())
260
264
  .addStep(newGuardReservedLabelsStep(deps.authorizer))
261
265
  .addStep(newNormalizeReferencesStep())
266
+ .addStep(newValidateReferencesStep(deps.store))
262
267
  .addStep(newPersistScheduleUpdateStep(deps.store))
263
268
  .addStep(newArmScheduleStep(deps.clock, deps.logger))
264
269
  .build()