@robelest/convex-auth 0.0.4-preview.32 → 0.0.4-preview.34

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 (89) hide show
  1. package/dist/component/_generated/component.d.ts +1611 -2039
  2. package/dist/component/account.js +3 -0
  3. package/dist/component/convex.config.d.ts +2 -2
  4. package/dist/component/factor/device.js +3 -0
  5. package/dist/component/factor/passkey.js +3 -0
  6. package/dist/component/factor/totp.js +3 -0
  7. package/dist/component/group/invite.js +3 -0
  8. package/dist/component/group/member.js +3 -0
  9. package/dist/component/group.js +3 -0
  10. package/dist/component/model.d.ts +342 -30
  11. package/dist/component/model.js +22 -4
  12. package/dist/component/modules.js +24 -21
  13. package/dist/component/public/factors/devices.js +37 -106
  14. package/dist/component/public/factors/passkeys.js +29 -149
  15. package/dist/component/public/factors/totp.js +32 -159
  16. package/dist/component/public/groups/core.js +19 -82
  17. package/dist/component/public/groups/invites.js +15 -104
  18. package/dist/component/public/groups/members.js +26 -149
  19. package/dist/component/public/identity/accounts.js +12 -94
  20. package/dist/component/public/identity/codes.js +13 -73
  21. package/dist/component/public/identity/sessions.js +5 -107
  22. package/dist/component/public/identity/tokens.js +13 -103
  23. package/dist/component/public/identity/users.js +188 -185
  24. package/dist/component/public/identity/verifiers.js +17 -80
  25. package/dist/component/public/security/keys.js +13 -120
  26. package/dist/component/public/security/limits.js +0 -43
  27. package/dist/component/public/sso/audit.js +0 -28
  28. package/dist/component/public/sso/core.js +31 -104
  29. package/dist/component/public/sso/domains.js +0 -71
  30. package/dist/component/public/sso/scim.js +63 -239
  31. package/dist/component/public/sso/secrets.js +0 -30
  32. package/dist/component/public/sso/webhooks.js +23 -128
  33. package/dist/component/rateLimit.js +3 -0
  34. package/dist/component/schema.d.ts +378 -342
  35. package/dist/component/schema.js +11 -1
  36. package/dist/component/session.js +3 -0
  37. package/dist/component/sso/audit.js +3 -0
  38. package/dist/component/sso/connection/domain/verification.js +3 -0
  39. package/dist/component/sso/connection/domain.js +3 -0
  40. package/dist/component/sso/connection/scim/config.js +3 -0
  41. package/dist/component/sso/connection/scim/identity.js +3 -0
  42. package/dist/component/sso/connection/secret.js +3 -0
  43. package/dist/component/sso/connection.js +3 -0
  44. package/dist/component/sso/webhook/delivery.js +3 -0
  45. package/dist/component/sso/webhook/endpoint.js +3 -0
  46. package/dist/component/token/pkce.js +3 -0
  47. package/dist/component/token/refresh.js +3 -0
  48. package/dist/component/token/verification.js +3 -0
  49. package/dist/component/user/email.js +3 -0
  50. package/dist/component/user/key.js +3 -0
  51. package/dist/component/user.js +62 -0
  52. package/dist/core/index.d.ts +131 -28
  53. package/dist/core/index.js +2 -0
  54. package/dist/model.js +391 -0
  55. package/dist/providers/credentials.d.ts +1 -1
  56. package/dist/providers/github.js +6 -0
  57. package/dist/providers/password.js +1 -2
  58. package/dist/server/auth.d.ts +73 -7
  59. package/dist/server/auth.js +4 -1
  60. package/dist/server/context.js +30 -3
  61. package/dist/server/contract.js +42 -42
  62. package/dist/server/core.js +224 -86
  63. package/dist/server/db.js +45 -37
  64. package/dist/server/facade.d.ts +39 -0
  65. package/dist/server/facade.js +16 -0
  66. package/dist/server/index.d.ts +5 -3
  67. package/dist/server/index.js +3 -1
  68. package/dist/server/mounts.d.ts +101 -101
  69. package/dist/server/mutations/credentials/signin.js +3 -7
  70. package/dist/server/mutations/oauth.js +9 -6
  71. package/dist/server/runtime.d.ts +147 -46
  72. package/dist/server/runtime.js +10 -8
  73. package/dist/server/services/group.js +9 -9
  74. package/dist/server/sso/domain.d.ts +1 -1
  75. package/dist/server/sso/domain.js +40 -40
  76. package/dist/server/sso/http.js +18 -18
  77. package/dist/server/sso/oidc.js +1 -1
  78. package/dist/server/sso/policies.js +3 -3
  79. package/dist/server/sso/policy.js +12 -4
  80. package/dist/server/sso/provision.js +9 -9
  81. package/dist/server/sso/validators.js +2 -2
  82. package/dist/server/sso/webhook.js +8 -8
  83. package/dist/server/types.d.ts +185 -124
  84. package/dist/server/types.js +29 -24
  85. package/dist/server/users.js +49 -2
  86. package/dist/server/validators.d.ts +745 -0
  87. package/dist/server/validators.js +60 -0
  88. package/package.json +1 -1
  89. package/dist/component/public.js +0 -22
@@ -8,7 +8,7 @@ function createGroupWebhookDomain(deps) {
8
8
  return {
9
9
  endpoint: {
10
10
  get: async (ctx, endpointId) => {
11
- return await getWebhookEndpoint(ctx, config.component.public, endpointId);
11
+ return await getWebhookEndpoint(ctx, config.component.sso, endpointId);
12
12
  },
13
13
  create: async (ctx, data) => {
14
14
  const connection = await loadConnectionOrThrow(ctx, data.connectionId);
@@ -17,7 +17,7 @@ function createGroupWebhookDomain(deps) {
17
17
  message: "Connection not found."
18
18
  });
19
19
  const secretHash = await sha256(data.secret);
20
- const endpointId = await createWebhookEndpoint(ctx, config.component.public, {
20
+ const endpointId = await createWebhookEndpoint(ctx, config.component.sso, {
21
21
  connectionId: connection._id,
22
22
  groupId: connection.groupId,
23
23
  url: data.url,
@@ -38,10 +38,10 @@ function createGroupWebhookDomain(deps) {
38
38
  return { endpointId };
39
39
  },
40
40
  list: async (ctx, connectionId) => {
41
- return await listWebhookEndpoints(ctx, config.component.public, connectionId);
41
+ return await listWebhookEndpoints(ctx, config.component.sso, connectionId);
42
42
  },
43
43
  disable: async (ctx, endpointId) => {
44
- await updateWebhookEndpoint(ctx, config.component.public, {
44
+ await updateWebhookEndpoint(ctx, config.component.sso, {
45
45
  endpointId,
46
46
  data: { status: "disabled" }
47
47
  });
@@ -53,16 +53,16 @@ function createGroupWebhookDomain(deps) {
53
53
  },
54
54
  delivery: {
55
55
  list: async (ctx, data) => {
56
- return await listWebhookDeliveries(ctx, config.component.public, data);
56
+ return await listWebhookDeliveries(ctx, config.component.sso, data);
57
57
  },
58
58
  listReady: async (ctx, limit) => {
59
- return await listReadyWebhookDeliveries(ctx, config.component.public, {
59
+ return await listReadyWebhookDeliveries(ctx, config.component.sso, {
60
60
  now: Date.now(),
61
61
  limit
62
62
  });
63
63
  },
64
64
  markDelivered: async (ctx, deliveryId, responseStatus) => {
65
- await patchWebhookDelivery(ctx, config.component.public, {
65
+ await patchWebhookDelivery(ctx, config.component.sso, {
66
66
  deliveryId,
67
67
  data: {
68
68
  status: "delivered",
@@ -73,7 +73,7 @@ function createGroupWebhookDomain(deps) {
73
73
  });
74
74
  },
75
75
  markFailed: async (ctx, deliveryId, data) => {
76
- await patchWebhookDelivery(ctx, config.component.public, {
76
+ await patchWebhookDelivery(ctx, config.component.sso, {
77
77
  deliveryId,
78
78
  data: {
79
79
  status: data.retryAt ? "pending" : "failed",
@@ -407,10 +407,15 @@ interface SSOProviderConfig {
407
407
  /**
408
408
  * Account linking strategy for group SSO sign-in.
409
409
  *
410
- * - `"verifiedEmail"` — link accounts when the IdP-provided email matches a verified email on an existing user.
410
+ * - `"sameConnection"` (default) only link to a user already associated
411
+ * with **this** connection (via its account/externalId). Never link across
412
+ * IdPs by email. This prevents cross-IdP/tenant account takeover.
413
+ * - `"verifiedEmail"` — link accounts when the IdP-provided email matches a
414
+ * verified email on an existing user. Opt-in; only safe when every
415
+ * connection that can assert this email is mutually trusted.
411
416
  * - `"none"` — never auto-link; always create a new account.
412
417
  */
413
- type GroupConnectionAccountLinkingPolicy = "verifiedEmail" | "none";
418
+ type GroupConnectionAccountLinkingPolicy = "verifiedEmail" | "none" | "sameConnection";
414
419
  /**
415
420
  * Policy for reusing existing users during SCIM provisioning.
416
421
  *
@@ -743,10 +748,21 @@ interface TotpProviderConfig {
743
748
  *
744
749
  * `id` is the provider-specific account identifier (e.g. GitHub user ID).
745
750
  */
751
+ interface ProfileEmail {
752
+ email: string;
753
+ primary?: boolean;
754
+ verified?: boolean;
755
+ }
746
756
  interface OAuthProfile {
747
757
  id: string;
748
758
  name?: string;
749
759
  email?: string;
760
+ /**
761
+ * All emails the provider reported (e.g. GitHub `/user/emails`). When
762
+ * present, every entry is recorded; `email` remains the primary for
763
+ * back-compat. Single-email providers omit this.
764
+ */
765
+ emails?: ProfileEmail[];
750
766
  image?: string;
751
767
  /** Additional claims from the ID token or userinfo endpoint. */
752
768
  [key: string]: unknown;
@@ -914,8 +930,7 @@ type AuthServerHelpers = {
914
930
  totp: {
915
931
  /**
916
932
  * Delete a TOTP factor by ID and fire the `totpRemoved` lifecycle
917
- * event. If this was the user's last verified factor, the
918
- * `User.hasTotp` flag is cleared as part of the same mutation.
933
+ * event.
919
934
  */
920
935
  delete: (ctx: GenericActionCtx<GenericDataModel>, args: AuthDeleteTotpArgs) => Promise<{
921
936
  totpId: GenericId<"TotpFactor">;
@@ -1013,7 +1028,7 @@ interface OAuthMaterializedConfig {
1013
1028
  * Account-linking policy for OAuth identities. Defaults to verified email linking.
1014
1029
  * @readonly
1015
1030
  */
1016
- readonly accountLinking?: "verifiedEmail" | "none";
1031
+ readonly accountLinking?: "verifiedEmail" | "none" | "sameConnection";
1017
1032
  }
1018
1033
  /**
1019
1034
  * Device authorization provider config (RFC 8628).
@@ -1142,124 +1157,170 @@ interface CorsConfig {
1142
1157
  * Component function references required by core auth runtime.
1143
1158
  */
1144
1159
  type AuthComponentApi = {
1145
- public: {
1146
- userGetById: FunctionReference<"query", "internal">;
1147
- userList: FunctionReference<"query", "internal">;
1148
- userFindByVerifiedEmail: FunctionReference<"query", "internal">;
1149
- userFindByVerifiedPhone: FunctionReference<"query", "internal">;
1150
- userInsert: FunctionReference<"mutation", "internal">;
1151
- userUpsert: FunctionReference<"mutation", "internal">;
1152
- userPatch: FunctionReference<"mutation", "internal">;
1153
- userDelete: FunctionReference<"mutation", "internal">;
1154
- accountGet: FunctionReference<"query", "internal">;
1155
- accountGetById: FunctionReference<"query", "internal">;
1156
- accountInsert: FunctionReference<"mutation", "internal">;
1157
- accountListByUser: FunctionReference<"query", "internal">;
1158
- accountPatch: FunctionReference<"mutation", "internal">;
1159
- accountDelete: FunctionReference<"mutation", "internal">;
1160
- sessionCreate: FunctionReference<"mutation", "internal">;
1161
- sessionGetById: FunctionReference<"query", "internal">;
1162
- sessionDelete: FunctionReference<"mutation", "internal">;
1163
- sessionListByUser: FunctionReference<"query", "internal">;
1164
- verifierCreate: FunctionReference<"mutation", "internal">;
1165
- verifierGetById: FunctionReference<"query", "internal">;
1166
- verifierGetBySignature: FunctionReference<"query", "internal">;
1167
- verifierPatch: FunctionReference<"mutation", "internal">;
1168
- verifierDelete: FunctionReference<"mutation", "internal">;
1169
- verificationCodeGetByAccountId: FunctionReference<"query", "internal">;
1170
- verificationCodeGetByCode: FunctionReference<"query", "internal">;
1171
- verificationCodeCreate: FunctionReference<"mutation", "internal">;
1172
- verificationCodeDelete: FunctionReference<"mutation", "internal">;
1173
- refreshTokenCreate: FunctionReference<"mutation", "internal">;
1174
- refreshTokenGetById: FunctionReference<"query", "internal">;
1175
- refreshTokenPatch: FunctionReference<"mutation", "internal">;
1176
- refreshTokenGetChildren: FunctionReference<"query", "internal">;
1177
- refreshTokenListBySession: FunctionReference<"query", "internal">;
1178
- refreshTokenDeleteAll: FunctionReference<"mutation", "internal">;
1179
- refreshTokenGetActive: FunctionReference<"query", "internal">;
1180
- rateLimitGet: FunctionReference<"query", "internal">;
1181
- rateLimitCreate: FunctionReference<"mutation", "internal">;
1182
- rateLimitPatch: FunctionReference<"mutation", "internal">;
1183
- rateLimitDelete: FunctionReference<"mutation", "internal">;
1184
- groupCreate: FunctionReference<"mutation", "internal">;
1185
- groupGet: FunctionReference<"query", "internal">;
1186
- groupList: FunctionReference<"query", "internal">;
1187
- groupUpdate: FunctionReference<"mutation", "internal">;
1188
- groupDelete: FunctionReference<"mutation", "internal">;
1189
- memberAdd: FunctionReference<"mutation", "internal">;
1190
- memberGet: FunctionReference<"query", "internal">;
1191
- memberList: FunctionReference<"query", "internal">;
1192
- memberGetByGroupAndUser: FunctionReference<"query", "internal">;
1193
- memberRemove: FunctionReference<"mutation", "internal">;
1194
- memberUpdate: FunctionReference<"mutation", "internal">;
1195
- inviteCreate: FunctionReference<"mutation", "internal">;
1196
- inviteGet: FunctionReference<"query", "internal">;
1197
- inviteGetByTokenHash: FunctionReference<"query", "internal">;
1198
- inviteList: FunctionReference<"query", "internal">;
1199
- inviteAccept: FunctionReference<"mutation", "internal">;
1200
- inviteAcceptByToken: FunctionReference<"mutation", "internal">;
1201
- inviteRevoke: FunctionReference<"mutation", "internal">;
1202
- keyInsert: FunctionReference<"mutation", "internal">;
1203
- keyGetByHashedKey: FunctionReference<"query", "internal">;
1204
- keyGetById: FunctionReference<"query", "internal">;
1205
- keyList: FunctionReference<"query", "internal">;
1206
- keyPatch: FunctionReference<"mutation", "internal">;
1207
- keyDelete: FunctionReference<"mutation", "internal">;
1208
- passkeyInsert: FunctionReference<"mutation", "internal">;
1209
- passkeyGetById: FunctionReference<"query", "internal">;
1210
- passkeyGetByCredentialId: FunctionReference<"query", "internal">;
1211
- passkeyListByUserId: FunctionReference<"query", "internal">;
1212
- passkeyUpdateCounter: FunctionReference<"mutation", "internal">;
1213
- passkeyUpdateMeta: FunctionReference<"mutation", "internal">;
1214
- passkeyDelete: FunctionReference<"mutation", "internal">;
1215
- totpInsert: FunctionReference<"mutation", "internal", any, any>;
1216
- totpGetVerifiedByUserId: FunctionReference<"query", "internal", any, any>;
1217
- totpListByUserId: FunctionReference<"query", "internal", any, any>;
1218
- totpGetById: FunctionReference<"query", "internal", any, any>;
1219
- totpMarkVerified: FunctionReference<"mutation", "internal", any, any>;
1220
- totpUpdateLastUsed: FunctionReference<"mutation", "internal", any, any>;
1221
- totpDelete: FunctionReference<"mutation", "internal", any, any>;
1222
- deviceInsert: FunctionReference<"mutation", "internal", any, any>;
1223
- deviceGetByCodeHash: FunctionReference<"query", "internal", any, any>;
1224
- deviceGetByUserCode: FunctionReference<"query", "internal", any, any>;
1225
- deviceAuthorize: FunctionReference<"mutation", "internal", any, any>;
1226
- deviceUpdateLastPolled: FunctionReference<"mutation", "internal", any, any>;
1227
- deviceDelete: FunctionReference<"mutation", "internal", any, any>;
1228
- groupConnectionCreate: FunctionReference<"mutation", "internal", any, any>;
1229
- groupConnectionGet: FunctionReference<"query", "internal", any, any>;
1230
- groupConnectionGetByDomain: FunctionReference<"query", "internal", any, any>;
1231
- groupConnectionList: FunctionReference<"query", "internal", any, any>;
1232
- groupConnectionUpdate: FunctionReference<"mutation", "internal", any, any>;
1233
- groupConnectionDelete: FunctionReference<"mutation", "internal", any, any>;
1234
- groupConnectionDomainAdd: FunctionReference<"mutation", "internal", any, any>;
1235
- groupConnectionDomainList: FunctionReference<"query", "internal", any, any>;
1236
- groupConnectionDomainDelete: FunctionReference<"mutation", "internal", any, any>;
1237
- groupConnectionDomainVerificationGet: FunctionReference<"query", "internal", any, any>;
1238
- groupConnectionDomainVerificationUpsert: FunctionReference<"mutation", "internal", any, any>;
1239
- groupConnectionDomainVerificationDelete: FunctionReference<"mutation", "internal", any, any>;
1240
- groupConnectionDomainVerify: FunctionReference<"mutation", "internal", any, any>;
1241
- groupConnectionSecretUpsert: FunctionReference<"mutation", "internal", any, any>;
1242
- groupConnectionSecretGet: FunctionReference<"query", "internal", any, any>;
1243
- groupConnectionSecretDelete: FunctionReference<"mutation", "internal", any, any>;
1244
- groupConnectionScimConfigUpsert: FunctionReference<"mutation", "internal", any, any>;
1245
- groupConnectionScimConfigGetByGroupConnection: FunctionReference<"query", "internal", any, any>;
1246
- groupConnectionScimConfigGetByTokenHash: FunctionReference<"query", "internal", any, any>;
1247
- groupConnectionScimIdentityGet: FunctionReference<"query", "internal", any, any>;
1248
- groupConnectionScimIdentityGetByUser: FunctionReference<"query", "internal", any, any>;
1249
- groupConnectionScimIdentityGetByGroupConnectionAndUser: FunctionReference<"query", "internal", any, any>;
1250
- groupConnectionScimIdentityGetByMappedGroup: FunctionReference<"query", "internal", any, any>;
1251
- groupConnectionScimIdentityListByGroupConnection: FunctionReference<"query", "internal", any, any>;
1252
- groupConnectionScimIdentityUpsert: FunctionReference<"mutation", "internal", any, any>;
1253
- groupConnectionScimIdentityDelete: FunctionReference<"mutation", "internal", any, any>;
1254
- groupAuditEventCreate: FunctionReference<"mutation", "internal", any, any>;
1255
- groupAuditEventList: FunctionReference<"query", "internal", any, any>;
1256
- groupWebhookEndpointCreate: FunctionReference<"mutation", "internal", any, any>;
1257
- groupWebhookEndpointList: FunctionReference<"query", "internal", any, any>;
1258
- groupWebhookEndpointGet: FunctionReference<"query", "internal", any, any>;
1259
- groupWebhookEndpointUpdate: FunctionReference<"mutation", "internal", any, any>;
1260
- groupWebhookDeliveryEnqueue: FunctionReference<"mutation", "internal", any, any>;
1261
- groupWebhookDeliveryListReady: FunctionReference<"query", "internal", any, any>;
1262
- groupWebhookDeliveryPatch: FunctionReference<"mutation", "internal", any, any>;
1160
+ user: {
1161
+ get: FunctionReference<"query", "internal">;
1162
+ list: FunctionReference<"query", "internal">;
1163
+ create: FunctionReference<"mutation", "internal">;
1164
+ upsert: FunctionReference<"mutation", "internal">;
1165
+ update: FunctionReference<"mutation", "internal">;
1166
+ delete: FunctionReference<"mutation", "internal">;
1167
+ email: {
1168
+ list: FunctionReference<"query", "internal">;
1169
+ owner: FunctionReference<"query", "internal">;
1170
+ upsert: FunctionReference<"mutation", "internal">;
1171
+ setPrimary: FunctionReference<"mutation", "internal">;
1172
+ delete: FunctionReference<"mutation", "internal">;
1173
+ };
1174
+ key: {
1175
+ get: FunctionReference<"query", "internal">;
1176
+ list: FunctionReference<"query", "internal">;
1177
+ create: FunctionReference<"mutation", "internal">;
1178
+ update: FunctionReference<"mutation", "internal">;
1179
+ delete: FunctionReference<"mutation", "internal">;
1180
+ };
1181
+ };
1182
+ account: {
1183
+ get: FunctionReference<"query", "internal">;
1184
+ list: FunctionReference<"query", "internal">;
1185
+ create: FunctionReference<"mutation", "internal">;
1186
+ update: FunctionReference<"mutation", "internal">;
1187
+ delete: FunctionReference<"mutation", "internal">;
1188
+ };
1189
+ session: {
1190
+ get: FunctionReference<"query", "internal">;
1191
+ list: FunctionReference<"query", "internal">;
1192
+ create: FunctionReference<"mutation", "internal">;
1193
+ issue: FunctionReference<"mutation", "internal">;
1194
+ delete: FunctionReference<"mutation", "internal">;
1195
+ };
1196
+ token: {
1197
+ refresh: {
1198
+ get: FunctionReference<"query", "internal">;
1199
+ list: FunctionReference<"query", "internal">;
1200
+ listChildren: FunctionReference<"query", "internal">;
1201
+ create: FunctionReference<"mutation", "internal">;
1202
+ update: FunctionReference<"mutation", "internal">;
1203
+ delete: FunctionReference<"mutation", "internal">;
1204
+ exchange: FunctionReference<"mutation", "internal">;
1205
+ };
1206
+ verification: {
1207
+ get: FunctionReference<"query", "internal">;
1208
+ create: FunctionReference<"mutation", "internal">;
1209
+ delete: FunctionReference<"mutation", "internal">;
1210
+ };
1211
+ pkce: {
1212
+ get: FunctionReference<"query", "internal">;
1213
+ create: FunctionReference<"mutation", "internal">;
1214
+ update: FunctionReference<"mutation", "internal">;
1215
+ delete: FunctionReference<"mutation", "internal">;
1216
+ };
1217
+ };
1218
+ rateLimit: {
1219
+ get: FunctionReference<"query", "internal">;
1220
+ create: FunctionReference<"mutation", "internal">;
1221
+ update: FunctionReference<"mutation", "internal">;
1222
+ delete: FunctionReference<"mutation", "internal">;
1223
+ };
1224
+ group: {
1225
+ get: FunctionReference<"query", "internal">;
1226
+ ancestors: FunctionReference<"query", "internal">;
1227
+ list: FunctionReference<"query", "internal">;
1228
+ create: FunctionReference<"mutation", "internal">;
1229
+ update: FunctionReference<"mutation", "internal">;
1230
+ delete: FunctionReference<"mutation", "internal">;
1231
+ member: {
1232
+ get: FunctionReference<"query", "internal">;
1233
+ list: FunctionReference<"query", "internal">;
1234
+ create: FunctionReference<"mutation", "internal">;
1235
+ update: FunctionReference<"mutation", "internal">;
1236
+ delete: FunctionReference<"mutation", "internal">;
1237
+ resolve: FunctionReference<"query", "internal">;
1238
+ };
1239
+ invite: {
1240
+ get: FunctionReference<"query", "internal">;
1241
+ list: FunctionReference<"query", "internal">;
1242
+ create: FunctionReference<"mutation", "internal">;
1243
+ accept: FunctionReference<"mutation", "internal">;
1244
+ redeem: FunctionReference<"mutation", "internal">;
1245
+ revoke: FunctionReference<"mutation", "internal">;
1246
+ };
1247
+ };
1248
+ factor: {
1249
+ passkey: {
1250
+ get: FunctionReference<"query", "internal">;
1251
+ list: FunctionReference<"query", "internal">;
1252
+ create: FunctionReference<"mutation", "internal">;
1253
+ update: FunctionReference<"mutation", "internal">;
1254
+ delete: FunctionReference<"mutation", "internal">;
1255
+ };
1256
+ totp: {
1257
+ get: FunctionReference<"query", "internal">;
1258
+ list: FunctionReference<"query", "internal">;
1259
+ create: FunctionReference<"mutation", "internal">;
1260
+ update: FunctionReference<"mutation", "internal">;
1261
+ delete: FunctionReference<"mutation", "internal">;
1262
+ };
1263
+ device: {
1264
+ get: FunctionReference<"query", "internal">;
1265
+ create: FunctionReference<"mutation", "internal">;
1266
+ authorize: FunctionReference<"mutation", "internal">;
1267
+ update: FunctionReference<"mutation", "internal">;
1268
+ delete: FunctionReference<"mutation", "internal">;
1269
+ };
1270
+ };
1271
+ sso: {
1272
+ connection: {
1273
+ get: FunctionReference<"query", "internal">;
1274
+ list: FunctionReference<"query", "internal">;
1275
+ create: FunctionReference<"mutation", "internal">;
1276
+ update: FunctionReference<"mutation", "internal">;
1277
+ delete: FunctionReference<"mutation", "internal">;
1278
+ domain: {
1279
+ list: FunctionReference<"query", "internal">;
1280
+ create: FunctionReference<"mutation", "internal">;
1281
+ delete: FunctionReference<"mutation", "internal">;
1282
+ verify: FunctionReference<"mutation", "internal">;
1283
+ verification: {
1284
+ get: FunctionReference<"query", "internal">;
1285
+ upsert: FunctionReference<"mutation", "internal">;
1286
+ delete: FunctionReference<"mutation", "internal">;
1287
+ };
1288
+ };
1289
+ secret: {
1290
+ get: FunctionReference<"query", "internal">;
1291
+ upsert: FunctionReference<"mutation", "internal">;
1292
+ delete: FunctionReference<"mutation", "internal">;
1293
+ };
1294
+ scim: {
1295
+ config: {
1296
+ get: FunctionReference<"query", "internal">;
1297
+ upsert: FunctionReference<"mutation", "internal">;
1298
+ };
1299
+ identity: {
1300
+ get: FunctionReference<"query", "internal">;
1301
+ list: FunctionReference<"query", "internal">;
1302
+ upsert: FunctionReference<"mutation", "internal">;
1303
+ delete: FunctionReference<"mutation", "internal">;
1304
+ };
1305
+ };
1306
+ };
1307
+ audit: {
1308
+ list: FunctionReference<"query", "internal">;
1309
+ create: FunctionReference<"mutation", "internal">;
1310
+ };
1311
+ webhook: {
1312
+ endpoint: {
1313
+ get: FunctionReference<"query", "internal">;
1314
+ list: FunctionReference<"query", "internal">;
1315
+ create: FunctionReference<"mutation", "internal">;
1316
+ update: FunctionReference<"mutation", "internal">;
1317
+ };
1318
+ delivery: {
1319
+ list: FunctionReference<"query", "internal">;
1320
+ create: FunctionReference<"mutation", "internal">;
1321
+ update: FunctionReference<"mutation", "internal">;
1322
+ };
1323
+ };
1263
1324
  };
1264
1325
  };
1265
1326
  /**
@@ -1286,5 +1347,5 @@ type SessionTokenIdentityClaims = {
1286
1347
  };
1287
1348
  type KeyDoc = Infer<typeof vApiKeyDoc>;
1288
1349
  //#endregion
1289
- export { AfterCtx, AuthAuthorizationConfig, AuthCallbackContext, AuthCallbackProfile, AuthCallbacks, AuthEvent, AuthGrant, AuthProviderConfig, AuthRoleId, BeforeCtx, BeforeEvent, BeforeResult, ConvexAuthConfig, ConvexAuthMaterializedConfig, ConvexCredentialsConfig, CorsConfig, DeviceProviderConfig, Doc, EmailConfig, EmailUserConfig, GenericActionCtxWithAuthConfig, GenericDoc, GroupConnectionPolicy, GroupConnectionPolicyPatch, HasDeviceProvider, HasPasskeyProvider, HasSSO, HasTotpProvider, HttpKeyContext, KeyDoc, KeyScope, OAuthMaterializedConfig, OAuthProfile, OAuthTokens, OIDCClaimMapping, PasskeyProviderConfig, PhoneConfig, PhoneUserConfig, SSOProviderConfig, ScopeChecker, SessionTokenIdentityClaims, TotpProviderConfig, UserOrderBy, UserWhere };
1350
+ export { AfterCtx, AuthAuthorizationConfig, AuthCallbackContext, AuthCallbackProfile, AuthCallbacks, AuthDataModel, AuthEvent, AuthGrant, AuthProviderConfig, AuthRoleId, BeforeCtx, BeforeEvent, BeforeResult, ConvexAuthConfig, ConvexAuthMaterializedConfig, ConvexCredentialsConfig, CorsConfig, DeviceProviderConfig, Doc, EmailConfig, EmailUserConfig, GenericActionCtxWithAuthConfig, GenericDoc, GroupConnectionPolicy, GroupConnectionPolicyPatch, HasDeviceProvider, HasPasskeyProvider, HasSSO, HasTotpProvider, HttpKeyContext, KeyDoc, KeyScope, OAuthMaterializedConfig, OAuthProfile, OAuthTokens, OIDCClaimMapping, PasskeyProviderConfig, PhoneConfig, PhoneUserConfig, SSOProviderConfig, ScopeChecker, SessionTokenIdentityClaims, TotpProviderConfig, UserOrderBy, UserWhere };
1290
1351
  //# sourceMappingURL=types.d.ts.map
@@ -1,77 +1,82 @@
1
1
  //#region src/server/types.ts
2
2
  async function queryUserById(ctx, userId) {
3
- return await ctx.runQuery(ctx.auth.config.component.public.userGetById, { userId });
3
+ return await ctx.runQuery(ctx.auth.config.component.user.get, { id: userId });
4
4
  }
5
5
  async function queryUserByVerifiedEmail(ctx, email) {
6
- return await ctx.runQuery(ctx.auth.config.component.public.userFindByVerifiedEmail, { email });
6
+ return await ctx.runQuery(ctx.auth.config.component.user.get, { verifiedEmail: email });
7
7
  }
8
8
  async function queryVerifierById(ctx, verifierId) {
9
- return await ctx.runQuery(ctx.auth.config.component.public.verifierGetById, { verifierId });
9
+ return await ctx.runQuery(ctx.auth.config.component.token.pkce.get, { id: verifierId });
10
10
  }
11
11
  async function mutateVerifierDelete(ctx, verifierId) {
12
- await ctx.runMutation(ctx.auth.config.component.public.verifierDelete, { verifierId });
12
+ await ctx.runMutation(ctx.auth.config.component.token.pkce.delete, { verifierId });
13
13
  }
14
14
  async function queryTotpById(ctx, totpId) {
15
- return await ctx.runQuery(ctx.auth.config.component.public.totpGetById, { totpId });
15
+ return await ctx.runQuery(ctx.auth.config.component.factor.totp.get, { id: totpId });
16
16
  }
17
17
  async function queryTotpVerifiedByUserId(ctx, userId) {
18
- return await ctx.runQuery(ctx.auth.config.component.public.totpGetVerifiedByUserId, { userId });
18
+ return await ctx.runQuery(ctx.auth.config.component.factor.totp.get, { verifiedForUserId: userId });
19
19
  }
20
20
  async function mutateTotpInsert(ctx, args) {
21
- return await ctx.runMutation(ctx.auth.config.component.public.totpInsert, args);
21
+ return await ctx.runMutation(ctx.auth.config.component.factor.totp.create, args);
22
22
  }
23
23
  async function mutateTotpMarkVerified(ctx, totpId, lastUsedAt) {
24
- await ctx.runMutation(ctx.auth.config.component.public.totpMarkVerified, {
24
+ await ctx.runMutation(ctx.auth.config.component.factor.totp.update, {
25
25
  totpId,
26
- lastUsedAt
26
+ data: {
27
+ verified: true,
28
+ lastUsedAt
29
+ }
27
30
  });
28
31
  }
29
32
  async function mutateTotpUpdateLastUsed(ctx, totpId, lastUsedAt) {
30
- await ctx.runMutation(ctx.auth.config.component.public.totpUpdateLastUsed, {
33
+ await ctx.runMutation(ctx.auth.config.component.factor.totp.update, {
31
34
  totpId,
32
- lastUsedAt
35
+ data: { lastUsedAt }
33
36
  });
34
37
  }
35
38
  async function queryPasskeysByUserId(ctx, userId) {
36
- return await ctx.runQuery(ctx.auth.config.component.public.passkeyListByUserId, { userId });
39
+ return await ctx.runQuery(ctx.auth.config.component.factor.passkey.list, { userId });
37
40
  }
38
41
  async function queryPasskeyByCredentialId(ctx, credentialId) {
39
- return await ctx.runQuery(ctx.auth.config.component.public.passkeyGetByCredentialId, { credentialId });
42
+ return await ctx.runQuery(ctx.auth.config.component.factor.passkey.get, { credentialId });
40
43
  }
41
44
  async function mutatePasskeyInsert(ctx, args) {
42
- return await ctx.runMutation(ctx.auth.config.component.public.passkeyInsert, args);
45
+ return await ctx.runMutation(ctx.auth.config.component.factor.passkey.create, args);
43
46
  }
44
47
  async function mutatePasskeyUpdateCounter(ctx, passkeyId, counter, lastUsedAt) {
45
- await ctx.runMutation(ctx.auth.config.component.public.passkeyUpdateCounter, {
48
+ await ctx.runMutation(ctx.auth.config.component.factor.passkey.update, {
46
49
  passkeyId,
47
- counter,
48
- lastUsedAt
50
+ data: {
51
+ counter,
52
+ lastUsedAt
53
+ }
49
54
  });
50
55
  }
51
56
  async function mutateDeviceInsert(ctx, args) {
52
- return await ctx.runMutation(ctx.auth.config.component.public.deviceInsert, args);
57
+ return await ctx.runMutation(ctx.auth.config.component.factor.device.create, args);
53
58
  }
54
59
  async function queryDeviceByCodeHash(ctx, deviceCodeHash) {
55
- return await ctx.runQuery(ctx.auth.config.component.public.deviceGetByCodeHash, { deviceCodeHash });
60
+ return await ctx.runQuery(ctx.auth.config.component.factor.device.get, { deviceCodeHash });
56
61
  }
57
62
  async function queryDeviceByUserCode(ctx, userCode) {
58
- return await ctx.runQuery(ctx.auth.config.component.public.deviceGetByUserCode, { userCode });
63
+ return await ctx.runQuery(ctx.auth.config.component.factor.device.get, { userCode });
59
64
  }
60
65
  async function mutateDeviceAuthorize(ctx, deviceId, userId, sessionId) {
61
- await ctx.runMutation(ctx.auth.config.component.public.deviceAuthorize, {
66
+ await ctx.runMutation(ctx.auth.config.component.factor.device.authorize, {
62
67
  deviceId,
63
68
  userId,
64
69
  sessionId
65
70
  });
66
71
  }
67
72
  async function mutateDeviceUpdateLastPolled(ctx, deviceId, lastPolledAt) {
68
- await ctx.runMutation(ctx.auth.config.component.public.deviceUpdateLastPolled, {
73
+ await ctx.runMutation(ctx.auth.config.component.factor.device.update, {
69
74
  deviceId,
70
- lastPolledAt
75
+ data: { lastPolledAt }
71
76
  });
72
77
  }
73
78
  async function mutateDeviceDelete(ctx, deviceId) {
74
- await ctx.runMutation(ctx.auth.config.component.public.deviceDelete, { deviceId });
79
+ await ctx.runMutation(ctx.auth.config.component.factor.device.delete, { deviceId });
75
80
  }
76
81
 
77
82
  //#endregion
@@ -67,6 +67,51 @@ async function checkAllowLink(args, config, userId) {
67
67
  userId
68
68
  }) !== false;
69
69
  }
70
+ /**
71
+ * Persist the emails this sign-in asserts onto the resolved user.
72
+ *
73
+ * The profile's primary email is recorded as the primary `UserEmail`
74
+ * row; any provider-reported secondaries (e.g. GitHub `/user/emails`)
75
+ * are recorded non-primary, each keeping its own verified state.
76
+ * Provenance (`source`, `provider`, `connectionId`) is captured so SSO
77
+ * linking can stay connection-scoped.
78
+ *
79
+ * @param db - The component-backed auth DB facade.
80
+ * @param userId - The resolved (created or linked) user.
81
+ * @param args - The create-or-update args (provider, accountExtend, emails).
82
+ * @param profile - The provisioned profile (already destructured).
83
+ * @param emailVerified - Whether the primary email is verified.
84
+ */
85
+ async function recordOwnedEmails(db, userId, args, profile, emailVerified) {
86
+ const identity = args.accountExtend?.identity;
87
+ const protocol = typeof identity?.protocol === "string" ? identity.protocol : void 0;
88
+ const source = protocol === "saml" ? "saml" : protocol === "oidc" ? "oidc" : args.provider.type === "oauth" ? "oauth" : "password";
89
+ const provider = typeof args.provider.id === "string" ? args.provider.id : void 0;
90
+ const connectionId = typeof identity?.connectionId === "string" ? identity.connectionId : void 0;
91
+ const primaryEmail = typeof profile.email === "string" ? profile.email.toLowerCase() : null;
92
+ if (primaryEmail !== null) await db.emails.upsert({
93
+ userId,
94
+ email: primaryEmail,
95
+ verified: emailVerified,
96
+ isPrimary: true,
97
+ source,
98
+ provider,
99
+ connectionId
100
+ });
101
+ for (const entry of args.emails ?? []) {
102
+ const addr = entry.email.toLowerCase();
103
+ if (addr === primaryEmail) continue;
104
+ await db.emails.upsert({
105
+ userId,
106
+ email: addr,
107
+ verified: entry.verified === true,
108
+ isPrimary: false,
109
+ source,
110
+ provider,
111
+ connectionId
112
+ });
113
+ }
114
+ }
70
115
  async function updateExistingUser(db, userId, userData, source, provisioningUser) {
71
116
  const currentUser = await db.users.getById(userId);
72
117
  const mode = effectiveUserUpdateMode(source, provisioningUser);
@@ -109,8 +154,9 @@ async function defaultCreateOrUpdateUser(ctx, existingSessionId, existingAccount
109
154
  const { provider, profile: { id: _profileId, emailVerified: profileEmailVerified, phoneVerified: profilePhoneVerified, ...profile } } = args;
110
155
  const emailVerified = profileEmailVerified ?? (provider.type === "oauth" && provider.accountLinking !== "none");
111
156
  const phoneVerified = profilePhoneVerified ?? false;
112
- const shouldLinkViaEmail = args.shouldLinkViaEmail || emailVerified || provider.type === "email";
113
- const shouldLinkViaPhone = args.shouldLinkViaPhone || phoneVerified || provider.type === "phone";
157
+ const connectionScopedLinking = provider.type === "oauth" && provider.accountLinking === "sameConnection";
158
+ const shouldLinkViaEmail = !connectionScopedLinking && (args.shouldLinkViaEmail || emailVerified || provider.type === "email");
159
+ const shouldLinkViaPhone = !connectionScopedLinking && (args.shouldLinkViaPhone || phoneVerified || provider.type === "phone");
114
160
  let userId = existingUserId ?? existingUserIdOverride;
115
161
  if (existingUserId === null) {
116
162
  userId = await resolveUserIdByLinking(ctx, args, profile, shouldLinkViaEmail, shouldLinkViaPhone, existingUserIdOverride, config);
@@ -130,6 +176,7 @@ async function defaultCreateOrUpdateUser(ctx, existingSessionId, existingAccount
130
176
  });
131
177
  userId = await db.users.insert(userData);
132
178
  }
179
+ await recordOwnedEmails(db, userId, args, profile, emailVerified === true);
133
180
  const after = config.callbacks?.after;
134
181
  if (after !== void 0) {
135
182
  log(LOG_LEVELS.DEBUG, "Calling `after` callback for user lifecycle event");