@opengeni/api-router 0.30.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-office-import.d.ts +7 -4
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1129 -166
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +25 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +113 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +71 -3
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/files.d.ts +4 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1974 -256
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +77 -9
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +820 -222
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3170 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -38
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +839 -131
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1040 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +337 -39
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-2PQMSRCB.js +0 -49759
- package/dist/chunk-2PQMSRCB.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Context, Hono } from "hono";
|
|
3
|
+
import { HTTPException } from "hono/http-exception";
|
|
4
|
+
import { SkillFile, SKILL_MAX_FILES, type SkillWriteReceipt } from "@opengeni/contracts";
|
|
5
|
+
import { getSessionForSubject, readSkillRemovalScope } from "@opengeni/db";
|
|
6
|
+
import {
|
|
7
|
+
approveSkill,
|
|
8
|
+
rejectSkill,
|
|
9
|
+
removeSkill,
|
|
10
|
+
listSkills,
|
|
11
|
+
readSkill,
|
|
12
|
+
requireAccessGrant,
|
|
13
|
+
requireAccessGrantAuthorization,
|
|
14
|
+
restoreSkill,
|
|
15
|
+
saveSkill,
|
|
16
|
+
validateSkillFiles,
|
|
17
|
+
type ApiRouteDeps,
|
|
18
|
+
} from "@opengeni/core";
|
|
19
|
+
import { applySkillFileChanges, buildPortableSkillArtifact } from "@opengeni/runtime/skill-library";
|
|
20
|
+
import { authorizePreferenceRegistryScopeMutation } from "./preference-registry";
|
|
21
|
+
|
|
22
|
+
const scopeSchema = z.enum(["workspace", "organization", "user"]);
|
|
23
|
+
const saveRequest = z
|
|
24
|
+
.object({
|
|
25
|
+
operationId: z.uuid(),
|
|
26
|
+
skillId: z.uuid(),
|
|
27
|
+
expectedRevisionId: z.uuid().nullable(),
|
|
28
|
+
expectedScopeVersion: z.number().int().nonnegative(),
|
|
29
|
+
scope: scopeSchema.default("workspace"),
|
|
30
|
+
stableKey: z.string().min(1).max(96),
|
|
31
|
+
files: z.array(SkillFile).max(SKILL_MAX_FILES),
|
|
32
|
+
deletions: z.array(z.string().min(1).max(512)).max(SKILL_MAX_FILES).default([]),
|
|
33
|
+
reason: z.string().min(1).max(2000),
|
|
34
|
+
})
|
|
35
|
+
.strict();
|
|
36
|
+
const revisionRequest = z
|
|
37
|
+
.object({
|
|
38
|
+
removalOperationId: z.uuid().optional(),
|
|
39
|
+
operationId: z.uuid(),
|
|
40
|
+
revisionId: z.uuid(),
|
|
41
|
+
expectedRevisionId: z.uuid().nullable(),
|
|
42
|
+
expectedScopeVersion: z.number().int().nonnegative(),
|
|
43
|
+
reason: z.string().min(1).max(2000),
|
|
44
|
+
})
|
|
45
|
+
.strict();
|
|
46
|
+
|
|
47
|
+
const removeRequest = revisionRequest.omit({ revisionId: true, removalOperationId: true });
|
|
48
|
+
|
|
49
|
+
async function parseSkillRequest<S extends z.ZodType>(c: Context, schema: S): Promise<z.infer<S>> {
|
|
50
|
+
const parsed = schema.safeParse(await c.req.json().catch(() => null));
|
|
51
|
+
if (!parsed.success) throw new HTTPException(422, { message: "Invalid Skill request" });
|
|
52
|
+
return parsed.data;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function skillIdentifier(value: string): string {
|
|
56
|
+
const parsed = z.uuid().safeParse(value);
|
|
57
|
+
if (!parsed.success)
|
|
58
|
+
throw new HTTPException(422, { message: "Invalid Skill revision or identity" });
|
|
59
|
+
return parsed.data;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Human folder editing and the legacy Skill admin share scope authorization. */
|
|
63
|
+
export function registerSkillContentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
64
|
+
const base = "/v1/workspaces/:workspaceId/skills/content";
|
|
65
|
+
app.get(base, async (c) => {
|
|
66
|
+
const workspaceId = c.req.param("workspaceId");
|
|
67
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
68
|
+
const query = z
|
|
69
|
+
.object({
|
|
70
|
+
limit: z.coerce.number().int().min(1).max(250).default(100),
|
|
71
|
+
cursor: z.string().max(2048).optional(),
|
|
72
|
+
sessionId: z.uuid().optional(),
|
|
73
|
+
})
|
|
74
|
+
.safeParse(c.req.query());
|
|
75
|
+
if (!query.success) throw new HTTPException(422, { message: "Invalid Skill list query" });
|
|
76
|
+
if (query.data.sessionId) {
|
|
77
|
+
await requireAccessGrant(c, deps, workspaceId, "sessions:read");
|
|
78
|
+
const session = await getSessionForSubject(
|
|
79
|
+
deps.db,
|
|
80
|
+
workspaceId,
|
|
81
|
+
query.data.sessionId,
|
|
82
|
+
grant.subjectId,
|
|
83
|
+
);
|
|
84
|
+
if (!session) throw new HTTPException(404, { message: "Session not found" });
|
|
85
|
+
}
|
|
86
|
+
let after: { stableKey: string; id: string } | undefined;
|
|
87
|
+
if (query.data.cursor !== undefined) {
|
|
88
|
+
try {
|
|
89
|
+
after = z
|
|
90
|
+
.object({ stableKey: z.string().min(1).max(128), id: z.uuid() })
|
|
91
|
+
.strict()
|
|
92
|
+
.parse(JSON.parse(Buffer.from(query.data.cursor, "base64url").toString("utf8")));
|
|
93
|
+
} catch {
|
|
94
|
+
throw new HTTPException(422, { message: "Invalid Skill list cursor" });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const rows = await listSkills(
|
|
98
|
+
deps.db,
|
|
99
|
+
{ accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
|
|
100
|
+
{
|
|
101
|
+
limit: query.data.limit + 1,
|
|
102
|
+
metadataOnly: true,
|
|
103
|
+
...(after ? { after } : {}),
|
|
104
|
+
...(query.data.sessionId ? { sessionId: query.data.sessionId } : {}),
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
const page = rows.slice(0, query.data.limit);
|
|
108
|
+
const last = page.at(-1);
|
|
109
|
+
return c.json({
|
|
110
|
+
skills: page.map(({ files: _files, ...summary }) => summary),
|
|
111
|
+
nextCursor:
|
|
112
|
+
rows.length > query.data.limit && last
|
|
113
|
+
? Buffer.from(JSON.stringify({ stableKey: last.stableKey, id: last.id })).toString(
|
|
114
|
+
"base64url",
|
|
115
|
+
)
|
|
116
|
+
: null,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
app.get(`${base}/:skillId`, async (c) => {
|
|
120
|
+
const workspaceId = c.req.param("workspaceId");
|
|
121
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
122
|
+
const skillId = skillIdentifier(c.req.param("skillId"));
|
|
123
|
+
const revision = c.req.query("revisionId");
|
|
124
|
+
const revisionId = revision === undefined ? undefined : skillIdentifier(revision);
|
|
125
|
+
const skill = await readSkill(
|
|
126
|
+
deps.db,
|
|
127
|
+
{ accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
|
|
128
|
+
skillId,
|
|
129
|
+
revisionId,
|
|
130
|
+
);
|
|
131
|
+
if (!skill) throw new HTTPException(404, { message: "Skill not found" });
|
|
132
|
+
return c.json(skill);
|
|
133
|
+
});
|
|
134
|
+
app.post(`${base}/save`, async (c) => {
|
|
135
|
+
const workspaceId = c.req.param("workspaceId");
|
|
136
|
+
const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "workspace:read");
|
|
137
|
+
const request = await parseSkillRequest(c, saveRequest);
|
|
138
|
+
authorizePreferenceRegistryScopeMutation(access, request.scope);
|
|
139
|
+
const context = {
|
|
140
|
+
accountId: access.grant.accountId,
|
|
141
|
+
workspaceId,
|
|
142
|
+
subjectId: access.grant.subjectId,
|
|
143
|
+
};
|
|
144
|
+
const skillId = request.skillId;
|
|
145
|
+
const current = await readSkill(
|
|
146
|
+
deps.db,
|
|
147
|
+
context,
|
|
148
|
+
skillId,
|
|
149
|
+
request.expectedRevisionId ?? undefined,
|
|
150
|
+
);
|
|
151
|
+
if (request.expectedRevisionId && !current)
|
|
152
|
+
throw new HTTPException(404, { message: "Skill not found" });
|
|
153
|
+
if (current) {
|
|
154
|
+
authorizePreferenceRegistryScopeMutation(access, current.scope);
|
|
155
|
+
if (current.scope !== request.scope)
|
|
156
|
+
throw new HTTPException(409, {
|
|
157
|
+
message: "Move Skill scope through the existing scope-management workflow.",
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
let files;
|
|
161
|
+
try {
|
|
162
|
+
files = validateSkillFiles(
|
|
163
|
+
applySkillFileChanges(
|
|
164
|
+
request.expectedRevisionId ? (current?.files ?? []) : [],
|
|
165
|
+
request.files,
|
|
166
|
+
request.deletions,
|
|
167
|
+
),
|
|
168
|
+
);
|
|
169
|
+
buildPortableSkillArtifact(files);
|
|
170
|
+
} catch {
|
|
171
|
+
throw new HTTPException(400, {
|
|
172
|
+
message:
|
|
173
|
+
"Invalid Skill folder. SKILL.md requires valid YAML frontmatter with a name and description. Use unique relative text-file paths and respect the file and folder size limits.",
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const receipt = await skillMutation(() =>
|
|
177
|
+
saveSkill(deps.db, {
|
|
178
|
+
accountId: context.accountId,
|
|
179
|
+
workspaceId,
|
|
180
|
+
actor: { kind: "human", principalKind: "human_session", subjectId: context.subjectId },
|
|
181
|
+
operationId: request.operationId,
|
|
182
|
+
skillId,
|
|
183
|
+
expectedRevisionId: request.expectedRevisionId,
|
|
184
|
+
expectedScopeVersion: request.expectedScopeVersion,
|
|
185
|
+
scope: request.scope,
|
|
186
|
+
stableKey: current?.stableKey ?? request.stableKey,
|
|
187
|
+
files,
|
|
188
|
+
reason: request.reason,
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
191
|
+
return c.json(receipt);
|
|
192
|
+
});
|
|
193
|
+
app.post(`${base}/:skillId/remove`, async (c) => {
|
|
194
|
+
const workspaceId = c.req.param("workspaceId");
|
|
195
|
+
const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "workspace:read");
|
|
196
|
+
const skillId = skillIdentifier(c.req.param("skillId"));
|
|
197
|
+
const request = await parseSkillRequest(c, removeRequest);
|
|
198
|
+
const context = {
|
|
199
|
+
accountId: access.grant.accountId,
|
|
200
|
+
workspaceId,
|
|
201
|
+
subjectId: access.grant.subjectId,
|
|
202
|
+
};
|
|
203
|
+
const current = await readSkill(deps.db, context, skillId);
|
|
204
|
+
const scope =
|
|
205
|
+
current?.scope ??
|
|
206
|
+
(await readSkillRemovalScope(deps.db, context, skillId, request.operationId));
|
|
207
|
+
if (!scope) throw new HTTPException(404, { message: "Skill not found" });
|
|
208
|
+
authorizePreferenceRegistryScopeMutation(access, scope);
|
|
209
|
+
if (scope === "organization")
|
|
210
|
+
throw new HTTPException(403, { message: "Organization skills cannot be removed here." });
|
|
211
|
+
return c.json(
|
|
212
|
+
await skillMutation(() =>
|
|
213
|
+
removeSkill(deps.db, {
|
|
214
|
+
...request,
|
|
215
|
+
skillId,
|
|
216
|
+
accountId: context.accountId,
|
|
217
|
+
workspaceId,
|
|
218
|
+
actor: { kind: "human", principalKind: "human_session", subjectId: context.subjectId },
|
|
219
|
+
}),
|
|
220
|
+
),
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
for (const operation of ["approve", "reject", "restore"] as const) {
|
|
224
|
+
app.post(`${base}/:skillId/${operation}`, async (c) => {
|
|
225
|
+
const workspaceId = c.req.param("workspaceId");
|
|
226
|
+
const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "workspace:read");
|
|
227
|
+
const skillId = skillIdentifier(c.req.param("skillId"));
|
|
228
|
+
const request = await parseSkillRequest(c, revisionRequest);
|
|
229
|
+
const current = await readSkill(
|
|
230
|
+
deps.db,
|
|
231
|
+
{ accountId: access.grant.accountId, workspaceId, subjectId: access.grant.subjectId },
|
|
232
|
+
skillId,
|
|
233
|
+
);
|
|
234
|
+
const scope =
|
|
235
|
+
current?.scope ??
|
|
236
|
+
(operation === "approve" && request.removalOperationId
|
|
237
|
+
? await readSkillRemovalScope(
|
|
238
|
+
deps.db,
|
|
239
|
+
{
|
|
240
|
+
accountId: access.grant.accountId,
|
|
241
|
+
workspaceId,
|
|
242
|
+
subjectId: access.grant.subjectId,
|
|
243
|
+
},
|
|
244
|
+
skillId,
|
|
245
|
+
request.operationId,
|
|
246
|
+
)
|
|
247
|
+
: null);
|
|
248
|
+
if (!scope) throw new HTTPException(404, { message: "Skill not found" });
|
|
249
|
+
authorizePreferenceRegistryScopeMutation(access, scope);
|
|
250
|
+
const apply =
|
|
251
|
+
operation === "approve"
|
|
252
|
+
? approveSkill
|
|
253
|
+
: operation === "reject"
|
|
254
|
+
? rejectSkill
|
|
255
|
+
: restoreSkill;
|
|
256
|
+
return c.json(
|
|
257
|
+
await skillMutation(() =>
|
|
258
|
+
apply(deps.db, {
|
|
259
|
+
...request,
|
|
260
|
+
skillId,
|
|
261
|
+
accountId: access.grant.accountId,
|
|
262
|
+
workspaceId,
|
|
263
|
+
actor: {
|
|
264
|
+
kind: "human",
|
|
265
|
+
principalKind: "human_session",
|
|
266
|
+
subjectId: access.grant.subjectId,
|
|
267
|
+
},
|
|
268
|
+
}),
|
|
269
|
+
),
|
|
270
|
+
);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function skillMutation(run: () => Promise<SkillWriteReceipt>): Promise<SkillWriteReceipt> {
|
|
276
|
+
try {
|
|
277
|
+
return await run();
|
|
278
|
+
} catch (error) {
|
|
279
|
+
let current: unknown = error;
|
|
280
|
+
for (let depth = 0; depth < 4 && current && typeof current === "object"; depth++) {
|
|
281
|
+
const candidate = current as { code?: unknown; cause?: unknown };
|
|
282
|
+
if (candidate.code === "23505" || candidate.code === "40001" || candidate.code === "55P03")
|
|
283
|
+
throw new HTTPException(409, {
|
|
284
|
+
message:
|
|
285
|
+
"Skill changed or this operation key was reused. Reload and reconcile the change.",
|
|
286
|
+
});
|
|
287
|
+
if (candidate.code === "42501")
|
|
288
|
+
throw new HTTPException(403, {
|
|
289
|
+
message: "Skill change is not permitted for this actor or scope.",
|
|
290
|
+
});
|
|
291
|
+
if (candidate.code === "22023" || candidate.code === "23514")
|
|
292
|
+
throw new HTTPException(400, { message: "Skill content or revision request is invalid." });
|
|
293
|
+
current = candidate.cause;
|
|
294
|
+
}
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { SkillActor, type SkillActor as SkillActorType } from "@opengeni/contracts";
|
|
2
|
+
import {
|
|
3
|
+
requireResolvedAccessGrantAuthorization,
|
|
4
|
+
type AccessGrantAuthorization,
|
|
5
|
+
} from "@opengeni/core";
|
|
6
|
+
import { HTTPException } from "hono/http-exception";
|
|
7
|
+
|
|
8
|
+
/** Use authenticated request provenance, never a caller-supplied actor or subject alone. */
|
|
9
|
+
export function skillInstallerActor(access: AccessGrantAuthorization): SkillActorType {
|
|
10
|
+
const grant = requireResolvedAccessGrantAuthorization(access, access.grant.workspaceId);
|
|
11
|
+
const metadata = grant.metadata ?? {};
|
|
12
|
+
const hasAttempt = ["sessionId", "turnId", "attemptId", "executionGeneration"].some(
|
|
13
|
+
(key) => metadata[key] !== undefined,
|
|
14
|
+
);
|
|
15
|
+
if (hasAttempt || grant.principalKind === "agent_attempt") {
|
|
16
|
+
const parsed = SkillActor.safeParse({
|
|
17
|
+
kind: "agent",
|
|
18
|
+
sessionId: metadata.sessionId,
|
|
19
|
+
turnId: metadata.turnId,
|
|
20
|
+
attemptId: metadata.attemptId,
|
|
21
|
+
executionGeneration: metadata.executionGeneration,
|
|
22
|
+
});
|
|
23
|
+
if (!parsed.success)
|
|
24
|
+
throw new HTTPException(403, {
|
|
25
|
+
message: "Skill installation requires complete signed attempt authority.",
|
|
26
|
+
});
|
|
27
|
+
return parsed.data;
|
|
28
|
+
}
|
|
29
|
+
if (
|
|
30
|
+
grant.principalKind === "human_session" &&
|
|
31
|
+
!grant.serviceInitiator &&
|
|
32
|
+
!grant.serviceInitiatorContext &&
|
|
33
|
+
!grant.subjectId.startsWith("api_key:")
|
|
34
|
+
) {
|
|
35
|
+
return { kind: "human", principalKind: "human_session", subjectId: grant.subjectId };
|
|
36
|
+
}
|
|
37
|
+
if (
|
|
38
|
+
grant.principalKind === "service" ||
|
|
39
|
+
grant.principalKind === "api_key" ||
|
|
40
|
+
grant.principalKind === "configured_key"
|
|
41
|
+
) {
|
|
42
|
+
return { kind: "service", principalKind: grant.principalKind, subjectId: grant.subjectId };
|
|
43
|
+
}
|
|
44
|
+
throw new HTTPException(403, {
|
|
45
|
+
message:
|
|
46
|
+
"Skill installation requires authenticated human, service, or complete live-attempt authority.",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Non-Skill component removals remain available to their existing callers. */
|
|
51
|
+
export function skillRemovalActor(access: AccessGrantAuthorization): SkillActorType | undefined {
|
|
52
|
+
const grant = requireResolvedAccessGrantAuthorization(access, access.grant.workspaceId);
|
|
53
|
+
if (
|
|
54
|
+
grant.principalKind !== "human_session" ||
|
|
55
|
+
grant.serviceInitiator ||
|
|
56
|
+
grant.serviceInitiatorContext ||
|
|
57
|
+
grant.subjectId.startsWith("api_key:") ||
|
|
58
|
+
["sessionId", "turnId", "attemptId", "executionGeneration"].some(
|
|
59
|
+
(key) => grant.metadata?.[key] !== undefined,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
return undefined;
|
|
63
|
+
return skillInstallerActor(access);
|
|
64
|
+
}
|
package/src/routes/skills.ts
CHANGED
|
@@ -11,8 +11,11 @@ import {
|
|
|
11
11
|
} from "@opengeni/contracts";
|
|
12
12
|
import {
|
|
13
13
|
portableSkillCapabilityId,
|
|
14
|
+
createPublicSkillSearchClient,
|
|
15
|
+
PublicSkillSearchError,
|
|
14
16
|
portableSkillPluginKey,
|
|
15
17
|
requireAccessGrant,
|
|
18
|
+
requireAccessGrantAuthorization,
|
|
16
19
|
resolveSkillImport,
|
|
17
20
|
type ApiRouteDeps,
|
|
18
21
|
type GitHubSkillSourceClient,
|
|
@@ -23,7 +26,9 @@ import {
|
|
|
23
26
|
listInstalledSkills,
|
|
24
27
|
PortableSkillInstallationVersionConflictError,
|
|
25
28
|
PortableSkillInstallationVersionRequiredError,
|
|
29
|
+
PortableSkillSourcePathConflictError,
|
|
26
30
|
uninstallPortableSkill,
|
|
31
|
+
SkillSourceRemovalAuthorityError,
|
|
27
32
|
} from "@opengeni/db";
|
|
28
33
|
import { loadSkillLibrarySkill, skillLibraryRepositoryUrl } from "@opengeni/runtime/skill-library";
|
|
29
34
|
import { createHash } from "node:crypto";
|
|
@@ -31,6 +36,9 @@ import { HTTPException } from "hono/http-exception";
|
|
|
31
36
|
import type { Hono } from "hono";
|
|
32
37
|
|
|
33
38
|
import { createGitHubSkillSourceClient } from "../integrations/github-skill-source";
|
|
39
|
+
import { registerSkillContentRoutes } from "./skill-content";
|
|
40
|
+
import { skillInstallerActor, skillRemovalActor } from "./skill-install-authority";
|
|
41
|
+
import { parseRequestJson } from "../http/request-body";
|
|
34
42
|
|
|
35
43
|
export type SkillRouteOverrides = Readonly<{
|
|
36
44
|
github?: GitHubSkillSourceClient;
|
|
@@ -41,7 +49,24 @@ export function registerSkillRoutes(
|
|
|
41
49
|
deps: ApiRouteDeps,
|
|
42
50
|
overrides: SkillRouteOverrides = {},
|
|
43
51
|
): void {
|
|
52
|
+
registerSkillContentRoutes(app, deps);
|
|
44
53
|
const github = overrides.github ?? createGitHubSkillSourceClient(deps.settings);
|
|
54
|
+
const discovery = createPublicSkillSearchClient(deps.settings);
|
|
55
|
+
app.get("/v1/workspaces/:workspaceId/skills/search", async (c) => {
|
|
56
|
+
await requireAccessGrant(c, deps, c.req.param("workspaceId"), "workspace:read");
|
|
57
|
+
try {
|
|
58
|
+
return c.json(await discovery.search({ query: c.req.query("q") ?? "", limit: 20 }));
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (!(error instanceof PublicSkillSearchError)) throw error;
|
|
61
|
+
if (error.retryAfterSeconds) c.header("Retry-After", String(error.retryAfterSeconds));
|
|
62
|
+
throw new HTTPException(
|
|
63
|
+
error.code === "invalid_query" ? 422 : error.code === "rate_limited" ? 429 : 503,
|
|
64
|
+
{
|
|
65
|
+
message: "Skill search is unavailable. Please try again.",
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
45
70
|
|
|
46
71
|
app.get("/v1/workspaces/:workspaceId/skills", async (c) => {
|
|
47
72
|
const workspaceId = c.req.param("workspaceId");
|
|
@@ -55,9 +80,16 @@ export function registerSkillRoutes(
|
|
|
55
80
|
|
|
56
81
|
app.post("/v1/workspaces/:workspaceId/skills/library/:libraryId/install", async (c) => {
|
|
57
82
|
const workspaceId = c.req.param("workspaceId");
|
|
58
|
-
const
|
|
83
|
+
const access = await requireAccessGrantAuthorization(
|
|
84
|
+
c,
|
|
85
|
+
deps,
|
|
86
|
+
workspaceId,
|
|
87
|
+
"capabilities:manage",
|
|
88
|
+
);
|
|
89
|
+
const { grant } = access;
|
|
90
|
+
const skillActor = skillInstallerActor(access);
|
|
59
91
|
const libraryId = decodeURIComponent(c.req.param("libraryId"));
|
|
60
|
-
const payload =
|
|
92
|
+
const payload = await parseRequestJson(c, InstallLibrarySkillRequest);
|
|
61
93
|
let loaded: ReturnType<typeof loadSkillLibrarySkill>;
|
|
62
94
|
try {
|
|
63
95
|
loaded = loadSkillLibrarySkill(libraryId, payload.expectedVersion);
|
|
@@ -81,6 +113,7 @@ export function registerSkillRoutes(
|
|
|
81
113
|
});
|
|
82
114
|
try {
|
|
83
115
|
const installed = await installPortableSkill(deps.db, {
|
|
116
|
+
skillActor,
|
|
84
117
|
accountId: grant.accountId,
|
|
85
118
|
workspaceId,
|
|
86
119
|
subjectId: grant.subjectId,
|
|
@@ -118,7 +151,7 @@ export function registerSkillRoutes(
|
|
|
118
151
|
app.post("/v1/workspaces/:workspaceId/skills/preview", async (c) => {
|
|
119
152
|
const workspaceId = c.req.param("workspaceId");
|
|
120
153
|
await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
121
|
-
const payload =
|
|
154
|
+
const payload = await parseRequestJson(c, PreviewSkillImportRequest);
|
|
122
155
|
const resolved = await resolveForRoute(payload.url, github);
|
|
123
156
|
const installed = await getPortableSkillUninstallPreview(
|
|
124
157
|
deps.db,
|
|
@@ -136,16 +169,22 @@ export function registerSkillRoutes(
|
|
|
136
169
|
|
|
137
170
|
app.post("/v1/workspaces/:workspaceId/skills/install", async (c) => {
|
|
138
171
|
const workspaceId = c.req.param("workspaceId");
|
|
139
|
-
const
|
|
140
|
-
|
|
172
|
+
const access = await requireAccessGrantAuthorization(
|
|
173
|
+
c,
|
|
174
|
+
deps,
|
|
175
|
+
workspaceId,
|
|
176
|
+
"capabilities:manage",
|
|
177
|
+
);
|
|
178
|
+
const { grant } = access;
|
|
179
|
+
const skillActor = skillInstallerActor(access);
|
|
180
|
+
const payload = await parseRequestJson(c, InstallSkillRequest);
|
|
141
181
|
const resolved = await resolveForRoute(payload.url, github);
|
|
142
182
|
if (
|
|
143
183
|
resolved.preview.sourceCommit !== payload.expectedSourceCommit ||
|
|
144
184
|
resolved.preview.contentSha256 !== payload.expectedContentSha256
|
|
145
185
|
) {
|
|
146
186
|
throw new HTTPException(409, {
|
|
147
|
-
message:
|
|
148
|
-
"The Skill source changed after preview. Review the new commit and contents before installing.",
|
|
187
|
+
message: "The skill changed after preview. Review its contents again before installing.",
|
|
149
188
|
});
|
|
150
189
|
}
|
|
151
190
|
const fileSummaryByPath = new Map(
|
|
@@ -153,6 +192,7 @@ export function registerSkillRoutes(
|
|
|
153
192
|
);
|
|
154
193
|
try {
|
|
155
194
|
const installed = await installPortableSkill(deps.db, {
|
|
195
|
+
skillActor,
|
|
156
196
|
accountId: grant.accountId,
|
|
157
197
|
workspaceId,
|
|
158
198
|
subjectId: grant.subjectId,
|
|
@@ -204,13 +244,21 @@ export function registerSkillRoutes(
|
|
|
204
244
|
|
|
205
245
|
app.delete("/v1/workspaces/:workspaceId/skills/:capabilityId", async (c) => {
|
|
206
246
|
const workspaceId = c.req.param("workspaceId");
|
|
207
|
-
const
|
|
247
|
+
const access = await requireAccessGrantAuthorization(
|
|
248
|
+
c,
|
|
249
|
+
deps,
|
|
250
|
+
workspaceId,
|
|
251
|
+
"capabilities:manage",
|
|
252
|
+
);
|
|
253
|
+
const { grant } = access;
|
|
254
|
+
const skillActor = skillRemovalActor(access);
|
|
208
255
|
const capabilityId = decodeURIComponent(c.req.param("capabilityId"));
|
|
209
|
-
const payload =
|
|
256
|
+
const payload = await parseRequestJson(c, UninstallSkillRequest);
|
|
210
257
|
try {
|
|
211
258
|
return c.json(
|
|
212
259
|
UninstallSkillResult.parse(
|
|
213
260
|
await uninstallPortableSkill(deps.db, {
|
|
261
|
+
...(skillActor ? { skillActor } : {}),
|
|
214
262
|
accountId: grant.accountId,
|
|
215
263
|
workspaceId,
|
|
216
264
|
capabilityId,
|
|
@@ -224,12 +272,17 @@ export function registerSkillRoutes(
|
|
|
224
272
|
message: "The Skill changed after preview. Review uninstall impact again.",
|
|
225
273
|
});
|
|
226
274
|
}
|
|
275
|
+
if (error instanceof SkillSourceRemovalAuthorityError)
|
|
276
|
+
throw new HTTPException(403, { message: error.message });
|
|
227
277
|
throw error;
|
|
228
278
|
}
|
|
229
279
|
});
|
|
230
280
|
}
|
|
231
281
|
|
|
232
282
|
function portableSkillMutationHttpError(error: unknown): Error {
|
|
283
|
+
if (error instanceof PortableSkillSourcePathConflictError) {
|
|
284
|
+
return new HTTPException(409, { message: error.message });
|
|
285
|
+
}
|
|
233
286
|
if (error instanceof PortableSkillInstallationVersionRequiredError) {
|
|
234
287
|
return new HTTPException(400, { message: error.message });
|
|
235
288
|
}
|
package/src/routes/social.ts
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
CreateSocialConnectionRequest,
|
|
3
3
|
CreateSocialPostRequest,
|
|
4
4
|
OAuthStartResponse,
|
|
5
|
+
OrganizationIntegrationDeniedError,
|
|
5
6
|
SocialOAuthStartRequest,
|
|
6
7
|
} from "@opengeni/contracts";
|
|
8
|
+
import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
|
|
7
9
|
import {
|
|
8
10
|
createSocialConnection,
|
|
9
11
|
createSocialPost,
|
|
@@ -15,10 +17,16 @@ import {
|
|
|
15
17
|
import type { Hono } from "hono";
|
|
16
18
|
import { HTTPException } from "hono/http-exception";
|
|
17
19
|
import { z } from "zod";
|
|
18
|
-
import { requireAccessGrant } from "@opengeni/core";
|
|
20
|
+
import { requireAccessGrant, requireAccessGrantAuthorization } from "@opengeni/core";
|
|
21
|
+
import {
|
|
22
|
+
assertPersonalConnectionOwnerPrincipal,
|
|
23
|
+
isPersonalConnectionOwnerPrincipal,
|
|
24
|
+
requireLegacyOAuthActor,
|
|
25
|
+
} from "../connection-ownership";
|
|
19
26
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
20
27
|
import { boundedLimit } from "../http/common";
|
|
21
28
|
import { completeSocialOAuthCallback, startSocialOAuth } from "../integrations/social-oauth";
|
|
29
|
+
import { parseRequestJson } from "../http/request-body";
|
|
22
30
|
|
|
23
31
|
export function registerSocialRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
24
32
|
const { db, settings, observability } = deps;
|
|
@@ -39,22 +47,28 @@ export function registerSocialRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
39
47
|
app.post("/v1/workspaces/:workspaceId/social/connections", async (c) => {
|
|
40
48
|
const workspaceId = c.req.param("workspaceId");
|
|
41
49
|
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
42
|
-
const payload =
|
|
50
|
+
const payload = await parseRequestJson(c, CreateSocialConnectionRequest);
|
|
43
51
|
try {
|
|
44
52
|
return c.json(
|
|
45
|
-
await
|
|
46
|
-
|
|
47
|
-
workspaceId,
|
|
48
|
-
provider
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
await withOrganizationIntegrationAcquisition(
|
|
54
|
+
db,
|
|
55
|
+
{ accountId: grant.accountId, workspaceId },
|
|
56
|
+
[payload.provider === "x" || payload.provider === "reddit" ? payload.provider : null],
|
|
57
|
+
(tx) =>
|
|
58
|
+
createSocialConnection(tx, {
|
|
59
|
+
accountId: grant.accountId,
|
|
60
|
+
workspaceId,
|
|
61
|
+
provider: payload.provider,
|
|
62
|
+
accountHandle: payload.accountHandle,
|
|
63
|
+
accountName: payload.accountName ?? null,
|
|
64
|
+
externalAccountId: payload.externalAccountId ?? null,
|
|
65
|
+
status: payload.status,
|
|
66
|
+
scopes: payload.scopes,
|
|
67
|
+
credentialRef: payload.credentialRef ?? null,
|
|
68
|
+
tokenMetadata: payload.tokenMetadata,
|
|
69
|
+
metadata: payload.metadata,
|
|
70
|
+
}),
|
|
71
|
+
),
|
|
58
72
|
201,
|
|
59
73
|
);
|
|
60
74
|
} catch (error) {
|
|
@@ -99,18 +113,27 @@ export function registerSocialRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
99
113
|
});
|
|
100
114
|
}
|
|
101
115
|
const payload = parsed.data;
|
|
102
|
-
const
|
|
116
|
+
const access = await requireAccessGrantAuthorization(
|
|
103
117
|
c,
|
|
104
118
|
deps,
|
|
105
119
|
workspaceId,
|
|
106
120
|
payload.ownership === "workspace" ? "workspace:admin" : "workspace:read",
|
|
107
121
|
);
|
|
122
|
+
// The contract already defaults this request to workspace ownership; an
|
|
123
|
+
// explicit personal choice still needs a human who can own it.
|
|
124
|
+
requireLegacyOAuthActor(access);
|
|
125
|
+
const personalOwnershipAllowed = isPersonalConnectionOwnerPrincipal(access);
|
|
126
|
+
if (payload.ownership === "personal") {
|
|
127
|
+
assertPersonalConnectionOwnerPrincipal(access);
|
|
128
|
+
}
|
|
129
|
+
const grant = access.grant;
|
|
108
130
|
const result = await startSocialOAuth(
|
|
109
131
|
{ db, settings, observability },
|
|
110
132
|
{
|
|
111
133
|
accountId: grant.accountId,
|
|
112
134
|
workspaceId,
|
|
113
135
|
subjectId: grant.subjectId,
|
|
136
|
+
personalOwnershipAllowed,
|
|
114
137
|
requestUrl: c.req.url,
|
|
115
138
|
payload,
|
|
116
139
|
},
|
|
@@ -128,7 +151,9 @@ export function registerSocialRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
128
151
|
requestUrl: c.req.url,
|
|
129
152
|
},
|
|
130
153
|
);
|
|
131
|
-
return
|
|
154
|
+
return result.exactReturn
|
|
155
|
+
? new Response(null, { status: 302, headers: { location: result.redirectTo } })
|
|
156
|
+
: c.redirect(result.redirectTo, 302);
|
|
132
157
|
});
|
|
133
158
|
|
|
134
159
|
app.get("/v1/workspaces/:workspaceId/social/posts", async (c) => {
|
|
@@ -152,7 +177,7 @@ export function registerSocialRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
152
177
|
app.post("/v1/workspaces/:workspaceId/social/posts", async (c) => {
|
|
153
178
|
const workspaceId = c.req.param("workspaceId");
|
|
154
179
|
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
155
|
-
const payload =
|
|
180
|
+
const payload = await parseRequestJson(c, CreateSocialPostRequest);
|
|
156
181
|
try {
|
|
157
182
|
return c.json(
|
|
158
183
|
await createSocialPost(db, {
|
|
@@ -206,6 +231,9 @@ function parseConnectionIds(raw: string | undefined): string[] | undefined {
|
|
|
206
231
|
}
|
|
207
232
|
|
|
208
233
|
function socialHttpException(error: unknown): HTTPException {
|
|
234
|
+
if (error instanceof OrganizationIntegrationDeniedError) {
|
|
235
|
+
return new HTTPException(403, { message: error.message });
|
|
236
|
+
}
|
|
209
237
|
const message = error instanceof Error ? error.message : String(error);
|
|
210
238
|
if (message.includes("not found")) {
|
|
211
239
|
return new HTTPException(404, { message });
|