@hotmeshio/long-tail 0.23.1 → 0.24.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/build/adapters/express.d.ts +9 -1
- package/build/adapters/express.js +32 -41
- package/build/api/auth-sso.d.ts +1 -1
- package/build/api/bot-accounts.d.ts +2 -0
- package/build/api/bot-accounts.js +4 -0
- package/build/api/capabilities.d.ts +7 -2
- package/build/api/capabilities.js +13 -2
- package/build/api/escalations/analytics.js +5 -0
- package/build/api/escalations/bulk.d.ts +2 -0
- package/build/api/escalations/bulk.js +9 -4
- package/build/api/escalations/helpers.d.ts +5 -0
- package/build/api/escalations/helpers.js +7 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +4 -1
- package/build/api/escalations/list.d.ts +5 -0
- package/build/api/escalations/list.js +19 -5
- package/build/api/escalations/metadata.js +3 -0
- package/build/api/escalations/related.d.ts +18 -0
- package/build/api/escalations/related.js +205 -0
- package/build/api/escalations/single.d.ts +3 -2
- package/build/api/escalations/single.js +8 -3
- package/build/api/mcp/tools.d.ts +12 -0
- package/build/api/mcp/tools.js +113 -9
- package/build/api/roles.js +4 -0
- package/build/api/scan-codes/choice.js +31 -7
- package/build/api/scan-codes/present.js +5 -1
- package/build/api/settings.d.ts +1 -1
- package/build/api/settings.js +12 -1
- package/build/api/tasks.d.ts +3 -3
- package/build/api/tasks.js +30 -7
- package/build/api/workflows/input-lookups.js +1 -1
- package/build/api/workflows/invocable.js +2 -2
- package/build/api/workflows/invocation.js +1 -1
- package/build/api/yaml-workflows/deploy.d.ts +10 -2
- package/build/api/yaml-workflows/deploy.js +42 -2
- package/build/lib/db/schemas/038_oauth_server.sql +46 -0
- package/build/lib/events/browser-view.d.ts +15 -0
- package/build/lib/events/browser-view.js +101 -0
- package/build/lib/events/nats-ws-filter.d.ts +29 -0
- package/build/lib/events/nats-ws-filter.js +94 -0
- package/build/lib/events/nats-ws-proxy.d.ts +2 -0
- package/build/lib/events/nats-ws-proxy.js +39 -5
- package/build/lib/events/nats-ws-server-filter.d.ts +16 -0
- package/build/lib/events/nats-ws-server-filter.js +56 -0
- package/build/lib/events/nats-ws-ticket.d.ts +10 -0
- package/build/lib/events/nats-ws-ticket.js +42 -0
- package/build/lib/events/socketio.d.ts +10 -1
- package/build/lib/events/socketio.js +10 -3
- package/build/lib/http/index.d.ts +27 -0
- package/build/lib/http/index.js +55 -0
- package/build/modules/auth.d.ts +15 -24
- package/build/modules/auth.js +43 -126
- package/build/modules/capabilities.d.ts +62 -0
- package/build/modules/capabilities.js +188 -0
- package/build/modules/config.d.ts +14 -0
- package/build/modules/config.js +20 -0
- package/build/modules/defaults.d.ts +10 -0
- package/build/modules/defaults.js +12 -1
- package/build/modules/display.d.ts +15 -0
- package/build/modules/display.js +27 -0
- package/build/modules/mcp-auth.d.ts +11 -0
- package/build/modules/mcp-auth.js +56 -0
- package/build/modules/oauth-server.d.ts +18 -0
- package/build/modules/oauth-server.js +40 -0
- package/build/routes/agents.js +46 -14
- package/build/routes/announcements.js +2 -2
- package/build/routes/auth-sso.js +2 -2
- package/build/routes/auth.js +2 -2
- package/build/routes/bot-accounts.js +26 -3
- package/build/routes/capabilities.js +4 -4
- package/build/routes/controlplane.js +2 -2
- package/build/routes/dba.js +2 -2
- package/build/routes/delegation.js +2 -2
- package/build/routes/diagnostics.js +2 -2
- package/build/routes/docs.js +2 -2
- package/build/routes/domain.js +2 -2
- package/build/routes/escalations/accumulate.d.ts +1 -1
- package/build/routes/escalations/acting.d.ts +1 -1
- package/build/routes/escalations/analytics.d.ts +1 -1
- package/build/routes/escalations/bulk.d.ts +1 -1
- package/build/routes/escalations/facets.d.ts +1 -1
- package/build/routes/escalations/index.js +5 -2
- package/build/routes/escalations/list.d.ts +1 -1
- package/build/routes/escalations/list.js +2 -0
- package/build/routes/escalations/metadata.d.ts +1 -1
- package/build/routes/escalations/related.d.ts +7 -0
- package/build/routes/escalations/related.js +60 -0
- package/build/routes/escalations/resolve.d.ts +1 -1
- package/build/routes/escalations/single.d.ts +1 -1
- package/build/routes/escalations/single.js +1 -1
- package/build/routes/exports.js +14 -13
- package/build/routes/file-browser.js +9 -8
- package/build/routes/files.js +2 -2
- package/build/routes/index.js +4 -2
- package/build/routes/insight.js +5 -4
- package/build/routes/knowledge.js +2 -2
- package/build/routes/maintenance.js +2 -2
- package/build/routes/mcp-endpoint.d.ts +3 -1
- package/build/routes/mcp-endpoint.js +18 -8
- package/build/routes/mcp.js +35 -15
- package/build/routes/me.js +2 -2
- package/build/routes/namespaces.js +4 -3
- package/build/routes/nats-credentials.js +27 -3
- package/build/routes/oauth-server/authorize.d.ts +2 -0
- package/build/routes/oauth-server/authorize.js +108 -0
- package/build/routes/oauth-server/grants.d.ts +2 -0
- package/build/routes/oauth-server/grants.js +35 -0
- package/build/routes/oauth-server/index.d.ts +8 -0
- package/build/routes/oauth-server/index.js +52 -0
- package/build/routes/oauth-server/registration.d.ts +2 -0
- package/build/routes/oauth-server/registration.js +38 -0
- package/build/routes/oauth-server/token.d.ts +2 -0
- package/build/routes/oauth-server/token.js +100 -0
- package/build/routes/oauth-well-known.d.ts +8 -0
- package/build/routes/oauth-well-known.js +31 -0
- package/build/routes/oauth.js +2 -2
- package/build/routes/overview.js +2 -2
- package/build/routes/personas.js +2 -2
- package/build/routes/pipelines.js +6 -5
- package/build/routes/roles.js +2 -2
- package/build/routes/scan-codes.js +2 -2
- package/build/routes/settings.js +2 -2
- package/build/routes/tasks.js +5 -5
- package/build/routes/topics.js +21 -9
- package/build/routes/users.js +25 -22
- package/build/routes/workflow-sets.js +13 -12
- package/build/routes/workflows/config.js +15 -2
- package/build/routes/workflows/discovery.js +2 -2
- package/build/routes/workflows/index.js +2 -2
- package/build/routes/workflows/invocation.js +11 -10
- package/build/routes/yaml-workflows/cron.js +19 -6
- package/build/routes/yaml-workflows/crud.js +13 -12
- package/build/routes/yaml-workflows/deployment.js +11 -10
- package/build/routes/yaml-workflows/index.js +2 -2
- package/build/routes/yaml-workflows/versions.js +2 -2
- package/build/scripts/consolidation-sim.d.ts +25 -0
- package/build/scripts/consolidation-sim.js +141 -0
- package/build/sdk/index.d.ts +12 -0
- package/build/sdk/index.js +2 -0
- package/build/services/agent/authority.d.ts +14 -0
- package/build/services/agent/authority.js +53 -0
- package/build/services/auth/bot-api-key.d.ts +2 -0
- package/build/services/auth/bot-api-key.js +10 -0
- package/build/services/auth/oauth-server/access-token.d.ts +36 -0
- package/build/services/auth/oauth-server/access-token.js +80 -0
- package/build/services/auth/oauth-server/authorization.d.ts +47 -0
- package/build/services/auth/oauth-server/authorization.js +54 -0
- package/build/services/auth/oauth-server/constants.d.ts +11 -0
- package/build/services/auth/oauth-server/constants.js +16 -0
- package/build/services/auth/oauth-server/index.d.ts +3 -0
- package/build/services/auth/oauth-server/index.js +26 -0
- package/build/services/auth/oauth-server/metadata.d.ts +21 -0
- package/build/services/auth/oauth-server/metadata.js +53 -0
- package/build/services/auth/oauth-server/registration.d.ts +42 -0
- package/build/services/auth/oauth-server/registration.js +134 -0
- package/build/services/auth/oauth-server/sql.d.ts +34 -0
- package/build/services/auth/oauth-server/sql.js +123 -0
- package/build/services/auth/oauth-server/store.d.ts +74 -0
- package/build/services/auth/oauth-server/store.js +151 -0
- package/build/services/auth/sql.d.ts +1 -0
- package/build/services/auth/sql.js +3 -1
- package/build/services/escalation/grouped-list.d.ts +19 -0
- package/build/services/escalation/grouped-list.js +54 -0
- package/build/services/escalation/index.d.ts +4 -0
- package/build/services/escalation/index.js +9 -1
- package/build/services/escalation/queries.d.ts +17 -13
- package/build/services/escalation/queries.js +38 -42
- package/build/services/escalation/read-scope-sql.d.ts +13 -0
- package/build/services/escalation/read-scope-sql.js +19 -0
- package/build/services/escalation/related.d.ts +58 -0
- package/build/services/escalation/related.js +196 -0
- package/build/services/export/index.d.ts +10 -0
- package/build/services/export/index.js +27 -0
- package/build/services/invocation-access.d.ts +25 -4
- package/build/services/invocation-access.js +39 -7
- package/build/services/mcp/client/connection-dispatch.d.ts +6 -1
- package/build/services/mcp/client/connection-dispatch.js +3 -2
- package/build/services/mcp/client/connection-lifecycle.d.ts +10 -2
- package/build/services/mcp/client/connection-lifecycle.js +45 -7
- package/build/services/mcp/client/connection-test.js +2 -6
- package/build/services/mcp/client/connection.d.ts +1 -1
- package/build/services/mcp/client/connection.js +3 -1
- package/build/services/mcp/client/index.d.ts +2 -2
- package/build/services/mcp/client/index.js +4 -1
- package/build/services/mcp/client/network-transport.d.ts +12 -0
- package/build/services/mcp/client/network-transport.js +20 -0
- package/build/services/mcp/client/tools.d.ts +13 -0
- package/build/services/mcp/client/tools.js +18 -0
- package/build/services/mcp/db-server/index.js +2 -1
- package/build/services/mcp/external-server.d.ts +9 -4
- package/build/services/mcp/external-server.js +34 -11
- package/build/services/mcp/playwright-server/index.js +2 -1
- package/build/services/mcp/registered-tools.d.ts +3 -0
- package/build/services/mcp/registered-tools.js +7 -0
- package/build/services/mcp/server-lifecycle.js +2 -1
- package/build/services/role/index.js +6 -0
- package/build/services/role/seed.js +4 -0
- package/build/services/scan-code/validate-facts.d.ts +1 -1
- package/build/services/scan-code/validate-facts.js +12 -1
- package/build/services/workflow-invocation.d.ts +16 -3
- package/build/services/workflow-invocation.js +42 -10
- package/build/services/yaml-workflow/deployer.d.ts +10 -2
- package/build/services/yaml-workflow/deployer.js +17 -5
- package/build/services/yaml-workflow/invoke.js +27 -26
- package/build/shared/form-validation/x-lt-scan.d.ts +8 -0
- package/build/shared/form-validation/x-lt-scan.js +20 -1
- package/build/shared/list-schema/index.d.ts +3 -0
- package/build/shared/list-schema/index.js +27 -0
- package/build/shared/list-schema/template.d.ts +14 -0
- package/build/shared/list-schema/template.js +85 -0
- package/build/shared/list-schema/types.d.ts +154 -0
- package/build/shared/list-schema/types.js +55 -0
- package/build/shared/list-schema/validate.d.ts +12 -0
- package/build/shared/list-schema/validate.js +204 -0
- package/build/shared/roles/segment.d.ts +22 -0
- package/build/shared/roles/segment.js +42 -0
- package/build/start/adapters.js +2 -0
- package/build/start/config.js +7 -0
- package/build/start/index.js +4 -22
- package/build/start/server.d.ts +6 -4
- package/build/start/server.js +11 -35
- package/build/start/socket-auth.js +2 -1
- package/build/start/workers.js +1 -1
- package/build/system/mcp-servers/admin/agent-subscriptions.js +24 -1
- package/build/system/mcp-servers/admin/agents.js +25 -2
- package/build/system/mcp-servers/admin/announcements.js +3 -2
- package/build/system/mcp-servers/admin/bot-accounts.js +37 -5
- package/build/system/mcp-servers/admin/escalations.d.ts +3 -5
- package/build/system/mcp-servers/admin/escalations.js +74 -70
- package/build/system/mcp-servers/admin/exports.js +7 -1
- package/build/system/mcp-servers/admin/index.js +24 -25
- package/build/system/mcp-servers/admin/overview.d.ts +2 -2
- package/build/system/mcp-servers/admin/run-read.d.ts +2 -0
- package/build/system/mcp-servers/admin/run-read.js +5 -0
- package/build/system/mcp-servers/admin/scan-codes.d.ts +2 -2
- package/build/system/mcp-servers/admin/scan-codes.js +5 -11
- package/build/system/mcp-servers/admin/schemas.d.ts +20 -20
- package/build/system/mcp-servers/admin/tasks.js +7 -2
- package/build/system/mcp-servers/admin/users.js +39 -4
- package/build/system/mcp-servers/admin/workflow-config.js +12 -1
- package/build/system/mcp-servers/admin/workflows.js +27 -5
- package/build/system/mcp-servers/admin/yaml-workflows.js +7 -1
- package/build/system/mcp-servers/caller-auth.d.ts +18 -0
- package/build/system/mcp-servers/caller-auth.js +29 -0
- package/build/system/mcp-servers/claude-code.js +2 -1
- package/build/system/mcp-servers/db-query/index.js +2 -1
- package/build/system/mcp-servers/file-storage.js +2 -1
- package/build/system/mcp-servers/http-fetch.js +2 -1
- package/build/system/mcp-servers/human-queue.js +7 -3
- package/build/system/mcp-servers/oauth.js +31 -4
- package/build/system/mcp-servers/schema-exchange.js +2 -1
- package/build/system/mcp-servers/vision.d.ts +1 -0
- package/build/system/mcp-servers/vision.js +17 -7
- package/build/system/seed/tool-manifests-admin.d.ts +2 -17985
- package/build/system/seed/tool-manifests-admin.js +121 -121
- package/build/system/seed/tool-manifests-data.d.ts +8 -374
- package/build/system/seed/tool-manifests-data.js +22 -4
- package/build/system/seed/tool-manifests-escalation.d.ts +2 -352
- package/build/system/seed/tool-manifests-escalation.js +11 -1
- package/build/system/seed/tool-manifests-events.d.ts +2 -116
- package/build/system/seed/tool-manifests-events.js +6 -2
- package/build/system/seed/tool-manifests-knowledge.d.ts +2 -221
- package/build/system/seed/tool-manifests-knowledge.js +41 -1
- package/build/system/seed/tool-manifests-workflows.d.ts +2 -71
- package/build/system/seed/tool-manifests-workflows.js +3 -1
- package/build/system/workflows/shared/principal-tools.d.ts +20 -0
- package/build/system/workflows/shared/principal-tools.js +64 -0
- package/build/system/workflows/shared/tool-executor.js +21 -11
- package/build/system/workflows/shared/tool-loader.js +8 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/auth.d.ts +1 -1
- package/build/types/capability.d.ts +14 -0
- package/build/types/capability.js +2 -0
- package/build/types/events.d.ts +1 -1
- package/build/types/index.d.ts +5 -3
- package/build/types/index.js +2 -1
- package/build/types/mcp.d.ts +3 -1
- package/build/types/oauth-server.d.ts +52 -0
- package/build/types/oauth-server.js +2 -0
- package/build/types/scan-code/constants.d.ts +7 -0
- package/build/types/scan-code/constants.js +7 -1
- package/build/types/scan-code/response.d.ts +3 -2
- package/build/types/scan-code/rule.d.ts +6 -1
- package/build/types/startup.d.ts +23 -7
- package/build/vitest.config.js +2 -1
- package/build/vitest.fast.config.d.ts +2 -0
- package/build/vitest.fast.config.js +20 -0
- package/build/vitest.llm.config.d.ts +2 -0
- package/build/vitest.llm.config.js +16 -0
- package/dashboard/dist/assets/{AdminDashboard-DKrqLGjn.js → AdminDashboard-B3mkMIOT.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DKrqLGjn.js.map → AdminDashboard-B3mkMIOT.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BoQhRW6U.js → AgentConfigPage-CQj2B678.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-BoQhRW6U.js.map → AgentConfigPage-CQj2B678.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-DZhzuZmO.js → AgentDetailPage-CzrD8JJI.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-DZhzuZmO.js.map → AgentDetailPage-CzrD8JJI.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-5MynmbWX.js → AgentsPage-jg2OFwyW.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-5MynmbWX.js.map → AgentsPage-jg2OFwyW.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-IS28XBRe.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-IS28XBRe.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-C3LR6Sqy.js → BotPicker-DvEJFpwS.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-C3LR6Sqy.js.map → BotPicker-DvEJFpwS.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-COjoOIIH.js → BulkAssignModal-BoQCi-YC.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-COjoOIIH.js.map → BulkAssignModal-BoQCi-YC.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-kwlrcb_t.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-DKxLvOfB.js.map → CapabilitiesPage-kwlrcb_t.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-Cz5sRx-r.js → CollapsibleSection-UMIV4KIj.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-Cz5sRx-r.js.map → CollapsibleSection-UMIV4KIj.js.map} +1 -1
- package/dashboard/dist/assets/ConfirmDeleteModal-C5puwMg7.js +2 -0
- package/dashboard/dist/assets/ConfirmDeleteModal-C5puwMg7.js.map +1 -0
- package/dashboard/dist/assets/ConnectedAppsPage-drZa65kP.js +2 -0
- package/dashboard/dist/assets/ConnectedAppsPage-drZa65kP.js.map +1 -0
- package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-DhiHiPsG.js → CredentialsPage-CaFQ6vLb.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-DhiHiPsG.js.map → CredentialsPage-CaFQ6vLb.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-C9SkawB-.js → CronLabel-Co5j7tzW.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-C9SkawB-.js.map → CronLabel-Co5j7tzW.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-FjFhx0SE.js +2 -0
- package/dashboard/dist/assets/DataTable-FjFhx0SE.js.map +1 -0
- package/dashboard/dist/assets/{ElapsedCell-BeK1SUDK.js → ElapsedCell-WJyE9G0T.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BeK1SUDK.js.map → ElapsedCell-WJyE9G0T.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-BThdefKj.js → EntityTimelinePanel-CDFFfX9d.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-BThdefKj.js.map → EntityTimelinePanel-CDFFfX9d.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DlDIYb-p.js → EscalationListSchemaPage-CMrUlaKI.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DlDIYb-p.js.map → EscalationListSchemaPage-CMrUlaKI.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-CQt-Embr.js → EscalationSchemaPage-Dx2Lyfrz.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-CQt-Embr.js.map → EscalationSchemaPage-Dx2Lyfrz.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-d3nvshOk.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-d3nvshOk.js.map +1 -0
- package/dashboard/dist/assets/{EscalationTitleSelect-Dewrv8wX.js → EscalationTitleSelect-DWQieOM9.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-Dewrv8wX.js.map → EscalationTitleSelect-DWQieOM9.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BzH-Y-5x.js → EscalationsOverview-BX8Cpi0X.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BzH-Y-5x.js.map → EscalationsOverview-BX8Cpi0X.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-C97m6IZv.js → EventTable-D1-ITVXS.js} +2 -2
- package/dashboard/dist/assets/{EventTable-C97m6IZv.js.map → EventTable-D1-ITVXS.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-D-6xVHIw.js → FilterBar-ABC9ctin.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-D-6xVHIw.js.map → FilterBar-ABC9ctin.js.map} +1 -1
- package/dashboard/dist/assets/FormattedValue-k27T4bG7.js +2 -0
- package/dashboard/dist/assets/FormattedValue-k27T4bG7.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-Bwi8EF9Y.js → GraphInvokePage-DKUErxWc.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Bwi8EF9Y.js.map → GraphInvokePage-DKUErxWc.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-Z_Q03C0z.js → HomePage-C6u9dIpR.js} +2 -2
- package/dashboard/dist/assets/{HomePage-Z_Q03C0z.js.map → HomePage-C6u9dIpR.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-_jWTw5no.js → ListToolbar-gA5rFzkz.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-_jWTw5no.js.map → ListToolbar-gA5rFzkz.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CjqTuP0N.js → McpOverview-BOPo3J_i.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CjqTuP0N.js.map → McpOverview-BOPo3J_i.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-leCsje1U.js → McpQueryDetailPage-BRVVi0Zh.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-leCsje1U.js.map → McpQueryDetailPage-BRVVi0Zh.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-C-PyXYX4.js → McpQueryPage-Dmbb6SAc.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-C-PyXYX4.js.map → McpQueryPage-Dmbb6SAc.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-JDrr3uUQ.js → McpRunDetailPage-bMXNO-6V.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-JDrr3uUQ.js.map → McpRunDetailPage-bMXNO-6V.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DERXQLgZ.js → McpRunsPage-Bi9AMWja.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DERXQLgZ.js.map → McpRunsPage-Bi9AMWja.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-B2DA7n9m.js → OperationsPage-CvR74ZUJ.js} +3 -3
- package/dashboard/dist/assets/OperationsPage-CvR74ZUJ.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-DctmZw10.js +2 -0
- package/dashboard/dist/assets/OperatorDashboard-DctmZw10.js.map +1 -0
- package/dashboard/dist/assets/{PersonaDetailPage-ChXwJ6u5.js → PersonaDetailPage-Ubqm2rQH.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-ChXwJ6u5.js.map → PersonaDetailPage-Ubqm2rQH.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BFFxncSE.js → PersonasPage-BpFL2rpo.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BFFxncSE.js.map → PersonasPage-BpFL2rpo.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-Dfc_Q02R.js +2 -0
- package/dashboard/dist/assets/PortalPage-Dfc_Q02R.js.map +1 -0
- package/dashboard/dist/assets/ProcessDetailPage-liJspvQh.js +2 -0
- package/dashboard/dist/assets/{ProcessDetailPage-D7EYwW-j.js.map → ProcessDetailPage-liJspvQh.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CakYRtnE.js → ProcessesListPage-C3OM5ZUy.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CakYRtnE.js.map → ProcessesListPage-C3OM5ZUy.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js +8 -0
- package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js.map +1 -0
- package/dashboard/dist/assets/{RoleDetailPage-CKbGwezP.js → RoleDetailPage-CrlYCh-R.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-CKbGwezP.js.map → RoleDetailPage-CrlYCh-R.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-Czu7Zku4.js → RolesPage-BaazL_pt.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-Czu7Zku4.js.map → RolesPage-BaazL_pt.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-6BLScYTX.js → RunAsSelector-DxuV0fa1.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-6BLScYTX.js.map → RunAsSelector-DxuV0fa1.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-Cv9q8Bvt.js → ScanCodesPage-C0mvmYTq.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-Cv9q8Bvt.js.map → ScanCodesPage-C0mvmYTq.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-BxazXYIc.js → ScanSchemeDetailPage-CiJgt5dZ.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-BxazXYIc.js.map → ScanSchemeDetailPage-CiJgt5dZ.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-DsdtYoXR.js → StickyPagination-CqbjVY6T.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-DsdtYoXR.js.map → StickyPagination-CqbjVY6T.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-CT3FQoT3.js → StreamMessageDetail-wX3i0aqs.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-CT3FQoT3.js.map → StreamMessageDetail-wX3i0aqs.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-C8TjkJ10.js → SwimlaneTimeline-C50PsFoV.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-C8TjkJ10.js.map → SwimlaneTimeline-C50PsFoV.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DGUzdBFN.js → TaskDetailPage-bbNSv4Ae.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DGUzdBFN.js.map → TaskDetailPage-bbNSv4Ae.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BVIP6-EZ.js → TasksListPage-CDWnm_d9.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BVIP6-EZ.js.map → TasksListPage-CDWnm_d9.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-C-rd9F9g.js → TimeAgo-BLjqlfoX.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-C-rd9F9g.js.map → TimeAgo-BLjqlfoX.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DPbchDOI.js → TimestampCell-CnW0ENb5.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DPbchDOI.js.map → TimestampCell-CnW0ENb5.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-DAUC8DHK.js → ToolTestPanel-DkMgCB-k.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-DAUC8DHK.js.map → ToolTestPanel-DkMgCB-k.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-70mMKBzG.js → TopicDetailPage-g3pljKKX.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-70mMKBzG.js.map → TopicDetailPage-g3pljKKX.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CE3hBthn.js → TopicsPage-CVcCYdy-.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CE3hBthn.js.map → TopicsPage-CVcCYdy-.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BDBDA-LR.js → UserName-D6zGIK2i.js} +2 -2
- package/dashboard/dist/assets/{UserName-BDBDA-LR.js.map → UserName-D6zGIK2i.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-BbkLZ1co.js → WorkflowExecutionPage-B8g81FCJ.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-BbkLZ1co.js.map → WorkflowExecutionPage-B8g81FCJ.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-Bp1L7Ggz.js → WorkflowsDashboard-nxT3bv6W.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-Bp1L7Ggz.js.map → WorkflowsDashboard-nxT3bv6W.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-IeTKHAi4.js → WorkflowsOverview-grI-KAI2.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-IeTKHAi4.js.map → WorkflowsOverview-grI-KAI2.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DtKCXnKt.js → YamlWorkflowDetailPage-BoZ-hfBE.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DtKCXnKt.js.map → YamlWorkflowDetailPage-BoZ-hfBE.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEcZBV_3.js → YamlWorkflowsPage-Bf04rwRv.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEcZBV_3.js.map → YamlWorkflowsPage-Bf04rwRv.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BT-sEk81.js → agents-Dphpdi8l.js} +2 -2
- package/dashboard/dist/assets/{agents-BT-sEk81.js.map → agents-Dphpdi8l.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DRoAdLek.js → bots-DIFE298x.js} +2 -2
- package/dashboard/dist/assets/{bots-DRoAdLek.js.map → bots-DIFE298x.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-Bc-nJk6y.js → capabilities-D7Y7LClY.js} +2 -2
- package/dashboard/dist/assets/{capabilities-Bc-nJk6y.js.map → capabilities-D7Y7LClY.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-aXceSIRf.js → controlplane-D1TGcYsS.js} +2 -2
- package/dashboard/dist/assets/{controlplane-aXceSIRf.js.map → controlplane-D1TGcYsS.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js +2 -0
- package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js.map +1 -0
- package/dashboard/dist/assets/{index-CuBGGwXf.js → index-BzYcUPdD.js} +2 -2
- package/dashboard/dist/assets/{index-CuBGGwXf.js.map → index-BzYcUPdD.js.map} +1 -1
- package/dashboard/dist/assets/index-CeCtqujG.js +67 -0
- package/dashboard/dist/assets/index-CeCtqujG.js.map +1 -0
- package/dashboard/dist/assets/{index-h2gX31B2.js → index-ChV7pBjM.js} +2 -2
- package/dashboard/dist/assets/{index-h2gX31B2.js.map → index-ChV7pBjM.js.map} +1 -1
- package/dashboard/dist/assets/index-CniRa65p.js +3 -0
- package/dashboard/dist/assets/index-CniRa65p.js.map +1 -0
- package/dashboard/dist/assets/index-CxdjT1Yk.js +2 -0
- package/dashboard/dist/assets/{index-BCFEQEMC.js.map → index-CxdjT1Yk.js.map} +1 -1
- package/dashboard/dist/assets/{index-CZyO9hRb.js → index-DAvi5_2T.js} +2 -2
- package/dashboard/dist/assets/{index-CZyO9hRb.js.map → index-DAvi5_2T.js.map} +1 -1
- package/dashboard/dist/assets/{index-Djsoi8DI.js → index-DN-kX7hL.js} +2 -2
- package/dashboard/dist/assets/{index-Djsoi8DI.js.map → index-DN-kX7hL.js.map} +1 -1
- package/dashboard/dist/assets/index-Dl_8hbYI.js +2 -0
- package/dashboard/dist/assets/index-Dl_8hbYI.js.map +1 -0
- package/dashboard/dist/assets/{index-DBxpyIw5.js → index-DpKOr311.js} +2 -2
- package/dashboard/dist/assets/{index-DBxpyIw5.js.map → index-DpKOr311.js.map} +1 -1
- package/dashboard/dist/assets/{index-Ba-s5Yb5.js → index-Dy1wWu2e.js} +2 -2
- package/dashboard/dist/assets/{index-Ba-s5Yb5.js.map → index-Dy1wWu2e.js.map} +1 -1
- package/dashboard/dist/assets/{index-DH03y-UT.js → index-HLu98Sqh.js} +2 -2
- package/dashboard/dist/assets/{index-DH03y-UT.js.map → index-HLu98Sqh.js.map} +1 -1
- package/dashboard/dist/assets/{index-C3VTJcrp.js → index-ag2pCAPu.js} +2 -2
- package/dashboard/dist/assets/{index-C3VTJcrp.js.map → index-ag2pCAPu.js.map} +1 -1
- package/dashboard/dist/assets/index-gkxPN7Vx.js +13 -0
- package/dashboard/dist/assets/{index-BEPKAjna.js.map → index-gkxPN7Vx.js.map} +1 -1
- package/dashboard/dist/assets/index-m9A3UYst.css +1 -0
- package/dashboard/dist/assets/{knowledge-BhW8V-Hq.js → knowledge-DnMs-SOJ.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BhW8V-Hq.js.map → knowledge-DnMs-SOJ.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BYfSMQzh.js → mcp-CwW-K3r4.js} +2 -2
- package/dashboard/dist/assets/{mcp-BYfSMQzh.js.map → mcp-CwW-K3r4.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DUJoOk_q.js → mcp-query-BZt5e8_Q.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DUJoOk_q.js.map → mcp-query-BZt5e8_Q.js.map} +1 -1
- package/dashboard/dist/assets/{personas-jT1O_SB4.js → personas-UA-Xn60f.js} +2 -2
- package/dashboard/dist/assets/{personas-jT1O_SB4.js.map → personas-UA-Xn60f.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Bp-wIaz2.js → pipelines-Cu3PARum.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Bp-wIaz2.js.map → pipelines-Cu3PARum.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CCrvnXbz.js → tasks-BO6h8GJE.js} +2 -2
- package/dashboard/dist/assets/{tasks-CCrvnXbz.js.map → tasks-BO6h8GJE.js.map} +1 -1
- package/dashboard/dist/assets/{topics-Blft0I1L.js → topics-CWjCR-17.js} +2 -2
- package/dashboard/dist/assets/{topics-Blft0I1L.js.map → topics-CWjCR-17.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-BYqbcism.js → useDebouncedValue-6t0jx1RB.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-BYqbcism.js.map → useDebouncedValue-6t0jx1RB.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-BfxJAUgG.js → useNamespace-CqpoQx6D.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-BfxJAUgG.js.map → useNamespace-CqpoQx6D.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BukJuWpb.js → useYamlActivityEvents-hmCQQwzB.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BukJuWpb.js.map → useYamlActivityEvents-hmCQQwzB.js.map} +1 -1
- package/dashboard/dist/assets/validate-BIRn4a6d.js +2 -0
- package/dashboard/dist/assets/validate-BIRn4a6d.js.map +1 -0
- package/dashboard/dist/assets/{yaml-workflows-DeRWqMGk.js → yaml-workflows-ziUdZhKY.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DeRWqMGk.js.map → yaml-workflows-ziUdZhKY.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/agents.md +3 -1
- package/docs/api/http/agents.md +15 -1
- package/docs/api/http/escalations.md +49 -3
- package/docs/api/http/exports.md +3 -1
- package/docs/api/http/file-browser.md +3 -1
- package/docs/api/http/mcp-endpoint.md +5 -2
- package/docs/api/http/mcp-servers.md +34 -4
- package/docs/api/http/namespaces.md +2 -0
- package/docs/api/http/pipelines.md +2 -0
- package/docs/api/http/roles.md +11 -8
- package/docs/api/http/service-accounts.md +8 -2
- package/docs/api/http/settings.md +29 -2
- package/docs/api/http/tasks.md +3 -1
- package/docs/api/http/topics.md +7 -1
- package/docs/api/http/users.md +8 -2
- package/docs/api/http/workflows.md +25 -10
- package/docs/api/http/yaml-workflows.md +21 -0
- package/docs/api/mcp/admin.md +409 -49
- package/docs/api/mcp/file-storage.md +4 -0
- package/docs/api/mcp/http-fetch.md +6 -2
- package/docs/api/mcp/human-queue.md +53 -0
- package/docs/api/mcp/index.md +13 -10
- package/docs/api/mcp/knowledge.md +34 -0
- package/docs/api/mcp/oauth.md +1 -1
- package/docs/api/mcp/ortho.md +113 -0
- package/docs/api/mcp/vision.md +1 -1
- package/docs/api/sdk/bot-accounts.md +1 -0
- package/docs/api/sdk/escalations.md +18 -2
- package/docs/api/sdk/mcp.md +2 -2
- package/docs/api/sdk/settings.md +1 -1
- package/docs/api/sdk/tasks.md +2 -2
- package/docs/api/sdk/workflows.md +2 -2
- package/docs/api/sdk/yaml-workflows.md +1 -1
- package/docs/architecture.md +3 -1
- package/docs/auth.md +3 -2
- package/docs/cloud.md +7 -2
- package/docs/code-owned-configuration.md +12 -0
- package/docs/dashboard.md +16 -7
- package/docs/data.md +1 -1
- package/docs/escalation-strategies.md +9 -20
- package/docs/events.md +6 -0
- package/docs/hitl/portal.md +2 -0
- package/docs/hitl/x-lt-list-schema.md +88 -1
- package/docs/hitl/x-lt-scan.md +4 -1
- package/docs/iam.md +7 -5
- package/docs/mcp.md +159 -210
- package/docs/oauth-and-delegation.md +32 -21
- package/docs/scan-codes.md +7 -1
- package/docs/topics.md +2 -0
- package/docs/workflows.md +14 -112
- package/package.json +6 -3
- package/dashboard/dist/assets/AvailableEscalationsPage-CWMyy3IL.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CWMyy3IL.js.map +0 -1
- package/dashboard/dist/assets/CapabilitiesPage-DKxLvOfB.js +0 -2
- package/dashboard/dist/assets/ConfirmDeleteModal-Beq1vQtY.js +0 -2
- package/dashboard/dist/assets/ConfirmDeleteModal-Beq1vQtY.js.map +0 -1
- package/dashboard/dist/assets/CountdownTimer-BUBl_4mP.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-BUBl_4mP.js.map +0 -1
- package/dashboard/dist/assets/DataTable-spX1dFyb.js +0 -2
- package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +0 -1
- package/dashboard/dist/assets/EscalationListView-DTIVuym4.js +0 -2
- package/dashboard/dist/assets/EscalationListView-DTIVuym4.js.map +0 -1
- package/dashboard/dist/assets/EscalationTimeline-DNKNp6pL.js +0 -2
- package/dashboard/dist/assets/EscalationTimeline-DNKNp6pL.js.map +0 -1
- package/dashboard/dist/assets/OperationsPage-B2DA7n9m.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-C8RtPv8P.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-C8RtPv8P.js.map +0 -1
- package/dashboard/dist/assets/PortalPage-Xk1zVneM.js +0 -2
- package/dashboard/dist/assets/PortalPage-Xk1zVneM.js.map +0 -1
- package/dashboard/dist/assets/ProcessDetailPage-D7EYwW-j.js +0 -2
- package/dashboard/dist/assets/ResolverForm-BwVOJUpJ.js +0 -8
- package/dashboard/dist/assets/ResolverForm-BwVOJUpJ.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-Cg8LCFR7.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-Cg8LCFR7.js.map +0 -1
- package/dashboard/dist/assets/escalation-columns-Bf09Q89t.js +0 -2
- package/dashboard/dist/assets/escalation-columns-Bf09Q89t.js.map +0 -1
- package/dashboard/dist/assets/index-BCFEQEMC.js +0 -2
- package/dashboard/dist/assets/index-BEPKAjna.js +0 -13
- package/dashboard/dist/assets/index-BUYokcrl.js +0 -67
- package/dashboard/dist/assets/index-BUYokcrl.js.map +0 -1
- package/dashboard/dist/assets/index-CcgmR-7-.js +0 -2
- package/dashboard/dist/assets/index-CcgmR-7-.js.map +0 -1
- package/dashboard/dist/assets/index-D1mKf_qz.js +0 -3
- package/dashboard/dist/assets/index-D1mKf_qz.js.map +0 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +0 -1
package/build/api/tasks.js
CHANGED
|
@@ -41,6 +41,24 @@ exports.getProcess = getProcess;
|
|
|
41
41
|
exports.getTask = getTask;
|
|
42
42
|
const taskService = __importStar(require("../services/task"));
|
|
43
43
|
const escalationService = __importStar(require("../services/escalation"));
|
|
44
|
+
const helpers_1 = require("./escalations/helpers");
|
|
45
|
+
const capabilities_1 = require("../modules/capabilities");
|
|
46
|
+
/**
|
|
47
|
+
* How a caller sees task rows. A builder, and the person a run was started by
|
|
48
|
+
* or runs as, see the whole row; anyone else sees it without the run's input
|
|
49
|
+
* (`envelope`), output (`data`) and `metadata`. An in-process call (no auth)
|
|
50
|
+
* sees whole rows.
|
|
51
|
+
*/
|
|
52
|
+
async function taskViewFor(auth) {
|
|
53
|
+
if (!auth?.userId || (await (0, capabilities_1.mayBuild)(auth)))
|
|
54
|
+
return (task) => task;
|
|
55
|
+
return (task) => {
|
|
56
|
+
if (task.initiated_by === auth.userId || task.executing_as === auth.userId)
|
|
57
|
+
return task;
|
|
58
|
+
const { envelope: _envelope, data: _data, metadata: _metadata, ...rest } = task;
|
|
59
|
+
return rest;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
44
62
|
/**
|
|
45
63
|
* Create a task record.
|
|
46
64
|
*
|
|
@@ -104,10 +122,10 @@ async function createTask(input, auth) {
|
|
|
104
122
|
* @param input.offset — pagination offset (default: 0)
|
|
105
123
|
* @returns `{ status: 200, data: { tasks, total } }`
|
|
106
124
|
*/
|
|
107
|
-
async function listTasks(input) {
|
|
125
|
+
async function listTasks(input, auth) {
|
|
108
126
|
try {
|
|
109
|
-
const result = await taskService.listTasks(input);
|
|
110
|
-
return { status: 200, data: result };
|
|
127
|
+
const [result, view] = await Promise.all([taskService.listTasks(input), taskViewFor(auth)]);
|
|
128
|
+
return { status: 200, data: { ...result, tasks: result.tasks.map(view) } };
|
|
111
129
|
}
|
|
112
130
|
catch (err) {
|
|
113
131
|
return { status: 500, error: err.message };
|
|
@@ -153,12 +171,17 @@ async function listProcesses(input) {
|
|
|
153
171
|
* @param input.originId — root process origin ID
|
|
154
172
|
* @returns `{ status: 200, data: { origin_id, tasks, escalations } }`
|
|
155
173
|
*/
|
|
156
|
-
async function getProcess(input) {
|
|
174
|
+
async function getProcess(input, auth) {
|
|
157
175
|
try {
|
|
158
|
-
const [
|
|
176
|
+
const [rows, all, view] = await Promise.all([
|
|
159
177
|
taskService.getProcessTasks(input.originId),
|
|
160
178
|
escalationService.getEscalationsByOriginId(input.originId),
|
|
179
|
+
taskViewFor(auth),
|
|
161
180
|
]);
|
|
181
|
+
const tasks = rows.map(view);
|
|
182
|
+
// With a caller, only the escalations that caller may read.
|
|
183
|
+
const scope = auth?.userId ? await (0, helpers_1.getEscalationReadScope)(auth.userId) : null;
|
|
184
|
+
const escalations = scope ? all.filter((e) => (0, helpers_1.scopeAdmits)(scope, auth.userId, e)) : all;
|
|
162
185
|
return {
|
|
163
186
|
status: 200,
|
|
164
187
|
data: { origin_id: input.originId, tasks, escalations },
|
|
@@ -174,13 +197,13 @@ async function getProcess(input) {
|
|
|
174
197
|
* @param input.id — task UUID
|
|
175
198
|
* @returns `{ status: 200, data: <task record> }` or 404
|
|
176
199
|
*/
|
|
177
|
-
async function getTask(input) {
|
|
200
|
+
async function getTask(input, auth) {
|
|
178
201
|
try {
|
|
179
202
|
const task = await taskService.getTask(input.id);
|
|
180
203
|
if (!task) {
|
|
181
204
|
return { status: 404, error: 'Task not found' };
|
|
182
205
|
}
|
|
183
|
-
return { status: 200, data: task };
|
|
206
|
+
return { status: 200, data: (await taskViewFor(auth))(task) };
|
|
184
207
|
}
|
|
185
208
|
catch (err) {
|
|
186
209
|
return { status: 500, error: err.message };
|
|
@@ -57,7 +57,7 @@ async function getWorkflowInputLookups(input, auth) {
|
|
|
57
57
|
return { status: 404, error: 'Workflow config not found' };
|
|
58
58
|
}
|
|
59
59
|
const user = auth.userId ? await userService.getUser(auth.userId) : null;
|
|
60
|
-
if (!(0, invocation_access_1.canInvokeWorkflow)(config, user?.roles ?? []
|
|
60
|
+
if (!(0, invocation_access_1.canInvokeWorkflow)(config, user?.roles ?? [])) {
|
|
61
61
|
return { status: 403, error: 'Not authorized to invoke this workflow' };
|
|
62
62
|
}
|
|
63
63
|
const lookups = await (0, knowledge_1.resolveLookupRefs)(config.input_lookups ?? []);
|
|
@@ -88,9 +88,9 @@ async function listInvocableWorkflows(auth) {
|
|
|
88
88
|
]);
|
|
89
89
|
const roles = user?.roles ?? [];
|
|
90
90
|
const workflows = configs
|
|
91
|
-
.filter((c) => (0, invocation_access_1.canInvokeWorkflow)(c, roles
|
|
91
|
+
.filter((c) => (0, invocation_access_1.canInvokeWorkflow)(c, roles))
|
|
92
92
|
.map((c) => ({ ...c, tier: tierOf(c) }));
|
|
93
|
-
if ((0, invocation_access_1.hasGlobalInvocationAccess)(roles
|
|
93
|
+
if ((0, invocation_access_1.hasGlobalInvocationAccess)(roles)) {
|
|
94
94
|
const registered = new Set(configs.map((c) => c.workflow_type));
|
|
95
95
|
for (const [name, { taskQueue }] of (0, registry_1.getRegisteredWorkers)()) {
|
|
96
96
|
if (registered.has(name) || registry_1.SYSTEM_WORKFLOWS.has(name))
|
|
@@ -62,7 +62,7 @@ function isResolveError(err) {
|
|
|
62
62
|
*/
|
|
63
63
|
async function invokeWorkflow(input, auth) {
|
|
64
64
|
try {
|
|
65
|
-
await (0, workflow_invocation_1.
|
|
65
|
+
await (0, workflow_invocation_1.authorizeInvocation)({ workflowType: input.type, userId: auth.userId, executeAs: input.execute_as });
|
|
66
66
|
const config = await configService.getWorkflowConfig(input.type);
|
|
67
67
|
const violation = await (0, input_validation_1.checkInvokeInput)(config, input.data, input.metadata);
|
|
68
68
|
if (violation)
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type { LTYamlWorkflowRecord } from '../../types/yaml-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* A compiled workflow's tool steps run with lt-system authority. Deploying or
|
|
4
|
+
* activating one needs the caller to be able to call every built-in tool it
|
|
5
|
+
* uses: automation never does more than its author may. Null when allowed;
|
|
6
|
+
* without a caller (in-process), allowed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function deployRefusal(wf: LTYamlWorkflowRecord, auth: LTApiAuth | undefined): Promise<LTApiResult | null>;
|
|
1
9
|
import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
2
10
|
/**
|
|
3
11
|
* Deploy a YAML workflow and all sibling workflows sharing its app_id namespace.
|
|
@@ -11,7 +19,7 @@ import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
|
11
19
|
*/
|
|
12
20
|
export declare function deployYamlWorkflow(input: {
|
|
13
21
|
id: string;
|
|
14
|
-
}): Promise<LTApiResult>;
|
|
22
|
+
}, auth?: LTApiAuth): Promise<LTApiResult>;
|
|
15
23
|
/**
|
|
16
24
|
* Activate a previously deployed YAML workflow and its app_id siblings.
|
|
17
25
|
*
|
|
@@ -24,7 +32,7 @@ export declare function deployYamlWorkflow(input: {
|
|
|
24
32
|
*/
|
|
25
33
|
export declare function activateYamlWorkflow(input: {
|
|
26
34
|
id: string;
|
|
27
|
-
}): Promise<LTApiResult>;
|
|
35
|
+
}, auth?: LTApiAuth): Promise<LTApiResult>;
|
|
28
36
|
/**
|
|
29
37
|
* Invoke an active YAML workflow, executing its DAG pipeline.
|
|
30
38
|
*
|
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.deployRefusal = deployRefusal;
|
|
36
37
|
exports.deployYamlWorkflow = deployYamlWorkflow;
|
|
37
38
|
exports.activateYamlWorkflow = activateYamlWorkflow;
|
|
38
39
|
exports.invokeYamlWorkflow = invokeYamlWorkflow;
|
|
@@ -42,6 +43,32 @@ const yamlDb = __importStar(require("../../services/yaml-workflow/db"));
|
|
|
42
43
|
const yamlDeployer = __importStar(require("../../services/yaml-workflow/deployer"));
|
|
43
44
|
const yamlWorkers = __importStar(require("../../services/yaml-workflow/workers"));
|
|
44
45
|
const invoke_1 = require("../../services/yaml-workflow/invoke");
|
|
46
|
+
const workflow_invocation_1 = require("../../services/workflow-invocation");
|
|
47
|
+
const capabilities_1 = require("../../modules/capabilities");
|
|
48
|
+
const tools_1 = require("../mcp/tools");
|
|
49
|
+
/**
|
|
50
|
+
* A compiled workflow's tool steps run with lt-system authority. Deploying or
|
|
51
|
+
* activating one needs the caller to be able to call every built-in tool it
|
|
52
|
+
* uses: automation never does more than its author may. Null when allowed;
|
|
53
|
+
* without a caller (in-process), allowed.
|
|
54
|
+
*/
|
|
55
|
+
async function deployRefusal(wf, auth) {
|
|
56
|
+
if (!auth?.userId)
|
|
57
|
+
return null;
|
|
58
|
+
const access = (0, capabilities_1.capabilityAccess)({ userId: auth.userId });
|
|
59
|
+
// A deploy publishes every workflow sharing the app id, so every one is checked.
|
|
60
|
+
const siblings = await yamlDb.listYamlWorkflowsByAppId(wf.app_id);
|
|
61
|
+
const steps = [wf, ...siblings.filter((w) => w.id !== wf.id)].flatMap((w) => w.activity_manifest ?? []);
|
|
62
|
+
for (const step of steps) {
|
|
63
|
+
if (step.tool_source !== 'mcp' || !step.mcp_server_id || !step.mcp_tool_name)
|
|
64
|
+
continue;
|
|
65
|
+
const builtin = await (0, tools_1.builtinServerFor)(step.mcp_server_id);
|
|
66
|
+
if (builtin && !(await access((0, tools_1.builtinToolGate)(builtin, step.mcp_tool_name)))) {
|
|
67
|
+
return { status: 403, error: `Forbidden: this workflow calls ${step.mcp_tool_name}, which is not available to you` };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
45
72
|
const helpers_1 = require("./helpers");
|
|
46
73
|
/**
|
|
47
74
|
* Deploy a YAML workflow and all sibling workflows sharing its app_id namespace.
|
|
@@ -53,12 +80,15 @@ const helpers_1 = require("./helpers");
|
|
|
53
80
|
* @param input.id — UUID of the workflow to deploy
|
|
54
81
|
* @returns `{ status: 200, data: YamlWorkflow }` the refreshed workflow record after deployment
|
|
55
82
|
*/
|
|
56
|
-
async function deployYamlWorkflow(input) {
|
|
83
|
+
async function deployYamlWorkflow(input, auth) {
|
|
57
84
|
try {
|
|
58
85
|
const wf = await yamlDb.getYamlWorkflow(input.id);
|
|
59
86
|
if (!wf) {
|
|
60
87
|
return { status: 404, error: 'YAML workflow not found' };
|
|
61
88
|
}
|
|
89
|
+
const refused = await deployRefusal(wf, auth);
|
|
90
|
+
if (refused)
|
|
91
|
+
return refused;
|
|
62
92
|
// Compute the next app-level version for the namespace.
|
|
63
93
|
// Each deploy increments regardless of individual tool versions —
|
|
64
94
|
// adding a second tool (v1 of itself) to an app already at v1 produces app v2.
|
|
@@ -99,12 +129,15 @@ async function deployYamlWorkflow(input) {
|
|
|
99
129
|
* @param input.id — UUID of the workflow to activate
|
|
100
130
|
* @returns `{ status: 200, data: YamlWorkflow }` the refreshed workflow record after activation
|
|
101
131
|
*/
|
|
102
|
-
async function activateYamlWorkflow(input) {
|
|
132
|
+
async function activateYamlWorkflow(input, auth) {
|
|
103
133
|
try {
|
|
104
134
|
const wf = await yamlDb.getYamlWorkflow(input.id);
|
|
105
135
|
if (!wf) {
|
|
106
136
|
return { status: 404, error: 'YAML workflow not found' };
|
|
107
137
|
}
|
|
138
|
+
const refused = await deployRefusal(wf, auth);
|
|
139
|
+
if (refused)
|
|
140
|
+
return refused;
|
|
108
141
|
if (wf.status !== 'deployed' && wf.status !== 'active') {
|
|
109
142
|
return { status: 400, error: 'Workflow must be deployed before activation' };
|
|
110
143
|
}
|
|
@@ -151,6 +184,11 @@ async function invokeYamlWorkflow(input, auth) {
|
|
|
151
184
|
if (wf.status !== 'active') {
|
|
152
185
|
return { status: 400, error: 'Workflow must be active to invoke' };
|
|
153
186
|
}
|
|
187
|
+
if (input.execute_as) {
|
|
188
|
+
if (!auth?.userId)
|
|
189
|
+
return { status: 403, error: 'execute_as requires an authenticated caller' };
|
|
190
|
+
await (0, workflow_invocation_1.assertMayActAs)(auth.userId, input.execute_as);
|
|
191
|
+
}
|
|
154
192
|
const result = await (0, invoke_1.invokeYamlWorkflow)(wf, {
|
|
155
193
|
data: input.data,
|
|
156
194
|
sync: input.sync,
|
|
@@ -161,6 +199,8 @@ async function invokeYamlWorkflow(input, auth) {
|
|
|
161
199
|
return { status: 200, data: result };
|
|
162
200
|
}
|
|
163
201
|
catch (err) {
|
|
202
|
+
if (err instanceof workflow_invocation_1.InvocationError)
|
|
203
|
+
return { status: err.statusCode, error: err.message };
|
|
164
204
|
if ((0, helpers_1.isNotFoundError)(err)) {
|
|
165
205
|
return { status: 404, error: 'YAML workflow not found' };
|
|
166
206
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
-- Migration 038: OAuth authorization server for /mcp
|
|
2
|
+
--
|
|
3
|
+
-- MCP clients register, a person consents to a grant, and the client holds a
|
|
4
|
+
-- refresh token for that grant. Access tokens are self-contained JWTs and are
|
|
5
|
+
-- never stored. Codes and refresh tokens are stored as SHA-256 hashes.
|
|
6
|
+
|
|
7
|
+
CREATE TABLE IF NOT EXISTS lt_oauth_clients (
|
|
8
|
+
client_id TEXT PRIMARY KEY,
|
|
9
|
+
client_name TEXT,
|
|
10
|
+
redirect_uris TEXT[] NOT NULL,
|
|
11
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- A grant is one person's consent for one client. The policy is the rights
|
|
15
|
+
-- the person chose (a preset today); the scope is its coarse summary.
|
|
16
|
+
CREATE TABLE IF NOT EXISTS lt_oauth_grants (
|
|
17
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
18
|
+
user_id UUID NOT NULL REFERENCES lt_users(id) ON DELETE CASCADE,
|
|
19
|
+
client_id TEXT NOT NULL REFERENCES lt_oauth_clients(client_id) ON DELETE CASCADE,
|
|
20
|
+
policy JSONB NOT NULL,
|
|
21
|
+
scope TEXT NOT NULL,
|
|
22
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
23
|
+
revoked_at TIMESTAMPTZ
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_lt_oauth_grants_user ON lt_oauth_grants (user_id);
|
|
27
|
+
|
|
28
|
+
CREATE TABLE IF NOT EXISTS lt_oauth_codes (
|
|
29
|
+
code_hash TEXT PRIMARY KEY,
|
|
30
|
+
grant_id UUID NOT NULL REFERENCES lt_oauth_grants(id) ON DELETE CASCADE,
|
|
31
|
+
redirect_uri TEXT NOT NULL,
|
|
32
|
+
code_challenge TEXT NOT NULL,
|
|
33
|
+
resource TEXT,
|
|
34
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
35
|
+
used_at TIMESTAMPTZ
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE TABLE IF NOT EXISTS lt_oauth_refresh_tokens (
|
|
39
|
+
token_hash TEXT PRIMARY KEY,
|
|
40
|
+
grant_id UUID NOT NULL REFERENCES lt_oauth_grants(id) ON DELETE CASCADE,
|
|
41
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
42
|
+
used_at TIMESTAMPTZ,
|
|
43
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
CREATE INDEX IF NOT EXISTS idx_lt_oauth_refresh_tokens_grant ON lt_oauth_refresh_tokens (grant_id);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LTEvent } from '../../types';
|
|
2
|
+
/** Escalation event fields a browser needs to route a refresh and follow a claim. */
|
|
3
|
+
export declare const BROWSER_ESCALATION_FIELDS: readonly ["id", "type", "subtype", "status", "priority", "role", "assigned_to", "assigned_until", "workflow_id", "workflow_type", "origin_id", "task_id", "parent_id", "resolved_at", "claimed_at", "bulk", "from_role", "to_role", "reassigned_from"];
|
|
4
|
+
export interface BrowserViewer {
|
|
5
|
+
builder: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** The event as this viewer receives it. */
|
|
8
|
+
export declare function eventForViewer(event: LTEvent, viewer: BrowserViewer): LTEvent;
|
|
9
|
+
/**
|
|
10
|
+
* Rewrite one serialized event for a viewer who is not a builder. A payload
|
|
11
|
+
* that is not an event is withheld (null).
|
|
12
|
+
*/
|
|
13
|
+
export declare function payloadForViewer(payload: Buffer, viewer: BrowserViewer): Buffer | null;
|
|
14
|
+
/** Whether a person is a builder, looked up lazily to keep lib free of an import cycle. */
|
|
15
|
+
export declare function viewerFor(userId: string | null | undefined): Promise<BrowserViewer>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BROWSER_ESCALATION_FIELDS = void 0;
|
|
37
|
+
exports.eventForViewer = eventForViewer;
|
|
38
|
+
exports.payloadForViewer = payloadForViewer;
|
|
39
|
+
exports.viewerFor = viewerFor;
|
|
40
|
+
/**
|
|
41
|
+
* What a browser receives of an event. Builders receive events whole. Anyone
|
|
42
|
+
* else receives enough to route and refresh: escalation events keep their
|
|
43
|
+
* routing fields, and every other event arrives without `data` and
|
|
44
|
+
* `milestones`. Full records are read through the scoped API, by id.
|
|
45
|
+
*
|
|
46
|
+
* Server-side consumers (agent triggers, callbacks) are unaffected: this view
|
|
47
|
+
* applies only where events leave for a browser.
|
|
48
|
+
*/
|
|
49
|
+
const ESCALATION_SUBJECT = 'system.escalation.';
|
|
50
|
+
/** Escalation event fields a browser needs to route a refresh and follow a claim. */
|
|
51
|
+
exports.BROWSER_ESCALATION_FIELDS = [
|
|
52
|
+
'id', 'type', 'subtype', 'status', 'priority', 'role',
|
|
53
|
+
'assigned_to', 'assigned_until', 'workflow_id', 'workflow_type',
|
|
54
|
+
'origin_id', 'task_id', 'parent_id', 'resolved_at', 'claimed_at',
|
|
55
|
+
'bulk', 'from_role', 'to_role', 'reassigned_from',
|
|
56
|
+
];
|
|
57
|
+
/** The event as this viewer receives it. */
|
|
58
|
+
function eventForViewer(event, viewer) {
|
|
59
|
+
if (viewer.builder)
|
|
60
|
+
return event;
|
|
61
|
+
const { data, milestones: _milestones, ...rest } = event;
|
|
62
|
+
if (typeof event.type === 'string' && event.type.startsWith(ESCALATION_SUBJECT) && data) {
|
|
63
|
+
const kept = {};
|
|
64
|
+
for (const key of exports.BROWSER_ESCALATION_FIELDS) {
|
|
65
|
+
if (data[key] !== undefined)
|
|
66
|
+
kept[key] = data[key];
|
|
67
|
+
}
|
|
68
|
+
return { ...rest, data: kept };
|
|
69
|
+
}
|
|
70
|
+
return rest;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rewrite one serialized event for a viewer who is not a builder. A payload
|
|
74
|
+
* that is not an event is withheld (null).
|
|
75
|
+
*/
|
|
76
|
+
function payloadForViewer(payload, viewer) {
|
|
77
|
+
if (viewer.builder)
|
|
78
|
+
return payload;
|
|
79
|
+
let event;
|
|
80
|
+
try {
|
|
81
|
+
event = JSON.parse(payload.toString('utf8'));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (!event || typeof event !== 'object' || typeof event.type !== 'string')
|
|
87
|
+
return null;
|
|
88
|
+
return Buffer.from(JSON.stringify(eventForViewer(event, viewer)), 'utf8');
|
|
89
|
+
}
|
|
90
|
+
/** Whether a person is a builder, looked up lazily to keep lib free of an import cycle. */
|
|
91
|
+
async function viewerFor(userId) {
|
|
92
|
+
if (!userId)
|
|
93
|
+
return { builder: false };
|
|
94
|
+
try {
|
|
95
|
+
const { mayBuild } = await Promise.resolve().then(() => __importStar(require('../../modules/capabilities')));
|
|
96
|
+
return { builder: await mayBuild({ userId }) };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return { builder: false };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser's half of a NATS connection, as the WebSocket proxy forwards
|
|
3
|
+
* it. A browser only subscribes, so the proxy authenticates the connection
|
|
4
|
+
* itself and lets the browser read, never publish:
|
|
5
|
+
*
|
|
6
|
+
* - CONNECT is rewritten to carry the server's credential (the browser is
|
|
7
|
+
* never given it), keeping the client's other options.
|
|
8
|
+
* - PUB and HPUB are dropped with their payloads.
|
|
9
|
+
* - SUB, UNSUB, PING and PONG pass through unchanged.
|
|
10
|
+
*
|
|
11
|
+
* The NATS client protocol is line-oriented (`OP args\r\n`), and a publish is
|
|
12
|
+
* followed by a payload of a declared size. Operations can span WebSocket
|
|
13
|
+
* frames, so the filter keeps whatever it has not yet seen whole.
|
|
14
|
+
*/
|
|
15
|
+
export declare class NatsClientFilter {
|
|
16
|
+
private readonly authToken;
|
|
17
|
+
private pending;
|
|
18
|
+
/** Payload bytes (plus the trailing CRLF) of a dropped publish still to skip. */
|
|
19
|
+
private skip;
|
|
20
|
+
private failed;
|
|
21
|
+
constructor(authToken: string | null);
|
|
22
|
+
/** Whether the stream was malformed; the proxy closes the connection. */
|
|
23
|
+
get malformed(): boolean;
|
|
24
|
+
/** The bytes to forward upstream for one chunk from the browser. */
|
|
25
|
+
feed(chunk: Buffer): Buffer;
|
|
26
|
+
/** The line to forward, or null to drop it. */
|
|
27
|
+
private filterLine;
|
|
28
|
+
private rewriteConnect;
|
|
29
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The browser's half of a NATS connection, as the WebSocket proxy forwards
|
|
4
|
+
* it. A browser only subscribes, so the proxy authenticates the connection
|
|
5
|
+
* itself and lets the browser read, never publish:
|
|
6
|
+
*
|
|
7
|
+
* - CONNECT is rewritten to carry the server's credential (the browser is
|
|
8
|
+
* never given it), keeping the client's other options.
|
|
9
|
+
* - PUB and HPUB are dropped with their payloads.
|
|
10
|
+
* - SUB, UNSUB, PING and PONG pass through unchanged.
|
|
11
|
+
*
|
|
12
|
+
* The NATS client protocol is line-oriented (`OP args\r\n`), and a publish is
|
|
13
|
+
* followed by a payload of a declared size. Operations can span WebSocket
|
|
14
|
+
* frames, so the filter keeps whatever it has not yet seen whole.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.NatsClientFilter = void 0;
|
|
18
|
+
const CRLF = Buffer.from('\r\n');
|
|
19
|
+
const MAX_LINE = 64 * 1024;
|
|
20
|
+
class NatsClientFilter {
|
|
21
|
+
constructor(authToken) {
|
|
22
|
+
this.authToken = authToken;
|
|
23
|
+
this.pending = Buffer.alloc(0);
|
|
24
|
+
/** Payload bytes (plus the trailing CRLF) of a dropped publish still to skip. */
|
|
25
|
+
this.skip = 0;
|
|
26
|
+
this.failed = false;
|
|
27
|
+
}
|
|
28
|
+
/** Whether the stream was malformed; the proxy closes the connection. */
|
|
29
|
+
get malformed() {
|
|
30
|
+
return this.failed;
|
|
31
|
+
}
|
|
32
|
+
/** The bytes to forward upstream for one chunk from the browser. */
|
|
33
|
+
feed(chunk) {
|
|
34
|
+
if (this.failed)
|
|
35
|
+
return Buffer.alloc(0);
|
|
36
|
+
this.pending = this.pending.length ? Buffer.concat([this.pending, chunk]) : chunk;
|
|
37
|
+
const out = [];
|
|
38
|
+
for (;;) {
|
|
39
|
+
if (this.skip > 0) {
|
|
40
|
+
const n = Math.min(this.skip, this.pending.length);
|
|
41
|
+
this.pending = this.pending.subarray(n);
|
|
42
|
+
this.skip -= n;
|
|
43
|
+
if (this.skip > 0)
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
const end = this.pending.indexOf(CRLF);
|
|
47
|
+
if (end === -1) {
|
|
48
|
+
if (this.pending.length > MAX_LINE)
|
|
49
|
+
this.failed = true;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
const line = this.pending.subarray(0, end).toString('utf8');
|
|
53
|
+
this.pending = this.pending.subarray(end + CRLF.length);
|
|
54
|
+
const forwarded = this.filterLine(line);
|
|
55
|
+
if (this.failed)
|
|
56
|
+
return Buffer.alloc(0);
|
|
57
|
+
if (forwarded !== null)
|
|
58
|
+
out.push(Buffer.from(`${forwarded}\r\n`, 'utf8'));
|
|
59
|
+
}
|
|
60
|
+
return Buffer.concat(out);
|
|
61
|
+
}
|
|
62
|
+
/** The line to forward, or null to drop it. */
|
|
63
|
+
filterLine(line) {
|
|
64
|
+
const space = line.indexOf(' ');
|
|
65
|
+
const op = (space === -1 ? line : line.slice(0, space)).toUpperCase();
|
|
66
|
+
const args = space === -1 ? '' : line.slice(space + 1);
|
|
67
|
+
if (op === 'CONNECT')
|
|
68
|
+
return this.rewriteConnect(args);
|
|
69
|
+
if (op === 'PUB' || op === 'HPUB') {
|
|
70
|
+
// PUB <subject> [reply] <size>; HPUB <subject> [reply] <header size> <total size>
|
|
71
|
+
const size = Number(args.trim().split(/\s+/).pop());
|
|
72
|
+
if (!Number.isInteger(size) || size < 0) {
|
|
73
|
+
this.failed = true;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
this.skip = size + CRLF.length;
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return line;
|
|
80
|
+
}
|
|
81
|
+
rewriteConnect(json) {
|
|
82
|
+
let options;
|
|
83
|
+
try {
|
|
84
|
+
options = JSON.parse(json);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
this.failed = true;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const { auth_token: _token, user: _user, pass: _pass, jwt: _jwt, nkey: _nkey, sig: _sig, ...rest } = options;
|
|
91
|
+
return `CONNECT ${JSON.stringify(this.authToken ? { ...rest, auth_token: this.authToken } : rest)}`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.NatsClientFilter = NatsClientFilter;
|
|
@@ -25,4 +25,6 @@ export declare function deriveWsUrlFromRequest(req: {
|
|
|
25
25
|
export declare function attachNatsWsProxy(server: HttpServer, target: string, options?: {
|
|
26
26
|
basePath?: string;
|
|
27
27
|
onWsUrlDerived?: (url: string) => void;
|
|
28
|
+
/** The NATS server credential, written into each browser's CONNECT by the proxy. */
|
|
29
|
+
authToken?: string | null;
|
|
28
30
|
}): void;
|
|
@@ -5,6 +5,10 @@ exports.deriveWsUrlFromRequest = deriveWsUrlFromRequest;
|
|
|
5
5
|
exports.attachNatsWsProxy = attachNatsWsProxy;
|
|
6
6
|
const ws_1 = require("ws");
|
|
7
7
|
const logger_1 = require("../logger");
|
|
8
|
+
const nats_ws_filter_1 = require("./nats-ws-filter");
|
|
9
|
+
const nats_ws_server_filter_1 = require("./nats-ws-server-filter");
|
|
10
|
+
const browser_view_1 = require("./browser-view");
|
|
11
|
+
const nats_ws_ticket_1 = require("./nats-ws-ticket");
|
|
8
12
|
/** Default path for the NATS WebSocket proxy endpoint. */
|
|
9
13
|
exports.NATS_WS_PROXY_PATH = '/nats-ws';
|
|
10
14
|
/**
|
|
@@ -36,8 +40,21 @@ function attachNatsWsProxy(server, target, options = {}) {
|
|
|
36
40
|
const proxyPath = `${basePath}${exports.NATS_WS_PROXY_PATH}`;
|
|
37
41
|
const wss = new ws_1.WebSocketServer({ noServer: true });
|
|
38
42
|
let derived = false;
|
|
39
|
-
server.on('upgrade', (req, socket, head) => {
|
|
40
|
-
|
|
43
|
+
server.on('upgrade', async (req, socket, head) => {
|
|
44
|
+
const url = new URL(req.url ?? '/', 'http://proxy');
|
|
45
|
+
if (url.pathname !== proxyPath)
|
|
46
|
+
return;
|
|
47
|
+
// Only a signed-in person, holding the ticket the credentials route issued.
|
|
48
|
+
const userId = (0, nats_ws_ticket_1.verifyNatsWsTicket)(url.searchParams.get(nats_ws_ticket_1.NATS_WS_TICKET_PARAM));
|
|
49
|
+
if (!userId) {
|
|
50
|
+
socket.write('HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n');
|
|
51
|
+
socket.destroy();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Decided once per connection: a builder receives events whole, anyone
|
|
55
|
+
// else receives the browser view (lib/events/browser-view.ts).
|
|
56
|
+
const viewer = await (0, browser_view_1.viewerFor)(userId);
|
|
57
|
+
if (socket.destroyed)
|
|
41
58
|
return;
|
|
42
59
|
// Derive the public wsUrl from the first request's headers
|
|
43
60
|
if (!derived && options.onWsUrlDerived) {
|
|
@@ -46,14 +63,31 @@ function attachNatsWsProxy(server, target, options = {}) {
|
|
|
46
63
|
}
|
|
47
64
|
wss.handleUpgrade(req, socket, head, (clientWs) => {
|
|
48
65
|
const upstream = new ws_1.WebSocket(target);
|
|
66
|
+
// The browser reads; the proxy holds the credential and drops its publishes.
|
|
67
|
+
const filter = new nats_ws_filter_1.NatsClientFilter(options.authToken ?? null);
|
|
68
|
+
const inbound = viewer.builder ? null : new nats_ws_server_filter_1.NatsServerFilter((payload) => (0, browser_view_1.payloadForViewer)(payload, viewer));
|
|
49
69
|
upstream.on('open', () => {
|
|
50
70
|
clientWs.on('message', (data) => {
|
|
51
|
-
|
|
52
|
-
|
|
71
|
+
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
72
|
+
const forward = filter.feed(chunk);
|
|
73
|
+
if (filter.malformed) {
|
|
74
|
+
clientWs.close();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (forward.length && upstream.readyState === ws_1.WebSocket.OPEN)
|
|
78
|
+
upstream.send(forward);
|
|
53
79
|
});
|
|
54
80
|
upstream.on('message', (data) => {
|
|
55
|
-
if (clientWs.readyState
|
|
81
|
+
if (clientWs.readyState !== ws_1.WebSocket.OPEN)
|
|
82
|
+
return;
|
|
83
|
+
if (!inbound) {
|
|
56
84
|
clientWs.send(data);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
88
|
+
const forward = inbound.feed(chunk);
|
|
89
|
+
if (forward.length)
|
|
90
|
+
clientWs.send(forward);
|
|
57
91
|
});
|
|
58
92
|
});
|
|
59
93
|
const close = () => {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server's half of a browser's NATS connection, as the WebSocket proxy
|
|
3
|
+
* forwards it. Message payloads (MSG and HMSG) pass through `rewrite`, which
|
|
4
|
+
* returns the payload to deliver or null to withhold the message; protocol
|
|
5
|
+
* lines (INFO, PING, PONG, +OK, -ERR) pass unchanged.
|
|
6
|
+
*
|
|
7
|
+
* Operations can span WebSocket frames, so the filter keeps whatever it has
|
|
8
|
+
* not yet seen whole.
|
|
9
|
+
*/
|
|
10
|
+
export declare class NatsServerFilter {
|
|
11
|
+
private readonly rewrite;
|
|
12
|
+
private pending;
|
|
13
|
+
constructor(rewrite: (payload: Buffer) => Buffer | null);
|
|
14
|
+
/** The bytes to forward to the browser for one chunk from the server. */
|
|
15
|
+
feed(chunk: Buffer): Buffer;
|
|
16
|
+
}
|