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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/dist/authorization/index.d.ts +1 -1
  2. package/dist/authorization/index.js +1 -1
  3. package/dist/authorization/index.js.map +1 -1
  4. package/dist/client/index.d.ts +1 -2
  5. package/dist/client/index.d.ts.map +1 -1
  6. package/dist/client/index.js +36 -39
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/component/client/index.d.ts +1 -2
  9. package/dist/component/model.d.ts +9 -9
  10. package/dist/component/model.d.ts.map +1 -1
  11. package/dist/component/public/enterprise/audit.d.ts.map +1 -1
  12. package/dist/component/public/enterprise/audit.js.map +1 -1
  13. package/dist/component/public/enterprise/core.d.ts.map +1 -1
  14. package/dist/component/public/enterprise/core.js.map +1 -1
  15. package/dist/component/public/enterprise/domains.d.ts.map +1 -1
  16. package/dist/component/public/enterprise/domains.js.map +1 -1
  17. package/dist/component/public/enterprise/scim.d.ts.map +1 -1
  18. package/dist/component/public/enterprise/scim.js.map +1 -1
  19. package/dist/component/public/enterprise/secrets.d.ts.map +1 -1
  20. package/dist/component/public/enterprise/secrets.js.map +1 -1
  21. package/dist/component/public/enterprise/webhooks.d.ts.map +1 -1
  22. package/dist/component/public/enterprise/webhooks.js.map +1 -1
  23. package/dist/component/public/factors/devices.d.ts.map +1 -1
  24. package/dist/component/public/factors/devices.js.map +1 -1
  25. package/dist/component/public/factors/passkeys.d.ts.map +1 -1
  26. package/dist/component/public/factors/passkeys.js.map +1 -1
  27. package/dist/component/public/factors/totp.d.ts.map +1 -1
  28. package/dist/component/public/factors/totp.js.map +1 -1
  29. package/dist/component/public/groups/core.js.map +1 -1
  30. package/dist/component/public/groups/invites.d.ts.map +1 -1
  31. package/dist/component/public/groups/invites.js.map +1 -1
  32. package/dist/component/public/groups/members.d.ts.map +1 -1
  33. package/dist/component/public/groups/members.js.map +1 -1
  34. package/dist/component/public/identity/accounts.d.ts.map +1 -1
  35. package/dist/component/public/identity/accounts.js.map +1 -1
  36. package/dist/component/public/identity/codes.d.ts.map +1 -1
  37. package/dist/component/public/identity/codes.js.map +1 -1
  38. package/dist/component/public/identity/sessions.d.ts.map +1 -1
  39. package/dist/component/public/identity/sessions.js.map +1 -1
  40. package/dist/component/public/identity/tokens.d.ts.map +1 -1
  41. package/dist/component/public/identity/tokens.js.map +1 -1
  42. package/dist/component/public/identity/users.d.ts.map +1 -1
  43. package/dist/component/public/identity/users.js.map +1 -1
  44. package/dist/component/public/identity/verifiers.d.ts.map +1 -1
  45. package/dist/component/public/identity/verifiers.js.map +1 -1
  46. package/dist/component/public/security/keys.d.ts.map +1 -1
  47. package/dist/component/public/security/keys.js.map +1 -1
  48. package/dist/component/public/security/limits.d.ts.map +1 -1
  49. package/dist/component/public/security/limits.js.map +1 -1
  50. package/dist/component/schema.d.ts +42 -42
  51. package/dist/component/server/auth.d.ts +37 -40
  52. package/dist/component/server/auth.d.ts.map +1 -1
  53. package/dist/component/server/auth.js +57 -23
  54. package/dist/component/server/auth.js.map +1 -1
  55. package/dist/component/server/core.js +116 -235
  56. package/dist/component/server/core.js.map +1 -1
  57. package/dist/component/server/crypto.js +25 -7
  58. package/dist/component/server/crypto.js.map +1 -1
  59. package/dist/component/server/device.js +58 -15
  60. package/dist/component/server/device.js.map +1 -1
  61. package/dist/component/server/enterprise/domain.js +148 -59
  62. package/dist/component/server/enterprise/domain.js.map +1 -1
  63. package/dist/component/server/enterprise/http.js +36 -15
  64. package/dist/component/server/enterprise/http.js.map +1 -1
  65. package/dist/component/server/enterprise/oidc.js +1 -1
  66. package/dist/component/server/http.js +26 -21
  67. package/dist/component/server/http.js.map +1 -1
  68. package/dist/component/server/identity.js +5 -2
  69. package/dist/component/server/identity.js.map +1 -1
  70. package/dist/component/server/limits.js +21 -30
  71. package/dist/component/server/limits.js.map +1 -1
  72. package/dist/component/server/mutations/account.js +12 -10
  73. package/dist/component/server/mutations/account.js.map +1 -1
  74. package/dist/component/server/mutations/code.js +5 -2
  75. package/dist/component/server/mutations/code.js.map +1 -1
  76. package/dist/component/server/mutations/invalidate.js +1 -1
  77. package/dist/component/server/mutations/invalidate.js.map +1 -1
  78. package/dist/component/server/mutations/oauth.js +10 -4
  79. package/dist/component/server/mutations/oauth.js.map +1 -1
  80. package/dist/component/server/mutations/refresh.js +2 -2
  81. package/dist/component/server/mutations/refresh.js.map +1 -1
  82. package/dist/component/server/mutations/register.js +46 -42
  83. package/dist/component/server/mutations/register.js.map +1 -1
  84. package/dist/component/server/mutations/retrieve.js +21 -25
  85. package/dist/component/server/mutations/retrieve.js.map +1 -1
  86. package/dist/component/server/mutations/signature.js +10 -4
  87. package/dist/component/server/mutations/signature.js.map +1 -1
  88. package/dist/component/server/mutations/signout.js.map +1 -1
  89. package/dist/component/server/mutations/store.js +9 -24
  90. package/dist/component/server/mutations/store.js.map +1 -1
  91. package/dist/component/server/mutations/verifier.js.map +1 -1
  92. package/dist/component/server/mutations/verify.js +1 -1
  93. package/dist/component/server/mutations/verify.js.map +1 -1
  94. package/dist/component/server/oauth.js +53 -16
  95. package/dist/component/server/oauth.js.map +1 -1
  96. package/dist/component/server/passkey.js +115 -31
  97. package/dist/component/server/passkey.js.map +1 -1
  98. package/dist/component/server/redirects.js +9 -3
  99. package/dist/component/server/redirects.js.map +1 -1
  100. package/dist/component/server/refresh.js +10 -7
  101. package/dist/component/server/refresh.js.map +1 -1
  102. package/dist/component/server/runtime.d.ts +1 -1
  103. package/dist/component/server/runtime.d.ts.map +1 -1
  104. package/dist/component/server/runtime.js +62 -20
  105. package/dist/component/server/runtime.js.map +1 -1
  106. package/dist/component/server/signin.js +34 -10
  107. package/dist/component/server/signin.js.map +1 -1
  108. package/dist/component/server/totp.js +79 -19
  109. package/dist/component/server/totp.js.map +1 -1
  110. package/dist/component/server/types.d.ts +12 -20
  111. package/dist/component/server/types.d.ts.map +1 -1
  112. package/dist/component/server/types.js.map +1 -1
  113. package/dist/component/server/users.js +6 -3
  114. package/dist/component/server/users.js.map +1 -1
  115. package/dist/component/server/utils.js +10 -4
  116. package/dist/component/server/utils.js.map +1 -1
  117. package/dist/core/types.d.ts +14 -22
  118. package/dist/core/types.d.ts.map +1 -1
  119. package/dist/factors/device.js +8 -9
  120. package/dist/factors/device.js.map +1 -1
  121. package/dist/factors/passkey.js +18 -21
  122. package/dist/factors/passkey.js.map +1 -1
  123. package/dist/providers/password.js +66 -81
  124. package/dist/providers/password.js.map +1 -1
  125. package/dist/runtime/invite.js +2 -8
  126. package/dist/runtime/invite.js.map +1 -1
  127. package/dist/server/auth.d.ts +37 -40
  128. package/dist/server/auth.d.ts.map +1 -1
  129. package/dist/server/auth.js +57 -23
  130. package/dist/server/auth.js.map +1 -1
  131. package/dist/server/core.d.ts +71 -159
  132. package/dist/server/core.d.ts.map +1 -1
  133. package/dist/server/core.js +116 -235
  134. package/dist/server/core.js.map +1 -1
  135. package/dist/server/crypto.d.ts.map +1 -1
  136. package/dist/server/crypto.js +25 -7
  137. package/dist/server/crypto.js.map +1 -1
  138. package/dist/server/device.js +58 -15
  139. package/dist/server/device.js.map +1 -1
  140. package/dist/server/enterprise/domain.d.ts +0 -8
  141. package/dist/server/enterprise/domain.d.ts.map +1 -1
  142. package/dist/server/enterprise/domain.js +148 -59
  143. package/dist/server/enterprise/domain.js.map +1 -1
  144. package/dist/server/enterprise/http.d.ts.map +1 -1
  145. package/dist/server/enterprise/http.js +35 -14
  146. package/dist/server/enterprise/http.js.map +1 -1
  147. package/dist/server/http.d.ts +2 -2
  148. package/dist/server/http.d.ts.map +1 -1
  149. package/dist/server/http.js +25 -20
  150. package/dist/server/http.js.map +1 -1
  151. package/dist/server/identity.js +5 -2
  152. package/dist/server/identity.js.map +1 -1
  153. package/dist/server/index.d.ts +2 -2
  154. package/dist/server/limits.js +21 -30
  155. package/dist/server/limits.js.map +1 -1
  156. package/dist/server/mounts.d.ts +24 -62
  157. package/dist/server/mounts.d.ts.map +1 -1
  158. package/dist/server/mounts.js +45 -106
  159. package/dist/server/mounts.js.map +1 -1
  160. package/dist/server/mutations/account.d.ts +8 -9
  161. package/dist/server/mutations/account.d.ts.map +1 -1
  162. package/dist/server/mutations/account.js +11 -9
  163. package/dist/server/mutations/account.js.map +1 -1
  164. package/dist/server/mutations/code.d.ts +12 -12
  165. package/dist/server/mutations/code.d.ts.map +1 -1
  166. package/dist/server/mutations/code.js +5 -2
  167. package/dist/server/mutations/code.js.map +1 -1
  168. package/dist/server/mutations/invalidate.d.ts +4 -4
  169. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  170. package/dist/server/mutations/invalidate.js.map +1 -1
  171. package/dist/server/mutations/oauth.d.ts +14 -12
  172. package/dist/server/mutations/oauth.d.ts.map +1 -1
  173. package/dist/server/mutations/oauth.js +9 -3
  174. package/dist/server/mutations/oauth.js.map +1 -1
  175. package/dist/server/mutations/refresh.d.ts +3 -3
  176. package/dist/server/mutations/refresh.d.ts.map +1 -1
  177. package/dist/server/mutations/refresh.js +1 -1
  178. package/dist/server/mutations/refresh.js.map +1 -1
  179. package/dist/server/mutations/register.d.ts +11 -11
  180. package/dist/server/mutations/register.d.ts.map +1 -1
  181. package/dist/server/mutations/register.js +45 -41
  182. package/dist/server/mutations/register.js.map +1 -1
  183. package/dist/server/mutations/retrieve.d.ts +6 -6
  184. package/dist/server/mutations/retrieve.d.ts.map +1 -1
  185. package/dist/server/mutations/retrieve.js +20 -24
  186. package/dist/server/mutations/retrieve.js.map +1 -1
  187. package/dist/server/mutations/signature.d.ts +6 -7
  188. package/dist/server/mutations/signature.d.ts.map +1 -1
  189. package/dist/server/mutations/signature.js +9 -3
  190. package/dist/server/mutations/signature.js.map +1 -1
  191. package/dist/server/mutations/signin.d.ts +5 -5
  192. package/dist/server/mutations/signin.d.ts.map +1 -1
  193. package/dist/server/mutations/signout.js.map +1 -1
  194. package/dist/server/mutations/store.d.ts +83 -83
  195. package/dist/server/mutations/store.js +8 -23
  196. package/dist/server/mutations/store.js.map +1 -1
  197. package/dist/server/mutations/verifier.js.map +1 -1
  198. package/dist/server/mutations/verify.d.ts +7 -7
  199. package/dist/server/mutations/verify.d.ts.map +1 -1
  200. package/dist/server/mutations/verify.js.map +1 -1
  201. package/dist/server/oauth.js +53 -16
  202. package/dist/server/oauth.js.map +1 -1
  203. package/dist/server/passkey.d.ts +2 -2
  204. package/dist/server/passkey.d.ts.map +1 -1
  205. package/dist/server/passkey.js +114 -30
  206. package/dist/server/passkey.js.map +1 -1
  207. package/dist/server/redirects.js +9 -3
  208. package/dist/server/redirects.js.map +1 -1
  209. package/dist/server/refresh.js +10 -7
  210. package/dist/server/refresh.js.map +1 -1
  211. package/dist/server/runtime.d.ts +7 -7
  212. package/dist/server/runtime.d.ts.map +1 -1
  213. package/dist/server/runtime.js +61 -19
  214. package/dist/server/runtime.js.map +1 -1
  215. package/dist/server/signin.js +34 -10
  216. package/dist/server/signin.js.map +1 -1
  217. package/dist/server/ssr.d.ts.map +1 -1
  218. package/dist/server/ssr.js +175 -184
  219. package/dist/server/ssr.js.map +1 -1
  220. package/dist/server/totp.js +78 -18
  221. package/dist/server/totp.js.map +1 -1
  222. package/dist/server/types.d.ts +13 -21
  223. package/dist/server/types.d.ts.map +1 -1
  224. package/dist/server/types.js.map +1 -1
  225. package/dist/server/users.js +6 -3
  226. package/dist/server/users.js.map +1 -1
  227. package/dist/server/utils.js +10 -4
  228. package/dist/server/utils.js.map +1 -1
  229. package/package.json +1 -5
  230. package/src/authorization/index.ts +1 -1
  231. package/src/client/core/types.ts +14 -14
  232. package/src/client/factors/device.ts +10 -12
  233. package/src/client/factors/passkey.ts +23 -26
  234. package/src/client/index.ts +54 -64
  235. package/src/client/runtime/invite.ts +5 -7
  236. package/src/component/index.ts +1 -1
  237. package/src/component/public/enterprise/audit.ts +6 -1
  238. package/src/component/public/enterprise/core.ts +1 -0
  239. package/src/component/public/enterprise/domains.ts +5 -1
  240. package/src/component/public/enterprise/scim.ts +1 -0
  241. package/src/component/public/enterprise/secrets.ts +1 -0
  242. package/src/component/public/enterprise/webhooks.ts +1 -0
  243. package/src/component/public/factors/devices.ts +1 -0
  244. package/src/component/public/factors/passkeys.ts +1 -0
  245. package/src/component/public/factors/totp.ts +1 -0
  246. package/src/component/public/groups/core.ts +1 -1
  247. package/src/component/public/groups/invites.ts +7 -1
  248. package/src/component/public/groups/members.ts +1 -0
  249. package/src/component/public/identity/accounts.ts +1 -0
  250. package/src/component/public/identity/codes.ts +1 -0
  251. package/src/component/public/identity/sessions.ts +1 -0
  252. package/src/component/public/identity/tokens.ts +1 -0
  253. package/src/component/public/identity/users.ts +1 -0
  254. package/src/component/public/identity/verifiers.ts +1 -0
  255. package/src/component/public/security/keys.ts +1 -0
  256. package/src/component/public/security/limits.ts +1 -0
  257. package/src/providers/password.ts +89 -110
  258. package/src/server/auth.ts +92 -70
  259. package/src/server/core.ts +197 -233
  260. package/src/server/crypto.ts +31 -29
  261. package/src/server/device.ts +65 -32
  262. package/src/server/enterprise/domain.ts +158 -170
  263. package/src/server/enterprise/http.ts +46 -39
  264. package/src/server/http.ts +36 -30
  265. package/src/server/identity.ts +5 -5
  266. package/src/server/index.ts +1 -1
  267. package/src/server/limits.ts +53 -80
  268. package/src/server/mounts.ts +47 -74
  269. package/src/server/mutations/account.ts +22 -36
  270. package/src/server/mutations/code.ts +6 -6
  271. package/src/server/mutations/invalidate.ts +1 -1
  272. package/src/server/mutations/oauth.ts +14 -8
  273. package/src/server/mutations/refresh.ts +5 -4
  274. package/src/server/mutations/register.ts +87 -132
  275. package/src/server/mutations/retrieve.ts +44 -44
  276. package/src/server/mutations/signature.ts +13 -6
  277. package/src/server/mutations/signout.ts +1 -1
  278. package/src/server/mutations/store.ts +16 -31
  279. package/src/server/mutations/verifier.ts +1 -1
  280. package/src/server/mutations/verify.ts +3 -5
  281. package/src/server/oauth.ts +60 -69
  282. package/src/server/passkey.ts +567 -517
  283. package/src/server/redirects.ts +10 -6
  284. package/src/server/refresh.ts +14 -18
  285. package/src/server/runtime.ts +70 -55
  286. package/src/server/signin.ts +44 -37
  287. package/src/server/ssr.ts +390 -407
  288. package/src/server/totp.ts +85 -35
  289. package/src/server/types.ts +19 -22
  290. package/src/server/users.ts +7 -6
  291. package/src/server/utils.ts +10 -12
  292. package/dist/component/server/authError.js +0 -34
  293. package/dist/component/server/authError.js.map +0 -1
  294. package/dist/component/server/errors.d.ts +0 -1
  295. package/dist/component/server/errors.js +0 -137
  296. package/dist/component/server/errors.js.map +0 -1
  297. package/dist/server/authError.d.ts +0 -46
  298. package/dist/server/authError.d.ts.map +0 -1
  299. package/dist/server/authError.js +0 -34
  300. package/dist/server/authError.js.map +0 -1
  301. package/dist/server/errors.d.ts +0 -177
  302. package/dist/server/errors.d.ts.map +0 -1
  303. package/dist/server/errors.js +0 -212
  304. package/dist/server/errors.js.map +0 -1
  305. package/src/server/authError.ts +0 -44
  306. package/src/server/errors.ts +0 -290
@@ -13,7 +13,7 @@ import { GenericId } from "convex/values";
13
13
  type AuthConfig = Omit<ConvexAuthConfig, "component">;
14
14
  /** Canonical user document type exposed by Convex Auth. */
15
15
  type UserDoc = Doc<"User">;
16
- type MemberApiWithAuthorization<TAuthorization extends AuthAuthorizationConfig | undefined> = Omit<ReturnType<typeof Auth$1>["auth"]["member"], "create" | "list" | "update" | "resolve"> & {
16
+ type MemberApiWithAuthorization<TAuthorization extends AuthAuthorizationConfig | undefined> = Omit<ReturnType<typeof Auth$1>["auth"]["member"], "create" | "list" | "update" | "inspect" | "require"> & {
17
17
  create: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["create"]>[0], data: {
18
18
  groupId: string;
19
19
  userId: string;
@@ -21,7 +21,6 @@ type MemberApiWithAuthorization<TAuthorization extends AuthAuthorizationConfig |
21
21
  status?: string;
22
22
  extend?: Record<string, unknown>;
23
23
  }) => Promise<{
24
- ok: true;
25
24
  memberId: string;
26
25
  }>;
27
26
  list: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["list"]>[0], opts?: {
@@ -39,17 +38,22 @@ type MemberApiWithAuthorization<TAuthorization extends AuthAuthorizationConfig |
39
38
  update: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["update"]>[0], memberId: string, data: Record<string, unknown> & {
40
39
  roleIds?: AuthRoleId<TAuthorization>[];
41
40
  }) => Promise<{
42
- ok: true;
43
41
  memberId: string;
44
42
  }>;
45
- resolve: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["resolve"]>[0], opts: {
43
+ inspect: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["inspect"]>[0], opts: {
44
+ userId: string;
45
+ groupId: string;
46
+ ancestry?: boolean;
47
+ maxDepth?: number;
48
+ }) => ReturnType<ReturnType<typeof Auth$1>["auth"]["member"]["inspect"]>;
49
+ require: (ctx: Parameters<ReturnType<typeof Auth$1>["auth"]["member"]["require"]>[0], opts: {
46
50
  userId: string;
47
51
  groupId: string;
48
52
  ancestry?: boolean;
49
53
  roleIds?: AuthRoleId<TAuthorization>[];
50
54
  grants?: AuthGrant<TAuthorization>[];
51
55
  maxDepth?: number;
52
- }) => ReturnType<ReturnType<typeof Auth$1>["auth"]["member"]["resolve"]>;
56
+ }) => ReturnType<ReturnType<typeof Auth$1>["auth"]["member"]["require"]>;
53
57
  };
54
58
  /**
55
59
  * The base auth API surface returned by {@link createAuth}.
@@ -80,30 +84,29 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
80
84
  key: ReturnType<typeof Auth$1>["auth"]["key"];
81
85
  http: ReturnType<typeof Auth$1>["auth"]["http"];
82
86
  /**
83
- * Resolve the current user's auth context. Framework-agnostic — use
87
+ * Resolve the current request's auth context. Framework-agnostic — use
84
88
  * this in fluent-convex middleware, custom wrappers, or anywhere you
85
- * need the resolved `{ userId, user, groupId, role, grants }` object.
89
+ * need the current `{ userId, user, groupId, role, grants }` object.
86
90
  *
87
- * Returns `null` when unauthenticated. Does not throw.
91
+ * Throws a structured `ConvexError` when unauthenticated.
88
92
  *
89
93
  * @param ctx - Convex query, mutation, or action context.
90
- * @returns The resolved auth context, or `null`.
94
+ * @returns The current auth context.
91
95
  *
92
96
  * @example fluent-convex middleware
93
97
  * ```ts
94
98
  * const withAuth = convex.createMiddleware(async (ctx, next) => {
95
- * return next({ ...ctx, auth: await auth.resolve(ctx) });
99
+ * return next({ ...ctx, auth: await auth.context(ctx) });
96
100
  * });
97
101
  * ```
98
102
  *
99
103
  * @example Direct usage in a handler
100
104
  * ```ts
101
- * const resolved = await auth.resolve(ctx);
102
- * if (!resolved) return { ok: false, code: "NOT_SIGNED_IN" };
103
- * const { userId, grants } = resolved;
105
+ * const authContext = await auth.context(ctx);
106
+ * const { userId, grants } = authContext;
104
107
  * ```
105
108
  */
106
- resolve: (ctx: any) => Promise<AuthResolvedContext | null>;
109
+ context: (ctx: any) => Promise<AuthContext>;
107
110
  /**
108
111
  * Context enrichment for convex-helpers `customQuery` / `customMutation` /
109
112
  * `customAction`.
@@ -112,9 +115,9 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
112
115
  * and grants, then attaches them to `ctx.auth`. Returns a `Customization`
113
116
  * object compatible with convex-helpers' custom function builders.
114
117
  *
115
- * `ctx.auth` is `{ userId, user, groupId, role, grants }` when
116
- * authenticated, `null` when unauthenticated. No throwing your
117
- * handler decides how to respond.
118
+ * `ctx.auth` is the current request auth context.
119
+ * By default this throws when unauthenticated so handlers can assume
120
+ * `ctx.auth.userId` and `ctx.auth.user` exist.
118
121
  *
119
122
  * @returns A convex-helpers `Customization` object.
120
123
  *
@@ -136,7 +139,6 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
136
139
  * export const list = authQuery({
137
140
  * args: { workspaceId: v.string() },
138
141
  * handler: async (ctx, args) => {
139
- * if (!ctx.auth) return [];
140
142
  * const { userId, groupId, grants } = ctx.auth;
141
143
  * // business logic
142
144
  * },
@@ -147,26 +149,27 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
147
149
  args: Record<string, never>;
148
150
  input: (ctx: any) => Promise<{
149
151
  ctx: {
150
- auth: AuthResolvedContext | null;
152
+ auth: AuthContext;
151
153
  };
152
154
  args: Record<string, never>;
153
155
  }>;
154
156
  };
155
157
  };
156
158
  /**
157
- * Resolved auth context injected into `ctx.auth` by `auth.ctx()` and
158
- * {@link AuthCtx}. Also the expected return shape for custom
159
- * {@link AuthCtxConfig.authResolve | authResolve} hooks.
159
+ * Current request auth context injected into `ctx.auth` by `auth.ctx()` and
160
+ * {@link AuthCtx}. This is the authenticated auth shape returned by
161
+ * {@link createAuth().context}. Optional context builders may still surface
162
+ * nullable fields when `optional: true` is used.
160
163
  *
161
- * - `null` when unauthenticated.
162
164
  * - `groupId` is `null` when the user has no active group set.
163
- * - `role` / `grants` are `null` / `[]` when no active group or no membership.
165
+ * - `role` is `null` when no active group or no membership is resolved.
166
+ * - `grants` is `[]` when no active group or no membership is resolved.
164
167
  *
165
168
  * @example
166
169
  * ```ts
167
- * import type { AuthResolvedContext } from "@robelest/convex-auth/server";
170
+ * import type { AuthContext } from "@robelest/convex-auth/server";
168
171
  *
169
- * const mockAuth: AuthResolvedContext = {
172
+ * const mockAuth: AuthContext = {
170
173
  * userId: "user123" as Id<"User">,
171
174
  * user: { _id: "user123", email: "test@example.com" },
172
175
  * groupId: "group456",
@@ -175,7 +178,7 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
175
178
  * };
176
179
  * ```
177
180
  */
178
- type AuthResolvedContext = {
181
+ type AuthContext = {
179
182
  /** The authenticated user's document ID. */userId: GenericId<"User">; /** The authenticated user's full document. */
180
183
  user: UserDoc; /** The user's active group ID, or `null` if none set. */
181
184
  groupId: string | null; /** The user's primary role in the active group, or `null`. */
@@ -185,7 +188,7 @@ type AuthResolvedContext = {
185
188
  type AuthCtxBase = {
186
189
  getUserIdentity: () => Promise<UserIdentity | null>;
187
190
  };
188
- type RequiredAuthCtxState = AuthCtxBase & AuthResolvedContext;
191
+ type RequiredAuthCtxState = AuthCtxBase & AuthContext;
189
192
  type OptionalAuthCtxState = AuthCtxBase & {
190
193
  userId: GenericId<"User"> | null;
191
194
  user: UserDoc | null;
@@ -203,7 +206,6 @@ type PublicSsoAdminApi = {
203
206
  domain: string;
204
207
  isPrimary?: boolean;
205
208
  }>) => Promise<{
206
- ok: true;
207
209
  enterpriseId: string;
208
210
  domains: Array<{
209
211
  domainId: string;
@@ -218,7 +220,6 @@ type PublicSsoAdminApi = {
218
220
  enterpriseId: string;
219
221
  domain: string;
220
222
  }) => Promise<{
221
- ok: true;
222
223
  enterpriseId: string;
223
224
  domain: string;
224
225
  requestedAt: number;
@@ -233,7 +234,6 @@ type PublicSsoAdminApi = {
233
234
  enterpriseId: string;
234
235
  domain: string;
235
236
  }) => Promise<{
236
- ok: boolean;
237
237
  enterpriseId: string;
238
238
  domain: string;
239
239
  verifiedAt?: number;
@@ -339,13 +339,13 @@ type AuthCtxConfig<TResolve extends Record<string, unknown> = Record<string, nev
339
339
  * Attach additional derived fields to the auth context after the base auth
340
340
  * context is resolved.
341
341
  */
342
- resolve?: (ctx: any, user: UserDoc, auth: AuthResolvedContext) => Promise<TResolve> | TResolve;
342
+ resolve?: (ctx: any, user: UserDoc, auth: AuthContext) => Promise<TResolve> | TResolve;
343
343
  /**
344
344
  * Override or wrap the base auth resolution used by {@link AuthCtx}.
345
345
  *
346
346
  * Return `undefined` to fall back to the built-in resolver,
347
347
  * `null` for an explicit unauthenticated state, or an
348
- * {@link AuthResolvedContext} object to provide a pre-resolved auth state.
348
+ * {@link AuthContext} object to provide a pre-resolved auth state.
349
349
  * This is useful for tests, proxy auth, impersonation flows, or any
350
350
  * environment that needs to inject auth without depending on the standard
351
351
  * Convex auth tables.
@@ -364,7 +364,7 @@ type AuthCtxConfig<TResolve extends Record<string, unknown> = Record<string, nev
364
364
  * });
365
365
  * ```
366
366
  */
367
- authResolve?: (ctx: any, fallback: () => Promise<AuthResolvedContext | null>) => Promise<AuthResolvedContext | null | undefined> | AuthResolvedContext | null | undefined;
367
+ authResolve?: (ctx: any, fallback: () => Promise<AuthContext | null>) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;
368
368
  };
369
369
  /**
370
370
  * Create a context enrichment for `customQuery` / `customMutation` — optional auth.
@@ -403,11 +403,8 @@ declare function AuthCtx<TResolve extends Record<string, unknown> = Record<strin
403
403
  /**
404
404
  * Create a context enrichment for `customQuery` / `customMutation` — required auth (default).
405
405
  *
406
- * When `optional` is omitted or `false`, the inferred type is the authenticated
407
- * auth shape. At runtime this helper still resolves instead of throwing, so if
408
- * no user is signed in the returned `ctx.auth.userId` / `ctx.auth.user` are
409
- * `null`, `ctx.auth.groupId` / `ctx.auth.role` are `null`, and
410
- * `ctx.auth.grants` is `[]`.
406
+ * When `optional` is omitted or `false`, unauthenticated requests throw a
407
+ * structured `ConvexError` before your handler runs.
411
408
  *
412
409
  * @param auth - The auth API object returned by {@link createAuth}.
413
410
  * @param config - Optional configuration with a `resolve` callback
@@ -465,5 +462,5 @@ type InferAuth<T extends {
465
462
  }>;
466
463
  }> = Awaited<ReturnType<T["input"]>>["ctx"]["auth"];
467
464
  //#endregion
468
- export { AuthApi, AuthApiBase, AuthConfig, AuthCtx, AuthCtxConfig, AuthResolvedContext, ConvexAuthResult, InferAuth, InferClientApi, UserDoc, createAuth };
465
+ export { AuthApi, AuthApiBase, AuthConfig, AuthContext, AuthCtx, AuthCtxConfig, ConvexAuthResult, InferAuth, InferClientApi, UserDoc, createAuth };
469
466
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/server/auth.ts"],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/server/auth.ts"],"mappings":"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"}
@@ -1,8 +1,13 @@
1
- import { AuthError } from "./authError.js";
2
1
  import { Auth } from "./runtime.js";
2
+ import { Cv } from "@robelest/fx/convex";
3
3
 
4
4
  //#region src/server/auth.ts
5
5
  /**
6
+ * Auth configuration helpers for Convex Auth.
7
+ *
8
+ * @module
9
+ */
10
+ /**
6
11
  * Create an auth API object.
7
12
  *
8
13
  * When `new SSO()` is included in providers, `auth.sso` and `auth.scim`
@@ -36,9 +41,9 @@ import { Auth } from "./runtime.js";
36
41
  * 1. `user.id(ctx)` → userId or null (exit early)
37
42
  * 2. `user.get(ctx, userId)` → user doc (cached per-execution)
38
43
  * 3. `user.getActiveGroup(ctx, { userId })` → groupId or null
39
- * 4. If groupId → `member.resolve(ctx, { userId, groupId })` → role + grants
44
+ * 4. If groupId → `member.inspect(ctx, { userId, groupId })` → role + grants
40
45
  */
41
- async function resolveAuthContext(auth, ctx) {
46
+ async function getAuthContext(auth, ctx) {
42
47
  const userId = await auth.user.id(ctx);
43
48
  if (!userId) return null;
44
49
  const user = await auth.user.get(ctx, userId);
@@ -46,7 +51,7 @@ async function resolveAuthContext(auth, ctx) {
46
51
  let role = null;
47
52
  let grants = [];
48
53
  if (groupId) {
49
- const resolved = await auth.member.resolve(ctx, {
54
+ const resolved = await auth.member.inspect(ctx, {
50
55
  userId,
51
56
  groupId
52
57
  });
@@ -72,20 +77,32 @@ function createAuth(component, config) {
72
77
  const { domain: domainApi, scim: scimApi, connection: connectionApi, audit: auditApi, webhook: webhookApi, oidc: oidcApi, saml: samlApi, ...restSso } = authResult.auth.sso;
73
78
  const setEnterpriseDomains = async (ctx, enterpriseId, domains) => {
74
79
  const enterprise = await connectionApi.get(ctx, enterpriseId);
75
- if (enterprise === null) throw new AuthError("INVALID_PARAMETERS", "Enterprise not found.").toConvexError();
80
+ if (enterprise === null) throw Cv.error({
81
+ code: "INVALID_PARAMETERS",
82
+ message: "Enterprise not found."
83
+ });
76
84
  const normalized = domains.map((entry) => ({
77
85
  ...entry,
78
86
  domain: entry.domain.trim().toLowerCase()
79
87
  }));
80
88
  const deduped = /* @__PURE__ */ new Map();
81
89
  for (const entry of normalized) {
82
- if (entry.domain.length === 0) throw new AuthError("INVALID_PARAMETERS", "Domain must not be empty.").toConvexError();
83
- if (deduped.has(entry.domain)) throw new AuthError("INVALID_PARAMETERS", `Duplicate domain: ${entry.domain}`).toConvexError();
90
+ if (entry.domain.length === 0) throw Cv.error({
91
+ code: "INVALID_PARAMETERS",
92
+ message: "Domain must not be empty."
93
+ });
94
+ if (deduped.has(entry.domain)) throw Cv.error({
95
+ code: "INVALID_PARAMETERS",
96
+ message: `Duplicate domain: ${entry.domain}`
97
+ });
84
98
  deduped.set(entry.domain, entry);
85
99
  }
86
100
  const nextDomains = [...deduped.values()];
87
101
  const primaryCount = nextDomains.filter((entry) => entry.isPrimary).length;
88
- if (primaryCount > 1) throw new AuthError("INVALID_PARAMETERS", "Only one primary domain may be set.").toConvexError();
102
+ if (primaryCount > 1) throw Cv.error({
103
+ code: "INVALID_PARAMETERS",
104
+ message: "Only one primary domain may be set."
105
+ });
89
106
  if (nextDomains.length > 0 && primaryCount === 0) nextDomains[0] = {
90
107
  ...nextDomains[0],
91
108
  isPrimary: true
@@ -109,7 +126,6 @@ function createAuth(component, config) {
109
126
  });
110
127
  }
111
128
  return {
112
- ok: true,
113
129
  enterpriseId,
114
130
  domains: (await domainApi.list(ctx, enterpriseId)).map((domain) => ({
115
131
  domainId: domain._id,
@@ -168,12 +184,24 @@ function createAuth(component, config) {
168
184
  validate: scimApi.validate
169
185
  } },
170
186
  http: authResult.auth.http,
171
- resolve: (ctx) => resolveAuthContext(authResult.auth, ctx),
187
+ context: async (ctx) => {
188
+ const authContext = await getAuthContext(authResult.auth, ctx);
189
+ if (authContext === null) throw Cv.error({
190
+ code: "NOT_SIGNED_IN",
191
+ message: "Authentication required."
192
+ });
193
+ return authContext;
194
+ },
172
195
  ctx: () => ({
173
196
  args: {},
174
197
  input: async (ctx) => {
198
+ const authCtx = await getAuthContext(authResult.auth, ctx);
199
+ if (authCtx === null) throw Cv.error({
200
+ code: "NOT_SIGNED_IN",
201
+ message: "Authentication required."
202
+ });
175
203
  return {
176
- ctx: { auth: await resolveAuthContext(authResult.auth, ctx) },
204
+ ctx: { auth: authCtx },
177
205
  args: {}
178
206
  };
179
207
  }
@@ -186,20 +214,26 @@ function AuthCtx(auth, config) {
186
214
  input: async (ctx, _args, _extra) => {
187
215
  const nativeAuth = ctx.auth;
188
216
  const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);
189
- const fallback = () => resolveAuthContext(auth, ctx);
217
+ const fallback = () => getAuthContext(auth, ctx);
190
218
  const authOverride = config?.authResolve ? await config.authResolve(ctx, fallback) : void 0;
191
219
  const resolved = authOverride === void 0 ? await fallback() : authOverride;
192
- if (resolved === null) return {
193
- ctx: { auth: {
194
- getUserIdentity,
195
- userId: null,
196
- user: null,
197
- groupId: null,
198
- role: null,
199
- grants: []
200
- } },
201
- args: {}
202
- };
220
+ if (resolved === null) {
221
+ if (config?.optional !== true) throw Cv.error({
222
+ code: "NOT_SIGNED_IN",
223
+ message: "Authentication required."
224
+ });
225
+ return {
226
+ ctx: { auth: {
227
+ getUserIdentity,
228
+ userId: null,
229
+ user: null,
230
+ groupId: null,
231
+ role: null,
232
+ grants: []
233
+ } },
234
+ args: {}
235
+ };
236
+ }
203
237
  const extra = config?.resolve ? await config.resolve(ctx, resolved.user, resolved) : {};
204
238
  return {
205
239
  ctx: { auth: {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","names":["AuthFactory"],"sources":["../../src/server/auth.ts"],"sourcesContent":["/**\n * Auth configuration helpers for Convex Auth.\n *\n * @module\n */\n\nimport type { UserIdentity } from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nimport type { AuthApiRefs } from \"../client/index\";\nimport { Auth as AuthFactory } from \"./runtime\";\nimport { AuthError } from \"./authError\";\nimport type { Doc } from \"./types\";\nimport type {\n AuthAuthorizationConfig,\n AuthGrant,\n AuthProviderConfig,\n AuthRoleDefinition,\n AuthRoleId,\n ConvexAuthConfig,\n HasDeviceProvider,\n HasPasskeyProvider,\n HasSSO,\n HasTotpProvider,\n} from \"./types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Config for auth setup. Extends the standard auth config\n * minus `component` (which is passed as the first constructor argument).\n */\nexport type AuthConfig = Omit<ConvexAuthConfig, \"component\">;\n\n/** Canonical user document type exposed by Convex Auth. */\nexport type UserDoc = Doc<\"User\">;\n\ntype MemberApiWithAuthorization<\n TAuthorization extends AuthAuthorizationConfig | undefined,\n> = Omit<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"],\n \"create\" | \"list\" | \"update\" | \"resolve\"\n> & {\n create: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"create\"]\n >[0],\n data: {\n groupId: string;\n userId: string;\n roleIds?: AuthRoleId<TAuthorization>[];\n status?: string;\n extend?: Record<string, unknown>;\n },\n ) => Promise<{ ok: true; memberId: string }>;\n list: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"list\"]\n >[0],\n opts?: {\n where?: {\n groupId?: string;\n userId?: string;\n roleId?: AuthRoleId<TAuthorization>;\n status?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"status\";\n order?: \"asc\" | \"desc\";\n },\n ) => ReturnType<ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"list\"]>;\n update: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"update\"]\n >[0],\n memberId: string,\n data: Record<string, unknown> & { roleIds?: AuthRoleId<TAuthorization>[] },\n ) => Promise<{ ok: true; memberId: string }>;\n resolve: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"resolve\"]\n >[0],\n opts: {\n userId: string;\n groupId: string;\n ancestry?: boolean;\n roleIds?: AuthRoleId<TAuthorization>[];\n grants?: AuthGrant<TAuthorization>[];\n maxDepth?: number;\n },\n ) => ReturnType<ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"resolve\"]>;\n};\n\n\n/**\n * The base auth API surface returned by {@link createAuth}.\n *\n * Provides core namespaces — `signIn`, `signOut`, `user`, `session`,\n * `member`, `invite`, `group`, `key`, and `http` — that are\n * always available regardless of which providers are configured.\n * Enterprise namespaces (`sso`, `scim`) are added conditionally by\n * {@link AuthApi} when an SSO provider is present.\n *\n * Use this type when you want to describe code that only depends on the\n * standard auth surface and should not assume enterprise features exist.\n *\n * @typeParam TAuthorization - The authorization config, used to narrow\n * role IDs and grant strings on the `member` API.\n */\nexport type AuthApiBase<\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> = {\n signIn: ReturnType<typeof AuthFactory>[\"signIn\"];\n signOut: ReturnType<typeof AuthFactory>[\"signOut\"];\n store: ReturnType<typeof AuthFactory>[\"store\"];\n user: ReturnType<typeof AuthFactory>[\"auth\"][\"user\"];\n session: ReturnType<typeof AuthFactory>[\"auth\"][\"session\"];\n provider: ReturnType<typeof AuthFactory>[\"auth\"][\"provider\"];\n account: ReturnType<typeof AuthFactory>[\"auth\"][\"account\"];\n group: ReturnType<typeof AuthFactory>[\"auth\"][\"group\"];\n member: MemberApiWithAuthorization<TAuthorization>;\n invite: ReturnType<typeof AuthFactory>[\"auth\"][\"invite\"];\n key: ReturnType<typeof AuthFactory>[\"auth\"][\"key\"];\n http: ReturnType<typeof AuthFactory>[\"auth\"][\"http\"];\n /**\n * Resolve the current user's auth context. Framework-agnostic — use\n * this in fluent-convex middleware, custom wrappers, or anywhere you\n * need the resolved `{ userId, user, groupId, role, grants }` object.\n *\n * Returns `null` when unauthenticated. Does not throw.\n *\n * @param ctx - Convex query, mutation, or action context.\n * @returns The resolved auth context, or `null`.\n *\n * @example fluent-convex middleware\n * ```ts\n * const withAuth = convex.createMiddleware(async (ctx, next) => {\n * return next({ ...ctx, auth: await auth.resolve(ctx) });\n * });\n * ```\n *\n * @example Direct usage in a handler\n * ```ts\n * const resolved = await auth.resolve(ctx);\n * if (!resolved) return { ok: false, code: \"NOT_SIGNED_IN\" };\n * const { userId, grants } = resolved;\n * ```\n */\n resolve: (ctx: any) => Promise<AuthResolvedContext | null>;\n /**\n * Context enrichment for convex-helpers `customQuery` / `customMutation` /\n * `customAction`.\n *\n * Resolves the current user's identity, active group, membership role,\n * and grants, then attaches them to `ctx.auth`. Returns a `Customization`\n * object compatible with convex-helpers' custom function builders.\n *\n * `ctx.auth` is `{ userId, user, groupId, role, grants }` when\n * authenticated, `null` when unauthenticated. No throwing — your\n * handler decides how to respond.\n *\n * @returns A convex-helpers `Customization` object.\n *\n * @example One-time setup in `convex/functions.ts`\n * ```ts\n * import { query, mutation, action } from \"./_generated/server\";\n * import { customQuery, customMutation, customAction } from \"convex-helpers/server/customFunctions\";\n * import { auth } from \"./auth\";\n *\n * export const authQuery = customQuery(query, auth.ctx());\n * export const authMutation = customMutation(mutation, auth.ctx());\n * export const authAction = customAction(action, auth.ctx());\n * ```\n *\n * @example Per-function usage\n * ```ts\n * import { authQuery } from \"./functions\";\n *\n * export const list = authQuery({\n * args: { workspaceId: v.string() },\n * handler: async (ctx, args) => {\n * if (!ctx.auth) return [];\n * const { userId, groupId, grants } = ctx.auth;\n * // business logic\n * },\n * });\n * ```\n */\n ctx: () => {\n args: Record<string, never>;\n input: (ctx: any) => Promise<{\n ctx: { auth: AuthResolvedContext | null };\n args: Record<string, never>;\n }>;\n };\n};\n\n/**\n * Resolved auth context injected into `ctx.auth` by `auth.ctx()` and\n * {@link AuthCtx}. Also the expected return shape for custom\n * {@link AuthCtxConfig.authResolve | authResolve} hooks.\n *\n * - `null` when unauthenticated.\n * - `groupId` is `null` when the user has no active group set.\n * - `role` / `grants` are `null` / `[]` when no active group or no membership.\n *\n * @example\n * ```ts\n * import type { AuthResolvedContext } from \"@robelest/convex-auth/server\";\n *\n * const mockAuth: AuthResolvedContext = {\n * userId: \"user123\" as Id<\"User\">,\n * user: { _id: \"user123\", email: \"test@example.com\" },\n * groupId: \"group456\",\n * role: \"admin\",\n * grants: [\"read\", \"write\"],\n * };\n * ```\n */\nexport type AuthResolvedContext = {\n /** The authenticated user's document ID. */\n userId: GenericId<\"User\">;\n /** The authenticated user's full document. */\n user: UserDoc;\n /** The user's active group ID, or `null` if none set. */\n groupId: string | null;\n /** The user's primary role in the active group, or `null`. */\n role: string | null;\n /** Resolved grant strings from the user's role definitions. */\n grants: string[];\n};\n\ntype AuthCtxBase = {\n getUserIdentity: () => Promise<UserIdentity | null>;\n};\n\ntype RequiredAuthCtxState = AuthCtxBase & AuthResolvedContext;\n\ntype OptionalAuthCtxState = AuthCtxBase & {\n userId: GenericId<\"User\"> | null;\n user: UserDoc | null;\n groupId: string | null;\n role: string | null;\n grants: string[];\n};\n\ntype InternalSsoApi = ReturnType<typeof AuthFactory>[\"auth\"][\"sso\"];\n\ntype PublicSsoAdminApi = {\n connection: InternalSsoApi[\"connection\"] & {\n domain: {\n list: InternalSsoApi[\"domain\"][\"list\"];\n validate: InternalSsoApi[\"domain\"][\"validate\"];\n set: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n enterpriseId: string,\n domains: Array<{\n domain: string;\n isPrimary?: boolean;\n }>,\n ) => Promise<{\n ok: true;\n enterpriseId: string;\n domains: Array<{\n domainId: string;\n domain: string;\n isPrimary: boolean;\n verified: boolean;\n verifiedAt: number | null;\n }>;\n }>;\n verification: {\n request: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n args: { enterpriseId: string; domain: string },\n ) => Promise<{\n ok: true;\n enterpriseId: string;\n domain: string;\n requestedAt: number;\n expiresAt: number;\n challenge: {\n recordType: \"TXT\";\n recordName: string;\n recordValue: string;\n };\n }>;\n confirm: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n args: { enterpriseId: string; domain: string },\n ) => Promise<{\n ok: boolean;\n enterpriseId: string;\n domain: string;\n verifiedAt?: number;\n checks: Array<{ name: string; ok: boolean; message?: string }>;\n }>;\n };\n };\n };\n oidc: Omit<InternalSsoApi[\"oidc\"], \"signIn\">;\n saml: Omit<InternalSsoApi[\"saml\"], \"metadata\">;\n policy: InternalSsoApi[\"policy\"];\n audit: {\n list: InternalSsoApi[\"audit\"][\"list\"];\n };\n webhook: {\n endpoint: InternalSsoApi[\"webhook\"][\"endpoint\"];\n delivery: {\n list: InternalSsoApi[\"webhook\"][\"delivery\"][\"list\"];\n };\n };\n};\n\ntype PublicSsoClientApi = {\n signIn: InternalSsoApi[\"oidc\"][\"signIn\"];\n metadata: InternalSsoApi[\"saml\"][\"metadata\"];\n};\n\ntype PublicSsoApi = {\n admin: PublicSsoAdminApi;\n client: PublicSsoClientApi;\n};\n\ntype PublicScimApi = {\n admin: Omit<InternalSsoApi[\"scim\"], \"getConfigByToken\" | \"identity\">;\n};\n\n/**\n * Extended auth API that includes enterprise SSO and SCIM namespaces.\n *\n * This type is the union of {@link AuthApiBase} plus `sso` (SSO connection\n * management, OIDC/SAML, domain verification, policies, audit, webhooks)\n * and `scim` (SCIM provisioning configuration). It is returned by\n * {@link createAuth} only when `new SSO()` is included in the providers\n * array; otherwise the narrower {@link AuthApiBase} is returned instead.\n * Attempting to access `auth.sso` or `auth.scim` without an SSO provider\n * produces a compile-time error because the return type narrows back to\n * {@link AuthApiBase}.\n *\n * @typeParam TAuthorization - The authorization config, forwarded to\n * {@link AuthApiBase} for typed role IDs and grant strings.\n */\nexport type AuthApi<\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> = AuthApiBase<TAuthorization> & {\n sso: PublicSsoApi;\n scim: PublicScimApi;\n};\n\n/**\n * The return type of {@link createAuth}.\n *\n * Resolves to {@link AuthApi} (with `sso` and `scim` namespaces) when\n * `new SSO()` is present in the providers array, or to the narrower\n * {@link AuthApiBase} otherwise. This conditional type ensures that\n * enterprise-only APIs are only accessible when the SSO provider is\n * configured, producing a compile-time error if you try to access\n * `auth.sso` without it.\n * This lets application code keep a single `createAuth()` call while still\n * getting provider-aware typing on the resulting API object.\n *\n * @typeParam P - The tuple of provider configs passed to `createAuth`.\n * @typeParam TAuthorization - Optional authorization config for typed roles/grants.\n */\nexport type ConvexAuthResult<\n P extends AuthProviderConfig[],\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> =\n HasSSO<P> extends true\n ? AuthApi<TAuthorization>\n : AuthApiBase<TAuthorization>;\n\n/**\n * Infer the typed `AuthApiRefs` for the client SDK from a `createAuth` call.\n *\n * Use this as the generic parameter for `client()` on the frontend:\n *\n * ```ts\n * // convex/auth.ts\n * export const auth = createAuth(components.auth, { providers: [...] });\n *\n * // Frontend\n * import type { auth } from \"../convex/auth\";\n * import type { InferClientApi } from \"@robelest/convex-auth/server\";\n * const c = client<InferClientApi<typeof auth>>({ convex, api: api.auth });\n * ```\n *\n * @typeParam T - A ConvexAuthResult to extract the client API from.\n */\nexport type InferClientApi<T> =\n T extends ConvexAuthResult<infer P>\n ? AuthApiRefs<\n HasPasskeyProvider<P>,\n HasTotpProvider<P>,\n HasDeviceProvider<P>\n >\n : AuthApiRefs;\n\n/** @internal */\nexport type AuthLike = Pick<AuthApiBase, \"user\" | \"member\">;\n\n// ============================================================================\n// Auth setup APIs\n// ============================================================================\n\n/**\n * Create an auth API object.\n *\n * When `new SSO()` is included in providers, `auth.sso` and `auth.scim`\n * are available on the returned object. Without it, those namespaces are\n * absent and accessing them is a TypeScript compile error.\n *\n * @param component - The installed auth component reference from\n * `components.auth` in your Convex app definition.\n * @param config - Auth configuration including `providers` and optional\n * `authorization`. All fields from {@link AuthConfig} are accepted\n * except `component` (passed as the first argument).\n * @returns A {@link ConvexAuthResult} object — either {@link AuthApi}\n * (with `sso`/`scim`) or {@link AuthApiBase}, depending on whether\n * an SSO provider is present.\n *\n * @example\n * ```ts\n * export const auth = createAuth(components.auth, {\n * providers: [password(), google()],\n * authorization: { roles },\n * });\n * ```\n *\n * @see {@link AuthCtx}\n */\n\n// ---------------------------------------------------------------------------\n// Function builders — shared auth resolution logic\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve auth context for the current user. Returns the enriched\n * `ctx.auth` object or `null` when unauthenticated.\n *\n * Resolution flow:\n * 1. `user.id(ctx)` → userId or null (exit early)\n * 2. `user.get(ctx, userId)` → user doc (cached per-execution)\n * 3. `user.getActiveGroup(ctx, { userId })` → groupId or null\n * 4. If groupId → `member.resolve(ctx, { userId, groupId })` → role + grants\n */\nasync function resolveAuthContext(auth: AuthLike, ctx: any) {\n const userId = await auth.user.id(ctx);\n if (!userId) return null;\n const user = await auth.user.get(ctx, userId);\n const groupId = await auth.user.getActiveGroup(ctx, { userId });\n let role: string | null = null;\n let grants: string[] = [];\n if (groupId) {\n const resolved = await auth.member.resolve(ctx, { userId, groupId });\n if (resolved.membership) {\n role = resolved.roleIds[0] ?? null;\n grants = resolved.grants;\n }\n }\n return { userId, user, groupId, role, grants };\n}\n\nexport function createAuth<\n P extends AuthProviderConfig[],\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n>(\n component: ConvexAuthConfig[\"component\"],\n config: Omit<AuthConfig, \"providers\" | \"authorization\"> & {\n providers: P;\n authorization?: TAuthorization;\n },\n): ConvexAuthResult<P, TAuthorization> {\n const authResult = AuthFactory({\n ...config,\n component,\n providers: [...config.providers],\n });\n const {\n domain: domainApi,\n scim: scimApi,\n connection: connectionApi,\n audit: auditApi,\n webhook: webhookApi,\n oidc: oidcApi,\n saml: samlApi,\n ...restSso\n } = authResult.auth.sso as InternalSsoApi;\n\n type SetEnterpriseDomains = PublicSsoAdminApi[\"connection\"][\"domain\"][\"set\"];\n type EnterpriseDomainInput = Array<{\n domain: string;\n isPrimary?: boolean;\n }>;\n const setEnterpriseDomains: PublicSsoAdminApi[\"connection\"][\"domain\"][\"set\"] =\n async (\n ctx: Parameters<SetEnterpriseDomains>[0],\n enterpriseId: Parameters<SetEnterpriseDomains>[1],\n domains: EnterpriseDomainInput,\n ) => {\n const enterprise = await connectionApi.get(ctx, enterpriseId);\n if (enterprise === null) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Enterprise not found.\",\n ).toConvexError();\n }\n\n const normalized = domains.map((entry: (typeof domains)[number]) => ({\n ...entry,\n domain: entry.domain.trim().toLowerCase(),\n }));\n const deduped = new Map<string, (typeof normalized)[number]>();\n for (const entry of normalized) {\n if (entry.domain.length === 0) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Domain must not be empty.\",\n ).toConvexError();\n }\n if (deduped.has(entry.domain)) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n `Duplicate domain: ${entry.domain}`,\n ).toConvexError();\n }\n deduped.set(entry.domain, entry);\n }\n\n const nextDomains = [...deduped.values()];\n const primaryCount = nextDomains.filter(\n (entry) => entry.isPrimary,\n ).length;\n if (primaryCount > 1) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Only one primary domain may be set.\",\n ).toConvexError();\n }\n if (nextDomains.length > 0 && primaryCount === 0) {\n nextDomains[0] = { ...nextDomains[0], isPrimary: true };\n }\n\n const currentDomains = await domainApi.list(ctx, enterpriseId);\n const currentByDomain = new Map<string, (typeof currentDomains)[number]>(\n currentDomains.map((entry: (typeof currentDomains)[number]) => [\n entry.domain.toLowerCase(),\n entry,\n ]),\n );\n\n for (const existing of currentDomains) {\n if (!deduped.has(existing.domain.toLowerCase())) {\n await domainApi.remove(ctx, existing._id);\n }\n }\n\n for (const nextDomain of nextDomains) {\n const current = currentByDomain.get(nextDomain.domain);\n if (current && current.isPrimary === Boolean(nextDomain.isPrimary)) {\n continue;\n }\n if (current) {\n await domainApi.remove(ctx, current._id);\n }\n const domainId = await domainApi.add(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n domain: nextDomain.domain,\n isPrimary: nextDomain.isPrimary,\n });\n if (current?.verifiedAt !== undefined) {\n await (ctx as any).runMutation(\n component.public.enterpriseDomainVerify,\n {\n domainId,\n verifiedAt: current.verifiedAt,\n },\n );\n }\n }\n\n const updatedDomains = await domainApi.list(ctx, enterpriseId);\n return {\n ok: true as const,\n enterpriseId,\n domains: updatedDomains.map(\n (domain: (typeof updatedDomains)[number]) => ({\n domainId: domain._id,\n domain: domain.domain,\n isPrimary: domain.isPrimary,\n verified: domain.verifiedAt !== undefined,\n verifiedAt: domain.verifiedAt ?? null,\n }),\n ),\n };\n };\n\n const publicSso: PublicSsoApi = {\n admin: {\n ...restSso,\n oidc: {\n ...oidcApi,\n },\n saml: {\n ...samlApi,\n },\n connection: {\n ...connectionApi,\n domain: {\n list: domainApi.list,\n validate: domainApi.validate,\n set: setEnterpriseDomains,\n verification: {\n request: domainApi.verification.request,\n confirm: domainApi.verification.confirm,\n },\n },\n },\n policy: restSso.policy,\n audit: {\n list: auditApi.list,\n },\n webhook: {\n endpoint: webhookApi.endpoint,\n delivery: {\n list: webhookApi.delivery.list,\n },\n },\n },\n client: {\n signIn: oidcApi.signIn,\n metadata: samlApi.metadata,\n },\n };\n\n return {\n signIn: authResult.signIn,\n signOut: authResult.signOut,\n store: authResult.store,\n user: authResult.auth.user,\n session: authResult.auth.session,\n provider: authResult.auth.provider,\n account: authResult.auth.account,\n group: authResult.auth.group,\n member: authResult.auth.member,\n invite: authResult.auth.invite,\n key: authResult.auth.key,\n sso: publicSso,\n scim: {\n admin: {\n configure: scimApi.configure,\n get: scimApi.get,\n validate: scimApi.validate,\n },\n },\n http: authResult.auth.http,\n\n resolve: (ctx: any) => resolveAuthContext(authResult.auth, ctx),\n\n ctx: () => ({\n args: {},\n input: async (ctx: any) => {\n const authCtx = await resolveAuthContext(authResult.auth, ctx);\n return { ctx: { auth: authCtx }, args: {} };\n },\n }),\n } as unknown as ConvexAuthResult<P, TAuthorization>;\n}\n\n// ============================================================================\n// AuthCtx — ctx enrichment for customQuery / customMutation\n// ============================================================================\n\n/**\n * Configuration for {@link AuthCtx} context enrichment.\n *\n * @typeParam TResolve - Extra fields returned from `resolve()` and merged into\n * the resulting `ctx.auth` object.\n */\nexport type AuthCtxConfig<\n TResolve extends Record<string, unknown> = Record<string, never>,\n> = {\n /** Allow unauthenticated callers and return `userId: null` / `user: null`. */\n optional?: boolean;\n /**\n * Attach additional derived fields to the auth context after the base auth\n * context is resolved.\n */\n resolve?: (\n ctx: any,\n user: UserDoc,\n auth: AuthResolvedContext,\n ) => Promise<TResolve> | TResolve;\n /**\n * Override or wrap the base auth resolution used by {@link AuthCtx}.\n *\n * Return `undefined` to fall back to the built-in resolver,\n * `null` for an explicit unauthenticated state, or an\n * {@link AuthResolvedContext} object to provide a pre-resolved auth state.\n * This is useful for tests, proxy auth, impersonation flows, or any\n * environment that needs to inject auth without depending on the standard\n * Convex auth tables.\n *\n * @param ctx - The Convex function context.\n * @param fallback - The built-in auth resolver used by {@link AuthCtx}.\n * @returns Resolved auth state, `null`, or `undefined` to use the fallback.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * authResolve: async (ctx, fallback) => {\n * const injected = getInjectedAuth(ctx);\n * return injected ?? (await fallback());\n * },\n * });\n * ```\n */\n authResolve?: (\n ctx: any,\n fallback: () => Promise<AuthResolvedContext | null>,\n ) =>\n | Promise<AuthResolvedContext | null | undefined>\n | AuthResolvedContext\n | null\n | undefined;\n};\n\n/**\n * Create a context enrichment for `customQuery` / `customMutation` — optional auth.\n *\n * When `optional: true` is set, unauthenticated requests are allowed.\n * The enriched `ctx.auth` will have `userId: null`, `user: null`,\n * `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.\n *\n * @param auth - The auth API object returned by {@link createAuth}.\n * @param config - Configuration with `optional: true` and an optional\n * `resolve` callback for attaching extra fields to the auth context.\n * @returns An object with `args` and `input` compatible with Convex\n * custom function builders.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * optional: true,\n * resolve: async (_ctx, user) => ({ plan: user?.extend?.plan ?? null }),\n * });\n * ```\n *\n * @see {@link createAuth}\n */\nexport function AuthCtx<\n TResolve extends Record<string, unknown> = Record<string, never>,\n>(\n auth: AuthLike,\n config: AuthCtxConfig<TResolve> & { optional: true },\n): {\n args: {};\n input: (\n ctx: any,\n _args: any,\n _extra?: any,\n ) => Promise<{\n ctx: {\n auth: OptionalAuthCtxState & TResolve;\n };\n args: {};\n }>;\n};\n/**\n * Create a context enrichment for `customQuery` / `customMutation` — required auth (default).\n *\n * When `optional` is omitted or `false`, the inferred type is the authenticated\n * auth shape. At runtime this helper still resolves instead of throwing, so if\n * no user is signed in the returned `ctx.auth.userId` / `ctx.auth.user` are\n * `null`, `ctx.auth.groupId` / `ctx.auth.role` are `null`, and\n * `ctx.auth.grants` is `[]`.\n *\n * @param auth - The auth API object returned by {@link createAuth}.\n * @param config - Optional configuration with a `resolve` callback\n * for attaching extra fields to the auth context.\n * @returns An object with `args` and `input` compatible with Convex\n * custom function builders.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * resolve: async (_ctx, user) => ({ email: user.email }),\n * });\n * ```\n *\n * @see {@link createAuth}\n */\nexport function AuthCtx<\n TResolve extends Record<string, unknown> = Record<string, never>,\n>(\n auth: AuthLike,\n config?: AuthCtxConfig<TResolve>,\n): {\n args: {};\n input: (\n ctx: any,\n _args: any,\n _extra?: any,\n ) => Promise<{\n ctx: {\n auth: RequiredAuthCtxState & TResolve;\n };\n args: {};\n }>;\n};\n// Implementation\nexport function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {\n return {\n args: {},\n input: async (ctx: any, _args: any, _extra?: any) => {\n const nativeAuth = ctx.auth;\n const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);\n const fallback = () => resolveAuthContext(auth, ctx);\n\n const authOverride = config?.authResolve\n ? await config.authResolve(ctx, fallback)\n : undefined;\n const resolved =\n authOverride === undefined ? await fallback() : authOverride;\n\n if (resolved === null) {\n return {\n ctx: {\n auth: {\n getUserIdentity,\n userId: null,\n user: null,\n groupId: null,\n role: null,\n grants: [],\n },\n },\n args: {},\n };\n }\n\n const extra = config?.resolve\n ? await config.resolve(ctx, resolved.user, resolved)\n : {};\n\n return {\n ctx: {\n auth: {\n getUserIdentity,\n ...resolved,\n ...extra,\n },\n },\n args: {},\n };\n },\n };\n}\n\n/**\n * Extract the resolved `auth` context type from an {@link AuthCtx} instance.\n *\n * Use this to type function parameters or variables that receive the\n * enriched auth context produced by `AuthCtx`. The inferred type includes\n * `userId`, `user`, `groupId`, `role`, `grants`, `getUserIdentity`, and any\n * additional fields added by the `resolve` callback. This is the generic\n * utility for reusing the enriched auth shape without manually duplicating\n * conditional auth types.\n *\n * @typeParam T - An `AuthCtx` return value (must have an `input` method\n * that returns `{ ctx: { auth: ... } }`).\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * resolve: async (ctx, user) => ({ orgId: user.orgId }),\n * });\n * type Auth = InferAuth<typeof authCtx>;\n * // Auth = { userId: Id<\"User\">; user: UserDoc; getUserIdentity: ...; orgId: string }\n * ```\n *\n * @see {@link createAuth}\n */\nexport type InferAuth<\n T extends { input: (...args: any[]) => Promise<{ ctx: { auth: any } }> },\n> = Awaited<ReturnType<T[\"input\"]>>[\"ctx\"][\"auth\"];\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","names":["AuthFactory"],"sources":["../../src/server/auth.ts"],"sourcesContent":["/**\n * Auth configuration helpers for Convex Auth.\n *\n * @module\n */\n\nimport { Cv } from \"@robelest/fx/convex\";\nimport type { UserIdentity } from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nimport type { AuthApiRefs } from \"../client/index\";\nimport { Auth as AuthFactory } from \"./runtime\";\nimport type { Doc } from \"./types\";\nimport type {\n AuthAuthorizationConfig,\n AuthGrant,\n AuthProviderConfig,\n AuthRoleDefinition,\n AuthRoleId,\n ConvexAuthConfig,\n HasDeviceProvider,\n HasPasskeyProvider,\n HasSSO,\n HasTotpProvider,\n} from \"./types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Config for auth setup. Extends the standard auth config\n * minus `component` (which is passed as the first constructor argument).\n */\nexport type AuthConfig = Omit<ConvexAuthConfig, \"component\">;\n\n/** Canonical user document type exposed by Convex Auth. */\nexport type UserDoc = Doc<\"User\">;\n\ntype MemberApiWithAuthorization<\n TAuthorization extends AuthAuthorizationConfig | undefined,\n> = Omit<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"],\n \"create\" | \"list\" | \"update\" | \"inspect\" | \"require\"\n> & {\n create: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"create\"]\n >[0],\n data: {\n groupId: string;\n userId: string;\n roleIds?: AuthRoleId<TAuthorization>[];\n status?: string;\n extend?: Record<string, unknown>;\n },\n ) => Promise<{ memberId: string }>;\n list: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"list\"]\n >[0],\n opts?: {\n where?: {\n groupId?: string;\n userId?: string;\n roleId?: AuthRoleId<TAuthorization>;\n status?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"status\";\n order?: \"asc\" | \"desc\";\n },\n ) => ReturnType<ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"list\"]>;\n update: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"update\"]\n >[0],\n memberId: string,\n data: Record<string, unknown> & { roleIds?: AuthRoleId<TAuthorization>[] },\n ) => Promise<{ memberId: string }>;\n inspect: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"inspect\"]\n >[0],\n opts: {\n userId: string;\n groupId: string;\n ancestry?: boolean;\n maxDepth?: number;\n },\n ) => ReturnType<ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"inspect\"]>;\n require: (\n ctx: Parameters<\n ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"require\"]\n >[0],\n opts: {\n userId: string;\n groupId: string;\n ancestry?: boolean;\n roleIds?: AuthRoleId<TAuthorization>[];\n grants?: AuthGrant<TAuthorization>[];\n maxDepth?: number;\n },\n ) => ReturnType<ReturnType<typeof AuthFactory>[\"auth\"][\"member\"][\"require\"]>;\n};\n\n/**\n * The base auth API surface returned by {@link createAuth}.\n *\n * Provides core namespaces — `signIn`, `signOut`, `user`, `session`,\n * `member`, `invite`, `group`, `key`, and `http` — that are\n * always available regardless of which providers are configured.\n * Enterprise namespaces (`sso`, `scim`) are added conditionally by\n * {@link AuthApi} when an SSO provider is present.\n *\n * Use this type when you want to describe code that only depends on the\n * standard auth surface and should not assume enterprise features exist.\n *\n * @typeParam TAuthorization - The authorization config, used to narrow\n * role IDs and grant strings on the `member` API.\n */\nexport type AuthApiBase<\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> = {\n signIn: ReturnType<typeof AuthFactory>[\"signIn\"];\n signOut: ReturnType<typeof AuthFactory>[\"signOut\"];\n store: ReturnType<typeof AuthFactory>[\"store\"];\n user: ReturnType<typeof AuthFactory>[\"auth\"][\"user\"];\n session: ReturnType<typeof AuthFactory>[\"auth\"][\"session\"];\n provider: ReturnType<typeof AuthFactory>[\"auth\"][\"provider\"];\n account: ReturnType<typeof AuthFactory>[\"auth\"][\"account\"];\n group: ReturnType<typeof AuthFactory>[\"auth\"][\"group\"];\n member: MemberApiWithAuthorization<TAuthorization>;\n invite: ReturnType<typeof AuthFactory>[\"auth\"][\"invite\"];\n key: ReturnType<typeof AuthFactory>[\"auth\"][\"key\"];\n http: ReturnType<typeof AuthFactory>[\"auth\"][\"http\"];\n /**\n * Resolve the current request's auth context. Framework-agnostic — use\n * this in fluent-convex middleware, custom wrappers, or anywhere you\n * need the current `{ userId, user, groupId, role, grants }` object.\n *\n * Throws a structured `ConvexError` when unauthenticated.\n *\n * @param ctx - Convex query, mutation, or action context.\n * @returns The current auth context.\n *\n * @example fluent-convex middleware\n * ```ts\n * const withAuth = convex.createMiddleware(async (ctx, next) => {\n * return next({ ...ctx, auth: await auth.context(ctx) });\n * });\n * ```\n *\n * @example Direct usage in a handler\n * ```ts\n * const authContext = await auth.context(ctx);\n * const { userId, grants } = authContext;\n * ```\n */\n context: (ctx: any) => Promise<AuthContext>;\n /**\n * Context enrichment for convex-helpers `customQuery` / `customMutation` /\n * `customAction`.\n *\n * Resolves the current user's identity, active group, membership role,\n * and grants, then attaches them to `ctx.auth`. Returns a `Customization`\n * object compatible with convex-helpers' custom function builders.\n *\n * `ctx.auth` is the current request auth context.\n * By default this throws when unauthenticated so handlers can assume\n * `ctx.auth.userId` and `ctx.auth.user` exist.\n *\n * @returns A convex-helpers `Customization` object.\n *\n * @example One-time setup in `convex/functions.ts`\n * ```ts\n * import { query, mutation, action } from \"./_generated/server\";\n * import { customQuery, customMutation, customAction } from \"convex-helpers/server/customFunctions\";\n * import { auth } from \"./auth\";\n *\n * export const authQuery = customQuery(query, auth.ctx());\n * export const authMutation = customMutation(mutation, auth.ctx());\n * export const authAction = customAction(action, auth.ctx());\n * ```\n *\n * @example Per-function usage\n * ```ts\n * import { authQuery } from \"./functions\";\n *\n * export const list = authQuery({\n * args: { workspaceId: v.string() },\n * handler: async (ctx, args) => {\n * const { userId, groupId, grants } = ctx.auth;\n * // business logic\n * },\n * });\n * ```\n */\n ctx: () => {\n args: Record<string, never>;\n input: (ctx: any) => Promise<{\n ctx: { auth: AuthContext };\n args: Record<string, never>;\n }>;\n };\n};\n\n/**\n * Current request auth context injected into `ctx.auth` by `auth.ctx()` and\n * {@link AuthCtx}. This is the authenticated auth shape returned by\n * {@link createAuth().context}. Optional context builders may still surface\n * nullable fields when `optional: true` is used.\n *\n * - `groupId` is `null` when the user has no active group set.\n * - `role` is `null` when no active group or no membership is resolved.\n * - `grants` is `[]` when no active group or no membership is resolved.\n *\n * @example\n * ```ts\n * import type { AuthContext } from \"@robelest/convex-auth/server\";\n *\n * const mockAuth: AuthContext = {\n * userId: \"user123\" as Id<\"User\">,\n * user: { _id: \"user123\", email: \"test@example.com\" },\n * groupId: \"group456\",\n * role: \"admin\",\n * grants: [\"read\", \"write\"],\n * };\n * ```\n */\nexport type AuthContext = {\n /** The authenticated user's document ID. */\n userId: GenericId<\"User\">;\n /** The authenticated user's full document. */\n user: UserDoc;\n /** The user's active group ID, or `null` if none set. */\n groupId: string | null;\n /** The user's primary role in the active group, or `null`. */\n role: string | null;\n /** Resolved grant strings from the user's role definitions. */\n grants: string[];\n};\n\ntype AuthCtxBase = {\n getUserIdentity: () => Promise<UserIdentity | null>;\n};\n\ntype RequiredAuthCtxState = AuthCtxBase & AuthContext;\n\ntype OptionalAuthCtxState = AuthCtxBase & {\n userId: GenericId<\"User\"> | null;\n user: UserDoc | null;\n groupId: string | null;\n role: string | null;\n grants: string[];\n};\n\ntype InternalSsoApi = ReturnType<typeof AuthFactory>[\"auth\"][\"sso\"];\n\ntype PublicSsoAdminApi = {\n connection: InternalSsoApi[\"connection\"] & {\n domain: {\n list: InternalSsoApi[\"domain\"][\"list\"];\n validate: InternalSsoApi[\"domain\"][\"validate\"];\n set: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n enterpriseId: string,\n domains: Array<{\n domain: string;\n isPrimary?: boolean;\n }>,\n ) => Promise<{\n enterpriseId: string;\n domains: Array<{\n domainId: string;\n domain: string;\n isPrimary: boolean;\n verified: boolean;\n verifiedAt: number | null;\n }>;\n }>;\n verification: {\n request: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n args: { enterpriseId: string; domain: string },\n ) => Promise<{\n enterpriseId: string;\n domain: string;\n requestedAt: number;\n expiresAt: number;\n challenge: {\n recordType: \"TXT\";\n recordName: string;\n recordValue: string;\n };\n }>;\n confirm: (\n ctx: Parameters<InternalSsoApi[\"connection\"][\"create\"]>[0],\n args: { enterpriseId: string; domain: string },\n ) => Promise<{\n enterpriseId: string;\n domain: string;\n verifiedAt?: number;\n checks: Array<{ name: string; ok: boolean; message?: string }>;\n }>;\n };\n };\n };\n oidc: Omit<InternalSsoApi[\"oidc\"], \"signIn\">;\n saml: Omit<InternalSsoApi[\"saml\"], \"metadata\">;\n policy: InternalSsoApi[\"policy\"];\n audit: {\n list: InternalSsoApi[\"audit\"][\"list\"];\n };\n webhook: {\n endpoint: InternalSsoApi[\"webhook\"][\"endpoint\"];\n delivery: {\n list: InternalSsoApi[\"webhook\"][\"delivery\"][\"list\"];\n };\n };\n};\n\ntype PublicSsoClientApi = {\n signIn: InternalSsoApi[\"oidc\"][\"signIn\"];\n metadata: InternalSsoApi[\"saml\"][\"metadata\"];\n};\n\ntype PublicSsoApi = {\n admin: PublicSsoAdminApi;\n client: PublicSsoClientApi;\n};\n\ntype PublicScimApi = {\n admin: Omit<InternalSsoApi[\"scim\"], \"getConfigByToken\" | \"identity\">;\n};\n\n/**\n * Extended auth API that includes enterprise SSO and SCIM namespaces.\n *\n * This type is the union of {@link AuthApiBase} plus `sso` (SSO connection\n * management, OIDC/SAML, domain verification, policies, audit, webhooks)\n * and `scim` (SCIM provisioning configuration). It is returned by\n * {@link createAuth} only when `new SSO()` is included in the providers\n * array; otherwise the narrower {@link AuthApiBase} is returned instead.\n * Attempting to access `auth.sso` or `auth.scim` without an SSO provider\n * produces a compile-time error because the return type narrows back to\n * {@link AuthApiBase}.\n *\n * @typeParam TAuthorization - The authorization config, forwarded to\n * {@link AuthApiBase} for typed role IDs and grant strings.\n */\nexport type AuthApi<\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> = AuthApiBase<TAuthorization> & {\n sso: PublicSsoApi;\n scim: PublicScimApi;\n};\n\n/**\n * The return type of {@link createAuth}.\n *\n * Resolves to {@link AuthApi} (with `sso` and `scim` namespaces) when\n * `new SSO()` is present in the providers array, or to the narrower\n * {@link AuthApiBase} otherwise. This conditional type ensures that\n * enterprise-only APIs are only accessible when the SSO provider is\n * configured, producing a compile-time error if you try to access\n * `auth.sso` without it.\n * This lets application code keep a single `createAuth()` call while still\n * getting provider-aware typing on the resulting API object.\n *\n * @typeParam P - The tuple of provider configs passed to `createAuth`.\n * @typeParam TAuthorization - Optional authorization config for typed roles/grants.\n */\nexport type ConvexAuthResult<\n P extends AuthProviderConfig[],\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n> =\n HasSSO<P> extends true\n ? AuthApi<TAuthorization>\n : AuthApiBase<TAuthorization>;\n\n/**\n * Infer the typed `AuthApiRefs` for the client SDK from a `createAuth` call.\n *\n * Use this as the generic parameter for `client()` on the frontend:\n *\n * ```ts\n * // convex/auth.ts\n * export const auth = createAuth(components.auth, { providers: [...] });\n *\n * // Frontend\n * import type { auth } from \"../convex/auth\";\n * import type { InferClientApi } from \"@robelest/convex-auth/server\";\n * const c = client<InferClientApi<typeof auth>>({ convex, api: api.auth });\n * ```\n *\n * @typeParam T - A ConvexAuthResult to extract the client API from.\n */\nexport type InferClientApi<T> =\n T extends ConvexAuthResult<infer P>\n ? AuthApiRefs<\n HasPasskeyProvider<P>,\n HasTotpProvider<P>,\n HasDeviceProvider<P>\n >\n : AuthApiRefs;\n\n/** @internal */\nexport type AuthLike = Pick<AuthApiBase, \"user\" | \"member\">;\n\n// ============================================================================\n// Auth setup APIs\n// ============================================================================\n\n/**\n * Create an auth API object.\n *\n * When `new SSO()` is included in providers, `auth.sso` and `auth.scim`\n * are available on the returned object. Without it, those namespaces are\n * absent and accessing them is a TypeScript compile error.\n *\n * @param component - The installed auth component reference from\n * `components.auth` in your Convex app definition.\n * @param config - Auth configuration including `providers` and optional\n * `authorization`. All fields from {@link AuthConfig} are accepted\n * except `component` (passed as the first argument).\n * @returns A {@link ConvexAuthResult} object — either {@link AuthApi}\n * (with `sso`/`scim`) or {@link AuthApiBase}, depending on whether\n * an SSO provider is present.\n *\n * @example\n * ```ts\n * export const auth = createAuth(components.auth, {\n * providers: [password(), google()],\n * authorization: { roles },\n * });\n * ```\n *\n * @see {@link AuthCtx}\n */\n\n// ---------------------------------------------------------------------------\n// Function builders — shared auth resolution logic\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve auth context for the current user. Returns the enriched\n * `ctx.auth` object or `null` when unauthenticated.\n *\n * Resolution flow:\n * 1. `user.id(ctx)` → userId or null (exit early)\n * 2. `user.get(ctx, userId)` → user doc (cached per-execution)\n * 3. `user.getActiveGroup(ctx, { userId })` → groupId or null\n * 4. If groupId → `member.inspect(ctx, { userId, groupId })` → role + grants\n */\nasync function getAuthContext(\n auth: AuthLike,\n ctx: any,\n): Promise<AuthContext | null> {\n const userId = await auth.user.id(ctx);\n if (!userId) return null;\n const user = await auth.user.get(ctx, userId);\n const groupId = await auth.user.getActiveGroup(ctx, { userId });\n let role: string | null = null;\n let grants: string[] = [];\n if (groupId) {\n const resolved = await auth.member.inspect(ctx, { userId, groupId });\n if (resolved.membership) {\n role = resolved.roleIds[0] ?? null;\n grants = resolved.grants;\n }\n }\n return { userId, user, groupId, role, grants };\n}\n\nexport function createAuth<\n P extends AuthProviderConfig[],\n TAuthorization extends AuthAuthorizationConfig | undefined = undefined,\n>(\n component: ConvexAuthConfig[\"component\"],\n config: Omit<AuthConfig, \"providers\" | \"authorization\"> & {\n providers: P;\n authorization?: TAuthorization;\n },\n): ConvexAuthResult<P, TAuthorization> {\n const authResult = AuthFactory({\n ...config,\n component,\n providers: [...config.providers],\n });\n const {\n domain: domainApi,\n scim: scimApi,\n connection: connectionApi,\n audit: auditApi,\n webhook: webhookApi,\n oidc: oidcApi,\n saml: samlApi,\n ...restSso\n } = authResult.auth.sso as InternalSsoApi;\n\n type SetEnterpriseDomains = PublicSsoAdminApi[\"connection\"][\"domain\"][\"set\"];\n type EnterpriseDomainInput = Array<{\n domain: string;\n isPrimary?: boolean;\n }>;\n const setEnterpriseDomains: PublicSsoAdminApi[\"connection\"][\"domain\"][\"set\"] =\n async (\n ctx: Parameters<SetEnterpriseDomains>[0],\n enterpriseId: Parameters<SetEnterpriseDomains>[1],\n domains: EnterpriseDomainInput,\n ) => {\n const enterprise = await connectionApi.get(ctx, enterpriseId);\n if (enterprise === null) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Enterprise not found.\",\n });\n }\n\n const normalized = domains.map((entry: (typeof domains)[number]) => ({\n ...entry,\n domain: entry.domain.trim().toLowerCase(),\n }));\n const deduped = new Map<string, (typeof normalized)[number]>();\n for (const entry of normalized) {\n if (entry.domain.length === 0) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Domain must not be empty.\",\n });\n }\n if (deduped.has(entry.domain)) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: `Duplicate domain: ${entry.domain}`,\n });\n }\n deduped.set(entry.domain, entry);\n }\n\n const nextDomains = [...deduped.values()];\n const primaryCount = nextDomains.filter(\n (entry) => entry.isPrimary,\n ).length;\n if (primaryCount > 1) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Only one primary domain may be set.\",\n });\n }\n if (nextDomains.length > 0 && primaryCount === 0) {\n nextDomains[0] = { ...nextDomains[0], isPrimary: true };\n }\n\n const currentDomains = await domainApi.list(ctx, enterpriseId);\n const currentByDomain = new Map<string, (typeof currentDomains)[number]>(\n currentDomains.map((entry: (typeof currentDomains)[number]) => [\n entry.domain.toLowerCase(),\n entry,\n ]),\n );\n\n for (const existing of currentDomains) {\n if (!deduped.has(existing.domain.toLowerCase())) {\n await domainApi.remove(ctx, existing._id);\n }\n }\n\n for (const nextDomain of nextDomains) {\n const current = currentByDomain.get(nextDomain.domain);\n if (current && current.isPrimary === Boolean(nextDomain.isPrimary)) {\n continue;\n }\n if (current) {\n await domainApi.remove(ctx, current._id);\n }\n const domainId = await domainApi.add(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n domain: nextDomain.domain,\n isPrimary: nextDomain.isPrimary,\n });\n if (current?.verifiedAt !== undefined) {\n await (ctx as any).runMutation(\n component.public.enterpriseDomainVerify,\n {\n domainId,\n verifiedAt: current.verifiedAt,\n },\n );\n }\n }\n\n const updatedDomains = await domainApi.list(ctx, enterpriseId);\n return {\n enterpriseId,\n domains: updatedDomains.map(\n (domain: (typeof updatedDomains)[number]) => ({\n domainId: domain._id,\n domain: domain.domain,\n isPrimary: domain.isPrimary,\n verified: domain.verifiedAt !== undefined,\n verifiedAt: domain.verifiedAt ?? null,\n }),\n ),\n };\n };\n\n const publicSso: PublicSsoApi = {\n admin: {\n ...restSso,\n oidc: {\n ...oidcApi,\n },\n saml: {\n ...samlApi,\n },\n connection: {\n ...connectionApi,\n domain: {\n list: domainApi.list,\n validate: domainApi.validate,\n set: setEnterpriseDomains,\n verification: {\n request: domainApi.verification.request,\n confirm: domainApi.verification.confirm,\n },\n },\n },\n policy: restSso.policy,\n audit: {\n list: auditApi.list,\n },\n webhook: {\n endpoint: webhookApi.endpoint,\n delivery: {\n list: webhookApi.delivery.list,\n },\n },\n },\n client: {\n signIn: oidcApi.signIn,\n metadata: samlApi.metadata,\n },\n };\n\n return {\n signIn: authResult.signIn,\n signOut: authResult.signOut,\n store: authResult.store,\n user: authResult.auth.user,\n session: authResult.auth.session,\n provider: authResult.auth.provider,\n account: authResult.auth.account,\n group: authResult.auth.group,\n member: authResult.auth.member,\n invite: authResult.auth.invite,\n key: authResult.auth.key,\n sso: publicSso,\n scim: {\n admin: {\n configure: scimApi.configure,\n get: scimApi.get,\n validate: scimApi.validate,\n },\n },\n http: authResult.auth.http,\n\n context: async (ctx: any) => {\n const authContext = await getAuthContext(authResult.auth, ctx);\n if (authContext === null) {\n throw Cv.error({\n code: \"NOT_SIGNED_IN\",\n message: \"Authentication required.\",\n });\n }\n return authContext;\n },\n\n ctx: () => ({\n args: {},\n input: async (ctx: any) => {\n const authCtx = await getAuthContext(authResult.auth, ctx);\n if (authCtx === null) {\n throw Cv.error({\n code: \"NOT_SIGNED_IN\",\n message: \"Authentication required.\",\n });\n }\n return { ctx: { auth: authCtx }, args: {} };\n },\n }),\n } as unknown as ConvexAuthResult<P, TAuthorization>;\n}\n\n// ============================================================================\n// AuthCtx — ctx enrichment for customQuery / customMutation\n// ============================================================================\n\n/**\n * Configuration for {@link AuthCtx} context enrichment.\n *\n * @typeParam TResolve - Extra fields returned from `resolve()` and merged into\n * the resulting `ctx.auth` object.\n */\nexport type AuthCtxConfig<\n TResolve extends Record<string, unknown> = Record<string, never>,\n> = {\n /** Allow unauthenticated callers and return `userId: null` / `user: null`. */\n optional?: boolean;\n /**\n * Attach additional derived fields to the auth context after the base auth\n * context is resolved.\n */\n resolve?: (\n ctx: any,\n user: UserDoc,\n auth: AuthContext,\n ) => Promise<TResolve> | TResolve;\n /**\n * Override or wrap the base auth resolution used by {@link AuthCtx}.\n *\n * Return `undefined` to fall back to the built-in resolver,\n * `null` for an explicit unauthenticated state, or an\n * {@link AuthContext} object to provide a pre-resolved auth state.\n * This is useful for tests, proxy auth, impersonation flows, or any\n * environment that needs to inject auth without depending on the standard\n * Convex auth tables.\n *\n * @param ctx - The Convex function context.\n * @param fallback - The built-in auth resolver used by {@link AuthCtx}.\n * @returns Resolved auth state, `null`, or `undefined` to use the fallback.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * authResolve: async (ctx, fallback) => {\n * const injected = getInjectedAuth(ctx);\n * return injected ?? (await fallback());\n * },\n * });\n * ```\n */\n authResolve?: (\n ctx: any,\n fallback: () => Promise<AuthContext | null>,\n ) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;\n};\n\n/**\n * Create a context enrichment for `customQuery` / `customMutation` — optional auth.\n *\n * When `optional: true` is set, unauthenticated requests are allowed.\n * The enriched `ctx.auth` will have `userId: null`, `user: null`,\n * `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.\n *\n * @param auth - The auth API object returned by {@link createAuth}.\n * @param config - Configuration with `optional: true` and an optional\n * `resolve` callback for attaching extra fields to the auth context.\n * @returns An object with `args` and `input` compatible with Convex\n * custom function builders.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * optional: true,\n * resolve: async (_ctx, user) => ({ plan: user?.extend?.plan ?? null }),\n * });\n * ```\n *\n * @see {@link createAuth}\n */\nexport function AuthCtx<\n TResolve extends Record<string, unknown> = Record<string, never>,\n>(\n auth: AuthLike,\n config: AuthCtxConfig<TResolve> & { optional: true },\n): {\n args: {};\n input: (\n ctx: any,\n _args: any,\n _extra?: any,\n ) => Promise<{\n ctx: {\n auth: OptionalAuthCtxState & TResolve;\n };\n args: {};\n }>;\n};\n/**\n * Create a context enrichment for `customQuery` / `customMutation` — required auth (default).\n *\n * When `optional` is omitted or `false`, unauthenticated requests throw a\n * structured `ConvexError` before your handler runs.\n *\n * @param auth - The auth API object returned by {@link createAuth}.\n * @param config - Optional configuration with a `resolve` callback\n * for attaching extra fields to the auth context.\n * @returns An object with `args` and `input` compatible with Convex\n * custom function builders.\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * resolve: async (_ctx, user) => ({ email: user.email }),\n * });\n * ```\n *\n * @see {@link createAuth}\n */\nexport function AuthCtx<\n TResolve extends Record<string, unknown> = Record<string, never>,\n>(\n auth: AuthLike,\n config?: AuthCtxConfig<TResolve>,\n): {\n args: {};\n input: (\n ctx: any,\n _args: any,\n _extra?: any,\n ) => Promise<{\n ctx: {\n auth: RequiredAuthCtxState & TResolve;\n };\n args: {};\n }>;\n};\n// Implementation\nexport function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {\n return {\n args: {},\n input: async (ctx: any, _args: any, _extra?: any) => {\n const nativeAuth = ctx.auth;\n const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);\n const fallback = () => getAuthContext(auth, ctx);\n\n const authOverride = config?.authResolve\n ? await config.authResolve(ctx, fallback)\n : undefined;\n const resolved =\n authOverride === undefined ? await fallback() : authOverride;\n\n if (resolved === null) {\n if (config?.optional !== true) {\n throw Cv.error({\n code: \"NOT_SIGNED_IN\",\n message: \"Authentication required.\",\n });\n }\n return {\n ctx: {\n auth: {\n getUserIdentity,\n userId: null,\n user: null,\n groupId: null,\n role: null,\n grants: [],\n },\n },\n args: {},\n };\n }\n\n const extra = config?.resolve\n ? await config.resolve(ctx, resolved.user, resolved)\n : {};\n\n return {\n ctx: {\n auth: {\n getUserIdentity,\n ...resolved,\n ...extra,\n },\n },\n args: {},\n };\n },\n };\n}\n\n/**\n * Extract the resolved `auth` context type from an {@link AuthCtx} instance.\n *\n * Use this to type function parameters or variables that receive the\n * enriched auth context produced by `AuthCtx`. The inferred type includes\n * `userId`, `user`, `groupId`, `role`, `grants`, `getUserIdentity`, and any\n * additional fields added by the `resolve` callback. This is the generic\n * utility for reusing the enriched auth shape without manually duplicating\n * conditional auth types.\n *\n * @typeParam T - An `AuthCtx` return value (must have an `input` method\n * that returns `{ ctx: { auth: ... } }`).\n *\n * @example\n * ```ts\n * const authCtx = AuthCtx(auth, {\n * resolve: async (ctx, user) => ({ orgId: user.orgId }),\n * });\n * type Auth = InferAuth<typeof authCtx>;\n * // Auth = { userId: Id<\"User\">; user: UserDoc; getUserIdentity: ...; orgId: string }\n * ```\n *\n * @see {@link createAuth}\n */\nexport type InferAuth<\n T extends { input: (...args: any[]) => Promise<{ ctx: { auth: any } }> },\n> = Awaited<ReturnType<T[\"input\"]>>[\"ctx\"][\"auth\"];\n"],"mappings":"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"}