@robelest/convex-auth 0.0.4-preview.21 → 0.0.4-preview.23

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 (310) hide show
  1. package/dist/authorization/index.d.ts +1 -1
  2. package/dist/authorization/index.js +1 -1
  3. package/dist/authorization/index.js.map +1 -1
  4. package/dist/client/index.d.ts +1 -2
  5. package/dist/client/index.d.ts.map +1 -1
  6. package/dist/client/index.js +36 -39
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/component/client/index.d.ts +1 -2
  9. package/dist/component/convex.config.d.ts +2 -2
  10. package/dist/component/convex.config.d.ts.map +1 -1
  11. package/dist/component/model.d.ts +5 -5
  12. package/dist/component/model.d.ts.map +1 -1
  13. package/dist/component/public/enterprise/audit.d.ts.map +1 -1
  14. package/dist/component/public/enterprise/audit.js.map +1 -1
  15. package/dist/component/public/enterprise/core.d.ts.map +1 -1
  16. package/dist/component/public/enterprise/core.js.map +1 -1
  17. package/dist/component/public/enterprise/domains.d.ts.map +1 -1
  18. package/dist/component/public/enterprise/domains.js.map +1 -1
  19. package/dist/component/public/enterprise/scim.d.ts.map +1 -1
  20. package/dist/component/public/enterprise/scim.js.map +1 -1
  21. package/dist/component/public/enterprise/secrets.d.ts.map +1 -1
  22. package/dist/component/public/enterprise/secrets.js.map +1 -1
  23. package/dist/component/public/enterprise/webhooks.d.ts.map +1 -1
  24. package/dist/component/public/enterprise/webhooks.js.map +1 -1
  25. package/dist/component/public/factors/devices.d.ts.map +1 -1
  26. package/dist/component/public/factors/devices.js.map +1 -1
  27. package/dist/component/public/factors/passkeys.d.ts.map +1 -1
  28. package/dist/component/public/factors/passkeys.js.map +1 -1
  29. package/dist/component/public/factors/totp.d.ts.map +1 -1
  30. package/dist/component/public/factors/totp.js.map +1 -1
  31. package/dist/component/public/groups/core.js.map +1 -1
  32. package/dist/component/public/groups/invites.d.ts.map +1 -1
  33. package/dist/component/public/groups/invites.js.map +1 -1
  34. package/dist/component/public/groups/members.d.ts.map +1 -1
  35. package/dist/component/public/groups/members.js.map +1 -1
  36. package/dist/component/public/identity/accounts.d.ts.map +1 -1
  37. package/dist/component/public/identity/accounts.js.map +1 -1
  38. package/dist/component/public/identity/codes.d.ts.map +1 -1
  39. package/dist/component/public/identity/codes.js.map +1 -1
  40. package/dist/component/public/identity/sessions.d.ts.map +1 -1
  41. package/dist/component/public/identity/sessions.js.map +1 -1
  42. package/dist/component/public/identity/tokens.d.ts.map +1 -1
  43. package/dist/component/public/identity/tokens.js.map +1 -1
  44. package/dist/component/public/identity/users.d.ts.map +1 -1
  45. package/dist/component/public/identity/users.js.map +1 -1
  46. package/dist/component/public/identity/verifiers.d.ts.map +1 -1
  47. package/dist/component/public/identity/verifiers.js.map +1 -1
  48. package/dist/component/public/security/keys.d.ts.map +1 -1
  49. package/dist/component/public/security/keys.js.map +1 -1
  50. package/dist/component/public/security/limits.d.ts.map +1 -1
  51. package/dist/component/public/security/limits.js.map +1 -1
  52. package/dist/component/schema.d.ts +39 -39
  53. package/dist/component/server/auth.d.ts +95 -52
  54. package/dist/component/server/auth.d.ts.map +1 -1
  55. package/dist/component/server/auth.js +63 -43
  56. package/dist/component/server/auth.js.map +1 -1
  57. package/dist/component/server/core.js +116 -235
  58. package/dist/component/server/core.js.map +1 -1
  59. package/dist/component/server/crypto.js +25 -7
  60. package/dist/component/server/crypto.js.map +1 -1
  61. package/dist/component/server/device.js +58 -15
  62. package/dist/component/server/device.js.map +1 -1
  63. package/dist/component/server/enterprise/domain.js +148 -59
  64. package/dist/component/server/enterprise/domain.js.map +1 -1
  65. package/dist/component/server/enterprise/http.js +36 -15
  66. package/dist/component/server/enterprise/http.js.map +1 -1
  67. package/dist/component/server/enterprise/oidc.js +1 -1
  68. package/dist/component/server/http.js +26 -21
  69. package/dist/component/server/http.js.map +1 -1
  70. package/dist/component/server/identity.js +5 -2
  71. package/dist/component/server/identity.js.map +1 -1
  72. package/dist/component/server/limits.js +21 -30
  73. package/dist/component/server/limits.js.map +1 -1
  74. package/dist/component/server/mutations/account.js +12 -10
  75. package/dist/component/server/mutations/account.js.map +1 -1
  76. package/dist/component/server/mutations/code.js +5 -2
  77. package/dist/component/server/mutations/code.js.map +1 -1
  78. package/dist/component/server/mutations/invalidate.js +1 -1
  79. package/dist/component/server/mutations/invalidate.js.map +1 -1
  80. package/dist/component/server/mutations/oauth.js +10 -4
  81. package/dist/component/server/mutations/oauth.js.map +1 -1
  82. package/dist/component/server/mutations/refresh.js +2 -2
  83. package/dist/component/server/mutations/refresh.js.map +1 -1
  84. package/dist/component/server/mutations/register.js +46 -42
  85. package/dist/component/server/mutations/register.js.map +1 -1
  86. package/dist/component/server/mutations/retrieve.js +21 -25
  87. package/dist/component/server/mutations/retrieve.js.map +1 -1
  88. package/dist/component/server/mutations/signature.js +10 -4
  89. package/dist/component/server/mutations/signature.js.map +1 -1
  90. package/dist/component/server/mutations/signout.js.map +1 -1
  91. package/dist/component/server/mutations/store.js +9 -24
  92. package/dist/component/server/mutations/store.js.map +1 -1
  93. package/dist/component/server/mutations/verifier.js.map +1 -1
  94. package/dist/component/server/mutations/verify.js +1 -1
  95. package/dist/component/server/mutations/verify.js.map +1 -1
  96. package/dist/component/server/oauth.js +53 -16
  97. package/dist/component/server/oauth.js.map +1 -1
  98. package/dist/component/server/passkey.js +115 -31
  99. package/dist/component/server/passkey.js.map +1 -1
  100. package/dist/component/server/redirects.js +9 -3
  101. package/dist/component/server/redirects.js.map +1 -1
  102. package/dist/component/server/refresh.js +10 -7
  103. package/dist/component/server/refresh.js.map +1 -1
  104. package/dist/component/server/runtime.d.ts +3 -3
  105. package/dist/component/server/runtime.d.ts.map +1 -1
  106. package/dist/component/server/runtime.js +62 -20
  107. package/dist/component/server/runtime.js.map +1 -1
  108. package/dist/component/server/signin.js +34 -10
  109. package/dist/component/server/signin.js.map +1 -1
  110. package/dist/component/server/totp.js +79 -19
  111. package/dist/component/server/totp.js.map +1 -1
  112. package/dist/component/server/types.d.ts +12 -20
  113. package/dist/component/server/types.d.ts.map +1 -1
  114. package/dist/component/server/types.js.map +1 -1
  115. package/dist/component/server/users.js +6 -3
  116. package/dist/component/server/users.js.map +1 -1
  117. package/dist/component/server/utils.js +10 -4
  118. package/dist/component/server/utils.js.map +1 -1
  119. package/dist/core/types.d.ts +14 -22
  120. package/dist/core/types.d.ts.map +1 -1
  121. package/dist/factors/device.js +8 -9
  122. package/dist/factors/device.js.map +1 -1
  123. package/dist/factors/passkey.js +18 -21
  124. package/dist/factors/passkey.js.map +1 -1
  125. package/dist/providers/password.js +66 -81
  126. package/dist/providers/password.js.map +1 -1
  127. package/dist/runtime/invite.js +2 -8
  128. package/dist/runtime/invite.js.map +1 -1
  129. package/dist/server/auth.d.ts +95 -52
  130. package/dist/server/auth.d.ts.map +1 -1
  131. package/dist/server/auth.js +63 -43
  132. package/dist/server/auth.js.map +1 -1
  133. package/dist/server/core.d.ts +71 -159
  134. package/dist/server/core.d.ts.map +1 -1
  135. package/dist/server/core.js +116 -235
  136. package/dist/server/core.js.map +1 -1
  137. package/dist/server/crypto.d.ts.map +1 -1
  138. package/dist/server/crypto.js +25 -7
  139. package/dist/server/crypto.js.map +1 -1
  140. package/dist/server/device.js +58 -15
  141. package/dist/server/device.js.map +1 -1
  142. package/dist/server/enterprise/domain.d.ts +0 -8
  143. package/dist/server/enterprise/domain.d.ts.map +1 -1
  144. package/dist/server/enterprise/domain.js +148 -59
  145. package/dist/server/enterprise/domain.js.map +1 -1
  146. package/dist/server/enterprise/http.d.ts.map +1 -1
  147. package/dist/server/enterprise/http.js +35 -14
  148. package/dist/server/enterprise/http.js.map +1 -1
  149. package/dist/server/http.d.ts +2 -2
  150. package/dist/server/http.d.ts.map +1 -1
  151. package/dist/server/http.js +25 -20
  152. package/dist/server/http.js.map +1 -1
  153. package/dist/server/identity.js +5 -2
  154. package/dist/server/identity.js.map +1 -1
  155. package/dist/server/index.d.ts +2 -2
  156. package/dist/server/limits.js +21 -30
  157. package/dist/server/limits.js.map +1 -1
  158. package/dist/server/mounts.d.ts +26 -64
  159. package/dist/server/mounts.d.ts.map +1 -1
  160. package/dist/server/mounts.js +45 -106
  161. package/dist/server/mounts.js.map +1 -1
  162. package/dist/server/mutations/account.d.ts +8 -9
  163. package/dist/server/mutations/account.d.ts.map +1 -1
  164. package/dist/server/mutations/account.js +11 -9
  165. package/dist/server/mutations/account.js.map +1 -1
  166. package/dist/server/mutations/code.d.ts +13 -13
  167. package/dist/server/mutations/code.d.ts.map +1 -1
  168. package/dist/server/mutations/code.js +5 -2
  169. package/dist/server/mutations/code.js.map +1 -1
  170. package/dist/server/mutations/invalidate.d.ts +4 -4
  171. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  172. package/dist/server/mutations/invalidate.js.map +1 -1
  173. package/dist/server/mutations/oauth.d.ts +12 -10
  174. package/dist/server/mutations/oauth.d.ts.map +1 -1
  175. package/dist/server/mutations/oauth.js +9 -3
  176. package/dist/server/mutations/oauth.js.map +1 -1
  177. package/dist/server/mutations/refresh.d.ts +3 -3
  178. package/dist/server/mutations/refresh.d.ts.map +1 -1
  179. package/dist/server/mutations/refresh.js +1 -1
  180. package/dist/server/mutations/refresh.js.map +1 -1
  181. package/dist/server/mutations/register.d.ts +11 -11
  182. package/dist/server/mutations/register.d.ts.map +1 -1
  183. package/dist/server/mutations/register.js +45 -41
  184. package/dist/server/mutations/register.js.map +1 -1
  185. package/dist/server/mutations/retrieve.d.ts +6 -6
  186. package/dist/server/mutations/retrieve.d.ts.map +1 -1
  187. package/dist/server/mutations/retrieve.js +20 -24
  188. package/dist/server/mutations/retrieve.js.map +1 -1
  189. package/dist/server/mutations/signature.d.ts +6 -7
  190. package/dist/server/mutations/signature.d.ts.map +1 -1
  191. package/dist/server/mutations/signature.js +9 -3
  192. package/dist/server/mutations/signature.js.map +1 -1
  193. package/dist/server/mutations/signin.d.ts +5 -5
  194. package/dist/server/mutations/signin.d.ts.map +1 -1
  195. package/dist/server/mutations/signout.js.map +1 -1
  196. package/dist/server/mutations/store.d.ts +97 -97
  197. package/dist/server/mutations/store.d.ts.map +1 -1
  198. package/dist/server/mutations/store.js +8 -23
  199. package/dist/server/mutations/store.js.map +1 -1
  200. package/dist/server/mutations/verifier.js.map +1 -1
  201. package/dist/server/mutations/verify.d.ts +10 -10
  202. package/dist/server/mutations/verify.d.ts.map +1 -1
  203. package/dist/server/mutations/verify.js.map +1 -1
  204. package/dist/server/oauth.js +53 -16
  205. package/dist/server/oauth.js.map +1 -1
  206. package/dist/server/passkey.d.ts +2 -2
  207. package/dist/server/passkey.d.ts.map +1 -1
  208. package/dist/server/passkey.js +114 -30
  209. package/dist/server/passkey.js.map +1 -1
  210. package/dist/server/redirects.js +9 -3
  211. package/dist/server/redirects.js.map +1 -1
  212. package/dist/server/refresh.js +10 -7
  213. package/dist/server/refresh.js.map +1 -1
  214. package/dist/server/runtime.d.ts +14 -14
  215. package/dist/server/runtime.d.ts.map +1 -1
  216. package/dist/server/runtime.js +61 -19
  217. package/dist/server/runtime.js.map +1 -1
  218. package/dist/server/signin.js +34 -10
  219. package/dist/server/signin.js.map +1 -1
  220. package/dist/server/ssr.d.ts.map +1 -1
  221. package/dist/server/ssr.js +175 -184
  222. package/dist/server/ssr.js.map +1 -1
  223. package/dist/server/totp.js +78 -18
  224. package/dist/server/totp.js.map +1 -1
  225. package/dist/server/types.d.ts +13 -21
  226. package/dist/server/types.d.ts.map +1 -1
  227. package/dist/server/types.js.map +1 -1
  228. package/dist/server/users.js +6 -3
  229. package/dist/server/users.js.map +1 -1
  230. package/dist/server/utils.js +10 -4
  231. package/dist/server/utils.js.map +1 -1
  232. package/package.json +2 -6
  233. package/src/authorization/index.ts +1 -1
  234. package/src/cli/index.ts +1 -1
  235. package/src/client/core/types.ts +14 -14
  236. package/src/client/factors/device.ts +10 -12
  237. package/src/client/factors/passkey.ts +23 -26
  238. package/src/client/index.ts +54 -64
  239. package/src/client/runtime/invite.ts +5 -7
  240. package/src/component/index.ts +1 -0
  241. package/src/component/public/enterprise/audit.ts +6 -1
  242. package/src/component/public/enterprise/core.ts +1 -0
  243. package/src/component/public/enterprise/domains.ts +5 -1
  244. package/src/component/public/enterprise/scim.ts +1 -0
  245. package/src/component/public/enterprise/secrets.ts +1 -0
  246. package/src/component/public/enterprise/webhooks.ts +1 -0
  247. package/src/component/public/factors/devices.ts +1 -0
  248. package/src/component/public/factors/passkeys.ts +1 -0
  249. package/src/component/public/factors/totp.ts +1 -0
  250. package/src/component/public/groups/core.ts +1 -1
  251. package/src/component/public/groups/invites.ts +7 -1
  252. package/src/component/public/groups/members.ts +1 -0
  253. package/src/component/public/identity/accounts.ts +1 -0
  254. package/src/component/public/identity/codes.ts +1 -0
  255. package/src/component/public/identity/sessions.ts +1 -0
  256. package/src/component/public/identity/tokens.ts +1 -0
  257. package/src/component/public/identity/users.ts +1 -0
  258. package/src/component/public/identity/verifiers.ts +1 -0
  259. package/src/component/public/security/keys.ts +1 -0
  260. package/src/component/public/security/limits.ts +1 -0
  261. package/src/providers/password.ts +89 -110
  262. package/src/server/auth.ts +177 -111
  263. package/src/server/core.ts +197 -233
  264. package/src/server/crypto.ts +31 -29
  265. package/src/server/device.ts +65 -32
  266. package/src/server/enterprise/domain.ts +158 -170
  267. package/src/server/enterprise/http.ts +46 -39
  268. package/src/server/http.ts +36 -30
  269. package/src/server/identity.ts +5 -5
  270. package/src/server/index.ts +2 -0
  271. package/src/server/limits.ts +53 -80
  272. package/src/server/mounts.ts +47 -74
  273. package/src/server/mutations/account.ts +22 -36
  274. package/src/server/mutations/code.ts +6 -6
  275. package/src/server/mutations/invalidate.ts +1 -1
  276. package/src/server/mutations/oauth.ts +14 -8
  277. package/src/server/mutations/refresh.ts +5 -4
  278. package/src/server/mutations/register.ts +87 -132
  279. package/src/server/mutations/retrieve.ts +44 -44
  280. package/src/server/mutations/signature.ts +13 -6
  281. package/src/server/mutations/signout.ts +1 -1
  282. package/src/server/mutations/store.ts +16 -31
  283. package/src/server/mutations/verifier.ts +1 -1
  284. package/src/server/mutations/verify.ts +3 -5
  285. package/src/server/oauth.ts +60 -69
  286. package/src/server/passkey.ts +567 -517
  287. package/src/server/redirects.ts +10 -6
  288. package/src/server/refresh.ts +14 -18
  289. package/src/server/runtime.ts +70 -55
  290. package/src/server/signin.ts +44 -37
  291. package/src/server/ssr.ts +390 -407
  292. package/src/server/totp.ts +85 -35
  293. package/src/server/types.ts +19 -22
  294. package/src/server/users.ts +7 -6
  295. package/src/server/utils.ts +10 -12
  296. package/dist/component/server/authError.js +0 -34
  297. package/dist/component/server/authError.js.map +0 -1
  298. package/dist/component/server/errors.d.ts +0 -1
  299. package/dist/component/server/errors.js +0 -137
  300. package/dist/component/server/errors.js.map +0 -1
  301. package/dist/server/authError.d.ts +0 -46
  302. package/dist/server/authError.d.ts.map +0 -1
  303. package/dist/server/authError.js +0 -34
  304. package/dist/server/authError.js.map +0 -1
  305. package/dist/server/errors.d.ts +0 -177
  306. package/dist/server/errors.d.ts.map +0 -1
  307. package/dist/server/errors.js +0 -212
  308. package/dist/server/errors.js.map +0 -1
  309. package/src/server/authError.ts +0 -44
  310. package/src/server/errors.ts +0 -290
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","names":["serializeCookie","state"],"sources":["../../../src/server/enterprise/http.ts"],"sourcesContent":["import type { GenericActionCtx, HttpRouter } from \"convex/server\";\nimport { serialize as serializeCookie } from \"cookie\";\n\nimport { redirectToParamCookie, useRedirectToParam } from \"../cookies\";\nimport { isAuthError } from \"../errors\";\nimport { Fx } from \"@robelest/fx\";\n\nimport { AuthError } from \"../authError\";\nimport { addSSORoutes, convertErrorsToResponse, getCookies } from \"../http\";\nimport type { SSORuntimeRoute } from \"../http\";\nimport { createOAuthAuthorizationURL, handleOAuthCallback } from \"../oauth\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"../redirects\";\nimport { createEnterpriseOidcRuntime } from \"./oidc\";\nimport {\n createEnterpriseSamlMetadataXml,\n createEnterpriseSamlSignInRequest,\n createSamlPostBindingResponse,\n encodeEnterpriseSamlRelayState,\n parseEnterpriseSamlLoginResponse,\n parseEnterpriseSamlLogoutMessage,\n profileFromSamlExtract,\n validateEnterpriseSamlLoginRelayState,\n} from \"./saml\";\nimport {\n parseScimListRequest,\n scimError,\n scimJson,\n serializeScimGroup,\n serializeScimUser,\n} from \"./scim\";\nimport {\n enterpriseSamlProviderId,\n SCIM_GROUP_SCHEMA_ID,\n SCIM_USER_SCHEMA_ID,\n} from \"./shared\";\n\nexport type EnterpriseHttpRuntimeDeps = {\n http: HttpRouter;\n hasSSO: boolean;\n auth: any;\n config: any;\n routeBase: string;\n requireEnv: (name: string) => string;\n loadActiveEnterpriseSamlOrThrow: any;\n loadEnterpriseOidcOrThrow: any;\n getEnterpriseScimContext: any;\n getPolicyFromEnterprise: any;\n normalizeEnterprisePolicy: any;\n recordEnterpriseAuditEvent: any;\n emitEnterpriseWebhookDeliveries: any;\n generateRandomString: (length: number, alphabet: string) => string;\n inviteTokenAlphabet: string;\n callUserOAuth: any;\n callVerifierSignature: any;\n};\n\nexport function addEnterpriseHttpRuntime(deps: EnterpriseHttpRuntimeDeps) {\n if (!deps.hasSSO) {\n return;\n }\n\n const {\n http,\n auth,\n config,\n requireEnv,\n loadActiveEnterpriseSamlOrThrow,\n loadEnterpriseOidcOrThrow,\n getEnterpriseScimContext,\n getPolicyFromEnterprise,\n recordEnterpriseAuditEvent,\n emitEnterpriseWebhookDeliveries,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n } = deps;\n const ENTERPRISE_CONTROL_ROUTE_BASE = deps.routeBase;\n\n type ScimState = {\n ctx: any;\n request: Request;\n url: URL;\n parsedPath: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"parsedPath\"];\n enterprise: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"enterprise\"];\n scimConfig: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"scimConfig\"];\n policy: any;\n recordScimEvent: (\n eventType: string,\n ok: boolean,\n subjectType: string,\n subjectId?: string,\n metadata?: Record<string, unknown>,\n ) => Promise<void>;\n };\n\n type ScimHandler = (state: ScimState) => Promise<Response>;\n\n const SCIM_SCHEMAS = [\n {\n id: SCIM_USER_SCHEMA_ID,\n name: \"User\",\n description: \"User Account\",\n attributes: [\n { name: \"userName\", type: \"string\", required: true },\n { name: \"displayName\", type: \"string\" },\n { name: \"active\", type: \"boolean\" },\n { name: \"emails\", type: \"complex\", multiValued: true },\n ],\n },\n {\n id: SCIM_GROUP_SCHEMA_ID,\n name: \"Group\",\n description: \"Group\",\n attributes: [\n { name: \"displayName\", type: \"string\", required: true },\n { name: \"members\", type: \"complex\", multiValued: true },\n ],\n },\n ] as const;\n\n const SCIM_RESOURCE_TYPES = [\n {\n id: \"User\",\n name: \"User\",\n endpoint: \"/Users\",\n schema: SCIM_USER_SCHEMA_ID,\n },\n {\n id: \"Group\",\n name: \"Group\",\n endpoint: \"/Groups\",\n schema: SCIM_GROUP_SCHEMA_ID,\n },\n ] as const;\n\n const handleStaticScimCollection = <T extends { id?: string; name?: string }>(\n items: readonly T[],\n resourceId: string | undefined,\n opts: { by: \"id\" | \"name\"; notFound: string },\n ) => {\n if (resourceId !== undefined) {\n const item = items.find(\n (entry) => entry[opts.by] === decodeURIComponent(resourceId),\n );\n return item ? scimJson(item) : scimError(404, \"notFound\", opts.notFound);\n }\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: items,\n totalResults: items.length,\n startIndex: 1,\n itemsPerPage: items.length,\n });\n };\n\n const filterScimCollection = <T>(\n items: T[],\n filter: ReturnType<typeof parseScimListRequest>[\"filter\"],\n filters: Record<string, (item: T, value: string) => boolean>,\n ) => {\n if (!filter) {\n return items;\n }\n const predicate = filters[filter.attribute];\n if (!predicate) {\n throw new Error(\"Unsupported SCIM filter.\");\n }\n return items.filter((item) => predicate(item, filter.value));\n };\n\n const paginateScimCollection = <T>(\n items: T[],\n listRequest: ReturnType<typeof parseScimListRequest>,\n ) => {\n const start = listRequest.startIndex - 1;\n return items.slice(start, start + listRequest.count);\n };\n\n const requireScimResourceId = (\n resourceId: string | undefined,\n label: string,\n ) => {\n if (!resourceId) {\n return scimError(400, \"invalidPath\", `${label} resource ID is required.`);\n }\n return null;\n };\n\n const readScimJson = async (request: Request) =>\n (await request.json()) as Record<string, any>;\n\n const handleSamlAcs = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) =>\n Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"acs\",\n Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError(),\n ),\n );\n\n const enterpriseId = runtimeRoute.enterpriseId;\n const { loaded, enterprise, saml } = yield* Fx.from({\n ok: () => loadActiveEnterpriseSamlOrThrow(ctx, enterpriseId),\n err: (e) => e,\n });\n\n const parsedResponse = yield* Fx.from({\n ok: () =>\n parseEnterpriseSamlLoginResponse({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n }),\n err: (e) =>\n new AuthError(\n \"OAUTH_PROVIDER_ERROR\",\n `SAML response parse failed: ${e instanceof Error ? e.message : String(e)}`,\n ).toConvexError(),\n });\n\n yield* Fx.from({\n ok: () => {\n validateEnterpriseSamlLoginRelayState({\n relayState: parsedResponse.relayState,\n source: { kind: \"enterprise\", id: enterprise._id },\n inResponseTo:\n parsedResponse.parsed.extract?.response?.inResponseTo,\n });\n return Promise.resolve();\n },\n err: () =>\n new AuthError(\n \"OAUTH_INVALID_STATE\",\n \"SAML RelayState did not match the pending login request.\",\n ).toConvexError(),\n });\n\n const { samlAttributes, samlSessionIndex, ...userProfile } =\n profileFromSamlExtract(\n parsedResponse.parsed.extract,\n saml.attributeMapping,\n );\n const profile = userProfile as Record<string, unknown> & {\n id: string;\n };\n\n const maybeRedirectTo = useRedirectToParam(\n enterpriseSamlProviderId(enterprise._id),\n getCookies(request),\n );\n\n const verificationCode = yield* Fx.from({\n ok: () =>\n callUserOAuth(ctx, {\n provider: enterpriseSamlProviderId(enterprise._id),\n providerAccountId: profile.id,\n profile,\n signature: parsedResponse.relayState.signature,\n accountExtend: {\n identity: {\n protocol: \"saml\",\n enterpriseId: enterprise._id,\n subject: profile.id,\n entityId:\n typeof saml.entityId === \"string\"\n ? saml.entityId\n : undefined,\n },\n saml: {\n attributes: samlAttributes,\n sessionIndex: samlSessionIndex,\n },\n },\n }),\n err: (e) => e,\n });\n\n const destinationUrl = yield* Fx.from({\n ok: () =>\n redirectAbsoluteUrl(config, {\n redirectTo:\n maybeRedirectTo?.redirectTo ??\n (typeof parsedResponse.relayState.redirectTo === \"string\"\n ? parsedResponse.relayState.redirectTo\n : undefined),\n }),\n err: (e) => e,\n });\n\n const vurl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const vheaders = new Headers({ Location: vurl });\n vheaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n vheaders.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers: vheaders });\n }).pipe(Fx.recover((e) => Fx.fatal(e))),\n );\n\n const handleSamlSlo = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) => {\n if (\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"slo\"\n ) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const parsedMessage = await parseEnterpriseSamlLogoutMessage({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n });\n if (parsedMessage.hasSamlRequest && parsedMessage.parsedRequest) {\n const responseContext = (\n parsedMessage.runtime.sp as any\n ).createLogoutResponse(\n parsedMessage.runtime.idp as any,\n parsedMessage.parsedRequest.extract,\n parsedMessage.binding as any,\n parsedMessage.relayState ?? \"\",\n ) as any;\n if (parsedMessage.binding === \"redirect\") {\n return new Response(null, {\n status: 302,\n headers: { Location: responseContext.context },\n });\n }\n return createSamlPostBindingResponse({\n endpoint: responseContext.entityEndpoint,\n parameter: \"SAMLResponse\",\n value: responseContext.context,\n relayState: parsedMessage.relayState,\n });\n }\n if (parsedMessage.hasSamlResponse) {\n return new Response(null, { status: 204 });\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Missing SAML logout payload.\",\n ).toConvexError();\n };\n\n const handleScimRequest = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => {\n try {\n const { scimConfig, enterprise, parsedPath } =\n await getEnterpriseScimContext(ctx, request);\n const url = new URL(request.url);\n const state: ScimState = {\n ctx,\n request,\n url,\n parsedPath,\n enterprise,\n scimConfig,\n policy: getPolicyFromEnterprise(enterprise),\n recordScimEvent: async (\n eventType,\n ok,\n subjectType,\n subjectId,\n metadata,\n ) => {\n const auditEventId = await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType,\n actorType: \"scim\",\n subjectType,\n subjectId,\n ok,\n metadata,\n });\n await emitEnterpriseWebhookDeliveries(ctx, {\n enterpriseId: enterprise._id,\n eventType,\n auditEventId,\n payload: {\n enterpriseId: enterprise._id,\n subjectId,\n metadata,\n },\n });\n },\n };\n\n const handleUsersGet: ScimHandler = async (state) => {\n const members = await auth.member.list(state.ctx, {\n where: { groupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByUserId = new Map(\n identities\n .filter((identity: any) => identity.userId !== undefined)\n .map((identity: any) => [identity.userId, identity]),\n );\n const users = (\n await Promise.all(\n members.items.map(async (member: any) => {\n const user = await auth.user.get(state.ctx, member.userId);\n return user\n ? {\n user,\n member,\n identity: identityByUserId.get(user._id),\n }\n : null;\n }),\n )\n ).filter(Boolean) as Array<{\n user: any;\n member: any;\n identity?: any;\n }>;\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection(users, listRequest.filter, {\n id: (item: { user: any }, value: string) => item.user._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n userName: (item: { user: any }, value: string) =>\n item.user.email === value,\n \"emails.value\": (item: { user: any }, value: string) =>\n item.user.email === value,\n active: (item: { identity?: any; member: any }, value: string) =>\n String(item.identity?.active ?? item.member.status === \"active\") ===\n value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ user }) => user._id === state.parsedPath.resourceId,\n );\n return resource\n ? scimJson(\n serializeScimUser({\n id: resource.user._id,\n user: resource.user,\n externalId: resource.identity?.externalId,\n location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n active:\n resource.identity?.active ??\n resource.member.status === \"active\",\n }),\n 200,\n {\n Location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n },\n )\n : scimError(404, \"notFound\", \"User not found.\");\n }\n const paged = paginateScimCollection(filtered, listRequest);\n await state.recordScimEvent(\n \"enterprise.scim.read\",\n true,\n \"enterprise_scim\",\n state.scimConfig._id,\n );\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ user, identity, member }) =>\n serializeScimUser({\n id: user._id,\n user,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${user._id}`,\n active: identity?.active ?? member.status === \"active\",\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleUsersPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const primaryEmail = Array.isArray(body.emails)\n ? (body.emails.find((entry) => entry.primary === true)?.value ??\n body.emails[0]?.value)\n : undefined;\n const phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n const userId = (await state.ctx.runMutation(\n config.component.public.userInsert,\n {\n data: {\n name: body.displayName ?? body.name?.formatted,\n email: primaryEmail ?? body.userName,\n ...(typeof (primaryEmail ?? body.userName) === \"string\"\n ? { emailVerificationTime: Date.now() }\n : {}),\n phone,\n ...(typeof phone === \"string\"\n ? { phoneVerificationTime: Date.now() }\n : {}),\n },\n },\n )) as string;\n try {\n await auth.member.create(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: body.active === false ? \"inactive\" : \"active\",\n });\n } catch {}\n if (typeof body.externalId === \"string\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId: body.externalId,\n userId,\n active: body.active !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.created\",\n true,\n \"user\",\n userId,\n );\n const createdUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}/${userId}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: createdUser ?? {},\n externalId: body.externalId,\n location,\n active: body.active !== false,\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleUsersUpsert: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const existingUser = await auth.user.get(state.ctx, userId);\n if (!existingUser) {\n return scimError(404, \"notFound\", \"User not found.\");\n }\n const body = await readScimJson(state.request);\n const patchData: Record<string, unknown> = {};\n let nextActive: boolean | undefined;\n if (state.request.method === \"PUT\") {\n patchData.name = body.displayName ?? body.name?.formatted;\n patchData.email =\n body.userName ??\n (Array.isArray(body.emails) ? body.emails[0]?.value : undefined);\n patchData.phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n if (typeof patchData.email === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n if (typeof patchData.phone === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n } else {\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"active\") {\n nextActive = operation.value;\n }\n if (\n operation.path === \"displayName\" ||\n operation.path === \"name.formatted\"\n ) {\n patchData.name = operation.value;\n }\n if (\n operation.path === \"userName\" ||\n operation.path === \"emails.value\"\n ) {\n patchData.email = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n }\n if (operation.path === \"phoneNumbers.value\") {\n patchData.phone = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n }\n }\n }\n await state.ctx.runMutation(config.component.public.userPatch, {\n userId,\n data: patchData,\n });\n const resolution = await auth.member.resolve(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.update(state.ctx, resolution.membership._id, {\n status:\n body.active === false || nextActive === false\n ? \"inactive\"\n : \"active\",\n });\n }\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId:\n typeof body.externalId === \"string\"\n ? body.externalId\n : ((\n await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n )\n )?.externalId ?? userId),\n userId,\n active: body.active !== false && nextActive !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n await state.recordScimEvent(\n \"enterprise.scim.user.updated\",\n true,\n \"user\",\n userId,\n );\n const updatedUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: updatedUser ?? existingUser,\n externalId:\n typeof body.externalId === \"string\" ? body.externalId : undefined,\n location,\n active: body.active !== false && nextActive !== false,\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleUsersDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const resolution = await auth.member.resolve(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.delete(state.ctx, resolution.membership._id);\n }\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n );\n if (identity) {\n if (state.policy.provisioning.deprovision.mode === \"hard\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n } else {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: identity.enterpriseId,\n groupId: identity.groupId,\n resourceType: identity.resourceType,\n externalId: identity.externalId,\n userId: identity.userId,\n mappedGroupId: identity.mappedGroupId,\n active: false,\n raw: identity.raw,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.deleted\",\n true,\n \"user\",\n userId,\n );\n return new Response(null, { status: 204 });\n };\n\n const handleGroupsGet: ScimHandler = async (state) => {\n const groupsList = await auth.group.list(state.ctx, {\n where: { parentGroupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByGroupId = new Map(\n identities\n .filter((identity: any) => identity.mappedGroupId !== undefined)\n .map((identity: any) => [identity.mappedGroupId, identity]),\n );\n const groups = groupsList.items.map((group: any) => ({\n group,\n identity: identityByGroupId.get(group._id),\n }));\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection<{\n group: any;\n identity?: any;\n }>(groups, listRequest.filter, {\n id: (item: { group: any }, value: string) => item.group._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n displayName: (item: { group: any }, value: string) =>\n item.group.name === value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ group }) => group._id === state.parsedPath.resourceId,\n );\n if (!resource) {\n return scimError(404, \"notFound\", \"Group not found.\");\n }\n const members = (\n await auth.member.list(state.ctx, {\n where: {\n groupId: resource.group._id,\n status: \"active\",\n },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId }));\n const location = `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.group._id}`;\n return scimJson(\n serializeScimGroup({\n id: resource.group._id,\n group: resource.group,\n externalId: resource.identity?.externalId,\n location,\n members,\n }),\n 200,\n { Location: location },\n );\n }\n const paged = paginateScimCollection(filtered, listRequest);\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ group, identity }) =>\n serializeScimGroup({\n id: group._id,\n group,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${group._id}`,\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleGroupsPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const { groupId } = await auth.group.create(state.ctx, {\n name: String(body.displayName ?? \"Group\"),\n parentGroupId: state.enterprise.groupId,\n type: \"organization\",\n });\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"group\",\n externalId: body.externalId ?? groupId,\n mappedGroupId: groupId,\n active: true,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n for (const member of Array.isArray(body.members) ? body.members : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.created\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}/${groupId}`;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n externalId: body.externalId,\n location,\n members: (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId })),\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleGroupsPatch: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n const body = await readScimJson(state.request);\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"displayName\") {\n await auth.group.update(state.ctx, groupId, {\n name: operation.value,\n });\n }\n if (operation.path === \"members\" && operation.op === \"add\") {\n for (const member of Array.isArray(operation.value)\n ? operation.value\n : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n if (operation.path === \"members\" && operation.op === \"replace\") {\n const currentMembers = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ _id: string; userId: string }>;\n const currentUserIds = new Set<string>(\n currentMembers.map((member) => member.userId),\n );\n const nextUserIds = new Set<string>(\n (Array.isArray(operation.value) ? operation.value : []).map(\n (member: any) => String(member.value),\n ),\n );\n for (const member of currentMembers) {\n if (!nextUserIds.has(member.userId)) {\n await auth.member.delete(state.ctx, member._id);\n }\n }\n for (const userId of nextUserIds.values()) {\n if (!currentUserIds.has(userId)) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n }\n if (\n typeof operation.path === \"string\" &&\n operation.op === \"remove\" &&\n operation.path.startsWith(\"members[\")\n ) {\n const match = operation.path.match(\n /^members\\[value eq \"([^\"]+)\"\\]$/,\n );\n const userId = match?.[1];\n if (userId) {\n const resolution = await auth.member.resolve(\n state.ctx,\n { groupId, userId },\n );\n if (resolution.membership) {\n await auth.member.delete(\n state.ctx,\n resolution.membership._id,\n );\n }\n }\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.updated\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}`;\n const members = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ userId: string }>;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n location,\n members: members.map((member) => ({\n value: member.userId,\n })),\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleGroupsDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n await auth.group.delete(state.ctx, groupId);\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByMappedGroup,\n { mappedGroupId: groupId },\n );\n if (identity) {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.deleted\",\n true,\n \"group\",\n groupId,\n );\n return new Response(null, { status: 204 });\n };\n\n const scimHandlers: Record<\n string,\n Partial<Record<string, ScimHandler>>\n > = {\n ServiceProviderConfig: {\n GET: async () =>\n scimJson({\n schemas: [\n \"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\",\n ],\n patch: { supported: true },\n bulk: {\n supported: false,\n maxOperations: 0,\n maxPayloadSize: 0,\n },\n filter: { supported: true, maxResults: 100 },\n changePassword: { supported: false },\n sort: { supported: false },\n etag: { supported: false },\n authenticationSchemes: [\n {\n type: \"oauthbearertoken\",\n name: \"Bearer Token\",\n description:\n \"Use the SCIM token generated by Convex Auth enterprise.\",\n },\n ],\n }),\n },\n Schemas: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_SCHEMAS,\n state.parsedPath.resourceId,\n {\n by: \"id\",\n notFound: \"Schema not found.\",\n },\n ),\n },\n ResourceTypes: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_RESOURCE_TYPES,\n state.parsedPath.resourceId,\n { by: \"name\", notFound: \"Resource type not found.\" },\n ),\n },\n Users: {\n GET: handleUsersGet,\n POST: handleUsersPost,\n PATCH: handleUsersUpsert,\n PUT: handleUsersUpsert,\n DELETE: handleUsersDelete,\n },\n Groups: {\n GET: handleGroupsGet,\n POST: handleGroupsPost,\n PATCH: handleGroupsPatch,\n DELETE: handleGroupsDelete,\n },\n };\n\n const handler =\n scimHandlers[state.parsedPath.resource]?.[state.request.method];\n return handler\n ? await handler(state)\n : scimError(404, \"notFound\", \"SCIM resource not found.\");\n } catch (error) {\n if (\n error instanceof Error &&\n error.message === \"Unsupported SCIM filter.\"\n ) {\n return scimError(400, \"invalidFilter\", error.message);\n }\n if (isAuthError(error)) {\n const code = error.data.code as string;\n const status =\n code === \"MISSING_BEARER_TOKEN\" || code === \"INVALID_API_KEY\"\n ? 401\n : 400;\n return scimError(status, code, error.data.message);\n }\n throw error;\n }\n };\n\n addSSORoutes(http, {\n routeBase: ENTERPRISE_CONTROL_ROUTE_BASE,\n convertErrorsToResponse,\n handleSamlMetadata: async (ctx, _request, runtimeRoute) => {\n const { loaded } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n return new Response(\n createEnterpriseSamlMetadataXml({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: loaded.source,\n config: loaded.config,\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/xml\" },\n },\n );\n },\n handleSamlSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const state = generateRandomString(24, INVITE_TOKEN_ALPHABET);\n const signInRequest = createEnterpriseSamlSignInRequest({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n state,\n signature: `saml ${enterprise._id} pending ${state}`,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n const signature = `saml ${enterprise._id} ${signInRequest.requestId} ${state}`;\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const redirectCookies =\n redirectTo !== null\n ? [\n redirectToParamCookie(\n enterpriseSamlProviderId(enterprise._id),\n redirectTo,\n ),\n ]\n : [];\n const relayState = encodeEnterpriseSamlRelayState({\n source: { kind: \"enterprise\", id: enterprise._id },\n signature,\n requestId: signInRequest.requestId,\n state,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n if (signInRequest.binding === \"redirect\" && signInRequest.redirectUrl) {\n const redirectUrl = new URL(signInRequest.redirectUrl);\n redirectUrl.searchParams.set(\"RelayState\", relayState);\n const headers = new Headers({\n Location: redirectUrl.toString(),\n });\n for (const { name, value, options } of redirectCookies as any) {\n headers.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers });\n }\n const response = createSamlPostBindingResponse({\n endpoint: signInRequest.post!.endpoint,\n parameter: \"SAMLRequest\",\n value: signInRequest.post!.value,\n relayState,\n });\n for (const { name, value, options } of redirectCookies as any) {\n response.headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return response;\n },\n handleOidcSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\n }\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(providerId, provider, oauthConfig);\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const headers_ = new Headers({ Location: redirect });\n for (const { name, value, options } of [\n ...cookies,\n ...(redirectTo !== null\n ? [redirectToParamCookie(providerId, redirectTo)]\n : []),\n ] as any) {\n headers_.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, {\n status: 302,\n headers: headers_,\n });\n },\n handleOidcCallback: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const cookies = getCookies(request);\n const maybeRedirectTo = useRedirectToParam(providerId, cookies);\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n const params = url.searchParams;\n const result = (await Fx.run(\n handleOAuthCallback(\n providerId,\n provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n )) as any;\n const extraFields = oidc.extraFields as\n | Record<string, string>\n | undefined;\n let profile = result.profile as Record<string, unknown>;\n if (extraFields && typeof profile === \"object\" && profile) {\n const extend: Record<string, unknown> = {};\n for (const [claimName, fieldName] of Object.entries(extraFields)) {\n if (claimName in profile) {\n extend[fieldName] = profile[claimName];\n }\n }\n if (Object.keys(extend).length > 0) {\n profile = { ...profile, extend };\n }\n }\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: result.providerAccountId,\n profile,\n signature: result.signature,\n accountExtend: {\n identity: {\n protocol: \"oidc\",\n enterpriseId: enterprise._id,\n subject: result.providerAccountId,\n issuer: typeof oidc.issuer === \"string\" ? oidc.issuer : undefined,\n discoveryUrl:\n typeof oidc.discoveryUrl === \"string\"\n ? oidc.discoveryUrl\n : undefined,\n },\n },\n });\n const headers = new Headers({\n Location: setURLSearchParam(destinationUrl, \"code\", verificationCode),\n });\n for (const { name, value, options } of result.cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n if (maybeRedirectTo) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(\n maybeRedirectTo.updatedCookie.name,\n maybeRedirectTo.updatedCookie.value,\n maybeRedirectTo.updatedCookie.options as any,\n ),\n );\n }\n return new Response(null, { status: 302, headers });\n },\n handleSamlAcs,\n handleSamlSlo,\n handleScimRequest,\n scimError,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"http.js","names":["serializeCookie","state"],"sources":["../../../src/server/enterprise/http.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport type { GenericActionCtx, HttpRouter } from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { serialize as serializeCookie } from \"cookie\";\n\nimport { redirectToParamCookie, useRedirectToParam } from \"../cookies\";\nimport { addSSORoutes, convertErrorsToResponse, getCookies } from \"../http\";\nimport type { SSORuntimeRoute } from \"../http\";\nimport { createOAuthAuthorizationURL, handleOAuthCallback } from \"../oauth\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"../redirects\";\nimport { createEnterpriseOidcRuntime } from \"./oidc\";\nimport {\n createEnterpriseSamlMetadataXml,\n createEnterpriseSamlSignInRequest,\n createSamlPostBindingResponse,\n encodeEnterpriseSamlRelayState,\n parseEnterpriseSamlLoginResponse,\n parseEnterpriseSamlLogoutMessage,\n profileFromSamlExtract,\n validateEnterpriseSamlLoginRelayState,\n} from \"./saml\";\nimport {\n parseScimListRequest,\n scimError,\n scimJson,\n serializeScimGroup,\n serializeScimUser,\n} from \"./scim\";\nimport {\n enterpriseSamlProviderId,\n SCIM_GROUP_SCHEMA_ID,\n SCIM_USER_SCHEMA_ID,\n} from \"./shared\";\n\nexport type EnterpriseHttpRuntimeDeps = {\n http: HttpRouter;\n hasSSO: boolean;\n auth: any;\n config: any;\n routeBase: string;\n requireEnv: (name: string) => string;\n loadActiveEnterpriseSamlOrThrow: any;\n loadEnterpriseOidcOrThrow: any;\n getEnterpriseScimContext: any;\n getPolicyFromEnterprise: any;\n normalizeEnterprisePolicy: any;\n recordEnterpriseAuditEvent: any;\n emitEnterpriseWebhookDeliveries: any;\n generateRandomString: (length: number, alphabet: string) => string;\n inviteTokenAlphabet: string;\n callUserOAuth: any;\n callVerifierSignature: any;\n};\n\nexport function addEnterpriseHttpRuntime(deps: EnterpriseHttpRuntimeDeps) {\n if (!deps.hasSSO) {\n return;\n }\n\n const {\n http,\n auth,\n config,\n requireEnv,\n loadActiveEnterpriseSamlOrThrow,\n loadEnterpriseOidcOrThrow,\n getEnterpriseScimContext,\n getPolicyFromEnterprise,\n recordEnterpriseAuditEvent,\n emitEnterpriseWebhookDeliveries,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n } = deps;\n const ENTERPRISE_CONTROL_ROUTE_BASE = deps.routeBase;\n\n type ScimState = {\n ctx: any;\n request: Request;\n url: URL;\n parsedPath: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"parsedPath\"];\n enterprise: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"enterprise\"];\n scimConfig: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"scimConfig\"];\n policy: any;\n recordScimEvent: (\n eventType: string,\n ok: boolean,\n subjectType: string,\n subjectId?: string,\n metadata?: Record<string, unknown>,\n ) => Promise<void>;\n };\n\n type ScimHandler = (state: ScimState) => Promise<Response>;\n\n const SCIM_SCHEMAS = [\n {\n id: SCIM_USER_SCHEMA_ID,\n name: \"User\",\n description: \"User Account\",\n attributes: [\n { name: \"userName\", type: \"string\", required: true },\n { name: \"displayName\", type: \"string\" },\n { name: \"active\", type: \"boolean\" },\n { name: \"emails\", type: \"complex\", multiValued: true },\n ],\n },\n {\n id: SCIM_GROUP_SCHEMA_ID,\n name: \"Group\",\n description: \"Group\",\n attributes: [\n { name: \"displayName\", type: \"string\", required: true },\n { name: \"members\", type: \"complex\", multiValued: true },\n ],\n },\n ] as const;\n\n const SCIM_RESOURCE_TYPES = [\n {\n id: \"User\",\n name: \"User\",\n endpoint: \"/Users\",\n schema: SCIM_USER_SCHEMA_ID,\n },\n {\n id: \"Group\",\n name: \"Group\",\n endpoint: \"/Groups\",\n schema: SCIM_GROUP_SCHEMA_ID,\n },\n ] as const;\n\n const handleStaticScimCollection = <T extends { id?: string; name?: string }>(\n items: readonly T[],\n resourceId: string | undefined,\n opts: { by: \"id\" | \"name\"; notFound: string },\n ) => {\n if (resourceId !== undefined) {\n const item = items.find(\n (entry) => entry[opts.by] === decodeURIComponent(resourceId),\n );\n return item ? scimJson(item) : scimError(404, \"notFound\", opts.notFound);\n }\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: items,\n totalResults: items.length,\n startIndex: 1,\n itemsPerPage: items.length,\n });\n };\n\n const filterScimCollection = <T>(\n items: T[],\n filter: ReturnType<typeof parseScimListRequest>[\"filter\"],\n filters: Record<string, (item: T, value: string) => boolean>,\n ) => {\n if (!filter) {\n return items;\n }\n const predicate = filters[filter.attribute];\n if (!predicate) {\n throw new Error(\"Unsupported SCIM filter.\");\n }\n return items.filter((item) => predicate(item, filter.value));\n };\n\n const paginateScimCollection = <T>(\n items: T[],\n listRequest: ReturnType<typeof parseScimListRequest>,\n ) => {\n const start = listRequest.startIndex - 1;\n return items.slice(start, start + listRequest.count);\n };\n\n const requireScimResourceId = (\n resourceId: string | undefined,\n label: string,\n ) => {\n if (!resourceId) {\n return scimError(400, \"invalidPath\", `${label} resource ID is required.`);\n }\n return null;\n };\n\n const readScimJson = async (request: Request) =>\n (await request.json()) as Record<string, any>;\n\n const handleSamlAcs = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) =>\n Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"acs\",\n Cv.fail({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n }),\n );\n\n const enterpriseId = runtimeRoute.enterpriseId;\n const { loaded, enterprise, saml } = yield* Fx.from({\n ok: () => loadActiveEnterpriseSamlOrThrow(ctx, enterpriseId),\n err: (e) => e,\n });\n\n const parsedResponse = yield* Fx.from({\n ok: () =>\n parseEnterpriseSamlLoginResponse({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n }),\n err: (e) =>\n Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `SAML response parse failed: ${e instanceof Error ? e.message : String(e)}`,\n }),\n });\n\n yield* Fx.from({\n ok: () => {\n validateEnterpriseSamlLoginRelayState({\n relayState: parsedResponse.relayState,\n source: { kind: \"enterprise\", id: enterprise._id },\n inResponseTo:\n parsedResponse.parsed.extract?.response?.inResponseTo,\n });\n return Promise.resolve();\n },\n err: () =>\n Cv.error({\n code: \"OAUTH_INVALID_STATE\",\n message:\n \"SAML RelayState did not match the pending login request.\",\n }),\n });\n\n const { samlAttributes, samlSessionIndex, ...userProfile } =\n profileFromSamlExtract(\n parsedResponse.parsed.extract,\n saml.attributeMapping,\n );\n const profile = userProfile as Record<string, unknown> & {\n id: string;\n };\n\n const maybeRedirectTo = useRedirectToParam(\n enterpriseSamlProviderId(enterprise._id),\n getCookies(request),\n );\n\n const verificationCode = yield* Fx.from({\n ok: () =>\n callUserOAuth(ctx, {\n provider: enterpriseSamlProviderId(enterprise._id),\n providerAccountId: profile.id,\n profile,\n signature: parsedResponse.relayState.signature,\n accountExtend: {\n identity: {\n protocol: \"saml\",\n enterpriseId: enterprise._id,\n subject: profile.id,\n entityId:\n typeof saml.entityId === \"string\"\n ? saml.entityId\n : undefined,\n },\n saml: {\n attributes: samlAttributes,\n sessionIndex: samlSessionIndex,\n },\n },\n }),\n err: (e) => e,\n });\n\n const destinationUrl = yield* Fx.from({\n ok: () =>\n redirectAbsoluteUrl(config, {\n redirectTo:\n maybeRedirectTo?.redirectTo ??\n (typeof parsedResponse.relayState.redirectTo === \"string\"\n ? parsedResponse.relayState.redirectTo\n : undefined),\n }),\n err: (e) => e,\n });\n\n const vurl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const vheaders = new Headers({ Location: vurl });\n vheaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n vheaders.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers: vheaders });\n }).pipe(Fx.recover((e) => Fx.fatal(e))),\n );\n\n const handleSamlSlo = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) => {\n if (\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"slo\"\n ) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const parsedMessage = await parseEnterpriseSamlLogoutMessage({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n });\n if (parsedMessage.hasSamlRequest && parsedMessage.parsedRequest) {\n const responseContext = (\n parsedMessage.runtime.sp as any\n ).createLogoutResponse(\n parsedMessage.runtime.idp as any,\n parsedMessage.parsedRequest.extract,\n parsedMessage.binding as any,\n parsedMessage.relayState ?? \"\",\n ) as any;\n if (parsedMessage.binding === \"redirect\") {\n return new Response(null, {\n status: 302,\n headers: { Location: responseContext.context },\n });\n }\n return createSamlPostBindingResponse({\n endpoint: responseContext.entityEndpoint,\n parameter: \"SAMLResponse\",\n value: responseContext.context,\n relayState: parsedMessage.relayState,\n });\n }\n if (parsedMessage.hasSamlResponse) {\n return new Response(null, { status: 204 });\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Missing SAML logout payload.\",\n });\n };\n\n const handleScimRequest = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => {\n try {\n const { scimConfig, enterprise, parsedPath } =\n await getEnterpriseScimContext(ctx, request);\n const url = new URL(request.url);\n const state: ScimState = {\n ctx,\n request,\n url,\n parsedPath,\n enterprise,\n scimConfig,\n policy: getPolicyFromEnterprise(enterprise),\n recordScimEvent: async (\n eventType,\n ok,\n subjectType,\n subjectId,\n metadata,\n ) => {\n const auditEventId = await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType,\n actorType: \"scim\",\n subjectType,\n subjectId,\n ok,\n metadata,\n });\n await emitEnterpriseWebhookDeliveries(ctx, {\n enterpriseId: enterprise._id,\n eventType,\n auditEventId,\n payload: {\n enterpriseId: enterprise._id,\n subjectId,\n metadata,\n },\n });\n },\n };\n\n const handleUsersGet: ScimHandler = async (state) => {\n const members = await auth.member.list(state.ctx, {\n where: { groupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByUserId = new Map(\n identities\n .filter((identity: any) => identity.userId !== undefined)\n .map((identity: any) => [identity.userId, identity]),\n );\n const users = (\n await Promise.all(\n members.items.map(async (member: any) => {\n const user = await auth.user.get(state.ctx, member.userId);\n return user\n ? {\n user,\n member,\n identity: identityByUserId.get(user._id),\n }\n : null;\n }),\n )\n ).filter(Boolean) as Array<{\n user: any;\n member: any;\n identity?: any;\n }>;\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection(users, listRequest.filter, {\n id: (item: { user: any }, value: string) => item.user._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n userName: (item: { user: any }, value: string) =>\n item.user.email === value,\n \"emails.value\": (item: { user: any }, value: string) =>\n item.user.email === value,\n active: (item: { identity?: any; member: any }, value: string) =>\n String(item.identity?.active ?? item.member.status === \"active\") ===\n value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ user }) => user._id === state.parsedPath.resourceId,\n );\n return resource\n ? scimJson(\n serializeScimUser({\n id: resource.user._id,\n user: resource.user,\n externalId: resource.identity?.externalId,\n location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n active:\n resource.identity?.active ??\n resource.member.status === \"active\",\n }),\n 200,\n {\n Location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n },\n )\n : scimError(404, \"notFound\", \"User not found.\");\n }\n const paged = paginateScimCollection(filtered, listRequest);\n await state.recordScimEvent(\n \"enterprise.scim.read\",\n true,\n \"enterprise_scim\",\n state.scimConfig._id,\n );\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ user, identity, member }) =>\n serializeScimUser({\n id: user._id,\n user,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${user._id}`,\n active: identity?.active ?? member.status === \"active\",\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleUsersPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const primaryEmail = Array.isArray(body.emails)\n ? (body.emails.find((entry) => entry.primary === true)?.value ??\n body.emails[0]?.value)\n : undefined;\n const phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n const userId = (await state.ctx.runMutation(\n config.component.public.userInsert,\n {\n data: {\n name: body.displayName ?? body.name?.formatted,\n email: primaryEmail ?? body.userName,\n ...(typeof (primaryEmail ?? body.userName) === \"string\"\n ? { emailVerificationTime: Date.now() }\n : {}),\n phone,\n ...(typeof phone === \"string\"\n ? { phoneVerificationTime: Date.now() }\n : {}),\n },\n },\n )) as string;\n try {\n await auth.member.create(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: body.active === false ? \"inactive\" : \"active\",\n });\n } catch {}\n if (typeof body.externalId === \"string\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId: body.externalId,\n userId,\n active: body.active !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.created\",\n true,\n \"user\",\n userId,\n );\n const createdUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}/${userId}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: createdUser ?? {},\n externalId: body.externalId,\n location,\n active: body.active !== false,\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleUsersUpsert: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const existingUser = await auth.user.get(state.ctx, userId);\n if (!existingUser) {\n return scimError(404, \"notFound\", \"User not found.\");\n }\n const body = await readScimJson(state.request);\n const patchData: Record<string, unknown> = {};\n let nextActive: boolean | undefined;\n if (state.request.method === \"PUT\") {\n patchData.name = body.displayName ?? body.name?.formatted;\n patchData.email =\n body.userName ??\n (Array.isArray(body.emails) ? body.emails[0]?.value : undefined);\n patchData.phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n if (typeof patchData.email === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n if (typeof patchData.phone === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n } else {\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"active\") {\n nextActive = operation.value;\n }\n if (\n operation.path === \"displayName\" ||\n operation.path === \"name.formatted\"\n ) {\n patchData.name = operation.value;\n }\n if (\n operation.path === \"userName\" ||\n operation.path === \"emails.value\"\n ) {\n patchData.email = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n }\n if (operation.path === \"phoneNumbers.value\") {\n patchData.phone = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n }\n }\n }\n await state.ctx.runMutation(config.component.public.userPatch, {\n userId,\n data: patchData,\n });\n const resolution = await auth.member.inspect(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.update(state.ctx, resolution.membership._id, {\n status:\n body.active === false || nextActive === false\n ? \"inactive\"\n : \"active\",\n });\n }\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId:\n typeof body.externalId === \"string\"\n ? body.externalId\n : ((\n await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n )\n )?.externalId ?? userId),\n userId,\n active: body.active !== false && nextActive !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n await state.recordScimEvent(\n \"enterprise.scim.user.updated\",\n true,\n \"user\",\n userId,\n );\n const updatedUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: updatedUser ?? existingUser,\n externalId:\n typeof body.externalId === \"string\" ? body.externalId : undefined,\n location,\n active: body.active !== false && nextActive !== false,\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleUsersDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const resolution = await auth.member.inspect(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.delete(state.ctx, resolution.membership._id);\n }\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n );\n if (identity) {\n if (state.policy.provisioning.deprovision.mode === \"hard\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n } else {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: identity.enterpriseId,\n groupId: identity.groupId,\n resourceType: identity.resourceType,\n externalId: identity.externalId,\n userId: identity.userId,\n mappedGroupId: identity.mappedGroupId,\n active: false,\n raw: identity.raw,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.deleted\",\n true,\n \"user\",\n userId,\n );\n return new Response(null, { status: 204 });\n };\n\n const handleGroupsGet: ScimHandler = async (state) => {\n const groupsList = await auth.group.list(state.ctx, {\n where: { parentGroupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByGroupId = new Map(\n identities\n .filter((identity: any) => identity.mappedGroupId !== undefined)\n .map((identity: any) => [identity.mappedGroupId, identity]),\n );\n const groups = groupsList.items.map((group: any) => ({\n group,\n identity: identityByGroupId.get(group._id),\n }));\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection<{\n group: any;\n identity?: any;\n }>(groups, listRequest.filter, {\n id: (item: { group: any }, value: string) => item.group._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n displayName: (item: { group: any }, value: string) =>\n item.group.name === value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ group }) => group._id === state.parsedPath.resourceId,\n );\n if (!resource) {\n return scimError(404, \"notFound\", \"Group not found.\");\n }\n const members = (\n await auth.member.list(state.ctx, {\n where: {\n groupId: resource.group._id,\n status: \"active\",\n },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId }));\n const location = `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.group._id}`;\n return scimJson(\n serializeScimGroup({\n id: resource.group._id,\n group: resource.group,\n externalId: resource.identity?.externalId,\n location,\n members,\n }),\n 200,\n { Location: location },\n );\n }\n const paged = paginateScimCollection(filtered, listRequest);\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ group, identity }) =>\n serializeScimGroup({\n id: group._id,\n group,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${group._id}`,\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleGroupsPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const { groupId } = await auth.group.create(state.ctx, {\n name: String(body.displayName ?? \"Group\"),\n parentGroupId: state.enterprise.groupId,\n type: \"organization\",\n });\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"group\",\n externalId: body.externalId ?? groupId,\n mappedGroupId: groupId,\n active: true,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n for (const member of Array.isArray(body.members) ? body.members : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.created\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}/${groupId}`;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n externalId: body.externalId,\n location,\n members: (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId })),\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleGroupsPatch: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n const body = await readScimJson(state.request);\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"displayName\") {\n await auth.group.update(state.ctx, groupId, {\n name: operation.value,\n });\n }\n if (operation.path === \"members\" && operation.op === \"add\") {\n for (const member of Array.isArray(operation.value)\n ? operation.value\n : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n if (operation.path === \"members\" && operation.op === \"replace\") {\n const currentMembers = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ _id: string; userId: string }>;\n const currentUserIds = new Set<string>(\n currentMembers.map((member) => member.userId),\n );\n const nextUserIds = new Set<string>(\n (Array.isArray(operation.value) ? operation.value : []).map(\n (member: any) => String(member.value),\n ),\n );\n for (const member of currentMembers) {\n if (!nextUserIds.has(member.userId)) {\n await auth.member.delete(state.ctx, member._id);\n }\n }\n for (const userId of nextUserIds.values()) {\n if (!currentUserIds.has(userId)) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n }\n if (\n typeof operation.path === \"string\" &&\n operation.op === \"remove\" &&\n operation.path.startsWith(\"members[\")\n ) {\n const match = operation.path.match(\n /^members\\[value eq \"([^\"]+)\"\\]$/,\n );\n const userId = match?.[1];\n if (userId) {\n const resolution = await auth.member.inspect(state.ctx, {\n groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.delete(state.ctx, resolution.membership._id);\n }\n }\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.updated\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}`;\n const members = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ userId: string }>;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n location,\n members: members.map((member) => ({\n value: member.userId,\n })),\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleGroupsDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n await auth.group.delete(state.ctx, groupId);\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByMappedGroup,\n { mappedGroupId: groupId },\n );\n if (identity) {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.deleted\",\n true,\n \"group\",\n groupId,\n );\n return new Response(null, { status: 204 });\n };\n\n const scimHandlers: Record<\n string,\n Partial<Record<string, ScimHandler>>\n > = {\n ServiceProviderConfig: {\n GET: async () =>\n scimJson({\n schemas: [\n \"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\",\n ],\n patch: { supported: true },\n bulk: {\n supported: false,\n maxOperations: 0,\n maxPayloadSize: 0,\n },\n filter: { supported: true, maxResults: 100 },\n changePassword: { supported: false },\n sort: { supported: false },\n etag: { supported: false },\n authenticationSchemes: [\n {\n type: \"oauthbearertoken\",\n name: \"Bearer Token\",\n description:\n \"Use the SCIM token generated by Convex Auth enterprise.\",\n },\n ],\n }),\n },\n Schemas: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_SCHEMAS,\n state.parsedPath.resourceId,\n {\n by: \"id\",\n notFound: \"Schema not found.\",\n },\n ),\n },\n ResourceTypes: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_RESOURCE_TYPES,\n state.parsedPath.resourceId,\n { by: \"name\", notFound: \"Resource type not found.\" },\n ),\n },\n Users: {\n GET: handleUsersGet,\n POST: handleUsersPost,\n PATCH: handleUsersUpsert,\n PUT: handleUsersUpsert,\n DELETE: handleUsersDelete,\n },\n Groups: {\n GET: handleGroupsGet,\n POST: handleGroupsPost,\n PATCH: handleGroupsPatch,\n DELETE: handleGroupsDelete,\n },\n };\n\n const handler =\n scimHandlers[state.parsedPath.resource]?.[state.request.method];\n return handler\n ? await handler(state)\n : scimError(404, \"notFound\", \"SCIM resource not found.\");\n } catch (error) {\n if (\n error instanceof Error &&\n error.message === \"Unsupported SCIM filter.\"\n ) {\n return scimError(400, \"invalidFilter\", error.message);\n }\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n ) {\n const code = error.data.code as string;\n const status =\n code === \"MISSING_BEARER_TOKEN\" || code === \"INVALID_API_KEY\"\n ? 401\n : 400;\n return scimError(status, code, error.data.message);\n }\n throw error;\n }\n };\n\n addSSORoutes(http, {\n routeBase: ENTERPRISE_CONTROL_ROUTE_BASE,\n convertErrorsToResponse,\n handleSamlMetadata: async (ctx, _request, runtimeRoute) => {\n const { loaded } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n return new Response(\n createEnterpriseSamlMetadataXml({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: loaded.source,\n config: loaded.config,\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/xml\" },\n },\n );\n },\n handleSamlSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw Cv.error({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing sign-in verifier.\",\n });\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const state = generateRandomString(24, INVITE_TOKEN_ALPHABET);\n const signInRequest = createEnterpriseSamlSignInRequest({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n state,\n signature: `saml ${enterprise._id} pending ${state}`,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n const signature = `saml ${enterprise._id} ${signInRequest.requestId} ${state}`;\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const redirectCookies =\n redirectTo !== null\n ? [\n redirectToParamCookie(\n enterpriseSamlProviderId(enterprise._id),\n redirectTo,\n ),\n ]\n : [];\n const relayState = encodeEnterpriseSamlRelayState({\n source: { kind: \"enterprise\", id: enterprise._id },\n signature,\n requestId: signInRequest.requestId,\n state,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n if (signInRequest.binding === \"redirect\" && signInRequest.redirectUrl) {\n const redirectUrl = new URL(signInRequest.redirectUrl);\n redirectUrl.searchParams.set(\"RelayState\", relayState);\n const headers = new Headers({\n Location: redirectUrl.toString(),\n });\n for (const { name, value, options } of redirectCookies as any) {\n headers.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers });\n }\n const response = createSamlPostBindingResponse({\n endpoint: signInRequest.post!.endpoint,\n parameter: \"SAMLRequest\",\n value: signInRequest.post!.value,\n relayState,\n });\n for (const { name, value, options } of redirectCookies as any) {\n response.headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return response;\n },\n handleOidcSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw Cv.error({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing sign-in verifier.\",\n });\n }\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(providerId, provider, oauthConfig);\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const headers_ = new Headers({ Location: redirect });\n for (const { name, value, options } of [\n ...cookies,\n ...(redirectTo !== null\n ? [redirectToParamCookie(providerId, redirectTo)]\n : []),\n ] as any) {\n headers_.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, {\n status: 302,\n headers: headers_,\n });\n },\n handleOidcCallback: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const cookies = getCookies(request);\n const maybeRedirectTo = useRedirectToParam(providerId, cookies);\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n const params = url.searchParams;\n const result = (await Fx.run(\n handleOAuthCallback(\n providerId,\n provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n )) as any;\n const extraFields = oidc.extraFields as\n | Record<string, string>\n | undefined;\n let profile = result.profile as Record<string, unknown>;\n if (extraFields && typeof profile === \"object\" && profile) {\n const extend: Record<string, unknown> = {};\n for (const [claimName, fieldName] of Object.entries(extraFields)) {\n if (claimName in profile) {\n extend[fieldName] = profile[claimName];\n }\n }\n if (Object.keys(extend).length > 0) {\n profile = { ...profile, extend };\n }\n }\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: result.providerAccountId,\n profile,\n signature: result.signature,\n accountExtend: {\n identity: {\n protocol: \"oidc\",\n enterpriseId: enterprise._id,\n subject: result.providerAccountId,\n issuer: typeof oidc.issuer === \"string\" ? oidc.issuer : undefined,\n discoveryUrl:\n typeof oidc.discoveryUrl === \"string\"\n ? oidc.discoveryUrl\n : undefined,\n },\n },\n });\n const headers = new Headers({\n Location: setURLSearchParam(destinationUrl, \"code\", verificationCode),\n });\n for (const { name, value, options } of result.cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n if (maybeRedirectTo) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(\n maybeRedirectTo.updatedCookie.name,\n maybeRedirectTo.updatedCookie.value,\n maybeRedirectTo.updatedCookie.options as any,\n ),\n );\n }\n return new Response(null, { status: 302, headers });\n },\n handleSamlAcs,\n handleSamlSlo,\n handleScimRequest,\n scimError,\n });\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { CorsConfig, HttpKeyContext } from "./types.js";
2
- import * as convex_server0 from "convex/server";
2
+ import * as convex_server62 from "convex/server";
3
3
  import { GenericActionCtx, GenericDataModel, HttpRouter } from "convex/server";
4
4
 
5
5
  //#region src/server/http.d.ts
@@ -13,7 +13,7 @@ declare function createHttpAction(auth: {
13
13
  action: string;
14
14
  };
15
15
  cors?: CorsConfig;
16
- }) => convex_server0.PublicHttpAction;
16
+ }) => convex_server62.PublicHttpAction;
17
17
  declare function createHttpRoute(wrapAction: ReturnType<typeof createHttpAction>): (http: {
18
18
  route: (config: any) => void;
19
19
  }, routeConfig: {
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","names":[],"sources":["../../src/server/http.ts"],"mappings":";;;;;iBAgBgB,gBAAA,CAAiB,IAAA;EAC/B,GAAA;IAAO,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,MAAA,aAAmB,OAAA;EAAA;AAAA,KAG7D,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA,oBACxB,OAAA;EACE,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA,MAAU,cAAA,CAClB,gBAAA;AAAA,iBA2IW,eAAA,CACd,UAAA,EAAY,UAAA,QAAkB,gBAAA,KAG5B,IAAA;EAAQ,KAAA,GAAQ,MAAA;AAAA,GAChB,WAAA;EACE,IAAA;EACA,MAAA;EACA,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA;EACxB,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA;AAAA,iBA+BG,uBAAA,CACd,eAAA,UACA,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA,KAEpD,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAO,OAAA,CAAA,QAAA;AAAA,iBA2C5C,UAAA,CACd,OAAA,EAAS,OAAA,GACR,MAAA;AAAA,KAIS,eAAA;EACV,QAAA;EACA,YAAA;EACA,QAAA;EACA,IAAA;AAAA;AAAA,iBA2Bc,eAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,OAAA;AAAA;AAAA,iBA0CY,aAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,YAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,cAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA;AAAA,iBAwBD,YAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,uBAAA,SAAgC,uBAAA;EAChC,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,iBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,SAAA,GAAY,MAAA,UAAgB,QAAA,UAAkB,MAAA,aAAmB,QAAA;AAAA"}
1
+ {"version":3,"file":"http.d.ts","names":[],"sources":["../../src/server/http.ts"],"mappings":";;;;;iBAcgB,gBAAA,CAAiB,IAAA;EAC/B,GAAA;IAAO,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,MAAA,aAAmB,OAAA;EAAA;AAAA,KAG7D,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA,oBACxB,OAAA;EACE,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA,MAAU,eAAA,CAClB,gBAAA;AAAA,iBA6IW,eAAA,CACd,UAAA,EAAY,UAAA,QAAkB,gBAAA,KAG5B,IAAA;EAAQ,KAAA,GAAQ,MAAA;AAAA,GAChB,WAAA;EACE,IAAA;EACA,MAAA;EACA,OAAA,GACE,GAAA,EAAK,gBAAA,CAAiB,gBAAA,IAAoB,cAAA,EAC1C,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA,GAAW,MAAA;EACxB,KAAA;IAAU,QAAA;IAAkB,MAAA;EAAA;EAC5B,IAAA,GAAO,UAAA;AAAA;AAAA,iBA+BG,uBAAA,CACd,eAAA,UACA,MAAA,GAAS,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA,KAEpD,GAAA,EAAK,gBAAA,OAAuB,OAAA,EAAS,OAAA,KAAO,OAAA,CAAA,QAAA;AAAA,iBAiD5C,UAAA,CACd,OAAA,EAAS,OAAA,GACR,MAAA;AAAA,KAIS,eAAA;EACV,QAAA;EACA,YAAA;EACA,QAAA;EACA,IAAA;AAAA;AAAA,iBA2Bc,eAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,OAAA;AAAA;AAAA,iBA0CY,aAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,YAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,cAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;AAAA;AAAA,iBAwBD,YAAA,CACd,IAAA,EAAM,UAAA,EACN,IAAA;EACE,SAAA;EACA,uBAAA,SAAgC,uBAAA;EAChC,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,gBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,kBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,aAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,EACT,KAAA,EAAO,eAAA,KACJ,OAAA,CAAQ,QAAA;EACb,iBAAA,GACE,GAAA,EAAK,gBAAA,OACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,QAAA;EACb,SAAA,GAAY,MAAA,UAAgB,QAAA,UAAkB,MAAA,aAAmB,QAAA;AAAA"}
@@ -1,7 +1,6 @@
1
- import { isAuthError } from "./errors.js";
2
- import { AuthError } from "./authError.js";
3
1
  import { logError } from "./utils.js";
4
2
  import { Fx } from "@robelest/fx";
3
+ import { Cv } from "@robelest/fx/convex";
5
4
  import { httpActionGeneric } from "convex/server";
6
5
  import { ConvexError } from "convex/values";
7
6
  import { parse } from "cookie";
@@ -30,21 +29,15 @@ function createHttpAction(auth) {
30
29
  }
31
30
  });
32
31
  const rawKey = authHeader.slice(7);
33
- const keyResult = await Fx.run(Fx.from({
34
- ok: () => auth.key.verify(genericCtx, rawKey),
35
- err: (error) => error
36
- }).pipe(Fx.fold({
37
- ok: (result$1) => ({
38
- ok: true,
39
- value: result$1
40
- }),
41
- err: (error) => ({
42
- ok: false,
43
- error
44
- })
32
+ const keyResult = await Fx.run(Fx.attempt(() => auth.key.verify(genericCtx, rawKey), (result$1) => ({
33
+ ok: true,
34
+ value: result$1
35
+ }), (error) => ({
36
+ ok: false,
37
+ error
45
38
  })));
46
39
  if (!keyResult.ok) {
47
- if (isAuthError(keyResult.error)) {
40
+ if (keyResult.error instanceof ConvexError && typeof keyResult.error.data === "object" && keyResult.error.data !== null && "code" in keyResult.error.data && "message" in keyResult.error.data) {
48
41
  const { code, message } = keyResult.error.data;
49
42
  return new Response(JSON.stringify({
50
43
  error: message,
@@ -142,7 +135,7 @@ function convertErrorsToResponse(errorStatusCode, action) {
142
135
  ok: () => action(ctx, request),
143
136
  err: (error) => error
144
137
  }).pipe(Fx.recover((error) => {
145
- if (isAuthError(error)) return Fx.succeed(new Response(JSON.stringify({
138
+ if (error instanceof ConvexError && typeof error.data === "object" && error.data !== null && "code" in error.data && "message" in error.data) return Fx.succeed(new Response(JSON.stringify({
146
139
  code: error.data.code,
147
140
  message: error.data.message
148
141
  }), {
@@ -235,7 +228,10 @@ function addSSORoutes(http, deps) {
235
228
  method: "GET",
236
229
  handler: httpActionGeneric(deps.convertErrorsToResponse(400, async (ctx, request) => {
237
230
  const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
238
- if (!route) throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
231
+ if (!route) throw Cv.error({
232
+ code: "INVALID_PARAMETERS",
233
+ message: "Invalid enterprise runtime path."
234
+ });
239
235
  if (route.protocol === "saml" && route.rest.length === 1) {
240
236
  if (route.rest[0] === "metadata") return await deps.handleSamlMetadata(ctx, request, route);
241
237
  if (route.rest[0] === "signin") return await deps.handleSamlSignIn(ctx, request, route);
@@ -247,7 +243,10 @@ function addSSORoutes(http, deps) {
247
243
  if (route.rest[0] === "callback") return await deps.handleOidcCallback(ctx, request, route);
248
244
  }
249
245
  if (route.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
250
- throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
246
+ throw Cv.error({
247
+ code: "INVALID_PARAMETERS",
248
+ message: "Invalid enterprise runtime path."
249
+ });
251
250
  }))
252
251
  });
253
252
  http.route({
@@ -260,7 +259,10 @@ function addSSORoutes(http, deps) {
260
259
  if (route.rest[0] === "slo") return await deps.handleSamlSlo(ctx, request, route);
261
260
  }
262
261
  if (route?.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
263
- throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
262
+ throw Cv.error({
263
+ code: "INVALID_PARAMETERS",
264
+ message: "Invalid enterprise runtime path."
265
+ });
264
266
  }))
265
267
  });
266
268
  http.route({
@@ -269,7 +271,10 @@ function addSSORoutes(http, deps) {
269
271
  handler: httpActionGeneric(deps.convertErrorsToResponse(400, async (ctx, request) => {
270
272
  const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
271
273
  if (route?.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
272
- throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
274
+ throw Cv.error({
275
+ code: "INVALID_PARAMETERS",
276
+ message: "Invalid enterprise runtime path."
277
+ });
273
278
  }))
274
279
  });
275
280
  for (const method of ["PATCH", "DELETE"]) http.route({
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","names":["result","parseCookies"],"sources":["../../src/server/http.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n httpActionGeneric,\n} from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { parse as parseCookies } from \"cookie\";\n\nimport { isAuthError } from \"./errors\";\nimport { Fx } from \"@robelest/fx\";\n\nimport { AuthError } from \"./authError\";\nimport type { CorsConfig, HttpKeyContext } from \"./types\";\nimport { logError } from \"./utils\";\n\nexport function createHttpAction(auth: {\n key: { verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any> };\n}) {\n return (\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>,\n options?: {\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = options?.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n return httpActionGeneric(async (genericCtx, request) => {\n return Fx.run(\n Fx.from({\n ok: async () => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error: \"Missing or malformed Authorization: Bearer header.\",\n code: \"MISSING_BEARER_TOKEN\",\n }),\n {\n status: 401,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n const rawKey = authHeader.slice(7);\n\n const keyResult = await Fx.run(\n Fx.from({\n ok: () => auth.key.verify(genericCtx, rawKey),\n err: (error) => error,\n }).pipe(\n Fx.fold({\n ok: (result) => ({ ok: true, value: result }) as const,\n err: (error) => ({ ok: false, error }) as const,\n }),\n ),\n );\n\n if (!keyResult.ok) {\n if (isAuthError(keyResult.error)) {\n const { code, message } = keyResult.error.data as {\n code: string;\n message: string;\n };\n return new Response(JSON.stringify({ error: message, code }), {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n throw keyResult.error;\n }\n\n if (\n options?.scope &&\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error: \"This API key does not have the required permissions.\",\n code: \"SCOPE_CHECK_FAILED\",\n }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n\n const enrichedCtx = Object.assign(genericCtx, {\n key: {\n userId: keyResult.value.userId,\n keyId: keyResult.value.keyId,\n scopes: keyResult.value.scopes,\n },\n });\n const result = await handler(enrichedCtx, request);\n\n if (result instanceof Response) {\n const headers = new Headers(result.headers);\n for (const [k, val] of Object.entries(corsHeaders)) {\n if (!headers.has(k)) headers.set(k, val);\n }\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers,\n });\n }\n\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n return Fx.succeed(\n new Response(\n JSON.stringify({\n error: \"An unexpected error occurred.\",\n code: \"INTERNAL_ERROR\",\n }),\n {\n status: 500,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n ),\n );\n }),\n ),\n );\n });\n };\n}\n\nexport function createHttpRoute(\n wrapAction: ReturnType<typeof createHttpAction>,\n) {\n return (\n http: { route: (config: any) => void },\n routeConfig: {\n path: string;\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>;\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = routeConfig.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n http.route({\n path: routeConfig.path,\n method: \"OPTIONS\",\n handler: httpActionGeneric(async () => {\n return new Response(null, { status: 204, headers: corsHeaders });\n }),\n });\n\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: wrapAction(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n };\n}\n\nexport function convertErrorsToResponse(\n errorStatusCode: number,\n action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,\n) {\n return async (ctx: GenericActionCtx<any>, request: Request) => {\n return Fx.run(\n Fx.from({\n ok: () => action(ctx, request),\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n if (isAuthError(error)) {\n return Fx.succeed(\n new Response(\n JSON.stringify({\n code: error.data.code,\n message: error.data.message,\n }),\n {\n status: errorStatusCode,\n headers: { \"Content-Type\": \"application/json\" },\n },\n ),\n );\n } else if (error instanceof ConvexError) {\n return Fx.succeed(\n new Response(null, {\n status: errorStatusCode,\n statusText:\n typeof error.data === \"string\" ? error.data : \"Error\",\n }),\n );\n } else {\n logError(error);\n return Fx.succeed(\n new Response(null, {\n status: 500,\n statusText: \"Internal Server Error\",\n }),\n );\n }\n }),\n ),\n );\n };\n}\n\nexport function getCookies(\n request: Request,\n): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n\nexport type SSORuntimeRoute = {\n pathname?: string;\n enterpriseId: string;\n protocol: \"oidc\" | \"saml\" | \"scim\";\n rest: string[];\n};\n\nfunction parseEnterpriseRuntimeRoute(\n pathname: string,\n routeBase: string,\n): SSORuntimeRoute | null {\n const runtimePrefix = `${routeBase}/`;\n const runtimeParts = pathname.startsWith(runtimePrefix)\n ? pathname.slice(runtimePrefix.length).split(\"/\").filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n if (\n runtimeEnterpriseId === undefined ||\n (protocol !== \"oidc\" && protocol !== \"saml\" && protocol !== \"scim\") ||\n rest.length === 0\n ) {\n return null;\n }\n return {\n pathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n };\n}\n\nexport function addOpenIdRoutes(\n http: HttpRouter,\n deps: {\n getIssuer: () => string;\n getJwks: () => string;\n },\n) {\n const cacheControl =\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\";\n\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n const issuer = deps.getIssuer();\n return new Response(\n JSON.stringify({\n issuer,\n jwks_uri: `${issuer}/.well-known/jwks.json`,\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n },\n );\n }),\n });\n\n http.route({\n path: \"/.well-known/jwks.json\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(deps.getJwks(), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n });\n }),\n });\n}\n\nexport function addAuthRoutes(\n http: HttpRouter,\n deps: {\n handleSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n handleCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n },\n) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(deps.handleSignIn),\n });\n\n const callbackHandler = httpActionGeneric(deps.handleCallback);\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackHandler,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackHandler,\n });\n}\n\nexport function addSSORoutes(\n http: HttpRouter,\n deps: {\n routeBase: string;\n convertErrorsToResponse: typeof convertErrorsToResponse;\n handleSamlMetadata: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlAcs: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSlo: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleScimRequest: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n scimError: (status: number, scimType: string, detail: string) => Response;\n },\n) {\n const routePrefix = `${deps.routeBase}/`;\n\n http.route({\n pathPrefix: routePrefix,\n method: \"GET\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n if (route.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"metadata\") {\n return await deps.handleSamlMetadata(ctx, request, route);\n }\n if (route.rest[0] === \"signin\") {\n return await deps.handleSamlSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route.protocol === \"oidc\" && route.rest.length === 1) {\n if (route.rest[0] === \"signin\") {\n return await deps.handleOidcSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"callback\") {\n return await deps.handleOidcCallback(ctx, request, route);\n }\n }\n if (route.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"POST\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"PUT\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: routePrefix,\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route || route.protocol !== \"scim\" || route.rest[0] !== \"v2\") {\n return deps.scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await deps.handleScimRequest(ctx, request);\n }),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"http.js","names":["result","parseCookies"],"sources":["../../src/server/http.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n httpActionGeneric,\n} from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { parse as parseCookies } from \"cookie\";\n\nimport type { CorsConfig, HttpKeyContext } from \"./types\";\nimport { logError } from \"./utils\";\n\nexport function createHttpAction(auth: {\n key: { verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any> };\n}) {\n return (\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>,\n options?: {\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = options?.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n return httpActionGeneric(async (genericCtx, request) => {\n return Fx.run(\n Fx.from({\n ok: async () => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error: \"Missing or malformed Authorization: Bearer header.\",\n code: \"MISSING_BEARER_TOKEN\",\n }),\n {\n status: 401,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n const rawKey = authHeader.slice(7);\n\n const keyResult = await Fx.run(\n Fx.attempt(\n () => auth.key.verify(genericCtx, rawKey),\n (result) => ({ ok: true, value: result }) as const,\n (error) => ({ ok: false, error }) as const,\n ),\n );\n\n if (!keyResult.ok) {\n if (\n keyResult.error instanceof ConvexError &&\n typeof keyResult.error.data === \"object\" &&\n keyResult.error.data !== null &&\n \"code\" in keyResult.error.data &&\n \"message\" in keyResult.error.data\n ) {\n const { code, message } = keyResult.error.data as {\n code: string;\n message: string;\n };\n return new Response(JSON.stringify({ error: message, code }), {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n throw keyResult.error;\n }\n\n if (\n options?.scope &&\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error: \"This API key does not have the required permissions.\",\n code: \"SCOPE_CHECK_FAILED\",\n }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n\n const enrichedCtx = Object.assign(genericCtx, {\n key: {\n userId: keyResult.value.userId,\n keyId: keyResult.value.keyId,\n scopes: keyResult.value.scopes,\n },\n });\n const result = await handler(enrichedCtx, request);\n\n if (result instanceof Response) {\n const headers = new Headers(result.headers);\n for (const [k, val] of Object.entries(corsHeaders)) {\n if (!headers.has(k)) headers.set(k, val);\n }\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers,\n });\n }\n\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n return Fx.succeed(\n new Response(\n JSON.stringify({\n error: \"An unexpected error occurred.\",\n code: \"INTERNAL_ERROR\",\n }),\n {\n status: 500,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n ),\n );\n }),\n ),\n );\n });\n };\n}\n\nexport function createHttpRoute(\n wrapAction: ReturnType<typeof createHttpAction>,\n) {\n return (\n http: { route: (config: any) => void },\n routeConfig: {\n path: string;\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>;\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = routeConfig.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n http.route({\n path: routeConfig.path,\n method: \"OPTIONS\",\n handler: httpActionGeneric(async () => {\n return new Response(null, { status: 204, headers: corsHeaders });\n }),\n });\n\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: wrapAction(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n };\n}\n\nexport function convertErrorsToResponse(\n errorStatusCode: number,\n action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,\n) {\n return async (ctx: GenericActionCtx<any>, request: Request) => {\n return Fx.run(\n Fx.from({\n ok: () => action(ctx, request),\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n ) {\n return Fx.succeed(\n new Response(\n JSON.stringify({\n code: error.data.code,\n message: error.data.message,\n }),\n {\n status: errorStatusCode,\n headers: { \"Content-Type\": \"application/json\" },\n },\n ),\n );\n } else if (error instanceof ConvexError) {\n return Fx.succeed(\n new Response(null, {\n status: errorStatusCode,\n statusText:\n typeof error.data === \"string\" ? error.data : \"Error\",\n }),\n );\n } else {\n logError(error);\n return Fx.succeed(\n new Response(null, {\n status: 500,\n statusText: \"Internal Server Error\",\n }),\n );\n }\n }),\n ),\n );\n };\n}\n\nexport function getCookies(\n request: Request,\n): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n\nexport type SSORuntimeRoute = {\n pathname?: string;\n enterpriseId: string;\n protocol: \"oidc\" | \"saml\" | \"scim\";\n rest: string[];\n};\n\nfunction parseEnterpriseRuntimeRoute(\n pathname: string,\n routeBase: string,\n): SSORuntimeRoute | null {\n const runtimePrefix = `${routeBase}/`;\n const runtimeParts = pathname.startsWith(runtimePrefix)\n ? pathname.slice(runtimePrefix.length).split(\"/\").filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n if (\n runtimeEnterpriseId === undefined ||\n (protocol !== \"oidc\" && protocol !== \"saml\" && protocol !== \"scim\") ||\n rest.length === 0\n ) {\n return null;\n }\n return {\n pathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n };\n}\n\nexport function addOpenIdRoutes(\n http: HttpRouter,\n deps: {\n getIssuer: () => string;\n getJwks: () => string;\n },\n) {\n const cacheControl =\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\";\n\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n const issuer = deps.getIssuer();\n return new Response(\n JSON.stringify({\n issuer,\n jwks_uri: `${issuer}/.well-known/jwks.json`,\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n },\n );\n }),\n });\n\n http.route({\n path: \"/.well-known/jwks.json\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(deps.getJwks(), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n });\n }),\n });\n}\n\nexport function addAuthRoutes(\n http: HttpRouter,\n deps: {\n handleSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n handleCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n },\n) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(deps.handleSignIn),\n });\n\n const callbackHandler = httpActionGeneric(deps.handleCallback);\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackHandler,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackHandler,\n });\n}\n\nexport function addSSORoutes(\n http: HttpRouter,\n deps: {\n routeBase: string;\n convertErrorsToResponse: typeof convertErrorsToResponse;\n handleSamlMetadata: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlAcs: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSlo: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleScimRequest: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n scimError: (status: number, scimType: string, detail: string) => Response;\n },\n) {\n const routePrefix = `${deps.routeBase}/`;\n\n http.route({\n pathPrefix: routePrefix,\n method: \"GET\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }\n if (route.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"metadata\") {\n return await deps.handleSamlMetadata(ctx, request, route);\n }\n if (route.rest[0] === \"signin\") {\n return await deps.handleSamlSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route.protocol === \"oidc\" && route.rest.length === 1) {\n if (route.rest[0] === \"signin\") {\n return await deps.handleOidcSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"callback\") {\n return await deps.handleOidcCallback(ctx, request, route);\n }\n }\n if (route.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"POST\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"PUT\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: routePrefix,\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route || route.protocol !== \"scim\" || route.rest[0] !== \"v2\") {\n return deps.scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await deps.handleScimRequest(ctx, request);\n }),\n });\n }\n}\n"],"mappings":"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"}
@@ -1,10 +1,13 @@
1
- import { AuthError } from "./authError.js";
1
+ import { Cv } from "@robelest/fx/convex";
2
2
 
3
3
  //#region src/server/identity.ts
4
4
  /** @internal */
5
5
  function userIdFromIdentitySubject(subject) {
6
6
  const [userId, ...rest] = subject.split("|");
7
- if (typeof userId !== "string" || userId.length === 0 || rest.length === 0 || rest.some((segment) => segment.length === 0)) throw new AuthError("INTERNAL_ERROR", "Authenticated identity subject is malformed.");
7
+ if (typeof userId !== "string" || userId.length === 0 || rest.length === 0 || rest.some((segment) => segment.length === 0)) throw Cv.error({
8
+ code: "INTERNAL_ERROR",
9
+ message: "Authenticated identity subject is malformed."
10
+ });
8
11
  return userId;
9
12
  }
10
13
 
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","names":[],"sources":["../../src/server/identity.ts"],"sourcesContent":["import { AuthError } from \"./authError\";\n\n/** @internal */\nexport function userIdFromIdentitySubject(subject: string): string {\n const [userId, ...rest] = subject.split(\"|\");\n if (\n typeof userId !== \"string\" ||\n userId.length === 0 ||\n rest.length === 0 ||\n rest.some((segment) => segment.length === 0)\n ) {\n throw new AuthError(\n \"INTERNAL_ERROR\",\n \"Authenticated identity subject is malformed.\",\n );\n }\n return userId;\n}\n"],"mappings":";;;;AAGA,SAAgB,0BAA0B,SAAyB;CACjE,MAAM,CAAC,QAAQ,GAAG,QAAQ,QAAQ,MAAM,IAAI;AAC5C,KACE,OAAO,WAAW,YAClB,OAAO,WAAW,KAClB,KAAK,WAAW,KAChB,KAAK,MAAM,YAAY,QAAQ,WAAW,EAAE,CAE5C,OAAM,IAAI,UACR,kBACA,+CACD;AAEH,QAAO"}
1
+ {"version":3,"file":"identity.js","names":[],"sources":["../../src/server/identity.ts"],"sourcesContent":["import { Cv } from \"@robelest/fx/convex\";\n\n/** @internal */\nexport function userIdFromIdentitySubject(subject: string): string {\n const [userId, ...rest] = subject.split(\"|\");\n if (\n typeof userId !== \"string\" ||\n userId.length === 0 ||\n rest.length === 0 ||\n rest.some((segment) => segment.length === 0)\n ) {\n throw Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"Authenticated identity subject is malformed.\",\n });\n }\n return userId;\n}\n"],"mappings":";;;;AAGA,SAAgB,0BAA0B,SAAyB;CACjE,MAAM,CAAC,QAAQ,GAAG,QAAQ,QAAQ,MAAM,IAAI;AAC5C,KACE,OAAO,WAAW,YAClB,OAAO,WAAW,KAClB,KAAK,WAAW,KAChB,KAAK,MAAM,YAAY,QAAQ,WAAW,EAAE,CAE5C,OAAM,GAAG,MAAM;EACb,MAAM;EACN,SAAS;EACV,CAAC;AAEJ,QAAO"}
@@ -1,4 +1,4 @@
1
- import { AuthApi, AuthApiBase, AuthConfig, AuthCtx, ConvexAuthResult, InferAuth, InferClientApi, UserDoc, createAuth } from "./auth.js";
1
+ import { AuthApi, AuthApiBase, AuthConfig, AuthContext, AuthCtx, AuthCtxConfig, ConvexAuthResult, InferAuth, InferClientApi, UserDoc, createAuth } from "./auth.js";
2
2
  import { EnterpriseAdminAuthorizationInput, EnterpriseAdminPermission, EnterpriseAuthorizer, EnterpriseMountOptions, enterprise, scim, sso } from "./mounts.js";
3
3
  import { AuthCookie, AuthCookieConfig, AuthCookies, RefreshResult, ServerOptions, authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./ssr.js";
4
- export { type AuthApi, type AuthApiBase, type AuthConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, AuthCtx, type ConvexAuthResult, type EnterpriseAdminAuthorizationInput, type EnterpriseAdminPermission, type EnterpriseAuthorizer, type EnterpriseMountOptions, type InferAuth, type InferClientApi, type RefreshResult, type ServerOptions, type UserDoc, authCookieNames, createAuth, enterprise, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };
4
+ export { type AuthApi, type AuthApiBase, type AuthConfig, type AuthContext, type AuthCookie, type AuthCookieConfig, type AuthCookies, AuthCtx, type AuthCtxConfig, type ConvexAuthResult, type EnterpriseAdminAuthorizationInput, type EnterpriseAdminPermission, type EnterpriseAuthorizer, type EnterpriseMountOptions, type InferAuth, type InferClientApi, type RefreshResult, type ServerOptions, type UserDoc, authCookieNames, createAuth, enterprise, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };