@robelest/convex-auth 0.0.4-preview.13 → 0.0.4-preview.16

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 (328) hide show
  1. package/README.md +140 -9
  2. package/dist/bin.cjs +5957 -5478
  3. package/dist/client/index.d.ts +3 -7
  4. package/dist/client/index.d.ts.map +1 -1
  5. package/dist/client/index.js +27 -26
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/component/_generated/api.d.ts +14 -0
  8. package/dist/component/_generated/api.d.ts.map +1 -1
  9. package/dist/component/_generated/api.js.map +1 -1
  10. package/dist/component/_generated/component.d.ts +1672 -24
  11. package/dist/component/_generated/component.d.ts.map +1 -1
  12. package/dist/component/convex.config.d.ts +2 -2
  13. package/dist/component/convex.config.d.ts.map +1 -1
  14. package/dist/component/index.d.ts +1 -1
  15. package/dist/component/index.js +2 -2
  16. package/dist/component/model.d.ts +153 -0
  17. package/dist/component/model.d.ts.map +1 -0
  18. package/dist/component/model.js +343 -0
  19. package/dist/component/model.js.map +1 -0
  20. package/dist/component/providers/sso.d.ts +1 -1
  21. package/dist/component/public/enterprise.d.ts +54 -0
  22. package/dist/component/public/enterprise.d.ts.map +1 -0
  23. package/dist/component/public/enterprise.js +515 -0
  24. package/dist/component/public/enterprise.js.map +1 -0
  25. package/dist/component/public/factors.d.ts +52 -0
  26. package/dist/component/public/factors.d.ts.map +1 -0
  27. package/dist/component/public/factors.js +285 -0
  28. package/dist/component/public/factors.js.map +1 -0
  29. package/dist/component/public/groups.d.ts +116 -0
  30. package/dist/component/public/groups.d.ts.map +1 -0
  31. package/dist/component/public/groups.js +596 -0
  32. package/dist/component/public/groups.js.map +1 -0
  33. package/dist/component/public/identity.d.ts +93 -0
  34. package/dist/component/public/identity.d.ts.map +1 -0
  35. package/dist/component/public/identity.js +426 -0
  36. package/dist/component/public/identity.js.map +1 -0
  37. package/dist/component/public/keys.d.ts +41 -0
  38. package/dist/component/public/keys.d.ts.map +1 -0
  39. package/dist/component/public/keys.js +157 -0
  40. package/dist/component/public/keys.js.map +1 -0
  41. package/dist/component/public/shared.d.ts +26 -0
  42. package/dist/component/public/shared.d.ts.map +1 -0
  43. package/dist/component/public/shared.js +32 -0
  44. package/dist/component/public/shared.js.map +1 -0
  45. package/dist/component/public.d.ts +9 -321
  46. package/dist/component/public.d.ts.map +1 -1
  47. package/dist/component/public.js +6 -2145
  48. package/dist/component/schema.d.ts +406 -260
  49. package/dist/component/schema.js +37 -32
  50. package/dist/component/schema.js.map +1 -1
  51. package/dist/component/server/auth.d.ts +161 -15
  52. package/dist/component/server/auth.d.ts.map +1 -1
  53. package/dist/component/server/auth.js +100 -7
  54. package/dist/component/server/auth.js.map +1 -1
  55. package/dist/component/server/cookies.js +3 -0
  56. package/dist/component/server/cookies.js.map +1 -1
  57. package/dist/component/server/db.js +1 -0
  58. package/dist/component/server/db.js.map +1 -1
  59. package/dist/component/server/device.js +3 -1
  60. package/dist/component/server/device.js.map +1 -1
  61. package/dist/component/server/domains/core.js +629 -0
  62. package/dist/component/server/domains/core.js.map +1 -0
  63. package/dist/component/server/domains/sso.js +884 -0
  64. package/dist/component/server/domains/sso.js.map +1 -0
  65. package/dist/component/server/factory.d.ts +136 -0
  66. package/dist/component/server/factory.d.ts.map +1 -0
  67. package/dist/component/server/factory.js +1134 -0
  68. package/dist/component/server/factory.js.map +1 -0
  69. package/dist/component/server/fx.js +2 -1
  70. package/dist/component/server/fx.js.map +1 -1
  71. package/dist/component/server/http.js +287 -0
  72. package/dist/component/server/http.js.map +1 -0
  73. package/dist/component/server/identity.js +13 -0
  74. package/dist/component/server/identity.js.map +1 -0
  75. package/dist/component/server/keys.js +4 -0
  76. package/dist/component/server/keys.js.map +1 -1
  77. package/dist/component/server/mutations/account.js +1 -1
  78. package/dist/component/server/mutations/index.js +2 -2
  79. package/dist/component/server/mutations/index.js.map +1 -1
  80. package/dist/component/server/mutations/invalidate.js +1 -1
  81. package/dist/component/server/mutations/oauth.js +10 -7
  82. package/dist/component/server/mutations/oauth.js.map +1 -1
  83. package/dist/component/server/mutations/refresh.js +1 -1
  84. package/dist/component/server/mutations/register.js +1 -1
  85. package/dist/component/server/mutations/retrieve.js +1 -1
  86. package/dist/component/server/mutations/signature.js +1 -1
  87. package/dist/component/server/mutations/store.js +6 -3
  88. package/dist/component/server/mutations/store.js.map +1 -1
  89. package/dist/component/server/mutations/verify.js +1 -1
  90. package/dist/component/server/oauth.js +3 -0
  91. package/dist/component/server/oauth.js.map +1 -1
  92. package/dist/component/server/passkey.js +3 -2
  93. package/dist/component/server/passkey.js.map +1 -1
  94. package/dist/component/server/provider.js +2 -0
  95. package/dist/component/server/provider.js.map +1 -1
  96. package/dist/component/server/providers.js +10 -0
  97. package/dist/component/server/providers.js.map +1 -1
  98. package/dist/component/server/ratelimit.js +3 -0
  99. package/dist/component/server/ratelimit.js.map +1 -1
  100. package/dist/component/server/redirects.js +2 -0
  101. package/dist/component/server/redirects.js.map +1 -1
  102. package/dist/component/server/refresh.js +5 -0
  103. package/dist/component/server/refresh.js.map +1 -1
  104. package/dist/component/server/sessions.js +5 -0
  105. package/dist/component/server/sessions.js.map +1 -1
  106. package/dist/component/server/signin.js +2 -1
  107. package/dist/component/server/signin.js.map +1 -1
  108. package/dist/component/server/sso.js +166 -19
  109. package/dist/component/server/sso.js.map +1 -1
  110. package/dist/component/server/tokens.js +1 -0
  111. package/dist/component/server/tokens.js.map +1 -1
  112. package/dist/component/server/totp.js +4 -2
  113. package/dist/component/server/totp.js.map +1 -1
  114. package/dist/component/server/types.d.ts +106 -38
  115. package/dist/component/server/types.d.ts.map +1 -1
  116. package/dist/component/server/types.js.map +1 -1
  117. package/dist/component/server/users.js +1 -0
  118. package/dist/component/server/users.js.map +1 -1
  119. package/dist/component/server/utils.js +44 -2
  120. package/dist/component/server/utils.js.map +1 -1
  121. package/dist/providers/anonymous.d.ts +1 -1
  122. package/dist/providers/credentials.d.ts +1 -1
  123. package/dist/providers/password.d.ts +1 -1
  124. package/dist/providers/sso.d.ts +1 -1
  125. package/dist/providers/sso.js.map +1 -1
  126. package/dist/server/auth.d.ts +163 -17
  127. package/dist/server/auth.d.ts.map +1 -1
  128. package/dist/server/auth.js +100 -7
  129. package/dist/server/auth.js.map +1 -1
  130. package/dist/server/cookies.d.ts +1 -38
  131. package/dist/server/cookies.js +3 -0
  132. package/dist/server/cookies.js.map +1 -1
  133. package/dist/server/db.d.ts +1 -125
  134. package/dist/server/db.js +1 -0
  135. package/dist/server/db.js.map +1 -1
  136. package/dist/server/device.d.ts +1 -24
  137. package/dist/server/device.js +3 -1
  138. package/dist/server/device.js.map +1 -1
  139. package/dist/server/domains/core.d.ts +434 -0
  140. package/dist/server/domains/core.d.ts.map +1 -0
  141. package/dist/server/domains/core.js +629 -0
  142. package/dist/server/domains/core.js.map +1 -0
  143. package/dist/server/domains/sso.d.ts +409 -0
  144. package/dist/server/domains/sso.d.ts.map +1 -0
  145. package/dist/server/domains/sso.js +884 -0
  146. package/dist/server/domains/sso.js.map +1 -0
  147. package/dist/server/enterpriseValidators.d.ts +1 -0
  148. package/dist/server/enterpriseValidators.js +60 -0
  149. package/dist/server/enterpriseValidators.js.map +1 -0
  150. package/dist/server/factory.d.ts +136 -0
  151. package/dist/server/factory.d.ts.map +1 -0
  152. package/dist/server/factory.js +1134 -0
  153. package/dist/server/factory.js.map +1 -0
  154. package/dist/server/fx.d.ts +1 -16
  155. package/dist/server/fx.d.ts.map +1 -1
  156. package/dist/server/fx.js +1 -0
  157. package/dist/server/fx.js.map +1 -1
  158. package/dist/server/http.d.ts +59 -0
  159. package/dist/server/http.d.ts.map +1 -0
  160. package/dist/server/http.js +287 -0
  161. package/dist/server/http.js.map +1 -0
  162. package/dist/server/identity.d.ts +1 -0
  163. package/dist/server/identity.js +13 -0
  164. package/dist/server/identity.js.map +1 -0
  165. package/dist/server/index.d.ts +468 -1
  166. package/dist/server/index.d.ts.map +1 -1
  167. package/dist/server/index.js +530 -36
  168. package/dist/server/index.js.map +1 -1
  169. package/dist/server/keys.d.ts +1 -57
  170. package/dist/server/keys.js +4 -0
  171. package/dist/server/keys.js.map +1 -1
  172. package/dist/server/mutations/account.d.ts +7 -7
  173. package/dist/server/mutations/account.d.ts.map +1 -1
  174. package/dist/server/mutations/code.d.ts +13 -13
  175. package/dist/server/mutations/code.d.ts.map +1 -1
  176. package/dist/server/mutations/index.d.ts +107 -107
  177. package/dist/server/mutations/index.d.ts.map +1 -1
  178. package/dist/server/mutations/index.js +1 -1
  179. package/dist/server/mutations/index.js.map +1 -1
  180. package/dist/server/mutations/invalidate.d.ts +5 -5
  181. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  182. package/dist/server/mutations/oauth.d.ts +10 -10
  183. package/dist/server/mutations/oauth.d.ts.map +1 -1
  184. package/dist/server/mutations/oauth.js +9 -6
  185. package/dist/server/mutations/oauth.js.map +1 -1
  186. package/dist/server/mutations/refresh.d.ts +4 -4
  187. package/dist/server/mutations/register.d.ts +12 -12
  188. package/dist/server/mutations/register.d.ts.map +1 -1
  189. package/dist/server/mutations/retrieve.d.ts +7 -7
  190. package/dist/server/mutations/signature.d.ts +5 -5
  191. package/dist/server/mutations/signin.d.ts +6 -6
  192. package/dist/server/mutations/signin.d.ts.map +1 -1
  193. package/dist/server/mutations/signout.d.ts +1 -1
  194. package/dist/server/mutations/store.d.ts +3 -2
  195. package/dist/server/mutations/store.d.ts.map +1 -1
  196. package/dist/server/mutations/store.js +6 -3
  197. package/dist/server/mutations/store.js.map +1 -1
  198. package/dist/server/mutations/verifier.d.ts +1 -1
  199. package/dist/server/mutations/verify.d.ts +11 -11
  200. package/dist/server/mutations/verify.d.ts.map +1 -1
  201. package/dist/server/oauth.d.ts +1 -59
  202. package/dist/server/oauth.js +3 -0
  203. package/dist/server/oauth.js.map +1 -1
  204. package/dist/server/passkey.d.ts.map +1 -1
  205. package/dist/server/passkey.js +3 -2
  206. package/dist/server/passkey.js.map +1 -1
  207. package/dist/server/provider.d.ts +1 -14
  208. package/dist/server/provider.d.ts.map +1 -1
  209. package/dist/server/provider.js +2 -0
  210. package/dist/server/provider.js.map +1 -1
  211. package/dist/server/providers.js +10 -0
  212. package/dist/server/providers.js.map +1 -1
  213. package/dist/server/ratelimit.d.ts +1 -22
  214. package/dist/server/ratelimit.js +3 -0
  215. package/dist/server/ratelimit.js.map +1 -1
  216. package/dist/server/redirects.d.ts +1 -10
  217. package/dist/server/redirects.js +2 -0
  218. package/dist/server/redirects.js.map +1 -1
  219. package/dist/server/refresh.d.ts +1 -37
  220. package/dist/server/refresh.js +5 -0
  221. package/dist/server/refresh.js.map +1 -1
  222. package/dist/server/sessions.d.ts +1 -28
  223. package/dist/server/sessions.js +5 -0
  224. package/dist/server/sessions.js.map +1 -1
  225. package/dist/server/signin.d.ts +1 -55
  226. package/dist/server/signin.js +2 -1
  227. package/dist/server/signin.js.map +1 -1
  228. package/dist/server/sso.d.ts +1 -348
  229. package/dist/server/sso.js +165 -18
  230. package/dist/server/sso.js.map +1 -1
  231. package/dist/server/templates.d.ts +1 -21
  232. package/dist/server/templates.js +1 -0
  233. package/dist/server/templates.js.map +1 -1
  234. package/dist/server/tokens.d.ts +1 -11
  235. package/dist/server/tokens.js +1 -0
  236. package/dist/server/tokens.js.map +1 -1
  237. package/dist/server/totp.d.ts +1 -23
  238. package/dist/server/totp.js +4 -2
  239. package/dist/server/totp.js.map +1 -1
  240. package/dist/server/types.d.ts +114 -77
  241. package/dist/server/types.d.ts.map +1 -1
  242. package/dist/server/types.js.map +1 -1
  243. package/dist/server/users.d.ts +1 -31
  244. package/dist/server/users.js +1 -0
  245. package/dist/server/users.js.map +1 -1
  246. package/dist/server/utils.d.ts +1 -27
  247. package/dist/server/utils.js +44 -2
  248. package/dist/server/utils.js.map +1 -1
  249. package/dist/server/version.d.ts +1 -1
  250. package/dist/server/version.js +1 -1
  251. package/dist/server/version.js.map +1 -1
  252. package/package.json +4 -5
  253. package/src/cli/bin.ts +5 -0
  254. package/src/cli/index.ts +22 -9
  255. package/src/cli/keys.ts +3 -0
  256. package/src/client/index.ts +36 -37
  257. package/src/component/_generated/api.ts +14 -0
  258. package/src/component/_generated/component.ts +2106 -9
  259. package/src/component/index.ts +3 -1
  260. package/src/component/model.ts +441 -0
  261. package/src/component/public/enterprise.ts +753 -0
  262. package/src/component/public/factors.ts +332 -0
  263. package/src/component/public/groups.ts +932 -0
  264. package/src/component/public/identity.ts +566 -0
  265. package/src/component/public/keys.ts +209 -0
  266. package/src/component/public/shared.ts +119 -0
  267. package/src/component/public.ts +5 -2965
  268. package/src/component/schema.ts +68 -63
  269. package/src/providers/sso.ts +1 -1
  270. package/src/server/auth.ts +413 -18
  271. package/src/server/cookies.ts +3 -0
  272. package/src/server/db.ts +3 -0
  273. package/src/server/device.ts +3 -1
  274. package/src/server/domains/core.ts +1071 -0
  275. package/src/server/domains/sso.ts +1749 -0
  276. package/src/server/enterpriseValidators.ts +93 -0
  277. package/src/server/factory.ts +2181 -0
  278. package/src/server/fx.ts +1 -0
  279. package/src/server/http.ts +529 -0
  280. package/src/server/identity.ts +18 -0
  281. package/src/server/index.ts +806 -40
  282. package/src/server/keys.ts +4 -0
  283. package/src/server/mutations/index.ts +1 -1
  284. package/src/server/mutations/oauth.ts +36 -8
  285. package/src/server/mutations/store.ts +6 -3
  286. package/src/server/oauth.ts +6 -0
  287. package/src/server/passkey.ts +3 -2
  288. package/src/server/provider.ts +2 -0
  289. package/src/server/providers.ts +20 -0
  290. package/src/server/ratelimit.ts +3 -0
  291. package/src/server/redirects.ts +2 -0
  292. package/src/server/refresh.ts +5 -0
  293. package/src/server/sessions.ts +5 -0
  294. package/src/server/signin.ts +1 -0
  295. package/src/server/sso.ts +259 -17
  296. package/src/server/templates.ts +1 -0
  297. package/src/server/tokens.ts +1 -0
  298. package/src/server/totp.ts +4 -2
  299. package/src/server/types.ts +178 -83
  300. package/src/server/users.ts +1 -0
  301. package/src/server/utils.ts +71 -1
  302. package/src/server/version.ts +1 -1
  303. package/dist/component/public.js.map +0 -1
  304. package/dist/component/server/implementation.d.ts +0 -1264
  305. package/dist/component/server/implementation.d.ts.map +0 -1
  306. package/dist/component/server/implementation.js +0 -2365
  307. package/dist/component/server/implementation.js.map +0 -1
  308. package/dist/server/cookies.d.ts.map +0 -1
  309. package/dist/server/db.d.ts.map +0 -1
  310. package/dist/server/device.d.ts.map +0 -1
  311. package/dist/server/implementation.d.ts +0 -1264
  312. package/dist/server/implementation.d.ts.map +0 -1
  313. package/dist/server/implementation.js +0 -2365
  314. package/dist/server/implementation.js.map +0 -1
  315. package/dist/server/keys.d.ts.map +0 -1
  316. package/dist/server/oauth.d.ts.map +0 -1
  317. package/dist/server/ratelimit.d.ts.map +0 -1
  318. package/dist/server/redirects.d.ts.map +0 -1
  319. package/dist/server/refresh.d.ts.map +0 -1
  320. package/dist/server/sessions.d.ts.map +0 -1
  321. package/dist/server/signin.d.ts.map +0 -1
  322. package/dist/server/sso.d.ts.map +0 -1
  323. package/dist/server/templates.d.ts.map +0 -1
  324. package/dist/server/tokens.d.ts.map +0 -1
  325. package/dist/server/totp.d.ts.map +0 -1
  326. package/dist/server/users.d.ts.map +0 -1
  327. package/dist/server/utils.d.ts.map +0 -1
  328. package/src/server/implementation.ts +0 -5336
@@ -1 +0,0 @@
1
- {"version":3,"file":"implementation.js","names":["serializeCookie","enterprise","loaded","saml","state","result","parseCookies"],"sources":["../../src/server/implementation.ts"],"sourcesContent":["import {\n Auth,\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n actionGeneric,\n httpActionGeneric,\n internalMutationGeneric,\n} from \"convex/server\";\nimport { ConvexError, GenericId, v } from \"convex/values\";\nimport { parse as parseCookies, serialize as serializeCookie } from \"cookie\";\n\nimport { redirectToParamCookie, useRedirectToParam } from \"./cookies\";\nimport { isAuthError } from \"./errors\";\nimport { AuthError, Fx } from \"./fx\";\nimport {\n generateApiKey,\n hashApiKey,\n buildScopeChecker,\n checkKeyRateLimit,\n} from \"./keys\";\nimport {\n callCreateAccountFromCredentials,\n callInvalidateSessions,\n callModifyAccount,\n callRetrieveAccountWithCredentials,\n callSignOut,\n callUserOAuth,\n callVerifierSignature,\n storeArgs,\n storeImpl,\n} from \"./mutations/index\";\nimport { createOAuthAuthorizationURL, handleOAuthCallback } from \"./oauth\";\nimport { GetProviderOrThrowFunc } from \"./provider\";\nimport {\n configDefaults,\n listAvailableProviders,\n materializeProvider,\n} from \"./providers\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"./redirects\";\nimport { signInImpl } from \"./signin\";\nimport {\n createEnterpriseSamlMetadataXml,\n createEnterpriseSamlSignInRequest,\n createEnterpriseOidcRuntime,\n createServiceProviderMetadata,\n createSamlPostBindingResponse,\n encodeEnterpriseSamlRelayState,\n enterpriseOidcProviderId,\n enterpriseSamlProviderId,\n getEnterpriseOidcUrls,\n getSamlServiceProviderOptions,\n isEnterpriseSamlSourceActive,\n parseEnterpriseSamlLoginResponse,\n parseEnterpriseSamlLogoutMessage,\n getOidcConfig,\n getSamlConfig,\n normalizeDomain,\n parseScimListRequest,\n parseScimPath,\n parseSamlIdpMetadata,\n profileFromSamlExtract,\n SCIM_GROUP_SCHEMA_ID,\n SCIM_USER_SCHEMA_ID,\n scimError,\n scimJson,\n serializeScimGroup,\n serializeScimUser,\n upsertProtocolConfig,\n validateEnterpriseSamlLoginRelayState,\n} from \"./sso\";\nimport { MutationCtx, KeyDoc } from \"./types\";\nimport type { Tokens } from \"./types\";\nimport type { FunctionReferenceFromExport } from \"./types\";\nimport type { KeyScope, ScopeChecker } from \"./types\";\nimport {\n AuthProviderConfig,\n ConvexAuthConfig,\n CorsConfig,\n HttpKeyContext,\n UserOrderBy,\n UserWhere,\n} from \"./types\";\nimport type { OAuthMaterializedConfig } from \"./types\";\nimport {\n generateRandomString,\n LOG_LEVELS,\n TOKEN_SUB_CLAIM_DIVIDER,\n logError,\n logWithLevel,\n sha256,\n} from \"./utils\";\nimport { requireEnv } from \"./utils\";\n\n/**\n * The type of the signIn Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignInAction = FunctionReferenceFromExport<\n ReturnType<typeof Auth>[\"signIn\"]\n>;\n\n/** @internal */\nexport type SignInActionResult =\n | { kind: \"signedIn\"; tokens: Tokens | null }\n | { kind: \"redirect\"; redirect: string; verifier: string }\n | { kind: \"started\" }\n | { kind: \"passkeyOptions\"; options: Record<string, any>; verifier: string }\n | { kind: \"totpRequired\"; verifier: string }\n | {\n kind: \"totpSetup\";\n totpSetup: { uri: string; secret: string; totpId: string };\n verifier: string;\n }\n | {\n kind: \"deviceCode\";\n deviceCode: {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresIn: number;\n interval: number;\n };\n };\n/**\n * The type of the signOut Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignOutAction = FunctionReferenceFromExport<\n ReturnType<typeof Auth>[\"signOut\"]\n>;\n/**\n * Configure the Convex Auth library. Returns an object with\n * functions and `auth` helper. You must export the functions\n * from `convex/auth.ts` to make them callable:\n *\n * ```ts filename=\"convex/auth.ts\"\n * import { createAuth } from \"@robelest/convex-auth/component\";\n * import { components } from \"./_generated/api\";\n *\n * export const auth = createAuth(components.auth, {\n * providers: [],\n * });\n * export const { signIn, signOut, store } = auth;\n * ```\n *\n * @returns An object with fields you should reexport from your\n * `convex/auth.ts` file.\n */\nexport function Auth(config_: ConvexAuthConfig) {\n const config = configDefaults(config_);\n const hasOAuth = config.providers.some(\n (provider) => provider.type === \"oauth\",\n );\n const hasSSO = config.providers.some((provider) => provider.type === \"sso\");\n const getProviderOrThrow: GetProviderOrThrowFunc = (\n id: string,\n allowExtraProviders: boolean = false,\n ) => {\n const provider =\n config.providers.find(\n (configuredProvider) => configuredProvider.id === id,\n ) ??\n (allowExtraProviders\n ? config.extraProviders.find(\n (configuredProvider) => configuredProvider.id === id,\n )\n : undefined);\n if (provider === undefined) {\n const detail =\n `Provider \\`${id}\\` is not configured, ` +\n `available providers are ${listAvailableProviders(config, allowExtraProviders)}.`;\n logWithLevel(LOG_LEVELS.ERROR, detail);\n throw new AuthError(\"PROVIDER_NOT_CONFIGURED\", detail, {\n provider: id,\n }).toConvexError();\n }\n return provider;\n };\n type ComponentCtx = Pick<\n GenericActionCtx<GenericDataModel>,\n \"runQuery\" | \"runMutation\"\n >;\n type ComponentReadCtx = Pick<GenericActionCtx<GenericDataModel>, \"runQuery\">;\n type ComponentAuthReadCtx = ComponentReadCtx & { auth: Auth };\n type AccountCredentials = { id: string; secret?: string };\n type CreateAccountArgs = {\n provider: string;\n account: AccountCredentials;\n profile: Record<string, unknown>;\n shouldLinkViaEmail?: boolean;\n shouldLinkViaPhone?: boolean;\n };\n type RetrieveAccountArgs = { provider: string; account: AccountCredentials };\n type UpdateAccountCredentialsArgs = {\n provider: string;\n account: { id: string; secret: string };\n };\n\n const INVITE_TOKEN_ALPHABET =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n const INVITE_TOKEN_LENGTH = 48;\n\n const enterpriseNotFoundError = \"Enterprise not found.\";\n\n const ENTERPRISE_CONTROL_ROUTE_BASE = \"/api/auth/sso\";\n\n const recordEnterpriseAuditEvent = async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n groupId: string;\n eventType: string;\n actorType: \"user\" | \"system\" | \"scim\" | \"api_key\" | \"webhook\";\n actorId?: string;\n subjectType: string;\n subjectId?: string;\n ok: boolean;\n requestId?: string;\n ip?: string;\n metadata?: Record<string, unknown>;\n },\n ) => {\n const { ok, ...rest } = data;\n return (await ctx.runMutation(\n config.component.public.enterpriseAuditEventCreate,\n {\n ...rest,\n status: ok ? \"success\" : \"failure\",\n occurredAt: Date.now(),\n },\n )) as string;\n };\n\n const emitEnterpriseWebhookDeliveries = async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n eventType: string;\n payload: Record<string, unknown>;\n auditEventId?: string;\n },\n ) => {\n const endpoints = await ctx.runQuery(\n config.component.public.enterpriseWebhookEndpointList,\n { enterpriseId: data.enterpriseId },\n );\n for (const endpoint of endpoints) {\n if (\n endpoint.status !== \"active\" ||\n !endpoint.subscriptions.includes(data.eventType)\n ) {\n continue;\n }\n await ctx.runMutation(\n config.component.public.enterpriseWebhookDeliveryEnqueue,\n {\n enterpriseId: data.enterpriseId,\n endpointId: endpoint._id,\n auditEventId: data.auditEventId,\n eventType: data.eventType,\n payload: data.payload,\n nextAttemptAt: Date.now(),\n },\n );\n }\n };\n\n const getEnterpriseScimContext = async (\n ctx: ComponentReadCtx,\n request: Request,\n ) => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n throw new AuthError(\"MISSING_BEARER_TOKEN\").toConvexError();\n }\n const token = authHeader.slice(7);\n const scimConfig = await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByTokenHash,\n { tokenHash: await sha256(token) },\n );\n if (!scimConfig || scimConfig.status !== \"active\") {\n throw new AuthError(\n \"INVALID_API_KEY\",\n \"Invalid SCIM token.\",\n ).toConvexError();\n }\n const parsedPath = parseScimPath(new URL(request.url).pathname);\n if (parsedPath.enterpriseId !== scimConfig.enterpriseId) {\n throw new AuthError(\n \"INVALID_API_KEY\",\n \"SCIM token/tenant mismatch.\",\n ).toConvexError();\n }\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: scimConfig.enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n return { scimConfig, enterprise, parsedPath };\n };\n\n type ScimState = {\n ctx: ComponentCtx;\n request: Request;\n url: URL;\n parsedPath: ReturnType<typeof parseScimPath>;\n enterprise: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"enterprise\"];\n scimConfig: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"scimConfig\"];\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 auth = {\n user: {\n /**\n * Get the current user's ID, or `null` if not signed in.\n *\n * Tries session JWT first. If `request` is provided, falls back to\n * verifying an `Authorization: Bearer sk_...` API key header.\n *\n * @param ctx - Any Convex context with an `auth` field.\n * @param request - Optional `Request`; enables API key fallback.\n * @returns The user's ID string, or `null` when unauthenticated.\n */\n current: async (\n ctx: { auth: Auth } & Partial<ComponentCtx>,\n request?: Request,\n ): Promise<string | null> => {\n const identity = await ctx.auth.getUserIdentity();\n if (identity !== null) {\n const [userId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);\n return userId;\n }\n if (request !== undefined && \"runMutation\" in ctx && ctx.runMutation) {\n const authHeader = request.headers.get(\"Authorization\");\n if (authHeader?.startsWith(\"Bearer sk_\")) {\n const rawKey = authHeader.slice(7);\n try {\n const result = await auth.key.verify(ctx as ComponentCtx, rawKey);\n return result.userId;\n } catch {\n return null;\n }\n }\n }\n return null;\n },\n /**\n * Get the current user's ID, or throw `NOT_SIGNED_IN` if not signed in.\n *\n * Tries session JWT first. If `request` is provided, falls back to\n * verifying an `Authorization: Bearer sk_...` API key header.\n *\n * @param ctx - Any Convex context with an `auth` field.\n * @param request - Optional `Request`; enables API key fallback.\n * @returns The user's ID string.\n * @throws `ConvexError` with code `NOT_SIGNED_IN` when unauthenticated.\n */\n require: async (\n ctx: { auth: Auth } & Partial<ComponentCtx>,\n request?: Request,\n ): Promise<string> => {\n const userId = await auth.user.current(ctx, request);\n if (userId === null) {\n throw new AuthError(\"NOT_SIGNED_IN\").toConvexError();\n }\n return userId;\n },\n /**\n * Retrieve a user document by their ID.\n *\n * @param ctx - Convex context with `runQuery`.\n * @param userId - The user document ID.\n * @returns The user document, or `null` if not found.\n */\n get: async (ctx: ComponentReadCtx, userId: string) => {\n return await ctx.runQuery(config.component.public.userGetById, {\n userId,\n });\n },\n /**\n * List users with optional filters, sorting, and pagination.\n *\n * @param opts.where - Optional filters (email, phone, name, anonymous).\n * @param opts.limit - Max users to return (default 50).\n * @param opts.cursor - Pagination cursor from a previous page.\n * @param opts.orderBy - Sort field.\n * @param opts.order - Sort direction.\n * @returns `{ items, nextCursor }`.\n */\n list: async (\n ctx: ComponentReadCtx,\n opts: {\n where?: UserWhere;\n limit?: number;\n cursor?: string | null;\n orderBy?: UserOrderBy;\n order?: \"asc\" | \"desc\";\n } = {},\n ) => {\n return await ctx.runQuery(config.component.public.userList, opts);\n },\n /**\n * Get the currently signed-in user's document, or `null` if not\n * signed in. Convenience combining `current()` + `get()`.\n *\n * @param ctx - Convex context with `auth` and `runQuery`.\n * @returns The user document, or `null` when unauthenticated.\n */\n viewer: async (ctx: ComponentAuthReadCtx) => {\n const userId = await auth.user.current(ctx);\n if (userId === null) {\n return null;\n }\n return await ctx.runQuery(config.component.public.userGetById, {\n userId,\n });\n },\n /**\n * Update a user document with partial data.\n *\n * @param ctx - Convex context with `runMutation`.\n * @param userId - The user document ID.\n * @param data - Partial data to merge into the user document.\n */\n patch: async (\n ctx: ComponentCtx,\n userId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.userPatch, {\n userId,\n data,\n });\n },\n /**\n * Set or clear a user's active group in `user.extend.lastActiveGroup`.\n *\n * This helper preserves other keys under `user.extend`.\n * Pass `groupId: null` to clear `lastActiveGroup`.\n */\n setActiveGroup: async (\n ctx: ComponentCtx,\n opts: { userId: string; groupId: string | null },\n ) => {\n const user = await auth.user.get(ctx, opts.userId);\n const existingExtend =\n user !== null &&\n user.extend !== null &&\n typeof user.extend === \"object\" &&\n !Array.isArray(user.extend)\n ? { ...(user.extend as Record<string, unknown>) }\n : {};\n\n if (opts.groupId === null) {\n const { lastActiveGroup: _omit, ...rest } = existingExtend;\n await auth.user.patch(ctx, opts.userId, { extend: rest });\n return;\n }\n\n await auth.user.patch(ctx, opts.userId, {\n extend: { ...existingExtend, lastActiveGroup: opts.groupId },\n });\n },\n /**\n * Get the user's active group ID from `user.extend.lastActiveGroup`.\n *\n * @param ctx - Convex context with `runQuery`.\n * @param opts.userId - The user document ID.\n * @returns The active group ID, or `null` if none is set.\n */\n getActiveGroup: async (\n ctx: ComponentReadCtx,\n opts: { userId: string },\n ): Promise<string | null> => {\n const user = await auth.user.get(ctx, opts.userId);\n if (\n user !== null &&\n user.extend !== null &&\n typeof user.extend === \"object\" &&\n !Array.isArray(user.extend)\n ) {\n const val = (user.extend as Record<string, unknown>).lastActiveGroup;\n if (typeof val === \"string\") {\n return val;\n }\n }\n return null;\n },\n\n /**\n * Delete a user and optionally cascade-delete all linked records.\n *\n * When `cascade` is `true` (default), this removes all sessions,\n * accounts, API keys, group memberships, passkeys, and TOTP\n * enrollments before deleting the user document itself.\n *\n * When `cascade` is `false`, the method throws if the user has any\n * linked records — the caller must clean them up explicitly first.\n *\n * @param ctx - Convex action context with `runMutation` and `runQuery`.\n * @param userId - The user document ID to delete.\n * @param opts.cascade - Whether to cascade-delete linked records (default: `true`).\n */\n remove: async (\n ctx: ComponentCtx,\n userId: string,\n opts?: { cascade?: boolean },\n ): Promise<void> => {\n const cascade = opts?.cascade !== false;\n\n // Collect all linked records\n const [sessions, accounts, keys, members, passkeys, totps] =\n await Promise.all([\n ctx.runQuery(config.component.public.sessionListByUser, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.accountListByUser, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.keyListByUserId, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.memberListByUser, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.passkeyListByUserId, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.totpListByUserId, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ]);\n\n const totalLinked =\n sessions.length +\n accounts.length +\n keys.length +\n members.length +\n passkeys.length +\n totps.length;\n\n if (!cascade && totalLinked > 0) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n `Cannot delete user with ${totalLinked} linked records. ` +\n `Pass { cascade: true } to delete all linked records, or ` +\n `remove them manually first.`,\n ).toConvexError();\n }\n\n // Cascade delete all linked records\n const deletions: Promise<unknown>[] = [];\n for (const s of sessions) {\n deletions.push(\n ctx.runMutation(config.component.public.sessionDelete, {\n sessionId: s._id,\n }),\n );\n }\n for (const a of accounts) {\n deletions.push(\n ctx.runMutation(config.component.public.accountDelete, {\n accountId: a._id,\n }),\n );\n }\n for (const k of keys) {\n deletions.push(\n ctx.runMutation(config.component.public.keyDelete, {\n keyId: k._id,\n }),\n );\n }\n for (const m of members) {\n deletions.push(\n ctx.runMutation(config.component.public.memberRemove, {\n memberId: m._id,\n }),\n );\n }\n for (const p of passkeys) {\n deletions.push(\n ctx.runMutation(config.component.public.passkeyDelete, {\n passkeyId: p._id,\n }),\n );\n }\n for (const t of totps) {\n deletions.push(\n ctx.runMutation(config.component.public.totpDelete, {\n totpId: t._id,\n }),\n );\n }\n await Promise.all(deletions);\n\n // Delete the user document\n await ctx.runMutation(config.component.public.userDelete, { userId });\n },\n },\n session: {\n /**\n * Get the current session ID from the auth context, or `null` if\n * not signed in.\n *\n * @param ctx - Any Convex context with an `auth` field.\n * @returns The session's `Id<\"Session\">`, or `null` when unauthenticated.\n */\n current: async (ctx: { auth: Auth }) => {\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) {\n return null;\n }\n const [, sessionId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);\n return sessionId as GenericId<\"Session\">;\n },\n /**\n * Invalidate sessions for a user, optionally preserving specific sessions.\n *\n * @param ctx - Convex action context.\n * @param args.userId - The user whose sessions to invalidate.\n * @param args.except - Session IDs to preserve (e.g. the current session).\n */\n invalidate: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: {\n userId: GenericId<\"User\">;\n except?: GenericId<\"Session\">[];\n },\n ): Promise<void> => {\n return await callInvalidateSessions(ctx, args);\n },\n /**\n * Get a session by its document ID.\n *\n * @param ctx - Convex context with `runQuery`.\n * @param sessionId - The session document ID.\n * @returns The session document, or `null` if not found.\n */\n get: async (ctx: ComponentReadCtx, sessionId: string) => {\n return await ctx.runQuery(config.component.public.sessionGetById, {\n sessionId,\n });\n },\n /**\n * List all active sessions for a user.\n *\n * @param ctx - Convex context with `runQuery`.\n * @param opts.userId - The user whose sessions to list.\n * @returns Array of session documents.\n */\n list: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(config.component.public.sessionListByUser, {\n userId: opts.userId,\n });\n },\n },\n account: {\n /**\n * Create an account and user for a credentials provider.\n *\n * @param ctx - Convex action context.\n * @param args - Provider ID, account credentials, profile data, and link flags.\n * @returns `{ account, user }` — the created account and user documents.\n */\n create: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: CreateAccountArgs,\n ) => {\n return await callCreateAccountFromCredentials(ctx, args);\n },\n /**\n * Retrieve an account and user for a credentials provider.\n *\n * @param ctx - Convex action context.\n * @param args - Provider ID and account credentials (id, optional secret).\n * @returns `{ account, user }` — the matched account and user documents.\n * @throws `ConvexError` with code `ACCOUNT_NOT_FOUND` when no match exists.\n */\n get: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: RetrieveAccountArgs,\n ) => {\n const result = await callRetrieveAccountWithCredentials(ctx, args);\n if (typeof result === \"string\") {\n throw new AuthError(\"ACCOUNT_NOT_FOUND\", result).toConvexError();\n }\n return result;\n },\n /**\n * Update account credentials (secret) for an existing account.\n *\n * @param ctx - Convex action context.\n * @param args - Provider ID and new account credentials (id + secret).\n */\n update: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: UpdateAccountCredentialsArgs,\n ): Promise<void> => {\n return await callModifyAccount(ctx, args);\n },\n\n /**\n * Unlink (delete) an account from a user.\n *\n * Throws if the account is the user's only account and the user has\n * no other way to sign in (prevents locking the user out).\n *\n * @param ctx - Convex context with `runQuery` and `runMutation`.\n * @param accountId - The account document ID to unlink.\n */\n remove: async (ctx: ComponentCtx, accountId: string): Promise<void> => {\n // Look up the account to get the userId\n const account = await ctx.runQuery(\n config.component.public.accountGetById,\n { accountId },\n );\n if (account === null) {\n throw new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n \"Account not found.\",\n ).toConvexError();\n }\n // Check if this is the user's only account\n const allAccounts = (await ctx.runQuery(\n config.component.public.accountListByUser,\n { userId: (account as any).userId },\n )) as Array<{ _id: string }>;\n\n if (allAccounts.length <= 1) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Cannot unlink the user's only account. This would lock them out.\",\n ).toConvexError();\n }\n\n await ctx.runMutation(config.component.public.accountDelete, {\n accountId,\n });\n },\n\n // --- Passkey account methods ---\n\n /** List all passkeys for a user. */\n listPasskeys: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(\n config.component.public.passkeyListByUserId,\n opts,\n );\n },\n /** Rename a passkey (set a user-friendly display name). */\n renamePasskey: async (\n ctx: ComponentCtx,\n passkeyId: string,\n name: string,\n ) => {\n await ctx.runMutation(config.component.public.passkeyUpdateMeta, {\n passkeyId,\n data: { name },\n });\n },\n /** Delete a passkey credential. */\n removePasskey: async (ctx: ComponentCtx, passkeyId: string) => {\n await ctx.runMutation(config.component.public.passkeyDelete, {\n passkeyId,\n });\n },\n\n // --- TOTP account methods ---\n\n /** List all TOTP enrollments for a user. */\n listTotps: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(\n config.component.public.totpListByUserId,\n opts,\n );\n },\n /** Delete a TOTP enrollment. */\n removeTotp: async (ctx: ComponentCtx, totpId: string) => {\n await ctx.runMutation(config.component.public.totpDelete, { totpId });\n },\n },\n provider: {\n /**\n * Sign in via another provider, typically from a credentials flow.\n *\n * @param ctx - Convex action context.\n * @param provider - The provider config to sign in with.\n * @param args - Optional account ID and params.\n * @returns `{ userId, sessionId }` on success, or `null`.\n */\n signIn: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n provider: AuthProviderConfig,\n args: {\n accountId?: GenericId<\"Account\">;\n params?: Record<string, unknown>;\n },\n ) => {\n const result = await signInImpl(\n enrichCtx(ctx),\n materializeProvider(provider),\n // params type widened: Record<string, unknown> → Record<string, any>\n args as {\n accountId?: GenericId<\"Account\">;\n params?: Record<string, any>;\n },\n {\n generateTokens: false,\n allowExtraProviders: true,\n },\n );\n return result.kind === \"signedIn\"\n ? result.signedIn !== null\n ? {\n userId: result.signedIn.userId,\n sessionId: result.signedIn.sessionId,\n }\n : null\n : null;\n },\n },\n /**\n * Hierarchical group management. Groups can nest arbitrarily deep\n * via `parentGroupId`. A root group has no parent.\n *\n * ```ts\n * const groupId = await auth.group.create(ctx, { name: \"Acme Corp\" });\n * const subGroupId = await auth.group.create(ctx, {\n * name: \"Engineering\",\n * parentGroupId: groupId,\n * });\n * ```\n */\n group: {\n /**\n * Create a new group. Omit `parentGroupId` for a root-level group,\n * or provide it to create a nested group.\n *\n * @returns The ID of the newly created group.\n */\n create: async (\n ctx: ComponentCtx,\n data: {\n name: string;\n slug?: string;\n type?: string;\n parentGroupId?: string;\n tags?: Array<{ key: string; value: string }>;\n extend?: Record<string, unknown>;\n },\n ): Promise<string> => {\n return (await ctx.runMutation(\n config.component.public.groupCreate,\n data,\n )) as string;\n },\n /**\n * Retrieve a group by its ID. Returns `null` if not found.\n */\n get: async (ctx: ComponentReadCtx, groupId: string) => {\n return await ctx.runQuery(config.component.public.groupGet, {\n groupId,\n });\n },\n /**\n * List groups with optional filtering, sorting, and pagination.\n *\n * Empty `where` returns **all** groups.\n *\n * ```ts\n * // All groups of type \"team\"\n * await auth.group.list(ctx, { where: { type: \"team\" } });\n *\n * // Paginated\n * const page1 = await auth.group.list(ctx, { limit: 10 });\n * const page2 = await auth.group.list(ctx, { limit: 10, cursor: page1.nextCursor });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n slug?: string;\n type?: string;\n parentGroupId?: string;\n name?: string;\n isRoot?: boolean;\n tagsAll?: Array<{ key: string; value: string }>;\n tagsAny?: Array<{ key: string; value: string }>;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"name\" | \"slug\" | \"type\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.groupList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Update a group's fields (name, slug, tags, extend, parentGroupId).\n */\n update: async (\n ctx: ComponentCtx,\n groupId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.groupUpdate, {\n groupId,\n data,\n });\n },\n /**\n * Delete a group and cascade to all descendants. Deletes child groups\n * (recursively), all members, and all invites for this group and its\n * descendants.\n */\n delete: async (ctx: ComponentCtx, groupId: string) => {\n await ctx.runMutation(config.component.public.groupDelete, { groupId });\n },\n /**\n * Retrieve the ancestor chain for a group by walking `parentGroupId`\n * upward toward the root.\n *\n * Useful for breadcrumbs, permission inheritance visualization, and\n * operations that need the full hierarchy path.\n *\n * @param ctx - Convex context with `runQuery`.\n * @param opts.groupId - The starting group.\n * @param opts.maxDepth - Maximum traversal depth (default 32).\n * @param opts.includeSelf - Include the starting group as the first\n * element (default `false`).\n * @returns Ancestors ordered from immediate parent to root, plus\n * diagnostic flags.\n */\n ancestors: async (\n ctx: ComponentReadCtx,\n opts: {\n groupId: string;\n maxDepth?: number;\n includeSelf?: boolean;\n },\n ) => {\n const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));\n const visited = new Set<string>();\n const ancestors: NonNullable<\n Awaited<ReturnType<typeof auth.group.get>>\n >[] = [];\n let cycleDetected = false;\n let maxDepthReached = false;\n\n let currentGroupId: string | undefined = opts.groupId;\n let depth = 0;\n let isFirst = true;\n\n while (currentGroupId !== undefined) {\n if (depth > maxDepth) {\n maxDepthReached = true;\n break;\n }\n if (visited.has(currentGroupId)) {\n cycleDetected = true;\n break;\n }\n visited.add(currentGroupId);\n\n const group = await auth.group.get(ctx, currentGroupId);\n if (group === null) {\n break;\n }\n\n if (isFirst) {\n isFirst = false;\n if (opts.includeSelf) {\n ancestors.push(group);\n }\n currentGroupId = group.parentGroupId;\n depth += 1;\n continue;\n }\n\n ancestors.push(group);\n currentGroupId = group.parentGroupId;\n depth += 1;\n }\n\n return { ancestors, cycleDetected, maxDepthReached };\n },\n },\n /**\n * Manage group membership. A member links a user to a group with an\n * application-defined role string (e.g. \"owner\", \"admin\", \"member\").\n *\n * The auth component stores roles but does not enforce access control.\n * Your application defines what each role means.\n */\n member: {\n /**\n * Add a user as a member of a group.\n *\n * @param data.groupId - The group to add the member to.\n * @param data.userId - The user to add.\n * @param data.role - Application-defined role (e.g. \"owner\", \"admin\", \"member\").\n * @param data.status - Optional membership status (e.g. \"active\", \"suspended\").\n * @param data.extend - Optional arbitrary JSON extension data.\n * @throws ConvexError with code `DUPLICATE_MEMBERSHIP` if the user is\n * already a member of the target group.\n * @returns The ID of the new member record.\n */\n add: async (\n ctx: ComponentCtx,\n data: {\n groupId: string;\n userId: string;\n role?: string;\n status?: string;\n extend?: Record<string, unknown>;\n },\n ): Promise<string> => {\n return (await ctx.runMutation(\n config.component.public.memberAdd,\n data,\n )) as string;\n },\n /**\n * Retrieve a member record by its ID. Returns `null` if not found.\n */\n get: async (ctx: ComponentReadCtx, memberId: string) => {\n return await ctx.runQuery(config.component.public.memberGet, {\n memberId,\n });\n },\n /**\n * Look up a user's membership in a specific group.\n */\n getByUserAndGroup: async (\n ctx: ComponentReadCtx,\n opts: { userId: string; groupId: string },\n ) => {\n return await ctx.runQuery(\n config.component.public.memberGetByGroupAndUser,\n opts,\n );\n },\n /**\n * List members with optional filtering, sorting, and pagination.\n *\n * ```ts\n * // All members of a group\n * await auth.member.list(ctx, { where: { groupId } });\n *\n * // Admins only\n * await auth.member.list(ctx, { where: { groupId, role: \"admin\" } });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n groupId?: string;\n userId?: string;\n role?: string;\n status?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"role\" | \"status\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.memberList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Remove a member from a group by deleting the member record.\n */\n remove: async (ctx: ComponentCtx, memberId: string) => {\n await ctx.runMutation(config.component.public.memberRemove, {\n memberId,\n });\n },\n /**\n * Update a member's fields (role, status, extend).\n */\n update: async (\n ctx: ComponentCtx,\n memberId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.memberUpdate, {\n memberId,\n data,\n });\n },\n /**\n * Resolve membership for a group, including inherited membership\n * from ancestor groups (`parentGroupId` chain).\n *\n * Returns direct membership when found on `opts.groupId`, otherwise\n * returns the nearest ancestor membership. Use `roles` to only match\n * specific roles (for example `admin`/`lead`).\n */\n inherit: async (\n ctx: ComponentReadCtx,\n opts: {\n userId: string;\n groupId: string;\n roles?: string[];\n maxDepth?: number;\n },\n ) => {\n const roleFilter =\n opts.roles !== undefined && opts.roles.length > 0\n ? new Set(opts.roles)\n : null;\n const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));\n const visited = new Set<string>();\n const traversedGroupIds: string[] = [];\n\n let currentGroupId: string | undefined = opts.groupId;\n let depth = 0;\n let cycleDetected = false;\n let maxDepthReached = false;\n\n while (currentGroupId !== undefined) {\n if (depth > maxDepth) {\n maxDepthReached = true;\n break;\n }\n\n if (visited.has(currentGroupId)) {\n cycleDetected = true;\n break;\n }\n visited.add(currentGroupId);\n traversedGroupIds.push(currentGroupId);\n\n const membership = await auth.member.getByUserAndGroup(ctx, {\n userId: opts.userId,\n groupId: currentGroupId,\n });\n if (\n membership !== null &&\n (roleFilter === null || roleFilter.has(membership.role))\n ) {\n return {\n requestedGroupId: opts.groupId,\n matchedGroupId: currentGroupId,\n membership,\n depth,\n isDirect: depth === 0,\n isInherited: depth > 0,\n traversedGroupIds,\n cycleDetected: false,\n maxDepthReached: false,\n };\n }\n\n const group = await auth.group.get(ctx, currentGroupId);\n if (group === null || group.parentGroupId === undefined) {\n break;\n }\n\n currentGroupId = group.parentGroupId;\n depth += 1;\n }\n\n return {\n requestedGroupId: opts.groupId,\n matchedGroupId: null,\n membership: null,\n depth: null,\n isDirect: false,\n isInherited: false,\n traversedGroupIds,\n cycleDetected,\n maxDepthReached,\n };\n },\n /**\n * Require membership on a group, checking inherited membership\n * from ancestor groups when no direct membership exists.\n *\n * Throws `FORBIDDEN` if no matching membership is found.\n */\n require: async (\n ctx: ComponentReadCtx,\n opts: {\n userId: string;\n groupId: string;\n roles?: string[];\n maxDepth?: number;\n },\n ) => {\n const result = await auth.member.inherit(ctx, opts);\n if (result.membership === null) {\n throw new AuthError(\n \"FORBIDDEN\",\n `User ${opts.userId} has no membership on group ${opts.groupId} or its ancestors.`,\n ).toConvexError();\n }\n return {\n membership: result.membership,\n matchedGroupId: result.matchedGroupId,\n isDirect: result.isDirect,\n isInherited: result.isInherited,\n depth: result.depth,\n };\n },\n },\n /**\n * Manage platform-level invitations.\n *\n * Invites can optionally target a group by setting `groupId`, but they do\n * not require groups and can be used in apps with user-only collaboration.\n */\n invite: {\n /**\n * Create a new invitation.\n *\n * @param data.groupId - Optional group to invite the user into.\n * @param data.invitedByUserId - Optional user sending the invitation\n * (omit for CLI-generated invites).\n * @param data.email - Optional email of the invitee (omit for\n * CLI-generated invite links where the email is unknown upfront).\n * @param data.role - Optional role to assign on acceptance.\n * @param data.expiresTime - Optional expiration timestamp (omit for\n * single-use, non-expiring invites).\n * @param data.extend - Optional arbitrary JSON extension data.\n * @throws ConvexError with code `DUPLICATE_INVITE` if a pending invite\n * already exists for this email and scope.\n * @returns An object with `inviteId` and raw `token`.\n */\n create: async (\n ctx: ComponentCtx,\n data: {\n groupId?: string;\n invitedByUserId?: string;\n email?: string;\n role?: string;\n expiresTime?: number;\n extend?: Record<string, unknown>;\n },\n ): Promise<{ inviteId: string; token: string }> => {\n const token = generateRandomString(\n INVITE_TOKEN_LENGTH,\n INVITE_TOKEN_ALPHABET,\n );\n const tokenHash = await sha256(token);\n const inviteId = (await ctx.runMutation(\n config.component.public.inviteCreate,\n {\n ...data,\n tokenHash,\n status: \"pending\",\n },\n )) as string;\n return { inviteId, token };\n },\n /**\n * Retrieve an invite by its ID. Returns `null` if not found.\n */\n get: async (ctx: ComponentReadCtx, inviteId: string) => {\n return await ctx.runQuery(config.component.public.inviteGet, {\n inviteId,\n });\n },\n /**\n * Token-based invite helpers.\n */\n token: {\n /**\n * Retrieve an invite by raw token.\n */\n get: async (ctx: ComponentReadCtx, token: string) => {\n const tokenHash = await sha256(token);\n return await ctx.runQuery(\n config.component.public.inviteGetByTokenHash,\n {\n tokenHash,\n },\n );\n },\n /**\n * Accept an invitation by raw token and atomically add group membership\n * when the invite is group-scoped.\n */\n accept: async (\n ctx: ComponentCtx,\n args: { token: string; acceptedByUserId: string },\n ) => {\n const tokenHash = await sha256(args.token);\n return await ctx.runMutation(\n config.component.public.inviteAcceptByToken,\n {\n tokenHash,\n acceptedByUserId: args.acceptedByUserId,\n },\n );\n },\n },\n /**\n * List invites with optional filtering, sorting, and pagination.\n *\n * ```ts\n * // Pending invites for a group\n * await auth.invite.list(ctx, { where: { groupId, status: \"pending\" } });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n tokenHash?: string;\n groupId?: string;\n status?: \"pending\" | \"accepted\" | \"revoked\" | \"expired\";\n email?: string;\n invitedByUserId?: string;\n role?: string;\n acceptedByUserId?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?:\n | \"_creationTime\"\n | \"status\"\n | \"email\"\n | \"expiresTime\"\n | \"acceptedTime\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.inviteList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Accept an invitation. Marks the invite as \"accepted\" and records\n * the timestamp. If the invite has a group, the caller is responsible\n * for creating the member record via `auth.member.add` in the\n * same Convex mutation for transactional safety.\n *\n * @param ctx - Convex context with `runMutation`.\n * @param inviteId - The invite document ID.\n * @param acceptedByUserId - User accepting the invite (recorded for audit).\n * @throws `ConvexError` with code `INVITE_NOT_FOUND` when the invite does not exist.\n * @throws `ConvexError` with code `INVITE_NOT_PENDING` when the invite is not in `pending` status.\n *\n * @example\n * ```ts\n * export const acceptInvite = mutation({\n * args: { inviteId: v.string() },\n * handler: async (ctx, { inviteId }) => {\n * const userId = await auth.user.require(ctx);\n * const invite = await auth.invite.get(ctx, inviteId);\n * if (!invite) throw new Error(\"Invite not found\");\n *\n * await auth.invite.accept(ctx, inviteId);\n * if (invite.groupId) {\n * await auth.member.add(ctx, {\n * groupId: invite.groupId,\n * userId,\n * role: invite.role,\n * });\n * }\n * },\n * });\n * ```\n */\n accept: async (\n ctx: ComponentCtx,\n inviteId: string,\n acceptedByUserId?: string,\n ) => {\n await ctx.runMutation(config.component.public.inviteAccept, {\n inviteId,\n ...(acceptedByUserId ? { acceptedByUserId } : {}),\n });\n },\n /**\n * Revoke a pending invitation.\n *\n * @param ctx - Convex context with `runMutation`.\n * @param inviteId - The invite document ID.\n * @throws `ConvexError` with code `INVITE_NOT_FOUND` when the invite does not exist.\n * @throws `ConvexError` with code `INVITE_NOT_PENDING` when the invite is not in `pending` status.\n */\n revoke: async (ctx: ComponentCtx, inviteId: string) => {\n await ctx.runMutation(config.component.public.inviteRevoke, {\n inviteId,\n });\n },\n },\n /**\n * Manage passkey credentials for users.\n *\n * ```ts\n * const passkeys = await auth.passkey.list(ctx, { userId });\n * await auth.passkey.rename(ctx, passkeyId, \"MacBook Touch ID\");\n /**\n * Manage API keys for programmatic access.\n *\n * Keys use SHA-256 hashing (via `@oslojs/crypto`) and support\n * scoped resource:action permissions with optional per-key rate limiting.\n *\n * ```ts\n * const { keyId, raw } = await auth.key.create(ctx, {\n * userId,\n * name: \"CI Pipeline\",\n * scopes: [{ resource: \"data\", actions: [\"read\"] }],\n * });\n * // raw = \"sk_abc123...\" — show once, never stored\n *\n * const result = await auth.key.verify(ctx, rawKey);\n * result.scopes.can(\"data\", \"read\"); // true\n * ```\n */\n key: {\n /**\n * Create a new API key. Returns the raw key **once** — it cannot\n * be retrieved again after creation.\n *\n * @param opts.userId - The user this key belongs to.\n * @param opts.name - Human-readable name (e.g. \"CI Pipeline\").\n * @param opts.scopes - Resource:action permissions for this key.\n * @param opts.rateLimit - Optional per-key rate limit override.\n * @param opts.expiresAt - Optional expiration timestamp.\n * @param opts.metadata - Optional arbitrary app data attached to the key.\n * @returns `{ keyId, raw }` where `raw` is the full key string.\n */\n create: async (\n ctx: ComponentCtx,\n opts: {\n userId: string;\n name: string;\n scopes: KeyScope[];\n rateLimit?: { maxRequests: number; windowMs: number };\n expiresAt?: number;\n metadata?: Record<string, unknown>;\n },\n ): Promise<{ keyId: string; raw: string }> => {\n const { raw, hashedKey, displayPrefix } = await generateApiKey(\"sk_\");\n\n const keyId = (await ctx.runMutation(\n config.component.public.keyInsert,\n {\n userId: opts.userId,\n prefix: displayPrefix,\n hashedKey,\n name: opts.name,\n scopes: opts.scopes,\n rateLimit: opts.rateLimit,\n expiresAt: opts.expiresAt,\n metadata: opts.metadata,\n },\n )) as string;\n\n return { keyId, raw };\n },\n\n /**\n * Verify a raw API key string. Returns the userId and a scope checker\n * if the key is valid, not revoked, not expired, and not rate-limited.\n *\n * Also updates `lastUsedAt` and rate limit state as a side effect.\n *\n * @throws Error if the key is invalid, revoked, expired, or rate-limited.\n */\n verify: async (\n ctx: ComponentCtx,\n rawKey: string,\n ): Promise<{\n userId: string;\n keyId: string;\n scopes: ScopeChecker;\n }> => {\n const hashedKey = await hashApiKey(rawKey);\n\n const key = (await ctx.runQuery(\n config.component.public.keyGetByHashedKey,\n { hashedKey },\n )) as KeyDoc | null;\n\n return Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(!key, Fx.fail(new AuthError(\"INVALID_API_KEY\")));\n const k = key!;\n\n yield* Fx.guard(\n k.revoked,\n Fx.fail(new AuthError(\"API_KEY_REVOKED\")),\n );\n\n yield* Fx.guard(\n !!(k.expiresAt && k.expiresAt < Date.now()),\n Fx.fail(new AuthError(\"API_KEY_EXPIRED\")),\n );\n\n // Check per-key rate limit\n const patchData: Record<string, unknown> = {\n lastUsedAt: Date.now(),\n };\n\n if (k.rateLimit) {\n const { limited, newState } = checkKeyRateLimit(\n k.rateLimit,\n k.rateLimitState ?? undefined,\n );\n yield* Fx.guard(\n limited,\n Fx.fail(new AuthError(\"API_KEY_RATE_LIMITED\")),\n );\n patchData.rateLimitState = newState;\n }\n\n // Update lastUsedAt (and rate limit state if applicable)\n yield* Fx.promise(() =>\n ctx.runMutation(config.component.public.keyPatch, {\n keyId: k._id,\n data: patchData,\n }),\n );\n\n return {\n userId: k.userId,\n keyId: k._id,\n scopes: buildScopeChecker(k.scopes),\n };\n }).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),\n );\n },\n\n /**\n * List API keys with optional filtering, sorting, and pagination.\n * Never includes the raw key — only the display prefix.\n *\n * ```ts\n * // All keys for a user\n * await auth.key.list(ctx, { where: { userId } });\n *\n * // Only active (non-revoked)\n * await auth.key.list(ctx, { where: { userId, revoked: false } });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n userId?: string;\n revoked?: boolean;\n name?: string;\n prefix?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?:\n | \"_creationTime\"\n | \"name\"\n | \"lastUsedAt\"\n | \"expiresAt\"\n | \"revoked\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.keyList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n\n /**\n * Get a single API key by its document ID.\n * Returns `null` if not found.\n */\n get: async (\n ctx: ComponentReadCtx,\n keyId: string,\n ): Promise<KeyDoc | null> => {\n return (await ctx.runQuery(config.component.public.keyGetById, {\n keyId,\n })) as KeyDoc | null;\n },\n\n /**\n * Update an API key's metadata (name, scopes, rate limit).\n */\n update: async (\n ctx: ComponentCtx,\n keyId: string,\n data: {\n name?: string;\n scopes?: KeyScope[];\n rateLimit?: { maxRequests: number; windowMs: number };\n },\n ) => {\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId,\n data,\n });\n },\n\n /**\n * Revoke an API key (soft delete). The key record is preserved\n * for audit purposes but can no longer be used for authentication.\n */\n revoke: async (ctx: ComponentCtx, keyId: string) => {\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId,\n data: { revoked: true },\n });\n },\n\n /**\n * Hard delete an API key record.\n */\n remove: async (ctx: ComponentCtx, keyId: string) => {\n await ctx.runMutation(config.component.public.keyDelete, {\n keyId,\n });\n },\n\n /**\n * Rotate an API key — revoke the old key and issue a replacement with\n * the same `userId`, `name`, `scopes`, and `rateLimit`.\n *\n * The old key is soft-revoked immediately; the replacement is a brand\n * new key with a new raw value. Returns the new `keyId` and `raw` key\n * (shown once, same as `auth.key.create`).\n *\n * @throws If the key does not exist or is already revoked.\n *\n * @example\n * ```ts\n * const { keyId, raw } = await auth.key.rotate(ctx, oldKeyId);\n * // raw = \"sk_abc...\" — new key to hand to the caller\n * // old key is now revoked and verify() will throw API_KEY_REVOKED\n * ```\n */\n rotate: async (\n ctx: ComponentCtx,\n keyId: string,\n opts?: { name?: string; expiresAt?: number },\n ): Promise<{ keyId: string; raw: string }> => {\n const existing = await ctx.runQuery(\n config.component.public.keyGetById,\n { keyId },\n );\n if (!existing) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"API key not found.\",\n ).toConvexError();\n }\n if ((existing as any).revoked === true) {\n throw new AuthError(\n \"API_KEY_REVOKED\",\n \"Cannot rotate a key that is already revoked.\",\n ).toConvexError();\n }\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId,\n data: { revoked: true },\n });\n return await auth.key.create(ctx, {\n userId: (existing as any).userId,\n name: opts?.name ?? (existing as any).name,\n scopes: (existing as any).scopes ?? [],\n rateLimit: (existing as any).rateLimit,\n expiresAt: opts?.expiresAt,\n metadata: (existing as any).metadata,\n });\n },\n },\n /**\n * SSO namespace — enterprise SSO connection management, domain, OIDC,\n * SAML, SCIM, audit, and webhook helpers.\n */\n sso: {\n connection: {\n create: async (\n ctx: ComponentCtx,\n data: {\n groupId: string;\n slug?: string;\n name?: string;\n status?: \"draft\" | \"active\" | \"disabled\";\n config?: Record<string, unknown>;\n extend?: Record<string, unknown>;\n },\n ): Promise<string> => {\n return (await ctx.runMutation(\n config.component.public.enterpriseCreate,\n data,\n )) as string;\n },\n get: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n return await ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId,\n });\n },\n getByGroup: async (ctx: ComponentReadCtx, groupId: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseGetByGroup,\n {\n groupId,\n },\n );\n },\n getByDomain: async (ctx: ComponentReadCtx, domain: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseGetByDomain,\n {\n domain: normalizeDomain(domain),\n },\n );\n },\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n groupId?: string;\n slug?: string;\n status?: \"draft\" | \"active\" | \"disabled\";\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"name\" | \"slug\" | \"status\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.enterpriseList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n update: async (\n ctx: ComponentCtx,\n enterpriseId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.enterpriseUpdate, {\n enterpriseId,\n data,\n });\n },\n remove: async (ctx: ComponentCtx, enterpriseId: string) => {\n await ctx.runMutation(config.component.public.enterpriseDelete, {\n enterpriseId,\n });\n },\n /**\n * Aggregate readiness status across all configured protocols for an\n * enterprise connection.\n *\n * Returns a structured result indicating whether the connection is\n * ready, with per-protocol checks so callers can surface actionable\n * diagnostics without running full network validation.\n */\n status: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n { enterpriseId },\n );\n if (!enterprise) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ).toConvexError();\n }\n const protocols = enterprise.config?.protocols ?? {};\n const oidcConfig = protocols.oidc;\n const samlConfig = protocols.saml;\n const scimConfig = await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByEnterprise,\n { enterpriseId },\n );\n const domains = await ctx.runQuery(\n config.component.public.enterpriseDomainList,\n { enterpriseId },\n );\n\n const oidcReady =\n oidcConfig?.enabled === true &&\n typeof oidcConfig?.clientId === \"string\" &&\n oidcConfig.clientId.length > 0 &&\n (typeof oidcConfig?.issuer === \"string\" ||\n typeof oidcConfig?.discoveryUrl === \"string\");\n const samlReady =\n samlConfig?.enabled === true &&\n typeof samlConfig?.idp?.entityId === \"string\";\n const scimReady =\n scimConfig !== null &&\n scimConfig !== undefined &&\n (scimConfig as any).status === \"active\";\n\n const ready =\n enterprise.status === \"active\" && (oidcReady || samlReady);\n\n return {\n enterpriseId: enterprise._id,\n status: enterprise.status,\n ready,\n domainCount: (domains as unknown[]).length,\n protocols: {\n oidc: {\n configured: oidcReady,\n ready: oidcReady,\n clientId: oidcConfig?.clientId ?? null,\n issuer: oidcConfig?.issuer ?? oidcConfig?.discoveryUrl ?? null,\n },\n saml: {\n configured: samlReady,\n ready: samlReady,\n entityId: samlConfig?.idp?.entityId ?? null,\n },\n scim: {\n configured: scimReady,\n ready: scimReady,\n basePath: scimConfig?.basePath ?? null,\n deprovisionMode: scimConfig?.deprovisionMode ?? null,\n },\n },\n };\n },\n },\n domain: {\n add: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n groupId: string;\n domain: string;\n isPrimary?: boolean;\n verifiedAt?: number;\n },\n ): Promise<string> => {\n return (await ctx.runMutation(\n config.component.public.enterpriseDomainAdd,\n {\n ...data,\n domain: normalizeDomain(data.domain),\n },\n )) as string;\n },\n list: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseDomainList,\n {\n enterpriseId,\n },\n );\n },\n remove: async (ctx: ComponentCtx, domainId: string) => {\n await ctx.runMutation(\n config.component.public.enterpriseDomainDelete,\n {\n domainId,\n },\n );\n },\n },\n saml: {\n configure: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n data: {\n enterpriseId: string;\n metadataXml?: string;\n metadataUrl?: string;\n domains?: string[];\n signAuthnRequests?: boolean;\n attributeMapping?: {\n subject?: string;\n email?: string;\n name?: string;\n firstName?: string;\n lastName?: string;\n };\n sp?: {\n entityId?: string;\n acsUrl?: string;\n sloUrl?: string;\n signingCert?: string | string[];\n encryptCert?: string | string[];\n privateKey?: string;\n privateKeyPass?: string;\n encPrivateKey?: string;\n encPrivateKeyPass?: string;\n };\n },\n ) => {\n return await Fx.run(\n Fx.gen(function* () {\n const enterprise = yield* Fx.from({\n ok: () =>\n ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId: data.enterpriseId,\n }),\n err: () =>\n new AuthError(\"INTERNAL_ERROR\", \"Failed to load enterprise.\"),\n }).pipe(\n Fx.chain((ent) =>\n ent === null\n ? Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ),\n )\n : Fx.succeed(ent),\n ),\n );\n const metadataXml = yield* data.metadataXml\n ? Fx.succeed(data.metadataXml)\n : data.metadataUrl\n ? Fx.defer(() =>\n Fx.from({\n ok: async () => {\n const response = await fetch(data.metadataUrl!);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch SAML metadata: ${response.status}`,\n );\n }\n return await response.text();\n },\n err: (error) =>\n new AuthError(\n \"INVALID_PARAMETERS\",\n error instanceof Error\n ? error.message\n : \"Failed to fetch SAML metadata\",\n ),\n }),\n ).pipe(\n Fx.timeout(10_000),\n Fx.retry(\n Fx.retry.compose(\n Fx.retry.jittered(Fx.retry.exponential(200)),\n Fx.retry.recurs(2),\n ),\n ),\n Fx.recover((error) =>\n Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n error instanceof Error\n ? error.message\n : \"Failed to fetch SAML metadata\",\n ),\n ),\n ),\n )\n : Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"SAML registration requires metadataXml or metadataUrl.\",\n ),\n );\n\n const parsed = yield* Fx.from({\n ok: () => parseSamlIdpMetadata(metadataXml),\n err: () =>\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"Failed to parse SAML metadata.\",\n ),\n });\n\n const baseConfig = upsertProtocolConfig(\n enterprise.config,\n \"saml\",\n {\n enabled: true,\n idp: {\n metadataXml,\n ...parsed,\n },\n sp: data.sp,\n signAuthnRequests:\n data.signAuthnRequests ?? parsed.wantsSignedAuthnRequests,\n attributeMapping: data.attributeMapping,\n accountLinking: \"verifiedEmail\",\n reuseScimUserBy: \"externalId\",\n },\n );\n const normalizedDomains = data.domains?.map(normalizeDomain);\n const nextConfig = normalizedDomains\n ? { ...baseConfig, domains: normalizedDomains }\n : baseConfig;\n\n yield* Fx.from({\n ok: () =>\n ctx.runMutation(config.component.public.enterpriseUpdate, {\n enterpriseId: enterprise._id,\n data: {\n status: \"active\",\n config: nextConfig,\n },\n }),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to persist SAML registration.\",\n ),\n });\n\n if (normalizedDomains) {\n for (const [index, domain] of normalizedDomains.entries()) {\n yield* Fx.from({\n ok: () =>\n ctx.runMutation(\n config.component.public.enterpriseDomainAdd,\n {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n domain,\n isPrimary: index === 0,\n },\n ),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to persist enterprise domain.\",\n ),\n });\n }\n }\n\n yield* Fx.from({\n ok: () =>\n recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType: \"enterprise.saml.registered\",\n actorType: \"system\",\n subjectType: \"enterprise_saml\",\n subjectId: enterprise._id,\n ok: true,\n metadata: {\n metadataUrl: data.metadataUrl,\n domains: normalizedDomains,\n },\n }),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to record SAML registration audit event.\",\n ),\n });\n\n return {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n };\n }).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),\n );\n },\n metadata: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n opts: {\n enterpriseId: string;\n entityId?: string;\n acsUrl?: string;\n sloUrl?: string;\n },\n ) => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: opts.enterpriseId,\n },\n );\n if (!enterprise) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n\n return createServiceProviderMetadata(\n getSamlServiceProviderOptions({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: enterprise.config,\n overrides: {\n entityId: opts.entityId,\n acsUrl: opts.acsUrl,\n sloUrl: opts.sloUrl,\n },\n }),\n );\n },\n /**\n * Validate the stored SAML config for an enterprise connection.\n *\n * Re-parses IdP metadata, checks signing cert presence, and verifies\n * SP metadata can be generated. Returns a structured result with\n * per-check details rather than throwing on first failure.\n */\n validate: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n enterpriseId: string,\n ) => {\n const checks: Array<{\n name: string;\n ok: boolean;\n message?: string;\n }> = [];\n\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n { enterpriseId },\n );\n\n if (!enterprise) {\n return {\n ok: false,\n enterpriseId,\n checks: [\n {\n name: \"enterprise_exists\",\n ok: false,\n message: \"Enterprise not found.\",\n },\n ],\n };\n }\n\n const samlConfig = enterprise.config?.protocols?.saml;\n const samlConfigured =\n samlConfig?.enabled === true &&\n typeof samlConfig?.idp?.metadataXml === \"string\";\n\n checks.push({\n name: \"saml_configured\",\n ok: samlConfigured,\n message: samlConfigured ? undefined : \"SAML is not configured.\",\n });\n\n const hasIdpMetadata =\n typeof samlConfig?.idp?.metadataXml === \"string\" &&\n samlConfig.idp.metadataXml.length > 0;\n checks.push({\n name: \"idp_metadata_present\",\n ok: hasIdpMetadata,\n message: hasIdpMetadata\n ? undefined\n : \"IdP metadata XML is missing.\",\n });\n\n const hasEntityId =\n typeof samlConfig?.idp?.entityId === \"string\" &&\n samlConfig.idp.entityId.length > 0;\n checks.push({\n name: \"idp_entity_id\",\n ok: hasEntityId,\n message: hasEntityId\n ? undefined\n : \"IdP entityId could not be parsed from metadata.\",\n });\n\n let spMetadataOk = false;\n let spMetadataMessage: string | undefined;\n if (samlConfigured) {\n try {\n createServiceProviderMetadata(\n getSamlServiceProviderOptions({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: enterprise.config,\n overrides: {},\n }),\n );\n spMetadataOk = true;\n } catch (e) {\n spMetadataMessage =\n e instanceof Error\n ? e.message\n : \"SP metadata generation failed.\";\n }\n } else {\n spMetadataMessage = \"Skipped — SAML not configured.\";\n }\n checks.push({\n name: \"sp_metadata_generates\",\n ok: spMetadataOk,\n message: spMetadataMessage,\n });\n\n return {\n ok: checks.every((c) => c.ok),\n enterpriseId: enterprise._id,\n checks,\n };\n },\n },\n oidc: {\n /**\n * Register or update enterprise OIDC connection settings.\n *\n * Persists protocol config under `enterprise.config.protocols.oidc` and\n * records an `enterprise.oidc.registered` audit event.\n */\n configure: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n issuer?: string;\n discoveryUrl?: string;\n clientId: string;\n clientSecret?: string;\n scopes?: string[];\n authorizationParams?: Record<string, string>;\n clockToleranceSeconds?: number;\n strictIssuer?: boolean;\n /**\n * Map OIDC claim names to `user.extend` field names.\n * Example: `{ department: \"department\", role: \"job_title\" }` means\n * the OIDC `department` claim is stored as `user.extend.department`.\n */\n extraFields?: Record<string, string>;\n },\n ) => {\n return await Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n data.issuer === undefined && data.discoveryUrl === undefined,\n Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"OIDC registration requires issuer or discoveryUrl.\",\n ),\n ),\n );\n\n const enterprise = yield* Fx.from({\n ok: () =>\n ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId: data.enterpriseId,\n }),\n err: () =>\n new AuthError(\"INTERNAL_ERROR\", \"Failed to load enterprise.\"),\n }).pipe(\n Fx.chain((ent) =>\n ent === null\n ? Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ),\n )\n : Fx.succeed(ent),\n ),\n );\n const nextConfig = upsertProtocolConfig(\n enterprise.config,\n \"oidc\",\n {\n enabled: true,\n issuer: data.issuer,\n discoveryUrl: data.discoveryUrl,\n clientId: data.clientId,\n clientSecret: data.clientSecret,\n scopes: data.scopes ?? [\"openid\", \"profile\", \"email\"],\n authorizationParams: data.authorizationParams,\n accountLinking: \"verifiedEmail\",\n reuseScimUserBy: \"externalId\",\n clockToleranceSeconds: data.clockToleranceSeconds,\n strictIssuer: data.strictIssuer,\n extraFields: data.extraFields,\n },\n );\n\n yield* Fx.from({\n ok: () =>\n ctx.runMutation(config.component.public.enterpriseUpdate, {\n enterpriseId: data.enterpriseId,\n data: { config: nextConfig },\n }),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to persist OIDC registration.\",\n ),\n });\n\n yield* Fx.from({\n ok: () =>\n recordEnterpriseAuditEvent(ctx, {\n enterpriseId: data.enterpriseId,\n groupId: enterprise.groupId,\n eventType: \"enterprise.oidc.registered\",\n actorType: \"system\",\n subjectType: \"enterprise_oidc\",\n subjectId: data.enterpriseId,\n ok: true,\n metadata: {\n issuer: data.issuer,\n discoveryUrl: data.discoveryUrl,\n },\n }),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to record OIDC registration audit event.\",\n ),\n });\n\n return getOidcConfig(nextConfig);\n }).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),\n );\n },\n /**\n * Fetch the stored OIDC config for an enterprise.\n */\n get: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n return await Fx.run(\n Fx.from({\n ok: () =>\n ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId,\n }),\n err: () =>\n new AuthError(\"INTERNAL_ERROR\", \"Failed to load enterprise.\"),\n }).pipe(\n Fx.chain((ent) =>\n ent === null\n ? Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ),\n )\n : Fx.succeed(ent),\n ),\n Fx.map((enterprise) => getOidcConfig(enterprise.config)),\n Fx.recover((e) => Fx.fatal(e.toConvexError())),\n ),\n );\n },\n /**\n * Resolve enterprise OIDC sign-in route from enterprise id, domain, or\n * user email domain.\n */\n resolveSignIn: async (\n ctx: ComponentReadCtx,\n data: {\n enterpriseId?: string;\n email?: string;\n domain?: string;\n redirectTo?: string;\n },\n ) => {\n return await Fx.run(\n Fx.gen(function* () {\n const enterprise =\n data.enterpriseId !== undefined\n ? yield* Fx.from({\n ok: () =>\n ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId: data.enterpriseId,\n }),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to load enterprise.\",\n ),\n }).pipe(\n Fx.chain((ent) =>\n ent === null\n ? Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n enterpriseNotFoundError,\n ),\n )\n : Fx.succeed(ent),\n ),\n )\n : data.domain !== undefined || data.email !== undefined\n ? yield* Fx.from({\n ok: () =>\n ctx.runQuery(\n config.component.public.enterpriseGetByDomain,\n {\n domain: normalizeDomain(\n data.domain ??\n String(data.email).split(\"@\").at(-1) ??\n \"\",\n ),\n },\n ),\n err: () =>\n new AuthError(\n \"INTERNAL_ERROR\",\n \"Failed to resolve enterprise by domain.\",\n ),\n }).pipe(\n Fx.chain((result) =>\n result?.enterprise\n ? Fx.succeed(result.enterprise)\n : Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"No enterprise OIDC connection matched the provided input.\",\n ),\n ),\n ),\n )\n : yield* Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"No enterprise OIDC connection matched the provided input.\",\n ),\n );\n\n yield* Fx.guard(\n enterprise.status !== \"active\",\n Fx.fail(\n new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ),\n ),\n );\n\n const oidc = getOidcConfig(enterprise.config);\n yield* Fx.guard(\n oidc.enabled !== true,\n Fx.fail(\n new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"OIDC is not configured for this enterprise.\",\n ),\n ),\n );\n\n const urls = getEnterpriseOidcUrls({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n });\n return {\n enterpriseId: enterprise._id,\n providerId: enterpriseOidcProviderId(enterprise._id),\n signInPath: urls.signInUrl,\n callbackPath: urls.callbackUrl,\n redirectTo: data.redirectTo,\n };\n }).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),\n );\n },\n /**\n * Validate the stored OIDC config for an enterprise connection.\n *\n * Fetches the OIDC discovery document from the configured issuer or\n * discoveryUrl, verifies required fields are present, and checks that\n * clientId is set. Returns a structured result with per-check details.\n */\n validate: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n const checks: Array<{\n name: string;\n ok: boolean;\n message?: string;\n }> = [];\n\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n { enterpriseId },\n );\n\n if (!enterprise) {\n return {\n ok: false,\n enterpriseId,\n checks: [\n {\n name: \"enterprise_exists\",\n ok: false,\n message: \"Enterprise not found.\",\n },\n ],\n };\n }\n\n const oidc = getOidcConfig(enterprise.config);\n const oidcConfigured =\n oidc.enabled === true &&\n typeof oidc.clientId === \"string\" &&\n oidc.clientId.length > 0;\n\n checks.push({\n name: \"oidc_configured\",\n ok: oidcConfigured,\n message: oidcConfigured ? undefined : \"OIDC is not configured.\",\n });\n\n const hasClientId =\n typeof oidc.clientId === \"string\" && oidc.clientId.length > 0;\n checks.push({\n name: \"client_id_present\",\n ok: hasClientId,\n message: hasClientId ? undefined : \"clientId is missing.\",\n });\n\n const discoveryTarget = oidc.discoveryUrl ?? oidc.issuer;\n const hasDiscovery =\n typeof discoveryTarget === \"string\" && discoveryTarget.length > 0;\n checks.push({\n name: \"issuer_or_discovery_url_present\",\n ok: hasDiscovery,\n message: hasDiscovery\n ? undefined\n : \"issuer or discoveryUrl is missing.\",\n });\n\n let discoveryOk = false;\n let discoveryMessage: string | undefined;\n if (hasDiscovery) {\n const discoveryUrl = oidc.discoveryUrl?.length\n ? oidc.discoveryUrl\n : `${oidc.issuer}/.well-known/openid-configuration`;\n try {\n const res = await fetch(discoveryUrl, {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(8_000),\n });\n if (!res.ok) {\n discoveryMessage = `Discovery endpoint returned ${res.status}.`;\n } else {\n const json = (await res.json()) as Record<string, unknown>;\n if (typeof json.issuer !== \"string\") {\n discoveryMessage =\n \"Discovery document is missing issuer field.\";\n } else if (typeof json.authorization_endpoint !== \"string\") {\n discoveryMessage =\n \"Discovery document is missing authorization_endpoint.\";\n } else {\n discoveryOk = true;\n }\n }\n } catch (e) {\n discoveryMessage =\n e instanceof Error\n ? `Discovery fetch failed: ${e.message}`\n : \"Discovery fetch failed.\";\n }\n } else {\n discoveryMessage = \"Skipped — issuer or discoveryUrl not set.\";\n }\n checks.push({\n name: \"discovery_reachable\",\n ok: discoveryOk,\n message: discoveryMessage,\n });\n\n return {\n ok: checks.every((c) => c.ok),\n enterpriseId: enterprise._id,\n checks,\n };\n },\n },\n scim: {\n configure: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n basePath?: string;\n deprovisionMode?: \"soft\" | \"hard\";\n status?: \"draft\" | \"active\" | \"disabled\";\n },\n ) => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: data.enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const rawToken = generateRandomString(48, INVITE_TOKEN_ALPHABET);\n const tokenHash = await sha256(rawToken);\n const configId = (await ctx.runMutation(\n config.component.public.enterpriseScimConfigUpsert,\n {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n status: data.status ?? \"active\",\n basePath:\n data.basePath ??\n `${requireEnv(\"CONVEX_SITE_URL\")}/api/auth/sso/${enterprise._id}/scim/v2`,\n tokenHash,\n lastRotatedAt: Date.now(),\n deprovisionMode: data.deprovisionMode ?? \"soft\",\n },\n )) as string;\n const auditEventId = await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType: \"enterprise.scim.configured\",\n actorType: \"system\",\n subjectType: \"enterprise_scim\",\n subjectId: configId,\n ok: true,\n });\n await emitEnterpriseWebhookDeliveries(ctx, {\n enterpriseId: enterprise._id,\n eventType: \"enterprise.scim.configured\",\n auditEventId,\n payload: { enterpriseId: enterprise._id, scimConfigId: configId },\n });\n return { token: rawToken, configId };\n },\n get: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByEnterprise,\n { enterpriseId },\n );\n },\n getConfigByToken: async (ctx: ComponentReadCtx, token: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByTokenHash,\n { tokenHash: await sha256(token) },\n );\n },\n /**\n * Validate the stored SCIM config for an enterprise connection.\n *\n * Checks that a SCIM config record exists, is active, has a token\n * hash set, and has a non-empty basePath. Returns a structured result\n * with per-check details.\n */\n validate: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n const checks: Array<{\n name: string;\n ok: boolean;\n message?: string;\n }> = [];\n\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n { enterpriseId },\n );\n\n if (!enterprise) {\n return {\n ok: false,\n enterpriseId,\n checks: [\n {\n name: \"enterprise_exists\",\n ok: false,\n message: \"Enterprise not found.\",\n },\n ],\n };\n }\n\n const scimConfig = await ctx.runQuery(\n config.component.public.enterpriseScimConfigGetByEnterprise,\n { enterpriseId },\n );\n\n const hasConfig = scimConfig !== null && scimConfig !== undefined;\n checks.push({\n name: \"scim_config_exists\",\n ok: hasConfig,\n message: hasConfig ? undefined : \"SCIM has not been configured.\",\n });\n\n const isActive = hasConfig && (scimConfig as any).status === \"active\";\n checks.push({\n name: \"scim_config_active\",\n ok: isActive,\n message: isActive\n ? undefined\n : `SCIM config status is ${hasConfig ? (scimConfig as any).status : \"unknown\"}.`,\n });\n\n const hasToken =\n hasConfig &&\n typeof (scimConfig as any).tokenHash === \"string\" &&\n (scimConfig as any).tokenHash.length > 0;\n checks.push({\n name: \"token_hash_set\",\n ok: hasToken,\n message: hasToken\n ? undefined\n : \"SCIM bearer token has not been set.\",\n });\n\n const hasBasePath =\n hasConfig &&\n typeof (scimConfig as any).basePath === \"string\" &&\n (scimConfig as any).basePath.length > 0;\n checks.push({\n name: \"base_path_set\",\n ok: hasBasePath,\n message: hasBasePath ? undefined : \"SCIM basePath is missing.\",\n });\n\n return {\n ok: checks.every((c) => c.ok),\n enterpriseId: enterprise._id,\n basePath: hasBasePath ? (scimConfig as any).basePath : null,\n deprovisionMode: hasConfig\n ? (scimConfig as any).deprovisionMode\n : null,\n checks,\n };\n },\n identity: {\n get: async (\n ctx: ComponentReadCtx,\n data: {\n enterpriseId: string;\n resourceType: \"user\" | \"group\";\n externalId: string;\n },\n ) => {\n return await ctx.runQuery(\n config.component.public.enterpriseScimIdentityGet,\n data,\n );\n },\n upsert: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n groupId: string;\n resourceType: \"user\" | \"group\";\n externalId: string;\n userId?: string;\n mappedGroupId?: string;\n active?: boolean;\n raw?: Record<string, unknown>;\n },\n ) => {\n return (await ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n { ...data, lastProvisionedAt: Date.now() },\n )) as string;\n },\n },\n },\n audit: {\n record: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n groupId: string;\n eventType: string;\n actorType: \"user\" | \"system\" | \"scim\" | \"api_key\" | \"webhook\";\n actorId?: string;\n subjectType: string;\n subjectId?: string;\n ok: boolean;\n requestId?: string;\n ip?: string;\n metadata?: Record<string, unknown>;\n },\n ) => {\n return await recordEnterpriseAuditEvent(ctx, data);\n },\n list: async (\n ctx: ComponentReadCtx,\n data: { enterpriseId?: string; groupId?: string; limit?: number },\n ) => {\n return await ctx.runQuery(\n config.component.public.enterpriseAuditEventList,\n data,\n );\n },\n },\n webhook: {\n endpoint: {\n create: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n url: string;\n secret: string;\n subscriptions: string[];\n createdByUserId?: string;\n },\n ) => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: data.enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const secretHash = await sha256(data.secret);\n const endpointId = (await ctx.runMutation(\n config.component.public.enterpriseWebhookEndpointCreate,\n {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n url: data.url,\n secretHash,\n subscriptions: data.subscriptions,\n createdByUserId: data.createdByUserId,\n },\n )) as string;\n await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType: \"enterprise.webhook.endpoint.created\",\n actorType: data.createdByUserId ? \"user\" : \"system\",\n actorId: data.createdByUserId,\n subjectType: \"enterprise_webhook_endpoint\",\n subjectId: endpointId,\n ok: true,\n });\n return { endpointId };\n },\n list: async (ctx: ComponentReadCtx, enterpriseId: string) => {\n return await ctx.runQuery(\n config.component.public.enterpriseWebhookEndpointList,\n { enterpriseId },\n );\n },\n disable: async (ctx: ComponentCtx, endpointId: string) => {\n await ctx.runMutation(\n config.component.public.enterpriseWebhookEndpointUpdate,\n { endpointId, data: { status: \"disabled\" } },\n );\n },\n },\n emit: async (\n ctx: ComponentCtx,\n data: {\n enterpriseId: string;\n eventType: string;\n payload: Record<string, unknown>;\n auditEventId?: string;\n },\n ) => {\n await emitEnterpriseWebhookDeliveries(ctx, data);\n },\n delivery: {\n list: async (\n ctx: ComponentReadCtx,\n data: { enterpriseId: string; limit?: number },\n ) => {\n return await ctx.runQuery(\n (config.component.public as any).enterpriseWebhookDeliveryList,\n data,\n );\n },\n listReady: async (ctx: ComponentReadCtx, limit?: number) => {\n return await ctx.runQuery(\n config.component.public.enterpriseWebhookDeliveryListReady,\n { now: Date.now(), limit },\n );\n },\n markDelivered: async (\n ctx: ComponentCtx,\n deliveryId: string,\n responseStatus?: number,\n ) => {\n await ctx.runMutation(\n config.component.public.enterpriseWebhookDeliveryPatch,\n {\n deliveryId,\n data: {\n status: \"delivered\",\n attemptCount: 1,\n lastAttemptAt: Date.now(),\n lastResponseStatus: responseStatus,\n },\n },\n );\n },\n markFailed: async (\n ctx: ComponentCtx,\n deliveryId: string,\n data: {\n attemptCount: number;\n responseStatus?: number;\n error?: string;\n retryAt?: number;\n },\n ) => {\n await ctx.runMutation(\n config.component.public.enterpriseWebhookDeliveryPatch,\n {\n deliveryId,\n data: {\n status: data.retryAt ? \"pending\" : \"failed\",\n attemptCount: data.attemptCount,\n lastAttemptAt: Date.now(),\n lastResponseStatus: data.responseStatus,\n lastError: data.error,\n nextAttemptAt: data.retryAt ?? Date.now(),\n },\n },\n );\n },\n },\n },\n },\n /**\n * HTTP namespace — route registration and Bearer-authenticated endpoints.\n */\n http: {\n /**\n * Register core HTTP routes for JWT verification and OAuth sign-in.\n *\n * ```ts\n * import { httpRouter } from \"convex/server\";\n * import { auth } from \"./auth\";\n *\n * const http = httpRouter();\n *\n * auth.http.add(http);\n *\n * export default http;\n * ```\n *\n * The following routes are handled always:\n *\n * - `/.well-known/openid-configuration`\n * - `/.well-known/jwks.json`\n *\n * The following routes are handled if OAuth is configured:\n *\n * - `/api/auth/signin/*`\n * - `/api/auth/callback/*`\n *\n * @param http your HTTP router\n */\n add: (http: HttpRouter) => {\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(\n JSON.stringify({\n issuer: requireEnv(\"CONVEX_SITE_URL\"),\n jwks_uri:\n requireEnv(\"CONVEX_SITE_URL\") + \"/.well-known/jwks.json\",\n authorization_endpoint:\n requireEnv(\"CONVEX_SITE_URL\") + \"/oauth/authorize\",\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\":\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\",\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(requireEnv(\"JWKS\"), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\":\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\",\n },\n });\n }),\n });\n\n if (hasSSO) {\n http.route({\n pathPrefix: `${ENTERPRISE_CONTROL_ROUTE_BASE}/`,\n method: \"GET\",\n handler: httpActionGeneric(\n convertErrorsToResponse(400, async (ctx, request) => {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n if (!runtimeRoute) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"metadata\"\n ) {\n const enterpriseDoc = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: runtimeRoute.enterpriseId,\n },\n );\n if (enterpriseDoc === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const loaded = {\n source: {\n kind: \"enterprise\" as const,\n id: runtimeRoute.enterpriseId,\n },\n config: enterpriseDoc.config,\n status: enterpriseDoc.status,\n };\n if (!isEnterpriseSamlSourceActive(loaded)) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const samlConfig = getSamlConfig(loaded.config);\n if (!samlConfig.idp?.metadataXml) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"SAML is not configured for this enterprise.\",\n ).toConvexError();\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 if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"signin\"\n ) {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\n \"OAUTH_MISSING_VERIFIER\",\n ).toConvexError();\n }\n const enterpriseDoc = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: runtimeRoute.enterpriseId,\n },\n );\n if (enterpriseDoc === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const loaded = {\n source: {\n kind: \"enterprise\" as const,\n id: runtimeRoute.enterpriseId,\n },\n config: enterpriseDoc.config,\n status: enterpriseDoc.status,\n enterprise: enterpriseDoc,\n };\n if (!isEnterpriseSamlSourceActive(loaded)) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const samlConfig = getSamlConfig(loaded.config);\n if (!samlConfig.idp?.metadataXml) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"SAML is not configured for this enterprise.\",\n ).toConvexError();\n }\n const enterprise = loaded.enterprise;\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 (\n signInRequest.binding === \"redirect\" &&\n signInRequest.redirectUrl\n ) {\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 {\n name,\n value,\n options,\n } of redirectCookies as any) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\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 {\n name,\n value,\n options,\n } of redirectCookies as any) {\n response.headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return response;\n }\n if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"acs\"\n ) {\n return await samlAcsHandler(ctx, request);\n }\n if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"slo\"\n ) {\n return await samlSloHandler(ctx, request);\n }\n if (\n runtimeRoute.protocol === \"oidc\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"signin\"\n ) {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw new AuthError(\n \"OAUTH_MISSING_VERIFIER\",\n ).toConvexError();\n }\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId: runtimeRoute.enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n if (enterprise.status !== \"active\") {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const oidc = getOidcConfig(enterprise.config);\n if (oidc.enabled !== true) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"OIDC is not configured for this enterprise.\",\n ).toConvexError();\n }\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n config: enterprise.config,\n });\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(\n providerId,\n provider,\n oauthConfig,\n );\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(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, {\n status: 302,\n headers: headers_,\n });\n }\n if (\n runtimeRoute.protocol === \"oidc\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"callback\"\n ) {\n const url = new URL(request.url);\n const enterpriseId = runtimeRoute.enterpriseId;\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const oidc = getOidcConfig(enterprise.config);\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n config: enterprise.config,\n });\n const cookies = getCookies(request);\n const maybeRedirectTo = useRedirectToParam(\n providerId,\n cookies,\n );\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 );\n // Apply OIDC extra field mapping if configured\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(\n extraFields,\n )) {\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:\n typeof oidc.issuer === \"string\"\n ? oidc.issuer\n : undefined,\n discoveryUrl:\n typeof oidc.discoveryUrl === \"string\"\n ? oidc.discoveryUrl\n : undefined,\n },\n },\n });\n const headers = new Headers({\n Location: setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n ),\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 if (\n runtimeRoute.protocol === \"scim\" &&\n runtimeRoute.rest[0] === \"v2\"\n ) {\n return await enterpriseScimHandler(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: `${ENTERPRISE_CONTROL_ROUTE_BASE}/`,\n method: \"POST\",\n handler: httpActionGeneric(\n convertErrorsToResponse(400, async (ctx, request) => {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n pathname: runtimePathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n if (runtimeRoute) {\n if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"acs\"\n ) {\n return await samlAcsHandler(ctx, request);\n }\n if (\n runtimeRoute.protocol === \"saml\" &&\n runtimeRoute.rest.length === 1 &&\n runtimeRoute.rest[0] === \"slo\"\n ) {\n return await samlSloHandler(ctx, request);\n }\n if (\n runtimeRoute.protocol === \"scim\" &&\n runtimeRoute.rest[0] === \"v2\"\n ) {\n return await enterpriseScimHandler(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: `${ENTERPRISE_CONTROL_ROUTE_BASE}/`,\n method: \"PUT\",\n handler: httpActionGeneric(\n convertErrorsToResponse(400, async (ctx, request) => {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n pathname: runtimePathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n if (runtimeRoute) {\n if (\n runtimeRoute.protocol === \"scim\" &&\n runtimeRoute.rest[0] === \"v2\"\n ) {\n return await enterpriseScimHandler(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n const samlAcsHandler = convertErrorsToResponse(\n 400,\n async (ctx, request) =>\n Fx.run(\n Fx.gen(function* () {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n pathname: runtimePathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n yield* Fx.guard(\n !runtimeRoute ||\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, saml } = yield* Fx.from({\n ok: async () => {\n const enterprise = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId,\n },\n );\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const loaded = {\n source: {\n kind: \"enterprise\" as const,\n id: enterpriseId,\n },\n config: enterprise.config,\n status: enterprise.status,\n enterprise,\n };\n if (!isEnterpriseSamlSourceActive(loaded)) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const saml = getSamlConfig(loaded.config);\n if (!saml.idp?.metadataXml) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"SAML is not configured for this enterprise.\",\n ).toConvexError();\n }\n return { loaded, saml };\n },\n err: (e) => e,\n });\n\n const enterprise = loaded.enterprise;\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 // samlAttributes and samlSessionIndex are SAML-specific — they\n // must not be stored in the User document. Put them in the\n // account extend payload and pass only standard fields to the\n // user upsert.\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 ===\n \"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 !==\n null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n vheaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, { status: 302, headers: vheaders });\n }).pipe(Fx.recover((e) => Fx.fatal(e))),\n ),\n );\n\n const samlSloHandler = convertErrorsToResponse(\n 400,\n async (ctx, request) => {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n pathname: runtimePathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n if (\n !runtimeRoute ||\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 enterpriseId = runtimeRoute.enterpriseId;\n const enterpriseDoc = await ctx.runQuery(\n config.component.public.enterpriseGet,\n {\n enterpriseId,\n },\n );\n if (enterpriseDoc === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n const loaded = {\n source: { kind: \"enterprise\" as const, id: enterpriseId },\n config: enterpriseDoc.config,\n status: enterpriseDoc.status,\n enterprise: enterpriseDoc,\n };\n if (!isEnterpriseSamlSourceActive(loaded)) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise connection is not active.\",\n ).toConvexError();\n }\n const saml = getSamlConfig(loaded.config);\n if (!saml.idp?.metadataXml) {\n throw new AuthError(\n \"PROVIDER_NOT_CONFIGURED\",\n \"SAML is not configured for this enterprise.\",\n ).toConvexError();\n }\n const enterprise = loaded.enterprise;\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.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\n const enterpriseScimHandler = 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 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\n .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(\n state.ctx,\n member.userId,\n );\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(\n users,\n listRequest.filter,\n {\n id: (item: { user: any }, value: string) =>\n 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: (\n item: { identity?: any; member: any },\n value: string,\n ) =>\n String(\n item.identity?.active ??\n item.member.status === \"active\",\n ) === value,\n },\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: [\n \"urn:ietf:params:scim:api:messages:2.0:ListResponse\",\n ],\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)\n ?.value ?? 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.add(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n role: \"member\",\n status: body.active === false ? \"inactive\" : \"active\",\n });\n } catch {}\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 : undefined,\n userId,\n active: body.active !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\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)\n ? body.emails[0]?.value\n : 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 membership = await auth.member.getByUserAndGroup(\n state.ctx,\n {\n groupId: state.enterprise.groupId,\n userId,\n },\n );\n if (membership) {\n await auth.member.update(state.ctx, 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 : undefined,\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\"\n ? body.externalId\n : 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 membership = await auth.member.getByUserAndGroup(\n state.ctx,\n {\n groupId: state.enterprise.groupId,\n userId,\n },\n );\n if (membership) {\n await auth.member.remove(state.ctx, membership._id);\n }\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByUser,\n { userId },\n );\n if (identity) {\n if (state.scimConfig.deprovisionMode === \"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\n .enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByGroupId = new Map(\n identities\n .filter(\n (identity: any) => identity.mappedGroupId !== undefined,\n )\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) =>\n 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: [\n \"urn:ietf:params:scim:api:messages:2.0:ListResponse\",\n ],\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)\n ? body.members\n : []) {\n try {\n await auth.member.add(state.ctx, {\n groupId,\n userId: String(member.value),\n role: \"member\",\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.add(state.ctx, {\n groupId,\n userId: String(member.value),\n role: \"member\",\n status: \"active\",\n });\n } catch {}\n }\n }\n if (\n operation.path === \"members\" &&\n operation.op === \"replace\"\n ) {\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)\n ? operation.value\n : []\n ).map((member: any) => String(member.value)),\n );\n for (const member of currentMembers) {\n if (!nextUserIds.has(member.userId)) {\n await auth.member.remove(state.ctx, member._id);\n }\n }\n for (const userId of nextUserIds.values()) {\n if (!currentUserIds.has(userId)) {\n try {\n await auth.member.add(state.ctx, {\n groupId,\n userId,\n role: \"member\",\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 membership = await auth.member.getByUserAndGroup(\n state.ctx,\n { groupId, userId },\n );\n if (membership) {\n await auth.member.remove(state.ctx, 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\n .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 for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: \"/api/auth/sso/\",\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const runtimePathname = new URL(request.url).pathname;\n const runtimePrefix = `${ENTERPRISE_CONTROL_ROUTE_BASE}/`;\n const runtimeParts = runtimePathname.startsWith(runtimePrefix)\n ? runtimePathname\n .slice(runtimePrefix.length)\n .split(\"/\")\n .filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n const runtimeRoute =\n runtimeEnterpriseId !== undefined &&\n (protocol === \"oidc\" ||\n protocol === \"saml\" ||\n protocol === \"scim\") &&\n rest.length > 0\n ? ({\n pathname: runtimePathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n } as const)\n : null;\n if (\n !runtimeRoute ||\n runtimeRoute.protocol !== \"scim\" ||\n runtimeRoute.rest[0] !== \"v2\"\n ) {\n return scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await enterpriseScimHandler(ctx, request);\n }),\n });\n }\n } // end if (hasSSO)\n\n if (hasOAuth) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(\n convertErrorsToResponse(400, async (ctx, request) => {\n const url = new URL(request.url);\n const pathParts = url.pathname.split(\"/\");\n const providerId = pathParts.at(-1)!;\n if (providerId === null) {\n throw new AuthError(\"OAUTH_MISSING_PROVIDER\").toConvexError();\n }\n const verifier = url.searchParams.get(\"code\");\n if (verifier === null) {\n throw new AuthError(\"OAUTH_MISSING_VERIFIER\").toConvexError();\n }\n const provider = getProviderOrThrow(providerId);\n\n const oauthConfig = provider as OAuthMaterializedConfig;\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(\n providerId,\n oauthConfig.provider,\n oauthConfig,\n );\n\n await callVerifierSignature(ctx, {\n verifier,\n signature,\n });\n\n const redirectTo = url.searchParams.get(\"redirectTo\");\n if (redirectTo !== null) {\n cookies.push(redirectToParamCookie(providerId, redirectTo));\n }\n\n const headers = new Headers({ Location: redirect });\n for (const { name, value, options } of cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n\n return new Response(null, { status: 302, headers });\n }),\n ),\n });\n\n const callbackAction = httpActionGeneric(async (ctx, request) => {\n const url = new URL(request.url);\n const providerId = new URL(request.url).pathname.split(\"/\").at(-1);\n if (!providerId) {\n throw new AuthError(\"OAUTH_MISSING_PROVIDER\").toConvexError();\n }\n logWithLevel(\n LOG_LEVELS.DEBUG,\n \"Handling OAuth callback for provider:\",\n providerId,\n );\n const provider = getProviderOrThrow(providerId);\n\n const cookies = getCookies(request);\n\n const maybeRedirectTo = useRedirectToParam(provider.id, cookies);\n\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n\n const params = url.searchParams;\n\n // Handle OAuth providers that use formData (such as Apple)\n if (\n request.headers.get(\"Content-Type\") ===\n \"application/x-www-form-urlencoded\"\n ) {\n const formData = await request.formData();\n formData.forEach((value, key) => {\n if (typeof value === \"string\") {\n params.append(key, value);\n }\n });\n }\n\n return Fx.run(\n Fx.from({\n ok: async () => {\n const oauthConfig = provider as OAuthMaterializedConfig;\n const result = await Fx.run(\n handleOAuthCallback(\n providerId,\n oauthConfig.provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n );\n const oauthCookies = result.cookies;\n const { id: profileId, ...profileData } = result.profile;\n const { signature } = result;\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: profileId,\n profile: profileData,\n signature,\n });\n\n const redirUrl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const redirHeaders = new Headers({ Location: redirUrl });\n redirHeaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of [\n ...oauthCookies,\n ...(maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []),\n ] as any) {\n redirHeaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return new Response(null, {\n status: 302,\n headers: redirHeaders,\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n const respHeaders = new Headers({ Location: destinationUrl });\n for (const { name, value, options } of maybeRedirectTo !==\n null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n respHeaders.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return Fx.succeed(\n new Response(null, { status: 302, headers: respHeaders }),\n );\n }),\n ),\n );\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackAction,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackAction,\n });\n }\n },\n\n /**\n * Wrap an HTTP action handler with Bearer token authentication.\n *\n * Extracts the `Authorization: Bearer <key>` header, verifies the\n * API key via `auth.key.verify()`, and injects `ctx.key` with the\n * verified key info. Returns structured JSON error responses for\n * missing/invalid/revoked/expired/rate-limited keys.\n *\n * If the handler returns a plain object, it is auto-wrapped in a\n * `200 JSON` response. If it returns a `Response`, CORS headers\n * are merged and the response is passed through.\n *\n * ```ts\n * const handler = auth.http.action(async (ctx, request) => {\n * const data = await ctx.runQuery(api.data.get, { userId: ctx.key.userId });\n * return { data };\n * });\n * http.route({ path: \"/api/data\", method: \"GET\", handler });\n * ```\n *\n * @param handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param options.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param options.cors - CORS config; defaults to permissive (`*`).\n */\n action: (\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 // 1. Extract Bearer token\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error:\n \"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 // 2. Verify API key — auth errors become JSON error responses\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(\n JSON.stringify({ error: message, code }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n throw keyResult.error;\n }\n\n // 3. Optional scope check\n if (options?.scope) {\n if (\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error:\n \"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\n // 4. Enrich context with key info\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\n // 5. Call handler\n const result = await handler(enrichedCtx, request);\n\n // 6. Auto-wrap plain objects as JSON responses\n if (result instanceof Response) {\n // Merge CORS headers into existing 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 /**\n * Register a Bearer-authenticated route **and** its OPTIONS preflight\n * in a single call.\n *\n * ```ts\n * auth.http.route(http, {\n * path: \"/api/messages\",\n * method: \"POST\",\n * handler: async (ctx, request) => {\n * const { body } = await request.json();\n * await ctx.runMutation(internal.messages.sendAsUser, {\n * userId: ctx.key.userId,\n * body,\n * });\n * return { success: true };\n * },\n * });\n * ```\n *\n * @param http - The Convex HTTP router.\n * @param routeConfig.path - The URL path to match.\n * @param routeConfig.method - HTTP method (GET, POST, PUT, PATCH, DELETE).\n * @param routeConfig.handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param routeConfig.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param routeConfig.cors - CORS config; defaults to permissive (`*`).\n */\n route: (\n http: HttpRouter,\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 // Register OPTIONS preflight\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 // Register the main route with Bearer auth wrapping\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: auth.http.action(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n },\n },\n };\n\n const enrichCtx = <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n ) => ({\n ...ctx,\n auth: {\n ...ctx.auth,\n config,\n account: auth.account,\n session: auth.session,\n provider: auth.provider,\n },\n });\n\n return {\n /**\n * Helper for configuring HTTP actions.\n */\n auth,\n /**\n * Action called by the client to sign the user in.\n *\n * Also used for refreshing the session.\n */\n signIn: actionGeneric({\n args: {\n provider: v.optional(v.string()),\n params: v.optional(v.any()),\n verifier: v.optional(v.string()),\n refreshToken: v.optional(v.string()),\n calledBy: v.optional(v.string()),\n },\n handler: async (ctx, args): Promise<SignInActionResult> => {\n if (args.calledBy !== undefined) {\n logWithLevel(\n \"INFO\",\n `\\`auth/session:start\\` called by ${args.calledBy}`,\n );\n }\n const provider =\n args.provider !== undefined\n ? getProviderOrThrow(args.provider)\n : null;\n const result = await signInImpl(enrichCtx(ctx), provider, args, {\n generateTokens: true,\n allowExtraProviders: false,\n });\n return Fx.run(\n Fx.match(result, result.kind, {\n redirect: (r) =>\n Fx.succeed({\n kind: \"redirect\" as const,\n redirect: r.redirect,\n verifier: r.verifier,\n }),\n signedIn: (r) =>\n Fx.succeed({\n kind: \"signedIn\" as const,\n tokens: r.signedIn?.tokens ?? null,\n }),\n refreshTokens: (r) =>\n Fx.succeed({\n kind: \"signedIn\" as const,\n tokens: r.signedIn?.tokens ?? null,\n }),\n started: () => Fx.succeed({ kind: \"started\" as const }),\n passkeyOptions: (r) =>\n Fx.succeed({\n kind: \"passkeyOptions\" as const,\n options: r.options,\n verifier: r.verifier,\n }),\n totpRequired: (r) =>\n Fx.succeed({\n kind: \"totpRequired\" as const,\n verifier: r.verifier,\n }),\n totpSetup: (r) =>\n Fx.succeed({\n kind: \"totpSetup\" as const,\n totpSetup: {\n uri: r.uri,\n secret: r.secret,\n totpId: r.totpId,\n },\n verifier: r.verifier,\n }),\n deviceCode: (r) =>\n Fx.succeed({\n kind: \"deviceCode\" as const,\n deviceCode: {\n deviceCode: r.deviceCode,\n userCode: r.userCode,\n verificationUri: r.verificationUri,\n verificationUriComplete: r.verificationUriComplete,\n expiresIn: r.expiresIn,\n interval: r.interval,\n },\n }),\n }),\n );\n },\n }),\n /**\n * Action called by the client to invalidate the current session.\n */\n signOut: actionGeneric({\n args: {},\n handler: async (ctx) => {\n await callSignOut(ctx);\n },\n }),\n\n /**\n * Internal mutation used by the library to read and write\n * to the database during signin and signout.\n */\n store: internalMutationGeneric({\n args: storeArgs,\n handler: async (ctx: MutationCtx, args) => {\n return storeImpl(ctx, args, getProviderOrThrow, config);\n },\n }),\n };\n}\n\nfunction 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}\nfunction getCookies(request: Request): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n"],"mappings":"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"}