@capybara-hq/kernel 0.1.0-rc.1 → 0.1.0-rc.10
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.
- package/bootstrap.json +85 -5
- package/dist/admin/admin.controller.d.ts +52 -71
- package/dist/admin/admin.controller.js +117 -63
- package/dist/admin/admin.module.d.ts +3 -0
- package/dist/admin/admin.module.js +22 -0
- package/dist/admin/admin.schemas.d.ts +57 -0
- package/dist/admin/admin.schemas.js +50 -0
- package/dist/admin/extensions.controller.d.ts +47 -16
- package/dist/admin/extensions.controller.js +94 -23
- package/dist/admin/extensions.schemas.d.ts +7 -0
- package/dist/admin/extensions.schemas.js +10 -0
- package/dist/admin/limit-defaults.d.ts +20 -0
- package/dist/admin/limit-defaults.js +10 -0
- package/dist/admin/setup-lock.d.ts +16 -0
- package/dist/admin/setup-lock.js +47 -0
- package/dist/admin/setup.controller.d.ts +9 -9
- package/dist/admin/setup.controller.js +28 -26
- package/dist/admin/setup.service.d.ts +20 -28
- package/dist/admin/setup.service.js +65 -65
- package/dist/agents/agent-lookup.d.ts +72 -0
- package/dist/agents/agent-lookup.js +208 -0
- package/dist/agents/agent-profile.service.d.ts +31 -0
- package/dist/agents/agent-profile.service.js +122 -0
- package/dist/agents/agents.controller.d.ts +54 -169
- package/dist/agents/agents.controller.js +172 -37
- package/dist/agents/agents.module.d.ts +10 -0
- package/dist/agents/agents.module.js +71 -0
- package/dist/agents/agents.schemas.d.ts +389 -0
- package/dist/agents/agents.schemas.js +126 -0
- package/dist/agents/agents.service.d.ts +104 -76
- package/dist/agents/agents.service.js +509 -383
- package/dist/agents/definition.d.ts +133 -21
- package/dist/agents/definition.js +361 -41
- package/dist/agents/from-template.d.ts +106 -0
- package/dist/agents/from-template.js +680 -0
- package/dist/agents/from-template.service.d.ts +72 -0
- package/dist/agents/from-template.service.js +178 -0
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +44 -6
- package/dist/agents/models.controller.js +84 -8
- package/dist/agents/org-templates.d.ts +186 -0
- package/dist/agents/org-templates.js +868 -0
- package/dist/agents/pending-connector-requests.d.ts +79 -0
- package/dist/agents/pending-connector-requests.js +215 -0
- package/dist/agents/pending-connectors.controller.d.ts +39 -0
- package/dist/agents/pending-connectors.controller.js +91 -0
- package/dist/agents/pending-connectors.service.d.ts +62 -0
- package/dist/agents/pending-connectors.service.js +282 -0
- package/dist/agents/profile.d.ts +114 -0
- package/dist/agents/profile.js +55 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.controller.d.ts +78 -6
- package/dist/agents/templates.controller.js +154 -8
- package/dist/agents/templates.d.ts +132 -30
- package/dist/agents/templates.js +500 -46
- package/dist/agents/templates.schemas.d.ts +20 -0
- package/dist/agents/templates.schemas.js +45 -0
- package/dist/app.d.ts +93 -0
- package/dist/app.js +150 -0
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +88 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +39 -0
- package/dist/background/background.schemas.d.ts +10 -0
- package/dist/background/background.schemas.js +16 -0
- package/dist/background/finish.d.ts +44 -0
- package/dist/background/finish.js +95 -0
- package/dist/background/launch-lock.d.ts +15 -0
- package/dist/background/launch-lock.js +40 -0
- package/dist/background/launch.d.ts +42 -0
- package/dist/background/launch.js +77 -0
- package/dist/background/poll.job.d.ts +56 -0
- package/dist/background/poll.job.js +195 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +48 -0
- package/dist/background/session.js +80 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +68 -0
- package/dist/background/stop.js +244 -0
- package/dist/background/store.d.ts +167 -0
- package/dist/background/store.js +361 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +77 -0
- package/dist/background/tasks.service.js +216 -0
- package/dist/background/wake-rules.d.ts +66 -0
- package/dist/background/wake-rules.js +113 -0
- package/dist/background/wake.d.ts +30 -0
- package/dist/background/wake.js +63 -0
- package/dist/catalog/admin-catalog.controller.d.ts +102 -52
- package/dist/catalog/admin-catalog.controller.js +222 -67
- package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
- package/dist/catalog/admin-catalog.schemas.js +92 -0
- package/dist/catalog/catalog-content.d.ts +232 -0
- package/dist/catalog/catalog-content.js +367 -0
- package/dist/catalog/catalog-files.d.ts +41 -0
- package/dist/catalog/catalog-files.js +86 -0
- package/dist/catalog/catalog-import.module.d.ts +7 -0
- package/dist/catalog/catalog-import.module.js +60 -0
- package/dist/catalog/catalog-items.d.ts +290 -0
- package/dist/catalog/catalog-items.js +676 -0
- package/dist/catalog/catalog-scope.service.d.ts +260 -0
- package/dist/catalog/catalog-scope.service.js +1124 -0
- package/dist/catalog/catalog.module.d.ts +12 -0
- package/dist/catalog/catalog.module.js +81 -0
- package/dist/catalog/catalog.service.d.ts +141 -206
- package/dist/catalog/catalog.service.js +237 -528
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/cli.d.ts +14 -3
- package/dist/catalog/cli.js +39 -32
- package/dist/catalog/component-promotion.d.ts +96 -0
- package/dist/catalog/component-promotion.js +395 -0
- package/dist/catalog/component-scope.controller.d.ts +90 -0
- package/dist/catalog/component-scope.controller.js +234 -0
- package/dist/catalog/component-scope.schemas.d.ts +114 -0
- package/dist/catalog/component-scope.schemas.js +97 -0
- package/dist/catalog/component-scope.service.d.ts +327 -0
- package/dist/catalog/component-scope.service.js +990 -0
- package/dist/catalog/component-state.d.ts +188 -0
- package/dist/catalog/component-state.js +455 -0
- package/dist/catalog/git-source.d.ts +9 -1
- package/dist/catalog/git-source.js +29 -2
- package/dist/catalog/job-ids.d.ts +45 -0
- package/dist/catalog/job-ids.js +40 -0
- package/dist/catalog/jobs.d.ts +27 -0
- package/dist/catalog/jobs.js +70 -0
- package/dist/catalog/locks.d.ts +24 -0
- package/dist/catalog/locks.js +63 -0
- package/dist/catalog/marketplace-fetch.d.ts +1 -1
- package/dist/catalog/marketplace-icons.d.ts +64 -0
- package/dist/catalog/marketplace-icons.js +131 -0
- package/dist/catalog/marketplaces.controller.d.ts +53 -44
- package/dist/catalog/marketplaces.controller.js +146 -51
- package/dist/catalog/marketplaces.schemas.d.ts +48 -0
- package/dist/catalog/marketplaces.schemas.js +53 -0
- package/dist/catalog/marketplaces.service.d.ts +136 -26
- package/dist/catalog/marketplaces.service.js +663 -281
- package/dist/catalog/org-catalog.controller.d.ts +115 -63
- package/dist/catalog/org-catalog.controller.js +207 -100
- package/dist/catalog/org-catalog.schemas.d.ts +88 -0
- package/dist/catalog/org-catalog.schemas.js +93 -0
- package/dist/catalog/org-catalog.service.d.ts +89 -216
- package/dist/catalog/org-catalog.service.js +431 -472
- package/dist/catalog/org-extension-switch.d.ts +41 -0
- package/dist/catalog/org-extension-switch.js +115 -0
- package/dist/catalog/org-extension.controller.d.ts +113 -0
- package/dist/catalog/org-extension.controller.js +271 -0
- package/dist/catalog/org-extension.schemas.d.ts +15 -0
- package/dist/catalog/org-extension.schemas.js +22 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +77 -0
- package/dist/catalog/org-plugin-uploads.controller.js +200 -0
- package/dist/catalog/org-plugin-uploads.d.ts +71 -0
- package/dist/catalog/org-plugin-uploads.js +122 -0
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
- package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
- package/dist/catalog/owned-items.d.ts +188 -0
- package/dist/catalog/owned-items.js +801 -0
- package/dist/catalog/owned-plugin-cleanup.d.ts +56 -0
- package/dist/catalog/owned-plugin-cleanup.js +194 -0
- package/dist/catalog/ownership.d.ts +172 -0
- package/dist/catalog/ownership.js +326 -0
- package/dist/catalog/platform-components.d.ts +223 -0
- package/dist/catalog/platform-components.js +763 -0
- package/dist/catalog/platform-migration.d.ts +115 -0
- package/dist/catalog/platform-migration.js +582 -0
- package/dist/catalog/plugin-import.d.ts +270 -68
- package/dist/catalog/plugin-import.js +1004 -277
- package/dist/catalog/plugin-install.d.ts +251 -65
- package/dist/catalog/plugin-install.js +1128 -344
- package/dist/catalog/plugin-package.js +14 -1
- package/dist/catalog/plugin-upgrade.d.ts +301 -188
- package/dist/catalog/plugin-upgrade.js +1256 -1068
- package/dist/catalog/request-rules.d.ts +65 -0
- package/dist/catalog/request-rules.js +217 -0
- package/dist/catalog/requests.service.d.ts +205 -117
- package/dist/catalog/requests.service.js +612 -369
- package/dist/catalog/reserved-names.d.ts +8 -0
- package/dist/catalog/reserved-names.js +42 -0
- package/dist/catalog/scope-orgs.d.ts +21 -0
- package/dist/catalog/scope-orgs.js +67 -0
- package/dist/catalog/scope-state.d.ts +35 -0
- package/dist/catalog/scope-state.js +87 -0
- package/dist/catalog/scope-sync-workers.d.ts +7 -0
- package/dist/catalog/scope-sync-workers.js +29 -0
- package/dist/catalog/scope-sync.d.ts +176 -0
- package/dist/catalog/scope-sync.js +576 -0
- package/dist/catalog/scope.d.ts +42 -0
- package/dist/catalog/scope.js +42 -0
- package/dist/catalog/unshare.d.ts +22 -0
- package/dist/catalog/unshare.js +118 -0
- package/dist/channels/actions.d.ts +6 -4
- package/dist/channels/actions.js +11 -4
- package/dist/channels/cards.d.ts +33 -11
- package/dist/channels/cards.js +96 -24
- package/dist/channels/channels.module.d.ts +40 -0
- package/dist/channels/channels.module.js +130 -0
- package/dist/channels/channels.schemas.d.ts +37 -0
- package/dist/channels/channels.schemas.js +38 -0
- package/dist/channels/connections.controller.d.ts +44 -37
- package/dist/channels/connections.controller.js +83 -38
- package/dist/channels/connections.service.d.ts +101 -30
- package/dist/channels/connections.service.js +380 -147
- package/dist/channels/inbound.d.ts +44 -38
- package/dist/channels/inbound.js +190 -44
- package/dist/channels/job-ids.d.ts +10 -0
- package/dist/channels/job-ids.js +10 -0
- package/dist/channels/jobs.d.ts +85 -0
- package/dist/channels/jobs.js +157 -0
- package/dist/channels/outbound.d.ts +71 -80
- package/dist/channels/outbound.js +219 -202
- package/dist/channels/phrases.d.ts +33 -2
- package/dist/channels/phrases.js +29 -1
- package/dist/channels/supervisor.d.ts +88 -46
- package/dist/channels/supervisor.js +230 -132
- package/dist/channels/threads.d.ts +34 -8
- package/dist/channels/threads.js +79 -13
- package/dist/channels/webhook.d.ts +20 -14
- package/dist/channels/webhook.js +51 -20
- package/dist/config/docs.js +5 -1
- package/dist/config/load.d.ts +3 -2
- package/dist/config/load.js +3 -2
- package/dist/config/nacos-source.js +11 -2
- package/dist/config/schema.d.ts +36 -2
- package/dist/config/schema.js +226 -25
- package/dist/conversations/access.d.ts +31 -0
- package/dist/conversations/access.js +110 -0
- package/dist/conversations/agent-tree.d.ts +46 -0
- package/dist/conversations/agent-tree.js +92 -0
- package/dist/conversations/artifacts.d.ts +11 -11
- package/dist/conversations/artifacts.js +36 -10
- package/dist/conversations/attachments.controller.d.ts +1 -1
- package/dist/conversations/attachments.controller.js +8 -6
- package/dist/conversations/attachments.module.d.ts +7 -0
- package/dist/conversations/attachments.module.js +25 -0
- package/dist/conversations/attachments.service.d.ts +60 -22
- package/dist/conversations/attachments.service.js +249 -51
- package/dist/conversations/conversations.controller.d.ts +86 -50
- package/dist/conversations/conversations.controller.js +184 -103
- package/dist/conversations/conversations.module.d.ts +8 -0
- package/dist/conversations/conversations.module.js +72 -0
- package/dist/conversations/conversations.schemas.d.ts +52 -0
- package/dist/conversations/conversations.schemas.js +79 -0
- package/dist/conversations/conversations.service.d.ts +166 -49
- package/dist/conversations/conversations.service.js +383 -179
- package/dist/conversations/environment-status.d.ts +24 -0
- package/dist/conversations/environment-status.js +71 -0
- package/dist/conversations/event-log.d.ts +64 -27
- package/dist/conversations/event-log.js +167 -31
- package/dist/conversations/events.d.ts +252 -9
- package/dist/conversations/events.js +243 -32
- package/dist/conversations/files.d.ts +10 -10
- package/dist/conversations/files.js +37 -11
- package/dist/conversations/idem-keys.d.ts +5 -0
- package/dist/conversations/idem-keys.js +5 -0
- package/dist/conversations/job-ids.d.ts +6 -0
- package/dist/conversations/job-ids.js +6 -0
- package/dist/conversations/message-context.d.ts +79 -0
- package/dist/conversations/message-context.js +145 -0
- package/dist/conversations/outputs-read.d.ts +11 -11
- package/dist/conversations/outputs-read.js +31 -7
- package/dist/conversations/queue.d.ts +53 -58
- package/dist/conversations/queue.js +37 -293
- package/dist/conversations/queue.service.d.ts +60 -0
- package/dist/conversations/queue.service.js +350 -0
- package/dist/conversations/titles.d.ts +83 -27
- package/dist/conversations/titles.js +195 -71
- package/dist/conversations/tree.d.ts +17 -0
- package/dist/conversations/tree.js +42 -0
- package/dist/ctx/bus.js +9 -3
- package/dist/ctx/create-ctx.d.ts +26 -1
- package/dist/ctx/create-ctx.js +45 -16
- package/dist/ctx/lock.d.ts +7 -3
- package/dist/ctx/lock.js +9 -20
- package/dist/ctx/secrets.d.ts +10 -2
- package/dist/ctx/secrets.js +7 -3
- package/dist/db/kernel-schema.d.ts +550 -25
- package/dist/db/pool.d.ts +10 -0
- package/dist/db/pool.js +4 -0
- package/dist/devices/device-auth.controller.d.ts +42 -0
- package/dist/devices/device-auth.controller.js +116 -0
- package/dist/devices/device-auth.d.ts +119 -0
- package/dist/devices/device-auth.js +403 -0
- package/dist/devices/device-auth.module.d.ts +7 -0
- package/dist/devices/device-auth.module.js +25 -0
- package/dist/devices/device-gateway.d.ts +128 -0
- package/dist/devices/device-gateway.js +530 -0
- package/dist/devices/device-provider.d.ts +89 -0
- package/dist/devices/device-provider.js +151 -0
- package/dist/devices/device-routes.d.ts +36 -0
- package/dist/devices/device-routes.js +90 -0
- package/dist/devices/devices.module.d.ts +16 -0
- package/dist/devices/devices.module.js +44 -0
- package/dist/devices/dto.d.ts +66 -0
- package/dist/devices/dto.js +44 -0
- package/dist/devices/keys.d.ts +25 -0
- package/dist/devices/keys.js +25 -0
- package/dist/devices/machines.d.ts +118 -0
- package/dist/devices/machines.js +366 -0
- package/dist/devices/relay.d.ts +100 -0
- package/dist/devices/relay.js +373 -0
- package/dist/devices/targets.d.ts +28 -0
- package/dist/devices/targets.js +73 -0
- package/dist/environments/access.d.ts +66 -0
- package/dist/environments/access.js +113 -0
- package/dist/environments/conversation-environments.d.ts +75 -0
- package/dist/environments/conversation-environments.js +231 -0
- package/dist/environments/dto.d.ts +25 -0
- package/dist/environments/dto.js +12 -0
- package/dist/environments/environments.controller.d.ts +36 -0
- package/dist/environments/environments.controller.js +124 -0
- package/dist/environments/environments.module.d.ts +8 -0
- package/dist/environments/environments.module.js +31 -0
- package/dist/environments/environments.schemas.d.ts +3 -0
- package/dist/environments/environments.schemas.js +14 -0
- package/dist/environments/environments.service.d.ts +251 -0
- package/dist/environments/environments.service.js +791 -0
- package/dist/environments/label.d.ts +11 -0
- package/dist/environments/label.js +25 -0
- package/dist/environments/legacy-cleanup.job.d.ts +34 -0
- package/dist/environments/legacy-cleanup.job.js +141 -0
- package/dist/errors.d.ts +135 -2
- package/dist/errors.js +135 -2
- package/dist/evals/budget.d.ts +42 -21
- package/dist/evals/budget.js +114 -62
- package/dist/evals/evals.module.d.ts +31 -0
- package/dist/evals/evals.module.js +114 -0
- package/dist/evals/evals.schemas.d.ts +110 -0
- package/dist/evals/evals.schemas.js +107 -0
- package/dist/evals/jobs.d.ts +20 -0
- package/dist/evals/jobs.js +45 -0
- package/dist/evals/reconstruct.d.ts +18 -9
- package/dist/evals/reconstruct.js +36 -10
- package/dist/evals/recorded-tools.d.ts +37 -1
- package/dist/evals/recorded-tools.js +120 -10
- package/dist/evals/run-replay.d.ts +75 -10
- package/dist/evals/run-replay.js +218 -94
- package/dist/evals/runs.controller.d.ts +3 -58
- package/dist/evals/runs.controller.js +18 -50
- package/dist/evals/runs.service.d.ts +31 -52
- package/dist/evals/runs.service.js +281 -255
- package/dist/evals/sets.controller.d.ts +3 -29
- package/dist/evals/sets.controller.js +18 -39
- package/dist/evals/sets.service.d.ts +29 -13
- package/dist/evals/sets.service.js +262 -202
- package/dist/evals/snapshot.d.ts +5 -4
- package/dist/evals/snapshot.js +17 -4
- package/dist/evals/step-replay.d.ts +6 -8
- package/dist/evals/step-replay.js +17 -10
- package/dist/evals/trajectory.controller.d.ts +1 -1
- package/dist/evals/trajectory.controller.js +11 -7
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/evals/trajectory.js +1 -1
- package/dist/evals/trajectory.service.d.ts +13 -7
- package/dist/evals/trajectory.service.js +56 -21
- package/dist/evals/worker.d.ts +48 -31
- package/dist/evals/worker.js +229 -124
- package/dist/extensions/admin-ops.d.ts +133 -41
- package/dist/extensions/admin-ops.js +378 -172
- package/dist/extensions/admin-view.d.ts +82 -32
- package/dist/extensions/admin-view.js +284 -71
- package/dist/extensions/approvals.d.ts +24 -10
- package/dist/extensions/approvals.js +73 -46
- package/dist/extensions/blobs.d.ts +27 -10
- package/dist/extensions/blobs.js +112 -45
- package/dist/extensions/bootstrap.d.ts +99 -36
- package/dist/extensions/bootstrap.js +290 -134
- package/dist/extensions/cli.d.ts +32 -10
- package/dist/extensions/cli.js +52 -98
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/config-issues.d.ts +19 -0
- package/dist/extensions/config-issues.js +48 -0
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +55 -0
- package/dist/extensions/deployment-config-store.js +133 -0
- package/dist/extensions/deployment-config.d.ts +146 -70
- package/dist/extensions/deployment-config.js +439 -246
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/effective-config.d.ts +127 -0
- package/dist/extensions/effective-config.js +368 -0
- package/dist/extensions/enabled.d.ts +5 -5
- package/dist/extensions/extensions.module.d.ts +8 -0
- package/dist/extensions/extensions.module.js +96 -0
- package/dist/extensions/hooks.d.ts +40 -6
- package/dist/extensions/hooks.js +83 -17
- package/dist/extensions/host.d.ts +161 -80
- package/dist/extensions/host.js +505 -213
- package/dist/extensions/installs.d.ts +73 -19
- package/dist/extensions/installs.js +174 -37
- package/dist/extensions/job-ids.d.ts +6 -0
- package/dist/extensions/job-ids.js +6 -0
- package/dist/extensions/lifecycle-topics.d.ts +18 -0
- package/dist/extensions/lifecycle-topics.js +18 -0
- package/dist/extensions/lifecycle.d.ts +35 -47
- package/dist/extensions/lifecycle.js +103 -39
- package/dist/extensions/locks.d.ts +45 -0
- package/dist/extensions/locks.js +112 -0
- package/dist/extensions/migrate-lock.d.ts +3 -4
- package/dist/extensions/org-config.d.ts +141 -49
- package/dist/extensions/org-config.js +471 -243
- package/dist/extensions/org-levels.d.ts +37 -0
- package/dist/extensions/org-levels.js +71 -0
- package/dist/extensions/org-overrides.d.ts +151 -0
- package/dist/extensions/org-overrides.js +524 -0
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +59 -6
- package/dist/extensions/permission-view.js +7 -5
- package/dist/extensions/plugin-guides.d.ts +129 -0
- package/dist/extensions/plugin-guides.js +283 -0
- package/dist/extensions/plugin-icons.d.ts +54 -0
- package/dist/extensions/plugin-icons.js +125 -0
- package/dist/extensions/plugin-items.d.ts +21 -0
- package/dist/extensions/plugin-items.js +42 -0
- package/dist/extensions/point-defaults.controller.d.ts +28 -0
- package/dist/extensions/point-defaults.controller.js +69 -0
- package/dist/extensions/point-defaults.d.ts +73 -0
- package/dist/extensions/point-defaults.js +236 -0
- package/dist/extensions/point-defaults.schemas.d.ts +9 -0
- package/dist/extensions/point-defaults.schemas.js +14 -0
- package/dist/extensions/registry.d.ts +50 -2
- package/dist/extensions/registry.js +91 -4
- package/dist/extensions/resolve.d.ts +51 -1
- package/dist/extensions/resolve.js +85 -3
- package/dist/extensions/single-provider.d.ts +92 -0
- package/dist/extensions/single-provider.js +180 -0
- package/dist/extensions/sources.d.ts +19 -10
- package/dist/extensions/sources.js +34 -13
- package/dist/extensions/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +38 -0
- package/dist/extensions/unavailable.d.ts +50 -0
- package/dist/extensions/unavailable.js +115 -0
- package/dist/files/files.module.d.ts +3 -0
- package/dist/files/files.module.js +22 -0
- package/dist/files/previewers.controller.d.ts +7 -2
- package/dist/files/previewers.controller.js +19 -12
- package/dist/files/previewers.d.ts +21 -19
- package/dist/files/previewers.js +114 -38
- package/dist/files/previewers.schemas.d.ts +10 -0
- package/dist/files/previewers.schemas.js +9 -0
- package/dist/http/adapter.d.ts +3 -0
- package/dist/http/adapter.js +25 -0
- package/dist/http/api.module.d.ts +3 -110
- package/dist/http/api.module.js +86 -358
- package/dist/http/app.d.ts +22 -17
- package/dist/http/app.js +46 -65
- package/dist/http/error-filter.module.d.ts +5 -0
- package/dist/http/error-filter.module.js +18 -0
- package/dist/http/error.filter.js +2 -2
- package/dist/http/{gateway.module.d.ts → gateway-routes.d.ts} +7 -3
- package/dist/http/gateway-routes.js +16 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/http/plugin-dispatch.d.ts +4 -1
- package/dist/http/plugin-dispatch.js +14 -2
- package/dist/identity/accounts.d.ts +130 -38
- package/dist/identity/accounts.js +373 -186
- package/dist/identity/api-tokens.d.ts +11 -7
- package/dist/identity/api-tokens.js +71 -44
- package/dist/identity/audit.d.ts +9 -5
- package/dist/identity/audit.js +5 -1
- package/dist/identity/auth.controller.d.ts +11 -10
- package/dist/identity/auth.controller.js +40 -30
- package/dist/identity/auth.guard.d.ts +16 -8
- package/dist/identity/auth.guard.js +41 -13
- package/dist/identity/binding.d.ts +9 -11
- package/dist/identity/binding.js +41 -13
- package/dist/identity/cookies.d.ts +26 -5
- package/dist/identity/cookies.js +58 -6
- package/dist/identity/external-identity-lock.d.ts +17 -0
- package/dist/identity/external-identity-lock.js +39 -0
- package/dist/identity/external.d.ts +19 -15
- package/dist/identity/external.js +163 -125
- package/dist/identity/identity.module.d.ts +6 -0
- package/dist/identity/identity.module.js +59 -0
- package/dist/identity/initial-passwords.controller.d.ts +22 -0
- package/dist/identity/initial-passwords.controller.js +49 -0
- package/dist/identity/initial-passwords.d.ts +61 -0
- package/dist/identity/initial-passwords.job.d.ts +16 -0
- package/dist/identity/initial-passwords.job.js +46 -0
- package/dist/identity/initial-passwords.js +159 -0
- package/dist/identity/me.controller.d.ts +32 -15
- package/dist/identity/me.controller.js +78 -33
- package/dist/identity/me.schemas.d.ts +14 -0
- package/dist/identity/me.schemas.js +17 -0
- package/dist/identity/principal.d.ts +11 -3
- package/dist/identity/principal.js +11 -3
- package/dist/identity/sessions.d.ts +24 -10
- package/dist/identity/sessions.js +119 -42
- package/dist/identity/settings.d.ts +42 -23
- package/dist/identity/settings.js +137 -72
- package/dist/identity/sso.controller.d.ts +7 -7
- package/dist/identity/sso.controller.js +13 -9
- package/dist/identity/sso.d.ts +9 -12
- package/dist/identity/sso.js +54 -24
- package/dist/identity/super-admin.d.ts +20 -0
- package/dist/identity/super-admin.js +81 -0
- package/dist/inbox/inbox.module.d.ts +6 -0
- package/dist/inbox/inbox.module.js +26 -0
- package/dist/inbox/inbox.schemas.d.ts +8 -0
- package/dist/inbox/inbox.schemas.js +11 -0
- package/dist/inbox/inbox.service.d.ts +68 -11
- package/dist/inbox/inbox.service.js +104 -13
- package/dist/inbox/org-notices.d.ts +63 -0
- package/dist/inbox/org-notices.js +91 -0
- package/dist/inbox/platform-inbox.controller.d.ts +23 -0
- package/dist/inbox/platform-inbox.controller.js +58 -0
- package/dist/inbox/platform-inbox.service.d.ts +151 -0
- package/dist/inbox/platform-inbox.service.js +263 -0
- package/dist/inbox/platform-notices.d.ts +19 -0
- package/dist/inbox/platform-notices.js +9 -0
- package/dist/index.d.ts +22 -13
- package/dist/index.js +16 -7
- package/dist/infra/cache/cache.module.d.ts +3 -0
- package/dist/infra/cache/cache.module.js +16 -0
- package/dist/infra/cache/cache.service.d.ts +21 -0
- package/dist/infra/cache/cache.service.js +80 -0
- package/dist/infra/cache/cacheable.decorator.d.ts +32 -0
- package/dist/infra/cache/cacheable.decorator.js +83 -0
- package/dist/infra/cli/kernel-cli.module.d.ts +66 -0
- package/dist/infra/cli/kernel-cli.module.js +173 -0
- package/dist/infra/close-within.d.ts +15 -0
- package/dist/infra/close-within.js +36 -0
- package/dist/infra/config/config.module.d.ts +13 -0
- package/dist/infra/config/config.module.js +39 -0
- package/dist/infra/config/kernel-config.service.d.ts +25 -0
- package/dist/infra/config/kernel-config.service.js +157 -0
- package/dist/infra/database/after-commit.d.ts +6 -0
- package/dist/infra/database/after-commit.js +9 -0
- package/dist/infra/database/database.module.d.ts +25 -0
- package/dist/infra/database/database.module.js +91 -0
- package/dist/infra/database/kernel-db.d.ts +22 -0
- package/dist/infra/database/kernel-db.js +65 -0
- package/dist/infra/database/transaction-host.d.ts +50 -0
- package/dist/infra/database/transaction-host.js +125 -0
- package/dist/infra/database/transactional.decorator.d.ts +15 -0
- package/dist/infra/database/transactional.decorator.js +27 -0
- package/dist/infra/database/xact-lock.d.ts +17 -0
- package/dist/infra/database/xact-lock.js +43 -0
- package/dist/infra/events/kernel-events.d.ts +121 -0
- package/dist/infra/events/kernel-events.js +65 -0
- package/dist/infra/health/health.controller.d.ts +26 -0
- package/dist/infra/health/health.controller.js +104 -0
- package/dist/infra/health/health.module.d.ts +9 -0
- package/dist/infra/health/health.module.js +24 -0
- package/dist/infra/health/health.options.d.ts +10 -0
- package/dist/infra/health/health.options.js +15 -0
- package/dist/infra/health/shutdown-state.d.ts +6 -0
- package/dist/infra/health/shutdown-state.js +2 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.d.ts +6 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.js +23 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.d.ts +70 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.js +135 -0
- package/dist/infra/lifecycle/process-guards.d.ts +52 -0
- package/dist/infra/lifecycle/process-guards.js +90 -0
- package/dist/infra/lifecycle/shutdown-signals.d.ts +30 -0
- package/dist/infra/lifecycle/shutdown-signals.js +48 -0
- package/dist/infra/lock/key-template.d.ts +13 -0
- package/dist/infra/lock/key-template.js +46 -0
- package/dist/infra/lock/lock.module.d.ts +3 -0
- package/dist/infra/lock/lock.module.js +16 -0
- package/dist/infra/lock/lock.service.d.ts +120 -0
- package/dist/infra/lock/lock.service.js +343 -0
- package/dist/infra/lock/shared-lease.d.ts +44 -0
- package/dist/infra/lock/shared-lease.js +121 -0
- package/dist/infra/lock/with-lock.decorator.d.ts +28 -0
- package/dist/infra/lock/with-lock.decorator.js +49 -0
- package/dist/infra/logging/logging.module.d.ts +18 -0
- package/dist/infra/logging/logging.module.js +52 -0
- package/dist/infra/queue/add-job-once.d.ts +14 -0
- package/dist/infra/queue/add-job-once.js +16 -0
- package/dist/infra/queue/configured-processor.d.ts +18 -0
- package/dist/infra/queue/configured-processor.js +23 -0
- package/dist/infra/queue/job-failure.d.ts +18 -0
- package/dist/infra/queue/job-failure.js +26 -0
- package/dist/infra/queue/queue-shutdown.d.ts +27 -0
- package/dist/infra/queue/queue-shutdown.js +81 -0
- package/dist/infra/queue/queue.module.d.ts +16 -0
- package/dist/infra/queue/queue.module.js +61 -0
- package/dist/infra/queue/redis-connection.d.ts +13 -0
- package/dist/infra/queue/redis-connection.js +25 -0
- package/dist/infra/queue/retired-schedulers.d.ts +7 -0
- package/dist/infra/queue/retired-schedulers.js +9 -0
- package/dist/infra/queue/run-job.d.ts +16 -0
- package/dist/infra/queue/run-job.js +19 -0
- package/dist/infra/redis/redis.module.d.ts +24 -0
- package/dist/infra/redis/redis.module.js +91 -0
- package/dist/infra/schedule/cron-tick.d.ts +12 -0
- package/dist/infra/schedule/cron-tick.js +25 -0
- package/dist/infra/schedule/locked-cron.decorator.d.ts +27 -0
- package/dist/infra/schedule/locked-cron.decorator.js +53 -0
- package/dist/infra/schedule/locked-interval.d.ts +69 -0
- package/dist/infra/schedule/locked-interval.js +190 -0
- package/dist/infra/schedule/locked-tick.d.ts +90 -0
- package/dist/infra/schedule/locked-tick.js +137 -0
- package/dist/infra/schedule/schedule.module.d.ts +8 -0
- package/dist/infra/schedule/schedule.module.js +27 -0
- package/dist/infra/schedule/scheduled-runs.d.ts +69 -0
- package/dist/infra/schedule/scheduled-runs.js +163 -0
- package/dist/infra/swagger/swagger.d.ts +16 -0
- package/dist/infra/swagger/swagger.js +31 -0
- package/dist/infra/throttler/credential-throttler.d.ts +35 -0
- package/dist/infra/throttler/credential-throttler.js +77 -0
- package/dist/infra/throttler/named-throttlers.d.ts +36 -0
- package/dist/infra/throttler/named-throttlers.js +157 -0
- package/dist/infra/throttler/redis-throttler-storage.d.ts +38 -0
- package/dist/infra/throttler/redis-throttler-storage.js +130 -0
- package/dist/infra/throttler/throttler.guard.d.ts +23 -0
- package/dist/infra/throttler/throttler.guard.js +68 -0
- package/dist/infra/throttler/throttler.module.d.ts +15 -0
- package/dist/infra/throttler/throttler.module.js +53 -0
- package/dist/infra/tokens.d.ts +20 -0
- package/dist/infra/tokens.js +20 -0
- package/dist/infra/validation/create-zod-dto.d.ts +23 -0
- package/dist/infra/validation/create-zod-dto.js +35 -0
- package/dist/infra/validation/parse-with-zod.d.ts +7 -0
- package/dist/infra/validation/parse-with-zod.js +12 -0
- package/dist/infra/validation/validation.module.d.ts +3 -0
- package/dist/infra/validation/validation.module.js +16 -0
- package/dist/infra/validation/zod-params.d.ts +7 -0
- package/dist/infra/validation/zod-params.js +42 -0
- package/dist/infra/validation/zod-validation.pipe.d.ts +11 -0
- package/dist/infra/validation/zod-validation.pipe.js +31 -0
- package/dist/kernel.d.ts +9 -244
- package/dist/kernel.js +8 -1305
- package/dist/kernel.module.d.ts +17 -0
- package/dist/kernel.module.js +145 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +140 -0
- package/dist/lifecycle/kernel-lifecycle.js +465 -0
- package/dist/lifecycle/tokens.d.ts +3 -0
- package/dist/lifecycle/tokens.js +3 -0
- package/dist/log-context.d.ts +2 -0
- package/dist/log-context.js +4 -0
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/embeddings.d.ts +82 -0
- package/dist/models/embeddings.js +326 -0
- package/dist/models/enablement.controller.d.ts +40 -0
- package/dist/models/enablement.controller.js +74 -0
- package/dist/models/enablement.d.ts +101 -0
- package/dist/models/enablement.js +264 -0
- package/dist/models/models.module.d.ts +7 -0
- package/dist/models/models.module.js +36 -0
- package/dist/models/org-models.schemas.d.ts +8 -0
- package/dist/models/org-models.schemas.js +22 -0
- package/dist/models/prices.d.ts +13 -5
- package/dist/models/prices.js +69 -39
- package/dist/models/purposes.controller.d.ts +6 -4
- package/dist/models/purposes.controller.js +16 -11
- package/dist/models/purposes.d.ts +103 -23
- package/dist/models/purposes.js +208 -77
- package/dist/orgs/directory-sync.controller.d.ts +1 -1
- package/dist/orgs/directory-sync.controller.js +2 -2
- package/dist/orgs/directory-sync.d.ts +74 -35
- package/dist/orgs/directory-sync.js +243 -132
- package/dist/orgs/invitations.controller.d.ts +8 -8
- package/dist/orgs/invitations.controller.js +27 -26
- package/dist/orgs/invitations.service.d.ts +12 -9
- package/dist/orgs/invitations.service.js +130 -92
- package/dist/orgs/job-ids.d.ts +8 -0
- package/dist/orgs/job-ids.js +8 -0
- package/dist/orgs/members.service.d.ts +19 -12
- package/dist/orgs/members.service.js +161 -117
- package/dist/orgs/offboarding.d.ts +61 -60
- package/dist/orgs/offboarding.js +206 -95
- package/dist/orgs/org-lock.d.ts +33 -19
- package/dist/orgs/org-lock.js +94 -35
- package/dist/orgs/org.guard.d.ts +11 -1
- package/dist/orgs/org.guard.js +45 -34
- package/dist/orgs/orgs.controller.d.ts +13 -16
- package/dist/orgs/orgs.controller.js +29 -20
- package/dist/orgs/orgs.module.d.ts +6 -0
- package/dist/orgs/orgs.module.js +71 -0
- package/dist/orgs/orgs.schemas.d.ts +8 -0
- package/dist/orgs/orgs.schemas.js +16 -0
- package/dist/orgs/orgs.service.d.ts +47 -21
- package/dist/orgs/orgs.service.js +166 -91
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +5 -1
- package/dist/orgs/settings.controller.d.ts +2 -2
- package/dist/orgs/settings.controller.js +8 -6
- package/dist/orgs/settings.service.d.ts +45 -14
- package/dist/orgs/settings.service.js +110 -51
- package/dist/overrides.d.ts +63 -0
- package/dist/overrides.js +34 -0
- package/dist/platform/actor.d.ts +48 -0
- package/dist/platform/actor.js +100 -0
- package/dist/platform/agent-docs.d.ts +18 -0
- package/dist/platform/agent-docs.js +59 -0
- package/dist/platform/availability.d.ts +14 -0
- package/dist/platform/availability.js +43 -0
- package/dist/platform/errors.d.ts +28 -0
- package/dist/platform/errors.js +65 -0
- package/dist/platform/exclusions.d.ts +11 -0
- package/dist/platform/exclusions.js +667 -0
- package/dist/platform/method.d.ts +6 -0
- package/dist/platform/method.js +15 -0
- package/dist/platform/operation.d.ts +169 -0
- package/dist/platform/operation.js +90 -0
- package/dist/platform/ops/accounts.ops.d.ts +32 -0
- package/dist/platform/ops/accounts.ops.js +291 -0
- package/dist/platform/ops/admin.ops.d.ts +36 -0
- package/dist/platform/ops/admin.ops.js +389 -0
- package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
- package/dist/platform/ops/agent-skills.ops.js +226 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +17 -0
- package/dist/platform/ops/agent-templates.ops.js +272 -0
- package/dist/platform/ops/agents.ops.d.ts +37 -0
- package/dist/platform/ops/agents.ops.js +717 -0
- package/dist/platform/ops/approvals.ops.d.ts +30 -0
- package/dist/platform/ops/approvals.ops.js +116 -0
- package/dist/platform/ops/background.ops.d.ts +14 -0
- package/dist/platform/ops/background.ops.js +134 -0
- package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
- package/dist/platform/ops/catalog-admin.ops.js +599 -0
- package/dist/platform/ops/channels.ops.d.ts +16 -0
- package/dist/platform/ops/channels.ops.js +195 -0
- package/dist/platform/ops/components.ops.d.ts +46 -0
- package/dist/platform/ops/components.ops.js +853 -0
- package/dist/platform/ops/connectors.ops.d.ts +17 -0
- package/dist/platform/ops/connectors.ops.js +188 -0
- package/dist/platform/ops/conversations.ops.d.ts +30 -0
- package/dist/platform/ops/conversations.ops.js +470 -0
- package/dist/platform/ops/environments.ops.d.ts +26 -0
- package/dist/platform/ops/environments.ops.js +311 -0
- package/dist/platform/ops/errors.d.ts +16 -0
- package/dist/platform/ops/errors.js +30 -0
- package/dist/platform/ops/evals.ops.d.ts +28 -0
- package/dist/platform/ops/evals.ops.js +783 -0
- package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
- package/dist/platform/ops/extensions-admin.ops.js +372 -0
- package/dist/platform/ops/extensions.ops.d.ts +25 -0
- package/dist/platform/ops/extensions.ops.js +347 -0
- package/dist/platform/ops/inbox.ops.d.ts +25 -0
- package/dist/platform/ops/inbox.ops.js +378 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +22 -0
- package/dist/platform/ops/marketplaces.ops.js +466 -0
- package/dist/platform/ops/models.ops.d.ts +25 -0
- package/dist/platform/ops/models.ops.js +232 -0
- package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
- package/dist/platform/ops/org-plugins.ops.js +329 -0
- package/dist/platform/ops/org-settings.ops.d.ts +16 -0
- package/dist/platform/ops/org-settings.ops.js +102 -0
- package/dist/platform/ops/orgs.ops.d.ts +28 -0
- package/dist/platform/ops/orgs.ops.js +295 -0
- package/dist/platform/ops/other-orgs.d.ts +20 -0
- package/dist/platform/ops/other-orgs.js +72 -0
- package/dist/platform/ops/paging.d.ts +14 -0
- package/dist/platform/ops/paging.js +20 -0
- package/dist/platform/ops/platform.ops.d.ts +28 -0
- package/dist/platform/ops/platform.ops.js +204 -0
- package/dist/platform/ops/plugins.ops.d.ts +35 -0
- package/dist/platform/ops/plugins.ops.js +476 -0
- package/dist/platform/ops/previewers.ops.d.ts +14 -0
- package/dist/platform/ops/previewers.ops.js +109 -0
- package/dist/platform/ops/requests.ops.d.ts +14 -0
- package/dist/platform/ops/requests.ops.js +191 -0
- package/dist/platform/ops/role.d.ts +4 -0
- package/dist/platform/ops/role.js +10 -0
- package/dist/platform/ops/skills.ops.d.ts +17 -0
- package/dist/platform/ops/skills.ops.js +216 -0
- package/dist/platform/ops/summary.d.ts +10 -0
- package/dist/platform/ops/summary.js +18 -0
- package/dist/platform/ops/unavailable.d.ts +23 -0
- package/dist/platform/ops/unavailable.js +118 -0
- package/dist/platform/parity.d.ts +33 -0
- package/dist/platform/parity.js +272 -0
- package/dist/platform/platform-ops.module.d.ts +39 -0
- package/dist/platform/platform-ops.module.js +122 -0
- package/dist/platform/platform.module.d.ts +8 -0
- package/dist/platform/platform.module.js +25 -0
- package/dist/platform/registry.d.ts +30 -0
- package/dist/platform/registry.js +111 -0
- package/dist/platform/route-schemas.d.ts +18 -0
- package/dist/platform/route-schemas.js +63 -0
- package/dist/roles/gateway-role.d.ts +54 -0
- package/dist/roles/gateway-role.js +118 -0
- package/dist/roles/gateway.module.d.ts +9 -0
- package/dist/roles/gateway.module.js +31 -0
- package/dist/roles/worker-role.d.ts +65 -0
- package/dist/roles/worker-role.js +151 -0
- package/dist/roles/worker.module.d.ts +14 -0
- package/dist/roles/worker.module.js +106 -0
- package/dist/runtime/abort.js +19 -2
- package/dist/runtime/checkpointer.d.ts +8 -3
- package/dist/runtime/checkpointer.js +87 -55
- package/dist/runtime/context/build.d.ts +21 -13
- package/dist/runtime/context/build.js +106 -29
- package/dist/runtime/context/claude-tools.d.ts +4 -1
- package/dist/runtime/context/claude-tools.js +13 -12
- package/dist/runtime/context/compaction.js +24 -1
- package/dist/runtime/context/environment-paths.d.ts +40 -0
- package/dist/runtime/context/environment-paths.js +48 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/reminders.d.ts +2 -0
- package/dist/runtime/context/reminders.js +2 -0
- package/dist/runtime/context/run-context.d.ts +65 -0
- package/dist/runtime/context/run-context.js +215 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +46 -32
- package/dist/runtime/context/tool-changes.d.ts +27 -0
- package/dist/runtime/context/tool-changes.js +60 -0
- package/dist/runtime/conversation-lock.d.ts +20 -11
- package/dist/runtime/conversation-lock.js +62 -72
- package/dist/runtime/hook-calls.d.ts +11 -4
- package/dist/runtime/hook-calls.js +41 -13
- package/dist/runtime/job-ids.d.ts +10 -0
- package/dist/runtime/job-ids.js +10 -0
- package/dist/runtime/langgraph-loop.d.ts +3 -1
- package/dist/runtime/langgraph-loop.js +37 -18
- package/dist/runtime/loop.d.ts +42 -6
- package/dist/runtime/loop.js +14 -0
- package/dist/runtime/maintenance-queue.d.ts +10 -0
- package/dist/runtime/maintenance-queue.js +10 -0
- package/dist/runtime/maintenance.d.ts +50 -74
- package/dist/runtime/maintenance.js +166 -137
- package/dist/runtime/model-call.d.ts +61 -15
- package/dist/runtime/model-call.js +128 -84
- package/dist/runtime/providers.d.ts +158 -27
- package/dist/runtime/providers.js +373 -63
- package/dist/runtime/quota.d.ts +17 -3
- package/dist/runtime/quota.js +27 -2
- package/dist/runtime/retired-schedulers.d.ts +7 -0
- package/dist/runtime/retired-schedulers.js +31 -0
- package/dist/runtime/run-context.service.d.ts +65 -0
- package/dist/runtime/run-context.service.js +236 -0
- package/dist/runtime/run-control.d.ts +43 -0
- package/dist/runtime/run-control.js +89 -0
- package/dist/runtime/run-drafts.d.ts +85 -0
- package/dist/runtime/run-drafts.js +230 -0
- package/dist/runtime/run-finish.d.ts +27 -18
- package/dist/runtime/run-finish.js +98 -51
- package/dist/runtime/run-jobs.d.ts +46 -0
- package/dist/runtime/run-jobs.js +91 -0
- package/dist/runtime/run-processors.d.ts +60 -0
- package/dist/runtime/run-processors.js +185 -0
- package/dist/runtime/run-queue.d.ts +90 -58
- package/dist/runtime/run-queue.js +566 -297
- package/dist/runtime/run-steps.d.ts +39 -0
- package/dist/runtime/run-steps.js +96 -0
- package/dist/runtime/run-worker.d.ts +134 -77
- package/dist/runtime/run-worker.js +412 -237
- package/dist/runtime/runtime.module.d.ts +10 -0
- package/dist/runtime/runtime.module.js +122 -0
- package/dist/runtime/step-log.d.ts +51 -0
- package/dist/runtime/step-log.js +111 -0
- package/dist/runtime/stream.controller.d.ts +28 -9
- package/dist/runtime/stream.controller.js +72 -13
- package/dist/runtime/stream.d.ts +27 -6
- package/dist/runtime/stream.js +102 -7
- package/dist/runtime/subagents/child.d.ts +58 -51
- package/dist/runtime/subagents/child.js +105 -86
- package/dist/runtime/subagents/definition.d.ts +32 -28
- package/dist/runtime/subagents/definition.js +89 -143
- package/dist/runtime/subagents/deliveries.d.ts +71 -0
- package/dist/runtime/subagents/deliveries.js +228 -0
- package/dist/runtime/subagents/dispatch.d.ts +197 -27
- package/dist/runtime/subagents/dispatch.js +336 -270
- package/dist/runtime/subagents/limits.d.ts +32 -8
- package/dist/runtime/subagents/limits.js +44 -8
- package/dist/runtime/subagents/messages.d.ts +95 -0
- package/dist/runtime/subagents/messages.js +328 -0
- package/dist/runtime/subagents/org-agents.d.ts +4 -4
- package/dist/runtime/subagents/org-agents.js +3 -2
- package/dist/runtime/subagents/preamble.d.ts +4 -4
- package/dist/runtime/subagents/preamble.js +9 -7
- package/dist/runtime/subagents/progress.d.ts +10 -8
- package/dist/runtime/subagents/progress.js +11 -6
- package/dist/runtime/subagents/render.d.ts +30 -0
- package/dist/runtime/subagents/render.js +53 -0
- package/dist/runtime/subagents/roster.d.ts +27 -10
- package/dist/runtime/subagents/roster.js +49 -13
- package/dist/runtime/subagents/skill-fork.d.ts +10 -10
- package/dist/runtime/subagents/skill-fork.js +23 -8
- package/dist/runtime/subagents/status.d.ts +14 -0
- package/dist/runtime/subagents/status.js +23 -0
- package/dist/runtime/subagents/subagents.service.d.ts +43 -0
- package/dist/runtime/subagents/subagents.service.js +106 -0
- package/dist/runtime/usage-report-jobs.d.ts +88 -0
- package/dist/runtime/usage-report-jobs.js +158 -0
- package/dist/runtime/usage-report.d.ts +121 -83
- package/dist/runtime/usage-report.js +355 -181
- package/dist/runtime/waits.d.ts +258 -81
- package/dist/runtime/waits.js +800 -263
- package/dist/sandbox/job-ids.d.ts +10 -0
- package/dist/sandbox/job-ids.js +10 -0
- package/dist/sandbox/jobs.d.ts +68 -0
- package/dist/sandbox/jobs.js +150 -0
- package/dist/sandbox/leases.d.ts +73 -82
- package/dist/sandbox/leases.js +162 -346
- package/dist/sandbox/providers.d.ts +46 -0
- package/dist/sandbox/providers.js +83 -0
- package/dist/sandbox/sandbox.module.d.ts +9 -0
- package/dist/sandbox/sandbox.module.js +36 -0
- package/dist/sandbox/sandbox.service.d.ts +359 -151
- package/dist/sandbox/sandbox.service.js +950 -435
- package/dist/sandbox/unreachable.d.ts +30 -0
- package/dist/sandbox/unreachable.js +108 -0
- package/dist/skills/catalog.d.ts +40 -26
- package/dist/skills/catalog.js +120 -99
- package/dist/skills/changes.controller.d.ts +11 -4
- package/dist/skills/changes.controller.js +34 -9
- package/dist/skills/changes.service.d.ts +31 -21
- package/dist/skills/changes.service.js +426 -368
- package/dist/skills/invocable.controller.d.ts +2 -2
- package/dist/skills/invocable.controller.js +10 -7
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +19 -18
- package/dist/skills/invoke.js +68 -24
- package/dist/skills/package.d.ts +20 -1
- package/dist/skills/package.js +28 -1
- package/dist/skills/skills.controller.d.ts +33 -7
- package/dist/skills/skills.controller.js +79 -12
- package/dist/skills/skills.module.d.ts +6 -0
- package/dist/skills/skills.module.js +39 -0
- package/dist/skills/skills.schemas.d.ts +48 -0
- package/dist/skills/skills.schemas.js +61 -0
- package/dist/skills/skills.service.d.ts +151 -44
- package/dist/skills/skills.service.js +636 -204
- package/dist/skills/usable.d.ts +81 -0
- package/dist/skills/usable.js +379 -0
- package/dist/storage/job-ids.d.ts +6 -0
- package/dist/storage/job-ids.js +6 -0
- package/dist/storage/purge.d.ts +22 -7
- package/dist/storage/purge.js +55 -3
- package/dist/storage/storage.module.d.ts +6 -0
- package/dist/storage/storage.module.js +23 -0
- package/dist/storage/storage.service.d.ts +18 -4
- package/dist/storage/storage.service.js +44 -3
- package/dist/time-zone.d.ts +5 -0
- package/dist/time-zone.js +19 -0
- package/dist/tools/approvals.controller.d.ts +1 -1
- package/dist/tools/approvals.controller.js +14 -11
- package/dist/tools/approvals.schemas.d.ts +21 -0
- package/dist/tools/approvals.schemas.js +15 -0
- package/dist/tools/approvals.service.d.ts +53 -27
- package/dist/tools/approvals.service.js +365 -260
- package/dist/tools/breaker.d.ts +2 -2
- package/dist/tools/breaker.js +21 -3
- package/dist/tools/builtin-names.d.ts +109 -0
- package/dist/tools/builtin-names.js +173 -0
- package/dist/tools/builtins/agent.d.ts +27 -25
- package/dist/tools/builtins/agent.js +66 -63
- package/dist/tools/builtins/ask-user.d.ts +3 -3
- package/dist/tools/builtins/ask-user.js +3 -3
- package/dist/tools/builtins/builtin-tools.d.ts +41 -0
- package/dist/tools/builtins/builtin-tools.js +151 -0
- package/dist/tools/builtins/current-time.d.ts +26 -0
- package/dist/tools/builtins/current-time.js +99 -0
- package/dist/tools/builtins/handback.d.ts +28 -0
- package/dist/tools/builtins/handback.js +53 -0
- package/dist/tools/builtins/platform.d.ts +51 -0
- package/dist/tools/builtins/platform.js +451 -0
- package/dist/tools/builtins/read-tool-output.d.ts +3 -3
- package/dist/tools/builtins/read-tool-output.js +3 -3
- package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
- package/dist/tools/builtins/sandbox/bash.js +293 -41
- package/dist/tools/builtins/sandbox/common.d.ts +137 -37
- package/dist/tools/builtins/sandbox/common.js +222 -62
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +21 -18
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +65 -51
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +19 -14
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +155 -36
- package/dist/tools/builtins/sandbox/index.d.ts +9 -5
- package/dist/tools/builtins/sandbox/index.js +13 -5
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +30 -20
- package/dist/tools/builtins/sandbox/task-output.d.ts +79 -0
- package/dist/tools/builtins/sandbox/task-output.js +334 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +113 -0
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +52 -45
- package/dist/tools/builtins/send-message.d.ts +56 -0
- package/dist/tools/builtins/send-message.js +100 -0
- package/dist/tools/builtins/skill-load.d.ts +32 -21
- package/dist/tools/builtins/skill-load.js +125 -74
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +12 -12
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +271 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +175 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +210 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/canonical-json.d.ts +6 -0
- package/dist/tools/canonical-json.js +16 -0
- package/dist/tools/connector-content.controller.d.ts +1 -1
- package/dist/tools/connector-content.controller.js +11 -6
- package/dist/tools/connector-content.d.ts +12 -15
- package/dist/tools/connector-content.js +53 -18
- package/dist/tools/connectors.controller.d.ts +16 -3
- package/dist/tools/connectors.controller.js +34 -14
- package/dist/tools/connectors.schemas.d.ts +12 -0
- package/dist/tools/connectors.schemas.js +19 -0
- package/dist/tools/connectors.service.d.ts +80 -18
- package/dist/tools/connectors.service.js +529 -358
- package/dist/tools/credentials.d.ts +20 -20
- package/dist/tools/credentials.js +55 -34
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.d.ts +29 -41
- package/dist/tools/drift.js +116 -84
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/extension-tools.controller.d.ts +14 -0
- package/dist/tools/extension-tools.controller.js +37 -0
- package/dist/tools/info.d.ts +73 -13
- package/dist/tools/info.js +151 -39
- package/dist/tools/job-ids.d.ts +13 -0
- package/dist/tools/job-ids.js +15 -0
- package/dist/tools/jobs.d.ts +24 -0
- package/dist/tools/jobs.js +69 -0
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +16 -0
- package/dist/tools/oauth/flow-paths.js +38 -0
- package/dist/tools/oauth/flow.d.ts +30 -30
- package/dist/tools/oauth/flow.js +109 -81
- package/dist/tools/oauth/oauth.controller.d.ts +3 -3
- package/dist/tools/oauth/oauth.controller.js +12 -9
- package/dist/tools/oauth/tokens.d.ts +45 -10
- package/dist/tools/oauth/tokens.js +70 -24
- package/dist/tools/org-tool-switches.d.ts +88 -0
- package/dist/tools/org-tool-switches.js +201 -0
- package/dist/tools/outputs.d.ts +13 -4
- package/dist/tools/outputs.js +48 -4
- package/dist/tools/pipeline.d.ts +108 -80
- package/dist/tools/pipeline.js +396 -409
- package/dist/tools/policy.d.ts +4 -17
- package/dist/tools/policy.js +49 -35
- package/dist/tools/questions.controller.d.ts +2 -2
- package/dist/tools/questions.controller.js +9 -6
- package/dist/tools/questions.service.d.ts +26 -25
- package/dist/tools/questions.service.js +201 -142
- package/dist/tools/registry.d.ts +215 -84
- package/dist/tools/registry.js +382 -264
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/specs.d.ts +5 -4
- package/dist/tools/specs.js +3 -1
- package/dist/tools/tools.module.d.ts +10 -0
- package/dist/tools/tools.module.js +113 -0
- package/dist/tools/validate.js +1 -1
- package/dist/ui/call-extension.d.ts +16 -0
- package/dist/ui/call-extension.js +38 -0
- package/dist/ui/embed-token.d.ts +9 -5
- package/dist/ui/embed-token.js +34 -6
- package/dist/ui/ui-stream.d.ts +22 -17
- package/dist/ui/ui-stream.js +72 -12
- package/dist/ui/ui.module.d.ts +7 -0
- package/dist/ui/ui.module.js +28 -0
- package/dist/ui/views.controller.d.ts +14 -12
- package/dist/ui/views.controller.js +32 -25
- package/dist/ui/views.d.ts +10 -57
- package/dist/ui/views.js +58 -46
- package/package.json +13 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
- package/src/migrations/0074_subagent_tree.sql +50 -0
- package/src/migrations/0075_plugin_scope.sql +61 -0
- package/src/migrations/0076_skills_created_by_nullable.sql +6 -0
- package/src/migrations/0077_scope_requests.sql +52 -0
- package/src/migrations/0078_scope_grant_switches.sql +18 -0
- package/src/migrations/0079_scope_live_install_switches.sql +19 -0
- package/src/migrations/0080_rename_enterprise_admin.sql +18 -0
- package/src/migrations/0081_platform_components.sql +129 -0
- package/src/migrations/0082_platform_migration.sql +33 -0
- package/src/migrations/0083_plugin_scope_sync_failures.sql +15 -0
- package/src/migrations/0084_org_owned_items.sql +85 -0
- package/src/migrations/0085_agent_templates_phase4.sql +45 -0
- package/src/migrations/0086_org_layering.sql +30 -0
- package/src/migrations/0087_approval_summary.sql +6 -0
- package/src/migrations/0088_environments.sql +80 -0
- package/src/migrations/0089_model_kinds_usage.sql +38 -0
- package/src/migrations/0090_initial_passwords.sql +27 -0
- package/src/migrations/0091_account_time_zone.sql +4 -0
- package/src/migrations/0092_tools_default_on.sql +27 -0
- package/src/migrations/0093_connected_environments.sql +37 -0
- package/src/migrations/0094_environment_paths_idx.sql +7 -0
- package/src/migrations/0095_environment_files_resets.sql +5 -0
- package/src/migrations/0096_environment_demoted_default.sql +18 -0
- package/src/migrations/0097_extension_installs_enabled_at.sql +16 -0
- package/src/migrations/0098_single_provider_running_first.sql +41 -0
- package/src/migrations/0099_channel_connection_guide_ack.sql +6 -0
- package/src/migrations/0100_catalog_files.sql +13 -0
- package/src/migrations/0101_marketplace_icons.sql +32 -0
- package/dist/catalog/upgrade-targets.d.ts +0 -59
- package/dist/catalog/upgrade-targets.js +0 -90
- package/dist/conversations/sandbox-status.d.ts +0 -21
- package/dist/conversations/sandbox-status.js +0 -24
- package/dist/extensions/org-config.controller.d.ts +0 -24
- package/dist/extensions/org-config.controller.js +0 -59
- package/dist/http/gateway.module.js +0 -13
- package/dist/http/health.controller.d.ts +0 -26
- package/dist/http/health.controller.js +0 -79
- package/dist/http/tokens.d.ts +0 -131
- package/dist/http/tokens.js +0 -131
- package/dist/http/zod.pipe.d.ts +0 -8
- package/dist/http/zod.pipe.js +0 -14
- package/dist/identity/enterprise-admin.d.ts +0 -14
- package/dist/identity/enterprise-admin.js +0 -27
- package/dist/identity/rate-limit.d.ts +0 -55
- package/dist/identity/rate-limit.js +0 -121
- package/dist/sandbox/lifecycle.d.ts +0 -21
- package/dist/sandbox/lifecycle.js +0 -68
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -1,28 +1,66 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
1
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { PLUGIN_MANIFEST_FILE, parseSkillMd, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
|
|
11
|
+
import { PLUGIN_MANIFEST_FILE, parseSkillMd, pluginDescription, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
|
|
12
|
+
import { getQueueToken } from "@nestjs/bullmq";
|
|
13
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
3
14
|
import { sql } from "kysely";
|
|
4
15
|
import semver from "semver";
|
|
5
16
|
import { ApiError } from "../errors.js";
|
|
17
|
+
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
18
|
+
import { ExtensionAdmin } from "../extensions/admin-view.js";
|
|
6
19
|
import { writeSnapshot } from "../extensions/approvals.js";
|
|
20
|
+
import { blobKey, ExtensionBlobs } from "../extensions/blobs.js";
|
|
21
|
+
import { ExtensionInstalls } from "../extensions/installs.js";
|
|
22
|
+
import { PluginApproveLock, PluginInstallLock } from "../extensions/locks.js";
|
|
7
23
|
import { unrunMigrations } from "../extensions/migrate-lock.js";
|
|
8
24
|
import { ExtensionPackageError, permissionSetOfPackage, readExtensionPackage, } from "../extensions/package.js";
|
|
9
25
|
import { diffPermissions, permissionKeys, WARNINGS_KEY_PREFIX, } from "../extensions/permission-set.js";
|
|
10
26
|
import { reviewHash as extensionReviewHash, migrationWarnings, permissionGroups, permissionKeyItems, } from "../extensions/permission-view.js";
|
|
27
|
+
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
11
28
|
import { audit } from "../identity/audit.js";
|
|
12
|
-
import {
|
|
29
|
+
import { assertCustomAllowed } from "../identity/settings.js";
|
|
30
|
+
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
31
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
32
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
33
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
34
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
35
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
36
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
37
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
13
38
|
import { packPackageTgz } from "../packages/tgz.js";
|
|
39
|
+
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
14
40
|
import { checkSkillFiles, SkillArchiveError } from "../skills/package.js";
|
|
41
|
+
import { StorageService } from "../storage/storage.service.js";
|
|
42
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
15
43
|
import { endpointCredentialIssues } from "../tools/endpoint.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
44
|
+
import { findConnectorIn } from "./catalog-content.js";
|
|
45
|
+
import { displayFilePaths, putDisplayFiles, sweepDisplayFiles } from "./catalog-files.js";
|
|
46
|
+
import { assertOrgsExist, assertPluginNameOwner, catalogObjectPrefix, itemConfirmations, itemScopeFacts, itemView, markVersionApplied, permissionsMismatch, precheckCatalogImport, putCatalogFiles, templateProblems, unappliedOwnVersion, writeCatalogVersion, } from "./catalog-items.js";
|
|
18
47
|
import { CLAUDE_PLUGIN_FILE, claudeContentDigest, } from "./claude/manifest.js";
|
|
19
48
|
import { CLAUDE_MCP_CONNECTOR } from "./claude/mcp.js";
|
|
20
49
|
import { item as reportItem, sortItems, } from "./claude/report.js";
|
|
21
50
|
import { isClaudePluginTree, translateClaudePlugin } from "./claude/translate.js";
|
|
51
|
+
import { CatalogItemLock } from "./locks.js";
|
|
52
|
+
import { assertNameFree, assertPackageFree, assertShareable, packageOwner, releaseExtensionClaim, shareGate, usableBy, } from "./ownership.js";
|
|
53
|
+
import { PlatformComponents } from "./platform-components.js";
|
|
54
|
+
import { PLATFORM_MIGRATION_JOB } from "./platform-migration.js";
|
|
22
55
|
import { PluginPackageError, packagePath, readPluginFiles, readPluginPackage, } from "./plugin-package.js";
|
|
56
|
+
import { hasImportRequests, importRequestOf, resolveImportRequests } from "./request-rules.js";
|
|
57
|
+
import { assertNameNotReserved } from "./reserved-names.js";
|
|
58
|
+
import { addScopeOrg } from "./scope-orgs.js";
|
|
23
59
|
import { maxSatisfying, satisfiesRange } from "./versions.js";
|
|
60
|
+
/** How long after a failed post-import platform sync the migration job runs for the item. */
|
|
61
|
+
export const PLATFORM_SYNC_RETRY_MS = 60_000;
|
|
24
62
|
/**
|
|
25
|
-
*
|
|
63
|
+
* Platform import of a plugin (package ecosystem spec §4.3): one review for every plugin, whatever
|
|
26
64
|
* it contains (an extension, skills, connector templates, dependencies), confirmed once.
|
|
27
65
|
*
|
|
28
66
|
* prepare: the tgz is always hostile input, and **nothing is written until every check passes**
|
|
@@ -32,27 +70,30 @@ import { maxSatisfying, satisfiesRange } from "./versions.js";
|
|
|
32
70
|
* refused; name ownership; a downgrade to a version with unrun migrations is refused), each skill by
|
|
33
71
|
* the skill package rules, each connector template against the connector loaded on this replica (or
|
|
34
72
|
* statically when the connector is provided by the plugin's own extension or by a dependency), the
|
|
35
|
-
* catalog name / version conflicts and the actor still
|
|
73
|
+
* catalog name / version conflicts and the actor still a super admin. Dependencies are only
|
|
36
74
|
* resolved against the imported catalog versions for the review (an unresolved one does not block
|
|
37
75
|
* the import, spec §4.1); they are never fetched. Only then is the extension handed to
|
|
38
|
-
* `ExtensionInstalls.ingest` (source `catalog`), the skill / template
|
|
39
|
-
* storage,
|
|
76
|
+
* `ExtensionInstalls.ingest` (source `catalog`), the skill / template files written to object
|
|
77
|
+
* storage, the display files (icons, setup guide files; `catalog-files.ts`) written to PG with a
|
|
78
|
+
* staging row (24 hours), and `catalog.plugin_staged` audited. A display file inside a skill
|
|
79
|
+
* directory or at a template's path goes to both places: each reader finds it where it looks.
|
|
40
80
|
*
|
|
41
81
|
* confirm: `reviewHash` must match the staging; in one transaction it deletes the staging row
|
|
42
82
|
* (confirm works once), locks the extension name and recomputes its deployment state (installed /
|
|
43
83
|
* upgraded / swapped after the review -> `plugin.review_stale`), writes the extension's permission
|
|
44
|
-
* snapshot when it is installed by this import (
|
|
45
|
-
* `extension.permissions_approved` carrying the plugin), and creates the item
|
|
46
|
-
* (`manifest` = the normalized plugin.json,
|
|
47
|
-
*
|
|
48
|
-
* deployment and enabled (`ExtensionAdminOps.install` + `enable`;
|
|
49
|
-
* restart); a failure is returned, not thrown, and an upgrade that was
|
|
50
|
-
* snapshot back.
|
|
84
|
+
* snapshot when it is installed or upgraded by this import (source web, audit
|
|
85
|
+
* `extension.permissions_approved` carrying the plugin), and creates the item (with the scope the
|
|
86
|
+
* admin chose, default `optional`) or adds the version (`manifest` = the normalized plugin.json,
|
|
87
|
+
* `extension_sha256`, the files under the staging prefix). After the commit the plugin's own
|
|
88
|
+
* extension is installed on the deployment and enabled (`ExtensionAdminOps.install` + `enable`;
|
|
89
|
+
* each replica reconciles, no restart); a failure is returned, not thrown, and an upgrade that was
|
|
90
|
+
* not installed gets its old snapshot back.
|
|
51
91
|
*
|
|
52
92
|
* Expired staging is cleaned by the maintenance job `app-staging-cleanup`
|
|
53
|
-
* ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix
|
|
54
|
-
*
|
|
55
|
-
*
|
|
93
|
+
* ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix, then the
|
|
94
|
+
* display files (`catalog_files`) nothing lists any more; a stored extension package stays in the
|
|
95
|
+
* content-addressed `extension_packages` (the same as importing the same tgz again; without an
|
|
96
|
+
* install record referencing it it is never loaded).
|
|
56
97
|
*/
|
|
57
98
|
/** How long a staged import is kept. */
|
|
58
99
|
export const PLUGIN_STAGING_TTL_MS = 24 * 3600_000;
|
|
@@ -67,6 +108,7 @@ const NOT_NPM = { provenance: { checked: false, reason: "not an npm package" } }
|
|
|
67
108
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
68
109
|
const notFound = () => new ApiError("plugin.staging_not_found", "This plugin import was not found or has expired (staged imports are kept for 24 hours); prepare it again");
|
|
69
110
|
const invalid = (problems) => new ApiError("catalog.invalid_manifest", `Invalid plugin package: ${problems[0] ?? "unknown problem"}`, problems.slice(0, 50));
|
|
111
|
+
const reviewStale = (review) => new ApiError("plugin.review_stale", `The review of plugin ${review.name} ${review.version} is out of date (it changed, or its extension on this deployment changed since it was prepared); review it again`);
|
|
70
112
|
const mismatch = (what) => new ApiError("marketplace.package_mismatch", `The downloaded package does not match the marketplace entry: ${what}`);
|
|
71
113
|
/**
|
|
72
114
|
* The API error of a plugin package that cannot be read in a catalog path: the pre-0.1.0 format ->
|
|
@@ -96,15 +138,97 @@ const fileOf = (path, data) => ({
|
|
|
96
138
|
sha256: createHash("sha256").update(data).digest("hex"),
|
|
97
139
|
data,
|
|
98
140
|
});
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
let PluginImport = class PluginImport {
|
|
142
|
+
kdb;
|
|
143
|
+
adminLock;
|
|
144
|
+
orgLock;
|
|
145
|
+
installLock;
|
|
146
|
+
approveLock;
|
|
147
|
+
itemLock;
|
|
148
|
+
config;
|
|
149
|
+
installs;
|
|
150
|
+
ops;
|
|
151
|
+
admin;
|
|
152
|
+
blobs;
|
|
153
|
+
registry;
|
|
154
|
+
log;
|
|
155
|
+
txHost;
|
|
156
|
+
platform;
|
|
157
|
+
maintenance;
|
|
158
|
+
/** Where plugin files go (the kernel's object storage; the CLI's own, see {@link useCliStorage}). */
|
|
159
|
+
files;
|
|
160
|
+
/**
|
|
161
|
+
* false: this process loads no connectors (the CLI), so a template of an unknown connector gets
|
|
162
|
+
* only the static endpoint checks and `endpointChecked: false`; the org install re-checks it
|
|
163
|
+
* against the loaded connector.
|
|
164
|
+
*/
|
|
165
|
+
connectorsLoaded = true;
|
|
166
|
+
constructor(kdb,
|
|
167
|
+
/** The super admin lock (identity/super-admin.ts): joins the caller's transaction. */
|
|
168
|
+
adminLock,
|
|
169
|
+
/** The owner org's lock: an org upload re-checks its admin under it (ruling P3-7). */
|
|
170
|
+
orgLock, installLock, approveLock, itemLock, config, storage, installs, ops, admin,
|
|
171
|
+
/** Reads a package from the package store (confirm recomputes the permission set). */
|
|
172
|
+
blobs,
|
|
173
|
+
/** Config-declared names, loaded connectors and extension versions (the extension registry). */
|
|
174
|
+
registry, log, txHost,
|
|
175
|
+
/** The platform rows of a new item's components, written after the confirm's commit. */
|
|
176
|
+
platform,
|
|
177
|
+
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
178
|
+
maintenance) {
|
|
179
|
+
this.kdb = kdb;
|
|
180
|
+
this.adminLock = adminLock;
|
|
181
|
+
this.orgLock = orgLock;
|
|
182
|
+
this.installLock = installLock;
|
|
183
|
+
this.approveLock = approveLock;
|
|
184
|
+
this.itemLock = itemLock;
|
|
185
|
+
this.config = config;
|
|
186
|
+
this.installs = installs;
|
|
187
|
+
this.ops = ops;
|
|
188
|
+
this.admin = admin;
|
|
189
|
+
this.blobs = blobs;
|
|
190
|
+
this.registry = registry;
|
|
191
|
+
this.log = log;
|
|
192
|
+
this.txHost = txHost;
|
|
193
|
+
this.platform = platform;
|
|
194
|
+
this.maintenance = maintenance;
|
|
195
|
+
this.files = storage;
|
|
196
|
+
}
|
|
197
|
+
/** The kernel-schema handle of the current context (the transaction, else the pool). */
|
|
198
|
+
get db() {
|
|
199
|
+
return this.kdb.db;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* CLI only (like `ExtensionHost.noteInspected`): plugin files go to the object store the CLI set
|
|
203
|
+
* up itself, and connector templates get static checks only (the CLI loads no connector). Called
|
|
204
|
+
* once, right after the command's context is created.
|
|
205
|
+
*/
|
|
206
|
+
useCliStorage(storage) {
|
|
207
|
+
this.files = storage;
|
|
208
|
+
this.connectorsLoaded = false;
|
|
209
|
+
this.platform.useCliStorage(storage);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The super-admin re-check under the lock, in the caller's transaction. `actor` null is the
|
|
213
|
+
* CLI (the operator of the deployment: no account to re-check, audits carry no actor), like
|
|
214
|
+
* `ExtensionInstalls.ingest`. An org upload (`owner`) re-checks the actor as an admin of the
|
|
215
|
+
* owner org under the org row lock instead (`catalog.upload`; an org deleted meanwhile -> 404
|
|
216
|
+
* `org.not_found`).
|
|
217
|
+
*/
|
|
218
|
+
async authorizeActor(actor, owner) {
|
|
219
|
+
if (owner !== undefined) {
|
|
220
|
+
if (actor === null)
|
|
221
|
+
throw new Error("an org upload has an actor");
|
|
222
|
+
await this.orgLock.lockAndAuthorize(owner.orgId, actor, "catalog.upload");
|
|
223
|
+
}
|
|
224
|
+
else if (actor === null)
|
|
225
|
+
await this.adminLock.lock();
|
|
226
|
+
else
|
|
227
|
+
await this.adminLock.lockAndAuthorize(actor);
|
|
228
|
+
}
|
|
229
|
+
/** The re-check alone, in a transaction of its own (before anything is written). */
|
|
230
|
+
async authorize(actor, owner) {
|
|
231
|
+
await this.authorizeActor(actor, owner);
|
|
108
232
|
}
|
|
109
233
|
/**
|
|
110
234
|
* Reads, checks and stages a plugin (see the file header). Returns the staging id and review.
|
|
@@ -112,7 +236,7 @@ export class PluginImport {
|
|
|
112
236
|
* versioned and published by it (the version defaulting to `0.0.0-sha256.h<12>`, spec §5.3).
|
|
113
237
|
*/
|
|
114
238
|
async prepare(actor, bytes, source, opts = {}) {
|
|
115
|
-
const maxBytes = this.
|
|
239
|
+
const maxBytes = this.config.get().packages.maxBytes;
|
|
116
240
|
const pkg = await readingPackage(() => readPluginPackage(bytes, {
|
|
117
241
|
maxBytes,
|
|
118
242
|
hostSdkVersion: SDK_VERSION,
|
|
@@ -143,7 +267,7 @@ export class PluginImport {
|
|
|
143
267
|
entryVersion: opts.fallback.entryVersion,
|
|
144
268
|
}),
|
|
145
269
|
...(claude !== undefined && { overlay: claude }),
|
|
146
|
-
allowInsecureLoopback: this.
|
|
270
|
+
allowInsecureLoopback: this.config.get().marketplaces.allowInsecureLoopback,
|
|
147
271
|
}));
|
|
148
272
|
const translated = await readingPackage(async () => readPluginFiles(t.tree, {
|
|
149
273
|
hostSdkVersion: SDK_VERSION,
|
|
@@ -194,7 +318,11 @@ export class PluginImport {
|
|
|
194
318
|
* (required with an extension: it is stored in the package store); `size` is recorded.
|
|
195
319
|
*/
|
|
196
320
|
async prepareContents(actor, pkg, tgz, source, opts) {
|
|
197
|
-
const maxBytes = this.
|
|
321
|
+
const maxBytes = this.config.get().packages.maxBytes;
|
|
322
|
+
const owner = opts.owner;
|
|
323
|
+
if (owner !== undefined && source.kind !== "file") {
|
|
324
|
+
throw new Error("an org upload is a file (ruling P3-7)");
|
|
325
|
+
}
|
|
198
326
|
// 1. Every check (nothing written)
|
|
199
327
|
const m = pkg.manifest;
|
|
200
328
|
const packageName = packageNameOf(pkg);
|
|
@@ -208,25 +336,54 @@ export class PluginImport {
|
|
|
208
336
|
? await readingPackage(() => readExtensionPackage(bytes, { maxBytes, hostSdkVersion: SDK_VERSION }))
|
|
209
337
|
: undefined;
|
|
210
338
|
const content = this.checkContent(pkg, format);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
339
|
+
// A name live for another owner (an org's for the super admin; the platform's or another
|
|
340
|
+
// org's for an org) -> 409 plugin.name_taken naming it (P3-14); the same owner adds a version
|
|
341
|
+
await assertNameFree(this.db, m.name, owner?.orgId ?? null);
|
|
342
|
+
if (owner !== undefined) {
|
|
343
|
+
// a bootstrap or marketplace plugin's name stays free for the platform (ruling P3-28)
|
|
344
|
+
await assertNameNotReserved(this.db, m.name);
|
|
345
|
+
// its npm package is an identity of this org only (ruling P3-51)
|
|
346
|
+
await assertPackageFree(this.db, packageName, owner.orgId);
|
|
347
|
+
await assertCustomContent(this.db, content);
|
|
348
|
+
}
|
|
349
|
+
// An org's own version imported but not applied: its update is retried (pre-flight F4)
|
|
350
|
+
const retry = owner !== undefined && !m.extension
|
|
351
|
+
? await unappliedOwnVersion(this.db, m.name, owner.orgId, {
|
|
352
|
+
packageName,
|
|
353
|
+
version: m.version,
|
|
354
|
+
contentDigest: pkg.contentDigest,
|
|
355
|
+
})
|
|
356
|
+
: undefined;
|
|
357
|
+
const { existing, version } = retry !== undefined
|
|
358
|
+
? { existing: { id: retry.itemId }, version: retry.version }
|
|
359
|
+
: await precheckCatalogImport(this.db, m.name, {
|
|
360
|
+
packageName,
|
|
361
|
+
version: m.version,
|
|
362
|
+
contentDigest: pkg.contentDigest,
|
|
363
|
+
...(source.integrity !== undefined && { integrity: source.integrity }),
|
|
364
|
+
...(source.detail !== undefined && { detail: source.detail }),
|
|
365
|
+
...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
|
|
366
|
+
});
|
|
219
367
|
// The catalog name space is the extension name space: a declarative plugin cannot take a
|
|
220
368
|
// config-declared or another package's extension name either
|
|
221
369
|
this.assertNotDeclared(m.name);
|
|
222
|
-
await assertPluginNameOwner(this.
|
|
370
|
+
await assertPluginNameOwner(this.db, m.name, packageName);
|
|
223
371
|
let extension;
|
|
224
372
|
if (ext) {
|
|
225
373
|
extension = await this.reviewExtension(ext, await this.extensionState(m.name, packageName));
|
|
226
|
-
await assertDowngradable(this.
|
|
374
|
+
await assertDowngradable(this.db, extension, ext.migrationSql);
|
|
375
|
+
}
|
|
376
|
+
// Display files go to PG with the staging row; skills and templates need object storage, which a
|
|
377
|
+
// bootstrap import never has (the object store may be a bootstrap plugin itself). A file that is
|
|
378
|
+
// both (an icon inside a skill directory) goes to both: the readers of each look only there
|
|
379
|
+
const displayFiles = content.files.filter((f) => content.displayPaths.has(f.path));
|
|
380
|
+
const objectFiles = content.files.filter((f) => content.objectPaths.has(f.path));
|
|
381
|
+
if (objectFiles.length > 0 && retry === undefined) {
|
|
382
|
+
if (source.kind === "bootstrap" && !this.files.available) {
|
|
383
|
+
throw new ApiError("storage.unavailable", `Bootstrap plugin ${m.name} ships skills, connector templates or agent templates, 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`);
|
|
384
|
+
}
|
|
385
|
+
this.files.assertAvailable();
|
|
227
386
|
}
|
|
228
|
-
if (content.files.length > 0)
|
|
229
|
-
this.d.storage.assertAvailable();
|
|
230
387
|
const src = {
|
|
231
388
|
kind: source.kind,
|
|
232
389
|
ref: source.ref,
|
|
@@ -234,7 +391,7 @@ export class PluginImport {
|
|
|
234
391
|
...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
|
|
235
392
|
...(source.detail !== undefined && { detail: source.detail }),
|
|
236
393
|
};
|
|
237
|
-
const dependencies = await this.resolveDependencies(m);
|
|
394
|
+
const dependencies = await this.resolveDependencies(m, owner);
|
|
238
395
|
let translation;
|
|
239
396
|
if (opts.claude !== undefined) {
|
|
240
397
|
const added = [
|
|
@@ -264,7 +421,8 @@ export class PluginImport {
|
|
|
264
421
|
contentDigest: pkg.contentDigest,
|
|
265
422
|
packageName,
|
|
266
423
|
publisher: m.publisher,
|
|
267
|
-
description: m.description,
|
|
424
|
+
description: pluginDescription(m.description).en,
|
|
425
|
+
descriptionZh: pluginDescription(m.description).zh ?? null,
|
|
268
426
|
...(m.displayName !== undefined && { displayName: m.displayName }),
|
|
269
427
|
...(m.license !== undefined && { license: m.license }),
|
|
270
428
|
...(m.homepage !== undefined && { homepage: m.homepage }),
|
|
@@ -280,14 +438,15 @@ export class PluginImport {
|
|
|
280
438
|
reviewHash: "",
|
|
281
439
|
};
|
|
282
440
|
review.reviewHash = pluginReviewHash(review, content.files);
|
|
283
|
-
// Re-check under the lock that the actor is still an
|
|
284
|
-
|
|
441
|
+
// Re-check under the lock that the actor is still a super admin (an org upload: an admin of
|
|
442
|
+
// the owner org) before writing
|
|
443
|
+
await this.authorize(actor, owner);
|
|
285
444
|
// 2. Write: the extension into the package store, files into object storage, the staging row
|
|
286
445
|
const stagingId = randomUUID();
|
|
287
446
|
const itemId = existing?.id ?? randomUUID();
|
|
288
447
|
if (ext) {
|
|
289
448
|
const bootstrap = src.kind === "bootstrap";
|
|
290
|
-
await this.
|
|
449
|
+
await this.installs.ingest(actor, bytes, bootstrap
|
|
291
450
|
? { source: "bootstrap", ref: src.ref }
|
|
292
451
|
: {
|
|
293
452
|
source: "catalog",
|
|
@@ -295,12 +454,14 @@ export class PluginImport {
|
|
|
295
454
|
}, {
|
|
296
455
|
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
297
456
|
...(bootstrap && { store: "pg" }),
|
|
457
|
+
// an org upload only stores the package (nothing runs until the super admin confirms)
|
|
458
|
+
...(owner !== undefined && { owner }),
|
|
298
459
|
});
|
|
299
460
|
}
|
|
300
461
|
let objectPrefix = null;
|
|
301
|
-
if (
|
|
462
|
+
if (objectFiles.length > 0 && retry === undefined) {
|
|
302
463
|
objectPrefix = catalogObjectPrefix(itemId, version, stagingId);
|
|
303
|
-
await putCatalogFiles(this.
|
|
464
|
+
await putCatalogFiles(this.files, objectPrefix, objectFiles);
|
|
304
465
|
}
|
|
305
466
|
const keys = ext
|
|
306
467
|
? permissionKeys(permissionSetOfPackage(ext))
|
|
@@ -321,47 +482,58 @@ export class PluginImport {
|
|
|
321
482
|
...(translation !== undefined && { translation }),
|
|
322
483
|
...(license.text !== undefined && { licenseText: license.text }),
|
|
323
484
|
...(license.truncated && { licenseTruncated: true }),
|
|
485
|
+
...(retry !== undefined && { retry: true }),
|
|
324
486
|
};
|
|
325
|
-
await this.
|
|
326
|
-
await authorizeActor(trx, actor);
|
|
327
|
-
await trx
|
|
328
|
-
.insertInto("plugin_import_staging")
|
|
329
|
-
.values({
|
|
330
|
-
id: stagingId,
|
|
331
|
-
review: JSON.stringify(review),
|
|
332
|
-
manifest: JSON.stringify(staged),
|
|
333
|
-
object_prefix: objectPrefix,
|
|
334
|
-
source: JSON.stringify(src),
|
|
335
|
-
created_by: actor,
|
|
336
|
-
expires_at: new Date(Date.now() + PLUGIN_STAGING_TTL_MS),
|
|
337
|
-
})
|
|
338
|
-
.execute();
|
|
339
|
-
await audit(trx, {
|
|
340
|
-
...(actor !== null && { actorAccountId: actor }),
|
|
341
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
342
|
-
action: "catalog.plugin_staged",
|
|
343
|
-
target: stagingId,
|
|
344
|
-
detail: {
|
|
345
|
-
stagingId,
|
|
346
|
-
name: m.name,
|
|
347
|
-
version,
|
|
348
|
-
source: src.kind,
|
|
349
|
-
sourceRef: src.ref,
|
|
350
|
-
...(src.integrity !== undefined && { integrity: src.integrity }),
|
|
351
|
-
...(src.marketplaceId !== undefined && { marketplaceId: src.marketplaceId }),
|
|
352
|
-
reviewHash: review.reviewHash,
|
|
353
|
-
...(extension && {
|
|
354
|
-
extension: { sha256: extension.sha256, action: extension.action },
|
|
355
|
-
}),
|
|
356
|
-
},
|
|
357
|
-
});
|
|
358
|
-
});
|
|
487
|
+
await this.writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles);
|
|
359
488
|
return { stagingId, review, permissionKeys: keys, permissionsMismatch: mismatch };
|
|
360
489
|
}
|
|
490
|
+
/** The staging row and the `catalog.plugin_staged` audit, the actor re-checked under the lock. */
|
|
491
|
+
async writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles) {
|
|
492
|
+
const { extension } = review;
|
|
493
|
+
const t = this.db;
|
|
494
|
+
await this.authorizeActor(actor, owner);
|
|
495
|
+
// committed with the staging row that lists them (the sweep keeps what a staging lists)
|
|
496
|
+
await putDisplayFiles(t, displayFiles);
|
|
497
|
+
await t
|
|
498
|
+
.insertInto("plugin_import_staging")
|
|
499
|
+
.values({
|
|
500
|
+
id: stagingId,
|
|
501
|
+
review: JSON.stringify(review),
|
|
502
|
+
manifest: JSON.stringify(staged),
|
|
503
|
+
object_prefix: objectPrefix,
|
|
504
|
+
source: JSON.stringify(src),
|
|
505
|
+
created_by: actor,
|
|
506
|
+
expires_at: new Date(Date.now() + PLUGIN_STAGING_TTL_MS),
|
|
507
|
+
// the org's own staging (P3-8); null = the super admin's
|
|
508
|
+
org_id: owner?.orgId ?? null,
|
|
509
|
+
})
|
|
510
|
+
.execute();
|
|
511
|
+
await audit(t, {
|
|
512
|
+
...(actor !== null && { actorAccountId: actor }),
|
|
513
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
514
|
+
action: "catalog.plugin_staged",
|
|
515
|
+
target: stagingId,
|
|
516
|
+
detail: {
|
|
517
|
+
stagingId,
|
|
518
|
+
name: review.name,
|
|
519
|
+
version: staged.version,
|
|
520
|
+
source: src.kind,
|
|
521
|
+
sourceRef: src.ref,
|
|
522
|
+
...(src.integrity !== undefined && { integrity: src.integrity }),
|
|
523
|
+
...(src.marketplaceId !== undefined && { marketplaceId: src.marketplaceId }),
|
|
524
|
+
reviewHash: review.reviewHash,
|
|
525
|
+
...(extension && {
|
|
526
|
+
extension: { sha256: extension.sha256, action: extension.action },
|
|
527
|
+
}),
|
|
528
|
+
...(owner !== undefined && { orgId: owner.orgId }),
|
|
529
|
+
...opts.auditDetail,
|
|
530
|
+
},
|
|
531
|
+
});
|
|
532
|
+
}
|
|
361
533
|
/** Fetches a plugin from the configured npm registry (verified by `dist.integrity`), then prepares it. */
|
|
362
534
|
async prepareNpm(actor, input, opts = {}) {
|
|
363
|
-
const got = await this.
|
|
364
|
-
const provenance = await this.
|
|
535
|
+
const got = await this.installs.fetchNpm(input);
|
|
536
|
+
const provenance = await this.installs.fetchProvenance({
|
|
365
537
|
package: input.package,
|
|
366
538
|
version: got.version,
|
|
367
539
|
integrity: got.integrity,
|
|
@@ -370,23 +542,25 @@ export class PluginImport {
|
|
|
370
542
|
kind: "npm",
|
|
371
543
|
ref: `${input.package}@${got.version}`,
|
|
372
544
|
integrity: got.integrity,
|
|
373
|
-
detail: { registry: new URL(this.
|
|
545
|
+
detail: { registry: new URL(this.config.get().packages.npmRegistry).origin },
|
|
374
546
|
}, { ...opts, expect: { packageName: input.package }, provenance: { provenance } });
|
|
375
547
|
return { stagingId: r.stagingId, review: r.review };
|
|
376
548
|
}
|
|
377
549
|
/**
|
|
378
550
|
* A staged import's review, as prepare returned it, with a marketplace import's permission
|
|
379
551
|
* mismatch when there is one (the import page loads `?staging=<id>` with it). Unknown, expired or
|
|
380
|
-
* already confirmed -> 404 `plugin.staging_not_found`.
|
|
552
|
+
* already confirmed -> 404 `plugin.staging_not_found`. Each sees only its own staging (P3-8):
|
|
553
|
+
* the super admin's routes the platform's (no `owner`), an org's routes that org's.
|
|
381
554
|
*/
|
|
382
|
-
async staged(stagingId) {
|
|
555
|
+
async staged(stagingId, owner) {
|
|
383
556
|
if (!UUID_RE.test(stagingId))
|
|
384
557
|
throw notFound();
|
|
385
|
-
const row = await this.
|
|
558
|
+
const row = await this.db
|
|
386
559
|
.selectFrom("plugin_import_staging")
|
|
387
560
|
.select(["id", "review", "manifest"])
|
|
388
561
|
.where("id", "=", stagingId)
|
|
389
562
|
.where("expires_at", ">", sql `now()`)
|
|
563
|
+
.where(ownStaging(owner))
|
|
390
564
|
.executeTakeFirst();
|
|
391
565
|
if (!row)
|
|
392
566
|
throw notFound();
|
|
@@ -398,107 +572,468 @@ export class PluginImport {
|
|
|
398
572
|
};
|
|
399
573
|
}
|
|
400
574
|
/**
|
|
401
|
-
*
|
|
402
|
-
*
|
|
575
|
+
* What an org's staged upload targets (P3-12, pre-flight F3): its item, version and review hash,
|
|
576
|
+
* whether the item exists (a new version of the org's own plugin) or the version is imported
|
|
577
|
+
* already (F4), and the target as the platform updater reads it: the staged manifest and files,
|
|
578
|
+
* or the imported version's for a retry. Another org's staging -> 404 `plugin.staging_not_found`.
|
|
579
|
+
*/
|
|
580
|
+
async stagedTarget(stagingId, owner) {
|
|
581
|
+
if (!UUID_RE.test(stagingId))
|
|
582
|
+
throw notFound();
|
|
583
|
+
const row = await this.db
|
|
584
|
+
.selectFrom("plugin_import_staging")
|
|
585
|
+
.select(["review", "manifest", "object_prefix"])
|
|
586
|
+
.where("id", "=", stagingId)
|
|
587
|
+
.where("expires_at", ">", sql `now()`)
|
|
588
|
+
.where(ownStaging(owner))
|
|
589
|
+
.executeTakeFirst();
|
|
590
|
+
if (!row)
|
|
591
|
+
throw notFound();
|
|
592
|
+
const review = row.review;
|
|
593
|
+
const staged = row.manifest;
|
|
594
|
+
const item = await this.db
|
|
595
|
+
.selectFrom("catalog_items")
|
|
596
|
+
.select(["id", "awaiting_confirmation"])
|
|
597
|
+
.where("id", "=", staged.itemId)
|
|
598
|
+
.where("deleted_at", "is", null)
|
|
599
|
+
.where("owner_org_id", "=", owner.orgId)
|
|
600
|
+
.executeTakeFirst();
|
|
601
|
+
const imported = staged.retry === true
|
|
602
|
+
? await this.db
|
|
603
|
+
.selectFrom("catalog_item_versions")
|
|
604
|
+
.select(["version", "manifest", "object_prefix", "files", "extension_sha256"])
|
|
605
|
+
.where("item_id", "=", staged.itemId)
|
|
606
|
+
.where("version", "=", staged.version)
|
|
607
|
+
.executeTakeFirst()
|
|
608
|
+
: undefined;
|
|
609
|
+
return {
|
|
610
|
+
itemId: staged.itemId,
|
|
611
|
+
version: staged.version,
|
|
612
|
+
reviewHash: review.reviewHash,
|
|
613
|
+
extension: review.extension !== undefined,
|
|
614
|
+
existing: item !== undefined,
|
|
615
|
+
awaiting: item?.awaiting_confirmation === true,
|
|
616
|
+
retry: staged.retry === true,
|
|
617
|
+
target: imported !== undefined
|
|
618
|
+
? {
|
|
619
|
+
version: imported.version,
|
|
620
|
+
manifest: imported.manifest,
|
|
621
|
+
object_prefix: imported.object_prefix,
|
|
622
|
+
files: imported.files,
|
|
623
|
+
extension_sha256: imported.extension_sha256,
|
|
624
|
+
}
|
|
625
|
+
: {
|
|
626
|
+
version: staged.version,
|
|
627
|
+
manifest: staged.manifest,
|
|
628
|
+
object_prefix: row.object_prefix,
|
|
629
|
+
files: staged.files,
|
|
630
|
+
extension_sha256: review.extension?.sha256 ?? null,
|
|
631
|
+
},
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/** The catalog item's view (as a confirm returns it). */
|
|
635
|
+
async view(itemId) {
|
|
636
|
+
return this.itemView(itemId);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Confirms a staged import (see the file header). Returns the committed catalog item and the
|
|
640
|
+
* extension's deploy result (a failed deploy is returned, not thrown). `scope` (default
|
|
641
|
+
* `optional`) and `orgs` (only with `named`; each an existing org, else `validation_failed`) are
|
|
642
|
+
* written when this confirm creates the item; a new version of an existing item keeps its scope.
|
|
643
|
+
* The caller enqueues the scope sync of the item after this returns.
|
|
644
|
+
*
|
|
645
|
+
* An org upload (`opts.owner`, spec §14): only that org's staging; the actor re-checked as its
|
|
646
|
+
* admin; `scope` / `orgs` are not taken: a new item is owned by the org, scope `named: [owner]`,
|
|
647
|
+
* not shown to other orgs, `shareable` as given (default false). Custom deny, the name owner and
|
|
648
|
+
* the dependencies are checked again under the item name's lock. A package with an extension
|
|
649
|
+
* is stored and its extension name claimed, nothing approved or installed: the version waits
|
|
650
|
+
* for the super admin (`pending`, ruling P3-10; see {@link commit}).
|
|
403
651
|
*/
|
|
404
652
|
async confirm(actor, stagingId, input, opts = {}) {
|
|
405
653
|
if (!UUID_RE.test(stagingId))
|
|
406
654
|
throw notFound();
|
|
407
|
-
const
|
|
655
|
+
const owner = opts.owner;
|
|
656
|
+
if (owner !== undefined && (input.scope !== undefined || input.orgs !== undefined)) {
|
|
657
|
+
throw new Error("an org upload's scope is its owner's");
|
|
658
|
+
}
|
|
659
|
+
// A staging prepared by approving an org's `import` request defaults to that org (spec §5.1
|
|
660
|
+
// rule 3); the admin may still choose any scope
|
|
661
|
+
const linked = input.scope === undefined && owner === undefined
|
|
662
|
+
? await importRequestOf(this.db, stagingId)
|
|
663
|
+
: undefined;
|
|
664
|
+
const scope = owner !== undefined
|
|
665
|
+
? "named"
|
|
666
|
+
: (input.scope ?? (linked !== undefined ? "named" : "optional"));
|
|
667
|
+
const orgs = owner !== undefined
|
|
668
|
+
? [owner.orgId]
|
|
669
|
+
: (input.orgs ?? (linked !== undefined ? [linked.orgId] : undefined));
|
|
670
|
+
if (input.orgs !== undefined && scope !== "named") {
|
|
671
|
+
throw new ApiError("validation_failed", "orgs: only allowed with scope named", [
|
|
672
|
+
{ path: "orgs", message: "only allowed with scope named" },
|
|
673
|
+
]);
|
|
674
|
+
}
|
|
675
|
+
if (scope === "named" && (orgs ?? []).length === 0) {
|
|
676
|
+
throw new ApiError("validation_failed", "orgs: scope named needs at least one organization", [
|
|
677
|
+
{ path: "orgs", message: "scope named needs at least one organization" },
|
|
678
|
+
]);
|
|
679
|
+
}
|
|
680
|
+
const row = await this.db
|
|
408
681
|
.selectFrom("plugin_import_staging")
|
|
409
682
|
.selectAll()
|
|
410
683
|
.where("id", "=", stagingId)
|
|
411
684
|
.where("expires_at", ">", sql `now()`)
|
|
685
|
+
.where(ownStaging(owner))
|
|
412
686
|
.executeTakeFirst();
|
|
413
687
|
if (!row)
|
|
414
688
|
throw notFound();
|
|
415
689
|
const review = row.review;
|
|
416
690
|
const staged = row.manifest;
|
|
417
691
|
const src = row.source;
|
|
418
|
-
const stale = () => new ApiError("plugin.review_stale", `The review of plugin ${review.name} ${review.version} is out of date (it changed, or its extension on this deployment changed since it was prepared); review it again`);
|
|
419
692
|
if (input.reviewHash !== review.reviewHash)
|
|
420
|
-
throw
|
|
693
|
+
throw reviewStale(review);
|
|
421
694
|
const manifest = withPinned(staged.manifest, review, input.pinnedSuggestions);
|
|
422
695
|
const reviewed = review.extension;
|
|
423
|
-
// Read the stored package outside the transaction (unless it was already installed as is
|
|
424
|
-
|
|
425
|
-
const
|
|
426
|
-
await
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if (!used)
|
|
434
|
-
throw notFound();
|
|
435
|
-
let now;
|
|
436
|
-
let previous;
|
|
437
|
-
if (reviewed) {
|
|
438
|
-
// The same per-name advisory lock as ExtensionAdminOps.install; under it the action is
|
|
439
|
-
// recomputed from the current deployment state (installed / upgraded / swapped since the
|
|
440
|
-
// review -> stale)
|
|
441
|
-
await sql `SELECT pg_advisory_xact_lock(hashtext(${`capybara.plugin-install:${reviewed.name}`}))`.execute(trx);
|
|
442
|
-
now = {
|
|
443
|
-
...reviewed,
|
|
444
|
-
...actionOf(await this.extensionState(reviewed.name, staged.packageName, trx), reviewed.sha256),
|
|
445
|
-
};
|
|
446
|
-
if (pluginReviewHash({ ...review, extension: now }, staged.files) !== review.reviewHash) {
|
|
447
|
-
throw stale();
|
|
448
|
-
}
|
|
449
|
-
// A foreseeable deploy failure (a downgrade to a version with unrun migrations) is refused
|
|
450
|
-
// before anything is written
|
|
451
|
-
if (input.deployExtension && now.action === "upgrade" && stored) {
|
|
452
|
-
await assertDowngradable(trx, now, stored.migrationSql);
|
|
453
|
-
}
|
|
454
|
-
if (now.action === "install" || (now.action === "upgrade" && input.deployExtension)) {
|
|
455
|
-
previous = await this.approve(trx, actor, review, staged, now, stored, opts);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
const m = manifest;
|
|
459
|
-
const itemId = await writeCatalogVersion(trx, {
|
|
460
|
-
actor,
|
|
461
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
462
|
-
name: m.name,
|
|
463
|
-
packageName: staged.packageName,
|
|
464
|
-
version: staged.version,
|
|
465
|
-
contentDigest: staged.contentDigest,
|
|
466
|
-
manifest: m,
|
|
467
|
-
listing: {
|
|
468
|
-
publisher: m.publisher,
|
|
469
|
-
description: m.description,
|
|
470
|
-
displayName: m.displayName ?? null,
|
|
471
|
-
},
|
|
472
|
-
newItemId: staged.itemId,
|
|
473
|
-
source: {
|
|
474
|
-
source: src.kind,
|
|
475
|
-
ref: src.ref,
|
|
476
|
-
...(src.integrity !== undefined && { integrity: src.integrity }),
|
|
477
|
-
...(src.detail !== undefined && { detail: src.detail }),
|
|
478
|
-
},
|
|
479
|
-
...(src.marketplaceId !== undefined && { marketplaceId: src.marketplaceId }),
|
|
480
|
-
objectPrefix: row.object_prefix,
|
|
481
|
-
extensionSha256: reviewed?.sha256 ?? null,
|
|
482
|
-
files: staged.files,
|
|
483
|
-
size: staged.size,
|
|
484
|
-
sourceFormat: staged.sourceFormat ?? "capybara",
|
|
485
|
-
translation: staged.translation ?? null,
|
|
486
|
-
licenseText: staged.licenseText ?? null,
|
|
487
|
-
licenseTruncated: staged.licenseTruncated === true,
|
|
488
|
-
auditDetail: {
|
|
489
|
-
stagingId,
|
|
490
|
-
deployExtension: input.deployExtension,
|
|
491
|
-
suggestedPinned: pinnedNames(manifest, review),
|
|
492
|
-
...(now && { extension: { name: now.name, version: now.version, action: now.action } }),
|
|
493
|
-
},
|
|
494
|
-
});
|
|
495
|
-
return { itemId, now, previous };
|
|
496
|
-
});
|
|
696
|
+
// Read the stored package outside the transaction (unless it was already installed as is, or
|
|
697
|
+
// an org upload, which approves nothing)
|
|
698
|
+
const stored = reviewed && reviewed.action !== "keep" && owner === undefined
|
|
699
|
+
? await this.readStored(reviewed.sha256)
|
|
700
|
+
: undefined;
|
|
701
|
+
const committed = await this.commit(actor, { stagingId, review, staged, src, manifest, objectPrefix: row.object_prefix }, {
|
|
702
|
+
scope,
|
|
703
|
+
orgs: [...new Set(orgs ?? [])].sort(),
|
|
704
|
+
...(owner !== undefined && { owner, shareable: input.shareable ?? false }),
|
|
705
|
+
}, stored, opts);
|
|
497
706
|
const { now } = committed;
|
|
498
|
-
|
|
707
|
+
if (committed.pending) {
|
|
708
|
+
// Waits for the super admin (P3-10): no platform components, nothing deployed
|
|
709
|
+
return {
|
|
710
|
+
item: await this.itemView(committed.itemId),
|
|
711
|
+
created: committed.created,
|
|
712
|
+
deploy: null,
|
|
713
|
+
pending: true,
|
|
714
|
+
firstVersion: false,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
// A new item's skills, agent templates and connector templates become platform components
|
|
718
|
+
// (plugin scope phase 2); a new version of an existing item leaves them to the platform
|
|
719
|
+
// update. After the commit: it copies files in object storage
|
|
720
|
+
if (committed.firstVersion)
|
|
721
|
+
await this.syncPlatform(committed.itemId, staged.version);
|
|
722
|
+
const deploy = now && now.action !== "keep"
|
|
499
723
|
? await this.deploy(actor, review, committed.itemId, now, committed.previous, opts, input.enable ?? true)
|
|
500
724
|
: null;
|
|
501
|
-
return {
|
|
725
|
+
return {
|
|
726
|
+
item: await this.itemView(committed.itemId),
|
|
727
|
+
created: committed.created,
|
|
728
|
+
deploy,
|
|
729
|
+
pending: false,
|
|
730
|
+
firstVersion: committed.firstVersion,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Writes the platform components of an item's first usable version after a commit made
|
|
735
|
+
* elsewhere (the super admin's confirmation of an org upload, `CatalogScopeService`); a failure
|
|
736
|
+
* is logged and retried by the migration job (see {@link syncPlatform}).
|
|
737
|
+
*/
|
|
738
|
+
async writePlatformComponents(itemId, version) {
|
|
739
|
+
await this.syncPlatform(itemId, version);
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* The confirm's transaction: the staging row consumed, the extension's action recomputed under
|
|
743
|
+
* its install lock (stale -> `plugin.review_stale`), its snapshot approved, and the catalog
|
|
744
|
+
* version written under the item name's lock.
|
|
745
|
+
*
|
|
746
|
+
* An org upload with an extension (ruling P3-10) approves nothing: under the install lock it
|
|
747
|
+
* claims the extension name for its package (another package's -> 409
|
|
748
|
+
* `extension.name_conflict` naming its owner, before anything is written), and the version
|
|
749
|
+
* written becomes the item's pending one (`pending_version` / `_by` / `_at`; a first version
|
|
750
|
+
* also `awaiting_confirmation`). A later upload replaces the pending version (P3-11). An org
|
|
751
|
+
* upload without an extension for an item whose first version still waits (plan Task 6) replaces
|
|
752
|
+
* that upload and applies at once: the item stops waiting and the claim is released (nothing
|
|
753
|
+
* was installed under it).
|
|
754
|
+
*/
|
|
755
|
+
async commit(actor, c, scope, stored, opts) {
|
|
756
|
+
const { stagingId, review, staged, src, manifest } = c;
|
|
757
|
+
const reviewed = review.extension;
|
|
758
|
+
const stale = () => reviewStale(review);
|
|
759
|
+
const { owner } = scope;
|
|
760
|
+
await this.authorizeActor(actor, owner);
|
|
761
|
+
const t = this.db;
|
|
762
|
+
const used = await t
|
|
763
|
+
.deleteFrom("plugin_import_staging")
|
|
764
|
+
.where("id", "=", stagingId)
|
|
765
|
+
.where("expires_at", ">", sql `now()`)
|
|
766
|
+
.where(ownStaging(owner))
|
|
767
|
+
.returning("id")
|
|
768
|
+
.executeTakeFirst();
|
|
769
|
+
if (!used)
|
|
770
|
+
throw notFound();
|
|
771
|
+
if (owner !== undefined) {
|
|
772
|
+
await assertCustomContent(t, {
|
|
773
|
+
skills: review.skills,
|
|
774
|
+
agentTemplates: review.agentTemplates ?? [],
|
|
775
|
+
templates: review.connectorTemplates,
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
await assertOrgsExist(t, scope.orgs);
|
|
779
|
+
// Checked again before this upload claims anything (ruling P3-51)
|
|
780
|
+
if (owner !== undefined)
|
|
781
|
+
await assertPackageFree(t, staged.packageName, owner.orgId);
|
|
782
|
+
let now;
|
|
783
|
+
let previous;
|
|
784
|
+
if (reviewed) {
|
|
785
|
+
// The same per-name advisory lock as ExtensionAdminOps.install; under it the action is
|
|
786
|
+
// recomputed from the current deployment state (installed / upgraded / swapped since the
|
|
787
|
+
// review -> stale)
|
|
788
|
+
await this.installLock.lock(reviewed.name);
|
|
789
|
+
now = {
|
|
790
|
+
...reviewed,
|
|
791
|
+
...actionOf(await this.extensionState(reviewed.name, staged.packageName), reviewed.sha256, reviewed.version),
|
|
792
|
+
};
|
|
793
|
+
if (pluginReviewHash({ ...review, extension: now }, staged.files) !== review.reviewHash) {
|
|
794
|
+
throw stale();
|
|
795
|
+
}
|
|
796
|
+
if (owner !== undefined) {
|
|
797
|
+
// An org upload only claims the name (P3-10): the super admin approves and installs it
|
|
798
|
+
await t
|
|
799
|
+
.insertInto("extension_name_owners")
|
|
800
|
+
.values({ name: reviewed.name, package_name: staged.packageName })
|
|
801
|
+
.onConflict((oc) => oc.column("name").doNothing())
|
|
802
|
+
.execute();
|
|
803
|
+
await assertPluginNameOwner(t, reviewed.name, staged.packageName);
|
|
804
|
+
}
|
|
805
|
+
// A foreseeable deploy failure (a downgrade to a version with unrun migrations) is refused
|
|
806
|
+
// before anything is written
|
|
807
|
+
if (now.action === "upgrade" && stored) {
|
|
808
|
+
await assertDowngradable(t, now, stored.migrationSql);
|
|
809
|
+
}
|
|
810
|
+
if (owner === undefined && (now.action === "install" || now.action === "upgrade")) {
|
|
811
|
+
previous = await this.approve(actor, review, staged, now, stored, opts);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
const m = manifest;
|
|
815
|
+
await this.itemLock.lock(m.name);
|
|
816
|
+
// Under the name's lock: the first confirm of a name wins, a later one of another owner is
|
|
817
|
+
// refused naming it, before anything of it is written (P3-14)
|
|
818
|
+
await assertNameFree(t, m.name, owner?.orgId ?? null);
|
|
819
|
+
if (owner !== undefined) {
|
|
820
|
+
await assertNameNotReserved(t, m.name);
|
|
821
|
+
await this.resolveDependencies(m, owner);
|
|
822
|
+
}
|
|
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();
|
|
832
|
+
const actual = existing === undefined
|
|
833
|
+
? scope
|
|
834
|
+
: {
|
|
835
|
+
scope: existing.scope,
|
|
836
|
+
orgs: (await t
|
|
837
|
+
.selectFrom("catalog_item_scope_orgs")
|
|
838
|
+
.select("org_id")
|
|
839
|
+
.where("item_id", "=", existing.id)
|
|
840
|
+
.orderBy("org_id")
|
|
841
|
+
.execute()).map((r) => r.org_id),
|
|
842
|
+
};
|
|
843
|
+
if (staged.retry === true) {
|
|
844
|
+
// An org's own version imported already (pre-flight F4): nothing to write, the caller
|
|
845
|
+
// retries its update; it must still be there as reviewed
|
|
846
|
+
const v = existing === undefined
|
|
847
|
+
? undefined
|
|
848
|
+
: await t
|
|
849
|
+
.selectFrom("catalog_item_versions")
|
|
850
|
+
.select("version")
|
|
851
|
+
.where("item_id", "=", existing.id)
|
|
852
|
+
.where("version", "=", staged.version)
|
|
853
|
+
.where("content_digest", "=", staged.contentDigest)
|
|
854
|
+
.executeTakeFirst();
|
|
855
|
+
if (existing === undefined || existing.id !== staged.itemId || v === undefined)
|
|
856
|
+
throw stale();
|
|
857
|
+
return {
|
|
858
|
+
itemId: existing.id,
|
|
859
|
+
created: false,
|
|
860
|
+
firstVersion: false,
|
|
861
|
+
pending: false,
|
|
862
|
+
now,
|
|
863
|
+
previous,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
const { id: itemId, created } = await writeCatalogVersion(t, {
|
|
867
|
+
// an org's version becomes its latest only when applied or confirmed (P3-34)
|
|
868
|
+
...(owner !== undefined && { keepLatest: true }),
|
|
869
|
+
actor,
|
|
870
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
871
|
+
name: m.name,
|
|
872
|
+
packageName: staged.packageName,
|
|
873
|
+
version: staged.version,
|
|
874
|
+
contentDigest: staged.contentDigest,
|
|
875
|
+
manifest: m,
|
|
876
|
+
listing: {
|
|
877
|
+
publisher: m.publisher,
|
|
878
|
+
description: pluginDescription(m.description).en,
|
|
879
|
+
displayName: m.displayName ?? null,
|
|
880
|
+
},
|
|
881
|
+
newItemId: staged.itemId,
|
|
882
|
+
source: {
|
|
883
|
+
source: src.kind,
|
|
884
|
+
ref: src.ref,
|
|
885
|
+
...(src.integrity !== undefined && { integrity: src.integrity }),
|
|
886
|
+
...(src.detail !== undefined && { detail: src.detail }),
|
|
887
|
+
},
|
|
888
|
+
...(src.marketplaceId !== undefined && { marketplaceId: src.marketplaceId }),
|
|
889
|
+
objectPrefix: c.objectPrefix,
|
|
890
|
+
extensionSha256: reviewed?.sha256 ?? null,
|
|
891
|
+
files: staged.files,
|
|
892
|
+
size: staged.size,
|
|
893
|
+
sourceFormat: staged.sourceFormat ?? "capybara",
|
|
894
|
+
translation: staged.translation ?? null,
|
|
895
|
+
licenseText: staged.licenseText ?? null,
|
|
896
|
+
licenseTruncated: staged.licenseTruncated === true,
|
|
897
|
+
auditDetail: {
|
|
898
|
+
stagingId,
|
|
899
|
+
scope: actual.scope,
|
|
900
|
+
...(actual.scope === "named" && { orgs: actual.orgs }),
|
|
901
|
+
suggestedPinned: pinnedNames(manifest, review),
|
|
902
|
+
...(now && { extension: { name: now.name, version: now.version, action: now.action } }),
|
|
903
|
+
},
|
|
904
|
+
});
|
|
905
|
+
// A new item gets the scope chosen in the review; a new version keeps the item's scope, its
|
|
906
|
+
// org list and its scope version (prepare reuses the live item's id, so the id cannot tell)
|
|
907
|
+
if (created) {
|
|
908
|
+
await t
|
|
909
|
+
.updateTable("catalog_items")
|
|
910
|
+
.set({
|
|
911
|
+
scope: scope.scope,
|
|
912
|
+
// an org upload: the org owns it, nobody else sees it until shared and shown (P3-16)
|
|
913
|
+
...(owner !== undefined && {
|
|
914
|
+
owner_org_id: owner.orgId,
|
|
915
|
+
shareable: scope.shareable === true,
|
|
916
|
+
shown_to_others: false,
|
|
917
|
+
}),
|
|
918
|
+
})
|
|
919
|
+
.where("id", "=", itemId)
|
|
920
|
+
.execute();
|
|
921
|
+
if (scope.scope === "named" && scope.orgs.length > 0) {
|
|
922
|
+
await t
|
|
923
|
+
.insertInto("catalog_item_scope_orgs")
|
|
924
|
+
.values(scope.orgs.map((org_id) => ({ item_id: itemId, org_id })))
|
|
925
|
+
.onConflict((oc) => oc.doNothing())
|
|
926
|
+
.execute();
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
// The org requests this staging answers resolve with the confirm; on an item that existed
|
|
930
|
+
// already (imported meanwhile) a `named` scope gains their orgs. An org-owned item held back by
|
|
931
|
+
// the share gate fails closed before any request is marked (ruling P3-26; P3-14 refuses a
|
|
932
|
+
// super admin import of an org-owned name, so this should not be reached)
|
|
933
|
+
const item = created
|
|
934
|
+
? undefined
|
|
935
|
+
: await t
|
|
936
|
+
.selectFrom("catalog_items")
|
|
937
|
+
.select(["id", "name", "scope", "builtin", "owner_org_id", "shareable"])
|
|
938
|
+
.where("id", "=", itemId)
|
|
939
|
+
.forUpdate()
|
|
940
|
+
.executeTakeFirstOrThrow();
|
|
941
|
+
if (item !== undefined && !shareGate(item) && (await hasImportRequests(t, stagingId))) {
|
|
942
|
+
assertShareable(item);
|
|
943
|
+
}
|
|
944
|
+
const requestOrgs = await resolveImportRequests(t, stagingId, itemId, actor, opts);
|
|
945
|
+
if (item !== undefined) {
|
|
946
|
+
for (const org of requestOrgs)
|
|
947
|
+
await addScopeOrg(t, actor, item, org, opts);
|
|
948
|
+
}
|
|
949
|
+
const pending = owner !== undefined && reviewed !== undefined;
|
|
950
|
+
// An org's first version without an extension is installed at once: applied (P3-52)
|
|
951
|
+
if (owner !== undefined && created && !pending)
|
|
952
|
+
await markVersionApplied(t, itemId, staged.version);
|
|
953
|
+
if (pending) {
|
|
954
|
+
// Waits for the super admin; a later upload replaces the pending version (P3-10, P3-11)
|
|
955
|
+
await t
|
|
956
|
+
.updateTable("catalog_items")
|
|
957
|
+
.set({
|
|
958
|
+
...(created && { awaiting_confirmation: true }),
|
|
959
|
+
pending_version: staged.version,
|
|
960
|
+
pending_by: actor,
|
|
961
|
+
pending_at: sql `now()`,
|
|
962
|
+
})
|
|
963
|
+
.where("id", "=", itemId)
|
|
964
|
+
.execute();
|
|
965
|
+
}
|
|
966
|
+
// A first version still waiting replaced by one without an extension: applied at once
|
|
967
|
+
const replacedAwaiting = owner !== undefined && !pending && existing?.awaiting_confirmation === true;
|
|
968
|
+
if (replacedAwaiting) {
|
|
969
|
+
await t
|
|
970
|
+
.updateTable("catalog_items")
|
|
971
|
+
.set({
|
|
972
|
+
awaiting_confirmation: false,
|
|
973
|
+
pending_version: null,
|
|
974
|
+
pending_by: null,
|
|
975
|
+
pending_at: null,
|
|
976
|
+
latest_version: staged.version,
|
|
977
|
+
})
|
|
978
|
+
.where("id", "=", itemId)
|
|
979
|
+
.execute();
|
|
980
|
+
await markVersionApplied(t, itemId, staged.version);
|
|
981
|
+
await releaseExtensionClaim(t, m.name, existing.package_name);
|
|
982
|
+
}
|
|
983
|
+
return {
|
|
984
|
+
itemId,
|
|
985
|
+
created,
|
|
986
|
+
firstVersion: (created && !pending) || replacedAwaiting,
|
|
987
|
+
pending,
|
|
988
|
+
now,
|
|
989
|
+
previous,
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* The platform components of a new item. The item is committed already, so a failure is logged
|
|
994
|
+
* and not thrown (like a failed deploy, the import itself succeeded); a run of the platform
|
|
995
|
+
* components migration job (which writes what is missing) is enqueued on `cap-kernel-maintenance`
|
|
996
|
+
* after {@link PLATFORM_SYNC_RETRY_MS}, one per item (deterministic job id). If that run fails
|
|
997
|
+
* too, its `itemsFailed` shows in the super admin's inbox; the daily run and every worker start
|
|
998
|
+
* try again.
|
|
999
|
+
*/
|
|
1000
|
+
async syncPlatform(itemId, version) {
|
|
1001
|
+
try {
|
|
1002
|
+
await this.platform.syncFromVersion(itemId, version, { initial: true });
|
|
1003
|
+
}
|
|
1004
|
+
catch (err) {
|
|
1005
|
+
// Removed meanwhile (an org deletion racing a confirmation, P3-20): nothing to write
|
|
1006
|
+
const live = await this.db
|
|
1007
|
+
.selectFrom("catalog_items")
|
|
1008
|
+
.select("id")
|
|
1009
|
+
.where("id", "=", itemId)
|
|
1010
|
+
.where("deleted_at", "is", null)
|
|
1011
|
+
.executeTakeFirst();
|
|
1012
|
+
if (live === undefined) {
|
|
1013
|
+
this.log.info("catalog item removed before its platform components were written", {
|
|
1014
|
+
itemId,
|
|
1015
|
+
version,
|
|
1016
|
+
});
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
this.log.error("writing the platform components of a new catalog item failed", {
|
|
1020
|
+
itemId,
|
|
1021
|
+
version,
|
|
1022
|
+
err,
|
|
1023
|
+
});
|
|
1024
|
+
try {
|
|
1025
|
+
await this.maintenance.add(PLATFORM_MIGRATION_JOB, {}, {
|
|
1026
|
+
jobId: `${PLATFORM_MIGRATION_JOB}-retry-${itemId}`,
|
|
1027
|
+
delay: PLATFORM_SYNC_RETRY_MS,
|
|
1028
|
+
attempts: 1,
|
|
1029
|
+
removeOnComplete: true,
|
|
1030
|
+
removeOnFail: { age: 86_400 },
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
catch (e) {
|
|
1034
|
+
this.log.warn("cannot enqueue the platform components migration", { itemId, err: e });
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
502
1037
|
}
|
|
503
1038
|
/**
|
|
504
1039
|
* Writes the extension's permission snapshot for the version being imported (source web; cli
|
|
@@ -506,23 +1041,24 @@ export class PluginImport {
|
|
|
506
1041
|
* registering the name owner like ExtensionAdminOps.install (Ruling P3). Returns the snapshot it
|
|
507
1042
|
* overwrote (null when there was none).
|
|
508
1043
|
*/
|
|
509
|
-
async approve(
|
|
1044
|
+
async approve(actor, review, staged, p, pkg, opts) {
|
|
510
1045
|
const set = permissionSetOfPackage(pkg);
|
|
511
|
-
await
|
|
512
|
-
const
|
|
1046
|
+
await this.approveLock.lock(p.name);
|
|
1047
|
+
const t = this.db;
|
|
1048
|
+
const snapRow = await t
|
|
513
1049
|
.selectFrom("extension_permission_snapshots")
|
|
514
1050
|
.selectAll()
|
|
515
1051
|
.where("plugin", "=", p.name)
|
|
516
1052
|
.forUpdate()
|
|
517
1053
|
.executeTakeFirst();
|
|
518
|
-
await
|
|
1054
|
+
await t
|
|
519
1055
|
.insertInto("extension_name_owners")
|
|
520
1056
|
.values({ name: p.name, package_name: staged.packageName })
|
|
521
1057
|
.onConflict((oc) => oc.column("name").doNothing())
|
|
522
1058
|
.execute();
|
|
523
|
-
await assertPluginNameOwner(
|
|
1059
|
+
await assertPluginNameOwner(t, p.name, staged.packageName);
|
|
524
1060
|
const { added, removed } = diffPermissions(snapRow?.permissions, set);
|
|
525
|
-
await writeSnapshot(
|
|
1061
|
+
await writeSnapshot(t, p.name, p.version, set, {
|
|
526
1062
|
source: review.source.kind === "bootstrap" ? "bootstrap" : actor === null ? "cli" : "web",
|
|
527
1063
|
approvedBy: actor,
|
|
528
1064
|
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
@@ -545,7 +1081,9 @@ export class PluginImport {
|
|
|
545
1081
|
}
|
|
546
1082
|
/**
|
|
547
1083
|
* Deploys the plugin's extension after the commit: `install` (a new install is disabled, a version
|
|
548
|
-
* change keeps the desired state) then `enable
|
|
1084
|
+
* change keeps the desired state) then `enable`, unless another enabled extension provides one of
|
|
1085
|
+
* its single-provider extension points: then it stays disabled (result `installed` with code
|
|
1086
|
+
* `extension.single_provider_enabled`). Nothing is thrown; the result says what happened.
|
|
549
1087
|
* When an upgrade was not installed, the snapshot overwritten at confirm is restored (the old
|
|
550
1088
|
* version keeps running, F-O; audit `extension.permissions_restored`). Retry through the extension
|
|
551
1089
|
* admin (the package is already in the package store) with the sha256 from the result.
|
|
@@ -560,13 +1098,14 @@ export class PluginImport {
|
|
|
560
1098
|
const failure = (e) => e instanceof ApiError
|
|
561
1099
|
? { code: e.code, message: e.message }
|
|
562
1100
|
: { code: "internal", message: "Internal error" };
|
|
1101
|
+
let installed;
|
|
563
1102
|
try {
|
|
564
|
-
await this.
|
|
1103
|
+
installed = await this.ops.install(p.name, p.sha256, actor, opts.actorTokenId, {
|
|
565
1104
|
catalogItemId: itemId,
|
|
566
1105
|
});
|
|
567
1106
|
}
|
|
568
1107
|
catch (e) {
|
|
569
|
-
this.
|
|
1108
|
+
this.log.warn("installing a plugin's extension on the deployment failed", {
|
|
570
1109
|
plugin: review.name,
|
|
571
1110
|
err: e,
|
|
572
1111
|
});
|
|
@@ -579,7 +1118,7 @@ export class PluginImport {
|
|
|
579
1118
|
}
|
|
580
1119
|
}
|
|
581
1120
|
catch (err) {
|
|
582
|
-
this.
|
|
1121
|
+
this.log.error("cannot restore the permission snapshot of a plugin's extension", {
|
|
583
1122
|
plugin: p.name,
|
|
584
1123
|
err,
|
|
585
1124
|
});
|
|
@@ -587,14 +1126,22 @@ export class PluginImport {
|
|
|
587
1126
|
}
|
|
588
1127
|
return result;
|
|
589
1128
|
}
|
|
1129
|
+
// An upgrade of an enabled extension that newly provides a held single-provider point: left
|
|
1130
|
+
// disabled by the install, and why
|
|
1131
|
+
if (installed.leftDisabled !== undefined) {
|
|
1132
|
+
return { ...base, result: "installed", ...installed.leftDisabled };
|
|
1133
|
+
}
|
|
590
1134
|
if (!enable)
|
|
591
1135
|
return { ...base, result: "installed" };
|
|
592
1136
|
try {
|
|
593
|
-
await this.
|
|
594
|
-
|
|
1137
|
+
const r = await this.ops.enableUnlessOccupied(p.name, actor, opts.actorTokenId);
|
|
1138
|
+
if (r.enabled)
|
|
1139
|
+
return { ...base, result: "enabled" };
|
|
1140
|
+
// A single-provider point another enabled extension provides: installed disabled, and why
|
|
1141
|
+
return { ...base, result: "installed", ...r.note };
|
|
595
1142
|
}
|
|
596
1143
|
catch (e) {
|
|
597
|
-
this.
|
|
1144
|
+
this.log.warn("enabling a plugin's extension failed", { plugin: p.name, err: e });
|
|
598
1145
|
return { ...base, result: "failed", ...failure(e) };
|
|
599
1146
|
}
|
|
600
1147
|
}
|
|
@@ -605,59 +1152,68 @@ export class PluginImport {
|
|
|
605
1152
|
* approved or changed it meanwhile it is left alone and false is returned.
|
|
606
1153
|
*/
|
|
607
1154
|
async restoreSnapshot(actor, review, p, prev, opts) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
1155
|
+
const t = this.db;
|
|
1156
|
+
await this.approveLock.lock(p.name);
|
|
1157
|
+
const current = await t
|
|
1158
|
+
.selectFrom("extension_permission_snapshots")
|
|
1159
|
+
.select(["version", "approved_by"])
|
|
1160
|
+
.where("plugin", "=", p.name)
|
|
1161
|
+
.forUpdate()
|
|
1162
|
+
.executeTakeFirst();
|
|
1163
|
+
if (current?.version !== p.version || current.approved_by !== actor)
|
|
1164
|
+
return false;
|
|
1165
|
+
if (prev) {
|
|
1166
|
+
await t
|
|
1167
|
+
.updateTable("extension_permission_snapshots")
|
|
1168
|
+
.set({
|
|
1169
|
+
version: prev.version,
|
|
1170
|
+
permissions: JSON.stringify(prev.permissions),
|
|
1171
|
+
approved_by: prev.approvedBy,
|
|
1172
|
+
approved_at: prev.approvedAt,
|
|
1173
|
+
source: prev.source,
|
|
1174
|
+
})
|
|
613
1175
|
.where("plugin", "=", p.name)
|
|
614
|
-
.
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
631
|
-
else {
|
|
632
|
-
await trx
|
|
633
|
-
.deleteFrom("extension_permission_snapshots")
|
|
634
|
-
.where("plugin", "=", p.name)
|
|
635
|
-
.execute();
|
|
636
|
-
}
|
|
637
|
-
await audit(trx, {
|
|
638
|
-
...(actor !== null && { actorAccountId: actor }),
|
|
639
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
640
|
-
action: "extension.permissions_restored",
|
|
641
|
-
target: p.name,
|
|
642
|
-
detail: {
|
|
643
|
-
plugin: p.name,
|
|
644
|
-
restoredVersion: prev?.version ?? null,
|
|
645
|
-
reason: "plugin_deploy_failed",
|
|
646
|
-
app: { name: review.name, version: review.version },
|
|
647
|
-
},
|
|
648
|
-
});
|
|
649
|
-
return true;
|
|
1176
|
+
.execute();
|
|
1177
|
+
}
|
|
1178
|
+
else {
|
|
1179
|
+
await t.deleteFrom("extension_permission_snapshots").where("plugin", "=", p.name).execute();
|
|
1180
|
+
}
|
|
1181
|
+
await audit(t, {
|
|
1182
|
+
...(actor !== null && { actorAccountId: actor }),
|
|
1183
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
1184
|
+
action: "extension.permissions_restored",
|
|
1185
|
+
target: p.name,
|
|
1186
|
+
detail: {
|
|
1187
|
+
plugin: p.name,
|
|
1188
|
+
restoredVersion: prev?.version ?? null,
|
|
1189
|
+
reason: "plugin_deploy_failed",
|
|
1190
|
+
app: { name: review.name, version: review.version },
|
|
1191
|
+
},
|
|
650
1192
|
});
|
|
1193
|
+
return true;
|
|
651
1194
|
}
|
|
652
1195
|
/**
|
|
653
|
-
* Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`)
|
|
654
|
-
* Row by row: objects first, then the
|
|
655
|
-
*
|
|
1196
|
+
* Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`),
|
|
1197
|
+
* then the unused display files ({@link sweepDisplayFiles}). Row by row: objects first, then the
|
|
1198
|
+
* row (a failed object delete keeps the row for the next round); concurrent replicas skip each
|
|
1199
|
+
* other's rows (`SKIP LOCKED`). Returns the rows deleted.
|
|
656
1200
|
*/
|
|
657
1201
|
async cleanupExpired() {
|
|
1202
|
+
const total = await this.cleanupStagingRows();
|
|
1203
|
+
// display files no version or staging lists (an abandoned import's), older than a staging
|
|
1204
|
+
try {
|
|
1205
|
+
await sweepDisplayFiles(this.db, PLUGIN_STAGING_TTL_MS);
|
|
1206
|
+
}
|
|
1207
|
+
catch (err) {
|
|
1208
|
+
this.log.warn("cannot sweep unused catalog display files", { err });
|
|
1209
|
+
}
|
|
1210
|
+
return total;
|
|
1211
|
+
}
|
|
1212
|
+
/** The expired staging rows, batch by batch; returns the rows deleted. */
|
|
1213
|
+
async cleanupStagingRows() {
|
|
658
1214
|
let total = 0;
|
|
659
1215
|
for (;;) {
|
|
660
|
-
const batch = await this.
|
|
1216
|
+
const batch = await this.db
|
|
661
1217
|
.selectFrom("plugin_import_staging")
|
|
662
1218
|
.select(["id", "object_prefix"])
|
|
663
1219
|
.where("expires_at", "<=", sql `now()`)
|
|
@@ -669,35 +1225,100 @@ export class PluginImport {
|
|
|
669
1225
|
let progressed = 0;
|
|
670
1226
|
for (const r of batch) {
|
|
671
1227
|
try {
|
|
672
|
-
const done = await this.
|
|
673
|
-
const locked = await trx
|
|
674
|
-
.selectFrom("plugin_import_staging")
|
|
675
|
-
.select("id")
|
|
676
|
-
.where("id", "=", r.id)
|
|
677
|
-
.where("expires_at", "<=", sql `now()`)
|
|
678
|
-
.forUpdate()
|
|
679
|
-
.skipLocked()
|
|
680
|
-
.executeTakeFirst();
|
|
681
|
-
if (!locked)
|
|
682
|
-
return false;
|
|
683
|
-
if (r.object_prefix)
|
|
684
|
-
await this.d.storage.deployment().deletePrefix(r.object_prefix);
|
|
685
|
-
await trx.deleteFrom("plugin_import_staging").where("id", "=", r.id).execute();
|
|
686
|
-
return true;
|
|
687
|
-
});
|
|
1228
|
+
const done = await this.cleanupOne(r);
|
|
688
1229
|
if (done) {
|
|
689
1230
|
total++;
|
|
690
1231
|
progressed++;
|
|
691
1232
|
}
|
|
692
1233
|
}
|
|
693
1234
|
catch (err) {
|
|
694
|
-
this.
|
|
1235
|
+
this.log.warn("cannot clean up an expired plugin import", { stagingId: r.id, err });
|
|
695
1236
|
}
|
|
696
1237
|
}
|
|
697
1238
|
if (progressed === 0 || batch.length < CLEANUP_BATCH)
|
|
698
1239
|
return total;
|
|
699
1240
|
}
|
|
700
1241
|
}
|
|
1242
|
+
/**
|
|
1243
|
+
* One expired staging row (row lock, `SKIP LOCKED`): its objects, then the row; false when another
|
|
1244
|
+
* replica has it or it is gone.
|
|
1245
|
+
*/
|
|
1246
|
+
async cleanupOne(r) {
|
|
1247
|
+
const t = this.db;
|
|
1248
|
+
const locked = await t
|
|
1249
|
+
.selectFrom("plugin_import_staging")
|
|
1250
|
+
.select(["id", "org_id", "review", "manifest"])
|
|
1251
|
+
.where("id", "=", r.id)
|
|
1252
|
+
.where("expires_at", "<=", sql `now()`)
|
|
1253
|
+
.forUpdate()
|
|
1254
|
+
.skipLocked()
|
|
1255
|
+
.executeTakeFirst();
|
|
1256
|
+
if (!locked)
|
|
1257
|
+
return false;
|
|
1258
|
+
if (r.object_prefix)
|
|
1259
|
+
await this.files.deployment().deletePrefix(r.object_prefix);
|
|
1260
|
+
await t.deleteFrom("plugin_import_staging").where("id", "=", r.id).execute();
|
|
1261
|
+
await this.dropOrgPackage(locked);
|
|
1262
|
+
return true;
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* An expired org staging's extension package (an org upload stores it at prepare, P3-10): removed
|
|
1266
|
+
* with the staging unless something else uses it — an install (running or migrated), a catalog
|
|
1267
|
+
* version, another staging — or it was stored by anyone else (the package row's source must be
|
|
1268
|
+
* this staging's own `catalog` ref). A platform staging keeps its package, as before. Its object
|
|
1269
|
+
* is deleted after the commit.
|
|
1270
|
+
*/
|
|
1271
|
+
async dropOrgPackage(row) {
|
|
1272
|
+
const sha = row.review.extension?.sha256;
|
|
1273
|
+
if (row.org_id === null || sha === undefined)
|
|
1274
|
+
return;
|
|
1275
|
+
const staged = row.manifest;
|
|
1276
|
+
const t = this.db;
|
|
1277
|
+
const pkg = await t
|
|
1278
|
+
.selectFrom("extension_packages")
|
|
1279
|
+
.select("blob_store")
|
|
1280
|
+
.where("sha256", "=", sha)
|
|
1281
|
+
.where("source", "=", "catalog")
|
|
1282
|
+
.where("source_ref", "=", `${staged.itemId}@${staged.version}`)
|
|
1283
|
+
.forUpdate()
|
|
1284
|
+
.executeTakeFirst();
|
|
1285
|
+
if (!pkg)
|
|
1286
|
+
return;
|
|
1287
|
+
const used = (await t
|
|
1288
|
+
.selectFrom("extension_installs")
|
|
1289
|
+
.select("name")
|
|
1290
|
+
.where((eb) => eb.or([eb("sha256", "=", sha), eb("migrated_sha", "=", sha)]))
|
|
1291
|
+
.executeTakeFirst()) ??
|
|
1292
|
+
(await t
|
|
1293
|
+
.selectFrom("catalog_item_versions")
|
|
1294
|
+
.select("version")
|
|
1295
|
+
.where("extension_sha256", "=", sha)
|
|
1296
|
+
.executeTakeFirst()) ??
|
|
1297
|
+
(await t
|
|
1298
|
+
.selectFrom("plugin_import_staging")
|
|
1299
|
+
.select("id")
|
|
1300
|
+
.where(sql `review->'extension'->>'sha256' = ${sha}`)
|
|
1301
|
+
.executeTakeFirst());
|
|
1302
|
+
if (used !== undefined)
|
|
1303
|
+
return;
|
|
1304
|
+
// extension_blobs (a PG-stored package) goes with the row (ON DELETE CASCADE)
|
|
1305
|
+
await t.deleteFrom("extension_packages").where("sha256", "=", sha).execute();
|
|
1306
|
+
// The object only once the row is gone for good: a failure leaves an unreferenced object
|
|
1307
|
+
// (harmless; a later upload of the same bytes rewrites it), never a row without its bytes
|
|
1308
|
+
if (pkg.blob_store === "object") {
|
|
1309
|
+
afterCommit(async () => {
|
|
1310
|
+
try {
|
|
1311
|
+
await this.files.deployment().delete(blobKey(sha));
|
|
1312
|
+
}
|
|
1313
|
+
catch (err) {
|
|
1314
|
+
this.log.warn("cannot delete an expired org upload's extension package object", {
|
|
1315
|
+
sha256: sha,
|
|
1316
|
+
err,
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
701
1322
|
// ---------------------------------------------------------------------------------------------
|
|
702
1323
|
/** npm / marketplace imports: the package must be the one that was asked for. */
|
|
703
1324
|
checkExpected(pkg, expect, format = "capybara") {
|
|
@@ -723,7 +1344,7 @@ export class PluginImport {
|
|
|
723
1344
|
}
|
|
724
1345
|
/** A config-declared extension's name cannot be taken by an imported plugin. */
|
|
725
1346
|
assertNotDeclared(name) {
|
|
726
|
-
const declared = this.
|
|
1347
|
+
const declared = this.registry.declared().get(name);
|
|
727
1348
|
if (declared === "config") {
|
|
728
1349
|
throw new ApiError("extension.config_declared", `Extension ${name} is declared in the startup config (extensions); remove it there before importing a plugin with this name`);
|
|
729
1350
|
}
|
|
@@ -744,8 +1365,16 @@ export class PluginImport {
|
|
|
744
1365
|
if (data !== undefined && !stored.has(path))
|
|
745
1366
|
stored.set(path, fileOf(path, data));
|
|
746
1367
|
};
|
|
747
|
-
|
|
748
|
-
|
|
1368
|
+
const objectPaths = new Set();
|
|
1369
|
+
const keepObject = (path) => {
|
|
1370
|
+
keep(path);
|
|
1371
|
+
if (stored.has(path))
|
|
1372
|
+
objectPaths.add(path);
|
|
1373
|
+
};
|
|
1374
|
+
// The plugin icon and the setup guide templates (rendered by PluginGuides): display files
|
|
1375
|
+
const displayPaths = displayFilePaths(m, pkg.connectorTemplates.flatMap((c) => (c.file.icon === undefined ? [] : [c.file.icon])));
|
|
1376
|
+
for (const path of displayPaths)
|
|
1377
|
+
keep(path);
|
|
749
1378
|
const skills = [];
|
|
750
1379
|
for (const s of pkg.skills) {
|
|
751
1380
|
const files = s.files.map((f) => fileOf(f, pkg.files.get(`${s.dir}/${f}`)));
|
|
@@ -764,7 +1393,7 @@ export class PluginImport {
|
|
|
764
1393
|
suggestPinned: pinned.get(s.dir) === true,
|
|
765
1394
|
});
|
|
766
1395
|
for (const f of s.files)
|
|
767
|
-
|
|
1396
|
+
keepObject(`${s.dir}/${f}`);
|
|
768
1397
|
}
|
|
769
1398
|
catch (e) {
|
|
770
1399
|
if (!(e instanceof SkillArchiveError))
|
|
@@ -783,10 +1412,10 @@ export class PluginImport {
|
|
|
783
1412
|
// The result depends on which connectors the replica serving this request has loaded right
|
|
784
1413
|
// now: it is the import-time gate, not the last word (an org install checks again against the
|
|
785
1414
|
// connector of the moment)
|
|
786
|
-
const loaded = this.
|
|
1415
|
+
const loaded = findConnectorIn(this.registry, t.plugin, t.connector);
|
|
787
1416
|
if (loaded) {
|
|
788
1417
|
problems.push(...templateProblems(loaded, t, at));
|
|
789
|
-
const v = this.
|
|
1418
|
+
const v = this.registry.manifests().find((x) => x.name === t.plugin)?.version;
|
|
790
1419
|
if (t.pluginVersion !== undefined &&
|
|
791
1420
|
v !== undefined &&
|
|
792
1421
|
!satisfiesRange(v, t.pluginVersion)) {
|
|
@@ -794,7 +1423,7 @@ export class PluginImport {
|
|
|
794
1423
|
}
|
|
795
1424
|
}
|
|
796
1425
|
else if (local.has(t.plugin) ||
|
|
797
|
-
this.
|
|
1426
|
+
!this.connectorsLoaded ||
|
|
798
1427
|
(format === "claude-code" && t.plugin === CLAUDE_MCP_CONNECTOR.plugin)) {
|
|
799
1428
|
// The connector comes with this plugin or a dependency (or this process loads no
|
|
800
1429
|
// connectors, or a translated Claude template targets connector-mcp, which may not be
|
|
@@ -808,10 +1437,8 @@ export class PluginImport {
|
|
|
808
1437
|
else {
|
|
809
1438
|
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`);
|
|
810
1439
|
}
|
|
811
|
-
|
|
1440
|
+
keepObject(c.path);
|
|
812
1441
|
templatePaths.set(c.id, c.path);
|
|
813
|
-
if (c.file.icon !== undefined)
|
|
814
|
-
keep(packagePath(c.file.icon));
|
|
815
1442
|
return {
|
|
816
1443
|
id: c.id,
|
|
817
1444
|
displayName: c.file.displayName,
|
|
@@ -825,7 +1452,7 @@ export class PluginImport {
|
|
|
825
1452
|
};
|
|
826
1453
|
});
|
|
827
1454
|
const agentTemplates = pkg.agentTemplates.map((a) => {
|
|
828
|
-
|
|
1455
|
+
keepObject(a.path);
|
|
829
1456
|
const { name, description, instructions, model, ...rest } = a.template;
|
|
830
1457
|
return { name, path: a.path, description, instructions, model: model ?? "inherit", ...rest };
|
|
831
1458
|
});
|
|
@@ -833,6 +1460,8 @@ export class PluginImport {
|
|
|
833
1460
|
throw invalid(problems);
|
|
834
1461
|
return {
|
|
835
1462
|
files: [...stored.values()],
|
|
1463
|
+
displayPaths,
|
|
1464
|
+
objectPaths,
|
|
836
1465
|
templates,
|
|
837
1466
|
skills,
|
|
838
1467
|
agentTemplates,
|
|
@@ -842,33 +1471,59 @@ export class PluginImport {
|
|
|
842
1471
|
}
|
|
843
1472
|
/**
|
|
844
1473
|
* The highest imported, non-deleted catalog version satisfying each dependency's range (null when
|
|
845
|
-
* none does).
|
|
1474
|
+
* none does). An org upload (`owner`, P3-13) resolves only against items the org can use
|
|
1475
|
+
* ({@link usableBy}: confirmed, not disabled, offered to it), and any dependency left unresolved
|
|
1476
|
+
* -> 409 `plugin.dependency_unavailable` (details `[{ dependencies }]`, their names): an org
|
|
1477
|
+
* upload never brings in anything the org could not install itself.
|
|
846
1478
|
*/
|
|
847
|
-
async resolveDependencies(m) {
|
|
1479
|
+
async resolveDependencies(m, owner) {
|
|
848
1480
|
const deps = m.dependencies ?? [];
|
|
849
1481
|
if (deps.length === 0)
|
|
850
1482
|
return [];
|
|
851
|
-
const
|
|
1483
|
+
const names = deps.map((d) => d.name);
|
|
1484
|
+
const versions = this.db
|
|
852
1485
|
.selectFrom("catalog_items as i")
|
|
853
1486
|
.innerJoin("catalog_item_versions as v", "v.item_id", "i.id")
|
|
854
|
-
.select(["i.name", "v.version", "v.imported_at"])
|
|
855
1487
|
.where("i.deleted_at", "is", null)
|
|
856
|
-
.where("i.name", "in",
|
|
857
|
-
|
|
858
|
-
|
|
1488
|
+
.where("i.name", "in", names);
|
|
1489
|
+
const rows = owner === undefined
|
|
1490
|
+
? await versions.select(["i.name", "v.version", "v.imported_at"]).execute()
|
|
1491
|
+
: (await versions
|
|
1492
|
+
// the org's own row of a `named` list (usableBy reads whether it is listed)
|
|
1493
|
+
.leftJoin("catalog_item_scope_orgs as so", (j) => j.onRef("so.item_id", "=", "i.id").on("so.org_id", "=", owner.orgId))
|
|
1494
|
+
.select([
|
|
1495
|
+
"i.name",
|
|
1496
|
+
"v.version",
|
|
1497
|
+
"v.imported_at",
|
|
1498
|
+
"i.scope",
|
|
1499
|
+
"i.builtin",
|
|
1500
|
+
"i.disabled",
|
|
1501
|
+
"i.deleted_at",
|
|
1502
|
+
"i.awaiting_confirmation",
|
|
1503
|
+
"i.owner_org_id",
|
|
1504
|
+
"i.shareable",
|
|
1505
|
+
"so.org_id as listed",
|
|
1506
|
+
])
|
|
1507
|
+
.execute()).filter((r) => usableBy(r, owner.orgId, r.listed !== null));
|
|
1508
|
+
const resolved = deps.map((d) => ({
|
|
859
1509
|
name: d.name,
|
|
860
1510
|
range: d.version,
|
|
861
1511
|
resolved: maxSatisfying(rows
|
|
862
1512
|
.filter((r) => r.name === d.name)
|
|
863
1513
|
.map((r) => ({ version: r.version, importedAt: r.imported_at })), d.version)?.version ?? null,
|
|
864
1514
|
}));
|
|
1515
|
+
const missing = resolved.filter((d) => d.resolved === null).map((d) => d.name);
|
|
1516
|
+
if (owner !== undefined && missing.length > 0) {
|
|
1517
|
+
throw new ApiError("plugin.dependency_unavailable", `Dependencies not available to this organization: ${missing.join(", ")}`, [{ dependencies: missing }]);
|
|
1518
|
+
}
|
|
1519
|
+
return resolved;
|
|
865
1520
|
}
|
|
866
1521
|
/**
|
|
867
1522
|
* The extension's state on the deployment; installed from another npm package ->
|
|
868
1523
|
* `extension.name_conflict`.
|
|
869
1524
|
*/
|
|
870
|
-
async extensionState(name, packageName
|
|
871
|
-
const r = await db
|
|
1525
|
+
async extensionState(name, packageName) {
|
|
1526
|
+
const r = await this.db
|
|
872
1527
|
.selectFrom("extension_installs")
|
|
873
1528
|
.innerJoin("extension_packages", "extension_packages.sha256", "extension_installs.sha256")
|
|
874
1529
|
.select([
|
|
@@ -879,7 +1534,7 @@ export class PluginImport {
|
|
|
879
1534
|
.where("extension_installs.name", "=", name)
|
|
880
1535
|
.executeTakeFirst();
|
|
881
1536
|
if (r && r.package_name !== packageName) {
|
|
882
|
-
throw new ApiError("extension.name_conflict", `Extension ${name} is already installed from package ${r.package_name}; package ${packageName} cannot use it
|
|
1537
|
+
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) }]);
|
|
883
1538
|
}
|
|
884
1539
|
return r
|
|
885
1540
|
? { kind: "installed", version: r.version, sha256: r.sha256, packageName: r.package_name }
|
|
@@ -888,7 +1543,7 @@ export class PluginImport {
|
|
|
888
1543
|
/** The review of the extension: permissions, the change against the snapshot, warnings, action. */
|
|
889
1544
|
async reviewExtension(pkg, state) {
|
|
890
1545
|
const name = pkg.section.name;
|
|
891
|
-
const snap = await this.
|
|
1546
|
+
const snap = await this.db
|
|
892
1547
|
.selectFrom("extension_permission_snapshots")
|
|
893
1548
|
.select("permissions")
|
|
894
1549
|
.where("plugin", "=", name)
|
|
@@ -901,7 +1556,7 @@ export class PluginImport {
|
|
|
901
1556
|
name,
|
|
902
1557
|
version: pkg.section.version,
|
|
903
1558
|
sha256: pkg.sha256,
|
|
904
|
-
...actionOf(state, pkg.sha256),
|
|
1559
|
+
...actionOf(state, pkg.sha256, pkg.section.version),
|
|
905
1560
|
permissions,
|
|
906
1561
|
added,
|
|
907
1562
|
addedItems: permissionKeyItems(added),
|
|
@@ -912,26 +1567,72 @@ export class PluginImport {
|
|
|
912
1567
|
};
|
|
913
1568
|
}
|
|
914
1569
|
async readStored(sha256) {
|
|
915
|
-
const bytes = await this.
|
|
1570
|
+
const bytes = await this.blobs.get(sha256);
|
|
916
1571
|
return readingPackage(() => readExtensionPackage(bytes, {
|
|
917
|
-
maxBytes: this.
|
|
1572
|
+
maxBytes: this.config.get().packages.maxBytes,
|
|
918
1573
|
hostSdkVersion: SDK_VERSION,
|
|
919
1574
|
}));
|
|
920
1575
|
}
|
|
921
1576
|
async itemView(itemId) {
|
|
922
|
-
const item = await this.
|
|
1577
|
+
const item = await this.db
|
|
923
1578
|
.selectFrom("catalog_items")
|
|
924
1579
|
.selectAll()
|
|
925
1580
|
.where("id", "=", itemId)
|
|
926
1581
|
.executeTakeFirstOrThrow();
|
|
927
|
-
const versions = await this.
|
|
1582
|
+
const versions = await this.db
|
|
928
1583
|
.selectFrom("catalog_item_versions")
|
|
929
|
-
.select(["version", "source", "imported_at"])
|
|
1584
|
+
.select(["version", "source", "imported_at", "extension_sha256", "manifest", "source_format"])
|
|
930
1585
|
.where("item_id", "=", itemId)
|
|
931
1586
|
.execute();
|
|
932
|
-
|
|
1587
|
+
const facts = await itemScopeFacts(this.db, [item], await itemConfirmations(this.admin, [item], new Map([[item.id, versions]])));
|
|
1588
|
+
return itemView(item, versions, 0, undefined, facts.get(item.id));
|
|
933
1589
|
}
|
|
934
|
-
}
|
|
1590
|
+
};
|
|
1591
|
+
__decorate([
|
|
1592
|
+
Transactional({ propagation: "mandatory" })
|
|
1593
|
+
], PluginImport.prototype, "authorizeActor", null);
|
|
1594
|
+
__decorate([
|
|
1595
|
+
Transactional()
|
|
1596
|
+
], PluginImport.prototype, "authorize", null);
|
|
1597
|
+
__decorate([
|
|
1598
|
+
Transactional()
|
|
1599
|
+
], PluginImport.prototype, "writeStaging", null);
|
|
1600
|
+
__decorate([
|
|
1601
|
+
Transactional()
|
|
1602
|
+
], PluginImport.prototype, "commit", null);
|
|
1603
|
+
__decorate([
|
|
1604
|
+
Transactional({ propagation: "mandatory" })
|
|
1605
|
+
], PluginImport.prototype, "approve", null);
|
|
1606
|
+
__decorate([
|
|
1607
|
+
Transactional()
|
|
1608
|
+
], PluginImport.prototype, "restoreSnapshot", null);
|
|
1609
|
+
__decorate([
|
|
1610
|
+
Transactional()
|
|
1611
|
+
], PluginImport.prototype, "cleanupOne", null);
|
|
1612
|
+
__decorate([
|
|
1613
|
+
Transactional({ propagation: "mandatory" })
|
|
1614
|
+
], PluginImport.prototype, "dropOrgPackage", null);
|
|
1615
|
+
PluginImport = __decorate([
|
|
1616
|
+
Injectable(),
|
|
1617
|
+
__param(0, Inject(KernelDb)),
|
|
1618
|
+
__param(1, Inject(SuperAdminLock)),
|
|
1619
|
+
__param(2, Inject(OrgLock)),
|
|
1620
|
+
__param(3, Inject(PluginInstallLock)),
|
|
1621
|
+
__param(4, Inject(PluginApproveLock)),
|
|
1622
|
+
__param(5, Inject(CatalogItemLock)),
|
|
1623
|
+
__param(6, Inject(KernelConfigService)),
|
|
1624
|
+
__param(7, Inject(StorageService)),
|
|
1625
|
+
__param(8, Inject(ExtensionInstalls)),
|
|
1626
|
+
__param(9, Inject(ExtensionAdminOps)),
|
|
1627
|
+
__param(10, Inject(ExtensionAdmin)),
|
|
1628
|
+
__param(11, Inject(ExtensionBlobs)),
|
|
1629
|
+
__param(12, Inject(ExtensionRegistry)),
|
|
1630
|
+
__param(13, Inject(KERNEL_LOGGER)),
|
|
1631
|
+
__param(14, Inject(TransactionHost)),
|
|
1632
|
+
__param(15, Inject(PlatformComponents)),
|
|
1633
|
+
__param(16, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME)))
|
|
1634
|
+
], PluginImport);
|
|
1635
|
+
export { PluginImport };
|
|
935
1636
|
/**
|
|
936
1637
|
* plugin.json as stored on the version: skills and connector templates listed explicitly (what was
|
|
937
1638
|
* scanned when the manifest omitted them), `pinned` kept from the listing.
|
|
@@ -958,13 +1659,20 @@ function packageNameOf(pkg) {
|
|
|
958
1659
|
return typeof name === "string" ? name : null;
|
|
959
1660
|
}
|
|
960
1661
|
/** The extension's deployment state -> action and current version. */
|
|
961
|
-
function actionOf(s, sha256) {
|
|
1662
|
+
function actionOf(s, sha256, version) {
|
|
962
1663
|
if (s.kind === "installed") {
|
|
1664
|
+
// A version below the deployed one is recorded in the catalog only: an import never
|
|
1665
|
+
// downgrades the deployment (ruling H)
|
|
1666
|
+
const older = s.sha256 !== sha256 &&
|
|
1667
|
+
semver.valid(version) !== null &&
|
|
1668
|
+
semver.valid(s.version) !== null &&
|
|
1669
|
+
semver.lt(version, s.version);
|
|
963
1670
|
return {
|
|
964
|
-
action: s.sha256 === sha256 ? "keep" : "upgrade",
|
|
1671
|
+
action: s.sha256 === sha256 || older ? "keep" : "upgrade",
|
|
965
1672
|
deployed: true,
|
|
966
1673
|
currentVersion: s.version,
|
|
967
1674
|
currentSha256: s.sha256,
|
|
1675
|
+
...(older && { olderThanDeployed: true }),
|
|
968
1676
|
};
|
|
969
1677
|
}
|
|
970
1678
|
return { action: "install", deployed: false, currentVersion: null, currentSha256: null };
|
|
@@ -1067,3 +1775,22 @@ function pinnedNames(m, review) {
|
|
|
1067
1775
|
const byPath = new Map(review.skills.map((s) => [s.path, s.name]));
|
|
1068
1776
|
return (m.skills ?? []).filter((s) => s.pinned === true).map((s) => byPath.get(s.path) ?? s.path);
|
|
1069
1777
|
}
|
|
1778
|
+
/**
|
|
1779
|
+
* The staging rows a route may see (P3-8): the platform's (`org_id` null) without an owner, else
|
|
1780
|
+
* the owner org's.
|
|
1781
|
+
*/
|
|
1782
|
+
function ownStaging(owner) {
|
|
1783
|
+
return (eb) => owner === undefined ? eb("org_id", "is", null) : eb("org_id", "=", owner.orgId);
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* An org upload's custom deny, by content (ruling P3-15'): skills or agent templates ->
|
|
1787
|
+
* `customSkills`, connector templates -> `customConnectors`; each `deny` -> 403
|
|
1788
|
+
* `catalog.custom_disabled`. A package carrying neither passes.
|
|
1789
|
+
*/
|
|
1790
|
+
async function assertCustomContent(db, content) {
|
|
1791
|
+
if (content.skills.length > 0 || content.agentTemplates.length > 0) {
|
|
1792
|
+
await assertCustomAllowed(db, "customSkills");
|
|
1793
|
+
}
|
|
1794
|
+
if (content.templates.length > 0)
|
|
1795
|
+
await assertCustomAllowed(db, "customConnectors");
|
|
1796
|
+
}
|