@hotmeshio/long-tail 0.23.2 → 0.24.1
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 +11 -1
- package/build/adapters/express.js +42 -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/metadata.js +3 -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/scan-codes/choice.js +31 -7
- package/build/api/settings.js +9 -0
- 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/cron.d.ts +3 -2
- package/build/api/yaml-workflows/cron.js +6 -1
- package/build/api/yaml-workflows/deploy.d.ts +15 -2
- package/build/api/yaml-workflows/deploy.js +69 -2
- package/build/lib/db/schemas/038_oauth_server.sql +46 -0
- package/build/lib/db/schemas/039_nats_ws_tickets.sql +12 -0
- package/build/lib/events/browser-view.d.ts +20 -0
- package/build/lib/events/browser-view.js +117 -0
- package/build/lib/events/nats-ws-filter.d.ts +29 -0
- package/build/lib/events/nats-ws-filter.js +109 -0
- package/build/lib/events/nats-ws-proxy.d.ts +7 -0
- package/build/lib/events/nats-ws-proxy.js +86 -7
- 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 +19 -0
- package/build/lib/events/nats-ws-ticket.js +63 -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 +19 -0
- package/build/modules/config.js +27 -0
- package/build/modules/defaults.d.ts +10 -0
- package/build/modules/defaults.js +12 -1
- package/build/modules/maintenance.d.ts +2 -0
- package/build/modules/maintenance.js +7 -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 +47 -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 +2 -2
- package/build/routes/escalations/list.d.ts +1 -1
- package/build/routes/escalations/metadata.d.ts +1 -1
- package/build/routes/escalations/related.d.ts +1 -1
- 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 +110 -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 +20 -7
- 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/services/agent/authority.d.ts +15 -0
- package/build/services/agent/authority.js +59 -0
- package/build/services/agent/trigger-registry.js +7 -2
- 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 +27 -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 +50 -0
- package/build/services/auth/oauth-server/sql.js +156 -0
- package/build/services/auth/oauth-server/store.d.ts +88 -0
- package/build/services/auth/oauth-server/store.js +171 -0
- package/build/services/auth/sql.d.ts +1 -0
- package/build/services/auth/sql.js +3 -1
- package/build/services/cron/index.js +5 -3
- package/build/services/escalation/queries.js +7 -2
- 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/maintenance/index.js +8 -0
- 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/seed-service-account.d.ts +4 -1
- package/build/services/mcp/seed-service-account.js +11 -6
- package/build/services/mcp/server-lifecycle.js +2 -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 +31 -26
- package/build/services/yaml-workflow/workers/register.js +3 -13
- package/build/services/yaml-workflow/workers/step-tool.d.ts +7 -0
- package/build/services/yaml-workflow/workers/step-tool.js +69 -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 +25 -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 +26 -26
- package/build/system/mcp-servers/admin/tasks.js +7 -2
- package/build/system/mcp-servers/admin/users.js +31 -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 +13 -21
- 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/mcp-servers/workflow.js +13 -25
- 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 +3 -1
- package/build/types/maintenance.d.ts +2 -2
- 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/startup.d.ts +15 -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-BPWsgMfZ.js → AdminDashboard-B3mkMIOT.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BPWsgMfZ.js.map → AdminDashboard-B3mkMIOT.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-De9imyo5.js → AgentConfigPage-CQj2B678.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-De9imyo5.js.map → AgentConfigPage-CQj2B678.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-B6o96Y5G.js → AgentDetailPage-CzrD8JJI.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-B6o96Y5G.js.map → AgentDetailPage-CzrD8JJI.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DMEmiK_W.js → AgentsPage-jg2OFwyW.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DMEmiK_W.js.map → AgentsPage-jg2OFwyW.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-DeYMngwE.js → AvailableEscalationsPage-IS28XBRe.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-DeYMngwE.js.map → AvailableEscalationsPage-IS28XBRe.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-DDmpgGHZ.js → BotPicker-DvEJFpwS.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-DDmpgGHZ.js.map → BotPicker-DvEJFpwS.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BqlklomG.js → BulkAssignModal-BoQCi-YC.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BqlklomG.js.map → BulkAssignModal-BoQCi-YC.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-DOtjDTbK.js → CapabilitiesPage-kwlrcb_t.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-DOtjDTbK.js.map → CapabilitiesPage-kwlrcb_t.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-CLr8LP0V.js → CollapsibleSection-UMIV4KIj.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-CLr8LP0V.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-DxX72PwV.js → CountdownTimer-LG03dVgR.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-DxX72PwV.js.map → CountdownTimer-LG03dVgR.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CObc9Rs5.js → CredentialsPage-CaFQ6vLb.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CObc9Rs5.js.map → CredentialsPage-CaFQ6vLb.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Bb8GoNY5.js → CronLabel-Co5j7tzW.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Bb8GoNY5.js.map → CronLabel-Co5j7tzW.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CmGhVlYl.js → ElapsedCell-WJyE9G0T.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CmGhVlYl.js.map → ElapsedCell-WJyE9G0T.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-B4Jwy1w3.js → EntityTimelinePanel-CDFFfX9d.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-B4Jwy1w3.js.map → EntityTimelinePanel-CDFFfX9d.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-CZZbZ4Aa.js → EscalationListSchemaPage-CMrUlaKI.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-CZZbZ4Aa.js.map → EscalationListSchemaPage-CMrUlaKI.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-D0ko59_S.js → EscalationSchemaPage-Dx2Lyfrz.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-D0ko59_S.js.map → EscalationSchemaPage-Dx2Lyfrz.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-BcnJEKFD.js → EscalationTimeline-d3nvshOk.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-BcnJEKFD.js.map → EscalationTimeline-d3nvshOk.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-P0q5sck4.js → EscalationTitleSelect-DWQieOM9.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-P0q5sck4.js.map → EscalationTitleSelect-DWQieOM9.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BLPmh4AF.js → EscalationsOverview-BX8Cpi0X.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BLPmh4AF.js.map → EscalationsOverview-BX8Cpi0X.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-gBzi5tIS.js → EventTable-D1-ITVXS.js} +2 -2
- package/dashboard/dist/assets/{EventTable-gBzi5tIS.js.map → EventTable-D1-ITVXS.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-BulSsWb2.js → FilterBar-ABC9ctin.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-BulSsWb2.js.map → FilterBar-ABC9ctin.js.map} +1 -1
- package/dashboard/dist/assets/{FormattedValue-BMHRrvrL.js → FormattedValue-k27T4bG7.js} +2 -2
- package/dashboard/dist/assets/{FormattedValue-BMHRrvrL.js.map → FormattedValue-k27T4bG7.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage--997yNRr.js → GraphInvokePage-DKUErxWc.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage--997yNRr.js.map → GraphInvokePage-DKUErxWc.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-CwXFz--v.js → HomePage-C6u9dIpR.js} +2 -2
- package/dashboard/dist/assets/{HomePage-CwXFz--v.js.map → HomePage-C6u9dIpR.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Df4qZryJ.js → ListToolbar-gA5rFzkz.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Df4qZryJ.js.map → ListToolbar-gA5rFzkz.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DrogIAKJ.js → McpOverview-BOPo3J_i.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DrogIAKJ.js.map → McpOverview-BOPo3J_i.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-CJmvCAE6.js → McpQueryDetailPage-BRVVi0Zh.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-CJmvCAE6.js.map → McpQueryDetailPage-BRVVi0Zh.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-lygo4Yq0.js → McpQueryPage-Dmbb6SAc.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-lygo4Yq0.js.map → McpQueryPage-Dmbb6SAc.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-hvns2sCm.js → McpRunDetailPage-bMXNO-6V.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-hvns2sCm.js.map → McpRunDetailPage-bMXNO-6V.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-C2_7spTX.js → McpRunsPage-Bi9AMWja.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-C2_7spTX.js.map → McpRunsPage-Bi9AMWja.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-BlK8WlsY.js → OperationsPage-CvR74ZUJ.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-BlK8WlsY.js.map → OperationsPage-CvR74ZUJ.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-BeWBiMGX.js → OperatorDashboard-DctmZw10.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-BeWBiMGX.js.map → OperatorDashboard-DctmZw10.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-CNHpsX_i.js → PersonaDetailPage-Ubqm2rQH.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-CNHpsX_i.js.map → PersonaDetailPage-Ubqm2rQH.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-ChASEZRg.js → PersonasPage-BpFL2rpo.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-ChASEZRg.js.map → PersonasPage-BpFL2rpo.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-D5Lk-PKF.js → PortalPage-Dfc_Q02R.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-D5Lk-PKF.js.map → PortalPage-Dfc_Q02R.js.map} +1 -1
- package/dashboard/dist/assets/ProcessDetailPage-liJspvQh.js +2 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DNgCIwRl.js.map → ProcessDetailPage-liJspvQh.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-pRjWuWlH.js → ProcessesListPage-C3OM5ZUy.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-pRjWuWlH.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-Bh_UcfYY.js → RoleDetailPage-CrlYCh-R.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-Bh_UcfYY.js.map → RoleDetailPage-CrlYCh-R.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-CK17N7zz.js → RolesPage-BaazL_pt.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-CK17N7zz.js.map → RolesPage-BaazL_pt.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BEKUP0p2.js → RunAsSelector-DxuV0fa1.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BEKUP0p2.js.map → RunAsSelector-DxuV0fa1.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-Bd0Pflqx.js → ScanCodesPage-C0mvmYTq.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-Bd0Pflqx.js.map → ScanCodesPage-C0mvmYTq.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CnuhozmJ.js → ScanSchemeDetailPage-CiJgt5dZ.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CnuhozmJ.js.map → ScanSchemeDetailPage-CiJgt5dZ.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-CoLc-q3h.js → ScanStationPage-DzGaXc40.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-CoLc-q3h.js.map → ScanStationPage-DzGaXc40.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-COrfvkBi.js → StickyPagination-CqbjVY6T.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-COrfvkBi.js.map → StickyPagination-CqbjVY6T.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-Cif2egLy.js → StreamMessageDetail-wX3i0aqs.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-Cif2egLy.js.map → StreamMessageDetail-wX3i0aqs.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BnZYTrAh.js → SwimlaneTimeline-C50PsFoV.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BnZYTrAh.js.map → SwimlaneTimeline-C50PsFoV.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DEz_dqyR.js → TaskDetailPage-bbNSv4Ae.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DEz_dqyR.js.map → TaskDetailPage-bbNSv4Ae.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-oEfEGj0_.js → TasksListPage-CDWnm_d9.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-oEfEGj0_.js.map → TasksListPage-CDWnm_d9.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-Dz5TgZZZ.js → TimeAgo-BLjqlfoX.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-Dz5TgZZZ.js.map → TimeAgo-BLjqlfoX.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BUTgE244.js → TimestampCell-CnW0ENb5.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BUTgE244.js.map → TimestampCell-CnW0ENb5.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BS4g6vt-.js → ToolTestPanel-DkMgCB-k.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BS4g6vt-.js.map → ToolTestPanel-DkMgCB-k.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-C_I6JIVD.js → TopicDetailPage-g3pljKKX.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-C_I6JIVD.js.map → TopicDetailPage-g3pljKKX.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Cr6-wfhJ.js → TopicsPage-CVcCYdy-.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Cr6-wfhJ.js.map → TopicsPage-CVcCYdy-.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-ZFpWMaFF.js → UserName-D6zGIK2i.js} +2 -2
- package/dashboard/dist/assets/{UserName-ZFpWMaFF.js.map → UserName-D6zGIK2i.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-ByPixDZW.js → WorkflowExecutionPage-B8g81FCJ.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-ByPixDZW.js.map → WorkflowExecutionPage-B8g81FCJ.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-CWsJdMdR.js → WorkflowsDashboard-nxT3bv6W.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-CWsJdMdR.js.map → WorkflowsDashboard-nxT3bv6W.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-Dk9gyqZN.js → WorkflowsOverview-grI-KAI2.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-Dk9gyqZN.js.map → WorkflowsOverview-grI-KAI2.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CHwcrsaT.js → YamlWorkflowDetailPage-BoZ-hfBE.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CHwcrsaT.js.map → YamlWorkflowDetailPage-BoZ-hfBE.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-B5jRX2Ph.js → YamlWorkflowsPage-Bf04rwRv.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-B5jRX2Ph.js.map → YamlWorkflowsPage-Bf04rwRv.js.map} +1 -1
- package/dashboard/dist/assets/{agents-Dd7E-27d.js → agents-Dphpdi8l.js} +2 -2
- package/dashboard/dist/assets/{agents-Dd7E-27d.js.map → agents-Dphpdi8l.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CpaYjZTk.js → bots-DIFE298x.js} +2 -2
- package/dashboard/dist/assets/{bots-CpaYjZTk.js.map → bots-DIFE298x.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CNjg_qv1.js → capabilities-D7Y7LClY.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CNjg_qv1.js.map → capabilities-D7Y7LClY.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DgmvnAtU.js → controlplane-D1TGcYsS.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DgmvnAtU.js.map → controlplane-D1TGcYsS.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Uj4U9g5H.js → escalation-columns-cwZE6xyo.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Uj4U9g5H.js.map → escalation-columns-cwZE6xyo.js.map} +1 -1
- package/dashboard/dist/assets/{index-x5z73M9N.js → index-BzYcUPdD.js} +2 -2
- package/dashboard/dist/assets/{index-x5z73M9N.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-RIFT3RlO.js → index-ChV7pBjM.js} +2 -2
- package/dashboard/dist/assets/{index-RIFT3RlO.js.map → index-ChV7pBjM.js.map} +1 -1
- package/dashboard/dist/assets/{index-OfO0173w.js → index-CniRa65p.js} +2 -2
- package/dashboard/dist/assets/{index-OfO0173w.js.map → index-CniRa65p.js.map} +1 -1
- package/dashboard/dist/assets/{index-ByBy9M3L.js → index-CxdjT1Yk.js} +2 -2
- package/dashboard/dist/assets/{index-ByBy9M3L.js.map → index-CxdjT1Yk.js.map} +1 -1
- package/dashboard/dist/assets/{index-C_K7OlzT.js → index-DAvi5_2T.js} +2 -2
- package/dashboard/dist/assets/{index-C_K7OlzT.js.map → index-DAvi5_2T.js.map} +1 -1
- package/dashboard/dist/assets/{index-BrwqtXRh.js → index-DN-kX7hL.js} +2 -2
- package/dashboard/dist/assets/{index-BrwqtXRh.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-D4Dlznn9.js → index-DpKOr311.js} +2 -2
- package/dashboard/dist/assets/{index-D4Dlznn9.js.map → index-DpKOr311.js.map} +1 -1
- package/dashboard/dist/assets/{index-CnOvJz6U.js → index-Dy1wWu2e.js} +2 -2
- package/dashboard/dist/assets/{index-CnOvJz6U.js.map → index-Dy1wWu2e.js.map} +1 -1
- package/dashboard/dist/assets/{index-BT1Ms5Q5.js → index-HLu98Sqh.js} +2 -2
- package/dashboard/dist/assets/{index-BT1Ms5Q5.js.map → index-HLu98Sqh.js.map} +1 -1
- package/dashboard/dist/assets/{index-BFASQ7_X.js → index-ag2pCAPu.js} +2 -2
- package/dashboard/dist/assets/{index-BFASQ7_X.js.map → index-ag2pCAPu.js.map} +1 -1
- package/dashboard/dist/assets/{index-BsHVgWH6.js → index-gkxPN7Vx.js} +2 -2
- package/dashboard/dist/assets/{index-BsHVgWH6.js.map → index-gkxPN7Vx.js.map} +1 -1
- package/dashboard/dist/assets/index-m9A3UYst.css +1 -0
- package/dashboard/dist/assets/{knowledge-Cci_r6Kl.js → knowledge-DnMs-SOJ.js} +2 -2
- package/dashboard/dist/assets/{knowledge-Cci_r6Kl.js.map → knowledge-DnMs-SOJ.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-NY4iL0L-.js → mcp-CwW-K3r4.js} +2 -2
- package/dashboard/dist/assets/{mcp-NY4iL0L-.js.map → mcp-CwW-K3r4.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CbvZo_I_.js → mcp-query-BZt5e8_Q.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CbvZo_I_.js.map → mcp-query-BZt5e8_Q.js.map} +1 -1
- package/dashboard/dist/assets/{personas-Fy-f7QQd.js → personas-UA-Xn60f.js} +2 -2
- package/dashboard/dist/assets/{personas-Fy-f7QQd.js.map → personas-UA-Xn60f.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-DKiuozxV.js → pipelines-Cu3PARum.js} +2 -2
- package/dashboard/dist/assets/{pipelines-DKiuozxV.js.map → pipelines-Cu3PARum.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CdM1Rkk9.js → tasks-BO6h8GJE.js} +2 -2
- package/dashboard/dist/assets/{tasks-CdM1Rkk9.js.map → tasks-BO6h8GJE.js.map} +1 -1
- package/dashboard/dist/assets/{topics-XNy2mf3n.js → topics-CWjCR-17.js} +2 -2
- package/dashboard/dist/assets/{topics-XNy2mf3n.js.map → topics-CWjCR-17.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-CyGcU3_S.js → useDebouncedValue-6t0jx1RB.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-CyGcU3_S.js.map → useDebouncedValue-6t0jx1RB.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-C2RIh_IN.js → useNamespace-CqpoQx6D.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-C2RIh_IN.js.map → useNamespace-CqpoQx6D.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CDiV5fjf.js → useYamlActivityEvents-hmCQQwzB.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CDiV5fjf.js.map → useYamlActivityEvents-hmCQQwzB.js.map} +1 -1
- package/dashboard/dist/assets/{validate-DcGWN82Y.js → validate-BIRn4a6d.js} +2 -2
- package/dashboard/dist/assets/{validate-DcGWN82Y.js.map → validate-BIRn4a6d.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CH8UrouH.js → yaml-workflows-ziUdZhKY.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CH8UrouH.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 +3 -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 +8 -5
- 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 +2 -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/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/iam.md +7 -5
- package/docs/maintenance.md +51 -28
- package/docs/mcp.md +159 -210
- package/docs/oauth-and-delegation.md +32 -21
- package/docs/topics.md +2 -0
- package/docs/workflows.md +14 -112
- package/package.json +5 -3
- package/dashboard/dist/assets/ConfirmDeleteModal-DW4DrPur.js +0 -2
- package/dashboard/dist/assets/ConfirmDeleteModal-DW4DrPur.js.map +0 -1
- package/dashboard/dist/assets/ProcessDetailPage-DNgCIwRl.js +0 -2
- package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js +0 -8
- package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js.map +0 -1
- package/dashboard/dist/assets/index-CtlBjl8o.js +0 -2
- package/dashboard/dist/assets/index-CtlBjl8o.js.map +0 -1
- package/dashboard/dist/assets/index-LRYC__mE.js +0 -67
- package/dashboard/dist/assets/index-LRYC__mE.js.map +0 -1
- package/dashboard/dist/assets/index-MYI2_Xb3.css +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
* - SUB, UNSUB, PING and PONG are forwarded, rebuilt from their parsed fields.
|
|
10
|
+
* - Any other operation, PUB and HPUB included, marks the stream malformed
|
|
11
|
+
* and the proxy closes the connection.
|
|
12
|
+
*
|
|
13
|
+
* The filter reads lines as nats-server does: fields split on spaces or tabs,
|
|
14
|
+
* and a line ends at LF with or without a preceding CR. Operations can span
|
|
15
|
+
* WebSocket frames, so the filter keeps whatever it has not yet seen whole.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.NatsClientFilter = void 0;
|
|
19
|
+
const LF = 0x0a;
|
|
20
|
+
const MAX_LINE = 64 * 1024;
|
|
21
|
+
const FIELD_DELIMITER = /[ \t]+/;
|
|
22
|
+
/** The operation name and its argument text. */
|
|
23
|
+
const OPERATION = /^[ \t]*([^ \t]+)[ \t]*(.*)$/s;
|
|
24
|
+
/** Control characters other than tab never appear inside a client line. */
|
|
25
|
+
const CONTROL_CHARACTER = /[\x00-\x08\x0a-\x1f\x7f]/;
|
|
26
|
+
/** Client operations forwarded, with the number of fields each takes. */
|
|
27
|
+
const ALLOWED_OPS = {
|
|
28
|
+
SUB: { min: 2, max: 3 },
|
|
29
|
+
UNSUB: { min: 1, max: 2 },
|
|
30
|
+
PING: { min: 0, max: 0 },
|
|
31
|
+
PONG: { min: 0, max: 0 },
|
|
32
|
+
};
|
|
33
|
+
class NatsClientFilter {
|
|
34
|
+
constructor(authToken) {
|
|
35
|
+
this.authToken = authToken;
|
|
36
|
+
this.pending = Buffer.alloc(0);
|
|
37
|
+
this.failed = false;
|
|
38
|
+
}
|
|
39
|
+
/** Whether the stream was malformed; the proxy closes the connection. */
|
|
40
|
+
get malformed() {
|
|
41
|
+
return this.failed;
|
|
42
|
+
}
|
|
43
|
+
/** The bytes to forward upstream for one chunk from the browser. */
|
|
44
|
+
feed(chunk) {
|
|
45
|
+
if (this.failed)
|
|
46
|
+
return Buffer.alloc(0);
|
|
47
|
+
this.pending = this.pending.length ? Buffer.concat([this.pending, chunk]) : chunk;
|
|
48
|
+
const out = [];
|
|
49
|
+
for (;;) {
|
|
50
|
+
const end = this.pending.indexOf(LF);
|
|
51
|
+
if (end === -1) {
|
|
52
|
+
if (this.pending.length > MAX_LINE)
|
|
53
|
+
return this.fail();
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
const raw = this.pending.subarray(0, end > 0 && this.pending[end - 1] === 0x0d ? end - 1 : end);
|
|
57
|
+
this.pending = this.pending.subarray(end + 1);
|
|
58
|
+
const forwarded = this.filterLine(raw.toString('utf8'));
|
|
59
|
+
if (this.failed)
|
|
60
|
+
return Buffer.alloc(0);
|
|
61
|
+
if (forwarded !== null)
|
|
62
|
+
out.push(Buffer.from(`${forwarded}\r\n`, 'utf8'));
|
|
63
|
+
}
|
|
64
|
+
return Buffer.concat(out);
|
|
65
|
+
}
|
|
66
|
+
fail() {
|
|
67
|
+
this.failed = true;
|
|
68
|
+
this.pending = Buffer.alloc(0);
|
|
69
|
+
return Buffer.alloc(0);
|
|
70
|
+
}
|
|
71
|
+
/** The line to forward, or null to forward nothing. */
|
|
72
|
+
filterLine(line) {
|
|
73
|
+
if (CONTROL_CHARACTER.test(line)) {
|
|
74
|
+
this.failed = true;
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const match = OPERATION.exec(line);
|
|
78
|
+
if (!match)
|
|
79
|
+
return null;
|
|
80
|
+
const op = match[1].toUpperCase();
|
|
81
|
+
const rest = match[2];
|
|
82
|
+
if (op === 'CONNECT')
|
|
83
|
+
return this.rewriteConnect(rest);
|
|
84
|
+
const shape = ALLOWED_OPS[op];
|
|
85
|
+
const fields = rest === '' ? [] : rest.split(FIELD_DELIMITER).filter(Boolean);
|
|
86
|
+
if (!shape || fields.length < shape.min || fields.length > shape.max) {
|
|
87
|
+
this.failed = true;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return [op, ...fields].join(' ');
|
|
91
|
+
}
|
|
92
|
+
rewriteConnect(json) {
|
|
93
|
+
let options;
|
|
94
|
+
try {
|
|
95
|
+
options = JSON.parse(json);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
this.failed = true;
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
if (!options || typeof options !== 'object' || Array.isArray(options)) {
|
|
102
|
+
this.failed = true;
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const { auth_token: _token, user: _user, pass: _pass, jwt: _jwt, nkey: _nkey, sig: _sig, ...rest } = options;
|
|
106
|
+
return `CONNECT ${JSON.stringify(this.authToken ? { ...rest, auth_token: this.authToken } : rest)}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.NatsClientFilter = NatsClientFilter;
|
|
@@ -18,6 +18,11 @@ export declare function deriveWsUrlFromRequest(req: {
|
|
|
18
18
|
* through an ALB or reverse proxy). This handler upgrades the connection
|
|
19
19
|
* and bridges bidirectionally to the internal NATS WS target.
|
|
20
20
|
*
|
|
21
|
+
* A connection needs an unspent ticket for an active account. The holder's
|
|
22
|
+
* account is rechecked every NATS_WS_RECHECK_SECONDS; a deactivation or a
|
|
23
|
+
* change in builder access closes the connection, and the dashboard
|
|
24
|
+
* reconnects with fresh credentials.
|
|
25
|
+
*
|
|
21
26
|
* The proxy auto-derives the public `wsUrl` from the first incoming
|
|
22
27
|
* request's headers, respecting `X-Forwarded-Proto` and `X-Forwarded-Host`
|
|
23
28
|
* so the correct `wss://` scheme is used behind TLS-terminating load balancers.
|
|
@@ -25,4 +30,6 @@ export declare function deriveWsUrlFromRequest(req: {
|
|
|
25
30
|
export declare function attachNatsWsProxy(server: HttpServer, target: string, options?: {
|
|
26
31
|
basePath?: string;
|
|
27
32
|
onWsUrlDerived?: (url: string) => void;
|
|
33
|
+
/** The NATS server credential, written into each browser's CONNECT by the proxy. */
|
|
34
|
+
authToken?: string | null;
|
|
28
35
|
}): void;
|
|
@@ -5,6 +5,11 @@ 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 config_1 = require("../../modules/config");
|
|
11
|
+
const browser_view_1 = require("./browser-view");
|
|
12
|
+
const nats_ws_ticket_1 = require("./nats-ws-ticket");
|
|
8
13
|
/** Default path for the NATS WebSocket proxy endpoint. */
|
|
9
14
|
exports.NATS_WS_PROXY_PATH = '/nats-ws';
|
|
10
15
|
/**
|
|
@@ -19,6 +24,31 @@ function deriveWsUrlFromRequest(req, basePath = '') {
|
|
|
19
24
|
const host = req.headers['x-forwarded-host'] || req.headers.host || 'localhost';
|
|
20
25
|
return `${scheme}://${host}${basePath}${exports.NATS_WS_PROXY_PATH}`;
|
|
21
26
|
}
|
|
27
|
+
/** The path and ticket of an upgrade's request target; null when it does not parse. */
|
|
28
|
+
function upgradeTarget(requestTarget) {
|
|
29
|
+
try {
|
|
30
|
+
const url = new URL(requestTarget ?? '/', 'http://proxy');
|
|
31
|
+
return { pathname: url.pathname, ticket: url.searchParams.get(nats_ws_ticket_1.NATS_WS_TICKET_PARAM) };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function refuseUpgrade(socket) {
|
|
38
|
+
socket.write('HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n');
|
|
39
|
+
socket.destroy();
|
|
40
|
+
}
|
|
41
|
+
/** Whether the holder's account still stands as it did when the connection opened. */
|
|
42
|
+
async function holderUnchanged(userId, viewer) {
|
|
43
|
+
try {
|
|
44
|
+
const now = await (0, browser_view_1.holderView)(userId);
|
|
45
|
+
return !!now && now.builder === viewer.builder;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
logger_1.loggerRegistry.warn(`[lt-nats-ws-proxy] holder recheck failed: ${err?.message}`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
22
52
|
/**
|
|
23
53
|
* Attach a WebSocket proxy to an HTTP server that bridges browser
|
|
24
54
|
* connections to an internal NATS WebSocket endpoint.
|
|
@@ -27,6 +57,11 @@ function deriveWsUrlFromRequest(req, basePath = '') {
|
|
|
27
57
|
* through an ALB or reverse proxy). This handler upgrades the connection
|
|
28
58
|
* and bridges bidirectionally to the internal NATS WS target.
|
|
29
59
|
*
|
|
60
|
+
* A connection needs an unspent ticket for an active account. The holder's
|
|
61
|
+
* account is rechecked every NATS_WS_RECHECK_SECONDS; a deactivation or a
|
|
62
|
+
* change in builder access closes the connection, and the dashboard
|
|
63
|
+
* reconnects with fresh credentials.
|
|
64
|
+
*
|
|
30
65
|
* The proxy auto-derives the public `wsUrl` from the first incoming
|
|
31
66
|
* request's headers, respecting `X-Forwarded-Proto` and `X-Forwarded-Host`
|
|
32
67
|
* so the correct `wss://` scheme is used behind TLS-terminating load balancers.
|
|
@@ -34,10 +69,19 @@ function deriveWsUrlFromRequest(req, basePath = '') {
|
|
|
34
69
|
function attachNatsWsProxy(server, target, options = {}) {
|
|
35
70
|
const basePath = options.basePath || '';
|
|
36
71
|
const proxyPath = `${basePath}${exports.NATS_WS_PROXY_PATH}`;
|
|
37
|
-
const wss = new ws_1.WebSocketServer({ noServer: true });
|
|
72
|
+
const wss = new ws_1.WebSocketServer({ noServer: true, maxPayload: config_1.config.NATS_WS_MAX_PAYLOAD_BYTES });
|
|
38
73
|
let derived = false;
|
|
39
|
-
|
|
40
|
-
|
|
74
|
+
const admit = async (req, socket, head, ticketParam) => {
|
|
75
|
+
// Only a signed-in person, holding an unspent ticket the credentials route issued.
|
|
76
|
+
const ticket = (0, nats_ws_ticket_1.verifyNatsWsTicket)(ticketParam);
|
|
77
|
+
if (!ticket || !(await (0, nats_ws_ticket_1.spendNatsWsTicket)(ticket)))
|
|
78
|
+
return refuseUpgrade(socket);
|
|
79
|
+
// Decided per connection: a builder receives events whole, anyone else
|
|
80
|
+
// receives the browser view (lib/events/browser-view.ts).
|
|
81
|
+
const viewer = await (0, browser_view_1.holderView)(ticket.userId);
|
|
82
|
+
if (!viewer)
|
|
83
|
+
return refuseUpgrade(socket);
|
|
84
|
+
if (socket.destroyed)
|
|
41
85
|
return;
|
|
42
86
|
// Derive the public wsUrl from the first request's headers
|
|
43
87
|
if (!derived && options.onWsUrlDerived) {
|
|
@@ -46,20 +90,45 @@ function attachNatsWsProxy(server, target, options = {}) {
|
|
|
46
90
|
}
|
|
47
91
|
wss.handleUpgrade(req, socket, head, (clientWs) => {
|
|
48
92
|
const upstream = new ws_1.WebSocket(target);
|
|
93
|
+
// The browser reads; the proxy holds the credential and refuses its publishes.
|
|
94
|
+
const filter = new nats_ws_filter_1.NatsClientFilter(options.authToken ?? null);
|
|
95
|
+
const inbound = viewer.builder ? null : new nats_ws_server_filter_1.NatsServerFilter((payload) => (0, browser_view_1.payloadForViewer)(payload, viewer));
|
|
49
96
|
upstream.on('open', () => {
|
|
50
97
|
clientWs.on('message', (data) => {
|
|
51
|
-
|
|
52
|
-
|
|
98
|
+
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
99
|
+
const forward = filter.feed(chunk);
|
|
100
|
+
if (filter.malformed) {
|
|
101
|
+
close();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (forward.length && upstream.readyState === ws_1.WebSocket.OPEN)
|
|
105
|
+
upstream.send(forward);
|
|
53
106
|
});
|
|
54
107
|
upstream.on('message', (data) => {
|
|
55
|
-
if (clientWs.readyState
|
|
108
|
+
if (clientWs.readyState !== ws_1.WebSocket.OPEN)
|
|
109
|
+
return;
|
|
110
|
+
if (!inbound) {
|
|
56
111
|
clientWs.send(data);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
115
|
+
const forward = inbound.feed(chunk);
|
|
116
|
+
if (forward.length)
|
|
117
|
+
clientWs.send(forward);
|
|
57
118
|
});
|
|
58
119
|
});
|
|
120
|
+
const recheck = setInterval(() => {
|
|
121
|
+
holderUnchanged(ticket.userId, viewer).then((unchanged) => {
|
|
122
|
+
if (!unchanged)
|
|
123
|
+
close();
|
|
124
|
+
});
|
|
125
|
+
}, config_1.config.NATS_WS_RECHECK_SECONDS * 1000);
|
|
126
|
+
recheck.unref();
|
|
59
127
|
const close = () => {
|
|
128
|
+
clearInterval(recheck);
|
|
60
129
|
if (clientWs.readyState === ws_1.WebSocket.OPEN)
|
|
61
130
|
clientWs.close();
|
|
62
|
-
if (upstream.readyState === ws_1.WebSocket.OPEN)
|
|
131
|
+
if (upstream.readyState === ws_1.WebSocket.OPEN || upstream.readyState === ws_1.WebSocket.CONNECTING)
|
|
63
132
|
upstream.close();
|
|
64
133
|
};
|
|
65
134
|
clientWs.on('close', close);
|
|
@@ -73,6 +142,16 @@ function attachNatsWsProxy(server, target, options = {}) {
|
|
|
73
142
|
close();
|
|
74
143
|
});
|
|
75
144
|
});
|
|
145
|
+
};
|
|
146
|
+
server.on('upgrade', (req, socket, head) => {
|
|
147
|
+
// A target that does not parse is not this proxy's; other listeners may take it.
|
|
148
|
+
const upgrade = upgradeTarget(req.url);
|
|
149
|
+
if (!upgrade || upgrade.pathname !== proxyPath)
|
|
150
|
+
return;
|
|
151
|
+
admit(req, socket, head, upgrade.ticket).catch((err) => {
|
|
152
|
+
logger_1.loggerRegistry.error(`[lt-nats-ws-proxy] upgrade failed: ${err?.message}`);
|
|
153
|
+
socket.destroy();
|
|
154
|
+
});
|
|
76
155
|
});
|
|
77
156
|
logger_1.loggerRegistry.info(`[lt-nats-ws-proxy] active: ${proxyPath} -> ${target}`);
|
|
78
157
|
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The server's half of a browser's NATS connection, as the WebSocket proxy
|
|
4
|
+
* forwards it. Message payloads (MSG and HMSG) pass through `rewrite`, which
|
|
5
|
+
* returns the payload to deliver or null to withhold the message; protocol
|
|
6
|
+
* lines (INFO, PING, PONG, +OK, -ERR) pass unchanged.
|
|
7
|
+
*
|
|
8
|
+
* Operations can span WebSocket frames, so the filter keeps whatever it has
|
|
9
|
+
* not yet seen whole.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.NatsServerFilter = void 0;
|
|
13
|
+
const CRLF = Buffer.from('\r\n');
|
|
14
|
+
class NatsServerFilter {
|
|
15
|
+
constructor(rewrite) {
|
|
16
|
+
this.rewrite = rewrite;
|
|
17
|
+
this.pending = Buffer.alloc(0);
|
|
18
|
+
}
|
|
19
|
+
/** The bytes to forward to the browser for one chunk from the server. */
|
|
20
|
+
feed(chunk) {
|
|
21
|
+
this.pending = this.pending.length ? Buffer.concat([this.pending, chunk]) : chunk;
|
|
22
|
+
const out = [];
|
|
23
|
+
for (;;) {
|
|
24
|
+
const end = this.pending.indexOf(CRLF);
|
|
25
|
+
if (end === -1)
|
|
26
|
+
break;
|
|
27
|
+
const line = this.pending.subarray(0, end).toString('utf8');
|
|
28
|
+
const space = line.indexOf(' ');
|
|
29
|
+
const op = (space === -1 ? line : line.slice(0, space)).toUpperCase();
|
|
30
|
+
if (op !== 'MSG' && op !== 'HMSG') {
|
|
31
|
+
out.push(this.pending.subarray(0, end + CRLF.length));
|
|
32
|
+
this.pending = this.pending.subarray(end + CRLF.length);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// MSG <subject> <sid> [reply] <size>
|
|
36
|
+
// HMSG <subject> <sid> [reply] <header size> <total size>
|
|
37
|
+
const args = line.slice(space + 1).trim().split(/\s+/);
|
|
38
|
+
const total = Number(args[args.length - 1]);
|
|
39
|
+
const headerSize = op === 'HMSG' ? Number(args[args.length - 2]) : 0;
|
|
40
|
+
const start = end + CRLF.length;
|
|
41
|
+
const need = start + total + CRLF.length;
|
|
42
|
+
if (this.pending.length < need)
|
|
43
|
+
break;
|
|
44
|
+
const headers = this.pending.subarray(start, start + headerSize);
|
|
45
|
+
const body = this.rewrite(this.pending.subarray(start + headerSize, start + total));
|
|
46
|
+
this.pending = this.pending.subarray(need);
|
|
47
|
+
if (body === null)
|
|
48
|
+
continue;
|
|
49
|
+
const prefix = args.slice(0, op === 'HMSG' ? -2 : -1).join(' ');
|
|
50
|
+
const sizes = op === 'HMSG' ? `${headerSize} ${headerSize + body.length}` : `${body.length}`;
|
|
51
|
+
out.push(Buffer.from(`${op} ${prefix} ${sizes}\r\n`, 'utf8'), headers, body, CRLF);
|
|
52
|
+
}
|
|
53
|
+
return Buffer.concat(out);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.NatsServerFilter = NatsServerFilter;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A browser's pass to the NATS WebSocket proxy, in place of the NATS server
|
|
3
|
+
* credential. It names the person in `sub` and carries no `userId`, so it
|
|
4
|
+
* authenticates nothing but the proxy upgrade. Each ticket admits one
|
|
5
|
+
* upgrade: the dashboard fetches a fresh one for every connection attempt.
|
|
6
|
+
*/
|
|
7
|
+
export declare const NATS_WS_TICKET_TYPE = "nats-ws+jwt";
|
|
8
|
+
export declare const NATS_WS_TICKET_PARAM = "ticket";
|
|
9
|
+
export interface NatsWsTicket {
|
|
10
|
+
userId: string;
|
|
11
|
+
jti: string;
|
|
12
|
+
/** Expiry, in seconds since the epoch. */
|
|
13
|
+
exp: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function signNatsWsTicket(userId: string): string | null;
|
|
16
|
+
/** The claims of a valid ticket; null for anything else. Does not spend it. */
|
|
17
|
+
export declare function verifyNatsWsTicket(ticket: string | null | undefined): NatsWsTicket | null;
|
|
18
|
+
/** Spend a verified ticket. False when it was already spent. */
|
|
19
|
+
export declare function spendNatsWsTicket(ticket: NatsWsTicket): Promise<boolean>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NATS_WS_TICKET_PARAM = exports.NATS_WS_TICKET_TYPE = void 0;
|
|
7
|
+
exports.signNatsWsTicket = signNatsWsTicket;
|
|
8
|
+
exports.verifyNatsWsTicket = verifyNatsWsTicket;
|
|
9
|
+
exports.spendNatsWsTicket = spendNatsWsTicket;
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
12
|
+
const db_1 = require("../db");
|
|
13
|
+
const config_1 = require("../../modules/config");
|
|
14
|
+
/**
|
|
15
|
+
* A browser's pass to the NATS WebSocket proxy, in place of the NATS server
|
|
16
|
+
* credential. It names the person in `sub` and carries no `userId`, so it
|
|
17
|
+
* authenticates nothing but the proxy upgrade. Each ticket admits one
|
|
18
|
+
* upgrade: the dashboard fetches a fresh one for every connection attempt.
|
|
19
|
+
*/
|
|
20
|
+
exports.NATS_WS_TICKET_TYPE = 'nats-ws+jwt';
|
|
21
|
+
exports.NATS_WS_TICKET_PARAM = 'ticket';
|
|
22
|
+
/** Record the ticket as spent, and drop expired records. True only for its first use. */
|
|
23
|
+
const SPEND_TICKET = `
|
|
24
|
+
WITH expired AS (
|
|
25
|
+
DELETE FROM lt_nats_ws_tickets WHERE expires_at < NOW()
|
|
26
|
+
)
|
|
27
|
+
INSERT INTO lt_nats_ws_tickets (jti, expires_at)
|
|
28
|
+
VALUES ($1, to_timestamp($2))
|
|
29
|
+
ON CONFLICT (jti) DO NOTHING
|
|
30
|
+
RETURNING jti`;
|
|
31
|
+
function signNatsWsTicket(userId) {
|
|
32
|
+
if (!config_1.config.JWT_SECRET)
|
|
33
|
+
return null;
|
|
34
|
+
return jsonwebtoken_1.default.sign({}, config_1.config.JWT_SECRET, {
|
|
35
|
+
algorithm: 'HS256',
|
|
36
|
+
header: { alg: 'HS256', typ: exports.NATS_WS_TICKET_TYPE },
|
|
37
|
+
subject: userId,
|
|
38
|
+
jwtid: (0, crypto_1.randomUUID)(),
|
|
39
|
+
expiresIn: config_1.config.NATS_WS_TICKET_TTL_SECONDS,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** The claims of a valid ticket; null for anything else. Does not spend it. */
|
|
43
|
+
function verifyNatsWsTicket(ticket) {
|
|
44
|
+
if (!ticket || !config_1.config.JWT_SECRET)
|
|
45
|
+
return null;
|
|
46
|
+
try {
|
|
47
|
+
const decoded = jsonwebtoken_1.default.verify(ticket, config_1.config.JWT_SECRET, { algorithms: ['HS256'], complete: true });
|
|
48
|
+
if (decoded.header.typ !== exports.NATS_WS_TICKET_TYPE)
|
|
49
|
+
return null;
|
|
50
|
+
const { sub, jti, exp } = decoded.payload;
|
|
51
|
+
if (typeof sub !== 'string' || typeof jti !== 'string' || typeof exp !== 'number')
|
|
52
|
+
return null;
|
|
53
|
+
return { userId: sub, jti, exp };
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Spend a verified ticket. False when it was already spent. */
|
|
60
|
+
async function spendNatsWsTicket(ticket) {
|
|
61
|
+
const { rowCount } = await (0, db_1.getPool)().query(SPEND_TICKET, [ticket.jti, ticket.exp]);
|
|
62
|
+
return rowCount === 1;
|
|
63
|
+
}
|
|
@@ -4,7 +4,16 @@ import type { LTEvent, LTEventAdapter } from '../../types';
|
|
|
4
4
|
* Callback to verify a Socket.IO handshake token.
|
|
5
5
|
* Return `true` to allow the connection, `false` to reject.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Verifies a socket's token. Returning the person (`{ userId }`) lets delivery
|
|
9
|
+
* follow their capabilities; `true` admits the socket with the browser view
|
|
10
|
+
* (lib/events/browser-view.ts).
|
|
11
|
+
*/
|
|
12
|
+
export type SocketIOAuthenticator = (token: string) => boolean | {
|
|
13
|
+
userId: string;
|
|
14
|
+
} | Promise<boolean | {
|
|
15
|
+
userId: string;
|
|
16
|
+
}>;
|
|
8
17
|
/**
|
|
9
18
|
* Socket.IO event adapter for browser clients.
|
|
10
19
|
*
|
|
@@ -4,6 +4,7 @@ exports.SocketIOEventAdapter = void 0;
|
|
|
4
4
|
const socket_io_1 = require("socket.io");
|
|
5
5
|
const logger_1 = require("../logger");
|
|
6
6
|
const matching_1 = require("./matching");
|
|
7
|
+
const browser_view_1 = require("./browser-view");
|
|
7
8
|
/**
|
|
8
9
|
* Socket.IO event adapter for browser clients.
|
|
9
10
|
*
|
|
@@ -73,6 +74,8 @@ class SocketIOEventAdapter {
|
|
|
73
74
|
if (!valid) {
|
|
74
75
|
return next(new Error('Authentication failed'));
|
|
75
76
|
}
|
|
77
|
+
if (typeof valid === 'object')
|
|
78
|
+
socket.data.ltUserId = valid.userId;
|
|
76
79
|
next();
|
|
77
80
|
}
|
|
78
81
|
catch {
|
|
@@ -86,6 +89,9 @@ class SocketIOEventAdapter {
|
|
|
86
89
|
// switches the socket from broadcast to scoped delivery.
|
|
87
90
|
const patterns = new Set();
|
|
88
91
|
socket.data.ltPatterns = patterns;
|
|
92
|
+
// Until the lookup answers, the socket receives the browser view.
|
|
93
|
+
socket.data.ltViewer = { builder: false };
|
|
94
|
+
(0, browser_view_1.viewerFor)(socket.data.ltUserId).then((viewer) => { socket.data.ltViewer = viewer; });
|
|
89
95
|
socket.on('lt.subscribe', (pattern) => {
|
|
90
96
|
if (typeof pattern === 'string' && pattern.length > 0 && pattern.length <= 256) {
|
|
91
97
|
patterns.add(pattern);
|
|
@@ -107,14 +113,15 @@ class SocketIOEventAdapter {
|
|
|
107
113
|
const channel = `lt.events.${event.type}`;
|
|
108
114
|
for (const socket of this.io.of('/').sockets.values()) {
|
|
109
115
|
const patterns = socket.data.ltPatterns;
|
|
116
|
+
const delivered = (0, browser_view_1.eventForViewer)(event, socket.data.ltViewer ?? { builder: false });
|
|
110
117
|
if (!patterns || patterns.size === 0) {
|
|
111
|
-
// Legacy scope: a socket with no registered patterns gets
|
|
112
|
-
socket.emit(channel,
|
|
118
|
+
// Legacy scope: a socket with no registered patterns gets every subject.
|
|
119
|
+
socket.emit(channel, delivered);
|
|
113
120
|
continue;
|
|
114
121
|
}
|
|
115
122
|
for (const pattern of patterns) {
|
|
116
123
|
if ((0, matching_1.subjectMatchesPattern)(channel, pattern)) {
|
|
117
|
-
socket.emit(channel,
|
|
124
|
+
socket.emit(channel, delivered);
|
|
118
125
|
break;
|
|
119
126
|
}
|
|
120
127
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* The single module that imports the HTTP framework.
|
|
4
|
+
*
|
|
5
|
+
* Routes, middleware, adapters and the standalone server take routers,
|
|
6
|
+
* handler types and body/static middleware from here. Long Tail runs both
|
|
7
|
+
* as its own server and as a guest on a host's Express instance (NestJS,
|
|
8
|
+
* Express), so the framework dependency has exactly one owner.
|
|
9
|
+
*/
|
|
10
|
+
export { Router } from 'express';
|
|
11
|
+
export type { Application, ErrorRequestHandler, NextFunction, Request, RequestHandler, Response, } from 'express';
|
|
12
|
+
type JsonBodyOptions = Parameters<typeof express.json>[0];
|
|
13
|
+
type StaticFilesOptions = Parameters<typeof express.static>[1];
|
|
14
|
+
/** A new application. Only the standalone server owns one; embedded mode uses the host's. */
|
|
15
|
+
export declare function createApp(): express.Application;
|
|
16
|
+
/** JSON body parsing. A body the host already parsed is left as is. */
|
|
17
|
+
export declare function jsonBody(options?: JsonBodyOptions): express.RequestHandler;
|
|
18
|
+
/** Static file serving from `root`. */
|
|
19
|
+
export declare function serveStatic(root: string, options?: StaticFilesOptions): express.RequestHandler;
|
|
20
|
+
/**
|
|
21
|
+
* Non-credentialed CORS for public endpoints: any origin may call them, and
|
|
22
|
+
* preflight requests are answered here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function allowAnyOrigin(methods?: string[]): express.RequestHandler;
|
|
25
|
+
type FormBodyOptions = Parameters<typeof express.urlencoded>[0];
|
|
26
|
+
/** URL-encoded form body parsing. A body the host already parsed is left as is. */
|
|
27
|
+
export declare function formBody(options?: FormBodyOptions): express.RequestHandler;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Router = void 0;
|
|
7
|
+
exports.createApp = createApp;
|
|
8
|
+
exports.jsonBody = jsonBody;
|
|
9
|
+
exports.serveStatic = serveStatic;
|
|
10
|
+
exports.allowAnyOrigin = allowAnyOrigin;
|
|
11
|
+
exports.formBody = formBody;
|
|
12
|
+
const express_1 = __importDefault(require("express"));
|
|
13
|
+
/**
|
|
14
|
+
* The single module that imports the HTTP framework.
|
|
15
|
+
*
|
|
16
|
+
* Routes, middleware, adapters and the standalone server take routers,
|
|
17
|
+
* handler types and body/static middleware from here. Long Tail runs both
|
|
18
|
+
* as its own server and as a guest on a host's Express instance (NestJS,
|
|
19
|
+
* Express), so the framework dependency has exactly one owner.
|
|
20
|
+
*/
|
|
21
|
+
var express_2 = require("express");
|
|
22
|
+
Object.defineProperty(exports, "Router", { enumerable: true, get: function () { return express_2.Router; } });
|
|
23
|
+
/** A new application. Only the standalone server owns one; embedded mode uses the host's. */
|
|
24
|
+
function createApp() {
|
|
25
|
+
return (0, express_1.default)();
|
|
26
|
+
}
|
|
27
|
+
/** JSON body parsing. A body the host already parsed is left as is. */
|
|
28
|
+
function jsonBody(options) {
|
|
29
|
+
return express_1.default.json(options);
|
|
30
|
+
}
|
|
31
|
+
/** Static file serving from `root`. */
|
|
32
|
+
function serveStatic(root, options) {
|
|
33
|
+
return express_1.default.static(root, options);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Non-credentialed CORS for public endpoints: any origin may call them, and
|
|
37
|
+
* preflight requests are answered here.
|
|
38
|
+
*/
|
|
39
|
+
function allowAnyOrigin(methods = ['GET', 'POST']) {
|
|
40
|
+
const allowMethods = [...methods, 'OPTIONS'].join(', ');
|
|
41
|
+
return (req, res, next) => {
|
|
42
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
43
|
+
res.setHeader('Access-Control-Allow-Methods', allowMethods);
|
|
44
|
+
res.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type, MCP-Protocol-Version');
|
|
45
|
+
if (req.method === 'OPTIONS') {
|
|
46
|
+
res.status(204).end();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
next();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** URL-encoded form body parsing. A body the host already parsed is left as is. */
|
|
53
|
+
function formBody(options = { extended: false }) {
|
|
54
|
+
return express_1.default.urlencoded(options);
|
|
55
|
+
}
|
package/build/modules/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Request, RequestHandler } from '
|
|
1
|
+
import { Request, RequestHandler } from '../lib/http';
|
|
2
2
|
import type { AuthPayload, LTAuthAdapter } from '../types';
|
|
3
3
|
export type { AuthPayload, LTAuthAdapter };
|
|
4
4
|
declare global {
|
|
@@ -40,34 +40,25 @@ export declare class JwtAuthAdapter implements LTAuthAdapter {
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function createAuthMiddleware(adapter: LTAuthAdapter): RequestHandler;
|
|
42
42
|
export declare const requireAuth: RequestHandler;
|
|
43
|
+
/**
|
|
44
|
+
* `requireAuth` without the SSO fallback: only a credential the request
|
|
45
|
+
* carries itself (the configured adapter, else a Bearer JWT or bot key).
|
|
46
|
+
* For endpoints a cross-site page must not reach through the host's cookie.
|
|
47
|
+
*/
|
|
48
|
+
export declare const requireCredentialAuth: RequestHandler;
|
|
43
49
|
/**
|
|
44
50
|
* Replace the auth adapter used by `requireAuth`.
|
|
45
51
|
* Call before starting the server.
|
|
46
52
|
*/
|
|
47
53
|
export declare function setAuthAdapter(adapter: LTAuthAdapter): void;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* Middleware that requires builder access. Must be placed AFTER requireAuth.
|
|
57
|
-
*
|
|
58
|
-
* Builders are superadmin or users with the 'engineer' role.
|
|
59
|
-
* This is the backend equivalent of the dashboard's `isBuilder` check.
|
|
60
|
-
*/
|
|
61
|
-
export declare const requireBuilder: RequestHandler;
|
|
62
|
-
/**
|
|
63
|
-
* Middleware that requires role-management access. Must be placed AFTER requireAuth.
|
|
64
|
-
*
|
|
65
|
-
* Grants access to superadmins, admin-type users, and engineers — the backend
|
|
66
|
-
* equivalent of the dashboard's `isBuilder || isOps`. Ops (admin type) manage
|
|
67
|
-
* users and roles; builders (superadmin, engineer) are a superset. This is the
|
|
68
|
-
* gate for reading and writing role definitions.
|
|
69
|
-
*/
|
|
70
|
-
export declare const requireRoleManager: RequestHandler;
|
|
54
|
+
/** Admin access: admin or superadmin claim, or a superadmin in the database. */
|
|
55
|
+
export declare const requireAdmin: RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
|
|
56
|
+
/** Builder access: superadmin or the 'engineer' role. Backend twin of the dashboard's `isBuilder`. */
|
|
57
|
+
export declare const requireBuilder: RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
|
|
58
|
+
/** Role-management access: admin access or the 'engineer' role. Backend twin of `isBuilder || isOps`. */
|
|
59
|
+
export declare const requireRoleManager: RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
|
|
60
|
+
/** Reads of one workflow run (`:workflowId`): builder access, or the person who started it or it runs as. */
|
|
61
|
+
export declare const requireWorkflowReader: RequestHandler;
|
|
71
62
|
/**
|
|
72
63
|
* Generate a JWT token. Utility for tests and token provisioning.
|
|
73
64
|
*/
|