@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
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkAuthorizationRequest = checkAuthorizationRequest;
|
|
4
|
+
exports.isGrantPreset = isGrantPreset;
|
|
5
|
+
exports.withQuery = withQuery;
|
|
6
|
+
exports.grantablePresets = grantablePresets;
|
|
7
|
+
const registration_1 = require("./registration");
|
|
8
|
+
const store_1 = require("./store");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const CODE_CHALLENGE = /^[A-Za-z0-9_-]{43,128}$/;
|
|
11
|
+
const PRESETS = new Set(Object.keys(constants_1.PRESET_SCOPE));
|
|
12
|
+
const text = (value) => (typeof value === 'string' && value !== '' && !(0, registration_1.hasControlCharacters)(value) ? value : undefined);
|
|
13
|
+
async function checkAuthorizationRequest(params, settings) {
|
|
14
|
+
const clientId = text(params.client_id);
|
|
15
|
+
const redirectUri = text(params.redirect_uri);
|
|
16
|
+
const client = clientId ? await (0, store_1.getClient)(clientId) : null;
|
|
17
|
+
if (!client)
|
|
18
|
+
return { ok: false, redirect: false, error: 'invalid_client', description: 'unknown client_id' };
|
|
19
|
+
if (!redirectUri || !client.redirect_uris.includes(redirectUri)) {
|
|
20
|
+
return { ok: false, redirect: false, error: 'invalid_request', description: 'redirect_uri is not registered for this client' };
|
|
21
|
+
}
|
|
22
|
+
const state = text(params.state);
|
|
23
|
+
const fail = (error, description) => ({ ok: false, redirect: true, redirectUri, state, error, description });
|
|
24
|
+
if (params.response_type !== 'code')
|
|
25
|
+
return fail('unsupported_response_type', 'response_type must be code');
|
|
26
|
+
const codeChallenge = text(params.code_challenge);
|
|
27
|
+
if (!codeChallenge || !CODE_CHALLENGE.test(codeChallenge))
|
|
28
|
+
return fail('invalid_request', 'a PKCE code_challenge is required');
|
|
29
|
+
if (params.code_challenge_method !== 'S256')
|
|
30
|
+
return fail('invalid_request', 'code_challenge_method must be S256');
|
|
31
|
+
const resource = text(params.resource) ?? settings.resource;
|
|
32
|
+
if (resource !== settings.resource)
|
|
33
|
+
return fail('invalid_target', `resource must be ${settings.resource}`);
|
|
34
|
+
return { ok: true, request: { client, redirectUri, codeChallenge, state, scope: text(params.scope), resource } };
|
|
35
|
+
}
|
|
36
|
+
function isGrantPreset(value) {
|
|
37
|
+
return typeof value === 'string' && PRESETS.has(value);
|
|
38
|
+
}
|
|
39
|
+
/** `uri` with `params` added to its query, keeping any query it already has. */
|
|
40
|
+
function withQuery(uri, params) {
|
|
41
|
+
const url = new URL(uri);
|
|
42
|
+
for (const [key, value] of Object.entries(params))
|
|
43
|
+
if (value !== undefined)
|
|
44
|
+
url.searchParams.set(key, value);
|
|
45
|
+
return url.toString();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The presets the person may grant. Read-only always; Just be me only when it
|
|
49
|
+
* adds something: a membership that can write, or an admin tier.
|
|
50
|
+
*/
|
|
51
|
+
function grantablePresets(roles) {
|
|
52
|
+
const canWrite = roles.some((r) => r.type === 'admin' || r.type === 'superadmin' || (r.write_scope ?? 'all') !== 'none');
|
|
53
|
+
return canWrite ? ['read_only', 'just_me'] : ['read_only'];
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LTGrantPreset } from '../../../types/oauth-server';
|
|
2
|
+
export declare const MCP_SCOPES: {
|
|
3
|
+
readonly READ: "mcp:read";
|
|
4
|
+
readonly FULL: "mcp:full";
|
|
5
|
+
};
|
|
6
|
+
/** The coarse scope a grant preset is reported as. */
|
|
7
|
+
export declare const PRESET_SCOPE: Record<LTGrantPreset, string>;
|
|
8
|
+
/** JOSE `typ` for access tokens (RFC 9068). */
|
|
9
|
+
export declare const ACCESS_TOKEN_TYPE = "at+jwt";
|
|
10
|
+
/** `principalType` of a request authenticated by an OAuth access token. */
|
|
11
|
+
export declare const OAUTH_PRINCIPAL_TYPE = "oauth";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OAUTH_PRINCIPAL_TYPE = exports.ACCESS_TOKEN_TYPE = exports.PRESET_SCOPE = exports.MCP_SCOPES = void 0;
|
|
4
|
+
exports.MCP_SCOPES = {
|
|
5
|
+
READ: 'mcp:read',
|
|
6
|
+
FULL: 'mcp:full',
|
|
7
|
+
};
|
|
8
|
+
/** The coarse scope a grant preset is reported as. */
|
|
9
|
+
exports.PRESET_SCOPE = {
|
|
10
|
+
read_only: exports.MCP_SCOPES.READ,
|
|
11
|
+
just_me: exports.MCP_SCOPES.FULL,
|
|
12
|
+
};
|
|
13
|
+
/** JOSE `typ` for access tokens (RFC 9068). */
|
|
14
|
+
exports.ACCESS_TOKEN_TYPE = 'at+jwt';
|
|
15
|
+
/** `principalType` of a request authenticated by an OAuth access token. */
|
|
16
|
+
exports.OAUTH_PRINCIPAL_TYPE = 'oauth';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { REFRESH_REUSE_GRACE_SECONDS, createSecret, hashSecret, pkceChallenge, registerClient, getClient, issueAuthorizationCode, exchangeAuthorizationCode, rotateRefreshToken, getLiveGrant, revokeByRefreshToken, revokeGrant, listGrants, type RevokedGrant, } from './store';
|
|
2
|
+
export { signAccessToken, verifyAccessToken, accessTokenPrincipal, type AccessTokenTarget, type LTAccessTokenClaims, } from './access-token';
|
|
3
|
+
export { MCP_SCOPES, PRESET_SCOPE, ACCESS_TOKEN_TYPE, OAUTH_PRINCIPAL_TYPE } from './constants';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OAUTH_PRINCIPAL_TYPE = exports.ACCESS_TOKEN_TYPE = exports.PRESET_SCOPE = exports.MCP_SCOPES = exports.accessTokenPrincipal = exports.verifyAccessToken = exports.signAccessToken = exports.listGrants = exports.revokeGrant = exports.revokeByRefreshToken = exports.getLiveGrant = exports.rotateRefreshToken = exports.exchangeAuthorizationCode = exports.issueAuthorizationCode = exports.getClient = exports.registerClient = exports.pkceChallenge = exports.hashSecret = exports.createSecret = exports.REFRESH_REUSE_GRACE_SECONDS = void 0;
|
|
4
|
+
var store_1 = require("./store");
|
|
5
|
+
Object.defineProperty(exports, "REFRESH_REUSE_GRACE_SECONDS", { enumerable: true, get: function () { return store_1.REFRESH_REUSE_GRACE_SECONDS; } });
|
|
6
|
+
Object.defineProperty(exports, "createSecret", { enumerable: true, get: function () { return store_1.createSecret; } });
|
|
7
|
+
Object.defineProperty(exports, "hashSecret", { enumerable: true, get: function () { return store_1.hashSecret; } });
|
|
8
|
+
Object.defineProperty(exports, "pkceChallenge", { enumerable: true, get: function () { return store_1.pkceChallenge; } });
|
|
9
|
+
Object.defineProperty(exports, "registerClient", { enumerable: true, get: function () { return store_1.registerClient; } });
|
|
10
|
+
Object.defineProperty(exports, "getClient", { enumerable: true, get: function () { return store_1.getClient; } });
|
|
11
|
+
Object.defineProperty(exports, "issueAuthorizationCode", { enumerable: true, get: function () { return store_1.issueAuthorizationCode; } });
|
|
12
|
+
Object.defineProperty(exports, "exchangeAuthorizationCode", { enumerable: true, get: function () { return store_1.exchangeAuthorizationCode; } });
|
|
13
|
+
Object.defineProperty(exports, "rotateRefreshToken", { enumerable: true, get: function () { return store_1.rotateRefreshToken; } });
|
|
14
|
+
Object.defineProperty(exports, "getLiveGrant", { enumerable: true, get: function () { return store_1.getLiveGrant; } });
|
|
15
|
+
Object.defineProperty(exports, "revokeByRefreshToken", { enumerable: true, get: function () { return store_1.revokeByRefreshToken; } });
|
|
16
|
+
Object.defineProperty(exports, "revokeGrant", { enumerable: true, get: function () { return store_1.revokeGrant; } });
|
|
17
|
+
Object.defineProperty(exports, "listGrants", { enumerable: true, get: function () { return store_1.listGrants; } });
|
|
18
|
+
var access_token_1 = require("./access-token");
|
|
19
|
+
Object.defineProperty(exports, "signAccessToken", { enumerable: true, get: function () { return access_token_1.signAccessToken; } });
|
|
20
|
+
Object.defineProperty(exports, "verifyAccessToken", { enumerable: true, get: function () { return access_token_1.verifyAccessToken; } });
|
|
21
|
+
Object.defineProperty(exports, "accessTokenPrincipal", { enumerable: true, get: function () { return access_token_1.accessTokenPrincipal; } });
|
|
22
|
+
var constants_1 = require("./constants");
|
|
23
|
+
Object.defineProperty(exports, "MCP_SCOPES", { enumerable: true, get: function () { return constants_1.MCP_SCOPES; } });
|
|
24
|
+
Object.defineProperty(exports, "PRESET_SCOPE", { enumerable: true, get: function () { return constants_1.PRESET_SCOPE; } });
|
|
25
|
+
Object.defineProperty(exports, "ACCESS_TOKEN_TYPE", { enumerable: true, get: function () { return constants_1.ACCESS_TOKEN_TYPE; } });
|
|
26
|
+
Object.defineProperty(exports, "OAUTH_PRINCIPAL_TYPE", { enumerable: true, get: function () { return constants_1.OAUTH_PRINCIPAL_TYPE; } });
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OAuthServerSettings } from '../../../modules/oauth-server';
|
|
2
|
+
/** Endpoint paths under the issuer. */
|
|
3
|
+
export declare const OAUTH_ENDPOINT_PATHS: {
|
|
4
|
+
readonly AUTHORIZE: "/api/oauth/authorize";
|
|
5
|
+
readonly TOKEN: "/api/oauth/token";
|
|
6
|
+
readonly REGISTER: "/api/oauth/register";
|
|
7
|
+
readonly REVOKE: "/api/oauth/revoke";
|
|
8
|
+
};
|
|
9
|
+
/** RFC 8414 authorization server metadata. */
|
|
10
|
+
export declare function authorizationServerMetadata(settings: OAuthServerSettings): Record<string, unknown>;
|
|
11
|
+
/** RFC 9728 protected resource metadata for `/mcp`. */
|
|
12
|
+
export declare function protectedResourceMetadata(settings: OAuthServerSettings): Record<string, unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* Root-relative paths of the two well-known documents. The issuer's and the
|
|
15
|
+
* resource's paths are appended after the well-known segment (RFC 8414 §3,
|
|
16
|
+
* RFC 9728 §3).
|
|
17
|
+
*/
|
|
18
|
+
export declare function wellKnownPaths(settings: OAuthServerSettings): {
|
|
19
|
+
authorizationServer: string;
|
|
20
|
+
protectedResource: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OAUTH_ENDPOINT_PATHS = void 0;
|
|
4
|
+
exports.authorizationServerMetadata = authorizationServerMetadata;
|
|
5
|
+
exports.protectedResourceMetadata = protectedResourceMetadata;
|
|
6
|
+
exports.wellKnownPaths = wellKnownPaths;
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
/** Endpoint paths under the issuer. */
|
|
9
|
+
exports.OAUTH_ENDPOINT_PATHS = {
|
|
10
|
+
AUTHORIZE: '/api/oauth/authorize',
|
|
11
|
+
TOKEN: '/api/oauth/token',
|
|
12
|
+
REGISTER: '/api/oauth/register',
|
|
13
|
+
REVOKE: '/api/oauth/revoke',
|
|
14
|
+
};
|
|
15
|
+
const SCOPES_SUPPORTED = [constants_1.MCP_SCOPES.READ, constants_1.MCP_SCOPES.FULL];
|
|
16
|
+
/** RFC 8414 authorization server metadata. */
|
|
17
|
+
function authorizationServerMetadata(settings) {
|
|
18
|
+
const at = (path) => `${settings.issuer}${path}`;
|
|
19
|
+
return {
|
|
20
|
+
issuer: settings.issuer,
|
|
21
|
+
authorization_endpoint: at(exports.OAUTH_ENDPOINT_PATHS.AUTHORIZE),
|
|
22
|
+
token_endpoint: at(exports.OAUTH_ENDPOINT_PATHS.TOKEN),
|
|
23
|
+
registration_endpoint: at(exports.OAUTH_ENDPOINT_PATHS.REGISTER),
|
|
24
|
+
revocation_endpoint: at(exports.OAUTH_ENDPOINT_PATHS.REVOKE),
|
|
25
|
+
response_types_supported: ['code'],
|
|
26
|
+
grant_types_supported: ['authorization_code', 'refresh_token'],
|
|
27
|
+
code_challenge_methods_supported: ['S256'],
|
|
28
|
+
token_endpoint_auth_methods_supported: ['none'],
|
|
29
|
+
revocation_endpoint_auth_methods_supported: ['none'],
|
|
30
|
+
scopes_supported: SCOPES_SUPPORTED,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** RFC 9728 protected resource metadata for `/mcp`. */
|
|
34
|
+
function protectedResourceMetadata(settings) {
|
|
35
|
+
return {
|
|
36
|
+
resource: settings.resource,
|
|
37
|
+
authorization_servers: [settings.issuer],
|
|
38
|
+
bearer_methods_supported: ['header'],
|
|
39
|
+
scopes_supported: SCOPES_SUPPORTED,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Root-relative paths of the two well-known documents. The issuer's and the
|
|
44
|
+
* resource's paths are appended after the well-known segment (RFC 8414 §3,
|
|
45
|
+
* RFC 9728 §3).
|
|
46
|
+
*/
|
|
47
|
+
function wellKnownPaths(settings) {
|
|
48
|
+
const issuerPath = new URL(settings.issuer).pathname.replace(/\/+$/, '');
|
|
49
|
+
return {
|
|
50
|
+
authorizationServer: `/.well-known/oauth-authorization-server${issuerPath}`,
|
|
51
|
+
protectedResource: new URL(settings.resourceMetadataUrl).pathname,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic client registration (RFC 7591) for public MCP clients: validation
|
|
3
|
+
* of the requested client metadata, and a per-address registration limit.
|
|
4
|
+
*/
|
|
5
|
+
/** Whether a value carries a control character. */
|
|
6
|
+
export declare function hasControlCharacters(value: string): boolean;
|
|
7
|
+
/** A client name as the consent page may show it: no controls, no direction overrides, trimmed. */
|
|
8
|
+
export declare function displayableClientName(name: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* The address a registration counts against: IPv4 as is, IPv6 by its /64,
|
|
11
|
+
* which one host or network usually holds in full.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registrationAddressKey(address: string): string;
|
|
14
|
+
export declare const REGISTRATION_ERRORS: {
|
|
15
|
+
readonly INVALID_REDIRECT_URI: "invalid_redirect_uri";
|
|
16
|
+
readonly INVALID_CLIENT_METADATA: "invalid_client_metadata";
|
|
17
|
+
};
|
|
18
|
+
export type RegistrationResult = {
|
|
19
|
+
ok: true;
|
|
20
|
+
clientName?: string;
|
|
21
|
+
redirectUris: string[];
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
error: string;
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Loopback http or https on any port, or an https URI equal, in canonical
|
|
29
|
+
* form, to one the deployment allows. Matching whole URIs, not hosts, keeps a
|
|
30
|
+
* code from landing on any other path, query or port of an allowed host.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isAllowedRedirectUri(uri: string, allowedUris: string[]): boolean;
|
|
33
|
+
export declare function validateClientMetadata(body: unknown, allowedUris: string[]): RegistrationResult;
|
|
34
|
+
/** A fixed-window count of registrations per address, in memory, per process. */
|
|
35
|
+
export declare class RegistrationLimiter {
|
|
36
|
+
private readonly limit;
|
|
37
|
+
private readonly windowMs;
|
|
38
|
+
private windows;
|
|
39
|
+
constructor(limit: number, windowMs: number);
|
|
40
|
+
/** Count one registration from `address`; false when over the limit. */
|
|
41
|
+
allow(address: string, now?: number): boolean;
|
|
42
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dynamic client registration (RFC 7591) for public MCP clients: validation
|
|
4
|
+
* of the requested client metadata, and a per-address registration limit.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RegistrationLimiter = exports.REGISTRATION_ERRORS = void 0;
|
|
8
|
+
exports.hasControlCharacters = hasControlCharacters;
|
|
9
|
+
exports.displayableClientName = displayableClientName;
|
|
10
|
+
exports.registrationAddressKey = registrationAddressKey;
|
|
11
|
+
exports.isAllowedRedirectUri = isAllowedRedirectUri;
|
|
12
|
+
exports.validateClientMetadata = validateClientMetadata;
|
|
13
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '[::1]']);
|
|
14
|
+
/** C0 controls, DEL and C1 controls: never part of a token, an id or a URI. */
|
|
15
|
+
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/;
|
|
16
|
+
/** Characters that reorder or hide text: a self-chosen client name must not use them to spoof another. */
|
|
17
|
+
const DISPLAY_SPOOFING = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u2069\ufeff]/g;
|
|
18
|
+
/** Whether a value carries a control character. */
|
|
19
|
+
function hasControlCharacters(value) {
|
|
20
|
+
return CONTROL_CHARACTERS.test(value);
|
|
21
|
+
}
|
|
22
|
+
/** A client name as the consent page may show it: no controls, no direction overrides, trimmed. */
|
|
23
|
+
function displayableClientName(name) {
|
|
24
|
+
return name.replace(DISPLAY_SPOOFING, '').trim();
|
|
25
|
+
}
|
|
26
|
+
/** An IPv6 address as its eight groups, or null when it is not one. */
|
|
27
|
+
function ipv6Groups(ip) {
|
|
28
|
+
const halves = ip.split('::');
|
|
29
|
+
if (halves.length > 2)
|
|
30
|
+
return null;
|
|
31
|
+
const head = halves[0] ? halves[0].split(':') : [];
|
|
32
|
+
if (halves.length === 1)
|
|
33
|
+
return head.length === 8 ? head : null;
|
|
34
|
+
const tail = halves[1] ? halves[1].split(':') : [];
|
|
35
|
+
const missing = 8 - head.length - tail.length;
|
|
36
|
+
return missing < 0 ? null : [...head, ...Array(missing).fill('0'), ...tail];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The address a registration counts against: IPv4 as is, IPv6 by its /64,
|
|
40
|
+
* which one host or network usually holds in full.
|
|
41
|
+
*/
|
|
42
|
+
function registrationAddressKey(address) {
|
|
43
|
+
const ip = address.split('%')[0];
|
|
44
|
+
if (ip.startsWith('::ffff:') && ip.includes('.'))
|
|
45
|
+
return ip.slice(7);
|
|
46
|
+
if (!ip.includes(':'))
|
|
47
|
+
return ip;
|
|
48
|
+
const groups = ipv6Groups(ip);
|
|
49
|
+
if (!groups)
|
|
50
|
+
return ip;
|
|
51
|
+
return `${groups.slice(0, 4).map((g) => (g.replace(/^0+(?=.)/, '') || '0').toLowerCase()).join(':')}::/64`;
|
|
52
|
+
}
|
|
53
|
+
const MAX_REDIRECT_URIS = 10;
|
|
54
|
+
const MAX_URI_LENGTH = 2048;
|
|
55
|
+
const MAX_NAME_LENGTH = 200;
|
|
56
|
+
const GRANT_TYPES = new Set(['authorization_code', 'refresh_token']);
|
|
57
|
+
const RESPONSE_TYPES = new Set(['code']);
|
|
58
|
+
exports.REGISTRATION_ERRORS = {
|
|
59
|
+
INVALID_REDIRECT_URI: 'invalid_redirect_uri',
|
|
60
|
+
INVALID_CLIENT_METADATA: 'invalid_client_metadata',
|
|
61
|
+
};
|
|
62
|
+
function invalid(error, description) {
|
|
63
|
+
return { ok: false, error, description };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Loopback http or https on any port, or an https URI equal, in canonical
|
|
67
|
+
* form, to one the deployment allows. Matching whole URIs, not hosts, keeps a
|
|
68
|
+
* code from landing on any other path, query or port of an allowed host.
|
|
69
|
+
*/
|
|
70
|
+
function isAllowedRedirectUri(uri, allowedUris) {
|
|
71
|
+
if (uri.length > MAX_URI_LENGTH || hasControlCharacters(uri) || uri.trim() !== uri)
|
|
72
|
+
return false;
|
|
73
|
+
let url;
|
|
74
|
+
try {
|
|
75
|
+
url = new URL(uri);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (url.hash || url.username || url.password)
|
|
81
|
+
return false;
|
|
82
|
+
if (url.protocol === 'http:')
|
|
83
|
+
return LOOPBACK_HOSTS.has(url.hostname);
|
|
84
|
+
if (url.protocol !== 'https:')
|
|
85
|
+
return false;
|
|
86
|
+
if (LOOPBACK_HOSTS.has(url.hostname))
|
|
87
|
+
return true;
|
|
88
|
+
return allowedUris.includes(url.href);
|
|
89
|
+
}
|
|
90
|
+
const isStringArray = (value) => Array.isArray(value) && value.every((v) => typeof v === 'string');
|
|
91
|
+
function validateClientMetadata(body, allowedUris) {
|
|
92
|
+
const input = (body ?? {});
|
|
93
|
+
const { redirect_uris, client_name, token_endpoint_auth_method, grant_types, response_types } = input;
|
|
94
|
+
if (!isStringArray(redirect_uris) || redirect_uris.length === 0 || redirect_uris.length > MAX_REDIRECT_URIS) {
|
|
95
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_REDIRECT_URI, `redirect_uris must list 1 to ${MAX_REDIRECT_URIS} URIs`);
|
|
96
|
+
}
|
|
97
|
+
const refused = redirect_uris.find((uri) => !isAllowedRedirectUri(uri, allowedUris));
|
|
98
|
+
if (refused !== undefined) {
|
|
99
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_REDIRECT_URI, `redirect URI not allowed: ${refused.slice(0, 200)}`);
|
|
100
|
+
}
|
|
101
|
+
if (client_name !== undefined && (typeof client_name !== 'string' || client_name.length > MAX_NAME_LENGTH)) {
|
|
102
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_CLIENT_METADATA, `client_name must be a string of at most ${MAX_NAME_LENGTH} characters`);
|
|
103
|
+
}
|
|
104
|
+
const shownName = typeof client_name === 'string' ? displayableClientName(client_name) : undefined;
|
|
105
|
+
if (token_endpoint_auth_method !== undefined && token_endpoint_auth_method !== 'none') {
|
|
106
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_CLIENT_METADATA, 'only public clients are supported: token_endpoint_auth_method must be none');
|
|
107
|
+
}
|
|
108
|
+
if (grant_types !== undefined && !(isStringArray(grant_types) && grant_types.every((g) => GRANT_TYPES.has(g)))) {
|
|
109
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_CLIENT_METADATA, 'grant_types may include only authorization_code and refresh_token');
|
|
110
|
+
}
|
|
111
|
+
if (response_types !== undefined && !(isStringArray(response_types) && response_types.every((r) => RESPONSE_TYPES.has(r)))) {
|
|
112
|
+
return invalid(exports.REGISTRATION_ERRORS.INVALID_CLIENT_METADATA, 'response_types may include only code');
|
|
113
|
+
}
|
|
114
|
+
return { ok: true, clientName: shownName || undefined, redirectUris: redirect_uris };
|
|
115
|
+
}
|
|
116
|
+
/** A fixed-window count of registrations per address, in memory, per process. */
|
|
117
|
+
class RegistrationLimiter {
|
|
118
|
+
constructor(limit, windowMs) {
|
|
119
|
+
this.limit = limit;
|
|
120
|
+
this.windowMs = windowMs;
|
|
121
|
+
this.windows = new Map();
|
|
122
|
+
}
|
|
123
|
+
/** Count one registration from `address`; false when over the limit. */
|
|
124
|
+
allow(address, now = Date.now()) {
|
|
125
|
+
for (const [key, w] of this.windows)
|
|
126
|
+
if (now - w.start >= this.windowMs)
|
|
127
|
+
this.windows.delete(key);
|
|
128
|
+
const window = this.windows.get(address) ?? { start: now, count: 0 };
|
|
129
|
+
window.count += 1;
|
|
130
|
+
this.windows.set(address, window);
|
|
131
|
+
return window.count <= this.limit;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.RegistrationLimiter = RegistrationLimiter;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const INSERT_CLIENT = "\n INSERT INTO lt_oauth_clients (client_id, client_name, redirect_uris)\n VALUES ($1, $2, $3)\n RETURNING client_id, client_name, redirect_uris, created_at";
|
|
2
|
+
export declare const GET_CLIENT = "\n SELECT client_id, client_name, redirect_uris, created_at\n FROM lt_oauth_clients WHERE client_id = $1";
|
|
3
|
+
/** Create the grant and its authorization code together. */
|
|
4
|
+
export declare const ISSUE_CODE = "\n WITH g AS (\n INSERT INTO lt_oauth_grants (user_id, client_id, policy, scope)\n VALUES ($1, $2, $3, $4)\n RETURNING id\n )\n INSERT INTO lt_oauth_codes (code_hash, grant_id, redirect_uri, code_challenge, resource, expires_at)\n SELECT $5, g.id, $6, $7, $8, NOW() + make_interval(secs => $9) FROM g\n RETURNING grant_id";
|
|
5
|
+
/**
|
|
6
|
+
* Consume a code and issue the first refresh token. The code must be unused,
|
|
7
|
+
* unexpired, for this client and redirect URI, and match the PKCE challenge;
|
|
8
|
+
* the grant must be live and its owner active.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EXCHANGE_CODE = "\n WITH c AS (\n UPDATE lt_oauth_codes c SET used_at = NOW()\n FROM lt_oauth_grants g\n WHERE c.code_hash = $1 AND c.used_at IS NULL AND c.expires_at > NOW()\n AND c.redirect_uri = $3 AND c.code_challenge = $4\n AND g.id = c.grant_id AND g.client_id = $2 AND g.revoked_at IS NULL\n RETURNING c.grant_id, c.resource\n ),\n g AS (\n SELECT g.* FROM lt_oauth_grants g\n JOIN c ON c.grant_id = g.id\n JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'\n ),\n rt AS (\n INSERT INTO lt_oauth_refresh_tokens (token_hash, grant_id, expires_at)\n SELECT $5, g.id, NOW() + make_interval(secs => $6) FROM g\n RETURNING grant_id\n )\n SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, c.resource, \n COALESCE((\n SELECT json_agg(json_build_object(\n 'role', r.role, 'type', r.type, 'read_scope', r.read_scope, 'write_scope', r.write_scope\n ) ORDER BY r.role)\n FROM lt_user_roles r WHERE r.user_id = g.user_id\n ), '[]'::json) AS roles\n FROM g JOIN rt ON rt.grant_id = g.id JOIN c ON c.grant_id = g.id";
|
|
11
|
+
/**
|
|
12
|
+
* The grant an access token names, as it stands now: only while the grant is
|
|
13
|
+
* unrevoked and its owner active, with the owner's current memberships. One
|
|
14
|
+
* primary-key lookup per /mcp request, so a revocation, a deactivation or a
|
|
15
|
+
* role change takes effect on the next request in every process.
|
|
16
|
+
*/
|
|
17
|
+
export declare const GET_LIVE_GRANT = "\n SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, \n COALESCE((\n SELECT json_agg(json_build_object(\n 'role', r.role, 'type', r.type, 'read_scope', r.read_scope, 'write_scope', r.write_scope\n ) ORDER BY r.role)\n FROM lt_user_roles r WHERE r.user_id = g.user_id\n ), '[]'::json) AS roles\n FROM lt_oauth_grants g\n JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'\n WHERE g.id = $1 AND g.user_id = $2 AND g.revoked_at IS NULL";
|
|
18
|
+
/**
|
|
19
|
+
* Rotate a refresh token: mark the old one used and issue its successor, only
|
|
20
|
+
* for the client that holds it and while the grant is live and its owner
|
|
21
|
+
* active. Returns current roles.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ROTATE_REFRESH_TOKEN = "\n WITH old AS (\n UPDATE lt_oauth_refresh_tokens t SET used_at = NOW()\n FROM lt_oauth_grants og\n WHERE t.token_hash = $1 AND t.used_at IS NULL AND t.expires_at > NOW()\n AND og.id = t.grant_id AND og.client_id = $4\n RETURNING t.grant_id\n ),\n g AS (\n SELECT g.* FROM lt_oauth_grants g\n JOIN old ON old.grant_id = g.id\n JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'\n WHERE g.revoked_at IS NULL\n ),\n rt AS (\n INSERT INTO lt_oauth_refresh_tokens (token_hash, grant_id, expires_at)\n SELECT $2, g.id, NOW() + make_interval(secs => $3) FROM g\n RETURNING grant_id\n )\n SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, \n COALESCE((\n SELECT json_agg(json_build_object(\n 'role', r.role, 'type', r.type, 'read_scope', r.read_scope, 'write_scope', r.write_scope\n ) ORDER BY r.role)\n FROM lt_user_roles r WHERE r.user_id = g.user_id\n ), '[]'::json) AS roles\n FROM g JOIN rt ON rt.grant_id = g.id";
|
|
24
|
+
/**
|
|
25
|
+
* Revoke the grant of a refresh token presented again after it was used,
|
|
26
|
+
* outside the retry grace window: the token has leaked.
|
|
27
|
+
*/
|
|
28
|
+
export declare const REVOKE_ON_REFRESH_REUSE = "\n UPDATE lt_oauth_grants g SET revoked_at = NOW()\n FROM lt_oauth_refresh_tokens t\n WHERE t.token_hash = $1 AND t.used_at IS NOT NULL\n AND t.used_at < NOW() - make_interval(secs => $2)\n AND g.id = t.grant_id AND g.revoked_at IS NULL\n RETURNING g.id AS grant_id, g.user_id";
|
|
29
|
+
/** Revoke the grant a refresh token belongs to, for the client presenting it. */
|
|
30
|
+
export declare const REVOKE_BY_REFRESH_TOKEN = "\n UPDATE lt_oauth_grants g SET revoked_at = NOW()\n FROM lt_oauth_refresh_tokens t\n WHERE t.token_hash = $1 AND g.id = t.grant_id AND g.client_id = $2 AND g.revoked_at IS NULL\n RETURNING g.id AS grant_id, g.user_id";
|
|
31
|
+
/** Revoke a grant by id, optionally only when it belongs to the given user. */
|
|
32
|
+
export declare const REVOKE_GRANT = "\n UPDATE lt_oauth_grants SET revoked_at = NOW()\n WHERE id = $1 AND ($2::uuid IS NULL OR user_id = $2) AND revoked_at IS NULL\n RETURNING id AS grant_id, user_id";
|
|
33
|
+
/** A person's live grants that a client has put to use, newest first. */
|
|
34
|
+
export declare const LIST_GRANTS = "\n SELECT g.id AS grant_id, g.client_id, c.client_name, g.policy, g.scope, g.created_at,\n (SELECT MAX(t.created_at) FROM lt_oauth_refresh_tokens t WHERE t.grant_id = g.id) AS last_used_at\n FROM lt_oauth_grants g\n JOIN lt_oauth_clients c ON c.client_id = g.client_id\n WHERE g.user_id = $1 AND g.revoked_at IS NULL\n AND EXISTS (SELECT 1 FROM lt_oauth_refresh_tokens t WHERE t.grant_id = g.id)\n ORDER BY g.created_at DESC";
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ── OAuth authorization server queries ─────────────────────────────────────
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.LIST_GRANTS = exports.REVOKE_GRANT = exports.REVOKE_BY_REFRESH_TOKEN = exports.REVOKE_ON_REFRESH_REUSE = exports.ROTATE_REFRESH_TOKEN = exports.GET_LIVE_GRANT = exports.EXCHANGE_CODE = exports.ISSUE_CODE = exports.GET_CLIENT = exports.INSERT_CLIENT = void 0;
|
|
5
|
+
/** The grant owner's current memberships, as a JSON array. Expects alias `g`. */
|
|
6
|
+
const GRANT_ROLES = `
|
|
7
|
+
COALESCE((
|
|
8
|
+
SELECT json_agg(json_build_object(
|
|
9
|
+
'role', r.role, 'type', r.type, 'read_scope', r.read_scope, 'write_scope', r.write_scope
|
|
10
|
+
) ORDER BY r.role)
|
|
11
|
+
FROM lt_user_roles r WHERE r.user_id = g.user_id
|
|
12
|
+
), '[]'::json)`;
|
|
13
|
+
exports.INSERT_CLIENT = `
|
|
14
|
+
INSERT INTO lt_oauth_clients (client_id, client_name, redirect_uris)
|
|
15
|
+
VALUES ($1, $2, $3)
|
|
16
|
+
RETURNING client_id, client_name, redirect_uris, created_at`;
|
|
17
|
+
exports.GET_CLIENT = `
|
|
18
|
+
SELECT client_id, client_name, redirect_uris, created_at
|
|
19
|
+
FROM lt_oauth_clients WHERE client_id = $1`;
|
|
20
|
+
/** Create the grant and its authorization code together. */
|
|
21
|
+
exports.ISSUE_CODE = `
|
|
22
|
+
WITH g AS (
|
|
23
|
+
INSERT INTO lt_oauth_grants (user_id, client_id, policy, scope)
|
|
24
|
+
VALUES ($1, $2, $3, $4)
|
|
25
|
+
RETURNING id
|
|
26
|
+
)
|
|
27
|
+
INSERT INTO lt_oauth_codes (code_hash, grant_id, redirect_uri, code_challenge, resource, expires_at)
|
|
28
|
+
SELECT $5, g.id, $6, $7, $8, NOW() + make_interval(secs => $9) FROM g
|
|
29
|
+
RETURNING grant_id`;
|
|
30
|
+
/**
|
|
31
|
+
* Consume a code and issue the first refresh token. The code must be unused,
|
|
32
|
+
* unexpired, for this client and redirect URI, and match the PKCE challenge;
|
|
33
|
+
* the grant must be live and its owner active.
|
|
34
|
+
*/
|
|
35
|
+
exports.EXCHANGE_CODE = `
|
|
36
|
+
WITH c AS (
|
|
37
|
+
UPDATE lt_oauth_codes c SET used_at = NOW()
|
|
38
|
+
FROM lt_oauth_grants g
|
|
39
|
+
WHERE c.code_hash = $1 AND c.used_at IS NULL AND c.expires_at > NOW()
|
|
40
|
+
AND c.redirect_uri = $3 AND c.code_challenge = $4
|
|
41
|
+
AND g.id = c.grant_id AND g.client_id = $2 AND g.revoked_at IS NULL
|
|
42
|
+
RETURNING c.grant_id, c.resource
|
|
43
|
+
),
|
|
44
|
+
g AS (
|
|
45
|
+
SELECT g.* FROM lt_oauth_grants g
|
|
46
|
+
JOIN c ON c.grant_id = g.id
|
|
47
|
+
JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'
|
|
48
|
+
),
|
|
49
|
+
rt AS (
|
|
50
|
+
INSERT INTO lt_oauth_refresh_tokens (token_hash, grant_id, expires_at)
|
|
51
|
+
SELECT $5, g.id, NOW() + make_interval(secs => $6) FROM g
|
|
52
|
+
RETURNING grant_id
|
|
53
|
+
)
|
|
54
|
+
SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, c.resource, ${GRANT_ROLES} AS roles
|
|
55
|
+
FROM g JOIN rt ON rt.grant_id = g.id JOIN c ON c.grant_id = g.id`;
|
|
56
|
+
/**
|
|
57
|
+
* The grant an access token names, as it stands now: only while the grant is
|
|
58
|
+
* unrevoked and its owner active, with the owner's current memberships. One
|
|
59
|
+
* primary-key lookup per /mcp request, so a revocation, a deactivation or a
|
|
60
|
+
* role change takes effect on the next request in every process.
|
|
61
|
+
*/
|
|
62
|
+
exports.GET_LIVE_GRANT = `
|
|
63
|
+
SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, ${GRANT_ROLES} AS roles
|
|
64
|
+
FROM lt_oauth_grants g
|
|
65
|
+
JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'
|
|
66
|
+
WHERE g.id = $1 AND g.user_id = $2 AND g.revoked_at IS NULL`;
|
|
67
|
+
/**
|
|
68
|
+
* Rotate a refresh token: mark the old one used and issue its successor, only
|
|
69
|
+
* for the client that holds it and while the grant is live and its owner
|
|
70
|
+
* active. Returns current roles.
|
|
71
|
+
*/
|
|
72
|
+
exports.ROTATE_REFRESH_TOKEN = `
|
|
73
|
+
WITH old AS (
|
|
74
|
+
UPDATE lt_oauth_refresh_tokens t SET used_at = NOW()
|
|
75
|
+
FROM lt_oauth_grants og
|
|
76
|
+
WHERE t.token_hash = $1 AND t.used_at IS NULL AND t.expires_at > NOW()
|
|
77
|
+
AND og.id = t.grant_id AND og.client_id = $4
|
|
78
|
+
RETURNING t.grant_id
|
|
79
|
+
),
|
|
80
|
+
g AS (
|
|
81
|
+
SELECT g.* FROM lt_oauth_grants g
|
|
82
|
+
JOIN old ON old.grant_id = g.id
|
|
83
|
+
JOIN lt_users u ON u.id = g.user_id AND u.status = 'active'
|
|
84
|
+
WHERE g.revoked_at IS NULL
|
|
85
|
+
),
|
|
86
|
+
rt AS (
|
|
87
|
+
INSERT INTO lt_oauth_refresh_tokens (token_hash, grant_id, expires_at)
|
|
88
|
+
SELECT $2, g.id, NOW() + make_interval(secs => $3) FROM g
|
|
89
|
+
RETURNING grant_id
|
|
90
|
+
)
|
|
91
|
+
SELECT g.id AS grant_id, g.user_id, g.client_id, g.policy, g.scope, ${GRANT_ROLES} AS roles
|
|
92
|
+
FROM g JOIN rt ON rt.grant_id = g.id`;
|
|
93
|
+
/**
|
|
94
|
+
* Revoke the grant of a refresh token presented again after it was used,
|
|
95
|
+
* outside the retry grace window: the token has leaked.
|
|
96
|
+
*/
|
|
97
|
+
exports.REVOKE_ON_REFRESH_REUSE = `
|
|
98
|
+
UPDATE lt_oauth_grants g SET revoked_at = NOW()
|
|
99
|
+
FROM lt_oauth_refresh_tokens t
|
|
100
|
+
WHERE t.token_hash = $1 AND t.used_at IS NOT NULL
|
|
101
|
+
AND t.used_at < NOW() - make_interval(secs => $2)
|
|
102
|
+
AND g.id = t.grant_id AND g.revoked_at IS NULL
|
|
103
|
+
RETURNING g.id AS grant_id, g.user_id`;
|
|
104
|
+
/** Revoke the grant a refresh token belongs to, for the client presenting it. */
|
|
105
|
+
exports.REVOKE_BY_REFRESH_TOKEN = `
|
|
106
|
+
UPDATE lt_oauth_grants g SET revoked_at = NOW()
|
|
107
|
+
FROM lt_oauth_refresh_tokens t
|
|
108
|
+
WHERE t.token_hash = $1 AND g.id = t.grant_id AND g.client_id = $2 AND g.revoked_at IS NULL
|
|
109
|
+
RETURNING g.id AS grant_id, g.user_id`;
|
|
110
|
+
/** Revoke a grant by id, optionally only when it belongs to the given user. */
|
|
111
|
+
exports.REVOKE_GRANT = `
|
|
112
|
+
UPDATE lt_oauth_grants SET revoked_at = NOW()
|
|
113
|
+
WHERE id = $1 AND ($2::uuid IS NULL OR user_id = $2) AND revoked_at IS NULL
|
|
114
|
+
RETURNING id AS grant_id, user_id`;
|
|
115
|
+
/** A person's live grants that a client has put to use, newest first. */
|
|
116
|
+
exports.LIST_GRANTS = `
|
|
117
|
+
SELECT g.id AS grant_id, g.client_id, c.client_name, g.policy, g.scope, g.created_at,
|
|
118
|
+
(SELECT MAX(t.created_at) FROM lt_oauth_refresh_tokens t WHERE t.grant_id = g.id) AS last_used_at
|
|
119
|
+
FROM lt_oauth_grants g
|
|
120
|
+
JOIN lt_oauth_clients c ON c.client_id = g.client_id
|
|
121
|
+
WHERE g.user_id = $1 AND g.revoked_at IS NULL
|
|
122
|
+
AND EXISTS (SELECT 1 FROM lt_oauth_refresh_tokens t WHERE t.grant_id = g.id)
|
|
123
|
+
ORDER BY g.created_at DESC`;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { LTGrantPolicy, LTGrantSnapshot, LTGrantSummary, LTOAuthClient } from '../../../types/oauth-server';
|
|
2
|
+
/** A refresh token reused within this many seconds is treated as a client retry. */
|
|
3
|
+
export declare const REFRESH_REUSE_GRACE_SECONDS = 10;
|
|
4
|
+
export interface RevokedGrant {
|
|
5
|
+
grant_id: string;
|
|
6
|
+
user_id: string;
|
|
7
|
+
}
|
|
8
|
+
/** A new random secret: 32 bytes, base64url. */
|
|
9
|
+
export declare function createSecret(): string;
|
|
10
|
+
/** SHA-256 of a secret. Codes and refresh tokens are stored only as hashes. */
|
|
11
|
+
export declare function hashSecret(secret: string): string;
|
|
12
|
+
/** The PKCE S256 challenge for a code verifier (RFC 7636). */
|
|
13
|
+
export declare function pkceChallenge(verifier: string): string;
|
|
14
|
+
export declare function registerClient(input: {
|
|
15
|
+
clientName?: string;
|
|
16
|
+
redirectUris: string[];
|
|
17
|
+
}): Promise<LTOAuthClient>;
|
|
18
|
+
export declare const isClientId: (value: string) => boolean;
|
|
19
|
+
export declare function getClient(clientId: string): Promise<LTOAuthClient | null>;
|
|
20
|
+
/** Record the person's consent as a grant and return a one-time code for it. */
|
|
21
|
+
export declare function issueAuthorizationCode(input: {
|
|
22
|
+
userId: string;
|
|
23
|
+
clientId: string;
|
|
24
|
+
policy: LTGrantPolicy;
|
|
25
|
+
scope: string;
|
|
26
|
+
redirectUri: string;
|
|
27
|
+
codeChallenge: string;
|
|
28
|
+
resource?: string;
|
|
29
|
+
ttlSeconds: number;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
code: string;
|
|
32
|
+
grantId: string;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Exchange a code for the grant and its first refresh token. Null when the
|
|
36
|
+
* code is unknown, used, expired, for another client or redirect URI, fails
|
|
37
|
+
* PKCE, or its grant or owner is no longer active.
|
|
38
|
+
*/
|
|
39
|
+
export declare function exchangeAuthorizationCode(input: {
|
|
40
|
+
code: string;
|
|
41
|
+
clientId: string;
|
|
42
|
+
redirectUri: string;
|
|
43
|
+
codeVerifier: string;
|
|
44
|
+
refreshTtlSeconds: number;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
snapshot: LTGrantSnapshot;
|
|
47
|
+
resource: string | null;
|
|
48
|
+
refreshToken: string;
|
|
49
|
+
} | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Rotate a refresh token for the client that holds it. Null when it is
|
|
52
|
+
* unknown, used, expired, another client's, or its grant or owner is no
|
|
53
|
+
* longer active. A used token presented again outside the
|
|
54
|
+
* grace window revokes its grant, and `revoked` reports it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function rotateRefreshToken(input: {
|
|
57
|
+
refreshToken: string;
|
|
58
|
+
clientId: string;
|
|
59
|
+
refreshTtlSeconds: number;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
snapshot: LTGrantSnapshot;
|
|
62
|
+
refreshToken: string;
|
|
63
|
+
} | {
|
|
64
|
+
snapshot: null;
|
|
65
|
+
revoked: RevokedGrant | null;
|
|
66
|
+
}>;
|
|
67
|
+
/** The live grant an access token names; null when it is revoked, its owner inactive, or it is another user's. */
|
|
68
|
+
export declare function getLiveGrant(grantId: string, userId: string): Promise<LTGrantSnapshot | null>;
|
|
69
|
+
/** Revoke the grant behind a refresh token presented by its own client (RFC 7009). */
|
|
70
|
+
export declare function revokeByRefreshToken(refreshToken: string, clientId: string): Promise<RevokedGrant | null>;
|
|
71
|
+
/** Revoke a grant; with `userId`, only when it belongs to that user. */
|
|
72
|
+
export declare function revokeGrant(grantId: string, userId?: string): Promise<RevokedGrant | null>;
|
|
73
|
+
/** The person's live grants that a client has put to use. */
|
|
74
|
+
export declare function listGrants(userId: string): Promise<LTGrantSummary[]>;
|