@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.21

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 (1039) hide show
  1. package/bootstrap.json +94 -5
  2. package/dist/admin/admin-agents.controller.d.ts +28 -0
  3. package/dist/admin/admin-agents.controller.js +79 -0
  4. package/dist/admin/admin-connectors.controller.d.ts +29 -0
  5. package/dist/admin/admin-connectors.controller.js +79 -0
  6. package/dist/admin/admin-items.schemas.d.ts +42 -0
  7. package/dist/admin/admin-items.schemas.js +48 -0
  8. package/dist/admin/admin.controller.d.ts +52 -80
  9. package/dist/admin/admin.controller.js +112 -81
  10. package/dist/admin/admin.module.d.ts +4 -1
  11. package/dist/admin/admin.module.js +50 -4
  12. package/dist/admin/admin.schemas.d.ts +69 -0
  13. package/dist/admin/admin.schemas.js +53 -0
  14. package/dist/admin/audit.controller.d.ts +14 -0
  15. package/dist/admin/audit.controller.js +42 -0
  16. package/dist/admin/audit.schemas.d.ts +8 -0
  17. package/dist/admin/audit.schemas.js +17 -0
  18. package/dist/admin/extensions.controller.d.ts +34 -3
  19. package/dist/admin/extensions.controller.js +66 -8
  20. package/dist/admin/extensions.schemas.d.ts +7 -0
  21. package/dist/admin/extensions.schemas.js +10 -0
  22. package/dist/admin/health.service.d.ts +104 -0
  23. package/dist/admin/health.service.js +246 -0
  24. package/dist/admin/limit-defaults.d.ts +20 -0
  25. package/dist/admin/limit-defaults.js +10 -0
  26. package/dist/admin/overview.controller.d.ts +31 -0
  27. package/dist/admin/overview.controller.js +78 -0
  28. package/dist/admin/overview.schemas.d.ts +8 -0
  29. package/dist/admin/overview.schemas.js +13 -0
  30. package/dist/admin/overview.service.d.ts +112 -0
  31. package/dist/admin/overview.service.js +223 -0
  32. package/dist/admin/platform-audit.service.d.ts +41 -0
  33. package/dist/admin/platform-audit.service.js +70 -0
  34. package/dist/admin/setup-lock.d.ts +1 -1
  35. package/dist/admin/setup-lock.js +1 -1
  36. package/dist/admin/setup.controller.d.ts +1 -1
  37. package/dist/admin/setup.controller.js +1 -1
  38. package/dist/admin/setup.service.d.ts +4 -4
  39. package/dist/admin/setup.service.js +8 -8
  40. package/dist/admin/usage.service.d.ts +149 -0
  41. package/dist/admin/usage.service.js +321 -0
  42. package/dist/agents/admin-agents.d.ts +92 -0
  43. package/dist/agents/admin-agents.js +170 -0
  44. package/dist/agents/agent-lookup.d.ts +24 -0
  45. package/dist/agents/agent-lookup.js +46 -2
  46. package/dist/agents/agent-profile.service.d.ts +31 -0
  47. package/dist/agents/agent-profile.service.js +122 -0
  48. package/dist/agents/agents.controller.d.ts +53 -168
  49. package/dist/agents/agents.controller.js +163 -34
  50. package/dist/agents/agents.module.d.ts +6 -2
  51. package/dist/agents/agents.module.js +41 -7
  52. package/dist/agents/agents.schemas.d.ts +392 -0
  53. package/dist/agents/agents.schemas.js +126 -0
  54. package/dist/agents/agents.service.d.ts +121 -36
  55. package/dist/agents/agents.service.js +411 -121
  56. package/dist/agents/definition.d.ts +142 -21
  57. package/dist/agents/definition.js +389 -43
  58. package/dist/agents/from-template.d.ts +106 -0
  59. package/dist/agents/from-template.js +680 -0
  60. package/dist/agents/from-template.service.d.ts +72 -0
  61. package/dist/agents/from-template.service.js +178 -0
  62. package/dist/agents/instruction-files.d.ts +60 -0
  63. package/dist/agents/instruction-files.js +111 -0
  64. package/dist/agents/models.controller.d.ts +44 -6
  65. package/dist/agents/models.controller.js +84 -8
  66. package/dist/agents/org-templates.d.ts +186 -0
  67. package/dist/agents/org-templates.js +876 -0
  68. package/dist/agents/pending-connector-requests.d.ts +79 -0
  69. package/dist/agents/pending-connector-requests.js +215 -0
  70. package/dist/agents/pending-connectors.controller.d.ts +39 -0
  71. package/dist/agents/pending-connectors.controller.js +91 -0
  72. package/dist/agents/pending-connectors.service.d.ts +62 -0
  73. package/dist/agents/pending-connectors.service.js +282 -0
  74. package/dist/agents/profile.d.ts +114 -0
  75. package/dist/agents/profile.js +55 -0
  76. package/dist/agents/readiness.controller.d.ts +26 -0
  77. package/dist/agents/readiness.controller.js +56 -0
  78. package/dist/agents/templates.controller.d.ts +77 -5
  79. package/dist/agents/templates.controller.js +153 -7
  80. package/dist/agents/templates.d.ts +127 -23
  81. package/dist/agents/templates.js +482 -44
  82. package/dist/agents/templates.schemas.d.ts +20 -0
  83. package/dist/agents/templates.schemas.js +45 -0
  84. package/dist/background/background.controller.d.ts +38 -0
  85. package/dist/background/background.controller.js +88 -0
  86. package/dist/background/background.module.d.ts +10 -0
  87. package/dist/background/background.module.js +39 -0
  88. package/dist/background/background.schemas.d.ts +10 -0
  89. package/dist/background/background.schemas.js +16 -0
  90. package/dist/background/finish.d.ts +44 -0
  91. package/dist/background/finish.js +95 -0
  92. package/dist/background/launch-lock.d.ts +15 -0
  93. package/dist/background/launch-lock.js +40 -0
  94. package/dist/background/launch.d.ts +42 -0
  95. package/dist/background/launch.js +77 -0
  96. package/dist/background/poll.job.d.ts +56 -0
  97. package/dist/background/poll.job.js +195 -0
  98. package/dist/background/render.d.ts +23 -0
  99. package/dist/background/render.js +48 -0
  100. package/dist/background/session.d.ts +48 -0
  101. package/dist/background/session.js +80 -0
  102. package/dist/background/status.d.ts +35 -0
  103. package/dist/background/status.js +57 -0
  104. package/dist/background/stop.d.ts +68 -0
  105. package/dist/background/stop.js +244 -0
  106. package/dist/background/store.d.ts +167 -0
  107. package/dist/background/store.js +361 -0
  108. package/dist/background/store.module.d.ts +6 -0
  109. package/dist/background/store.module.js +22 -0
  110. package/dist/background/tasks.service.d.ts +109 -0
  111. package/dist/background/tasks.service.js +271 -0
  112. package/dist/background/wake-rules.d.ts +66 -0
  113. package/dist/background/wake-rules.js +113 -0
  114. package/dist/background/wake.d.ts +30 -0
  115. package/dist/background/wake.js +63 -0
  116. package/dist/catalog/admin-catalog.controller.d.ts +136 -52
  117. package/dist/catalog/admin-catalog.controller.js +275 -65
  118. package/dist/catalog/admin-catalog.schemas.d.ts +82 -0
  119. package/dist/catalog/admin-catalog.schemas.js +99 -0
  120. package/dist/catalog/appearance.schemas.d.ts +10 -0
  121. package/dist/catalog/appearance.schemas.js +20 -0
  122. package/dist/catalog/appearance.service.d.ts +105 -0
  123. package/dist/catalog/appearance.service.js +306 -0
  124. package/dist/catalog/catalog-content.d.ts +122 -35
  125. package/dist/catalog/catalog-content.js +122 -14
  126. package/dist/catalog/catalog-files.d.ts +42 -0
  127. package/dist/catalog/catalog-files.js +89 -0
  128. package/dist/catalog/catalog-import.module.d.ts +7 -0
  129. package/dist/catalog/catalog-import.module.js +63 -0
  130. package/dist/catalog/catalog-items.d.ts +122 -7
  131. package/dist/catalog/catalog-items.js +301 -13
  132. package/dist/catalog/catalog-scope.service.d.ts +293 -0
  133. package/dist/catalog/catalog-scope.service.js +1236 -0
  134. package/dist/catalog/catalog.module.d.ts +7 -9
  135. package/dist/catalog/catalog.module.js +47 -31
  136. package/dist/catalog/catalog.service.d.ts +122 -31
  137. package/dist/catalog/catalog.service.js +177 -105
  138. package/dist/catalog/claude/agents.js +15 -10
  139. package/dist/catalog/claude/translate.js +3 -0
  140. package/dist/catalog/cli.d.ts +11 -1
  141. package/dist/catalog/cli.js +29 -1
  142. package/dist/catalog/component-promotion.d.ts +96 -0
  143. package/dist/catalog/component-promotion.js +395 -0
  144. package/dist/catalog/component-scope.controller.d.ts +102 -0
  145. package/dist/catalog/component-scope.controller.js +257 -0
  146. package/dist/catalog/component-scope.schemas.d.ts +118 -0
  147. package/dist/catalog/component-scope.schemas.js +97 -0
  148. package/dist/catalog/component-scope.service.d.ts +394 -0
  149. package/dist/catalog/component-scope.service.js +1133 -0
  150. package/dist/catalog/component-state.d.ts +207 -0
  151. package/dist/catalog/component-state.js +484 -0
  152. package/dist/catalog/git-source.d.ts +9 -1
  153. package/dist/catalog/git-source.js +29 -2
  154. package/dist/catalog/job-ids.d.ts +30 -0
  155. package/dist/catalog/job-ids.js +25 -0
  156. package/dist/catalog/marketplace-fetch.d.ts +1 -1
  157. package/dist/catalog/marketplace-icons.d.ts +64 -0
  158. package/dist/catalog/marketplace-icons.js +131 -0
  159. package/dist/catalog/marketplaces.controller.d.ts +50 -41
  160. package/dist/catalog/marketplaces.controller.js +130 -46
  161. package/dist/catalog/marketplaces.schemas.d.ts +48 -0
  162. package/dist/catalog/marketplaces.schemas.js +53 -0
  163. package/dist/catalog/marketplaces.service.d.ts +110 -17
  164. package/dist/catalog/marketplaces.service.js +337 -29
  165. package/dist/catalog/org-catalog.controller.d.ts +114 -62
  166. package/dist/catalog/org-catalog.controller.js +191 -98
  167. package/dist/catalog/org-catalog.schemas.d.ts +104 -0
  168. package/dist/catalog/org-catalog.schemas.js +107 -0
  169. package/dist/catalog/org-catalog.service.d.ts +72 -33
  170. package/dist/catalog/org-catalog.service.js +367 -158
  171. package/dist/catalog/org-extension-switch.d.ts +41 -0
  172. package/dist/catalog/org-extension-switch.js +115 -0
  173. package/dist/catalog/org-extension.controller.d.ts +133 -0
  174. package/dist/catalog/org-extension.controller.js +313 -0
  175. package/dist/catalog/org-extension.schemas.d.ts +15 -0
  176. package/dist/catalog/org-extension.schemas.js +22 -0
  177. package/dist/catalog/org-plugin-uploads.controller.d.ts +77 -0
  178. package/dist/catalog/org-plugin-uploads.controller.js +200 -0
  179. package/dist/catalog/org-plugin-uploads.d.ts +71 -0
  180. package/dist/catalog/org-plugin-uploads.js +122 -0
  181. package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
  182. package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
  183. package/dist/catalog/owned-items.d.ts +188 -0
  184. package/dist/catalog/owned-items.js +808 -0
  185. package/dist/catalog/owned-plugin-cleanup.d.ts +56 -0
  186. package/dist/catalog/owned-plugin-cleanup.js +194 -0
  187. package/dist/catalog/ownership.d.ts +172 -0
  188. package/dist/catalog/ownership.js +326 -0
  189. package/dist/catalog/platform-components.d.ts +243 -0
  190. package/dist/catalog/platform-components.js +872 -0
  191. package/dist/catalog/platform-migration.d.ts +115 -0
  192. package/dist/catalog/platform-migration.js +583 -0
  193. package/dist/catalog/plugin-import.d.ts +254 -47
  194. package/dist/catalog/plugin-import.js +810 -112
  195. package/dist/catalog/plugin-install.d.ts +205 -42
  196. package/dist/catalog/plugin-install.js +828 -126
  197. package/dist/catalog/plugin-package.d.ts +43 -4
  198. package/dist/catalog/plugin-package.js +194 -7
  199. package/dist/catalog/plugin-upgrade.d.ts +308 -225
  200. package/dist/catalog/plugin-upgrade.js +1325 -1131
  201. package/dist/catalog/request-rules.d.ts +65 -0
  202. package/dist/catalog/request-rules.js +217 -0
  203. package/dist/catalog/requests.service.d.ts +194 -118
  204. package/dist/catalog/requests.service.js +530 -343
  205. package/dist/catalog/reserved-names.d.ts +8 -0
  206. package/dist/catalog/reserved-names.js +42 -0
  207. package/dist/catalog/scope-orgs.d.ts +21 -0
  208. package/dist/catalog/scope-orgs.js +67 -0
  209. package/dist/catalog/scope-state.d.ts +35 -0
  210. package/dist/catalog/scope-state.js +87 -0
  211. package/dist/catalog/scope-sync-workers.d.ts +7 -0
  212. package/dist/catalog/scope-sync-workers.js +29 -0
  213. package/dist/catalog/scope-sync.d.ts +176 -0
  214. package/dist/catalog/scope-sync.js +576 -0
  215. package/dist/catalog/scope.d.ts +42 -0
  216. package/dist/catalog/scope.js +42 -0
  217. package/dist/catalog/unshare.d.ts +22 -0
  218. package/dist/catalog/unshare.js +119 -0
  219. package/dist/channels/actions.js +10 -3
  220. package/dist/channels/cards.d.ts +36 -10
  221. package/dist/channels/cards.js +100 -25
  222. package/dist/channels/channels.module.js +13 -2
  223. package/dist/channels/channels.schemas.d.ts +41 -0
  224. package/dist/channels/channels.schemas.js +40 -0
  225. package/dist/channels/connections.controller.d.ts +46 -37
  226. package/dist/channels/connections.controller.js +76 -34
  227. package/dist/channels/connections.service.d.ts +102 -10
  228. package/dist/channels/connections.service.js +271 -24
  229. package/dist/channels/inbound.d.ts +11 -1
  230. package/dist/channels/inbound.js +87 -7
  231. package/dist/channels/outbound.d.ts +14 -1
  232. package/dist/channels/outbound.js +64 -15
  233. package/dist/channels/phrases.d.ts +33 -2
  234. package/dist/channels/phrases.js +29 -1
  235. package/dist/channels/supervisor.d.ts +2 -0
  236. package/dist/channels/supervisor.js +4 -0
  237. package/dist/channels/threads.d.ts +5 -0
  238. package/dist/channels/threads.js +8 -0
  239. package/dist/channels/webhook.d.ts +21 -1
  240. package/dist/channels/webhook.js +39 -4
  241. package/dist/client/client-access.service.d.ts +102 -0
  242. package/dist/client/client-access.service.js +303 -0
  243. package/dist/client/client-builds.service.d.ts +109 -0
  244. package/dist/client/client-builds.service.js +229 -0
  245. package/dist/client/client-delivery.controller.d.ts +25 -0
  246. package/dist/client/client-delivery.controller.js +66 -0
  247. package/dist/client/client-files.d.ts +48 -0
  248. package/dist/client/client-files.js +136 -0
  249. package/dist/client/client-reports.cron.d.ts +13 -0
  250. package/dist/client/client-reports.cron.js +42 -0
  251. package/dist/client/client-reports.service.d.ts +30 -0
  252. package/dist/client/client-reports.service.js +102 -0
  253. package/dist/client/client-sign-in.service.d.ts +21 -0
  254. package/dist/client/client-sign-in.service.js +49 -0
  255. package/dist/client/client.controller.d.ts +49 -0
  256. package/dist/client/client.controller.js +129 -0
  257. package/dist/client/client.module.d.ts +8 -0
  258. package/dist/client/client.module.js +28 -0
  259. package/dist/client/client.schemas.d.ts +61 -0
  260. package/dist/client/client.schemas.js +27 -0
  261. package/dist/config/docs.js +5 -1
  262. package/dist/config/schema.d.ts +35 -2
  263. package/dist/config/schema.js +216 -21
  264. package/dist/conversations/access.d.ts +6 -4
  265. package/dist/conversations/access.js +29 -5
  266. package/dist/conversations/agent-tree.d.ts +46 -0
  267. package/dist/conversations/agent-tree.js +92 -0
  268. package/dist/conversations/artifacts.d.ts +1 -1
  269. package/dist/conversations/artifacts.js +1 -1
  270. package/dist/conversations/attachments.service.d.ts +30 -0
  271. package/dist/conversations/attachments.service.js +130 -5
  272. package/dist/conversations/conversations.controller.d.ts +79 -44
  273. package/dist/conversations/conversations.controller.js +133 -82
  274. package/dist/conversations/conversations.module.d.ts +1 -1
  275. package/dist/conversations/conversations.module.js +10 -7
  276. package/dist/conversations/conversations.schemas.d.ts +52 -0
  277. package/dist/conversations/conversations.schemas.js +79 -0
  278. package/dist/conversations/conversations.service.d.ts +161 -13
  279. package/dist/conversations/conversations.service.js +329 -57
  280. package/dist/conversations/device-status.d.ts +24 -0
  281. package/dist/conversations/device-status.js +71 -0
  282. package/dist/conversations/event-log.d.ts +45 -9
  283. package/dist/conversations/event-log.js +113 -6
  284. package/dist/conversations/events.d.ts +255 -9
  285. package/dist/conversations/events.js +250 -34
  286. package/dist/conversations/message-context.d.ts +79 -0
  287. package/dist/conversations/message-context.js +145 -0
  288. package/dist/conversations/queue.d.ts +5 -2
  289. package/dist/conversations/queue.js +24 -4
  290. package/dist/conversations/queue.service.d.ts +2 -2
  291. package/dist/conversations/queue.service.js +21 -3
  292. package/dist/conversations/titles.d.ts +12 -3
  293. package/dist/conversations/titles.js +40 -16
  294. package/dist/conversations/tree.d.ts +17 -0
  295. package/dist/conversations/tree.js +42 -0
  296. package/dist/ctx/create-ctx.d.ts +48 -5
  297. package/dist/ctx/create-ctx.js +174 -34
  298. package/dist/db/kernel-schema.d.ts +668 -27
  299. package/dist/db/pool.d.ts +5 -0
  300. package/dist/db/pool.js +3 -0
  301. package/dist/devices/access.d.ts +66 -0
  302. package/dist/devices/access.js +113 -0
  303. package/dist/devices/conversation-devices.d.ts +75 -0
  304. package/dist/devices/conversation-devices.js +230 -0
  305. package/dist/devices/devices.controller.d.ts +36 -0
  306. package/dist/devices/devices.controller.js +124 -0
  307. package/dist/devices/devices.module.d.ts +8 -0
  308. package/dist/devices/devices.module.js +34 -0
  309. package/dist/devices/devices.schemas.d.ts +3 -0
  310. package/dist/devices/devices.schemas.js +14 -0
  311. package/dist/devices/devices.service.d.ts +251 -0
  312. package/dist/devices/devices.service.js +791 -0
  313. package/dist/devices/dto.d.ts +25 -0
  314. package/dist/devices/dto.js +12 -0
  315. package/dist/devices/label.d.ts +11 -0
  316. package/dist/devices/label.js +25 -0
  317. package/dist/devices/legacy-cleanup.job.d.ts +34 -0
  318. package/dist/devices/legacy-cleanup.job.js +141 -0
  319. package/dist/errors.d.ts +215 -3
  320. package/dist/errors.js +215 -3
  321. package/dist/evals/evals.module.js +11 -2
  322. package/dist/evals/evals.schemas.d.ts +110 -0
  323. package/dist/evals/evals.schemas.js +107 -0
  324. package/dist/evals/reconstruct.d.ts +18 -9
  325. package/dist/evals/reconstruct.js +36 -10
  326. package/dist/evals/recorded-tools.d.ts +37 -1
  327. package/dist/evals/recorded-tools.js +120 -10
  328. package/dist/evals/run-replay.d.ts +20 -3
  329. package/dist/evals/run-replay.js +78 -14
  330. package/dist/evals/runs.controller.d.ts +2 -57
  331. package/dist/evals/runs.controller.js +1 -42
  332. package/dist/evals/runs.service.d.ts +8 -7
  333. package/dist/evals/runs.service.js +45 -30
  334. package/dist/evals/sets.controller.d.ts +2 -28
  335. package/dist/evals/sets.controller.js +1 -31
  336. package/dist/evals/sets.service.d.ts +7 -7
  337. package/dist/evals/sets.service.js +23 -17
  338. package/dist/evals/snapshot.d.ts +3 -2
  339. package/dist/evals/snapshot.js +17 -4
  340. package/dist/evals/step-replay.d.ts +4 -6
  341. package/dist/evals/step-replay.js +16 -9
  342. package/dist/evals/trajectory.d.ts +5 -3
  343. package/dist/evals/trajectory.js +4 -1
  344. package/dist/evals/trajectory.service.d.ts +8 -3
  345. package/dist/evals/trajectory.service.js +26 -14
  346. package/dist/evals/worker.d.ts +5 -5
  347. package/dist/evals/worker.js +9 -3
  348. package/dist/extensions/admin-ops.d.ts +81 -14
  349. package/dist/extensions/admin-ops.js +181 -47
  350. package/dist/extensions/admin-view.d.ts +57 -10
  351. package/dist/extensions/admin-view.js +249 -27
  352. package/dist/extensions/approvals.d.ts +12 -2
  353. package/dist/extensions/blobs.d.ts +14 -1
  354. package/dist/extensions/blobs.js +49 -5
  355. package/dist/extensions/bootstrap.d.ts +85 -10
  356. package/dist/extensions/bootstrap.js +215 -36
  357. package/dist/extensions/cli.d.ts +12 -0
  358. package/dist/extensions/cli.js +11 -2
  359. package/dist/extensions/config-hash.d.ts +10 -0
  360. package/dist/extensions/config-hash.js +38 -0
  361. package/dist/extensions/config-issues.d.ts +13 -1
  362. package/dist/extensions/config-issues.js +22 -5
  363. package/dist/extensions/config-json-schema.d.ts +43 -7
  364. package/dist/extensions/config-json-schema.js +124 -58
  365. package/dist/extensions/deployment-config-store.d.ts +6 -0
  366. package/dist/extensions/deployment-config.d.ts +94 -9
  367. package/dist/extensions/deployment-config.js +255 -34
  368. package/dist/extensions/display-name.d.ts +22 -0
  369. package/dist/extensions/display-name.js +77 -0
  370. package/dist/extensions/effective-config.d.ts +133 -0
  371. package/dist/extensions/effective-config.js +379 -0
  372. package/dist/extensions/extensions.module.js +31 -12
  373. package/dist/extensions/guide-places.d.ts +68 -0
  374. package/dist/extensions/guide-places.js +152 -0
  375. package/dist/extensions/hooks.d.ts +37 -4
  376. package/dist/extensions/hooks.js +82 -16
  377. package/dist/extensions/host.d.ts +105 -12
  378. package/dist/extensions/host.js +372 -87
  379. package/dist/extensions/installs.d.ts +30 -9
  380. package/dist/extensions/installs.js +57 -16
  381. package/dist/extensions/instance.d.ts +17 -2
  382. package/dist/extensions/instance.js +21 -0
  383. package/dist/extensions/ledger.d.ts +1 -1
  384. package/dist/extensions/locks.d.ts +12 -0
  385. package/dist/extensions/locks.js +26 -0
  386. package/dist/extensions/org-config.d.ts +97 -7
  387. package/dist/extensions/org-config.js +215 -45
  388. package/dist/extensions/org-levels.d.ts +37 -0
  389. package/dist/extensions/org-levels.js +71 -0
  390. package/dist/extensions/org-overrides.d.ts +151 -0
  391. package/dist/extensions/org-overrides.js +524 -0
  392. package/dist/extensions/package.d.ts +18 -4
  393. package/dist/extensions/package.js +56 -3
  394. package/dist/extensions/permission-set.d.ts +35 -5
  395. package/dist/extensions/permission-set.js +36 -5
  396. package/dist/extensions/permission-view.d.ts +106 -13
  397. package/dist/extensions/permission-view.js +33 -15
  398. package/dist/extensions/plugin-guides.d.ts +282 -0
  399. package/dist/extensions/plugin-guides.js +554 -0
  400. package/dist/extensions/plugin-icons.d.ts +54 -0
  401. package/dist/extensions/plugin-icons.js +125 -0
  402. package/dist/extensions/plugin-items.d.ts +21 -0
  403. package/dist/extensions/plugin-items.js +42 -0
  404. package/dist/extensions/point-defaults.controller.d.ts +28 -0
  405. package/dist/extensions/point-defaults.controller.js +69 -0
  406. package/dist/extensions/point-defaults.d.ts +73 -0
  407. package/dist/extensions/point-defaults.js +236 -0
  408. package/dist/extensions/point-defaults.schemas.d.ts +9 -0
  409. package/dist/extensions/point-defaults.schemas.js +14 -0
  410. package/dist/extensions/registry.d.ts +1 -1
  411. package/dist/extensions/registry.js +2 -0
  412. package/dist/extensions/resolve.d.ts +51 -1
  413. package/dist/extensions/resolve.js +85 -3
  414. package/dist/extensions/single-provider.d.ts +92 -0
  415. package/dist/extensions/single-provider.js +180 -0
  416. package/dist/extensions/sources.d.ts +13 -2
  417. package/dist/extensions/sources.js +2 -0
  418. package/dist/extensions/state.module.d.ts +9 -0
  419. package/dist/extensions/state.module.js +46 -0
  420. package/dist/extensions/unavailable.d.ts +50 -0
  421. package/dist/extensions/unavailable.js +115 -0
  422. package/dist/files/previewers.controller.js +2 -3
  423. package/dist/files/previewers.d.ts +10 -3
  424. package/dist/files/previewers.js +40 -11
  425. package/dist/files/previewers.schemas.d.ts +10 -0
  426. package/dist/files/previewers.schemas.js +9 -0
  427. package/dist/http/api.module.js +76 -4
  428. package/dist/http/app.d.ts +11 -2
  429. package/dist/http/app.js +31 -5
  430. package/dist/http/gateway-routes.d.ts +7 -3
  431. package/dist/http/gateway-routes.js +6 -3
  432. package/dist/http/nest-logger.d.ts +6 -5
  433. package/dist/http/nest-logger.js +24 -10
  434. package/dist/http/plugin-dispatch.d.ts +4 -1
  435. package/dist/http/plugin-dispatch.js +14 -2
  436. package/dist/identity/accounts.d.ts +77 -31
  437. package/dist/identity/accounts.js +133 -52
  438. package/dist/identity/audit.d.ts +2 -1
  439. package/dist/identity/auth.controller.js +9 -5
  440. package/dist/identity/auth.guard.d.ts +13 -5
  441. package/dist/identity/auth.guard.js +35 -9
  442. package/dist/identity/cookies.d.ts +26 -5
  443. package/dist/identity/cookies.js +58 -6
  444. package/dist/identity/identity.module.d.ts +1 -1
  445. package/dist/identity/identity.module.js +7 -4
  446. package/dist/identity/initial-passwords.controller.d.ts +22 -0
  447. package/dist/identity/initial-passwords.controller.js +49 -0
  448. package/dist/identity/initial-passwords.d.ts +61 -0
  449. package/dist/identity/initial-passwords.job.d.ts +16 -0
  450. package/dist/identity/initial-passwords.job.js +46 -0
  451. package/dist/identity/initial-passwords.js +159 -0
  452. package/dist/identity/me.controller.d.ts +17 -1
  453. package/dist/identity/me.controller.js +45 -4
  454. package/dist/identity/me.schemas.d.ts +24 -0
  455. package/dist/identity/me.schemas.js +25 -0
  456. package/dist/identity/principal.d.ts +11 -3
  457. package/dist/identity/principal.js +11 -3
  458. package/dist/identity/sessions.d.ts +12 -0
  459. package/dist/identity/sessions.js +45 -0
  460. package/dist/identity/settings.d.ts +99 -12
  461. package/dist/identity/settings.js +234 -25
  462. package/dist/identity/{enterprise-admin.d.ts → super-admin.d.ts} +5 -5
  463. package/dist/identity/{enterprise-admin.js → super-admin.js} +24 -24
  464. package/dist/identity/write-actor.d.ts +11 -0
  465. package/dist/identity/write-actor.js +7 -0
  466. package/dist/inbox/inbox.module.d.ts +4 -1
  467. package/dist/inbox/inbox.module.js +7 -3
  468. package/dist/inbox/inbox.schemas.d.ts +8 -0
  469. package/dist/inbox/inbox.schemas.js +11 -0
  470. package/dist/inbox/inbox.service.d.ts +64 -4
  471. package/dist/inbox/inbox.service.js +74 -4
  472. package/dist/inbox/org-notices.d.ts +63 -0
  473. package/dist/inbox/org-notices.js +91 -0
  474. package/dist/inbox/platform-inbox.controller.d.ts +23 -0
  475. package/dist/inbox/platform-inbox.controller.js +58 -0
  476. package/dist/inbox/platform-inbox.service.d.ts +157 -0
  477. package/dist/inbox/platform-inbox.service.js +281 -0
  478. package/dist/inbox/platform-notices.d.ts +19 -0
  479. package/dist/inbox/platform-notices.js +9 -0
  480. package/dist/index.d.ts +6 -2
  481. package/dist/index.js +7 -1
  482. package/dist/infra/cli/kernel-cli.module.js +9 -1
  483. package/dist/infra/config/kernel-config.service.js +32 -1
  484. package/dist/infra/database/database.module.js +1 -0
  485. package/dist/infra/database/xact-lock.d.ts +1 -1
  486. package/dist/infra/database/xact-lock.js +1 -1
  487. package/dist/infra/events/kernel-events.d.ts +31 -3
  488. package/dist/infra/lifecycle/process-guards.js +4 -0
  489. package/dist/infra/lock/lock.service.d.ts +8 -0
  490. package/dist/infra/lock/lock.service.js +27 -0
  491. package/dist/infra/logging/logging.module.d.ts +4 -2
  492. package/dist/infra/logging/logging.module.js +24 -6
  493. package/dist/infra/presence/presence.module.d.ts +6 -0
  494. package/dist/infra/presence/presence.module.js +22 -0
  495. package/dist/infra/presence/replica-presence.d.ts +87 -0
  496. package/dist/infra/presence/replica-presence.js +189 -0
  497. package/dist/infra/queue/add-job-once.d.ts +14 -0
  498. package/dist/infra/queue/add-job-once.js +16 -0
  499. package/dist/infra/queue/redis-connection.d.ts +6 -0
  500. package/dist/infra/queue/redis-connection.js +7 -0
  501. package/dist/infra/redis/redis.module.js +6 -2
  502. package/dist/infra/throttler/named-throttlers.d.ts +12 -0
  503. package/dist/infra/throttler/named-throttlers.js +67 -0
  504. package/dist/infra/throttler/throttler.guard.js +1 -1
  505. package/dist/infra/tokens.d.ts +6 -1
  506. package/dist/infra/tokens.js +6 -1
  507. package/dist/kernel.module.js +15 -0
  508. package/dist/lifecycle/kernel-lifecycle.d.ts +9 -3
  509. package/dist/lifecycle/kernel-lifecycle.js +51 -11
  510. package/dist/local-devices/device-auth.controller.d.ts +42 -0
  511. package/dist/local-devices/device-auth.controller.js +116 -0
  512. package/dist/local-devices/device-auth.d.ts +119 -0
  513. package/dist/local-devices/device-auth.js +401 -0
  514. package/dist/local-devices/device-auth.module.d.ts +7 -0
  515. package/dist/local-devices/device-auth.module.js +25 -0
  516. package/dist/local-devices/device-routes.d.ts +36 -0
  517. package/dist/local-devices/device-routes.js +90 -0
  518. package/dist/local-devices/dto.d.ts +66 -0
  519. package/dist/local-devices/dto.js +44 -0
  520. package/dist/local-devices/keys.d.ts +25 -0
  521. package/dist/local-devices/keys.js +25 -0
  522. package/dist/local-devices/local-device-gateway.d.ts +134 -0
  523. package/dist/local-devices/local-device-gateway.js +542 -0
  524. package/dist/local-devices/local-device-provider.d.ts +89 -0
  525. package/dist/local-devices/local-device-provider.js +151 -0
  526. package/dist/local-devices/local-devices.module.d.ts +16 -0
  527. package/dist/local-devices/local-devices.module.js +44 -0
  528. package/dist/local-devices/machines.d.ts +118 -0
  529. package/dist/local-devices/machines.js +366 -0
  530. package/dist/local-devices/relay.d.ts +100 -0
  531. package/dist/local-devices/relay.js +373 -0
  532. package/dist/local-devices/targets.d.ts +28 -0
  533. package/dist/local-devices/targets.js +73 -0
  534. package/dist/log.d.ts +13 -1
  535. package/dist/log.js +93 -17
  536. package/dist/models/embeddings.d.ts +82 -0
  537. package/dist/models/embeddings.js +326 -0
  538. package/dist/models/enablement.controller.d.ts +40 -0
  539. package/dist/models/enablement.controller.js +74 -0
  540. package/dist/models/enablement.d.ts +101 -0
  541. package/dist/models/enablement.js +264 -0
  542. package/dist/models/models.module.d.ts +5 -1
  543. package/dist/models/models.module.js +16 -4
  544. package/dist/models/org-models.schemas.d.ts +8 -0
  545. package/dist/models/org-models.schemas.js +22 -0
  546. package/dist/models/prices.d.ts +8 -6
  547. package/dist/models/prices.js +11 -9
  548. package/dist/models/purposes.controller.d.ts +6 -4
  549. package/dist/models/purposes.controller.js +13 -7
  550. package/dist/models/purposes.d.ts +72 -14
  551. package/dist/models/purposes.js +115 -34
  552. package/dist/orgs/directory-sync.d.ts +14 -5
  553. package/dist/orgs/directory-sync.js +41 -17
  554. package/dist/orgs/offboarding.d.ts +12 -8
  555. package/dist/orgs/offboarding.js +54 -33
  556. package/dist/orgs/org-lock.d.ts +5 -0
  557. package/dist/orgs/org-lock.js +13 -0
  558. package/dist/orgs/org.guard.d.ts +10 -0
  559. package/dist/orgs/org.guard.js +43 -32
  560. package/dist/orgs/orgs.controller.d.ts +2 -5
  561. package/dist/orgs/orgs.controller.js +3 -6
  562. package/dist/orgs/orgs.module.js +3 -0
  563. package/dist/orgs/orgs.schemas.d.ts +8 -0
  564. package/dist/orgs/orgs.schemas.js +16 -0
  565. package/dist/orgs/orgs.service.d.ts +23 -8
  566. package/dist/orgs/orgs.service.js +38 -16
  567. package/dist/orgs/roles.d.ts +1 -1
  568. package/dist/orgs/roles.js +5 -1
  569. package/dist/orgs/settings.controller.d.ts +1 -1
  570. package/dist/orgs/settings.service.d.ts +66 -6
  571. package/dist/orgs/settings.service.js +89 -10
  572. package/dist/overrides.d.ts +16 -1
  573. package/dist/overrides.js +10 -0
  574. package/dist/platform/actor.d.ts +48 -0
  575. package/dist/platform/actor.js +100 -0
  576. package/dist/platform/agent-docs.d.ts +18 -0
  577. package/dist/platform/agent-docs.js +59 -0
  578. package/dist/platform/availability.d.ts +14 -0
  579. package/dist/platform/availability.js +43 -0
  580. package/dist/platform/errors.d.ts +28 -0
  581. package/dist/platform/errors.js +65 -0
  582. package/dist/platform/exclusions.d.ts +11 -0
  583. package/dist/platform/exclusions.js +774 -0
  584. package/dist/platform/method.d.ts +6 -0
  585. package/dist/platform/method.js +15 -0
  586. package/dist/platform/operation.d.ts +169 -0
  587. package/dist/platform/operation.js +102 -0
  588. package/dist/platform/ops/accounts.ops.d.ts +32 -0
  589. package/dist/platform/ops/accounts.ops.js +291 -0
  590. package/dist/platform/ops/admin-items.ops.d.ts +37 -0
  591. package/dist/platform/ops/admin-items.ops.js +278 -0
  592. package/dist/platform/ops/admin.ops.d.ts +38 -0
  593. package/dist/platform/ops/admin.ops.js +497 -0
  594. package/dist/platform/ops/agent-skills.ops.d.ts +50 -0
  595. package/dist/platform/ops/agent-skills.ops.js +509 -0
  596. package/dist/platform/ops/agent-templates.ops.d.ts +17 -0
  597. package/dist/platform/ops/agent-templates.ops.js +272 -0
  598. package/dist/platform/ops/agents.ops.d.ts +37 -0
  599. package/dist/platform/ops/agents.ops.js +730 -0
  600. package/dist/platform/ops/approvals.ops.d.ts +30 -0
  601. package/dist/platform/ops/approvals.ops.js +116 -0
  602. package/dist/platform/ops/background.ops.d.ts +14 -0
  603. package/dist/platform/ops/background.ops.js +134 -0
  604. package/dist/platform/ops/catalog-admin.ops.d.ts +92 -0
  605. package/dist/platform/ops/catalog-admin.ops.js +682 -0
  606. package/dist/platform/ops/channels.ops.d.ts +16 -0
  607. package/dist/platform/ops/channels.ops.js +195 -0
  608. package/dist/platform/ops/components.ops.d.ts +46 -0
  609. package/dist/platform/ops/components.ops.js +854 -0
  610. package/dist/platform/ops/connectors.ops.d.ts +17 -0
  611. package/dist/platform/ops/connectors.ops.js +190 -0
  612. package/dist/platform/ops/conversations.ops.d.ts +30 -0
  613. package/dist/platform/ops/conversations.ops.js +470 -0
  614. package/dist/platform/ops/devices.ops.d.ts +26 -0
  615. package/dist/platform/ops/devices.ops.js +311 -0
  616. package/dist/platform/ops/errors.d.ts +16 -0
  617. package/dist/platform/ops/errors.js +30 -0
  618. package/dist/platform/ops/evals.ops.d.ts +28 -0
  619. package/dist/platform/ops/evals.ops.js +783 -0
  620. package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
  621. package/dist/platform/ops/extensions-admin.ops.js +372 -0
  622. package/dist/platform/ops/extensions.ops.d.ts +25 -0
  623. package/dist/platform/ops/extensions.ops.js +347 -0
  624. package/dist/platform/ops/inbox.ops.d.ts +25 -0
  625. package/dist/platform/ops/inbox.ops.js +381 -0
  626. package/dist/platform/ops/marketplaces.ops.d.ts +22 -0
  627. package/dist/platform/ops/marketplaces.ops.js +466 -0
  628. package/dist/platform/ops/models.ops.d.ts +25 -0
  629. package/dist/platform/ops/models.ops.js +232 -0
  630. package/dist/platform/ops/org-plugins.ops.d.ts +35 -0
  631. package/dist/platform/ops/org-plugins.ops.js +388 -0
  632. package/dist/platform/ops/org-settings.ops.d.ts +18 -0
  633. package/dist/platform/ops/org-settings.ops.js +127 -0
  634. package/dist/platform/ops/orgs.ops.d.ts +28 -0
  635. package/dist/platform/ops/orgs.ops.js +298 -0
  636. package/dist/platform/ops/other-orgs.d.ts +20 -0
  637. package/dist/platform/ops/other-orgs.js +72 -0
  638. package/dist/platform/ops/paging.d.ts +14 -0
  639. package/dist/platform/ops/paging.js +20 -0
  640. package/dist/platform/ops/platform.ops.d.ts +30 -0
  641. package/dist/platform/ops/platform.ops.js +231 -0
  642. package/dist/platform/ops/plugins.ops.d.ts +35 -0
  643. package/dist/platform/ops/plugins.ops.js +476 -0
  644. package/dist/platform/ops/previewers.ops.d.ts +14 -0
  645. package/dist/platform/ops/previewers.ops.js +109 -0
  646. package/dist/platform/ops/requests.ops.d.ts +14 -0
  647. package/dist/platform/ops/requests.ops.js +191 -0
  648. package/dist/platform/ops/role.d.ts +4 -0
  649. package/dist/platform/ops/role.js +10 -0
  650. package/dist/platform/ops/setup.ops.d.ts +24 -0
  651. package/dist/platform/ops/setup.ops.js +212 -0
  652. package/dist/platform/ops/skills.ops.d.ts +17 -0
  653. package/dist/platform/ops/skills.ops.js +160 -0
  654. package/dist/platform/ops/summary.d.ts +10 -0
  655. package/dist/platform/ops/summary.js +18 -0
  656. package/dist/platform/ops/themes.ops.d.ts +14 -0
  657. package/dist/platform/ops/themes.ops.js +47 -0
  658. package/dist/platform/ops/ui.ops.d.ts +8 -0
  659. package/dist/platform/ops/ui.ops.js +41 -0
  660. package/dist/platform/ops/unavailable.d.ts +23 -0
  661. package/dist/platform/ops/unavailable.js +118 -0
  662. package/dist/platform/parity.d.ts +33 -0
  663. package/dist/platform/parity.js +272 -0
  664. package/dist/platform/platform-ops.module.d.ts +43 -0
  665. package/dist/platform/platform-ops.module.js +142 -0
  666. package/dist/platform/platform.module.d.ts +8 -0
  667. package/dist/platform/platform.module.js +25 -0
  668. package/dist/platform/registry.d.ts +30 -0
  669. package/dist/platform/registry.js +111 -0
  670. package/dist/platform/route-schemas.d.ts +18 -0
  671. package/dist/platform/route-schemas.js +85 -0
  672. package/dist/roles/gateway-role.d.ts +18 -3
  673. package/dist/roles/gateway-role.js +33 -5
  674. package/dist/roles/gateway.module.d.ts +2 -1
  675. package/dist/roles/gateway.module.js +6 -3
  676. package/dist/roles/worker-role.d.ts +6 -4
  677. package/dist/roles/worker-role.js +14 -7
  678. package/dist/roles/worker.module.d.ts +1 -1
  679. package/dist/roles/worker.module.js +21 -1
  680. package/dist/runtime/context/build.d.ts +21 -13
  681. package/dist/runtime/context/build.js +106 -29
  682. package/dist/runtime/context/claude-tools.d.ts +4 -1
  683. package/dist/runtime/context/claude-tools.js +13 -12
  684. package/dist/runtime/context/compaction.js +24 -1
  685. package/dist/runtime/context/device-paths.d.ts +40 -0
  686. package/dist/runtime/context/device-paths.js +48 -0
  687. package/dist/runtime/context/legacy-text.d.ts +22 -0
  688. package/dist/runtime/context/legacy-text.js +37 -0
  689. package/dist/runtime/context/reminders.d.ts +2 -0
  690. package/dist/runtime/context/reminders.js +2 -0
  691. package/dist/runtime/context/run-context.d.ts +65 -0
  692. package/dist/runtime/context/run-context.js +215 -0
  693. package/dist/runtime/context/skills.d.ts +29 -11
  694. package/dist/runtime/context/skills.js +46 -32
  695. package/dist/runtime/context/tool-changes.d.ts +27 -0
  696. package/dist/runtime/context/tool-changes.js +60 -0
  697. package/dist/runtime/hook-calls.d.ts +8 -1
  698. package/dist/runtime/hook-calls.js +40 -7
  699. package/dist/runtime/langgraph-loop.d.ts +3 -1
  700. package/dist/runtime/langgraph-loop.js +36 -17
  701. package/dist/runtime/loop.d.ts +35 -6
  702. package/dist/runtime/maintenance.d.ts +9 -4
  703. package/dist/runtime/maintenance.js +35 -8
  704. package/dist/runtime/model-call.d.ts +54 -11
  705. package/dist/runtime/model-call.js +105 -28
  706. package/dist/runtime/providers.d.ts +149 -29
  707. package/dist/runtime/providers.js +332 -63
  708. package/dist/runtime/run-context.service.d.ts +65 -0
  709. package/dist/runtime/run-context.service.js +236 -0
  710. package/dist/runtime/run-control.d.ts +11 -1
  711. package/dist/runtime/run-control.js +12 -0
  712. package/dist/runtime/run-drafts.d.ts +85 -0
  713. package/dist/runtime/run-drafts.js +230 -0
  714. package/dist/runtime/run-finish.d.ts +1 -1
  715. package/dist/runtime/run-jobs.d.ts +3 -5
  716. package/dist/runtime/run-jobs.js +7 -9
  717. package/dist/runtime/run-queue.d.ts +62 -5
  718. package/dist/runtime/run-queue.js +313 -40
  719. package/dist/runtime/run-worker.d.ts +19 -8
  720. package/dist/runtime/run-worker.js +105 -44
  721. package/dist/runtime/runtime.module.js +13 -3
  722. package/dist/runtime/step-log.d.ts +15 -4
  723. package/dist/runtime/step-log.js +24 -7
  724. package/dist/runtime/stream.controller.d.ts +23 -1
  725. package/dist/runtime/stream.controller.js +60 -3
  726. package/dist/runtime/stream.d.ts +4 -1
  727. package/dist/runtime/stream.js +27 -3
  728. package/dist/runtime/subagents/child.d.ts +55 -7
  729. package/dist/runtime/subagents/child.js +105 -7
  730. package/dist/runtime/subagents/definition.d.ts +31 -26
  731. package/dist/runtime/subagents/definition.js +89 -142
  732. package/dist/runtime/subagents/deliveries.d.ts +71 -0
  733. package/dist/runtime/subagents/deliveries.js +228 -0
  734. package/dist/runtime/subagents/dispatch.d.ts +116 -27
  735. package/dist/runtime/subagents/dispatch.js +213 -142
  736. package/dist/runtime/subagents/limits.d.ts +24 -5
  737. package/dist/runtime/subagents/limits.js +40 -6
  738. package/dist/runtime/subagents/messages.d.ts +95 -0
  739. package/dist/runtime/subagents/messages.js +328 -0
  740. package/dist/runtime/subagents/org-agents.js +2 -1
  741. package/dist/runtime/subagents/preamble.d.ts +4 -4
  742. package/dist/runtime/subagents/preamble.js +9 -7
  743. package/dist/runtime/subagents/progress.d.ts +8 -6
  744. package/dist/runtime/subagents/progress.js +11 -6
  745. package/dist/runtime/subagents/render.d.ts +30 -0
  746. package/dist/runtime/subagents/render.js +53 -0
  747. package/dist/runtime/subagents/roster.d.ts +25 -8
  748. package/dist/runtime/subagents/roster.js +48 -12
  749. package/dist/runtime/subagents/skill-fork.d.ts +4 -3
  750. package/dist/runtime/subagents/skill-fork.js +9 -5
  751. package/dist/runtime/subagents/status.d.ts +14 -0
  752. package/dist/runtime/subagents/status.js +23 -0
  753. package/dist/runtime/subagents/subagents.service.d.ts +9 -6
  754. package/dist/runtime/subagents/subagents.service.js +13 -8
  755. package/dist/runtime/usage-report-jobs.d.ts +88 -0
  756. package/dist/runtime/usage-report-jobs.js +158 -0
  757. package/dist/runtime/usage-report.d.ts +35 -39
  758. package/dist/runtime/usage-report.js +171 -97
  759. package/dist/runtime/waits.d.ts +148 -39
  760. package/dist/runtime/waits.js +426 -112
  761. package/dist/sandbox/jobs.d.ts +40 -13
  762. package/dist/sandbox/jobs.js +57 -20
  763. package/dist/sandbox/leases.d.ts +37 -54
  764. package/dist/sandbox/leases.js +71 -115
  765. package/dist/sandbox/providers.d.ts +34 -7
  766. package/dist/sandbox/providers.js +54 -9
  767. package/dist/sandbox/sandbox-file-reader.d.ts +35 -0
  768. package/dist/sandbox/sandbox-file-reader.js +98 -0
  769. package/dist/sandbox/sandbox.module.d.ts +3 -2
  770. package/dist/sandbox/sandbox.module.js +10 -4
  771. package/dist/sandbox/sandbox.service.d.ts +345 -132
  772. package/dist/sandbox/sandbox.service.js +883 -399
  773. package/dist/sandbox/unreachable.d.ts +30 -0
  774. package/dist/sandbox/unreachable.js +108 -0
  775. package/dist/setup/kernel-checks.d.ts +91 -0
  776. package/dist/setup/kernel-checks.js +295 -0
  777. package/dist/setup/oauth-token-probe.d.ts +47 -0
  778. package/dist/setup/oauth-token-probe.js +108 -0
  779. package/dist/setup/redact-check.d.ts +18 -0
  780. package/dist/setup/redact-check.js +46 -0
  781. package/dist/setup/setup-check-registry.d.ts +86 -0
  782. package/dist/setup/setup-check-registry.js +75 -0
  783. package/dist/setup/setup-checks.controller.d.ts +28 -0
  784. package/dist/setup/setup-checks.controller.js +78 -0
  785. package/dist/setup/setup-checks.schemas.d.ts +38 -0
  786. package/dist/setup/setup-checks.schemas.js +43 -0
  787. package/dist/setup/setup-checks.service.d.ts +144 -0
  788. package/dist/setup/setup-checks.service.js +683 -0
  789. package/dist/setup/setup-guides.controller.d.ts +18 -0
  790. package/dist/setup/setup-guides.controller.js +48 -0
  791. package/dist/setup/setup-guides.schemas.d.ts +10 -0
  792. package/dist/setup/setup-guides.schemas.js +6 -0
  793. package/dist/setup/setup-guides.service.d.ts +126 -0
  794. package/dist/setup/setup-guides.service.js +315 -0
  795. package/dist/setup/setup.module.d.ts +8 -0
  796. package/dist/setup/setup.module.js +31 -0
  797. package/dist/skills/agent-skills.controller.d.ts +48 -0
  798. package/dist/skills/agent-skills.controller.js +131 -0
  799. package/dist/skills/agent-skills.service.d.ts +262 -0
  800. package/dist/skills/agent-skills.service.js +996 -0
  801. package/dist/skills/catalog.d.ts +14 -11
  802. package/dist/skills/catalog.js +32 -50
  803. package/dist/skills/changes.controller.d.ts +12 -22
  804. package/dist/skills/changes.controller.js +27 -56
  805. package/dist/skills/changes.service.d.ts +69 -115
  806. package/dist/skills/changes.service.js +249 -598
  807. package/dist/skills/conversation-catalog.d.ts +53 -0
  808. package/dist/skills/conversation-catalog.js +149 -0
  809. package/dist/skills/invocable.controller.d.ts +1 -1
  810. package/dist/skills/invocable.controller.js +2 -2
  811. package/dist/skills/invocation-keys.d.ts +1 -1
  812. package/dist/skills/invocation-keys.js +1 -1
  813. package/dist/skills/invoke.d.ts +3 -3
  814. package/dist/skills/invoke.js +21 -8
  815. package/dist/skills/package.d.ts +15 -1
  816. package/dist/skills/package.js +14 -1
  817. package/dist/skills/skills.controller.d.ts +32 -6
  818. package/dist/skills/skills.controller.js +64 -11
  819. package/dist/skills/skills.module.js +25 -3
  820. package/dist/skills/skills.schemas.d.ts +44 -0
  821. package/dist/skills/skills.schemas.js +68 -0
  822. package/dist/skills/skills.service.d.ts +123 -26
  823. package/dist/skills/skills.service.js +493 -76
  824. package/dist/skills/usable.d.ts +82 -0
  825. package/dist/skills/usable.js +388 -0
  826. package/dist/themes/render-css.d.ts +13 -0
  827. package/dist/themes/render-css.js +135 -0
  828. package/dist/themes/theme-delivery.service.d.ts +36 -0
  829. package/dist/themes/theme-delivery.service.js +116 -0
  830. package/dist/themes/theme-state.d.ts +116 -0
  831. package/dist/themes/theme-state.js +221 -0
  832. package/dist/themes/theme-usage.d.ts +61 -0
  833. package/dist/themes/theme-usage.js +98 -0
  834. package/dist/themes/themes-public.controller.d.ts +33 -0
  835. package/dist/themes/themes-public.controller.js +98 -0
  836. package/dist/themes/themes.controller.d.ts +13 -0
  837. package/dist/themes/themes.controller.js +38 -0
  838. package/dist/themes/themes.module.d.ts +3 -0
  839. package/dist/themes/themes.module.js +21 -0
  840. package/dist/themes/themes.schemas.d.ts +3 -0
  841. package/dist/themes/themes.schemas.js +2 -0
  842. package/dist/themes/themes.service.d.ts +50 -0
  843. package/dist/themes/themes.service.js +99 -0
  844. package/dist/time-zone.d.ts +5 -0
  845. package/dist/time-zone.js +19 -0
  846. package/dist/tools/admin-connectors.d.ts +69 -0
  847. package/dist/tools/admin-connectors.js +135 -0
  848. package/dist/tools/approvals.controller.js +2 -3
  849. package/dist/tools/approvals.schemas.d.ts +21 -0
  850. package/dist/tools/approvals.schemas.js +15 -0
  851. package/dist/tools/approvals.service.d.ts +26 -2
  852. package/dist/tools/approvals.service.js +44 -5
  853. package/dist/tools/builtin-names.d.ts +104 -0
  854. package/dist/tools/builtin-names.js +164 -0
  855. package/dist/tools/builtins/agent.d.ts +27 -25
  856. package/dist/tools/builtins/agent.js +66 -63
  857. package/dist/tools/builtins/ask-user.d.ts +1 -1
  858. package/dist/tools/builtins/ask-user.js +5 -4
  859. package/dist/tools/builtins/builtin-tools.d.ts +23 -4
  860. package/dist/tools/builtins/builtin-tools.js +78 -12
  861. package/dist/tools/builtins/current-time.d.ts +26 -0
  862. package/dist/tools/builtins/current-time.js +99 -0
  863. package/dist/tools/builtins/handback.d.ts +28 -0
  864. package/dist/tools/builtins/handback.js +53 -0
  865. package/dist/tools/builtins/platform.d.ts +51 -0
  866. package/dist/tools/builtins/platform.js +451 -0
  867. package/dist/tools/builtins/read-tool-output.d.ts +1 -1
  868. package/dist/tools/builtins/read-tool-output.js +2 -2
  869. package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
  870. package/dist/tools/builtins/sandbox/bash.js +291 -39
  871. package/dist/tools/builtins/sandbox/common.d.ts +135 -36
  872. package/dist/tools/builtins/sandbox/common.js +222 -62
  873. package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
  874. package/dist/tools/builtins/sandbox/deliver.js +19 -16
  875. package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
  876. package/dist/tools/builtins/sandbox/edit.js +64 -50
  877. package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
  878. package/dist/tools/builtins/sandbox/file-state.js +34 -0
  879. package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
  880. package/dist/tools/builtins/sandbox/glob-match.js +1 -1
  881. package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
  882. package/dist/tools/builtins/sandbox/glob.js +17 -12
  883. package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
  884. package/dist/tools/builtins/sandbox/grep.js +153 -34
  885. package/dist/tools/builtins/sandbox/index.d.ts +9 -5
  886. package/dist/tools/builtins/sandbox/index.js +13 -5
  887. package/dist/tools/builtins/sandbox/read.d.ts +2 -2
  888. package/dist/tools/builtins/sandbox/read.js +29 -19
  889. package/dist/tools/builtins/sandbox/task-output.d.ts +79 -0
  890. package/dist/tools/builtins/sandbox/task-output.js +334 -0
  891. package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
  892. package/dist/tools/builtins/sandbox/task-stop.js +113 -0
  893. package/dist/tools/builtins/sandbox/write.d.ts +1 -1
  894. package/dist/tools/builtins/sandbox/write.js +51 -44
  895. package/dist/tools/builtins/send-message.d.ts +56 -0
  896. package/dist/tools/builtins/send-message.js +100 -0
  897. package/dist/tools/builtins/skill-load.d.ts +29 -18
  898. package/dist/tools/builtins/skill-load.js +125 -73
  899. package/dist/tools/builtins/tool-search.d.ts +13 -9
  900. package/dist/tools/builtins/tool-search.js +25 -14
  901. package/dist/tools/builtins/web/errors.d.ts +8 -0
  902. package/dist/tools/builtins/web/errors.js +53 -0
  903. package/dist/tools/builtins/web/extract.d.ts +62 -0
  904. package/dist/tools/builtins/web/extract.js +271 -0
  905. package/dist/tools/builtins/web/fetch.d.ts +55 -0
  906. package/dist/tools/builtins/web/fetch.js +175 -0
  907. package/dist/tools/builtins/web/index.d.ts +13 -0
  908. package/dist/tools/builtins/web/index.js +12 -0
  909. package/dist/tools/builtins/web/page-cache.d.ts +25 -0
  910. package/dist/tools/builtins/web/page-cache.js +77 -0
  911. package/dist/tools/builtins/web/search.d.ts +25 -0
  912. package/dist/tools/builtins/web/search.js +210 -0
  913. package/dist/tools/builtins/web/url.d.ts +17 -0
  914. package/dist/tools/builtins/web/url.js +43 -0
  915. package/dist/tools/connector-account-policies.d.ts +51 -0
  916. package/dist/tools/connector-account-policies.js +165 -0
  917. package/dist/tools/connectors.controller.d.ts +74 -9
  918. package/dist/tools/connectors.controller.js +133 -16
  919. package/dist/tools/connectors.schemas.d.ts +27 -0
  920. package/dist/tools/connectors.schemas.js +34 -0
  921. package/dist/tools/connectors.service.d.ts +101 -8
  922. package/dist/tools/connectors.service.js +266 -28
  923. package/dist/tools/credentials.d.ts +23 -0
  924. package/dist/tools/credentials.js +90 -1
  925. package/dist/tools/display-names.d.ts +9 -0
  926. package/dist/tools/display-names.js +24 -0
  927. package/dist/tools/drift.js +5 -5
  928. package/dist/tools/elicitation.js +1 -1
  929. package/dist/tools/extension-tools.controller.d.ts +14 -0
  930. package/dist/tools/extension-tools.controller.js +37 -0
  931. package/dist/tools/info.d.ts +61 -4
  932. package/dist/tools/info.js +119 -33
  933. package/dist/tools/legacy-data.d.ts +34 -0
  934. package/dist/tools/legacy-data.js +76 -0
  935. package/dist/tools/legacy-keys.d.ts +51 -0
  936. package/dist/tools/legacy-keys.js +114 -0
  937. package/dist/tools/naming.d.ts +1 -5
  938. package/dist/tools/naming.js +1 -7
  939. package/dist/tools/oauth/flow-paths.d.ts +1 -1
  940. package/dist/tools/oauth/flow-paths.js +1 -1
  941. package/dist/tools/oauth/flow.js +1 -1
  942. package/dist/tools/oauth/tokens.d.ts +54 -7
  943. package/dist/tools/oauth/tokens.js +87 -17
  944. package/dist/tools/org-tool-switches.d.ts +89 -0
  945. package/dist/tools/org-tool-switches.js +201 -0
  946. package/dist/tools/outputs.js +1 -1
  947. package/dist/tools/pipeline.d.ts +67 -47
  948. package/dist/tools/pipeline.js +319 -380
  949. package/dist/tools/policy.d.ts +30 -23
  950. package/dist/tools/policy.js +142 -64
  951. package/dist/tools/questions.controller.d.ts +1 -1
  952. package/dist/tools/questions.controller.js +1 -1
  953. package/dist/tools/questions.service.d.ts +23 -2
  954. package/dist/tools/questions.service.js +104 -2
  955. package/dist/tools/registry.d.ts +189 -68
  956. package/dist/tools/registry.js +318 -236
  957. package/dist/tools/resources.d.ts +1 -1
  958. package/dist/tools/resources.js +1 -1
  959. package/dist/tools/tools.module.js +31 -3
  960. package/dist/tools/validate.js +1 -1
  961. package/dist/ui/admin-ui.controller.d.ts +56 -0
  962. package/dist/ui/admin-ui.controller.js +192 -0
  963. package/dist/ui/arrangement.d.ts +65 -0
  964. package/dist/ui/arrangement.js +171 -0
  965. package/dist/ui/embed-token.d.ts +2 -2
  966. package/dist/ui/embed-token.js +30 -5
  967. package/dist/ui/registry.d.ts +42 -17
  968. package/dist/ui/registry.js +46 -14
  969. package/dist/ui/slots.controller.d.ts +11 -0
  970. package/dist/ui/slots.controller.js +25 -0
  971. package/dist/ui/ui-stream.d.ts +20 -3
  972. package/dist/ui/ui-stream.js +25 -7
  973. package/dist/ui/ui.schemas.d.ts +70 -0
  974. package/dist/ui/ui.schemas.js +65 -0
  975. package/dist/ui/views.controller.d.ts +35 -49
  976. package/dist/ui/views.controller.js +48 -70
  977. package/dist/ui/views.d.ts +112 -18
  978. package/dist/ui/views.js +254 -47
  979. package/package.json +6 -3
  980. package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
  981. package/src/migrations/0064_account_last_org.sql +7 -0
  982. package/src/migrations/0065_conversation_archive.sql +8 -0
  983. package/src/migrations/0066_extension_display_name.sql +4 -0
  984. package/src/migrations/0067_agent_profiles.sql +20 -0
  985. package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
  986. package/src/migrations/0069_attachments_agent_idx.sql +3 -0
  987. package/src/migrations/0070_background_tasks.sql +37 -0
  988. package/src/migrations/0071_background_tasks_reserve.sql +6 -0
  989. package/src/migrations/0072_background_tasks_stopping.sql +5 -0
  990. package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
  991. package/src/migrations/0074_subagent_tree.sql +50 -0
  992. package/src/migrations/0075_plugin_scope.sql +61 -0
  993. package/src/migrations/0076_skills_created_by_nullable.sql +6 -0
  994. package/src/migrations/0077_scope_requests.sql +52 -0
  995. package/src/migrations/0078_scope_grant_switches.sql +18 -0
  996. package/src/migrations/0079_scope_live_install_switches.sql +19 -0
  997. package/src/migrations/0080_rename_enterprise_admin.sql +18 -0
  998. package/src/migrations/0081_platform_components.sql +129 -0
  999. package/src/migrations/0082_platform_migration.sql +33 -0
  1000. package/src/migrations/0083_plugin_scope_sync_failures.sql +15 -0
  1001. package/src/migrations/0084_org_owned_items.sql +85 -0
  1002. package/src/migrations/0085_agent_templates_phase4.sql +45 -0
  1003. package/src/migrations/0086_org_layering.sql +30 -0
  1004. package/src/migrations/0087_approval_summary.sql +6 -0
  1005. package/src/migrations/0088_environments.sql +80 -0
  1006. package/src/migrations/0089_model_kinds_usage.sql +38 -0
  1007. package/src/migrations/0090_initial_passwords.sql +27 -0
  1008. package/src/migrations/0091_account_time_zone.sql +4 -0
  1009. package/src/migrations/0092_tools_default_on.sql +27 -0
  1010. package/src/migrations/0093_connected_environments.sql +37 -0
  1011. package/src/migrations/0094_environment_paths_idx.sql +7 -0
  1012. package/src/migrations/0095_environment_files_resets.sql +5 -0
  1013. package/src/migrations/0096_environment_demoted_default.sql +18 -0
  1014. package/src/migrations/0097_extension_installs_enabled_at.sql +16 -0
  1015. package/src/migrations/0098_single_provider_running_first.sql +41 -0
  1016. package/src/migrations/0099_channel_connection_guide_ack.sql +6 -0
  1017. package/src/migrations/0100_catalog_files.sql +13 -0
  1018. package/src/migrations/0101_marketplace_icons.sql +32 -0
  1019. package/src/migrations/0102_themes.sql +64 -0
  1020. package/src/migrations/0103_ui_theme_setting.sql +7 -0
  1021. package/src/migrations/0104_connector_tool_account_policies.sql +16 -0
  1022. package/src/migrations/0105_devices_rename.sql +136 -0
  1023. package/src/migrations/0106_setup_guides_v2.sql +10 -0
  1024. package/src/migrations/0107_extension_client_builds.sql +50 -0
  1025. package/src/migrations/0108_question_skipped.sql +6 -0
  1026. package/src/migrations/0109_audit_platform_idx.sql +5 -0
  1027. package/src/migrations/0110_usage_time_idx.sql +8 -0
  1028. package/src/migrations/0111_agent_skill_sharing.sql +22 -0
  1029. package/src/migrations/0112_skill_share_requests.sql +4 -0
  1030. package/dist/catalog/upgrade-targets.d.ts +0 -56
  1031. package/dist/catalog/upgrade-targets.js +0 -90
  1032. package/dist/conversations/sandbox-status.d.ts +0 -24
  1033. package/dist/conversations/sandbox-status.js +0 -52
  1034. package/dist/extensions/org-config.controller.d.ts +0 -24
  1035. package/dist/extensions/org-config.controller.js +0 -62
  1036. package/dist/tools/builtins/sandbox/names.d.ts +0 -7
  1037. package/dist/tools/builtins/sandbox/names.js +0 -20
  1038. package/dist/tools/builtins/skill-write.d.ts +0 -59
  1039. package/dist/tools/builtins/skill-write.js +0 -244
@@ -8,14 +8,18 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { createHash, randomUUID } from "node:crypto";
11
- import { PLUGIN_MANIFEST_FILE, parseSkillMd, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
11
+ import { appearanceIssues, PLUGIN_MANIFEST_FILE, parseSkillMd, pluginDescription, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
12
+ import { getQueueToken } from "@nestjs/bullmq";
12
13
  import { Inject, Injectable } from "@nestjs/common";
13
14
  import { sql } from "kysely";
14
15
  import semver from "semver";
16
+ import { ClientBuilds } from "../client/client-builds.service.js";
17
+ import { checkClientFiles } from "../client/client-files.js";
15
18
  import { ApiError } from "../errors.js";
16
19
  import { ExtensionAdminOps } from "../extensions/admin-ops.js";
20
+ import { ExtensionAdmin } from "../extensions/admin-view.js";
17
21
  import { writeSnapshot } from "../extensions/approvals.js";
18
- import { ExtensionBlobs } from "../extensions/blobs.js";
22
+ import { blobKey, ExtensionBlobs } from "../extensions/blobs.js";
19
23
  import { ExtensionInstalls } from "../extensions/installs.js";
20
24
  import { PluginApproveLock, PluginInstallLock } from "../extensions/locks.js";
21
25
  import { unrunMigrations } from "../extensions/migrate-lock.js";
@@ -24,28 +28,41 @@ import { diffPermissions, permissionKeys, WARNINGS_KEY_PREFIX, } from "../extens
24
28
  import { reviewHash as extensionReviewHash, migrationWarnings, permissionGroups, permissionKeyItems, } from "../extensions/permission-view.js";
25
29
  import { ExtensionRegistry } from "../extensions/registry.js";
26
30
  import { audit } from "../identity/audit.js";
27
- import { EnterpriseAdminLock } from "../identity/enterprise-admin.js";
31
+ import { assertCustomAllowed } from "../identity/settings.js";
32
+ import { SuperAdminLock } from "../identity/super-admin.js";
28
33
  import { KernelConfigService } from "../infra/config/kernel-config.service.js";
34
+ import { afterCommit } from "../infra/database/after-commit.js";
29
35
  import { KernelDb } from "../infra/database/kernel-db.js";
30
36
  import { TransactionHost } from "../infra/database/transaction-host.js";
31
37
  import { Transactional } from "../infra/database/transactional.decorator.js";
32
38
  import { KERNEL_LOGGER } from "../infra/tokens.js";
39
+ import { OrgLock } from "../orgs/org-lock.js";
33
40
  import { packPackageTgz } from "../packages/tgz.js";
41
+ import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
34
42
  import { checkSkillFiles, SkillArchiveError } from "../skills/package.js";
35
43
  import { StorageService } from "../storage/storage.service.js";
44
+ import { canonicalJson } from "../tools/canonical-json.js";
36
45
  import { endpointCredentialIssues } from "../tools/endpoint.js";
37
- import { canonicalJson } from "../tools/registry.js";
38
46
  import { findConnectorIn } from "./catalog-content.js";
39
- import { assertPluginNameOwner, catalogObjectPrefix, itemView, permissionsMismatch, precheckCatalogImport, putCatalogFiles, templateProblems, writeCatalogVersion, } from "./catalog-items.js";
47
+ import { displayFilePaths, putDisplayFiles, sweepDisplayFiles } from "./catalog-files.js";
48
+ import { assertOrgsExist, assertPluginNameOwner, catalogObjectPrefix, itemConfirmations, itemScopeFacts, itemView, markVersionApplied, permissionsMismatch, precheckCatalogImport, putCatalogFiles, templateProblems, unappliedOwnVersion, writeCatalogVersion, } from "./catalog-items.js";
40
49
  import { CLAUDE_PLUGIN_FILE, claudeContentDigest, } from "./claude/manifest.js";
41
50
  import { CLAUDE_MCP_CONNECTOR } from "./claude/mcp.js";
42
51
  import { item as reportItem, sortItems, } from "./claude/report.js";
43
52
  import { isClaudePluginTree, translateClaudePlugin } from "./claude/translate.js";
44
53
  import { CatalogItemLock } from "./locks.js";
45
- import { PluginPackageError, packagePath, readPluginFiles, readPluginPackage, } from "./plugin-package.js";
54
+ import { assertNameFree, assertPackageFree, assertShareable, packageOwner, releaseExtensionClaim, shareGate, usableBy, } from "./ownership.js";
55
+ import { PlatformComponents } from "./platform-components.js";
56
+ import { PLATFORM_MIGRATION_JOB } from "./platform-migration.js";
57
+ import { PluginPackageError, packagePath, readPluginFiles, readPluginPackage, themeApiError, } from "./plugin-package.js";
58
+ import { hasImportRequests, importRequestOf, resolveImportRequests } from "./request-rules.js";
59
+ import { assertNameNotReserved } from "./reserved-names.js";
60
+ import { addScopeOrg } from "./scope-orgs.js";
46
61
  import { maxSatisfying, satisfiesRange } from "./versions.js";
62
+ /** How long after a failed post-import platform sync the migration job runs for the item. */
63
+ export const PLATFORM_SYNC_RETRY_MS = 60_000;
47
64
  /**
48
- * Enterprise import of a plugin (package ecosystem spec §4.3): one review for every plugin, whatever
65
+ * Platform import of a plugin (package ecosystem spec §4.3): one review for every plugin, whatever
49
66
  * it contains (an extension, skills, connector templates, dependencies), confirmed once.
50
67
  *
51
68
  * prepare: the tgz is always hostile input, and **nothing is written until every check passes**
@@ -55,27 +72,30 @@ import { maxSatisfying, satisfiesRange } from "./versions.js";
55
72
  * refused; name ownership; a downgrade to a version with unrun migrations is refused), each skill by
56
73
  * the skill package rules, each connector template against the connector loaded on this replica (or
57
74
  * statically when the connector is provided by the plugin's own extension or by a dependency), the
58
- * catalog name / version conflicts and the actor still an enterprise admin. Dependencies are only
75
+ * catalog name / version conflicts and the actor still a super admin. Dependencies are only
59
76
  * resolved against the imported catalog versions for the review (an unresolved one does not block
60
77
  * the import, spec §4.1); they are never fetched. Only then is the extension handed to
61
- * `ExtensionInstalls.ingest` (source `catalog`), the skill / template / icon files written to object
62
- * storage, a staging row written (24 hours) and `catalog.plugin_staged` audited.
78
+ * `ExtensionInstalls.ingest` (source `catalog`), the skill / template files written to object
79
+ * storage, the display files (icons, setup guide files; `catalog-files.ts`) written to PG with a
80
+ * staging row (24 hours), and `catalog.plugin_staged` audited. A display file inside a skill
81
+ * directory or at a template's path goes to both places: each reader finds it where it looks.
63
82
  *
64
83
  * confirm: `reviewHash` must match the staging; in one transaction it deletes the staging row
65
84
  * (confirm works once), locks the extension name and recomputes its deployment state (installed /
66
85
  * upgraded / swapped after the review -> `plugin.review_stale`), writes the extension's permission
67
- * snapshot when it is installed by this import (or upgraded with `deployExtension`; source web, audit
68
- * `extension.permissions_approved` carrying the plugin), and creates the item or adds the version
69
- * (`manifest` = the normalized plugin.json, `extension_sha256`, the files under the staging prefix).
70
- * After the commit, with `deployExtension`, the plugin's own extension is installed on the
71
- * deployment and enabled (`ExtensionAdminOps.install` + `enable`; each replica reconciles, no
72
- * restart); a failure is returned, not thrown, and an upgrade that was not installed gets its old
73
- * snapshot back.
86
+ * snapshot when it is installed or upgraded by this import (source web, audit
87
+ * `extension.permissions_approved` carrying the plugin), and creates the item (with the scope the
88
+ * admin chose, default `optional`) or adds the version (`manifest` = the normalized plugin.json,
89
+ * `extension_sha256`, the files under the staging prefix). After the commit the plugin's own
90
+ * extension is installed on the deployment and enabled (`ExtensionAdminOps.install` + `enable`;
91
+ * each replica reconciles, no restart); a failure is returned, not thrown, and an upgrade that was
92
+ * not installed gets its old snapshot back.
74
93
  *
75
94
  * Expired staging is cleaned by the maintenance job `app-staging-cleanup`
76
- * ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix; a stored
77
- * extension package stays in the content-addressed `extension_packages` (the same as importing the
78
- * same tgz again; without an install record referencing it it is never loaded).
95
+ * ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix, then the
96
+ * display files (`catalog_files`) nothing lists any more; a stored extension package stays in the
97
+ * content-addressed `extension_packages` (the same as importing the same tgz again; without an
98
+ * install record referencing it it is never loaded).
79
99
  */
80
100
  /** How long a staged import is kept. */
81
101
  export const PLUGIN_STAGING_TTL_MS = 24 * 3600_000;
@@ -94,12 +114,20 @@ const reviewStale = (review) => new ApiError("plugin.review_stale", `The review
94
114
  const mismatch = (what) => new ApiError("marketplace.package_mismatch", `The downloaded package does not match the marketplace entry: ${what}`);
95
115
  /**
96
116
  * The API error of a plugin package that cannot be read in a catalog path: the pre-0.1.0 format ->
97
- * `catalog.legacy_format`, anything else -> `catalog.invalid_manifest` (issues as details).
117
+ * `catalog.legacy_format`; undeclared client code -> `client.undeclared`; a failing theme (themes
118
+ * spec §5) -> `theme.invalid` (details `[{ theme, errors }]`) or `theme.unreadable` (details
119
+ * `[{ theme, issues }]`, the failing pairs); anything else -> `catalog.invalid_manifest` (issues as
120
+ * details).
98
121
  */
99
122
  export function catalogPackageError(e) {
100
123
  const legacy = e.code === "catalog.legacy_format" || e.code === "extension.legacy_format";
101
124
  if (legacy)
102
125
  return new ApiError("catalog.legacy_format", e.message, e.issues);
126
+ if (e.code === "client.undeclared")
127
+ return new ApiError("client.undeclared", e.message);
128
+ if (e.code === "theme.invalid" || e.code === "theme.unreadable") {
129
+ return themeApiError(e);
130
+ }
103
131
  return invalid(e.issues);
104
132
  }
105
133
  /** Runs a package read, mapping its errors with {@link catalogPackageError}. */
@@ -123,16 +151,21 @@ const fileOf = (path, data) => ({
123
151
  let PluginImport = class PluginImport {
124
152
  kdb;
125
153
  adminLock;
154
+ orgLock;
126
155
  installLock;
127
156
  approveLock;
128
157
  itemLock;
129
158
  config;
130
159
  installs;
131
160
  ops;
161
+ admin;
132
162
  blobs;
133
163
  registry;
134
164
  log;
135
165
  txHost;
166
+ platform;
167
+ maintenance;
168
+ clientBuilds;
136
169
  /** Where plugin files go (the kernel's object storage; the CLI's own, see {@link useCliStorage}). */
137
170
  files;
138
171
  /**
@@ -142,24 +175,37 @@ let PluginImport = class PluginImport {
142
175
  */
143
176
  connectorsLoaded = true;
144
177
  constructor(kdb,
145
- /** The enterprise admin lock (identity/enterprise-admin.ts): joins the caller's transaction. */
146
- adminLock, installLock, approveLock, itemLock, config, storage, installs, ops,
178
+ /** The super admin lock (identity/super-admin.ts): joins the caller's transaction. */
179
+ adminLock,
180
+ /** The owner org's lock: an org upload re-checks its admin under it (ruling P3-7). */
181
+ orgLock, installLock, approveLock, itemLock, config, storage, installs, ops, admin,
147
182
  /** Reads a package from the package store (confirm recomputes the permission set). */
148
183
  blobs,
149
184
  /** Config-declared names, loaded connectors and extension versions (the extension registry). */
150
- registry, log, txHost) {
185
+ registry, log, txHost,
186
+ /** The platform rows of a new item's components, written after the confirm's commit. */
187
+ platform,
188
+ /** A failed platform sync enqueues a run of the migration job here (it heals the item). */
189
+ maintenance,
190
+ /** The client build of a dropped org upload's package is deleted with it. */
191
+ clientBuilds) {
151
192
  this.kdb = kdb;
152
193
  this.adminLock = adminLock;
194
+ this.orgLock = orgLock;
153
195
  this.installLock = installLock;
154
196
  this.approveLock = approveLock;
155
197
  this.itemLock = itemLock;
156
198
  this.config = config;
157
199
  this.installs = installs;
158
200
  this.ops = ops;
201
+ this.admin = admin;
159
202
  this.blobs = blobs;
160
203
  this.registry = registry;
161
204
  this.log = log;
162
205
  this.txHost = txHost;
206
+ this.platform = platform;
207
+ this.maintenance = maintenance;
208
+ this.clientBuilds = clientBuilds;
163
209
  this.files = storage;
164
210
  }
165
211
  /** The kernel-schema handle of the current context (the transaction, else the pool). */
@@ -174,21 +220,29 @@ let PluginImport = class PluginImport {
174
220
  useCliStorage(storage) {
175
221
  this.files = storage;
176
222
  this.connectorsLoaded = false;
223
+ this.platform.useCliStorage(storage);
177
224
  }
178
225
  /**
179
- * The enterprise-admin re-check under the lock, in the caller's transaction. `actor` null is the
226
+ * The super-admin re-check under the lock, in the caller's transaction. `actor` null is the
180
227
  * CLI (the operator of the deployment: no account to re-check, audits carry no actor), like
181
- * `ExtensionInstalls.ingest`.
228
+ * `ExtensionInstalls.ingest`. An org upload (`owner`) re-checks the actor as an admin of the
229
+ * owner org under the org row lock instead (`catalog.upload`; an org deleted meanwhile -> 404
230
+ * `org.not_found`).
182
231
  */
183
- async authorizeActor(actor) {
184
- if (actor === null)
232
+ async authorizeActor(actor, owner) {
233
+ if (owner !== undefined) {
234
+ if (actor === null)
235
+ throw new Error("an org upload has an actor");
236
+ await this.orgLock.lockAndAuthorize(owner.orgId, actor, "catalog.upload");
237
+ }
238
+ else if (actor === null)
185
239
  await this.adminLock.lock();
186
240
  else
187
241
  await this.adminLock.lockAndAuthorize(actor);
188
242
  }
189
243
  /** The re-check alone, in a transaction of its own (before anything is written). */
190
- async authorize(actor) {
191
- await this.authorizeActor(actor);
244
+ async authorize(actor, owner) {
245
+ await this.authorizeActor(actor, owner);
192
246
  }
193
247
  /**
194
248
  * Reads, checks and stages a plugin (see the file header). Returns the staging id and review.
@@ -279,6 +333,10 @@ let PluginImport = class PluginImport {
279
333
  */
280
334
  async prepareContents(actor, pkg, tgz, source, opts) {
281
335
  const maxBytes = this.config.get().packages.maxBytes;
336
+ const owner = opts.owner;
337
+ if (owner !== undefined && source.kind !== "file") {
338
+ throw new Error("an org upload is a file (ruling P3-7)");
339
+ }
282
340
  // 1. Every check (nothing written)
283
341
  const m = pkg.manifest;
284
342
  const packageName = packageNameOf(pkg);
@@ -292,14 +350,50 @@ let PluginImport = class PluginImport {
292
350
  ? await readingPackage(() => readExtensionPackage(bytes, { maxBytes, hostSdkVersion: SDK_VERSION }))
293
351
  : undefined;
294
352
  const content = this.checkContent(pkg, format);
295
- const { existing, version } = await precheckCatalogImport(this.db, m.name, {
296
- packageName,
297
- version: m.version,
298
- contentDigest: pkg.contentDigest,
299
- ...(source.integrity !== undefined && { integrity: source.integrity }),
300
- ...(source.detail !== undefined && { detail: source.detail }),
301
- ...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
302
- });
353
+ // suggestedAppearance.theme against the themes the scan found (the manifest may not list them)
354
+ const appearance = appearanceIssues(m, pkg.themes.map((t) => t.id));
355
+ if (appearance.length > 0)
356
+ throw invalid(appearance);
357
+ // Client code (client extensions spec §9.1): the section re-checked and every file against it
358
+ // (keys, listed = present, sizes, sha384 recomputed, the CSS layer wrap); delivered from object
359
+ // storage, so refused without one. The store checks the bytes it writes again. A bootstrap
360
+ // plugin never carries it: a bootstrap run may have no object store (it may be a bootstrap
361
+ // plugin itself), and a required entry failing on that would stop the start.
362
+ if (ext?.section.client !== undefined) {
363
+ if (source.kind === "bootstrap") {
364
+ throw new ApiError("client.invalid", `Bootstrap plugin ${m.name} ships client code (extension.client), which a bootstrap plugin may not carry: its files are kept in object storage, which a bootstrap run may not have (the object store may be a bootstrap plugin itself); take ${m.name} out of bootstrap.json and import it into the catalog instead`);
365
+ }
366
+ checkClientFiles(ext.section.client, pkg.files);
367
+ this.files.assertAvailable();
368
+ }
369
+ // A name live for another owner (an org's for the super admin; the platform's or another
370
+ // org's for an org) -> 409 plugin.name_taken naming it (P3-14); the same owner adds a version
371
+ await assertNameFree(this.db, m.name, owner?.orgId ?? null);
372
+ if (owner !== undefined) {
373
+ // a bootstrap or marketplace plugin's name stays free for the platform (ruling P3-28)
374
+ await assertNameNotReserved(this.db, m.name);
375
+ // its npm package is an identity of this org only (ruling P3-51)
376
+ await assertPackageFree(this.db, packageName, owner.orgId);
377
+ await assertCustomContent(this.db, content);
378
+ }
379
+ // An org's own version imported but not applied: its update is retried (pre-flight F4)
380
+ const retry = owner !== undefined && !m.extension
381
+ ? await unappliedOwnVersion(this.db, m.name, owner.orgId, {
382
+ packageName,
383
+ version: m.version,
384
+ contentDigest: pkg.contentDigest,
385
+ })
386
+ : undefined;
387
+ const { existing, version } = retry !== undefined
388
+ ? { existing: { id: retry.itemId }, version: retry.version }
389
+ : await precheckCatalogImport(this.db, m.name, {
390
+ packageName,
391
+ version: m.version,
392
+ contentDigest: pkg.contentDigest,
393
+ ...(source.integrity !== undefined && { integrity: source.integrity }),
394
+ ...(source.detail !== undefined && { detail: source.detail }),
395
+ ...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
396
+ });
303
397
  // The catalog name space is the extension name space: a declarative plugin cannot take a
304
398
  // config-declared or another package's extension name either
305
399
  this.assertNotDeclared(m.name);
@@ -309,8 +403,17 @@ let PluginImport = class PluginImport {
309
403
  extension = await this.reviewExtension(ext, await this.extensionState(m.name, packageName));
310
404
  await assertDowngradable(this.db, extension, ext.migrationSql);
311
405
  }
312
- if (content.files.length > 0)
406
+ // Display files go to PG with the staging row; skills and templates need object storage, which a
407
+ // bootstrap import never has (the object store may be a bootstrap plugin itself). A file that is
408
+ // both (an icon inside a skill directory) goes to both: the readers of each look only there
409
+ const displayFiles = content.files.filter((f) => content.displayPaths.has(f.path));
410
+ const objectFiles = content.files.filter((f) => content.objectPaths.has(f.path));
411
+ if (objectFiles.length > 0 && retry === undefined) {
412
+ if (source.kind === "bootstrap" && !this.files.available) {
413
+ throw new ApiError("storage.unavailable", `Bootstrap plugin ${m.name} ships skills, connector templates, agent templates or themes, which are kept in object storage, and object storage is not running yet (it may be a bootstrap plugin itself); a required bootstrap plugin may ship only an icon and setup guides, an optional one is retried once the extensions have loaded`);
414
+ }
313
415
  this.files.assertAvailable();
416
+ }
314
417
  const src = {
315
418
  kind: source.kind,
316
419
  ref: source.ref,
@@ -318,7 +421,7 @@ let PluginImport = class PluginImport {
318
421
  ...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
319
422
  ...(source.detail !== undefined && { detail: source.detail }),
320
423
  };
321
- const dependencies = await this.resolveDependencies(m);
424
+ const dependencies = await this.resolveDependencies(m, owner);
322
425
  let translation;
323
426
  if (opts.claude !== undefined) {
324
427
  const added = [
@@ -348,7 +451,8 @@ let PluginImport = class PluginImport {
348
451
  contentDigest: pkg.contentDigest,
349
452
  packageName,
350
453
  publisher: m.publisher,
351
- description: m.description,
454
+ description: pluginDescription(m.description).en,
455
+ descriptionZh: pluginDescription(m.description).zh ?? null,
352
456
  ...(m.displayName !== undefined && { displayName: m.displayName }),
353
457
  ...(m.license !== undefined && { license: m.license }),
354
458
  ...(m.homepage !== undefined && { homepage: m.homepage }),
@@ -356,6 +460,7 @@ let PluginImport = class PluginImport {
356
460
  skills: content.skills,
357
461
  connectorTemplates: content.templates,
358
462
  ...(content.agentTemplates.length > 0 && { agentTemplates: content.agentTemplates }),
463
+ ...(content.themes.length > 0 && { themes: content.themes }),
359
464
  dependencies,
360
465
  source: src,
361
466
  provenance: (opts.provenance ?? NOT_NPM).provenance,
@@ -364,8 +469,9 @@ let PluginImport = class PluginImport {
364
469
  reviewHash: "",
365
470
  };
366
471
  review.reviewHash = pluginReviewHash(review, content.files);
367
- // Re-check under the lock that the actor is still an enterprise admin before writing
368
- await this.authorize(actor);
472
+ // Re-check under the lock that the actor is still a super admin (an org upload: an admin of
473
+ // the owner org) before writing
474
+ await this.authorize(actor, owner);
369
475
  // 2. Write: the extension into the package store, files into object storage, the staging row
370
476
  const stagingId = randomUUID();
371
477
  const itemId = existing?.id ?? randomUUID();
@@ -379,12 +485,14 @@ let PluginImport = class PluginImport {
379
485
  }, {
380
486
  ...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
381
487
  ...(bootstrap && { store: "pg" }),
488
+ // an org upload only stores the package (nothing runs until the super admin confirms)
489
+ ...(owner !== undefined && { owner }),
382
490
  });
383
491
  }
384
492
  let objectPrefix = null;
385
- if (content.files.length > 0) {
493
+ if (objectFiles.length > 0 && retry === undefined) {
386
494
  objectPrefix = catalogObjectPrefix(itemId, version, stagingId);
387
- await putCatalogFiles(this.files, objectPrefix, content.files);
495
+ await putCatalogFiles(this.files, objectPrefix, objectFiles);
388
496
  }
389
497
  const keys = ext
390
498
  ? permissionKeys(permissionSetOfPackage(ext))
@@ -392,28 +500,34 @@ let PluginImport = class PluginImport {
392
500
  .sort()
393
501
  : [];
394
502
  const mismatch = permissionsMismatch(opts.expect?.marketplace?.permissions, ext ? keys : undefined);
503
+ const manifest = normalizedManifest(pkg);
504
+ const replacements = manifest.suggestedAppearance?.replacements;
395
505
  const staged = {
396
506
  itemId,
397
507
  packageName,
398
508
  version,
399
509
  contentDigest: pkg.contentDigest,
400
510
  size: tgz.size,
401
- manifest: normalizedManifest(pkg),
511
+ manifest,
512
+ ...(replacements !== undefined && { appearanceOrder: Object.keys(replacements) }),
402
513
  files: content.files.map(({ path, size, sha256 }) => ({ path, size, sha256 })),
403
514
  ...(mismatch !== null && { permissionsMismatch: mismatch }),
404
515
  sourceFormat: format,
405
516
  ...(translation !== undefined && { translation }),
406
517
  ...(license.text !== undefined && { licenseText: license.text }),
407
518
  ...(license.truncated && { licenseTruncated: true }),
519
+ ...(retry !== undefined && { retry: true }),
408
520
  };
409
- await this.writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts);
521
+ await this.writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles);
410
522
  return { stagingId, review, permissionKeys: keys, permissionsMismatch: mismatch };
411
523
  }
412
524
  /** The staging row and the `catalog.plugin_staged` audit, the actor re-checked under the lock. */
413
- async writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts) {
525
+ async writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles) {
414
526
  const { extension } = review;
415
527
  const t = this.db;
416
- await this.authorizeActor(actor);
528
+ await this.authorizeActor(actor, owner);
529
+ // committed with the staging row that lists them (the sweep keeps what a staging lists)
530
+ await putDisplayFiles(t, displayFiles);
417
531
  await t
418
532
  .insertInto("plugin_import_staging")
419
533
  .values({
@@ -424,6 +538,8 @@ let PluginImport = class PluginImport {
424
538
  source: JSON.stringify(src),
425
539
  created_by: actor,
426
540
  expires_at: new Date(Date.now() + PLUGIN_STAGING_TTL_MS),
541
+ // the org's own staging (P3-8); null = the super admin's
542
+ org_id: owner?.orgId ?? null,
427
543
  })
428
544
  .execute();
429
545
  await audit(t, {
@@ -443,6 +559,8 @@ let PluginImport = class PluginImport {
443
559
  ...(extension && {
444
560
  extension: { sha256: extension.sha256, action: extension.action },
445
561
  }),
562
+ ...(owner !== undefined && { orgId: owner.orgId }),
563
+ ...opts.auditDetail,
446
564
  },
447
565
  });
448
566
  }
@@ -465,9 +583,10 @@ let PluginImport = class PluginImport {
465
583
  /**
466
584
  * A staged import's review, as prepare returned it, with a marketplace import's permission
467
585
  * mismatch when there is one (the import page loads `?staging=<id>` with it). Unknown, expired or
468
- * already confirmed -> 404 `plugin.staging_not_found`.
586
+ * already confirmed -> 404 `plugin.staging_not_found`. Each sees only its own staging (P3-8):
587
+ * the super admin's routes the platform's (no `owner`), an org's routes that org's.
469
588
  */
470
- async staged(stagingId) {
589
+ async staged(stagingId, owner) {
471
590
  if (!UUID_RE.test(stagingId))
472
591
  throw notFound();
473
592
  const row = await this.db
@@ -475,6 +594,7 @@ let PluginImport = class PluginImport {
475
594
  .select(["id", "review", "manifest"])
476
595
  .where("id", "=", stagingId)
477
596
  .where("expires_at", ">", sql `now()`)
597
+ .where(ownStaging(owner))
478
598
  .executeTakeFirst();
479
599
  if (!row)
480
600
  throw notFound();
@@ -486,17 +606,117 @@ let PluginImport = class PluginImport {
486
606
  };
487
607
  }
488
608
  /**
489
- * Confirms a staged import (see the file header). Returns the committed catalog item and, with
490
- * `deployExtension`, the extension's deploy result (a failed deploy is returned, not thrown).
609
+ * What an org's staged upload targets (P3-12, pre-flight F3): its item, version and review hash,
610
+ * whether the item exists (a new version of the org's own plugin) or the version is imported
611
+ * already (F4), and the target as the platform updater reads it: the staged manifest and files,
612
+ * or the imported version's for a retry. Another org's staging -> 404 `plugin.staging_not_found`.
613
+ */
614
+ async stagedTarget(stagingId, owner) {
615
+ if (!UUID_RE.test(stagingId))
616
+ throw notFound();
617
+ const row = await this.db
618
+ .selectFrom("plugin_import_staging")
619
+ .select(["review", "manifest", "object_prefix"])
620
+ .where("id", "=", stagingId)
621
+ .where("expires_at", ">", sql `now()`)
622
+ .where(ownStaging(owner))
623
+ .executeTakeFirst();
624
+ if (!row)
625
+ throw notFound();
626
+ const review = row.review;
627
+ const staged = row.manifest;
628
+ const item = await this.db
629
+ .selectFrom("catalog_items")
630
+ .select(["id", "awaiting_confirmation"])
631
+ .where("id", "=", staged.itemId)
632
+ .where("deleted_at", "is", null)
633
+ .where("owner_org_id", "=", owner.orgId)
634
+ .executeTakeFirst();
635
+ const imported = staged.retry === true
636
+ ? await this.db
637
+ .selectFrom("catalog_item_versions")
638
+ .select(["version", "manifest", "object_prefix", "files", "extension_sha256"])
639
+ .where("item_id", "=", staged.itemId)
640
+ .where("version", "=", staged.version)
641
+ .executeTakeFirst()
642
+ : undefined;
643
+ return {
644
+ itemId: staged.itemId,
645
+ version: staged.version,
646
+ reviewHash: review.reviewHash,
647
+ extension: review.extension !== undefined,
648
+ existing: item !== undefined,
649
+ awaiting: item?.awaiting_confirmation === true,
650
+ retry: staged.retry === true,
651
+ target: imported !== undefined
652
+ ? {
653
+ version: imported.version,
654
+ manifest: imported.manifest,
655
+ object_prefix: imported.object_prefix,
656
+ files: imported.files,
657
+ extension_sha256: imported.extension_sha256,
658
+ }
659
+ : {
660
+ version: staged.version,
661
+ manifest: staged.manifest,
662
+ object_prefix: row.object_prefix,
663
+ files: staged.files,
664
+ extension_sha256: review.extension?.sha256 ?? null,
665
+ },
666
+ };
667
+ }
668
+ /** The catalog item's view (as a confirm returns it). */
669
+ async view(itemId) {
670
+ return this.itemView(itemId);
671
+ }
672
+ /**
673
+ * Confirms a staged import (see the file header). Returns the committed catalog item and the
674
+ * extension's deploy result (a failed deploy is returned, not thrown). `scope` (default
675
+ * `optional`) and `orgs` (only with `named`; each an existing org, else `validation_failed`) are
676
+ * written when this confirm creates the item; a new version of an existing item keeps its scope.
677
+ * The caller enqueues the scope sync of the item after this returns.
678
+ *
679
+ * An org upload (`opts.owner`, spec §14): only that org's staging; the actor re-checked as its
680
+ * admin; `scope` / `orgs` are not taken: a new item is owned by the org, scope `named: [owner]`,
681
+ * not shown to other orgs, `shareable` as given (default false). Custom deny, the name owner and
682
+ * the dependencies are checked again under the item name's lock. A package with an extension
683
+ * is stored and its extension name claimed, nothing approved or installed: the version waits
684
+ * for the super admin (`pending`, ruling P3-10; see {@link commit}).
491
685
  */
492
686
  async confirm(actor, stagingId, input, opts = {}) {
493
687
  if (!UUID_RE.test(stagingId))
494
688
  throw notFound();
689
+ const owner = opts.owner;
690
+ if (owner !== undefined && (input.scope !== undefined || input.orgs !== undefined)) {
691
+ throw new Error("an org upload's scope is its owner's");
692
+ }
693
+ // A staging prepared by approving an org's `import` request defaults to that org (spec §5.1
694
+ // rule 3); the admin may still choose any scope
695
+ const linked = input.scope === undefined && owner === undefined
696
+ ? await importRequestOf(this.db, stagingId)
697
+ : undefined;
698
+ const scope = owner !== undefined
699
+ ? "named"
700
+ : (input.scope ?? (linked !== undefined ? "named" : "optional"));
701
+ const orgs = owner !== undefined
702
+ ? [owner.orgId]
703
+ : (input.orgs ?? (linked !== undefined ? [linked.orgId] : undefined));
704
+ if (input.orgs !== undefined && scope !== "named") {
705
+ throw new ApiError("validation_failed", "orgs: only allowed with scope named", [
706
+ { path: "orgs", message: "only allowed with scope named" },
707
+ ]);
708
+ }
709
+ if (scope === "named" && (orgs ?? []).length === 0) {
710
+ throw new ApiError("validation_failed", "orgs: scope named needs at least one organization", [
711
+ { path: "orgs", message: "scope named needs at least one organization" },
712
+ ]);
713
+ }
495
714
  const row = await this.db
496
715
  .selectFrom("plugin_import_staging")
497
716
  .selectAll()
498
717
  .where("id", "=", stagingId)
499
718
  .where("expires_at", ">", sql `now()`)
719
+ .where(ownStaging(owner))
500
720
  .executeTakeFirst();
501
721
  if (!row)
502
722
  throw notFound();
@@ -507,34 +727,108 @@ let PluginImport = class PluginImport {
507
727
  throw reviewStale(review);
508
728
  const manifest = withPinned(staged.manifest, review, input.pinnedSuggestions);
509
729
  const reviewed = review.extension;
510
- // Read the stored package outside the transaction (unless it was already installed as is)
511
- const stored = reviewed && reviewed.action !== "keep" ? await this.readStored(reviewed.sha256) : undefined;
512
- const committed = await this.commit(actor, { stagingId, review, staged, src, manifest, objectPrefix: row.object_prefix }, input, stored, opts);
730
+ // Read the stored package outside the transaction (unless it was already installed as is, or
731
+ // an org upload, which approves nothing)
732
+ const stored = reviewed && reviewed.action !== "keep" && owner === undefined
733
+ ? await this.readStored(reviewed.sha256)
734
+ : undefined;
735
+ const committed = await this.commit(actor, { stagingId, review, staged, src, manifest, objectPrefix: row.object_prefix }, {
736
+ scope,
737
+ orgs: [...new Set(orgs ?? [])].sort(),
738
+ ...(owner !== undefined && { owner, shareable: input.shareable ?? false }),
739
+ }, stored, opts);
513
740
  const { now } = committed;
514
- const deploy = input.deployExtension && now && now.action !== "keep"
741
+ if (committed.pending) {
742
+ // Waits for the super admin (P3-10): no platform components, nothing deployed
743
+ return {
744
+ item: await this.itemView(committed.itemId),
745
+ created: committed.created,
746
+ deploy: null,
747
+ pending: true,
748
+ firstVersion: false,
749
+ };
750
+ }
751
+ // A new item's skills, agent templates and connector templates become platform components
752
+ // (plugin scope phase 2); a new version of an existing item leaves them to the platform
753
+ // update. After the commit: it copies files in object storage
754
+ if (committed.firstVersion)
755
+ await this.syncPlatform(committed.itemId, staged.version);
756
+ const deploy = now && now.action !== "keep"
515
757
  ? await this.deploy(actor, review, committed.itemId, now, committed.previous, opts, input.enable ?? true)
516
758
  : null;
517
- return { item: await this.itemView(committed.itemId), deploy };
759
+ return {
760
+ item: await this.itemView(committed.itemId),
761
+ created: committed.created,
762
+ deploy,
763
+ pending: false,
764
+ firstVersion: committed.firstVersion,
765
+ };
766
+ }
767
+ /**
768
+ * Writes the platform components of an item's first usable version after a commit made
769
+ * elsewhere (the super admin's confirmation of an org upload, `CatalogScopeService`); a failure
770
+ * is logged and retried by the migration job (see {@link syncPlatform}).
771
+ */
772
+ async writePlatformComponents(itemId, version) {
773
+ await this.syncPlatform(itemId, version);
518
774
  }
519
775
  /**
520
776
  * The confirm's transaction: the staging row consumed, the extension's action recomputed under
521
777
  * its install lock (stale -> `plugin.review_stale`), its snapshot approved, and the catalog
522
778
  * version written under the item name's lock.
779
+ *
780
+ * An org upload with an extension (ruling P3-10) approves nothing: under the install lock it
781
+ * claims the extension name for its package (another package's -> 409
782
+ * `extension.name_conflict` naming its owner, before anything is written), and the version
783
+ * written becomes the item's pending one (`pending_version` / `_by` / `_at`; a first version
784
+ * also `awaiting_confirmation`). A later upload replaces the pending version (P3-11). An org
785
+ * upload without an extension for an item whose first version still waits (plan Task 6) replaces
786
+ * that upload and applies at once: the item stops waiting and the claim is released (nothing
787
+ * was installed under it).
523
788
  */
524
- async commit(actor, c, input, stored, opts) {
789
+ async commit(actor, c, scope, stored, opts) {
525
790
  const { stagingId, review, staged, src, manifest } = c;
526
791
  const reviewed = review.extension;
527
792
  const stale = () => reviewStale(review);
528
- await this.authorizeActor(actor);
793
+ const { owner } = scope;
794
+ await this.authorizeActor(actor, owner);
529
795
  const t = this.db;
530
796
  const used = await t
531
797
  .deleteFrom("plugin_import_staging")
532
798
  .where("id", "=", stagingId)
533
799
  .where("expires_at", ">", sql `now()`)
800
+ .where(ownStaging(owner))
534
801
  .returning("id")
535
802
  .executeTakeFirst();
536
803
  if (!used)
537
804
  throw notFound();
805
+ if (owner !== undefined) {
806
+ await assertCustomContent(t, {
807
+ skills: review.skills,
808
+ agentTemplates: review.agentTemplates ?? [],
809
+ templates: review.connectorTemplates,
810
+ });
811
+ }
812
+ await assertOrgsExist(t, scope.orgs);
813
+ // Checked again before this upload claims anything (ruling P3-51)
814
+ if (owner !== undefined)
815
+ await assertPackageFree(t, staged.packageName, owner.orgId);
816
+ // The item's name lock and its live row before the extension's install lock: the global lock
817
+ // order is the item, then the install lock (ruling P3-50; ExtensionAdminOps.install locks the
818
+ // source item row before the install lock, an org deletion its items before it). Taken after
819
+ // the install lock instead, a confirmation of an org upload racing a replacement upload
820
+ // deadlocks (40P01).
821
+ const m = manifest;
822
+ await this.itemLock.lock(m.name);
823
+ // The scope the audit records: the review's for a new item, the item's own for a new version
824
+ // of a live item (which keeps its scope)
825
+ const existing = await t
826
+ .selectFrom("catalog_items")
827
+ .select(["id", "scope", "awaiting_confirmation", "package_name"])
828
+ .where("name", "=", m.name)
829
+ .where("deleted_at", "is", null)
830
+ .forUpdate()
831
+ .executeTakeFirst();
538
832
  let now;
539
833
  let previous;
540
834
  if (reviewed) {
@@ -544,23 +838,73 @@ let PluginImport = class PluginImport {
544
838
  await this.installLock.lock(reviewed.name);
545
839
  now = {
546
840
  ...reviewed,
547
- ...actionOf(await this.extensionState(reviewed.name, staged.packageName), reviewed.sha256),
841
+ ...actionOf(await this.extensionState(reviewed.name, staged.packageName), reviewed.sha256, reviewed.version),
548
842
  };
549
843
  if (pluginReviewHash({ ...review, extension: now }, staged.files) !== review.reviewHash) {
550
844
  throw stale();
551
845
  }
846
+ if (owner !== undefined) {
847
+ // An org upload only claims the name (P3-10): the super admin approves and installs it
848
+ await t
849
+ .insertInto("extension_name_owners")
850
+ .values({ name: reviewed.name, package_name: staged.packageName })
851
+ .onConflict((oc) => oc.column("name").doNothing())
852
+ .execute();
853
+ await assertPluginNameOwner(t, reviewed.name, staged.packageName);
854
+ }
552
855
  // A foreseeable deploy failure (a downgrade to a version with unrun migrations) is refused
553
856
  // before anything is written
554
- if (input.deployExtension && now.action === "upgrade" && stored) {
857
+ if (now.action === "upgrade" && stored) {
555
858
  await assertDowngradable(t, now, stored.migrationSql);
556
859
  }
557
- if (now.action === "install" || (now.action === "upgrade" && input.deployExtension)) {
860
+ if (owner === undefined && (now.action === "install" || now.action === "upgrade")) {
558
861
  previous = await this.approve(actor, review, staged, now, stored, opts);
559
862
  }
560
863
  }
561
- const m = manifest;
562
- await this.itemLock.lock(m.name);
563
- const itemId = await writeCatalogVersion(t, {
864
+ // Under the name's lock: the first confirm of a name wins, a later one of another owner is
865
+ // refused naming it, before anything of it is written (P3-14)
866
+ await assertNameFree(t, m.name, owner?.orgId ?? null);
867
+ if (owner !== undefined) {
868
+ await assertNameNotReserved(t, m.name);
869
+ await this.resolveDependencies(m, owner);
870
+ }
871
+ const actual = existing === undefined
872
+ ? scope
873
+ : {
874
+ scope: existing.scope,
875
+ orgs: (await t
876
+ .selectFrom("catalog_item_scope_orgs")
877
+ .select("org_id")
878
+ .where("item_id", "=", existing.id)
879
+ .orderBy("org_id")
880
+ .execute()).map((r) => r.org_id),
881
+ };
882
+ if (staged.retry === true) {
883
+ // An org's own version imported already (pre-flight F4): nothing to write, the caller
884
+ // retries its update; it must still be there as reviewed
885
+ const v = existing === undefined
886
+ ? undefined
887
+ : await t
888
+ .selectFrom("catalog_item_versions")
889
+ .select("version")
890
+ .where("item_id", "=", existing.id)
891
+ .where("version", "=", staged.version)
892
+ .where("content_digest", "=", staged.contentDigest)
893
+ .executeTakeFirst();
894
+ if (existing === undefined || existing.id !== staged.itemId || v === undefined)
895
+ throw stale();
896
+ return {
897
+ itemId: existing.id,
898
+ created: false,
899
+ firstVersion: false,
900
+ pending: false,
901
+ now,
902
+ previous,
903
+ };
904
+ }
905
+ const { id: itemId, created } = await writeCatalogVersion(t, {
906
+ // an org's version becomes its latest only when applied or confirmed (P3-34)
907
+ ...(owner !== undefined && { keepLatest: true }),
564
908
  actor,
565
909
  ...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
566
910
  name: m.name,
@@ -568,9 +912,10 @@ let PluginImport = class PluginImport {
568
912
  version: staged.version,
569
913
  contentDigest: staged.contentDigest,
570
914
  manifest: m,
915
+ appearanceOrder: staged.appearanceOrder ?? null,
571
916
  listing: {
572
917
  publisher: m.publisher,
573
- description: m.description,
918
+ description: pluginDescription(m.description).en,
574
919
  displayName: m.displayName ?? null,
575
920
  },
576
921
  newItemId: staged.itemId,
@@ -591,12 +936,144 @@ let PluginImport = class PluginImport {
591
936
  licenseTruncated: staged.licenseTruncated === true,
592
937
  auditDetail: {
593
938
  stagingId,
594
- deployExtension: input.deployExtension,
939
+ scope: actual.scope,
940
+ ...(actual.scope === "named" && { orgs: actual.orgs }),
595
941
  suggestedPinned: pinnedNames(manifest, review),
596
942
  ...(now && { extension: { name: now.name, version: now.version, action: now.action } }),
597
943
  },
598
944
  });
599
- return { itemId, now, previous };
945
+ // A new item gets the scope chosen in the review; a new version keeps the item's scope, its
946
+ // org list and its scope version (prepare reuses the live item's id, so the id cannot tell)
947
+ if (created) {
948
+ await t
949
+ .updateTable("catalog_items")
950
+ .set({
951
+ scope: scope.scope,
952
+ // an org upload: the org owns it, nobody else sees it until shared and shown (P3-16)
953
+ ...(owner !== undefined && {
954
+ owner_org_id: owner.orgId,
955
+ shareable: scope.shareable === true,
956
+ shown_to_others: false,
957
+ }),
958
+ })
959
+ .where("id", "=", itemId)
960
+ .execute();
961
+ if (scope.scope === "named" && scope.orgs.length > 0) {
962
+ await t
963
+ .insertInto("catalog_item_scope_orgs")
964
+ .values(scope.orgs.map((org_id) => ({ item_id: itemId, org_id })))
965
+ .onConflict((oc) => oc.doNothing())
966
+ .execute();
967
+ }
968
+ }
969
+ // The org requests this staging answers resolve with the confirm; on an item that existed
970
+ // already (imported meanwhile) a `named` scope gains their orgs. An org-owned item held back by
971
+ // the share gate fails closed before any request is marked (ruling P3-26; P3-14 refuses a
972
+ // super admin import of an org-owned name, so this should not be reached)
973
+ const item = created
974
+ ? undefined
975
+ : await t
976
+ .selectFrom("catalog_items")
977
+ .select(["id", "name", "scope", "builtin", "owner_org_id", "shareable"])
978
+ .where("id", "=", itemId)
979
+ .forUpdate()
980
+ .executeTakeFirstOrThrow();
981
+ if (item !== undefined && !shareGate(item) && (await hasImportRequests(t, stagingId))) {
982
+ assertShareable(item);
983
+ }
984
+ const requestOrgs = await resolveImportRequests(t, stagingId, itemId, actor, opts);
985
+ if (item !== undefined) {
986
+ for (const org of requestOrgs)
987
+ await addScopeOrg(t, actor, item, org, opts);
988
+ }
989
+ const pending = owner !== undefined && reviewed !== undefined;
990
+ // An org's first version without an extension is installed at once: applied (P3-52)
991
+ if (owner !== undefined && created && !pending)
992
+ await markVersionApplied(t, itemId, staged.version);
993
+ if (pending) {
994
+ // Waits for the super admin; a later upload replaces the pending version (P3-10, P3-11)
995
+ await t
996
+ .updateTable("catalog_items")
997
+ .set({
998
+ ...(created && { awaiting_confirmation: true }),
999
+ pending_version: staged.version,
1000
+ pending_by: actor,
1001
+ pending_at: sql `now()`,
1002
+ })
1003
+ .where("id", "=", itemId)
1004
+ .execute();
1005
+ }
1006
+ // A first version still waiting replaced by one without an extension: applied at once
1007
+ const replacedAwaiting = owner !== undefined && !pending && existing?.awaiting_confirmation === true;
1008
+ if (replacedAwaiting) {
1009
+ await t
1010
+ .updateTable("catalog_items")
1011
+ .set({
1012
+ awaiting_confirmation: false,
1013
+ pending_version: null,
1014
+ pending_by: null,
1015
+ pending_at: null,
1016
+ latest_version: staged.version,
1017
+ })
1018
+ .where("id", "=", itemId)
1019
+ .execute();
1020
+ await markVersionApplied(t, itemId, staged.version);
1021
+ await releaseExtensionClaim(t, m.name, existing.package_name);
1022
+ }
1023
+ return {
1024
+ itemId,
1025
+ created,
1026
+ firstVersion: (created && !pending) || replacedAwaiting,
1027
+ pending,
1028
+ now,
1029
+ previous,
1030
+ };
1031
+ }
1032
+ /**
1033
+ * The platform components of a new item. The item is committed already, so a failure is logged
1034
+ * and not thrown (like a failed deploy, the import itself succeeded); a run of the platform
1035
+ * components migration job (which writes what is missing) is enqueued on `cap-kernel-maintenance`
1036
+ * after {@link PLATFORM_SYNC_RETRY_MS}, one per item (deterministic job id). If that run fails
1037
+ * too, its `itemsFailed` shows in the super admin's inbox; the daily run and every worker start
1038
+ * try again.
1039
+ */
1040
+ async syncPlatform(itemId, version) {
1041
+ try {
1042
+ await this.platform.syncFromVersion(itemId, version, { initial: true });
1043
+ }
1044
+ catch (err) {
1045
+ // Removed meanwhile (an org deletion racing a confirmation, P3-20): nothing to write
1046
+ const live = await this.db
1047
+ .selectFrom("catalog_items")
1048
+ .select("id")
1049
+ .where("id", "=", itemId)
1050
+ .where("deleted_at", "is", null)
1051
+ .executeTakeFirst();
1052
+ if (live === undefined) {
1053
+ this.log.info("catalog item removed before its platform components were written", {
1054
+ itemId,
1055
+ version,
1056
+ });
1057
+ return;
1058
+ }
1059
+ this.log.error("writing the platform components of a new catalog item failed", {
1060
+ itemId,
1061
+ version,
1062
+ err,
1063
+ });
1064
+ try {
1065
+ await this.maintenance.add(PLATFORM_MIGRATION_JOB, {}, {
1066
+ jobId: `${PLATFORM_MIGRATION_JOB}-retry-${itemId}`,
1067
+ delay: PLATFORM_SYNC_RETRY_MS,
1068
+ attempts: 1,
1069
+ removeOnComplete: true,
1070
+ removeOnFail: { age: 86_400 },
1071
+ });
1072
+ }
1073
+ catch (e) {
1074
+ this.log.warn("cannot enqueue the platform components migration", { itemId, err: e });
1075
+ }
1076
+ }
600
1077
  }
601
1078
  /**
602
1079
  * Writes the extension's permission snapshot for the version being imported (source web; cli
@@ -644,7 +1121,9 @@ let PluginImport = class PluginImport {
644
1121
  }
645
1122
  /**
646
1123
  * Deploys the plugin's extension after the commit: `install` (a new install is disabled, a version
647
- * change keeps the desired state) then `enable`. Nothing is thrown; the result says what happened.
1124
+ * change keeps the desired state) then `enable`, unless another enabled extension provides one of
1125
+ * its single-provider extension points: then it stays disabled (result `installed` with code
1126
+ * `extension.single_provider_enabled`). Nothing is thrown; the result says what happened.
648
1127
  * When an upgrade was not installed, the snapshot overwritten at confirm is restored (the old
649
1128
  * version keeps running, F-O; audit `extension.permissions_restored`). Retry through the extension
650
1129
  * admin (the package is already in the package store) with the sha256 from the result.
@@ -659,8 +1138,9 @@ let PluginImport = class PluginImport {
659
1138
  const failure = (e) => e instanceof ApiError
660
1139
  ? { code: e.code, message: e.message }
661
1140
  : { code: "internal", message: "Internal error" };
1141
+ let installed;
662
1142
  try {
663
- await this.ops.install(p.name, p.sha256, actor, opts.actorTokenId, {
1143
+ installed = await this.ops.install(p.name, p.sha256, actor, opts.actorTokenId, {
664
1144
  catalogItemId: itemId,
665
1145
  });
666
1146
  }
@@ -686,11 +1166,19 @@ let PluginImport = class PluginImport {
686
1166
  }
687
1167
  return result;
688
1168
  }
1169
+ // An upgrade of an enabled extension that newly provides a held single-provider point: left
1170
+ // disabled by the install, and why
1171
+ if (installed.leftDisabled !== undefined) {
1172
+ return { ...base, result: "installed", ...installed.leftDisabled };
1173
+ }
689
1174
  if (!enable)
690
1175
  return { ...base, result: "installed" };
691
1176
  try {
692
- await this.ops.enable(p.name, actor, opts.actorTokenId);
693
- return { ...base, result: "enabled" };
1177
+ const r = await this.ops.enableUnlessOccupied(p.name, actor, opts.actorTokenId);
1178
+ if (r.enabled)
1179
+ return { ...base, result: "enabled" };
1180
+ // A single-provider point another enabled extension provides: installed disabled, and why
1181
+ return { ...base, result: "installed", ...r.note };
694
1182
  }
695
1183
  catch (e) {
696
1184
  this.log.warn("enabling a plugin's extension failed", { plugin: p.name, err: e });
@@ -745,11 +1233,24 @@ let PluginImport = class PluginImport {
745
1233
  return true;
746
1234
  }
747
1235
  /**
748
- * Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`).
749
- * Row by row: objects first, then the row (a failed object delete keeps the row for the next
750
- * round); concurrent replicas skip each other's rows (`SKIP LOCKED`). Returns the rows deleted.
1236
+ * Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`),
1237
+ * then the unused display files ({@link sweepDisplayFiles}). Row by row: objects first, then the
1238
+ * row (a failed object delete keeps the row for the next round); concurrent replicas skip each
1239
+ * other's rows (`SKIP LOCKED`). Returns the rows deleted.
751
1240
  */
752
1241
  async cleanupExpired() {
1242
+ const total = await this.cleanupStagingRows();
1243
+ // display files no version or staging lists (an abandoned import's), older than a staging
1244
+ try {
1245
+ await sweepDisplayFiles(this.db, PLUGIN_STAGING_TTL_MS);
1246
+ }
1247
+ catch (err) {
1248
+ this.log.warn("cannot sweep unused catalog display files", { err });
1249
+ }
1250
+ return total;
1251
+ }
1252
+ /** The expired staging rows, batch by batch; returns the rows deleted. */
1253
+ async cleanupStagingRows() {
753
1254
  let total = 0;
754
1255
  for (;;) {
755
1256
  const batch = await this.db
@@ -786,7 +1287,7 @@ let PluginImport = class PluginImport {
786
1287
  const t = this.db;
787
1288
  const locked = await t
788
1289
  .selectFrom("plugin_import_staging")
789
- .select("id")
1290
+ .select(["id", "org_id", "review", "manifest"])
790
1291
  .where("id", "=", r.id)
791
1292
  .where("expires_at", "<=", sql `now()`)
792
1293
  .forUpdate()
@@ -797,8 +1298,86 @@ let PluginImport = class PluginImport {
797
1298
  if (r.object_prefix)
798
1299
  await this.files.deployment().deletePrefix(r.object_prefix);
799
1300
  await t.deleteFrom("plugin_import_staging").where("id", "=", r.id).execute();
1301
+ await this.dropOrgPackage(locked);
800
1302
  return true;
801
1303
  }
1304
+ /**
1305
+ * An expired org staging's extension package (an org upload stores it at prepare, P3-10): removed
1306
+ * with the staging unless something else uses it — an install (running or migrated), a catalog
1307
+ * version, another staging — or it was stored by anyone else (the package row's source must be
1308
+ * this staging's own `catalog` ref). A platform staging keeps its package, as before. Its object
1309
+ * is deleted after the commit.
1310
+ */
1311
+ async dropOrgPackage(row) {
1312
+ const sha = row.review.extension?.sha256;
1313
+ if (row.org_id === null || sha === undefined)
1314
+ return;
1315
+ const staged = row.manifest;
1316
+ const t = this.db;
1317
+ const pkg = await t
1318
+ .selectFrom("extension_packages")
1319
+ .select("blob_store")
1320
+ .where("sha256", "=", sha)
1321
+ .where("source", "=", "catalog")
1322
+ .where("source_ref", "=", `${staged.itemId}@${staged.version}`)
1323
+ .forUpdate()
1324
+ .executeTakeFirst();
1325
+ if (!pkg)
1326
+ return;
1327
+ const used = (await t
1328
+ .selectFrom("extension_installs")
1329
+ .select("name")
1330
+ .where((eb) => eb.or([eb("sha256", "=", sha), eb("migrated_sha", "=", sha)]))
1331
+ .executeTakeFirst()) ??
1332
+ (await t
1333
+ .selectFrom("catalog_item_versions")
1334
+ .select("version")
1335
+ .where("extension_sha256", "=", sha)
1336
+ .executeTakeFirst()) ??
1337
+ (await t
1338
+ .selectFrom("plugin_import_staging")
1339
+ .select("id")
1340
+ .where(sql `review->'extension'->>'sha256' = ${sha}`)
1341
+ .executeTakeFirst());
1342
+ if (used !== undefined)
1343
+ return;
1344
+ const build = await t
1345
+ .selectFrom("extension_client_builds")
1346
+ .select("object_prefix")
1347
+ .where("package_sha256", "=", sha)
1348
+ .executeTakeFirst();
1349
+ // extension_blobs (a PG-stored package) and extension_client_builds go with the row (ON
1350
+ // DELETE CASCADE)
1351
+ await t.deleteFrom("extension_packages").where("sha256", "=", sha).execute();
1352
+ if (build !== undefined) {
1353
+ afterCommit(async () => {
1354
+ try {
1355
+ await this.clientBuilds.deleteFiles(sha, build.object_prefix);
1356
+ }
1357
+ catch (err) {
1358
+ this.log.warn("cannot delete an expired org upload's client build objects", {
1359
+ sha256: sha,
1360
+ err,
1361
+ });
1362
+ }
1363
+ });
1364
+ }
1365
+ // The object only once the row is gone for good: a failure leaves an unreferenced object
1366
+ // (harmless; a later upload of the same bytes rewrites it), never a row without its bytes
1367
+ if (pkg.blob_store === "object") {
1368
+ afterCommit(async () => {
1369
+ try {
1370
+ await this.files.deployment().delete(blobKey(sha));
1371
+ }
1372
+ catch (err) {
1373
+ this.log.warn("cannot delete an expired org upload's extension package object", {
1374
+ sha256: sha,
1375
+ err,
1376
+ });
1377
+ }
1378
+ });
1379
+ }
1380
+ }
802
1381
  // ---------------------------------------------------------------------------------------------
803
1382
  /** npm / marketplace imports: the package must be the one that was asked for. */
804
1383
  checkExpected(pkg, expect, format = "capybara") {
@@ -845,8 +1424,16 @@ let PluginImport = class PluginImport {
845
1424
  if (data !== undefined && !stored.has(path))
846
1425
  stored.set(path, fileOf(path, data));
847
1426
  };
848
- if (m.icon !== undefined)
849
- keep(packagePath(m.icon));
1427
+ const objectPaths = new Set();
1428
+ const keepObject = (path) => {
1429
+ keep(path);
1430
+ if (stored.has(path))
1431
+ objectPaths.add(path);
1432
+ };
1433
+ // The plugin icon and the setup guide documents (rendered by PluginGuides): display files
1434
+ const displayPaths = displayFilePaths(m, pkg.connectorTemplates.flatMap((c) => (c.file.icon === undefined ? [] : [c.file.icon])));
1435
+ for (const path of displayPaths)
1436
+ keep(path);
850
1437
  const skills = [];
851
1438
  for (const s of pkg.skills) {
852
1439
  const files = s.files.map((f) => fileOf(f, pkg.files.get(`${s.dir}/${f}`)));
@@ -865,7 +1452,7 @@ let PluginImport = class PluginImport {
865
1452
  suggestPinned: pinned.get(s.dir) === true,
866
1453
  });
867
1454
  for (const f of s.files)
868
- keep(`${s.dir}/${f}`);
1455
+ keepObject(`${s.dir}/${f}`);
869
1456
  }
870
1457
  catch (e) {
871
1458
  if (!(e instanceof SkillArchiveError))
@@ -909,10 +1496,8 @@ let PluginImport = class PluginImport {
909
1496
  else {
910
1497
  problems.push(`${at}.connector: extension ${t.plugin} providing connector "${t.connector}" is not loaded in this deployment and is neither this plugin's extension nor a dependency`);
911
1498
  }
912
- keep(c.path);
1499
+ keepObject(c.path);
913
1500
  templatePaths.set(c.id, c.path);
914
- if (c.file.icon !== undefined)
915
- keep(packagePath(c.file.icon));
916
1501
  return {
917
1502
  id: c.id,
918
1503
  displayName: c.file.displayName,
@@ -926,43 +1511,89 @@ let PluginImport = class PluginImport {
926
1511
  };
927
1512
  });
928
1513
  const agentTemplates = pkg.agentTemplates.map((a) => {
929
- keep(a.path);
1514
+ keepObject(a.path);
930
1515
  const { name, description, instructions, model, ...rest } = a.template;
931
1516
  return { name, path: a.path, description, instructions, model: model ?? "inherit", ...rest };
932
1517
  });
1518
+ // Themes: the file as written, the assets as sanitized by the reader (never the uploaded
1519
+ // originals: a shared path, e.g. the plugin icon, is stored sanitized too)
1520
+ const themes = pkg.themes.map((t) => {
1521
+ keepObject(t.path);
1522
+ for (const [path, data] of t.assets) {
1523
+ stored.set(path, fileOf(path, data));
1524
+ objectPaths.add(path);
1525
+ }
1526
+ const logo = t.theme.logo;
1527
+ return {
1528
+ id: t.id,
1529
+ name: t.theme.name,
1530
+ schemes: ["dark", "light"].filter((k) => t.theme.schemes[k] !== undefined),
1531
+ fonts: t.theme.fonts?.length ?? 0,
1532
+ logo: logo !== undefined && Object.keys(logo).length > 0,
1533
+ };
1534
+ });
933
1535
  if (problems.length > 0)
934
1536
  throw invalid(problems);
935
1537
  return {
936
1538
  files: [...stored.values()],
1539
+ displayPaths,
1540
+ objectPaths,
937
1541
  templates,
938
1542
  skills,
939
1543
  agentTemplates,
1544
+ themes,
940
1545
  notLoaded,
941
1546
  templatePaths,
942
1547
  };
943
1548
  }
944
1549
  /**
945
1550
  * The highest imported, non-deleted catalog version satisfying each dependency's range (null when
946
- * none does).
1551
+ * none does). An org upload (`owner`, P3-13) resolves only against items the org can use
1552
+ * ({@link usableBy}: confirmed, not disabled, offered to it), and any dependency left unresolved
1553
+ * -> 409 `plugin.dependency_unavailable` (details `[{ dependencies }]`, their names): an org
1554
+ * upload never brings in anything the org could not install itself.
947
1555
  */
948
- async resolveDependencies(m) {
1556
+ async resolveDependencies(m, owner) {
949
1557
  const deps = m.dependencies ?? [];
950
1558
  if (deps.length === 0)
951
1559
  return [];
952
- const rows = await this.db
1560
+ const names = deps.map((d) => d.name);
1561
+ const versions = this.db
953
1562
  .selectFrom("catalog_items as i")
954
1563
  .innerJoin("catalog_item_versions as v", "v.item_id", "i.id")
955
- .select(["i.name", "v.version", "v.imported_at"])
956
1564
  .where("i.deleted_at", "is", null)
957
- .where("i.name", "in", deps.map((d) => d.name))
958
- .execute();
959
- return deps.map((d) => ({
1565
+ .where("i.name", "in", names);
1566
+ const rows = owner === undefined
1567
+ ? await versions.select(["i.name", "v.version", "v.imported_at"]).execute()
1568
+ : (await versions
1569
+ // the org's own row of a `named` list (usableBy reads whether it is listed)
1570
+ .leftJoin("catalog_item_scope_orgs as so", (j) => j.onRef("so.item_id", "=", "i.id").on("so.org_id", "=", owner.orgId))
1571
+ .select([
1572
+ "i.name",
1573
+ "v.version",
1574
+ "v.imported_at",
1575
+ "i.scope",
1576
+ "i.builtin",
1577
+ "i.disabled",
1578
+ "i.deleted_at",
1579
+ "i.awaiting_confirmation",
1580
+ "i.owner_org_id",
1581
+ "i.shareable",
1582
+ "so.org_id as listed",
1583
+ ])
1584
+ .execute()).filter((r) => usableBy(r, owner.orgId, r.listed !== null));
1585
+ const resolved = deps.map((d) => ({
960
1586
  name: d.name,
961
1587
  range: d.version,
962
1588
  resolved: maxSatisfying(rows
963
1589
  .filter((r) => r.name === d.name)
964
1590
  .map((r) => ({ version: r.version, importedAt: r.imported_at })), d.version)?.version ?? null,
965
1591
  }));
1592
+ const missing = resolved.filter((d) => d.resolved === null).map((d) => d.name);
1593
+ if (owner !== undefined && missing.length > 0) {
1594
+ throw new ApiError("plugin.dependency_unavailable", `Dependencies not available to this organization: ${missing.join(", ")}`, [{ dependencies: missing }]);
1595
+ }
1596
+ return resolved;
966
1597
  }
967
1598
  /**
968
1599
  * The extension's state on the deployment; installed from another npm package ->
@@ -980,7 +1611,7 @@ let PluginImport = class PluginImport {
980
1611
  .where("extension_installs.name", "=", name)
981
1612
  .executeTakeFirst();
982
1613
  if (r && r.package_name !== packageName) {
983
- throw new ApiError("extension.name_conflict", `Extension ${name} is already installed from package ${r.package_name}; package ${packageName} cannot use it`);
1614
+ throw new ApiError("extension.name_conflict", `Extension ${name} is already installed from package ${r.package_name}; package ${packageName} cannot use it`, [{ owner: await packageOwner(this.db, r.package_name, name) }]);
984
1615
  }
985
1616
  return r
986
1617
  ? { kind: "installed", version: r.version, sha256: r.sha256, packageName: r.package_name }
@@ -1002,7 +1633,7 @@ let PluginImport = class PluginImport {
1002
1633
  name,
1003
1634
  version: pkg.section.version,
1004
1635
  sha256: pkg.sha256,
1005
- ...actionOf(state, pkg.sha256),
1636
+ ...actionOf(state, pkg.sha256, pkg.section.version),
1006
1637
  permissions,
1007
1638
  added,
1008
1639
  addedItems: permissionKeyItems(added),
@@ -1010,6 +1641,7 @@ let PluginImport = class PluginImport {
1010
1641
  warnings,
1011
1642
  reviewHash: extensionReviewHash(set, warnings),
1012
1643
  sensitive: permissions.some((g) => g.sensitive) || warnings.length > 0,
1644
+ ...(pkg.section.client !== undefined && { client: reviewClient(pkg) }),
1013
1645
  };
1014
1646
  }
1015
1647
  async readStored(sha256) {
@@ -1027,10 +1659,11 @@ let PluginImport = class PluginImport {
1027
1659
  .executeTakeFirstOrThrow();
1028
1660
  const versions = await this.db
1029
1661
  .selectFrom("catalog_item_versions")
1030
- .select(["version", "source", "imported_at"])
1662
+ .select(["version", "source", "imported_at", "extension_sha256", "manifest", "source_format"])
1031
1663
  .where("item_id", "=", itemId)
1032
1664
  .execute();
1033
- return itemView(item, versions);
1665
+ const facts = await itemScopeFacts(this.db, [item], await itemConfirmations(this.admin, [item], new Map([[item.id, versions]])));
1666
+ return itemView(item, versions, 0, undefined, facts.get(item.id));
1034
1667
  }
1035
1668
  };
1036
1669
  __decorate([
@@ -1054,21 +1687,29 @@ __decorate([
1054
1687
  __decorate([
1055
1688
  Transactional()
1056
1689
  ], PluginImport.prototype, "cleanupOne", null);
1690
+ __decorate([
1691
+ Transactional({ propagation: "mandatory" })
1692
+ ], PluginImport.prototype, "dropOrgPackage", null);
1057
1693
  PluginImport = __decorate([
1058
1694
  Injectable(),
1059
1695
  __param(0, Inject(KernelDb)),
1060
- __param(1, Inject(EnterpriseAdminLock)),
1061
- __param(2, Inject(PluginInstallLock)),
1062
- __param(3, Inject(PluginApproveLock)),
1063
- __param(4, Inject(CatalogItemLock)),
1064
- __param(5, Inject(KernelConfigService)),
1065
- __param(6, Inject(StorageService)),
1066
- __param(7, Inject(ExtensionInstalls)),
1067
- __param(8, Inject(ExtensionAdminOps)),
1068
- __param(9, Inject(ExtensionBlobs)),
1069
- __param(10, Inject(ExtensionRegistry)),
1070
- __param(11, Inject(KERNEL_LOGGER)),
1071
- __param(12, Inject(TransactionHost))
1696
+ __param(1, Inject(SuperAdminLock)),
1697
+ __param(2, Inject(OrgLock)),
1698
+ __param(3, Inject(PluginInstallLock)),
1699
+ __param(4, Inject(PluginApproveLock)),
1700
+ __param(5, Inject(CatalogItemLock)),
1701
+ __param(6, Inject(KernelConfigService)),
1702
+ __param(7, Inject(StorageService)),
1703
+ __param(8, Inject(ExtensionInstalls)),
1704
+ __param(9, Inject(ExtensionAdminOps)),
1705
+ __param(10, Inject(ExtensionAdmin)),
1706
+ __param(11, Inject(ExtensionBlobs)),
1707
+ __param(12, Inject(ExtensionRegistry)),
1708
+ __param(13, Inject(KERNEL_LOGGER)),
1709
+ __param(14, Inject(TransactionHost)),
1710
+ __param(15, Inject(PlatformComponents)),
1711
+ __param(16, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME))),
1712
+ __param(17, Inject(ClientBuilds))
1072
1713
  ], PluginImport);
1073
1714
  export { PluginImport };
1074
1715
  /**
@@ -1077,7 +1718,7 @@ export { PluginImport };
1077
1718
  */
1078
1719
  function normalizedManifest(pkg) {
1079
1720
  const pinned = new Map((pkg.manifest.skills ?? []).map((s) => [packagePath(s.path), s.pinned]));
1080
- const { agents: _, ...manifest } = pkg.manifest;
1721
+ const { agents: _, themes: __, ...manifest } = pkg.manifest;
1081
1722
  return {
1082
1723
  ...manifest,
1083
1724
  skills: pkg.skills.map((s) => {
@@ -1089,6 +1730,7 @@ function normalizedManifest(pkg) {
1089
1730
  ...(pkg.agentTemplates.length > 0 && {
1090
1731
  agents: pkg.agentTemplates.map((a) => ({ path: `./${a.path}` })),
1091
1732
  }),
1733
+ ...(pkg.themes.length > 0 && { themes: pkg.themes.map((t) => ({ path: `./${t.path}` })) }),
1092
1734
  };
1093
1735
  }
1094
1736
  /** package.json `name`, or null without one (a git plugin; never the string "undefined"). */
@@ -1097,13 +1739,20 @@ function packageNameOf(pkg) {
1097
1739
  return typeof name === "string" ? name : null;
1098
1740
  }
1099
1741
  /** The extension's deployment state -> action and current version. */
1100
- function actionOf(s, sha256) {
1742
+ function actionOf(s, sha256, version) {
1101
1743
  if (s.kind === "installed") {
1744
+ // A version below the deployed one is recorded in the catalog only: an import never
1745
+ // downgrades the deployment (ruling H)
1746
+ const older = s.sha256 !== sha256 &&
1747
+ semver.valid(version) !== null &&
1748
+ semver.valid(s.version) !== null &&
1749
+ semver.lt(version, s.version);
1102
1750
  return {
1103
- action: s.sha256 === sha256 ? "keep" : "upgrade",
1751
+ action: s.sha256 === sha256 || older ? "keep" : "upgrade",
1104
1752
  deployed: true,
1105
1753
  currentVersion: s.version,
1106
1754
  currentSha256: s.sha256,
1755
+ ...(older && { olderThanDeployed: true }),
1107
1756
  };
1108
1757
  }
1109
1758
  return { action: "install", deployed: false, currentVersion: null, currentSha256: null };
@@ -1113,13 +1762,17 @@ function actionOf(s, sha256) {
1113
1762
  * current version / package, its own review digest), every template field, each skill's name / path
1114
1763
  * / file count, the dependency resolution, the sha256 of every stored file, the format, the
1115
1764
  * translation report's items, the sha256 of the license text and the two review flags
1116
- * (`claudeManifestIgnored`, `licenseTruncated`), and the agent templates when there are any.
1765
+ * (`claudeManifestIgnored`, `licenseTruncated`), the agent templates when there are any and the
1766
+ * themes when there are any.
1117
1767
  * Exported for tests. `repository` is display only.
1118
1768
  */
1119
1769
  export function pluginReviewHash(r, files) {
1120
1770
  const e = r.extension;
1121
1771
  const lic = r.licenseText;
1122
- const canonical = JSON.stringify([
1772
+ // canonicalJson, not JSON.stringify: the review is stored as jsonb, which reorders object keys,
1773
+ // so a template's auth / endpoint object would hash differently at confirm (plugin.review_stale
1774
+ // on every import of a plugin whose connector template has a non-trivial auth block).
1775
+ const canonical = canonicalJson([
1123
1776
  r.name,
1124
1777
  r.version,
1125
1778
  r.contentDigest,
@@ -1146,9 +1799,34 @@ export function pluginReviewHash(r, files) {
1146
1799
  ...((r.agentTemplates ?? []).length > 0
1147
1800
  ? [(r.agentTemplates ?? []).map((a) => [a.path, canonicalJson(a)])]
1148
1801
  : []),
1802
+ // themes, only when there are any, tagged (never read as agent templates)
1803
+ ...((r.themes ?? []).length > 0
1804
+ ? [{ themes: (r.themes ?? []).map((t) => [t.id, canonicalJson(t)]) }]
1805
+ : []),
1149
1806
  ]);
1150
1807
  return createHash("sha256").update(canonical).digest("hex").slice(0, 32);
1151
1808
  }
1809
+ /** The client code of a read extension package for its review (sizes from the package's files). */
1810
+ function reviewClient(pkg) {
1811
+ const c = pkg.section.client;
1812
+ const sizes = new Map(pkg.files.map((f) => [f.path, f.size]));
1813
+ const files = [
1814
+ ...(c.entry !== undefined ? [c.entry] : []),
1815
+ ...(c.styles ?? []),
1816
+ ...(c.assets ?? []),
1817
+ ].map((path) => {
1818
+ // checkClientFiles ran first: every listed file is in the package
1819
+ const size = sizes.get(path.slice(2));
1820
+ if (size === undefined)
1821
+ throw new Error(`client file ${path} is not in the package`);
1822
+ return { path, size };
1823
+ });
1824
+ return {
1825
+ files,
1826
+ totalBytes: files.reduce((n, f) => n + f.size, 0),
1827
+ apiVersion: c.apiVersion,
1828
+ };
1829
+ }
1152
1830
  /**
1153
1831
  * A version change that is a downgrade (the imported version below the installed one) whose
1154
1832
  * version has migrations not run on this deployment -> `extension.downgrade_unsupported` (the same
@@ -1206,3 +1884,23 @@ function pinnedNames(m, review) {
1206
1884
  const byPath = new Map(review.skills.map((s) => [s.path, s.name]));
1207
1885
  return (m.skills ?? []).filter((s) => s.pinned === true).map((s) => byPath.get(s.path) ?? s.path);
1208
1886
  }
1887
+ /**
1888
+ * The staging rows a route may see (P3-8): the platform's (`org_id` null) without an owner, else
1889
+ * the owner org's.
1890
+ */
1891
+ function ownStaging(owner) {
1892
+ return (eb) => owner === undefined ? eb("org_id", "is", null) : eb("org_id", "=", owner.orgId);
1893
+ }
1894
+ /**
1895
+ * An org upload's custom deny, by content (ruling P3-15'): skills or agent templates ->
1896
+ * `customSkills`, connector templates -> `customConnectors`; each `deny` -> 403
1897
+ * `catalog.custom_disabled`. A package carrying neither passes; themes are covered by neither
1898
+ * switch (themes spec §6), so a themes-only upload passes.
1899
+ */
1900
+ async function assertCustomContent(db, content) {
1901
+ if (content.skills.length > 0 || content.agentTemplates.length > 0) {
1902
+ await assertCustomAllowed(db, "customSkills");
1903
+ }
1904
+ if (content.templates.length > 0)
1905
+ await assertCustomAllowed(db, "customConnectors");
1906
+ }