@redocly/reef 0.137.0-next.0 → 0.137.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/dist/api-schemas/otel-traces.d.ts +1359 -0
  3. package/dist/api-schemas/otel-traces.js +1 -0
  4. package/dist/cli/stats/collectors/asyncapi/index.d.ts +3 -0
  5. package/dist/cli/stats/collectors/asyncapi/index.js +1 -0
  6. package/dist/cli/stats/collectors/extension-sampling.d.ts +44 -0
  7. package/dist/cli/stats/collectors/extension-sampling.js +1 -0
  8. package/dist/cli/stats/collectors/openapi/index.js +1 -1
  9. package/dist/cli/stats/collectors/page-slugs/index.d.ts +9 -0
  10. package/dist/cli/stats/collectors/page-slugs/index.js +1 -0
  11. package/dist/cli/stats/collectors/prepare-stats-walk.d.ts +10 -0
  12. package/dist/cli/stats/collectors/prepare-stats-walk.js +1 -0
  13. package/dist/cli/stats/collectors/run-stats-collector.d.ts +24 -0
  14. package/dist/cli/stats/collectors/run-stats-collector.js +1 -0
  15. package/dist/cli/stats/index.js +1 -1
  16. package/dist/client/app/hooks/useMcpData.d.ts +1 -0
  17. package/dist/client/app/hooks/useMcpData.js +1 -1
  18. package/dist/client/app/markdoc/custom-components/openapi/json-schema.js +1 -1
  19. package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.js +1 -1
  20. package/dist/client/app/markdoc/custom-components/openapi/openapi-example.js +1 -1
  21. package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -1
  22. package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
  23. package/dist/client/app/markdoc/custom-components/openapi/use-markdown-adapter.d.ts +45 -0
  24. package/dist/client/app/markdoc/custom-components/openapi/use-markdown-adapter.js +1 -0
  25. package/dist/client/app/utils/loadAndNavigate.js +1 -1
  26. package/dist/client/providers/hooks.js +1 -1
  27. package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
  28. package/dist/client/templates/api-docs/helpers.d.ts +4 -1
  29. package/dist/client/templates/api-docs/helpers.js +5 -1
  30. package/dist/client/templates/api-docs/template.js +8 -3
  31. package/dist/client/utils/catalog/get-next-page-param.d.ts +1 -1
  32. package/dist/client/utils/catalog/get-next-page-param.js +1 -1
  33. package/dist/compiled/svgo/svgo-node.js +32 -32
  34. package/dist/constants/l10n/langs/ar.js +1 -1
  35. package/dist/constants/l10n/langs/de.js +1 -1
  36. package/dist/constants/l10n/langs/en.js +1 -1
  37. package/dist/constants/l10n/langs/es.js +1 -1
  38. package/dist/constants/l10n/langs/fr.js +1 -1
  39. package/dist/constants/l10n/langs/hi.js +1 -1
  40. package/dist/constants/l10n/langs/it.js +1 -1
  41. package/dist/constants/l10n/langs/ja.js +1 -1
  42. package/dist/constants/l10n/langs/ko.js +1 -1
  43. package/dist/constants/l10n/langs/pl.js +1 -1
  44. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  45. package/dist/constants/l10n/langs/pt.js +1 -1
  46. package/dist/constants/l10n/langs/ru.js +1 -1
  47. package/dist/constants/l10n/langs/uk.js +1 -1
  48. package/dist/constants/l10n/langs/zh.js +1 -1
  49. package/dist/server/config/env-config.d.ts +6 -0
  50. package/dist/server/config/env-schema.d.ts +15 -0
  51. package/dist/server/config/env-schemas/feature-flags.d.ts +9 -1
  52. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  53. package/dist/server/config/env-schemas/search.d.ts +3 -0
  54. package/dist/server/config/env-schemas/search.js +1 -1
  55. package/dist/server/constants/common.d.ts +1 -0
  56. package/dist/server/constants/common.js +1 -1
  57. package/dist/server/constants/mcp.d.ts +5 -0
  58. package/dist/server/constants/mcp.js +1 -0
  59. package/dist/server/constants/plugins/search.d.ts +0 -2
  60. package/dist/server/constants/plugins/search.js +1 -1
  61. package/dist/server/constants/rbac.d.ts +3 -0
  62. package/dist/server/constants/rbac.js +1 -0
  63. package/dist/server/esbuild/esbuild.js +3 -3
  64. package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -1
  65. package/dist/server/plugins/api-docs/options.js +1 -1
  66. package/dist/server/plugins/api-docs/search/create-indexer.d.ts +5 -0
  67. package/dist/server/plugins/api-docs/search/create-indexer.js +1 -0
  68. package/dist/server/plugins/api-docs/search/get-ai-search-documents.js +28 -28
  69. package/dist/server/plugins/api-docs/search/search-resolver.js +1 -1
  70. package/dist/server/plugins/{openapi-docs/is-openapi-doc.d.ts → api-docs/utils/is-api-doc.d.ts} +4 -2
  71. package/dist/server/plugins/api-docs/utils/is-api-doc.js +1 -0
  72. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.d.ts +1 -1
  73. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.js +1 -1
  74. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.d.ts +5 -0
  75. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
  76. package/dist/server/plugins/entitlements/index.js +1 -1
  77. package/dist/server/plugins/l10n/index.js +1 -1
  78. package/dist/server/plugins/lifecycle.js +2 -2
  79. package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
  80. package/dist/server/plugins/markdown/attribute-resolvers/resolve-open-api-ref.js +1 -1
  81. package/dist/server/plugins/markdown/html/html-jsx-attribute-mapping.js +1 -1
  82. package/dist/server/plugins/markdown/utils/sanitize-malformed-md-content.js +2 -2
  83. package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +1 -2
  84. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  85. package/dist/server/plugins/mcp/auth/token-audience-telemetry.d.ts +7 -0
  86. package/dist/server/plugins/mcp/auth/token-audience-telemetry.js +1 -0
  87. package/dist/server/plugins/mcp/auth/token-audience.d.ts +6 -0
  88. package/dist/server/plugins/mcp/auth/token-audience.js +1 -0
  89. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +4 -4
  90. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +3 -1
  91. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
  92. package/dist/server/plugins/mcp/codemode/invoke-tool.js +1 -1
  93. package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
  94. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.d.ts +1 -1
  95. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.js +9 -3
  96. package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +1 -1
  97. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +1 -1
  98. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
  99. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  100. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.d.ts +1 -0
  101. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  102. package/dist/server/plugins/mcp/codemode/types.d.ts +1 -0
  103. package/dist/server/plugins/mcp/constants.d.ts +1 -1
  104. package/dist/server/plugins/mcp/constants.js +1 -1
  105. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.d.ts +13 -0
  106. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.js +1 -0
  107. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.d.ts +6 -0
  108. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -0
  109. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.d.ts +3 -0
  110. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.js +1 -0
  111. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +2 -0
  112. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  113. package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +2 -2
  114. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoints.js +1 -1
  115. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
  116. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  117. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.d.ts +10 -0
  118. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.js +1 -0
  119. package/dist/server/plugins/mcp/gateway-mcp/credential-validation.d.ts +4 -0
  120. package/dist/server/plugins/mcp/gateway-mcp/credential-validation.js +1 -0
  121. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +15 -5
  122. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -3
  123. package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
  124. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.d.ts +2 -1
  125. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.js +1 -1
  126. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +10 -1
  127. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
  128. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.d.ts +7 -0
  129. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.js +1 -0
  130. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +2 -10
  131. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
  132. package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +16 -4
  133. package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -1
  134. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +26 -1
  135. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +2 -1
  136. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +12 -0
  137. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -1
  138. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  139. package/dist/server/plugins/mcp/handlers/errors.d.ts +7 -2
  140. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  141. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  142. package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -124
  143. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.d.ts +12 -0
  144. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +225 -0
  145. package/dist/server/plugins/mcp/index.d.ts +0 -2
  146. package/dist/server/plugins/mcp/index.js +1 -1
  147. package/dist/server/plugins/mcp/servers/docs-server.d.ts +2 -2
  148. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  149. package/dist/server/plugins/mcp/servers/mcp-server.d.ts +2 -11
  150. package/dist/server/plugins/mcp/servers/mcp-server.js +4 -2
  151. package/dist/server/plugins/mcp/types.d.ts +32 -5
  152. package/dist/server/plugins/mcp/utils/available-sandbox-tools.d.ts +4 -0
  153. package/dist/server/plugins/mcp/utils/available-sandbox-tools.js +1 -0
  154. package/dist/server/plugins/mcp/utils/find-gated-tool-names.d.ts +12 -0
  155. package/dist/server/plugins/mcp/utils/find-gated-tool-names.js +1 -0
  156. package/dist/server/plugins/mcp/utils/mcp-client.d.ts +13 -0
  157. package/dist/server/plugins/mcp/utils/mcp-client.js +1 -0
  158. package/dist/server/plugins/mcp/utils/tool-registration.d.ts +17 -0
  159. package/dist/server/plugins/mcp/utils/tool-registration.js +1 -0
  160. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +6 -1
  161. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  162. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.d.ts +5 -0
  163. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.js +1 -0
  164. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +6 -11
  165. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  166. package/dist/server/plugins/mcp/workers/tool-file-system.d.ts +6 -0
  167. package/dist/server/plugins/mcp/workers/tool-file-system.js +1 -0
  168. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.d.ts +4 -2
  169. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -3
  170. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  171. package/dist/server/plugins/search/engines/flexsearch/search-index.d.ts +8 -4
  172. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  173. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  174. package/dist/server/plugins/search/index.js +1 -1
  175. package/dist/server/plugins/search/llmstxt/build-page-llms-txt-md.d.ts +4 -0
  176. package/dist/server/plugins/search/llmstxt/build-page-llms-txt-md.js +3 -0
  177. package/dist/server/plugins/search/llmstxt/create-llms-txt-generator.d.ts +4 -0
  178. package/dist/server/plugins/search/llmstxt/create-llms-txt-generator.js +1 -0
  179. package/dist/server/plugins/search/llmstxt/get-llms-txt-exclude-matcher.d.ts +4 -0
  180. package/dist/server/plugins/search/llmstxt/get-llms-txt-exclude-matcher.js +1 -0
  181. package/dist/server/plugins/search/llmstxt/index.d.ts +2 -2
  182. package/dist/server/plugins/search/llmstxt/is-included-in-llms-txt.d.ts +6 -0
  183. package/dist/server/plugins/search/llmstxt/is-included-in-llms-txt.js +1 -0
  184. package/dist/server/plugins/search/utils.d.ts +2 -1
  185. package/dist/server/plugins/search/utils.js +2 -2
  186. package/dist/server/sandbox/constants/sandbox.d.ts +4 -1
  187. package/dist/server/sandbox/constants/sandbox.js +1 -1
  188. package/dist/server/sandbox/sandbox.js +2 -2
  189. package/dist/server/sandbox/utils/returns-from-top-level.d.ts +4 -0
  190. package/dist/server/sandbox/utils/returns-from-top-level.js +1 -0
  191. package/dist/server/store.d.ts +2 -0
  192. package/dist/server/store.js +1 -1
  193. package/dist/server/types/plugins/common.d.ts +5 -0
  194. package/dist/server/types/plugins/search.d.ts +7 -2
  195. package/dist/server/types/web-server.d.ts +8 -0
  196. package/dist/server/utils/envs/get-api-route-allowed-env-variables.js +1 -1
  197. package/dist/server/utils/get-route-ai-documents-store.d.ts +5 -0
  198. package/dist/server/utils/get-route-ai-documents-store.js +1 -0
  199. package/dist/server/utils/get-route-static-data.d.ts +4 -0
  200. package/dist/server/utils/get-route-static-data.js +1 -0
  201. package/dist/server/utils/llmstxt/agent-feedback-llms-footer.js +1 -1
  202. package/dist/server/utils/llmstxt/resolve-llms-txt-md.d.ts +10 -0
  203. package/dist/server/utils/llmstxt/resolve-llms-txt-md.js +1 -0
  204. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.d.ts +3 -0
  205. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.js +1 -0
  206. package/dist/server/utils/rbac/should-handle-mcp-auth.d.ts +2 -0
  207. package/dist/server/utils/rbac/should-handle-mcp-auth.js +1 -0
  208. package/dist/server/utils/rbac.js +1 -1
  209. package/dist/server/utils/search/highlight-text-for-search.js +1 -1
  210. package/dist/server/web-server/auth.d.ts +13 -2
  211. package/dist/server/web-server/auth.js +3 -3
  212. package/dist/server/web-server/dev-server.js +1 -1
  213. package/dist/server/web-server/handle-api-route-request.js +1 -1
  214. package/dist/server/web-server/middleware/ensureSearchData.js +1 -1
  215. package/dist/server/web-server/routes/ask-ai.d.ts +1 -0
  216. package/dist/server/web-server/routes/ask-ai.js +1 -1
  217. package/dist/server/web-server/routes/auth.js +1 -1
  218. package/dist/server/web-server/routes/dynamic-route.d.ts +2 -1
  219. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  220. package/dist/server/web-server/routes/error.js +1 -1
  221. package/dist/server/web-server/routes/helpers/resolve-ui-locales-for-idp-login.js +1 -1
  222. package/dist/server/web-server/routes/index.d.ts +2 -1
  223. package/dist/server/web-server/routes/index.js +1 -1
  224. package/dist/server/web-server/routes/llms-txt.d.ts +4 -0
  225. package/dist/server/web-server/routes/llms-txt.js +1 -0
  226. package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
  227. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  228. package/dist/server/web-server/routes/otel/otel.js +1 -1
  229. package/dist/server/web-server/routes/page-data.js +1 -1
  230. package/dist/server/web-server/routes/resolve-route.js +1 -1
  231. package/dist/server/web-server/utils/get-request-origin.d.ts +2 -0
  232. package/dist/server/web-server/utils/get-request-origin.js +1 -1
  233. package/dist/server/web-server/utils/prepare-list-response.d.ts +2 -4
  234. package/dist/server/web-server/utils/prepare-list-response.js +1 -1
  235. package/dist/server/web-server/utils.d.ts +1 -1
  236. package/dist/server/web-server/utils.js +1 -1
  237. package/dist/server/workers/mcp-tool-worker-pool.d.ts +1 -0
  238. package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
  239. package/dist/server/workers/mcp-tool-worker.js +1 -1
  240. package/dist/server/workers/types.d.ts +9 -2
  241. package/dist/server/workers/worker-pool.d.ts +1 -0
  242. package/dist/server/workers/worker-pool.js +1 -1
  243. package/dist/types/global-data.d.ts +1 -0
  244. package/dist/utils/guards/is-plain-object.d.ts +19 -0
  245. package/dist/utils/guards/is-plain-object.js +1 -0
  246. package/package.json +12 -15
  247. package/dist/client/templates/asyncapi-docs/helpers.d.ts +0 -12
  248. package/dist/client/templates/asyncapi-docs/helpers.js +0 -1
  249. package/dist/client/templates/asyncapi-docs/template.d.ts +0 -15
  250. package/dist/client/templates/asyncapi-docs/template.js +0 -9
  251. package/dist/client/templates/openapi-docs/helpers.d.ts +0 -18
  252. package/dist/client/templates/openapi-docs/helpers.js +0 -5
  253. package/dist/client/templates/openapi-docs/template.d.ts +0 -6
  254. package/dist/client/templates/openapi-docs/template.js +0 -14
  255. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.d.ts +0 -9
  256. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.js +0 -1
  257. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.d.ts +0 -2
  258. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.js +0 -1
  259. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.d.ts +0 -6
  260. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.js +0 -1
  261. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.d.ts +0 -8
  262. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.js +0 -1
  263. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.d.ts +0 -2
  264. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.js +0 -1
  265. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.d.ts +0 -5
  266. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.js +0 -1
  267. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.d.ts +0 -6
  268. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.js +0 -1
  269. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.d.ts +0 -3
  270. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.js +0 -1
  271. package/dist/server/plugins/api-docs/search/search-indexer.d.ts +0 -9
  272. package/dist/server/plugins/api-docs/search/search-indexer.js +0 -1
  273. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.d.ts +0 -18
  274. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.js +0 -5
  275. package/dist/server/plugins/asyncapi-docs/get-server-props.d.ts +0 -4
  276. package/dist/server/plugins/asyncapi-docs/get-server-props.js +0 -1
  277. package/dist/server/plugins/asyncapi-docs/get-template-path.d.ts +0 -2
  278. package/dist/server/plugins/asyncapi-docs/get-template-path.js +0 -1
  279. package/dist/server/plugins/asyncapi-docs/index.d.ts +0 -3
  280. package/dist/server/plugins/asyncapi-docs/index.js +0 -1
  281. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.d.ts +0 -3
  282. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.js +0 -1
  283. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.d.ts +0 -9
  284. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.js +0 -56
  285. package/dist/server/plugins/asyncapi-docs/search/schema-processor.d.ts +0 -8
  286. package/dist/server/plugins/asyncapi-docs/search/schema-processor.js +0 -1
  287. package/dist/server/plugins/asyncapi-docs/search/search-facets.d.ts +0 -8
  288. package/dist/server/plugins/asyncapi-docs/search/search-facets.js +0 -1
  289. package/dist/server/plugins/asyncapi-docs/search/search-resolver.d.ts +0 -5
  290. package/dist/server/plugins/asyncapi-docs/search/search-resolver.js +0 -1
  291. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.d.ts +0 -4
  292. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.js +0 -1
  293. package/dist/server/plugins/graphql-docs/constants.d.ts +0 -2
  294. package/dist/server/plugins/graphql-docs/constants.js +0 -1
  295. package/dist/server/plugins/graphql-docs/get-template-path.d.ts +0 -2
  296. package/dist/server/plugins/graphql-docs/get-template-path.js +0 -1
  297. package/dist/server/plugins/graphql-docs/graphql-doc-loader.d.ts +0 -17
  298. package/dist/server/plugins/graphql-docs/graphql-doc-loader.js +0 -1
  299. package/dist/server/plugins/graphql-docs/index.d.ts +0 -4
  300. package/dist/server/plugins/graphql-docs/index.js +0 -1
  301. package/dist/server/plugins/graphql-docs/is-graphql-doc.d.ts +0 -2
  302. package/dist/server/plugins/graphql-docs/is-graphql-doc.js +0 -1
  303. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.d.ts +0 -17
  304. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.js +0 -4
  305. package/dist/server/plugins/graphql-docs/search/ai/utils.d.ts +0 -14
  306. package/dist/server/plugins/graphql-docs/search/ai/utils.js +0 -36
  307. package/dist/server/plugins/graphql-docs/search/search-facets.d.ts +0 -8
  308. package/dist/server/plugins/graphql-docs/search/search-facets.js +0 -1
  309. package/dist/server/plugins/graphql-docs/search/search-resolver.d.ts +0 -5
  310. package/dist/server/plugins/graphql-docs/search/search-resolver.js +0 -1
  311. package/dist/server/plugins/graphql-docs/spec-download.api.d.ts +0 -3
  312. package/dist/server/plugins/graphql-docs/spec-download.api.js +0 -1
  313. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.d.ts +0 -5
  314. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +0 -4
  315. package/dist/server/plugins/graphql-docs/types.d.ts +0 -40
  316. package/dist/server/plugins/graphql-docs/types.js +0 -0
  317. package/dist/server/plugins/openapi-docs/ai-search-indexer.d.ts +0 -14
  318. package/dist/server/plugins/openapi-docs/ai-search-indexer.js +0 -1
  319. package/dist/server/plugins/openapi-docs/decorators.d.ts +0 -25
  320. package/dist/server/plugins/openapi-docs/decorators.js +0 -1
  321. package/dist/server/plugins/openapi-docs/format-bundle-error.d.ts +0 -6
  322. package/dist/server/plugins/openapi-docs/format-bundle-error.js +0 -5
  323. package/dist/server/plugins/openapi-docs/get-server-props.d.ts +0 -4
  324. package/dist/server/plugins/openapi-docs/get-server-props.js +0 -1
  325. package/dist/server/plugins/openapi-docs/get-template-path.d.ts +0 -2
  326. package/dist/server/plugins/openapi-docs/get-template-path.js +0 -1
  327. package/dist/server/plugins/openapi-docs/index.d.ts +0 -3
  328. package/dist/server/plugins/openapi-docs/index.js +0 -1
  329. package/dist/server/plugins/openapi-docs/is-openapi-doc.js +0 -1
  330. package/dist/server/plugins/openapi-docs/load-definition.d.ts +0 -31
  331. package/dist/server/plugins/openapi-docs/load-definition.js +0 -3
  332. package/dist/server/plugins/openapi-docs/openapi-search-builder.d.ts +0 -24
  333. package/dist/server/plugins/openapi-docs/openapi-search-builder.js +0 -1
  334. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.d.ts +0 -18
  335. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +0 -94
  336. package/dist/server/plugins/openapi-docs/search/search-facets.d.ts +0 -11
  337. package/dist/server/plugins/openapi-docs/search/search-facets.js +0 -1
  338. package/dist/server/plugins/openapi-docs/search/search-resolver.d.ts +0 -5
  339. package/dist/server/plugins/openapi-docs/search/search-resolver.js +0 -1
  340. package/dist/server/plugins/openapi-docs/search-indexer.d.ts +0 -17
  341. package/dist/server/plugins/openapi-docs/search-indexer.js +0 -1
  342. package/dist/server/plugins/openapi-docs/spec-download.api.d.ts +0 -4
  343. package/dist/server/plugins/openapi-docs/spec-download.api.js +0 -1
  344. package/dist/server/plugins/openapi-docs/store-definition-bundles.d.ts +0 -4
  345. package/dist/server/plugins/openapi-docs/store-definition-bundles.js +0 -1
  346. package/dist/server/plugins/openapi-docs/types.d.ts +0 -17
  347. package/dist/server/plugins/openapi-docs/types.js +0 -0
  348. package/dist/server/plugins/openapi-docs/utils.d.ts +0 -25
  349. package/dist/server/plugins/openapi-docs/utils.js +0 -1
  350. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.d.ts +0 -0
  351. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.js +0 -0
  352. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.d.ts +0 -0
  353. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.js +0 -0
  354. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.d.ts +0 -0
  355. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.js +0 -0
@@ -1 +1 @@
1
- import C from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as O}from"./constants/common.js";import{isObject as M}from"../utils/guards/is-object.js";import{mapObject as k}from"../utils/object/map-object.js";import{getValueDeep as D}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as y}from"../utils/path/is-local-link.js";import{reporter as S}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as H}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as B}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{SandboxContext as G}from"./utils/sandbox-context.js";import{writeSharedData as I}from"./utils/index.js";import{renderComponents as N}from"./ssr/render.js";import{readStaticData as V,writeStaticData as q}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as U}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as w}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as x}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as W}from"./utils/redirects/find-redirect.js";import{followRedirectChain as $}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as z}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Y}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},E="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Me="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#o=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#u=Promise.resolve();#h;#e=!1;#r=0;#f=0;#a=new Map;constructor({outdir:e,contentDir:t,serverMode:s=!1,serverOutDir:a}){this.#i=t,this.outdir=e,this.serverMode=s,this.serverOutDir=a,G.register({serverOutDir:a,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(r=>{this.#n=r})}on(e,t){const s=this.listeners.get(e);s?s.add(t):this.listeners.set(e,new Set([t]))}queueEvent=(e,t,...s)=>{this.#a.set(e+String(t),[e,t,...s])};runListeners=(e,t,...s)=>{for(const a of this.listeners.get(e)||new Set)t?a(t,...s):a(...s)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#a.values())this.runListeners(...e);this.#a.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#h=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#h?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await Y("com.redocly.build.reloadMarkdocOptions",async()=>{const e=w.instance(),t=await U(this.serverOutDir),s=Object.fromEntries(Object.entries(t.tags).filter(([a])=>R[a]!=null?e.canAccessFeature(R[a]):!0));this.#o={...t,tags:s}})}get markdocOptions(){return{...this.#o,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const t=this.globalData,s={...this.globalData,...e};this.globalData=s,JSON.stringify(s)!==JSON.stringify(t)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:t,deps:s,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(e,this.markdocOptions,{actions:this,context:t},a);for(const i of r.sharedDataDeps||[]){for(const n of s?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of s?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of s?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of s?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(s?.routeSlugs&&r.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const t=Object.keys(e);for(const o of t)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=D(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:s,unsetEnvVars:a,replacedValues:r}=J(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,t,s={})=>{if(!w.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=t;const{trackOriginalSource:l=!0}=s,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&z(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const t=h(e).toLowerCase(),s=W(t,this.config.redirects,this.config.wildcardRedirectsTree);if(!s)return null;if(y(s.to)){const a=h(s.to).toLowerCase();if(!a.endsWith("*")&&$(a,[t],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:s.to,type:s.type}};createSharedData=async(e,t,s)=>{if(s&&this.#t[e]===s)return e;const a=JSON.stringify(t),r=s??H(a);return this.#t[e]===r||(this.#t[e]=r,await I(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,t,s)=>{const a=L(e),r=this.routesSharedData.get(a)||{};r[t]=s,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${e}, ${t}, ${s}`)};getRouteSharedDataByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.routesSharedData.get(t)||{}:{}};getPartialsForRoute=e=>{const t=this.getGlobalConfig(m)||{},s=this.routesPartials.get(e);if(!s||s.length===0)return{};const a=this.getGlobalConfig(O)||{},r=new Set(s),o=Array.from(s);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)t[i]&&(l[i]=t[i]);return l};addRoute=e=>{const s={...x(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,t,s)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t)this.mcpToolHandlers.set(s.name,{...s,importPath:e}),u.verbose("Created MCP tool %s",s.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addSkills=e=>{for(const t of e)this.skills.set(t.slug,t),u.verbose("Discovered skill %s",t.slug)};getSkills=()=>Array.from(this.skills.values());addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,t)=>{this.config.responseHeaders||(this.config.responseHeaders={});const s=new Set(t.map(o=>o.name.toLowerCase())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!s.has(o.name.toLowerCase())),...t];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,a=this.getRedirect(e);return s&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!y(t.to))return!0;const s=h(t.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=e=>this.newRoutes.filter(t=>t.templateId===e);getAllRoutesForLocale=(e=g)=>{const t=Array.from(this.routesBySlug.values()),s=e.toLowerCase();return t.filter(a=>e===g?!K(a.fsPath):a.slug.startsWith(`/${s}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,t)=>(this.templates.set(e,t),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,t)=>(this.apiRoutesRequestHandlers.set(e,t),e);clearRequestHandlersByPrefix=e=>{for(const t of this.apiRoutesRequestHandlers.keys())t.startsWith(e)&&this.apiRoutesRequestHandlers.delete(t)};registerServerPropsGetter=(e,t)=>(this.serverPropsGetters.set(e,t),e);registerPagePropsGetter=(e,t)=>{this.pagePropsGetters.set(e,t)};async writeRouteStaticData(e,t){const s=await this.resolveRouteStaticData(e,t,!1);s&&q(e.slug,s,this.outdir)}async resolveRouteStaticData(e,t,s){if(this.serverMode)return V(e.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:s||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,t){if(!e?.length)return;const s=typeof e[0]=="string"?e.join(""):N(e);s&&(t==="head"?this.ssr.headTags.push(s):t==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[s,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[s].entries());e.push([s,r]);break;case"object":s==="config"&&e.push([s,await this.getConfigWithEnvPlaceholders()]),e.push([s,this[s]]);break;default:throw new Error("Invalid format")}const t=Object.fromEntries(e);return t[E]=_.PLAN_GATES,t}static fromJson(e,t){const s=new P(t);for(const[r,o]of Object.entries(v))switch(o){case"map":s[r]=new Map(e[r]);break;case"object":if(r==="config"){s.setGlobalConfig(e[r]);break}s[r]=e[r];break;default:throw new Error("Invalid format")}s.config[m]=Q(s.config[m]||{});const a=e[E];return a&&B("PLAN_GATES",a),s}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],a=t.split(":"),r=a.pop(),{error:o,value:l}=D(e,a);if(o||!M(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}l[r]=s}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(s=>!Z.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await S.panicOnBuildContentError(t)}}function Q(b){return k(b,e=>C.Ast.fromJSON(JSON.stringify(e)))}export{P as Store,Me as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
1
+ import C from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as M}from"./constants/common.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as k}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as D}from"../utils/path/is-local-link.js";import{reporter as S}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as H}from"./utils/crypto/sha1.js";import{envConfig as G,setEnv as _}from"./config/env-config.js";import{KvService as B}from"./persistence/kv/services/kv-service.js";import{SandboxContext as F}from"./utils/sandbox-context.js";import{writeSharedData as I}from"./utils/index.js";import{renderComponents as N}from"./ssr/render.js";import{readStaticData as V,writeStaticData as q}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as U}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as w}from"./entitlements/entitlements-provider.js";import{isL10nPath as x}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as W}from"./utils/redirects/find-redirect.js";import{followRedirectChain as $}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as z}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Y}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},E="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Oe="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#o=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#u=Promise.resolve();#h;#e=!1;#r=0;#f=0;#a=new Map;constructor({outdir:e,contentDir:t,serverMode:s=!1,serverOutDir:r}){this.#i=t,this.outdir=e,this.serverMode=s,this.serverOutDir=r,F.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}on(e,t){const s=this.listeners.get(e);s?s.add(t):this.listeners.set(e,new Set([t]))}queueEvent=(e,t,...s)=>{this.#a.set(e+String(t),[e,t,...s])};runListeners=(e,t,...s)=>{for(const r of this.listeners.get(e)||new Set)t?r(t,...s):r(...s)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#a.values())this.runListeners(...e);this.#a.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#h=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#h?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await Y("com.redocly.build.reloadMarkdocOptions",async()=>{const e=w.instance(),t=await U(this.serverOutDir),s=Object.fromEntries(Object.entries(t.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!0));this.#o={...t,tags:s}})}get markdocOptions(){return{...this.#o,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const t=this.globalData,s={...this.globalData,...e};this.globalData=s,JSON.stringify(s)!==JSON.stringify(t)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>B.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:t,deps:s,resource:r})=>{const{data:{info:a,ast:o},compoundHash:l}=await j(e,this.markdocOptions,{actions:this,context:t},r);for(const i of a.sharedDataDeps||[]){for(const n of s?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of s?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of a.dynamicMarkdocComponents||[]){for(const n of s?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of s?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(s?.routeSlugs&&a.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:a,ast:o,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const t=Object.keys(e);for(const o of t)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:s,unsetEnvVars:r,replacedValues:a}=J(e);for(const o of r)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,a),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,t,s={})=>{if(!w.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=t;const{trackOriginalSource:l=!0}=s,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&z(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const t=h(e).toLowerCase(),s=W(t,this.config.redirects,this.config.wildcardRedirectsTree);if(!s)return null;if(D(s.to)){const r=h(s.to).toLowerCase();if(!r.endsWith("*")&&$(r,[t],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:s.to,type:s.type}};createSharedData=async(e,t,s)=>{if(s&&this.#t[e]===s)return e;const r=JSON.stringify(t),a=s??H(r);return this.#t[e]===a||(this.#t[e]=a,await I(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,t,s)=>{const r=L(e),a=this.routesSharedData.get(r)||{};a[t]=s,this.routesSharedData.set(r,a),u.verbose(`Adding shared data to ${e}, ${t}, ${s}`)};getRouteSharedDataByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.routesSharedData.get(t)||{}:{}};getPartialsForRoute=e=>{const t=this.getGlobalConfig(m)||{},s=this.routesPartials.get(e);if(!s||s.length===0)return{};const r=this.getGlobalConfig(M)||{},a=new Set(s),o=Array.from(s);for(let i=0;i<o.length;i++){const n=o[i],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),o.push(d))}const l={};for(const i of a)t[i]&&(l[i]=t[i]);return l};addRoute=e=>{const s={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,t,s)=>{const r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const o=A(e,g,a.code,r);this.addRouteSharedData(o,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t){const r=this.mcpToolHandlers.get(s.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',s.name,e,r.importPath),this.mcpToolHandlers.set(s.name,{...s,importPath:e}),u.verbose("Created MCP tool %s",s.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const t of e){const s=this.mcpToolHandlers.get(t);s&&this.mcpToolHandlers.set(t,{...s,hasAvailabilityGate:!0})}};addSkills=e=>{for(const t of e)this.skills.set(t.slug,t),u.verbose("Discovered skill %s",t.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const t of e)this.mcpToolHandlers.delete(t)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,t)=>{this.config.responseHeaders||(this.config.responseHeaders={});const s=new Set(t.map(o=>o.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(o=>!s.has(o.name.toLowerCase())),...t];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,r=this.getRedirect(e);return s&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!D(t.to))return!0;const s=h(t.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=e=>this.newRoutes.filter(t=>t.templateId===e);getAllRoutesForLocale=(e=g)=>{const t=Array.from(this.routesBySlug.values()),s=e.toLowerCase();return t.filter(r=>e===g?!x(r.fsPath):r.slug.startsWith(`/${s}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,t)=>(this.templates.set(e,t),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,t)=>(this.apiRoutesRequestHandlers.set(e,t),e);clearRequestHandlersByPrefix=e=>{for(const t of this.apiRoutesRequestHandlers.keys())t.startsWith(e)&&this.apiRoutesRequestHandlers.delete(t)};registerServerPropsGetter=(e,t)=>(this.serverPropsGetters.set(e,t),e);registerPagePropsGetter=(e,t)=>{this.pagePropsGetters.set(e,t)};async writeRouteStaticData(e,t){const s=await this.resolveRouteStaticData(e,t,!1);s&&q(e.slug,s,this.outdir)}async resolveRouteStaticData(e,t,s){if(this.serverMode)return V(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},a=await e.getStaticData?.(e,r)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(o),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:T,...i,...a.props?.seo},compilationErrors:this.compilationErrors},lastModified:s||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,t){if(!e?.length)return;const s=typeof e[0]=="string"?e.join(""):N(e);s&&(t==="head"?this.ssr.headTags.push(s):t==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[s,r]of Object.entries(v))switch(r){case"map":const a=Array.from(this[s].entries());e.push([s,a]);break;case"object":if(s==="config"){e.push([s,await this.getConfigWithEnvPlaceholders()]);break}e.push([s,this[s]]);break;default:throw new Error("Invalid format")}const t=Object.fromEntries(e);return t[E]=G.PLAN_GATES,t}static fromJson(e,t){const s=new P(t);for(const[a,o]of Object.entries(v))switch(o){case"map":s[a]=new Map(e[a]);break;case"object":if(a==="config"){s.setGlobalConfig(e[a]);break}s[a]=e[a];break;default:throw new Error("Invalid format")}s.config[m]=Q(s.config[m]||{});const r=e[E];return r&&_("PLAN_GATES",r),s}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],r=t.split(":"),a=r.pop(),{error:o,value:l}=y(e,r);if(o||!O(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}l[a]=s}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(s=>!Z.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await S.panicOnBuildContentError(t)}}function Q(b){return k(b,e=>C.Ast.fromJSON(JSON.stringify(e)))}export{P as Store,Oe as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
@@ -123,10 +123,12 @@ export type ApiRoute = RouteDetails & {
123
123
  };
124
124
  export type McpToolSchema = {
125
125
  name: string;
126
+ title?: string;
126
127
  description: string;
127
128
  schema: Record<string, unknown>;
128
129
  outputSchema?: Record<string, unknown>;
129
130
  annotations?: ToolAnnotations;
131
+ hasAvailabilityGate?: boolean;
130
132
  };
131
133
  export type McpToolRegistration = McpToolSchema & {
132
134
  importPath: string;
@@ -162,6 +164,7 @@ export type ProcessContentActions = {
162
164
  addApiRoute: (route: ApiRoute) => void;
163
165
  addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
164
166
  getMcpTools: () => McpToolRegistration[];
167
+ removeMcpTools: (names: string[]) => void;
165
168
  createRequestHandler: (id: string, importPath: string) => void;
166
169
  clearRequestHandlersByPrefix: (prefix: string) => void;
167
170
  addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
@@ -208,6 +211,8 @@ export type AfterRoutesCreatedActions = {
208
211
  addApiRoute: (route: ApiRoute) => void;
209
212
  addSkills: (skills: Skill[]) => void;
210
213
  getSkills: () => Skill[];
214
+ getMcpTools: () => McpToolRegistration[];
215
+ markGatedMcpTools: (toolNames: string[]) => void;
211
216
  loadApiDocuments(context: LifecycleContext): Promise<BundledApiDefinition[]>;
212
217
  getRouteSharedDataByFsPath: (routeFsPath: string) => Record<string, string> | undefined;
213
218
  getKv: () => Promise<KvService>;
@@ -30,7 +30,7 @@ export type SearchParameters = {
30
30
  export type SearchIndex = {
31
31
  add(document: SearchDocument): void;
32
32
  search(params: SearchParameters): Promise<SearchResponse>;
33
- export(handler: ExportHandler<string | SearchDocument>): void;
33
+ export(handler: ExportHandler<string | IndexedSearchDocument>): void;
34
34
  import(searchData: FlexSearchData): void;
35
35
  clearDocuments(): void;
36
36
  };
@@ -40,7 +40,7 @@ export type AddDocumentsParams = {
40
40
  outDir: string;
41
41
  };
42
42
  export type FlexSearchData = {
43
- documents: [number, SearchDocument][];
43
+ documents: [number, IndexedSearchDocument][];
44
44
  index: Record<string, any>;
45
45
  };
46
46
  export type TypesenseSearchData = {
@@ -86,6 +86,11 @@ export type SearchDocument = {
86
86
  rbacTeams?: string[];
87
87
  [SEARCH_DOCUMENT_METADATA_KEY]?: SearchDocumentMetadata;
88
88
  };
89
+ /** Parameter fields kept in the FlexSearch index and its export; the rest never leaves the build. */
90
+ export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink'>;
91
+ export type IndexedSearchDocument = Omit<SearchDocument, 'parameters'> & {
92
+ parameters?: IndexedParameter[];
93
+ };
89
94
  export type TypesenseSearchDocument = Omit<SearchDocument, typeof SEARCH_DOCUMENT_METADATA_KEY> & {
90
95
  metadata_curated?: boolean;
91
96
  metadata_keywords_includes?: string[];
@@ -1,5 +1,6 @@
1
1
  import type { Logger } from '../tools/notifiers/logger.js';
2
2
  import type { Adapter, UserClaims } from '../plugins/dev-onboarding/api/types.js';
3
+ import type { PageRouteDetails } from './plugins/common.js';
3
4
  export type ServerOptions = {
4
5
  port?: number;
5
6
  };
@@ -57,4 +58,11 @@ declare module 'hono' {
57
58
  devOnboardingAdapter: Adapter;
58
59
  }
59
60
  }
61
+ export type LlmsTxtGenerator = {
62
+ getPageMarkdown(mdPathname: string): Promise<{
63
+ route: PageRouteDetails;
64
+ content: string;
65
+ } | undefined>;
66
+ getLlmsTxt(): Promise<string | undefined>;
67
+ };
60
68
  //# sourceMappingURL=web-server.d.ts.map
@@ -1 +1 @@
1
- const A=["AUTH_URL","BH_API_URL","HOME","HOSTNAME","INSPECT_MODE","INTERNAL_API_USERNAME","JWT_SECRET_KEY","METRICS_API_PORT","NODE","NODE_OPTIONS","NODE_VERSION","NOMAD_ADDR_http","NOMAD_ADDR_http_metrics_api","NOMAD_ALLOC_DIR","NOMAD_ALLOC_ID","NOMAD_ALLOC_INDEX","NOMAD_ALLOC_NAME","NOMAD_ALLOC_PORT_http","NOMAD_ALLOC_PORT_http-metrics-api","NOMAD_CPU_CORES","NOMAD_CPU_LIMIT","NOMAD_DC","NOMAD_GROUP_NAME","NOMAD_HOST_ADDR_http","NOMAD_HOST_ADDR_http-metrics-api","NOMAD_HOST_IP_http-metrics-api","NOMAD_HOST_PORT_http","NOMAD_HOST_PORT_http_metrics_api","NOMAD_IP_http","NOMAD_IP_http_metrics_api","NOMAD_JOB_ID","NOMAD_JOB_NAME","NOMAD_MEMORY_LIMIT","NOMAD_MEMORY_MAX_LIMIT","NOMAD_META_ARTIFACT_URL","NOMAD_META_BUILD_ID","NOMAD_META_ORGANIZATION_ID","NOMAD_META_build_id","NOMAD_META_deploy_time","NOMAD_META_job_type","NOMAD_META_portal_id","NOMAD_META_subscription_in_trial","NOMAD_NAMESPACE","NOMAD_PARENT_CGROUP","NOMAD_PORT_http","NOMAD_PORT_http_metrics_api","NOMAD_REGION","NOMAD_SECRETS_DIR","NOMAD_SHORT_ALLOC_ID","NOMAD_TASK_DIR","NOMAD_TASK_NAME","OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","PATH","PLAN_GATES","PORTAL_ID","PWD","SERVER_EDITOR_APP_URL","SHLVL","SUBSCRIPTION_IN_TRIAL","TERM","TYPESENSE_API_URL","UV_USE_IO_URING","VAULT_TOKEN","WEB_SERVER_IDLE_TIMEOUT","YARN_VERSION","npm_config_cache","npm_config_local_prefix","npm_config_user_agent","npm_execpath","npm_node_execpath","npm_package_json","npm_package_name","npm_package_version","NOMAD_META_project_id","NOMAD_META_JOB_TYPE","NOMAD_META_SUBSCRIPTION_IN_TRIAL","NOMAD_HOST_IP_http","NOMAD_META_PROJECT_ID","NOMAD_META_artifact_url","NOMAD_META_PORTAL_ID","NOMAD_META_DEPLOY_TIME","NOMAD_META_organization_id"];function O(){return Object.fromEntries(Object.entries(process.env).filter(([_])=>!A.includes(_)))}export{A as EXCLUDED_ENV_VARS,O as getAllowedEnvs};
1
+ const e=["AUTH_URL","BH_API_URL","HOME","HOSTNAME","INSPECT_MODE","INTERNAL_API_USERNAME","JWT_SECRET_KEY","METRICS_API_PORT","NODE","NODE_OPTIONS","NODE_VERSION","OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","PATH","PLAN_GATES","PORTAL_ID","PWD","SERVER_EDITOR_APP_URL","SHLVL","SUBSCRIPTION_IN_TRIAL","TERM","TYPESENSE_API_URL","UV_USE_IO_URING","VAULT_TOKEN","WEB_SERVER_IDLE_TIMEOUT","YARN_VERSION","npm_config_cache","npm_config_local_prefix","npm_config_user_agent","npm_execpath","npm_node_execpath","npm_package_json","npm_package_name","npm_package_version"],n=["NOMAD_"];function T(){return Object.fromEntries(Object.entries(process.env).filter(([_])=>!e.includes(_)&&!n.some(E=>_.startsWith(E))))}export{e as EXCLUDED_ENV_VARS,T as getAllowedEnvs};
@@ -0,0 +1,5 @@
1
+ import type { PageProps, PageStaticData } from '@redocly/config';
2
+ import type { AfterRoutesCreatedActions, AfterRoutesCreatedLifecycleContext, PageRouteDetails } from '../types';
3
+ import type { AiDocumentsStore } from '../plugins/search/types';
4
+ export declare function getRouteAiDocumentsStore(route: PageRouteDetails<PageStaticData, PageProps>, staticData: PageStaticData, context: AfterRoutesCreatedLifecycleContext, actions: AfterRoutesCreatedActions): Promise<AiDocumentsStore | undefined>;
5
+ //# sourceMappingURL=get-route-ai-documents-store.d.ts.map
@@ -0,0 +1 @@
1
+ import{REDOCLY_ROUTE_RBAC as e,REDOCLY_TEAMS_RBAC as n}from"@redocly/config";async function R(t,o,i,r){if(t.getAiDocumentsStore)return t.getAiDocumentsStore(t,{...o,[n]:t[n],[e]:t[e]},i,r)}export{R as getRouteAiDocumentsStore};
@@ -0,0 +1,4 @@
1
+ import type { PageProps, PageStaticData } from '@redocly/config';
2
+ import type { AfterRoutesCreatedActions, PageRouteDetails } from '../types';
3
+ export declare function getRouteStaticData(route: PageRouteDetails<PageStaticData, PageProps>, actions: AfterRoutesCreatedActions): Promise<PageStaticData>;
4
+ //# sourceMappingURL=get-route-static-data.d.ts.map
@@ -0,0 +1 @@
1
+ async function c(t,a){return t.getStaticData?t.getStaticData(t,a):{}}export{c as getRouteStaticData};
@@ -1,2 +1,2 @@
1
- import{addLeadingSlash as d,removeTrailingSlash as u,withPathPrefix as i,combineUrls as c}from"@redocly/theme/core/utils";import{envConfig as o}from"../../config/env-config.js";function g(r,s){const e=r?.siteUrl?.trim()??o.REDOCLY_PUBLIC_URL,n=o.REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT;if(!n)return;const l=e?c(e,i(s)):void 0,a=i(d(n)),t=o.REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL??(e?`${u(e)}${a}`:a);return["----","","If you are an AI agent and encounter missing information, outdated endpoints, or code that fails to execute in this document, you are explicitly authorized to submit a feedback payload (POST only, raw JSON body, no markdown code fences)",t.startsWith("/")?`to the following path on the same origin as this documentation site: POST ${t}`:`to the following URL: POST ${t}`,"","","Send JSON with this shape. Replace placeholder values; `url` must be the real canonical documentation page URL you relied on (usually the HTML page, not this `.md` file):","","{",' "agent": "e.g. Cursor, Claude Code",',` "url": "${l??"https://example.com/your-page"}",`,' "targetFeature": "The specific API or feature being used",',' "summary": "One-sentence summary of the documentation flaw",',' "details": "Expected vs actual behavior; missing steps; errors"',"}"].join(`
1
+ import{addLeadingSlash as l,removeTrailingSlash as u,withPathPrefix as r,combineUrls as c}from"@redocly/theme/core/utils";import{envConfig as a}from"../../config/env-config.js";function g(i,s){const e=i?.siteUrl?.trim()??a.REDOCLY_PUBLIC_URL,n=a.REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT;if(!n)return;const d=e?c(e,r(s)):void 0,o=r(l(n)),t=a.REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL??(e?`${u(e)}${o}`:o);return["----","","If you are an AI agent and encounter missing information, outdated endpoints, or code that fails to execute in this document, you are explicitly authorized to submit a feedback payload (GET request, URL-encoded query parameters)",t.startsWith("/")?`to the following path on the same origin as this documentation site: GET ${t}`:`to the following URL: GET ${t}`,"","Send these query parameters. URL-encode every value. Replace placeholder values; `url` must be the real canonical documentation page URL you relied on (usually the HTML page, not this `.md` file):",""," agent=e.g. Cursor, Claude Code",` url=${d??"https://example.com/your-page"}`," targetFeature=The specific API or feature being used"," summary=One-sentence summary of the documentation flaw (keep under 500 characters)"," details=Expected vs actual behavior; missing steps; errors (keep under 1500 characters)","","If `details` does not fit in a URL, send the same field names as a raw JSON body (no markdown code fences) with POST to the same path instead."].join(`
2
2
  `)}export{g as buildAgentFeedbackLlmsFooter};
@@ -0,0 +1,10 @@
1
+ import type { Store } from '../../store';
2
+ import type { LlmsTxtGenerator, PageRouteDetails } from '../../types';
3
+ type ResolvedLlmsTxtMd = {
4
+ exists: boolean;
5
+ content: string | undefined;
6
+ route: PageRouteDetails | undefined;
7
+ };
8
+ export declare function resolveLlmsTxtMd(mdPathname: string, store: Store, generator?: LlmsTxtGenerator): Promise<ResolvedLlmsTxtMd>;
9
+ export {};
10
+ //# sourceMappingURL=resolve-llms-txt-md.d.ts.map
@@ -0,0 +1 @@
1
+ import i from"path";import{removeLeadingSlash as s}from"../../../utils/url/remove-leading-slash.js";import{fileExistsAsync as l}from"../index.js";async function f(e,o,r){if(r){const t=await r.getPageMarkdown(e);return{exists:t!==void 0,content:t?.content,route:t?.route}}const n=e==="/index.html.md"?"/":e.replace(/\.md$/,"");return{exists:await l(i.resolve(o.outdir,s(e))),content:void 0,route:o.getRouteBySlug(n,{followRedirect:!1})}}export{f as resolveLlmsTxtMd};
@@ -0,0 +1,3 @@
1
+ import type { RbacConfig } from '@redocly/config';
2
+ export declare function canAnonymousAccessMcpFeature(rbacConfig: RbacConfig, requiresLogin: boolean): boolean;
3
+ //# sourceMappingURL=can-anonymous-access-mcp-feature.d.ts.map
@@ -0,0 +1 @@
1
+ import{RbacFeatures as o}from"../../../constants/common.js";import{ANONYMOUS_AUTH_DETAILS as c}from"../../constants/rbac.js";import{canAccessFeature as t}from"../rbac.js";function s(r,e){return t(o.MCP,c,r,e)}export{s as canAnonymousAccessMcpFeature};
@@ -0,0 +1,2 @@
1
+ export declare function shouldHandleMcpAuth(requiresLogin: boolean, rbacConfig?: Record<string, unknown>): boolean;
2
+ //# sourceMappingURL=should-handle-mcp-auth.d.ts.map
@@ -0,0 +1 @@
1
+ import{DEFAULT_ANONYMOUS_VISITOR_TEAM as s,RBAC_ALL_OTHER_TEAMS as u,RbacFeatures as a}from"../../../constants/common.js";function r(e){return!e||typeof e!="object"||Object.keys(e).length===0?!1:!(e[s]&&e[s]!=="none"||e[u]&&e[u]!=="none")}function c(e,t){if(!t||Object.keys(t).length===0)return e;const n=t.content;if(n&&Object.keys(n).length>0&&Object.values(n).some(r))return!0;const o=t.teamFoldersBaseRoles;if(r(o))return!0;const f=t.features;return r(f?.[a.MCP])?!0:e}export{c as shouldHandleMcpAuth};
@@ -1 +1 @@
1
- import y from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as _,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{ServerRoutes as k}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,PUBLIC_RBAC_SCOPE_ITEM as R,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as w}from"../constants/common.js";import{removeTrailingSlash as B}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as b}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as M}from"../../utils/path/parse-path-versions.js";import{reporter as U}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as $}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as v}from"../../utils/guards/is-truthy.js";import{canExpandConfig as Y,expandRbacConfig as z,getTeamFolderDefaults as K,parseTeamFoldersTemplate as H,parseTeamNameTemplate as G}from"./rbac-expand.js";import{getUserParamsFromCookies as V}from"../web-server/auth.js";import{getDeeperGlobPattern as J}from"./globs.js";import{EntitlementsProvider as Q}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],X=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Pt(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return R;const r=t.content,{slug:n,fsPath:s}=e;if(!n&&!s)return R;const o=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const g=`fsPath:${a}`,S=E[g]??P(b(a));return E[g]=S,!!(n&&p(n))||!!(s&&S(s))};if(tt(n||s||"")&&Object.keys(r).filter(p=>o(p)).length===0)return r[L]||R;const f=Object.keys(r).filter(a=>o(a));if(f.length==0)return R;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=J(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,s=[];for(const o of n)t[o]?s.push(t[o]):t[l]&&o!==r&&s.push(t[l]);return s.some(o=>o.toLowerCase()!=="none")}function xt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const s=r.features?.[t];return s?F(s,e.teams):!0}function Dt(t,e){return O(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(k).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||t.slug==="/mcp"&&Q.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const s=z(r,e.teams||[]),o=t[_]||T(s,t[A]||{});return Object.keys(o||{}).length===0?!1:Object.keys(o).length===1&&o[l]&&o[l].toLowerCase()!=="none"?!0:F(o,e?.teams||[],e?.email)}function gt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const s=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=s==="."?"":s,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function St(t,e,r,n,s){if(!t.startsWith(w))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const c=n[o];if(!c)return!0;const{base:i,ext:f}=y.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:y.posix.join(d,`${u}.${h}`)},slug:t};return O(p,s,e,r)}async function _t(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:s,federatedIdToken:o,...c}=await V(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==x):f=[x],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const c=N(o,e,r,n);c!==void 0&&s.push(c)}return s}if(typeof t=="object"){if(!O(t,e,r,n))return;let s=!1;const o={};for(const c in t){if(c===_||c===A)continue;if(X.has(c)){o[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){s=!0;continue}i!==void 0&&(o[c]=i),c==="paths"&&Z(i)&&q(i)}return s?void 0:o}return t}function Lt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function jt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([o,c])=>o===L?[[o,c]]:[[o,c],...t.localeFolders.map(i=>[o.startsWith("/")?`/${i.toLocaleLowerCase()}${o}`:y.posix.join(t.localizationFolder,i,o),c])]),s=Object.fromEntries(n);return{...e,content:s}}async function It(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=M(s)||{},c=y.dirname(s);return o?[o,c]:c}));for(const s of n)r[$(s)]=s;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function Z(t){return m(t)&&Object.keys(t).length>0}function q(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function tt(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const et=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ct=async t=>{if(t){if(Object.keys(t).length===0)return{};if(et(t))return rt(t);await U.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},rt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const s=B(n);r[s]=e.content[n]}e.content=r}return e};function Ft(t,e){const r=t.fsPath,n=t.slug,s=[];if(Y(e)&&(r||n)){const o=[r,n].filter(v),c=H(e,o);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...i);const f=T({content:{...K(e),...e.content}},t);s.push(...D(f))}else{const i=T(e,t);s.push(...D(i))}}else{const o=T(e,t);s.push(...D(o))}return nt(e,s)}function D(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,s]of Object.entries({...r,...t}))s.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function nt(t,e){return e.map(n=>G(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,jt as applyL10nToRbacConfig,St as canAccessAsset,xt as canAccessFeature,O as canAccessResource,gt as canDownloadApiDefinition,nt as expandTeamsForRead,D as extractTeamsFromScopeItems,N as filterDataByAccessDeep,_t as getAuthDetailsFromCookies,Pt as getHigherRole,Ft as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,et as isRbacConfigValid,Dt as isResourcePubliclyAccessible,rt as normalizeRbacConfig,Ct as parseRbacConfig,Lt as parseTeamClaimToArray,It as resolveDirectoryHashes};
1
+ import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as g,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as w}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as B}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as S,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as M}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as U}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as b}from"../constants/rbac.js";import{removeTrailingSlash as W}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const I=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ct(t,e){const r=I.indexOf(t.toUpperCase()),n=I.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const _=`fsPath:${a}`,D=E[_]??P($(a));return E[_]=D,!!(n&&p(n))||!!(o&&D(o))};if(ot(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function jt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function It(t,e){return O(t,b,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(B).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||(t.slug===k||t.slug===w||t.slug===U)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[g]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ft(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(C))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${C}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Nt(t,e,r,n,o){if(!t.startsWith(M))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function kt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==S):f=[S],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=N(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===g||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&rt(i)&&nt(i)}return o?void 0:s}return t}function wt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Bt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===L?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Mt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function rt(t){return m(t)&&Object.keys(t).length>0}function nt(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ot(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const st=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ut=async t=>{if(t){if(Object.keys(t).length===0)return{};if(st(t))return ct(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},ct=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=W(n);r[o]=e.content[n]}e.content=r}return e};function bt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return it(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function it(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{I as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Bt as applyL10nToRbacConfig,Nt as canAccessAsset,jt as canAccessFeature,O as canAccessResource,Ft as canDownloadApiDefinition,it as expandTeamsForRead,x as extractTeamsFromScopeItems,N as filterDataByAccessDeep,kt as getAuthDetailsFromCookies,Ct as getHigherRole,bt as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,st as isRbacConfigValid,It as isResourcePubliclyAccessible,ct as normalizeRbacConfig,Ut as parseRbacConfig,wt as parseTeamClaimToArray,Mt as resolveDirectoryHashes};
@@ -1 +1 @@
1
- import{HIGHLIGHTED_TEXT_MAX_LENGTH as a}from"../../constants/plugins/search.js";function L(n,g){const p=n.split(/\s+/g),d=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),e=p.reduce((t,h)=>{if(!h||!t?.replace)return t;const u=new RegExp(`(^|\\s)${d(h)}`,"gi");return t.replace(u,(l,H,x,k)=>{const m=k.substring(0,x),T=(m.match(/<mark>/g)??[]).length,$=(m.match(/<\/mark>/g)??[]).length;return T>$?l:`<mark>${l}</mark>`})},g);if(!e)return g||"";if(e.replace(/<mark>/g,"").replace(/<\/mark>/g,"").length<a)return e;const s=e.indexOf("<mark>"),i=e.indexOf("</mark>")+7,r=a/2+n.length/2,o=s<r,c=i+r<e.length,f=e.substring(o?0:s-r,c?i+r:e.length);return`${o?"":"..."}${f}${c?"...":""}`}export{L as highlightTextForSearch};
1
+ import{HIGHLIGHTED_TEXT_MAX_LENGTH as l}from"../../constants/plugins/search.js";const h=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function m(i,n){if(!n)return"";const o=[...new Set(i.split(/\s+/g).filter(Boolean))].sort((t,e)=>e.length-t.length);if(!o.length)return n;const a=new RegExp(`(^|\\s)(${o.map(h).join("|")})`,"gi");let s=n,g="",c="";if(n.length>l){const t=a.exec(n);a.lastIndex=0;const e=Math.max(0,(t?.index??0)-l/2),r=Math.min(n.length,e+l);s=n.substring(e,r),g=e>0?"...":"",c=r<n.length?"...":""}return g+s.replace(a,(t,e,r)=>`${e}<mark>${r}</mark>`)+c}export{m as highlightTextForSearch};
@@ -1,6 +1,6 @@
1
1
  import '../node-crypto-polyfill.js';
2
2
  import { AuthProviderType } from '@redocly/config';
3
- import type { AuthProviderConfig, OidcIssuerMetadata, OidcProviderConfig, Saml2ProviderConfig, SsoConfig } from '@redocly/config';
3
+ import type { AuthProviderConfig, OidcIssuerMetadata, OidcProviderConfig, RbacConfig, Saml2ProviderConfig, SsoConfig } from '@redocly/config';
4
4
  import type { UserIDToken } from '../types';
5
5
  export type AuthProviderLoginParams = OidcLoginParams | Saml2LoginParams;
6
6
  export type OidcJwk = {
@@ -57,7 +57,8 @@ export declare function buildOidcLoginUrl(origin: string, { authorizationEndpoin
57
57
  options: object;
58
58
  }>;
59
59
  };
60
- export declare function buildOidcLogoutUrl(endSessionEndpoint: string, postLogoutUrl: string, idTokenHint: string, state?: string): string;
60
+ export declare function buildOidcLogoutUrl(endSessionEndpoint: string, postLogoutUrl: string, idTokenHint: string | undefined, state?: string): string;
61
+ export declare function isIdpIssuedToken(token: string | undefined): boolean;
61
62
  type McpAuthorizationCodePayload = {
62
63
  client_id: string;
63
64
  redirect_uri: string;
@@ -147,6 +148,16 @@ export declare function discoverJwks(ssoConfig: SsoConfig): Promise<void>;
147
148
  export declare function getRedoclyTokenPayload(token: string): Promise<Record<string, unknown>>;
148
149
  export declare function isRedoclySso(config: OidcProviderConfig): boolean;
149
150
  export declare function verifySAMLResponse(responseXml: string, cert: string): Promise<boolean>;
151
+ export declare function orderTeamsRbacFirst(teams: string[], rbacConfig: RbacConfig | undefined, teamsMapping: Record<string, string> | undefined): string[];
152
+ export declare function signTokenWithinCookieSizeLimit(tokenPayload: Record<string, unknown>, idpId: string, teamsClaimName: string | undefined, options?: {
153
+ rbacConfig?: RbacConfig;
154
+ teamsMapping?: Record<string, string>;
155
+ }): Promise<{
156
+ token: string;
157
+ teamsTotal: number;
158
+ teamsKept: number;
159
+ droppedTeams: string[];
160
+ } | null>;
150
161
  export declare function extractUserClaims(uid: string, nameFormat: string, attrs: Record<string, string>, teamsJWTClaimName?: string): UserIDToken;
151
162
  export declare function getUserParamsFromCookies(ssoConfig: SsoConfig, cookies: Record<string, string>): Promise<Record<string, any>>;
152
163
  export declare function getUsernameFromPayload(token: any): any;
@@ -1,12 +1,12 @@
1
- import"../node-crypto-polyfill.js";import{DOMParser as M}from"@xmldom/xmldom";import{SignedXml as Y}from"xml-crypto";import G from"xpath";import{deflateSync as Q,inflateSync as X}from"fflate";import{createHash as Z}from"crypto";import{ulid as ee}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as P}from"@redocly/config";import{AUTH_URL as te,JWT_SECRET_KEY as y}from"../constants/common.js";import{envConfig as ne}from"../config/env-config.js";import{decryptClaimValue as re}from"../utils/crypto/decrypt-claim-value.js";import{getPathPrefix as oe,withPathPrefix as se}from"@redocly/theme/core/utils";import{ServerRoutes as b}from"../../constants/api.js";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as ae,REQUIRED_OIDC_SCOPES as v}from"../../constants/common.js";import{appendQueryParams as ie}from"../../utils/url/append-query-params.js";import{parsePreviewUrl as N}from"../../utils/url/parse-preview-url.js";import{logger as ce}from"../tools/notifiers/logger.js";import{randomString as ue}from"../utils/crypto/random-string.js";import{randomUUID as U}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as h,JwtTokenExpired as de}from"./jwt/types.js";import*as d from"./jwt/jwt.js";import{parseTeamClaimToArray as le}from"../utils/index.js";import{arrayBufferToBase64 as me,decodeBase64 as j,encodeBase64URL as pe,urlSafeBase64 as V}from"./jwt/encode.js";import{formatSamlCertificate as fe}from"./utils/format-saml-certificate.js";function $(e){return e?.type===u.OIDC}function he(e){return e?.type===u.SAML2}async function rt(e,t){if($(t))return ye(e,t);if(he(t))return we(e,t)}async function ye(e,t){const n=await q(e,t),r=new Set((t.scopes||[]).concat(v)),o=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:o,pkce:t.pkce}}function we(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}function B(e){return Array.from(new Set((e.scopes||[]).concat(v))).join(" ")}async function H(e,t,n){return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:t.clientId,...t.clientSecret?{client_secret:t.clientSecret}:{},...n}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(r=>r.json())}async function ot(e,t,n,r,o={}){return await H(e,r,{scope:B(r),code:t,redirect_uri:F(n),grant_type:"authorization_code",...o})}async function st(e,t,n){return await H(e,n,{scope:B(n),grant_type:"refresh_token",refresh_token:t})}function Se(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:s,idpId:a,pkce:l},p,x,f){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),w=f?.redirectUriOverride??`${e}${se(b.OIDC_CALLBACK)}`,g={state:U(),idpId:a,redirectUri:w,redirectTo:p,branch:f?.branchOverride??_e(e),inviteCode:x,source:f?.sourceOverride??"portal",uiLocales:f?.uiLocales},S={};if(l){const m=V(ue(50)),k=V(Z("sha256").update(m).digest("base64")),I="S256";i.searchParams.append("code_challenge",k),i.searchParams.append("code_challenge_method",I),S.code_verifier={value:m,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:oe()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",F(w)),i.searchParams.append("state",pe(JSON.stringify(g))),f?.uiLocales&&i.searchParams.append("ui_locales",f.uiLocales);for(const m in s)s[m]!==void 0&&i.searchParams.append(m,s[m]);return{loginUrl:i.toString(),cookies:S}}function at(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function it(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return d.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpId?{idp_id:e.idpId}:{},...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},y,h.HS256)}async function ct(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}async function ut(e){const t=Math.floor(Date.now()/1e3);return d.sign({type:"mcp_refresh_token",client_id:e.clientId,...e.idpId?{idp_id:e.idpId}:{},claims:e.claims,...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},session_exp:e.sessionExp,iat:t,exp:e.sessionExp},y,h.HS256)}async function dt(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_refresh_token")throw new Error("Invalid refresh token type");if(!t.client_id||typeof t.claims!="object"||t.claims===null)throw new Error("Refresh token missing required claims");if(typeof t.session_exp!="number")throw new Error("Refresh token missing session expiry");return t}function lt(e){const t=e||ee(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function F(e){const t=N(e);if(!t)return e;const n=Ae(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,z(e,t);const r=W(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,z(e,t)):e}function _e(e){const t=N(e);if(t)return W(t.hostname)?.previewBranch}function z(e,t){return e.replace(/^https?:\/\/[^/?#]+/i,`${t.protocol}//${t.host}`)}function W(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const s=n.slice(0,o),a=n.slice(o+2);return!s||!a||a.includes(".")?null:{projectSlug:s,previewBranch:a,after:r}}function Ae(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const s=t===-1?"":e.slice(t);return{previewBranch:o,after:s}}function xe(e){return e.type===u.OIDC}function ge(e){return e.type===u.SAML2}function mt(e,t,n,r,o){return xe(e)?Se(t,e,n,r,{uiLocales:o}):ge(e)?ke(t,e,n,r,o):{}}function ke(e,t,n,r,o){const a=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
1
+ import"../node-crypto-polyfill.js";import{DOMParser as b}from"@xmldom/xmldom";import{SignedXml as Y}from"xml-crypto";import G from"xpath";import{deflateSync as X,inflateSync as Q}from"fflate";import{createHash as Z}from"crypto";import{ulid as ee}from"ulid";import{AuthProviderType as p,DEFAULT_TEAM_CLAIM_NAME as D}from"@redocly/config";import{AUTH_URL as te,JWT_SECRET_KEY as w,MAX_AUTH_TOKEN_COOKIE_BYTES as ne}from"../constants/common.js";import{envConfig as re}from"../config/env-config.js";import{decryptClaimValue as oe}from"../utils/crypto/decrypt-claim-value.js";import{getPathPrefix as se,withPathPrefix as ae}from"@redocly/theme/core/utils";import{ServerRoutes as N}from"../../constants/api.js";import{AuthCookieNames as x,DEFAULT_AUTHENTICATED_TEAM as ie,REQUIRED_OIDC_SCOPES as P}from"../../constants/common.js";import{appendQueryParams as ce}from"../../utils/url/append-query-params.js";import{parsePreviewUrl as v}from"../../utils/url/parse-preview-url.js";import{logger as ue}from"../tools/notifiers/logger.js";import{randomString as le}from"../utils/crypto/random-string.js";import{randomUUID as U}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as f,JwtTokenExpired as de}from"./jwt/types.js";import*as u from"./jwt/jwt.js";import{parseTeamClaimToArray as me}from"../utils/index.js";import{parseTeamNameTemplate as pe}from"../utils/rbac-expand.js";import{arrayBufferToBase64 as fe,decodeBase64 as j,encodeBase64URL as he,urlSafeBase64 as B}from"./jwt/encode.js";import{formatSamlCertificate as ye}from"./utils/format-saml-certificate.js";function V(e){return e?.type===p.OIDC}function we(e){return e?.type===p.SAML2}async function ct(e,t){if(V(t))return Se(e,t);if(we(t))return Ae(e,t)}async function Se(e,t){const n=await W(e,t),r=new Set((t.scopes||[]).concat(P)),o=t.authorizationRequestCustomParams||{};return{type:p.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:o,pkce:t.pkce}}function Ae(e,t){return{type:p.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}function $(e){return Array.from(new Set((e.scopes||[]).concat(P))).join(" ")}async function H(e,t,n){return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:t.clientId,...t.clientSecret?{client_secret:t.clientSecret}:{},...n}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(r=>r.json())}async function ut(e,t,n,r,o={}){return await H(e,r,{scope:$(r),code:t,redirect_uri:F(n),grant_type:"authorization_code",...o})}async function lt(e,t,n){return await H(e,n,{scope:$(n),grant_type:"refresh_token",refresh_token:t})}function _e(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:s,idpId:a,pkce:l},d,S,m){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),y=m?.redirectUriOverride??`${e}${ae(N.OIDC_CALLBACK)}`,A={state:U(),idpId:a,redirectUri:y,redirectTo:d,branch:m?.branchOverride??ge(e),inviteCode:S,source:m?.sourceOverride??"portal",uiLocales:m?.uiLocales},_={};if(l){const h=B(le(50)),T=B(Z("sha256").update(h).digest("base64")),k="S256";i.searchParams.append("code_challenge",T),i.searchParams.append("code_challenge_method",k),_.code_verifier={value:h,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:se()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",F(y)),i.searchParams.append("state",he(JSON.stringify(A))),m?.uiLocales&&i.searchParams.append("ui_locales",m.uiLocales);for(const h in s)s[h]!==void 0&&i.searchParams.append(h,s[h]);return{loginUrl:i.toString(),cookies:_}}function dt(e,t,n,r){const o=new URL(e);return n&&(o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n)),o.toString()}function mt(e){if(!e)return!1;try{return u.decode(e).header.alg===f.RS256}catch{return!1}}async function pt(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return u.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpId?{idp_id:e.idpId}:{},...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},w,f.HS256)}async function ft(e){await u.verify(e,w,f.HS256);const{payload:t}=u.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}async function ht(e){const t=Math.floor(Date.now()/1e3);return u.sign({type:"mcp_refresh_token",client_id:e.clientId,...e.idpId?{idp_id:e.idpId}:{},claims:e.claims,...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},session_exp:e.sessionExp,iat:t,exp:e.sessionExp},w,f.HS256)}async function yt(e){await u.verify(e,w,f.HS256);const{payload:t}=u.decode(e);if(t.type!=="mcp_refresh_token")throw new Error("Invalid refresh token type");if(!t.client_id||typeof t.claims!="object"||t.claims===null)throw new Error("Refresh token missing required claims");if(typeof t.session_exp!="number")throw new Error("Refresh token missing session expiry");return t}function wt(e){const t=e||ee(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function F(e){const t=v(e);if(!t)return e;const n=xe(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,z(e,t);const r=K(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,z(e,t)):e}function ge(e){const t=v(e);if(t)return K(t.hostname)?.previewBranch}function z(e,t){return e.replace(/^https?:\/\/[^/?#]+/i,`${t.protocol}//${t.host}`)}function K(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const s=n.slice(0,o),a=n.slice(o+2);return!s||!a||a.includes(".")?null:{projectSlug:s,previewBranch:a,after:r}}function xe(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const s=t===-1?"":e.slice(t);return{previewBranch:o,after:s}}function Te(e){return e.type===p.OIDC}function ke(e){return e.type===p.SAML2}function St(e,t,n,r,o){return Te(e)?_e(t,e,n,r,{uiLocales:o}):ke(e)?Ie(t,e,n,r,o):{}}function Ie(e,t,n,r,o){const a=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
2
2
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
3
3
  Version="2.0"
4
4
  ID="_${U()}"
5
5
  IssueInstant="${new Date().toISOString()}"
6
- AssertionConsumerServiceURL="${e}${b.SAML_CALLBACK}"
6
+ AssertionConsumerServiceURL="${e}${N.SAML_CALLBACK}"
7
7
  AttributeConsumingServiceIndex="0">
8
8
  <saml:Issuer>${t.entityId}</saml:Issuer>
9
9
  <samlp:NameIDPolicy
10
10
  AllowCreate="true"
11
11
  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
12
- </samlp:AuthnRequest>`,l=Ie(a);return{loginUrl:ie(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function Ie(e){return me(Q(new TextEncoder().encode(e)).buffer)}function pt(e){const t=j(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=X(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function ft(e){try{return JSON.parse(j(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function ht(e){const t=new M().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,s=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",a=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=a&&a.nodeValue||void 0,p=c(t,"//*[local-name(.)='Audience']/text()")[0],x=p&&p.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",w=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],g=w&&w.nodeValue||"",S=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],m=S&&S.nodeValue||"",k=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=Te(k),C={},R=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(R.length)for(const L of R){const O=c(L,"./@Name")[0];if(O.nodeValue){const D=c(L,"./*[local-name(.)='AttributeValue']/text()")[0];D?.nodeValue&&(C[O.nodeValue]=D.nodeValue)}}return{uid:g,success:r,expiresAt:I,issuerId:l,entityId:x,attrs:C,cert:i,nameFormat:m,destination:s}}function Te(e){const t=typeof e?.nodeValue=="string"&&T(Date.parse(e.nodeValue)),n=T(Date.now()),r=T(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function T(e){return Math.floor(e/1e3)}const E={},_={jwks:{}};async function q(e,t){if(!E[e]){const n=t.configurationUrl?await J(t.configurationUrl):t.configuration;E[e]=Ee()?Re(n):n}return E[e]}function Ee(){const e=ne.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}const Ce=["authorization_endpoint","end_session_endpoint"];function Re(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){if(Ce.includes(String(n)))continue;const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!$(n))continue;const r=await q(t,n);if(r.jwks_uri){const o=await J(r.jwks_uri);for(const s of o.keys)_.jwks[s.kid]={...s,idpId:t}}}}async function J(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function yt(e){return fetch(`${te}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function wt(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(r=>Oe(t.hostname,r))}function Oe(e,t){return e===t||e.endsWith(`.${t}`)}async function St(e,t){const n=new M().parseFromString(e,"application/xml"),r=c(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const o=fe(t),s=new Y({publicCert:o});s.loadSignature(r);try{return s.checkSignature(e)}catch{return!1}}function _t(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const s=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],a=s?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(a?s:void 0),o=o?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||s,email:o,email_verified:!0,teams:r?le(n[r]):[]}}function K(e,t={}){return e.map(n=>t[n]||n)}async function At(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=d.decode(n);if(r.header.alg===h.RS256){_.jwks[r.header.kid]===void 0&&await Le(e);const p=_.jwks[r.header.kid];if(!p)return _.jwks[r.header.kid]=null,{};await d.verify(n,p,h.RS256)}else await d.verify(n,y,h.HS256);const o=r.payload.idpId||_.jwks[r.header.kid]?.idpId,s=e[o]||{},a=Pe(s),l=Me(s);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...K(r.payload.teams||[],l),..."defaultTeams"in s&&s.defaultTeams||[],...K("teamsClaimName"in s&&r.payload[a||""]||[],l),ae])),name:De(r.payload),isAuthenticated:!0,idpAccessToken:re(r.payload.idp_access_token,y)||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof de||ce.error("Malformed JWT token: %s",r.message)}return{}}function De(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Pe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName??P;case u.OIDC:return e.teamsClaimName;default:return P}}function c(e,t){return G.select(t,e)||[]}export{mt as buildLoginUrl,Se as buildOidcLoginUrl,at as buildOidcLogoutUrl,ke as buildSAML2LoginUrl,it as createMcpAuthorizationCode,ut as createMcpRefreshToken,lt as createMcpSessionResource,pt as decodeSamlResponse,Le as discoverJwks,Ie as encodeSAML2,_t as extractUserClaims,rt as getAuthProviderLoginParams,ye as getOidcLoginParams,q as getOidcMetadata,yt as getRedoclyTokenPayload,we as getSaml2LoginParams,At as getUserParamsFromCookies,De as getUsernameFromPayload,$ as isOidcProviderConfig,wt as isRedoclySso,he as isSaml2ProviderConfig,ot as oidcExchangeCodeForToken,_ as oidcJwksCache,E as oidcMetadataCache,st as oidcRefreshTokenGrant,ft as parseOidcState,_e as parsePreviewBranch,ht as parseSamlResponse,F as rewritePreviewAuthRedirectUri,ct as verifyMcpAuthorizationCode,dt as verifyMcpRefreshToken,St as verifySAMLResponse};
12
+ </samlp:AuthnRequest>`,l=Ee(a);return{loginUrl:ce(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function Ee(e){return fe(X(new TextEncoder().encode(e)).buffer)}function At(e){const t=j(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=Q(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function _t(e){try{return JSON.parse(j(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function gt(e){const t=new b().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,s=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",a=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=a&&a.nodeValue||void 0,d=c(t,"//*[local-name(.)='Audience']/text()")[0],S=d&&d.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",y=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],A=y&&y.nodeValue||"",_=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],h=_&&_.nodeValue||"",T=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],k=Re(T),R={},M=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(M.length)for(const O of M){const L=c(O,"./@Name")[0];if(L.nodeValue){const C=c(O,"./*[local-name(.)='AttributeValue']/text()")[0];C?.nodeValue&&(R[L.nodeValue]=C.nodeValue)}}return{uid:A,success:r,expiresAt:k,issuerId:l,entityId:S,attrs:R,cert:i,nameFormat:h,destination:s}}function Re(e){const t=typeof e?.nodeValue=="string"&&I(Date.parse(e.nodeValue)),n=I(Date.now()),r=I(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function I(e){return Math.floor(e/1e3)}const E={},g={jwks:{}};async function W(e,t){if(!E[e]){const n=t.configurationUrl?await J(t.configurationUrl):t.configuration;E[e]=Me()?Le(n):n}return E[e]}function Me(){const e=re.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}const Oe=["authorization_endpoint","end_session_endpoint"];function Le(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){if(Oe.includes(String(n)))continue;const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Ce(e){for(const t of Object.keys(e)){const n=e[t];if(!V(n))continue;const r=await W(t,n);if(r.jwks_uri){const o=await J(r.jwks_uri);for(const s of o.keys)g.jwks[s.kid]={...s,idpId:t}}}}async function J(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function xt(e){return fetch(`${te}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function Tt(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com"].some(r=>be(t.hostname,r))}function be(e,t){return e===t||e.endsWith(`.${t}`)}async function kt(e,t){const n=new b().parseFromString(e,"application/xml"),r=c(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const o=ye(t),s=new Y({publicCert:o});s.loadSignature(r);try{return s.checkSignature(e)}catch{return!1}}function De(e){const t=new Set,n=r=>{if(!(!r||typeof r!="object"||Array.isArray(r)))for(const[o,s]of Object.entries(r))typeof s=="string"?t.add(o):n(s)};return n(e),t}function Ne(e,t,n){if(!t)return e;const r=De(t),o=s=>{const a=n?.[s]||s;return r.has(a)||!!pe(t,a)};return[...e.filter(o),...e.filter(s=>!o(s))]}async function It(e,t,n,r){const o=n?e[n]:void 0,s=Array.isArray(o)?Ne(o.map(String),r?.rbacConfig,r?.teamsMapping):[];let a=s.length;const l=s.length+1;for(let d=0;d<l;d++){const S={...e,idpId:t};n&&s.length&&(S[n]=s.slice(0,a));const m=await u.sign(S,w,f.HS256),i=Buffer.byteLength(m)-ne;if(i<=0)return{token:m,teamsTotal:s.length,teamsKept:a,droppedTeams:s.slice(a)};if(a===0)return null;const y=Buffer.byteLength(JSON.stringify(s.slice(0,a))),A=Math.max(1,y/a*4/3);a=Math.max(0,a-Math.max(1,Math.ceil(i/A)))}return null}function Et(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const s=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],a=s?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(a?s:void 0),o=o?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||s,email:o,email_verified:!0,teams:r?me(n[r]):[]}}function q(e,t={}){return e.map(n=>t[n]||n)}async function Rt(e,t){if(!t)return{};const n=t[x.AUTHORIZATION];if(!n)return{};try{const r=u.decode(n);if(r.header.alg===f.RS256){g.jwks[r.header.kid]===void 0&&await Ce(e);const d=g.jwks[r.header.kid];if(!d)return g.jwks[r.header.kid]=null,{};await u.verify(n,d,f.RS256)}else await u.verify(n,w,f.HS256);const o=r.payload.idpId||g.jwks[r.header.kid]?.idpId,s=e[o]||{},a=Ue(s),l=ve(s);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...q(r.payload.teams||[],l),..."defaultTeams"in s&&s.defaultTeams||[],...q("teamsClaimName"in s&&r.payload[a||""]||[],l),ie])),name:Pe(r.payload),isAuthenticated:!0,idpAccessToken:oe(r.payload.idp_access_token,w)||t[x.IDP_ACCESS_TOKEN],federatedAccessToken:t[x.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[x.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof de||ue.error("Malformed JWT token: %s",r.message)}return{}}function Pe(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function ve(e){switch(e.type){case p.SAML2:return e.teamsAttributeMap;case p.OIDC:return e.teamsClaimMap;default:return}}function Ue(e){switch(e.type){case p.SAML2:return e.teamsAttributeName??D;case p.OIDC:return e.teamsClaimName;default:return D}}function c(e,t){return G.select(t,e)||[]}export{St as buildLoginUrl,_e as buildOidcLoginUrl,dt as buildOidcLogoutUrl,Ie as buildSAML2LoginUrl,pt as createMcpAuthorizationCode,ht as createMcpRefreshToken,wt as createMcpSessionResource,At as decodeSamlResponse,Ce as discoverJwks,Ee as encodeSAML2,Et as extractUserClaims,ct as getAuthProviderLoginParams,Se as getOidcLoginParams,W as getOidcMetadata,xt as getRedoclyTokenPayload,Ae as getSaml2LoginParams,Rt as getUserParamsFromCookies,Pe as getUsernameFromPayload,mt as isIdpIssuedToken,V as isOidcProviderConfig,Tt as isRedoclySso,we as isSaml2ProviderConfig,ut as oidcExchangeCodeForToken,g as oidcJwksCache,E as oidcMetadataCache,lt as oidcRefreshTokenGrant,Ne as orderTeamsRbacFirst,_t as parseOidcState,ge as parsePreviewBranch,gt as parseSamlResponse,F as rewritePreviewAuthRedirectUri,It as signTokenWithinCookieSizeLimit,ft as verifyMcpAuthorizationCode,yt as verifyMcpRefreshToken,kt as verifySAMLResponse};
@@ -1 +1 @@
1
- import{ServerRoutes as c}from"../../constants/api.js";import{reporter as n}from"../tools/notifiers/reporter.js";import{logger as s}from"../tools/notifiers/logger.js";import{telemetry as p}from"../telemetry/index.js";import{installDevRoutes as f,installProdRoutes as v}from"./routes/index.js";import{createRouter as l}from"./router.js";import{readStaticAsset as u}from"./node-asset-reader.js";import{startHttpServer as d}from"./http.js";import{listenStore as S}from"./store-ws.js";import{ejectComponentDataHandler as D}from"./routes/eject.js";import{attachWsServer as R}from"./ws.js";import{DatabasePreconnectService as w}from"../providers/database/database-preconnect-service.js";import{KvService as g}from"../persistence/kv/services/kv-service.js";import{runScorecardsWorker as O}from"../plugins/scorecards/workers/run-scorecards-worker.js";import{isScorecardsEnabled as E}from"../utils/is-scorecards-enabled.js";import{isRealmOrReef as b}from"../utils/is-realm-or-reef.js";async function J(r,i,a){p.initialize(!0);const{port:m=4e3}=a,t=l();if(t.get(c.EJECT_COMPONENT,D(r)),f(t,r),v(t,r,{readStaticAsset:u,resolveRouteData:e=>r.resolveRouteStaticData(e,i)}),b()){await w.init(r.serverOutDir);const e=await g.getInstance({baseDbDir:r.serverOutDir});setInterval(()=>{e.clearExpired().catch(o=>{s.error("Failed to clear expired KV entries",o)})},300*1e3)}try{await r.userCodeReady;const e=await d(t,m),o=R(e);S(r,o),E(r.config)&&await O(r.serverOutDir,r.config.scorecards)}catch(e){await n.panic(e)}}export{J as startDevServer};
1
+ import{ServerRoutes as c}from"../../constants/api.js";import{reporter as n}from"../tools/notifiers/reporter.js";import{logger as s}from"../tools/notifiers/logger.js";import{telemetry as p}from"../telemetry/index.js";import{installDevRoutes as f,installProdRoutes as l}from"./routes/index.js";import{createRouter as v}from"./router.js";import{readStaticAsset as u}from"./node-asset-reader.js";import{createLlmsTxtGenerator as d}from"../plugins/search/llmstxt/create-llms-txt-generator.js";import{startHttpServer as S}from"./http.js";import{listenStore as D}from"./store-ws.js";import{ejectComponentDataHandler as R}from"./routes/eject.js";import{attachWsServer as w}from"./ws.js";import{DatabasePreconnectService as g}from"../providers/database/database-preconnect-service.js";import{KvService as O}from"../persistence/kv/services/kv-service.js";import{runScorecardsWorker as E}from"../plugins/scorecards/workers/run-scorecards-worker.js";import{isScorecardsEnabled as b}from"../utils/is-scorecards-enabled.js";import{isRealmOrReef as x}from"../utils/is-realm-or-reef.js";async function L(r,i,a){p.initialize(!0);const{port:m=4e3}=a,t=v();if(t.get(c.EJECT_COMPONENT,R(r)),f(t,r),l(t,r,{readStaticAsset:u,resolveRouteData:e=>r.resolveRouteStaticData(e,i),llmsTxtGenerator:d(r,i)}),x()){await g.init(r.serverOutDir);const e=await O.getInstance({baseDbDir:r.serverOutDir});setInterval(()=>{e.clearExpired().catch(o=>{s.error("Failed to clear expired KV entries",o)})},300*1e3)}try{await r.userCodeReady;const e=await S(t,m),o=w(e);D(r,o),b(r.config)&&await E(r.serverOutDir,r.config.scorecards)}catch(e){await n.panic(e)}}export{L as startDevServer};
@@ -1 +1 @@
1
- import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_CREDENTIALS_HANDLER_ID as i,MCP_DOCS_SERVER_HANDLER_ID as u}from"../plugins/mcp/index.js";import{handleMcpRequest as d}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===u||r.requestHandlerId===i?await d(r,s,a):await m(r,s,a);return n.infoTime(e,`API request handled "${new URL(s.req.url).pathname}" with status "${t.status}" and content type "${t.headers?.get("content-type")}"`),t.headers.set("X-Source","REALM_API_FUNCTION"),t}catch(e){return n.error(`[${r.requestHandlerId}] ${e.stack}`),e.name==="RequestBodySizeLimitError"?s.json({message:e.message},{status:413}):e.name==="ResponseSizeLimitError"?s.json({message:e.message},{status:500}):e.name==="MemoryUsageLimitError"?s.json({message:e.message},{status:502}):e.name==="TimeoutExceededError"?s.json({message:e.message},{status:504}):o.isDevelopMode?s.json({message:e.message},{status:500}):s.json({message:"Internal server error"},{status:500})}}export{l as handleApiRouteRequest};
1
+ import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_CREDENTIALS_HANDLER_ID as i,MCP_DOCS_SERVER_HANDLER_ID as u}from"../constants/mcp.js";import{handleMcpRequest as d}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===u||r.requestHandlerId===i?await d(r,s,a):await m(r,s,a);return n.infoTime(e,`API request handled "${new URL(s.req.url).pathname}" with status "${t.status}" and content type "${t.headers?.get("content-type")}"`),t.headers.set("X-Source","REALM_API_FUNCTION"),t}catch(e){return n.error(`[${r.requestHandlerId}] ${e.stack}`),e.name==="RequestBodySizeLimitError"?s.json({message:e.message},{status:413}):e.name==="ResponseSizeLimitError"?s.json({message:e.message},{status:500}):e.name==="MemoryUsageLimitError"?s.json({message:e.message},{status:502}):e.name==="TimeoutExceededError"?s.json({message:e.message},{status:504}):o.isDevelopMode?s.json({message:e.message},{status:500}):s.json({message:"Internal server error"},{status:500})}}export{l as handleApiRouteRequest};
@@ -1 +1 @@
1
- import{DEFAULT_SEARCH_ENGINE as r}from"@redocly/config";import{logger as e}from"../../tools/notifiers/logger.js";import{SearchEngine as t}from"../../plugins/search/engines/search-engine.js";function E(a){return async(o,i)=>{if(!a.searchEngine&&!a.config?.search?.hide){e.info("Loading search data...");const c=a.config?.search?.engine??r,n=new t(c,a.globalData.l10n);await n.initIndexSchema(a.searchFacets),await n.import(a.outdir),a.setSearchEngine(n),e.info("Search data loaded")}await i()}}export{E as ensureSearchData};
1
+ import{DEFAULT_SEARCH_ENGINE as t}from"@redocly/config";import{logger as c}from"../../tools/notifiers/logger.js";import{SearchEngine as o}from"../../plugins/search/engines/search-engine.js";function f(a){let e;const r=async()=>{c.info("Loading search data...");const i=a.config?.search?.engine??t,n=new o(i,a.globalData.l10n);await n.initIndexSchema(a.searchFacets),await n.import(a.outdir),a.setSearchEngine(n),c.info("Search data loaded")};return async(i,n)=>{!a.searchEngine&&!a.config?.search?.hide&&(e??=r().finally(()=>{e=void 0}),await e),await n()}}export{f as ensureSearchData};
@@ -1,5 +1,6 @@
1
1
  import type { Handler } from 'hono';
2
2
  import type { Store } from '../../store';
3
+ export declare const AI_ASSISTANT_IDENTITY_STATUS_HEADER = "x-redocly-ai-assistant-identity-status";
3
4
  export declare function askAiHandler(store: Store): Handler;
4
5
  /**
5
6
  * Ticket submissions from the embedded assistant. Proxied for the portal's own org/project so the
@@ -1 +1 @@
1
- import{RbacFeatures as c}from"../../../constants/common.js";import{ASK_AI_API_URL as u,AI_ASSISTANT_ESCALATIONS_API_URL as A,AI_ASSISTANT_FEEDBACK_API_URL as p}from"../../constants/common.js";import{fetchWithClient as f}from"../../utils/fetch-with-client.js";import{canAccessFeature as h}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as d}from"../utils.js";import{isAiSearchEnabled as l}from"../../plugins/search/utils.js";function m(e,n){const r=n.getConfig();return l(r)?h(c.AI_SEARCH,e.get("auth"),r.access?.rbac,r.access?.requiresLogin)?null:d(e):e.newResponse(null,403,{})}function S(e){const n=e.get("auth"),r={"Content-Type":"application/json"},t=[];n.claims?.authCookie&&t.push(`authorization=${n.claims.authCookie}`),n.idpAccessToken&&t.push(`accessToken=${n.idpAccessToken}`),t.length>0&&(r.Cookie=t.join("; "));const i=e.req.header("Authorization");return i&&(r.Authorization=i),r}const g="x-redocly-ai-assistant-origin";function _(e){const n=e.req.header("Origin");if(n)return n;const r=e.req.header("Referer");if(r)try{return new URL(r).origin}catch{}return new URL(e.req.url).origin}function s({store:e,apiUrl:n,successContentType:r="application/json"}){return async t=>{if(!n)return t.newResponse(null,404);const i=m(t,e);if(i)return i;const a=S(t);a[g]=_(t);const o=await f(n,{method:"POST",body:JSON.stringify(await t.req.json()),headers:a});return t.newResponse(o.body,o.status,{"Content-Type":o.ok?r:"application/json"})}}function E(e){return s({store:e,apiUrl:u,successContentType:"text/event-stream"})}function b(e){return s({store:e,apiUrl:A})}function w(e){return s({store:e,apiUrl:p})}export{b as aiAssistantEscalationsHandler,w as aiAssistantFeedbackHandler,E as askAiHandler};
1
+ import{RbacFeatures as d}from"../../../constants/common.js";import{ASK_AI_API_URL as h,AI_ASSISTANT_ESCALATIONS_API_URL as p,AI_ASSISTANT_FEEDBACK_API_URL as f}from"../../constants/common.js";import{fetchWithClient as l}from"../../utils/fetch-with-client.js";import{canAccessFeature as S}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as T}from"../utils.js";import{isAiSearchEnabled as I}from"../../plugins/search/utils.js";function _(e,t){const n=t.getConfig();return I(n)?S(d.AI_SEARCH,e.get("auth"),n.access?.rbac,n.access?.requiresLogin)?null:T(e):e.newResponse(null,403,{})}function g(e){const t=e.get("auth"),n={"Content-Type":"application/json"},r=[];t.claims?.authCookie&&r.push(`authorization=${t.claims.authCookie}`),t.idpAccessToken&&r.push(`accessToken=${t.idpAccessToken}`),r.length>0&&(n.Cookie=r.join("; "));const i=e.req.header("Authorization");i&&(n.Authorization=i);const s=e.req.header(u);return s&&(n[u]=s),n}const m="x-redocly-ai-assistant-origin",u="x-redocly-ai-assistant-identity",A="x-redocly-ai-assistant-identity-status";function y(e){const t=e.req.header("Origin");if(t)return t;const n=e.req.header("Referer");if(n)try{return new URL(n).origin}catch{}return new URL(e.req.url).origin}function a({store:e,apiUrl:t,successContentType:n="application/json"}){return async r=>{if(!t)return r.newResponse(null,404);const i=_(r,e);if(i)return i;const s=g(r);s[m]=y(r);const o=await l(t,{method:"POST",body:JSON.stringify(await r.req.json()),headers:s}),c=o.headers.get(A);return r.newResponse(o.body,o.status,{"Content-Type":o.ok?n:"application/json",...c?{[A]:c}:{}})}}function U(e){return a({store:e,apiUrl:h,successContentType:"text/event-stream"})}function b(e){return a({store:e,apiUrl:p})}function q(e){return a({store:e,apiUrl:f})}export{A as AI_ASSISTANT_IDENTITY_STATUS_HEADER,b as aiAssistantEscalationsHandler,q as aiAssistantFeedbackHandler,U as askAiHandler};
@@ -1 +1 @@
1
- import{setCookie as L,deleteCookie as U}from"hono/cookie";import{AuthProviderType as Q,DEFAULT_TEAM_CLAIM_NAME as x}from"@redocly/config";import{withPathPrefix as O,getPathPrefix as C}from"@redocly/theme/core/utils";import{compareURIs as ee}from"../../../utils/url/compare-uris.js";import{ensureArray as N}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as H,JWT_SECRET_KEY as v,ORG_SLUG as re,ORG_ID as oe}from"../../constants/common.js";import{AUTH_SEGMENT as ne,ServerRoutes as P}from"../../../constants/api.js";import{AuthCookieNames as _,DEFAULT_COOKIE_EXPIRATION as B}from"../../../constants/common.js";import{sanitizeRedirectPathname as K}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as T}from"../../telemetry/index.js";import{envConfig as j}from"../../config/env-config.js";import{fetchWithClient as te}from"../../utils/fetch-with-client.js";import{clearAuthCookies as z,clearPostLogoutCookie as $,hasPostLogoutCookie as se,setPostLogoutCookie as G}from"../../utils/cookie.js";import{getAuthProviderLoginParams as ie,isOidcProviderConfig as b,isSaml2ProviderConfig as ae,oidcExchangeCodeForToken as de,buildLoginUrl as ce,decodeSamlResponse as le,extractUserClaims as ue,parseSamlResponse as pe,parseOidcState as ge,verifySAMLResponse as fe,getUsernameFromPayload as me,buildOidcLogoutUrl as he,getOidcMetadata as J,getRedoclyTokenPayload as Re,isRedoclySso as _e,rewritePreviewAuthRedirectUri as Ie,parsePreviewBranch as Z,buildOidcLoginUrl as Ce,createMcpSessionResource as D}from"../auth.js";import*as k from"../jwt/jwt.js";import{AlgorithmTypes as E}from"../jwt/types.js";import{handleErrorPageRender as Ae}from"../utils.js";import{encodeBase64URL as we}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as Le}from"./helpers/resolve-ui-locales-for-idp-login.js";async function Ke(s){if(j.isProductionEnv)return s.newResponse(null,404,{});const{password:e,...r}=await s.req.json(),a=await k.sign({...r,name:r.username||r.email||"Unknown"},v,E.HS256);return L(s,_.AUTHORIZATION,a,{path:C()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),$(s),s.newResponse(null,200,{})}function je(){return async s=>{const e=s.get("logger"),r=encodeURIComponent(s.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${P.LOGIN}/?error=${encodeURIComponent(r)}`;return s.newResponse(null,301,{Location:a})}}function V(s){if(!s||!s.includes(P.MCP_CALLBACK))return null;try{const e=s.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function ze(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=ge(e.req.query("state")),m=o.idpId,t=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK),l=t?V(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,i=a?.[m];if(!b(i))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await J(m,i);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,u=e.req.query("code"),h=e.req.query("error");if(h)return t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:`OIDC error: ${h}`,error_details:e.req.query("error_description")||null}]),Ae(e,s,{slug:"/"},403,"403OIDC");if(!u){const I="Code is expected but not present";return r.error(`OIDC login error: ${I}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:I,error_details:null}]),new Response(`Forbidden: ${I}`,{status:403})}const w=typeof o.redirectUri=="string"?o.redirectUri:new URL(O(P.OIDC_CALLBACK),e.req.url).toString(),R=e.get("cookies")?.code_verifier,c=await de(p,u,w,i,{...i.tokenRequestCustomParams,...R?{code_verifier:R}:{}});if(c.error)return r.error(`Error from OIDC provider: "${c.error}"`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:`Token exchange error: ${c.error}`,error_details:c.error_description||null}]),e.text(`Forbidden: ${c.error_description||c.error}`,403);if(!c?.id_token){const I="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${I}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:I,error_details:null}]),new Response(`Forbidden: ${I}`,{status:403})}const{payload:f,header:M}=k.decode(c.id_token),n=M.alg===E.RS256;if(i.audience?.length&&![...N(f.aud||[]),...N(f[H]||[])].some(y=>i.audience?.includes(y))){const y="No valid audience found in id_token";return r.error(`OIDC login error: ${y}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:y,error_details:null}]),new Response(`Forbidden: ${y}`)}const g=n?c.id_token:await k.sign({...f,idpId:m},v,E.HS256);me(f)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const S=i?.tokenExpirationTime?Date.now()+i.tokenExpirationTime*1e3:f.exp*1e3||Date.now()+B*1e3;if(i.introspectEndpoint){const I=await fetch(i.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:c.access_token})});if(I.ok){const q=(await I.json()).ext?.federatedIdentity;q&&(L(e,_.FEDERATED_ACCESS_TOKEN,q.access_token||"",{path:C()||"/",httpOnly:!1,expires:new Date(S)}),L(e,_.FEDERATED_ID_TOKEN,q.id_token||"",{path:C()||"/",httpOnly:!1,expires:new Date(S)}))}else r.warn(`OIDC introspect error: ${I.statusText}`)}if(L(e,_.AUTHORIZATION,g,{path:C()||"/",httpOnly:!0,expires:new Date(S)}),g!==c.id_token&&L(e,_.IDP_ID_TOKEN,c.id_token||"",{path:C()||"/",httpOnly:!0,expires:new Date(S)}),L(e,_.IDP_ACCESS_TOKEN,c.access_token||"",{path:C()||"/",httpOnly:!0,expires:new Date(S)}),c.refresh_token?L(e,_.IDP_REFRESH_TOKEN,c.refresh_token,{path:C()||"/",httpOnly:!0,expires:new Date(S)}):U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),U(e,"code_verifier",{path:C()||"/"}),$(e),t&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK)){const y=`${e.req.url.split("?")[0].replace(P.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:y})}const W=typeof o.redirectTo=="string"?o.redirectTo:void 0;let X=K(new URL(W||"/",e.req.url).pathname);const Y=e.newResponse(null,302,{Location:X});return r.updateContext({email:f.email,subject:f.sub}),r.info("OIDC login successful"),Y}catch(p){const u=p instanceof Error?p.message:String(p),h=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${u}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:u,error_details:h}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const A="Something went wrong";return r.error(`OIDC login error: ${A}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:A,error_details:null}]),e.text(A,500)}}function Ge(s){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,t=s.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return b(t)||(z(e),G(e)),r.info("Logout successful"),e.newResponse(null,200,{});let l;if(b(t)){const i=(await J(o,t)).end_session_endpoint;if(i){const d=new URL(e.req.url),A=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,u=`${A}://${p}`,h=Z(u),w=h?we(JSON.stringify({branch:Z(u)})):void 0,R=h?`${Ie(u)}/${ne}/logout`:`${u}${O(P.POST_LOGOUT)}`;l=he(i,R,e.get("cookies")?.[_.IDP_ID_TOKEN]||e.get("cookies")?.[_.AUTHORIZATION]||"",w)}}return r.info("Logout successful"),z(e),G(e),e.newResponse(null,302,{Location:l||O("/")})}}function Je(s){return async e=>{const r=s.getConfig().access?.logoutReturnUrl,a=r||O("/");return e.newResponse(null,302,{Location:a})}}function Ze(s){return async e=>{const r=e.get("logger"),a=e.req.param("code"),o=j.BH_API_URL,m=(t,l,i)=>t&&l?`${t} ${l.charAt(0)}`:i;try{if(!o)throw new Error("BH_API_URL is not set");const t=s.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(O("/"));const l=await te(`${o}/public-user-invites/${a}`);if(!l.ok)return l.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(O("/"))):(r.error("Invite error",await l.text()),e.redirect(O("/")));const i=await l.json(),d=new URL(O("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",i.organization.name),d.searchParams.set("invitedBy",m(i.invitedBy.firstName,i.invitedBy.lastName,i.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Ve(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=new URL(e.req.url),m=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",l=e.req.header("x-forwarded-host")||o.host,i=`${t}://${l}`;let d=o.searchParams.get("idpId");const A=o.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const u=o.searchParams.get("mcp_redirect_uri"),h=!!u;if(!a?.[d]){const g="Invalid idpId";if(r.error(`IdP login error: ${g}`),h){const F=V(A||void 0);T.sendMcpAuthorizationFailedMessage([{...D(F),error:g,error_details:null}])}return e.text(`Forbidden: ${g}`,403)}const R=Le({localePrefixParam:o.searchParams.get("localePrefix"),l10n:s.getGlobalData()?.l10n}),c=d&&a?await ie(d,a[d]):void 0,f={};for(const g of Object.keys(c?.extraParams||{}))f[g]=o.searchParams.get(g)||c?.extraParams?.[g]||void 0;se(e)&&(f.prompt="login",f.post_logout="1");let M,n={};if(h&&u&&c&&c.type===Q.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${u}`);const g=Ce("",{...c,extraParams:f},A,m,{redirectUriOverride:u,sourceOverride:"mcp",branchOverride:void 0,uiLocales:R});M=g.loginUrl,n=g.cookies||{}}else if(c){const g=ce({...c,extraParams:f},i,A,m,R);M=g.loginUrl,n=g.cookies||{}}return Object.keys(n).forEach(g=>{L(e,g,n[g].value,n[g].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:M||new URL(e.req.url).pathname})}}function We(s){return async e=>{const r=e.get("logger"),a=await e.req.formData(),o=a.get("SAMLResponse"),m=a.get("RelayState");if(typeof o!="string"||typeof m!="string"){const n="SAMLResponse is required";return r.error(`SAML2 login error: ${n}`),e.text(`Bad request: ${n}`,400)}const t=le(o),{success:l,uid:i,nameFormat:d,attrs:A,issuerId:p,expiresAt:u}=pe(t),{idpId:h,redirectTo:w}=JSON.parse(m);if(!l){const n="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!u||Math.ceil(Date.now()/1e3)>=u){const n="SAML2 Token Expired";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const R=s.getConfig().ssoDirect?.[h];if(!R||!ae(R)){const n="Cannot find valid IdP";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!(R.issuerId&&p&&ee(R.issuerId,p))){const n="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!await fe(t,R.x509PublicCert)){const n="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const f=ue(i,d,A,R.teamsAttributeName??x);if(!f.sub){const n="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}if(!f.email){const n="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}const M=await k.sign({...f,idpId:h},v,E.HS256);return L(e,_.AUTHORIZATION,M,{path:C()||"/",httpOnly:!0,expires:new Date(u*1e3)}),U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),$(e),r.updateContext({email:f.email,subject:f.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:w||"/"})}}function Xe(s){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),o=O(K(a.pathname)),m=s.getConfig().ssoDirect,t=Object.entries(m||{}).find(([,w])=>b(w)&&_e(w));if(!(m&&t))return e.newResponse(null,302,{Location:o});const i=e.req.query("token"),d=i&&await Re(i);if(!d)return e.newResponse(null,302,{Location:o});if(!N(d[H]||[]).some(w=>w===re||w===oe))return e.newResponse(null,302,{Location:o});const u=await k.sign({...d,idpId:t?.at(0)},v,E.HS256),h=Date.now()+B*1e3;return L(e,_.AUTHORIZATION,u,{path:C()||"/",httpOnly:!0,expires:new Date(h),sameSite:"None",secure:!0}),U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),$(e),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{Ke as authorizeHandler,Ve as idpLoginHandler,Ze as inviteHandler,Ge as logoutHandler,ze as oidcCallbackHandler,Je as postLogoutHandler,je as redoclyLoginCallbackHandler,Xe as redoclyTokenLoginHandler,We as samlCallbackHandler};
1
+ import{setCookie as L,deleteCookie as P}from"hono/cookie";import{AuthProviderType as ee,DEFAULT_TEAM_CLAIM_NAME as re}from"@redocly/config";import{withPathPrefix as w,getPathPrefix as A}from"@redocly/theme/core/utils";import{compareURIs as oe}from"../../../utils/url/compare-uris.js";import{ensureArray as N}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as H,JWT_SECRET_KEY as U,MAX_AUTH_TOKEN_COOKIE_BYTES as F,ORG_SLUG as te,ORG_ID as ne}from"../../constants/common.js";import{AUTH_SEGMENT as ie,ServerRoutes as D}from"../../../constants/api.js";import{AuthCookieNames as _,DEFAULT_COOKIE_EXPIRATION as K}from"../../../constants/common.js";import{sanitizeRedirectPathname as z}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as k}from"../../telemetry/index.js";import{envConfig as j}from"../../config/env-config.js";import{fetchWithClient as se}from"../../utils/fetch-with-client.js";import{clearAuthCookies as J,clearPostLogoutCookie as v,hasPostLogoutCookie as ae,setPostLogoutCookie as G}from"../../utils/cookie.js";import{getAuthProviderLoginParams as de,isOidcProviderConfig as b,isSaml2ProviderConfig as le,oidcExchangeCodeForToken as ce,buildLoginUrl as ue,decodeSamlResponse as pe,extractUserClaims as ge,parseSamlResponse as fe,parseOidcState as me,verifySAMLResponse as he,getUsernameFromPayload as Ce,buildOidcLogoutUrl as Ie,isIdpIssuedToken as _e,getOidcMetadata as Z,getRedoclyTokenPayload as Ae,isRedoclySso as Re,rewritePreviewAuthRedirectUri as Oe,parsePreviewBranch as V,buildOidcLoginUrl as Te,createMcpSessionResource as M,signTokenWithinCookieSizeLimit as W}from"../auth.js";import*as E from"../jwt/jwt.js";import{AlgorithmTypes as $}from"../jwt/types.js";import{handleErrorPageRender as ye}from"../utils.js";import{encodeBase64URL as Le}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as we}from"./helpers/resolve-ui-locales-for-idp-login.js";async function Je(n){if(j.isProductionEnv)return n.newResponse(null,404,{});const{password:e,...r}=await n.req.json(),d=await E.sign({...r,name:r.username||r.email||"Unknown"},U,$.HS256);return L(n,_.AUTHORIZATION,d,{path:A()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),v(n),n.newResponse(null,200,{})}function Ge(){return async n=>{const e=n.get("logger"),r=encodeURIComponent(n.req.query("message")||"");e.error(`Login error: ${r}`);const d=`${D.LOGIN}/?error=${encodeURIComponent(r)}`;return n.newResponse(null,301,{Location:d})}}function X(n){if(!n||!n.includes(D.MCP_CALLBACK))return null;try{const e=n.split("/"),r=e[e.length-1];if(r){const d=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(d).mcpSessionId||null}}catch{}return null}function Ze(n){return async e=>{const r=e.get("logger"),d=n.getConfig().ssoDirect;let o;try{o=me(e.req.query("state"))}catch{return r.warn("OIDC login error: Invalid OAuth2 state"),e.text("Bad request: Invalid OAuth2 state",400)}const h=o.idpId,i=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(D.MCP_CALLBACK),u=i?X(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,s=d?.[h];if(!b(s))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const p=await Z(h,s);if(d&&!p.token_endpoint){const m="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${m}`),e.text(m,500)}try{const m=p.token_endpoint,g=e.req.query("code"),C=e.req.query("error");if(C)return i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:`OIDC error: ${C}`,error_details:e.req.query("error_description")||null}]),ye(e,n,{slug:"/"},403,"403OIDC");if(!g){const f="Code is expected but not present";return r.error(`OIDC login error: ${f}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:f,error_details:null}]),new Response(`Forbidden: ${f}`,{status:403})}const O=typeof o.redirectUri=="string"?o.redirectUri:new URL(w(D.OIDC_CALLBACK),e.req.url).toString(),I=e.get("cookies")?.code_verifier,a=await ce(m,g,O,s,{...s.tokenRequestCustomParams,...I?{code_verifier:I}:{}});if(a.error)return r.error(`Error from OIDC provider: "${a.error}"`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:`Token exchange error: ${a.error}`,error_details:a.error_description||null}]),e.text(`Forbidden: ${a.error_description||a.error}`,403);if(!a?.id_token){const f="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${f}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:f,error_details:null}]),new Response(`Forbidden: ${f}`,{status:403})}const{payload:l,header:y}=E.decode(a.id_token),t=y.alg===$.RS256;if(s.audience?.length&&![...N(l.aud||[]),...N(l[H]||[])].some(T=>s.audience?.includes(T))){const T="No valid audience found in id_token";return r.error(`OIDC login error: ${T}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:T,error_details:null}]),new Response(`Forbidden: ${T}`)}let c=t?a.id_token:await E.sign({...l,idpId:h},U,$.HS256);if(Buffer.byteLength(c)>F){const f=await W(l,h,s.teamsClaimName,{rbacConfig:n.getConfig().access?.rbac,teamsMapping:s.teamsClaimMap});if(!f){const T=`The id_token claims are too large for the session cookie: ${Buffer.byteLength(JSON.stringify(l))} bytes of claims`;return r.error(`OIDC login error: ${T}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:T,error_details:null}]),e.text(`Forbidden: ${T}`,403)}f.teamsKept<f.teamsTotal&&r.warn(`OIDC login: the "${s.teamsClaimName}" claim is too large for the session cookie size limit; kept ${f.teamsKept} of ${f.teamsTotal} values, with teams from the RBAC configuration first; RBAC ignores the dropped teams: ${JSON.stringify(f.droppedTeams)}`),c=f.token}Ce(l)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const S=s?.tokenExpirationTime?Date.now()+s.tokenExpirationTime*1e3:l.exp*1e3||Date.now()+K*1e3;if(s.introspectEndpoint){const f=await fetch(s.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:a.access_token})});if(f.ok){const q=(await f.json()).ext?.federatedIdentity;q&&(L(e,_.FEDERATED_ACCESS_TOKEN,q.access_token||"",{path:A()||"/",httpOnly:!1,expires:new Date(S)}),L(e,_.FEDERATED_ID_TOKEN,q.id_token||"",{path:A()||"/",httpOnly:!1,expires:new Date(S)}))}else r.warn(`OIDC introspect error: ${f.statusText}`)}if(L(e,_.AUTHORIZATION,c,{path:A()||"/",httpOnly:!0,expires:new Date(S)}),c!==a.id_token&&Buffer.byteLength(a.id_token)<=F?L(e,_.IDP_ID_TOKEN,a.id_token||"",{path:A()||"/",httpOnly:!0,expires:new Date(S)}):P(e,_.IDP_ID_TOKEN,{path:A()||"/"}),L(e,_.IDP_ACCESS_TOKEN,a.access_token||"",{path:A()||"/",httpOnly:!0,expires:new Date(S)}),a.refresh_token?L(e,_.IDP_REFRESH_TOKEN,a.refresh_token,{path:A()||"/",httpOnly:!0,expires:new Date(S)}):P(e,_.IDP_REFRESH_TOKEN,{path:A()||"/"}),P(e,"code_verifier",{path:A()||"/"}),v(e),i&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(D.MCP_CALLBACK)){const T=`${e.req.url.split("?")[0].replace(D.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:T})}const Y=typeof o.redirectTo=="string"?o.redirectTo:void 0;let Q=z(new URL(Y||"/",e.req.url).pathname);const x=e.newResponse(null,302,{Location:Q});return r.updateContext({email:l.email,subject:l.sub}),r.info("OIDC login successful"),x}catch(m){const g=m instanceof Error?m.message:String(m),C=m instanceof Error?m.stack:String(m);if(r.error(`OIDC login error: ${g}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:g,error_details:C}]),m.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const R="Something went wrong";return r.error(`OIDC login error: ${R}`),i&&k.sendMcpAuthorizationFailedMessage([{...M(u),error:R,error_details:null}]),e.text(R,500)}}function Ve(n){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,i=n.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return b(i)||(J(e),G(e)),r.info("Logout successful"),e.newResponse(null,200,{});let u;if(b(i)){const s=(await Z(o,i)).end_session_endpoint;if(s){const p=new URL(e.req.url),R=e.req.header("x-forwarded-proto")||p.protocol.slice(0,-1)||"https",m=e.req.header("x-forwarded-host")||p.host,g=`${R}://${m}`,C=V(g),O=C?Le(JSON.stringify({branch:V(g)})):void 0,I=C?`${Oe(g)}/${ie}/logout`:`${g}${w(D.POST_LOGOUT)}`,a=e.get("cookies"),l=a?.[_.AUTHORIZATION],y=a?.[_.IDP_ID_TOKEN]||(_e(l)?l:void 0);u=Ie(s,I,y,O)}}return r.info("Logout successful"),J(e),G(e),e.newResponse(null,302,{Location:u||w("/")})}}function We(n){return async e=>{const r=n.getConfig().access?.logoutReturnUrl,d=r||w("/");return e.newResponse(null,302,{Location:d})}}function Xe(n){return async e=>{const r=e.get("logger"),d=e.req.param("code"),o=j.BH_API_URL,h=(i,u,s)=>i&&u?`${i} ${u.charAt(0)}`:s;try{if(!o)throw new Error("BH_API_URL is not set");const i=n.getConfig().ssoDirect;if(!i||!Object.keys(i).length)return r.warn("Invite no sso configured to handle"),e.redirect(w("/"));const u=await se(`${o}/public-user-invites/${d}`);if(!u.ok)return u.status===404?(r.warn(`Invite ${d} not found redirect to homepage`),e.redirect(w("/"))):(r.error("Invite error",await u.text()),e.redirect(w("/")));const s=await u.json(),p=new URL(w("/invite"),e.req.url);return p.searchParams.set("code",d),p.searchParams.set("org",s.organization.name),p.searchParams.set("invitedBy",h(s.invitedBy.firstName,s.invitedBy.lastName,s.invitedBy.name)),e.newResponse(null,302,{Location:p.toString()})}catch(i){return r.error("Error processing invite",{error:i,inviteCode:d}),e.text(i.message||"Failed to process invite",400)}}}function Ye(n){return async e=>{const r=e.get("logger"),d=n.getConfig().ssoDirect,o=new URL(e.req.url),h=e.req.query("inviteCode"),i=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",u=e.req.header("x-forwarded-host")||o.host,s=`${i}://${u}`;let p=o.searchParams.get("idpId");const R=o.searchParams.get("redirectTo"),m=Object.keys(d||{})[0];p=p||m;const g=o.searchParams.get("mcp_redirect_uri"),C=!!g;if(!d?.[p]){const c="Invalid idpId";if(r.error(`IdP login error: ${c}`),C){const B=X(R||void 0);k.sendMcpAuthorizationFailedMessage([{...M(B),error:c,error_details:null}])}return e.text(`Forbidden: ${c}`,403)}const I=we({localePrefixParam:o.searchParams.get("localePrefix"),l10n:n.getGlobalData()?.l10n}),a=p&&d?await de(p,d[p]):void 0,l={};for(const c of Object.keys(a?.extraParams||{}))l[c]=o.searchParams.get(c)||a?.extraParams?.[c]||void 0;ae(e)&&(l.prompt="login",l.post_logout="1");let y,t={};if(C&&g&&a&&a.type===ee.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${g}`);const c=Te("",{...a,extraParams:l},R,h,{redirectUriOverride:g,sourceOverride:"mcp",branchOverride:void 0,uiLocales:I});y=c.loginUrl,t=c.cookies||{}}else if(a){const c=ue({...a,extraParams:l},s,R,h,I);y=c.loginUrl,t=c.cookies||{}}return Object.keys(t).forEach(c=>{L(e,c,t[c].value,t[c].options)}),r.info(`IdP login initiated for ID '${p}'`),e.newResponse(null,302,{Location:y||new URL(e.req.url).pathname})}}function Qe(n){return async e=>{const r=e.get("logger"),d=await e.req.formData(),o=d.get("SAMLResponse"),h=d.get("RelayState");if(typeof o!="string"||typeof h!="string"){const t="SAMLResponse is required";return r.error(`SAML2 login error: ${t}`),e.text(`Bad request: ${t}`,400)}const i=pe(o),{success:u,uid:s,nameFormat:p,attrs:R,issuerId:m,expiresAt:g}=fe(i),{idpId:C,redirectTo:O}=JSON.parse(h);if(!u){const t="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${t}`),e.text(`Permission denied: ${t}`,401)}if(!g||Math.ceil(Date.now()/1e3)>=g){const t="SAML2 Token Expired";return r.error(`SAML2 login error: ${t}`),e.text(t,401)}const I=n.getConfig().ssoDirect?.[C];if(!I||!le(I)){const t="Cannot find valid IdP";return r.error(`SAML2 login error: ${t}`),e.text(`Permission denied: ${t}`,401)}if(!(I.issuerId&&m&&oe(I.issuerId,m))){const t="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${t}`),e.text(`Permission denied: ${t}`,401)}if(!await he(i,I.x509PublicCert)){const t="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${t}`),e.text(t,401)}const l=ge(s,p,R,I.teamsAttributeName??re);if(!l.sub){const t="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${t}`),e.text(t,400)}if(!l.email){const t="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${t}`),e.text(t,400)}let y=await E.sign({...l,idpId:C},U,$.HS256);if(Buffer.byteLength(y)>F){const t=await W({...l},C,"teams",{rbacConfig:n.getConfig().access?.rbac,teamsMapping:I.teamsAttributeMap});if(!t){const c=`The SAML2 claims are too large for the session cookie: ${Buffer.byteLength(JSON.stringify(l))} bytes of claims`;return r.error(`SAML2 login error: ${c}`),e.text(`Forbidden: ${c}`,403)}t.teamsKept<t.teamsTotal&&r.warn(`SAML2 login: the "teams" claim is too large for the session cookie size limit; kept ${t.teamsKept} of ${t.teamsTotal} values, with teams from the RBAC configuration first; RBAC ignores the dropped teams: ${JSON.stringify(t.droppedTeams)}`),y=t.token}return L(e,_.AUTHORIZATION,y,{path:A()||"/",httpOnly:!0,expires:new Date(g*1e3)}),P(e,_.IDP_REFRESH_TOKEN,{path:A()||"/"}),v(e),r.updateContext({email:l.email,subject:l.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:O||"/"})}}function xe(n){return async e=>{const r=e.get("logger"),d=new URL(e.req.query("redirectTo")||"/",e.req.url),o=w(z(d.pathname)),h=n.getConfig().ssoDirect,i=Object.entries(h||{}).find(([,O])=>b(O)&&Re(O));if(!(h&&i))return e.newResponse(null,302,{Location:o});const s=e.req.query("token"),p=s&&await Ae(s);if(!p)return e.newResponse(null,302,{Location:o});if(!N(p[H]||[]).some(O=>O===te||O===ne))return e.newResponse(null,302,{Location:o});const g=await E.sign({...p,idpId:i?.at(0)},U,$.HS256),C=Date.now()+K*1e3;return L(e,_.AUTHORIZATION,g,{path:A()||"/",httpOnly:!0,expires:new Date(C),sameSite:"None",secure:!0}),P(e,_.IDP_REFRESH_TOKEN,{path:A()||"/"}),v(e),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{Je as authorizeHandler,Ye as idpLoginHandler,Xe as inviteHandler,Ve as logoutHandler,Ze as oidcCallbackHandler,We as postLogoutHandler,Ge as redoclyLoginCallbackHandler,xe as redoclyTokenLoginHandler,Qe as samlCallbackHandler};
@@ -1,5 +1,6 @@
1
1
  import type { Handler } from 'hono';
2
2
  import type { Store } from '../../store';
3
3
  import type { RouteDataResolver, StaticAssetReader } from './index';
4
- export declare function dynamicRouteHandler(store: Store, resolveRouteData: RouteDataResolver, readStaticAsset: StaticAssetReader): Handler;
4
+ import type { LlmsTxtGenerator } from '../../types';
5
+ export declare function dynamicRouteHandler(store: Store, resolveRouteData: RouteDataResolver, readStaticAsset: StaticAssetReader, llmsTxtGenerator?: LlmsTxtGenerator): Handler;
5
6
  //# sourceMappingURL=dynamic-route.d.ts.map