@fonoster/identity 0.26.0 → 0.30.0

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 (119) hide show
  1. package/README.md +25 -0
  2. package/dist/allowList.d.ts +4 -0
  3. package/dist/allowList.js +7 -1
  4. package/dist/apikeys/createCreateApiKey.js +16 -0
  5. package/dist/apikeys/createDeleteApiKey.js +22 -2
  6. package/dist/apikeys/createListApiKeys.js +14 -0
  7. package/dist/apikeys/createRegenerateApiKey.js +23 -2
  8. package/dist/config/index.d.ts +20 -0
  9. package/dist/config/index.js +36 -0
  10. package/dist/config/publishedKeys.d.ts +9 -0
  11. package/dist/config/publishedKeys.js +56 -0
  12. package/dist/config/schemas.d.ts +392 -0
  13. package/dist/config/schemas.js +163 -0
  14. package/dist/config/toIdentityConfig.d.ts +19 -0
  15. package/dist/config/toIdentityConfig.js +93 -0
  16. package/dist/constants.d.ts +28 -0
  17. package/dist/constants.js +29 -1
  18. package/dist/exchanges/createExchangeApiKey.js +4 -1
  19. package/dist/exchanges/createExchangeCredentials.d.ts +6 -1
  20. package/dist/exchanges/createExchangeCredentials.js +20 -2
  21. package/dist/exchanges/createExchangeOauth2Code.js +25 -2
  22. package/dist/exchanges/createExchangeRefreshToken.d.ts +9 -1
  23. package/dist/exchanges/createExchangeRefreshToken.js +57 -13
  24. package/dist/exchanges/createExchangeVerificationCode.d.ts +35 -0
  25. package/dist/exchanges/createExchangeVerificationCode.js +95 -0
  26. package/dist/exchanges/createRevokeToken.d.ts +33 -0
  27. package/dist/exchanges/createRevokeToken.js +64 -0
  28. package/dist/exchanges/exchangeTokens.d.ts +3 -1
  29. package/dist/exchanges/exchangeTokens.js +23 -5
  30. package/dist/exchanges/index.d.ts +2 -0
  31. package/dist/exchanges/index.js +2 -0
  32. package/dist/exchanges/payloads/users/createGetIdTokenPayload.js +3 -2
  33. package/dist/exchanges/refreshTokens.d.ts +30 -0
  34. package/dist/exchanges/refreshTokens.js +101 -0
  35. package/dist/exchanges/types.d.ts +53 -2
  36. package/dist/generated/@prisma/client/edge.js +32 -9
  37. package/dist/generated/@prisma/client/index-browser.js +24 -1
  38. package/dist/generated/@prisma/client/index.d.ts +3233 -417
  39. package/dist/generated/@prisma/client/index.js +34 -11
  40. package/dist/generated/@prisma/client/{libquery_engine-darwin-arm64.dylib.node → libquery_engine-debian-openssl-3.0.x.so.node} +0 -0
  41. package/dist/generated/@prisma/client/package.json +1 -1
  42. package/dist/generated/@prisma/client/schema.prisma +47 -7
  43. package/dist/generated/@prisma/client/wasm.js +32 -9
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +1 -0
  46. package/dist/server/config.d.ts +286 -55
  47. package/dist/server/config.js +74 -108
  48. package/dist/server/index.js +5 -3
  49. package/dist/service.d.ts +6 -0
  50. package/dist/service.js +11 -4
  51. package/dist/users/createCreateUser.d.ts +6 -1
  52. package/dist/users/createCreateUser.js +17 -9
  53. package/dist/users/createCreateUserWithOauth2Code.js +19 -15
  54. package/dist/users/createResetPassword.d.ts +5 -0
  55. package/dist/users/createResetPassword.js +33 -7
  56. package/dist/users/createSendResetPasswordCode.d.ts +6 -0
  57. package/dist/users/createSendResetPasswordCode.js +33 -1
  58. package/dist/users/createUpdateUser.d.ts +7 -0
  59. package/dist/users/createUpdateUser.js +41 -8
  60. package/dist/users/createUserFromGitHub.d.ts +40 -0
  61. package/dist/users/createUserFromGitHub.js +27 -0
  62. package/dist/users/index.d.ts +1 -0
  63. package/dist/users/index.js +1 -0
  64. package/dist/users/migratePasswordStorage.d.ts +7 -0
  65. package/dist/users/migratePasswordStorage.js +47 -0
  66. package/dist/users/types.d.ts +3 -1
  67. package/dist/users/upsertDefaultUser.js +6 -14
  68. package/dist/utils/authMethods.d.ts +31 -0
  69. package/dist/utils/authMethods.js +44 -0
  70. package/dist/utils/claimUnverifiedAccount.d.ts +35 -0
  71. package/dist/utils/claimUnverifiedAccount.js +43 -0
  72. package/dist/utils/clientAddress.d.ts +26 -0
  73. package/dist/utils/clientAddress.js +9 -0
  74. package/dist/utils/createGenerateVerificationCode.d.ts +4 -0
  75. package/dist/utils/createGenerateVerificationCode.js +12 -2
  76. package/dist/utils/createGenerateWorkspaceInviteToken.js +3 -0
  77. package/dist/utils/createGetApiKeyByAccessKeyId.d.ts +5 -1
  78. package/dist/utils/createGetApiKeyByAccessKeyId.js +5 -0
  79. package/dist/utils/createGetUserByAccessKeyId.d.ts +3 -1
  80. package/dist/utils/createGetUserByEmail.d.ts +3 -1
  81. package/dist/utils/createGetUserByGitHubEmails.d.ts +41 -0
  82. package/dist/utils/createGetUserByGitHubEmails.js +31 -0
  83. package/dist/utils/createGetUserByWorkspaceAccessKeyId.d.ts +3 -1
  84. package/dist/utils/createIsValidVerificationCode.d.ts +5 -0
  85. package/dist/utils/createIsValidVerificationCode.js +34 -7
  86. package/dist/utils/createSendEmail.d.ts +2 -1
  87. package/dist/utils/createSendEmail.js +17 -0
  88. package/dist/utils/createUpdateMembershipStatus.js +10 -3
  89. package/dist/utils/generateOneTimePassword.d.ts +3 -0
  90. package/dist/utils/generateOneTimePassword.js +25 -0
  91. package/dist/utils/getGitHubUserWithOauth2Code.d.ts +20 -2
  92. package/dist/utils/getGitHubUserWithOauth2Code.js +41 -9
  93. package/dist/utils/isWorkspaceAdminCall.d.ts +8 -0
  94. package/dist/utils/isWorkspaceAdminCall.js +47 -0
  95. package/dist/utils/normalizeContact.d.ts +22 -0
  96. package/dist/utils/normalizeContact.js +28 -0
  97. package/dist/utils/passwords.d.ts +11 -0
  98. package/dist/utils/passwords.js +84 -0
  99. package/dist/utils/rateLimiter.d.ts +20 -0
  100. package/dist/utils/rateLimiter.js +108 -0
  101. package/dist/utils/signInThrottle.d.ts +47 -0
  102. package/dist/utils/signInThrottle.js +90 -0
  103. package/dist/utils/userPasswords.d.ts +25 -0
  104. package/dist/utils/userPasswords.js +98 -0
  105. package/dist/verification/createSendVerificationCode.js +27 -1
  106. package/dist/verification/createVerifyCode.js +10 -0
  107. package/dist/workspaces/createCreateWorkspace.d.ts +7 -1
  108. package/dist/workspaces/createCreateWorkspace.js +41 -5
  109. package/dist/workspaces/createDeleteWorkspace.d.ts +2 -1
  110. package/dist/workspaces/createDeleteWorkspace.js +16 -2
  111. package/dist/workspaces/createInviteUserToWorkspace.js +19 -17
  112. package/dist/workspaces/createResendWorkspaceMembershipInvitation.js +17 -2
  113. package/dist/workspaces/createUpdateWorkspace.js +18 -4
  114. package/dist/workspaces/createWorkspaceDirectory.d.ts +29 -0
  115. package/dist/workspaces/createWorkspaceDirectory.js +42 -0
  116. package/dist/workspaces/index.d.ts +1 -0
  117. package/dist/workspaces/index.js +1 -0
  118. package/package.json +7 -6
  119. package/dist/generated/@prisma/client/runtime/wasm.js +0 -35
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createRefreshTokenStore = createRefreshTokenStore;
13
+ /**
14
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster/fonoster
16
+ *
17
+ * This file is part of Fonoster
18
+ *
19
+ * Licensed under the MIT License (the "License");
20
+ * you may not use this file except in compliance with
21
+ * the License. You may obtain a copy of the License at
22
+ *
23
+ * https://opensource.org/licenses/MIT
24
+ *
25
+ * Unless required by applicable law or agreed to in writing, software
26
+ * distributed under the License is distributed on an "AS IS" BASIS,
27
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28
+ * See the License for the specific language governing permissions and
29
+ * limitations under the License.
30
+ */
31
+ const constants_1 = require("../constants");
32
+ /**
33
+ * Issued refresh tokens, by `jti`. A token is good for one exchange: using it
34
+ * marks it used and the exchange issues the next token in the same family. A
35
+ * token presented again (or after revocation) revokes the whole family, so a
36
+ * stolen token stops working for the thief and the owner alike. A token used
37
+ * moments ago (REFRESH_TOKEN_REUSE_GRACE_MS) may be used again, so two tabs
38
+ * renewing the same session at once don't sign each other out.
39
+ */
40
+ function createRefreshTokenStore(prisma) {
41
+ return {
42
+ record(token) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ // Expired rows are no longer useful; drop this principal's on the way.
45
+ yield prisma.refreshToken.deleteMany({
46
+ where: { accessKeyId: token.accessKeyId, expiresAt: { lt: new Date() } }
47
+ });
48
+ yield prisma.refreshToken.create({ data: token });
49
+ });
50
+ },
51
+ /** Marks `jti` used, once. A second use revokes its family. */
52
+ consume(jti) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ const now = new Date();
55
+ const { count } = yield prisma.refreshToken.updateMany({
56
+ where: {
57
+ jti,
58
+ usedAt: null,
59
+ revokedAt: null,
60
+ expiresAt: { gt: now }
61
+ },
62
+ data: { usedAt: now }
63
+ });
64
+ const row = yield prisma.refreshToken.findUnique({ where: { jti } });
65
+ if (!row) {
66
+ return { status: "unknown" };
67
+ }
68
+ const inGrace = row.usedAt !== null &&
69
+ row.revokedAt === null &&
70
+ row.expiresAt > now &&
71
+ now.getTime() - row.usedAt.getTime() < constants_1.REFRESH_TOKEN_REUSE_GRACE_MS;
72
+ if (count !== 1 && !inGrace) {
73
+ yield this.revokeFamily(row.familyId);
74
+ return { status: "reused" };
75
+ }
76
+ return {
77
+ status: "ok",
78
+ familyId: row.familyId,
79
+ accessKeyId: row.accessKeyId
80
+ };
81
+ });
82
+ },
83
+ revokeFamily(familyId) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ yield prisma.refreshToken.updateMany({
86
+ where: { familyId, revokedAt: null },
87
+ data: { revokedAt: new Date() }
88
+ });
89
+ });
90
+ },
91
+ /** Signs a user or API key out everywhere (password reset, key rotation). */
92
+ revokeAll(accessKeyId) {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ yield prisma.refreshToken.updateMany({
95
+ where: { accessKeyId, revokedAt: null },
96
+ data: { revokedAt: new Date() }
97
+ });
98
+ });
99
+ }
100
+ };
101
+ }
@@ -18,7 +18,42 @@
18
18
  */
19
19
  import { Validators as V } from "@fonoster/common";
20
20
  import { z } from "zod";
21
+ /** A workspace as the control plane's regions code reads it. */
22
+ type RegionWorkspace = {
23
+ ref: string;
24
+ accessKeyId: string;
25
+ name: string;
26
+ ownerRef: string;
27
+ region: string;
28
+ };
29
+ /**
30
+ * Workspace ↔ region binding (add-private-regions PR-1, PR-14, PR-15), provided by the control
31
+ * plane. Without it every workspace is on the default public region.
32
+ */
33
+ type WorkspaceRegionHooks = {
34
+ publicRegions: string[];
35
+ defaultRegion: string;
36
+ /**
37
+ * The `region` to store for what the caller picked (an offered public id, or one of the
38
+ * caller's private regions by id or ref); throws (status 400) for anything else.
39
+ */
40
+ resolveRegion(ownerRef: string, requested?: string): Promise<{
41
+ region: string;
42
+ }>;
43
+ /** A workspace joined (created) or left (deleted) a region. */
44
+ workspaceChanged(workspace: {
45
+ accessKeyId: string;
46
+ region: string;
47
+ }): void;
48
+ /** Identity hands the control plane read access to its workspaces. */
49
+ attachDirectory?(directory: {
50
+ workspace(accessKeyId: string): Promise<RegionWorkspace | undefined>;
51
+ inRegion(region: string): Promise<RegionWorkspace[]>;
52
+ }): void;
53
+ };
21
54
  type IdentityConfig = {
55
+ /** Workspace regions (control plane); absent means the default public region only. */
56
+ regions?: WorkspaceRegionHooks;
22
57
  dbUrl: string;
23
58
  issuer: string;
24
59
  audience: string;
@@ -31,9 +66,16 @@ type IdentityConfig = {
31
66
  workspaceInviteExpiration: string;
32
67
  workspaceInviteUrl: string;
33
68
  workspaceInviteFailUrl: string;
69
+ /**
70
+ * The page password-reset emails link to (`?token=…` is appended). Built
71
+ * from configuration, never from the request. Defaults to
72
+ * `<issuer>/reset-password`.
73
+ */
74
+ resetPasswordUrl?: string;
34
75
  contactVerificationRequired: boolean;
35
76
  twoFactorAuthenticationRequired: boolean;
36
- smtpConfig: {
77
+ /** Absent when outgoing email isn't configured; sending email then fails clearly. */
78
+ smtpConfig?: {
37
79
  sender: string;
38
80
  host: string;
39
81
  port: number;
@@ -51,6 +93,15 @@ type IdentityConfig = {
51
93
  githubOauth2Config?: {
52
94
  clientId: string;
53
95
  clientSecret: string;
96
+ /** Defaults to https://github.com. */
97
+ url?: string;
98
+ /** Defaults to https://api.github.com. */
99
+ apiUrl?: string;
100
+ };
101
+ /** Sign-in methods and sign-up policy, from features.auth. */
102
+ auth: {
103
+ methods: Array<"password" | "email_code" | "github">;
104
+ signup: "invite" | "open";
54
105
  };
55
106
  };
56
107
  type ExchangeApiKeysRequest = z.infer<typeof V.exchangeApiKeysRequestSchema>;
@@ -62,4 +113,4 @@ type ExchangeResponse = {
62
113
  refreshToken: string;
63
114
  };
64
115
  type ExchangeRefreshTokenRequest = z.infer<typeof V.exchangeRefreshTokenRequestSchema>;
65
- export { ExchangeApiKeysRequest, ExchangeCredentialsRequest, ExchangeOauth2CodeRequest, ExchangeRefreshTokenRequest, ExchangeResponse, IdentityConfig };
116
+ export { RegionWorkspace, WorkspaceRegionHooks, ExchangeApiKeysRequest, ExchangeCredentialsRequest, ExchangeOauth2CodeRequest, ExchangeRefreshTokenRequest, ExchangeResponse, IdentityConfig };
@@ -100,6 +100,8 @@ exports.Prisma.UserScalarFieldEnum = {
100
100
  email: 'email',
101
101
  emailVerified: 'emailVerified',
102
102
  password: 'password',
103
+ passwordDigest: 'passwordDigest',
104
+ mustChangePassword: 'mustChangePassword',
103
105
  phoneNumber: 'phoneNumber',
104
106
  phoneNumberVerified: 'phoneNumberVerified',
105
107
  avatar: 'avatar',
@@ -112,6 +114,7 @@ exports.Prisma.WorkspaceScalarFieldEnum = {
112
114
  ref: 'ref',
113
115
  accessKeyId: 'accessKeyId',
114
116
  name: 'name',
117
+ region: 'region',
115
118
  createdAt: 'createdAt',
116
119
  updatedAt: 'updatedAt',
117
120
  ownerRef: 'ownerRef'
@@ -138,12 +141,30 @@ exports.Prisma.ApiKeyScalarFieldEnum = {
138
141
  workspaceRef: 'workspaceRef'
139
142
  };
140
143
 
144
+ exports.Prisma.RateLimitWindowScalarFieldEnum = {
145
+ key: 'key',
146
+ startedAt: 'startedAt',
147
+ count: 'count'
148
+ };
149
+
141
150
  exports.Prisma.VerificationCodeScalarFieldEnum = {
142
151
  ref: 'ref',
143
152
  type: 'type',
144
153
  code: 'code',
145
154
  value: 'value',
146
155
  expiresAt: 'expiresAt',
156
+ attempts: 'attempts',
157
+ consumedAt: 'consumedAt',
158
+ createdAt: 'createdAt'
159
+ };
160
+
161
+ exports.Prisma.RefreshTokenScalarFieldEnum = {
162
+ jti: 'jti',
163
+ familyId: 'familyId',
164
+ accessKeyId: 'accessKeyId',
165
+ expiresAt: 'expiresAt',
166
+ usedAt: 'usedAt',
167
+ revokedAt: 'revokedAt',
147
168
  createdAt: 'createdAt'
148
169
  };
149
170
 
@@ -194,7 +215,9 @@ exports.Prisma.ModelName = {
194
215
  Workspace: 'Workspace',
195
216
  WorkspaceMember: 'WorkspaceMember',
196
217
  ApiKey: 'ApiKey',
197
- VerificationCode: 'VerificationCode'
218
+ RateLimitWindow: 'RateLimitWindow',
219
+ VerificationCode: 'VerificationCode',
220
+ RefreshToken: 'RefreshToken'
198
221
  };
199
222
  /**
200
223
  * Create the Client
@@ -207,7 +230,7 @@ const config = {
207
230
  "value": "prisma-client-js"
208
231
  },
209
232
  "output": {
210
- "value": "/Users/psanders/Projects/fonoster/mods/identity/src/generated/@prisma/client",
233
+ "value": "/home/runner/work/fonoster/fonoster/mods/identity/src/generated/@prisma/client",
211
234
  "fromEnvVar": null
212
235
  },
213
236
  "config": {
@@ -216,17 +239,16 @@ const config = {
216
239
  "binaryTargets": [
217
240
  {
218
241
  "fromEnvVar": null,
219
- "value": "darwin-arm64",
242
+ "value": "debian-openssl-3.0.x",
220
243
  "native": true
221
244
  }
222
245
  ],
223
246
  "previewFeatures": [],
224
- "sourceFilePath": "/Users/psanders/Projects/fonoster/mods/identity/schema.prisma",
247
+ "sourceFilePath": "/home/runner/work/fonoster/fonoster/mods/identity/schema.prisma",
225
248
  "isCustomOutput": true
226
249
  },
227
250
  "relativeEnvPaths": {
228
- "rootEnvPath": null,
229
- "schemaEnvPath": "../../../../../../.env"
251
+ "rootEnvPath": null
230
252
  },
231
253
  "relativePath": "../../../..",
232
254
  "clientVersion": "6.19.3",
@@ -236,6 +258,7 @@ const config = {
236
258
  ],
237
259
  "activeProvider": "postgresql",
238
260
  "postinstall": false,
261
+ "ciName": "GitHub Actions",
239
262
  "inlineDatasources": {
240
263
  "db": {
241
264
  "url": {
@@ -244,13 +267,13 @@ const config = {
244
267
  }
245
268
  }
246
269
  },
247
- "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"src/generated/@prisma/client\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"APISERVER_IDENTITY_DATABASE_URL\")\n}\n\nmodel User {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n name String @db.VarChar(60)\n email String @unique @db.VarChar(255)\n emailVerified Boolean @default(false) @map(\"email_verified\")\n password String @map(\"password_hash\") /// @encrypted\n phoneNumber String? @map(\"phone_number\") @db.VarChar(20)\n phoneNumberVerified Boolean @default(false) @map(\"phone_number_verified\")\n avatar String? @db.VarChar(255)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n extended Json?\n\n // Relations\n ownedWorkspaces Workspace[] // Workspaces owned by the user\n memberships WorkspaceMember[] // Workspaces the user is a member of\n\n // Indexes and maps\n @@index([email], type: Hash)\n @@index([accessKeyId], type: Hash)\n @@map(\"users\")\n}\n\nmodel Workspace {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n name String @db.VarChar(60)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n\n // Relations\n owner User @relation(fields: [ownerRef], references: [ref], onDelete: Cascade)\n ownerRef String @map(\"owner_ref\")\n members WorkspaceMember[]\n apiKeys ApiKey[]\n\n // Indexes and maps\n @@index([accessKeyId], type: Hash)\n @@index([ownerRef], type: Hash)\n @@map(\"workspaces\")\n}\n\nmodel WorkspaceMember {\n ref String @id @default(uuid())\n status WorkspaceMemberStatus @default(PENDING)\n role Role @default(WORKSPACE_MEMBER)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n\n // Relations\n user User @relation(fields: [userRef], references: [ref], onDelete: Cascade)\n userRef String @map(\"user_ref\")\n workspace Workspace @relation(fields: [workspaceRef], references: [ref], onDelete: Cascade)\n workspaceRef String @map(\"workspace_ref\")\n\n @@unique([userRef, workspaceRef])\n @@map(\"workspace_members\")\n}\n\nmodel ApiKey {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n accessKeySecret String @map(\"access_key_secret\") @db.VarChar(255) /// @encrypted\n role Role @default(WORKSPACE_MEMBER)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n expiresAt DateTime? @map(\"expires_at\") @db.Timestamptz(3)\n\n // Relations\n workspace Workspace @relation(fields: [workspaceRef], references: [ref], onDelete: Cascade)\n workspaceRef String @map(\"workspace_ref\")\n\n // Indexes and maps\n @@index([accessKeyId], type: Hash)\n @@index([workspaceRef], type: Hash)\n @@map(\"api_keys\")\n}\n\nmodel VerificationCode {\n ref String @id @default(uuid())\n type VerificationType\n code String @db.VarChar(6)\n value String @db.VarChar(255)\n expiresAt DateTime @map(\"expires_at\") @db.Timestamptz(3)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n\n // Indexes and maps\n @@index([code], type: Hash)\n @@map(\"verification_codes\")\n}\n\nenum VerificationType {\n EMAIL\n PHONE\n}\n\nenum WorkspaceMemberStatus {\n PENDING\n ACTIVE\n\n @@map(\"workspace_member_status\")\n}\n\nenum Role {\n USER\n WORKSPACE_ADMIN\n WORKSPACE_OWNER\n WORKSPACE_MEMBER\n\n @@map(\"role\")\n}\n",
248
- "inlineSchemaHash": "3c4034bb83309aca32420626a655f9903a7716403fd270cee2525246f662cb96",
270
+ "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"src/generated/@prisma/client\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"APISERVER_IDENTITY_DATABASE_URL\")\n}\n\nmodel User {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n name String @db.VarChar(60)\n email String @unique @db.VarChar(255)\n emailVerified Boolean @default(false) @map(\"email_verified\")\n /// Legacy reversible storage, cleared once password_digest is written.\n password String? @map(\"password_hash\") /// @encrypted\n /// scrypt digest: scrypt$N$r$p$salt$hash\n passwordDigest String? @map(\"password_digest\") @db.VarChar(255)\n /// Set for invitees holding a one-time password; cleared when they set their own.\n mustChangePassword Boolean @default(false) @map(\"must_change_password\")\n phoneNumber String? @map(\"phone_number\") @db.VarChar(20)\n phoneNumberVerified Boolean @default(false) @map(\"phone_number_verified\")\n avatar String? @db.VarChar(255)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n extended Json?\n\n // Relations\n ownedWorkspaces Workspace[] // Workspaces owned by the user\n memberships WorkspaceMember[] // Workspaces the user is a member of\n\n // Indexes and maps\n @@index([email], type: Hash)\n @@index([accessKeyId], type: Hash)\n @@map(\"users\")\n}\n\nmodel Workspace {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n name String @db.VarChar(60)\n /// A public region id (`default`, `us-east-1`) or a private region ref (rg_…). Immutable.\n region String @default(\"default\") @db.VarChar(64)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n\n // Relations\n owner User @relation(fields: [ownerRef], references: [ref], onDelete: Cascade)\n ownerRef String @map(\"owner_ref\")\n members WorkspaceMember[]\n apiKeys ApiKey[]\n\n // Indexes and maps\n @@index([accessKeyId], type: Hash)\n @@index([ownerRef], type: Hash)\n @@map(\"workspaces\")\n}\n\nmodel WorkspaceMember {\n ref String @id @default(uuid())\n status WorkspaceMemberStatus @default(PENDING)\n role Role @default(WORKSPACE_MEMBER)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n\n // Relations\n user User @relation(fields: [userRef], references: [ref], onDelete: Cascade)\n userRef String @map(\"user_ref\")\n workspace Workspace @relation(fields: [workspaceRef], references: [ref], onDelete: Cascade)\n workspaceRef String @map(\"workspace_ref\")\n\n @@unique([userRef, workspaceRef])\n @@map(\"workspace_members\")\n}\n\nmodel ApiKey {\n ref String @id @default(uuid())\n accessKeyId String @unique @map(\"access_key_id\") @db.VarChar(255)\n accessKeySecret String @map(\"access_key_secret\") @db.VarChar(255) /// @encrypted\n role Role @default(WORKSPACE_MEMBER)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n updatedAt DateTime @default(now()) @map(\"updated_at\") @db.Timestamptz(3)\n expiresAt DateTime? @map(\"expires_at\") @db.Timestamptz(3)\n\n // Relations\n workspace Workspace @relation(fields: [workspaceRef], references: [ref], onDelete: Cascade)\n workspaceRef String @map(\"workspace_ref\")\n\n // Indexes and maps\n @@index([accessKeyId], type: Hash)\n @@index([workspaceRef], type: Hash)\n @@map(\"api_keys\")\n}\n\n/// Fixed-window counters of the send and reset limits (verification codes, password resets),\n/// shared by every Identity replica (ST-4). Rows of past windows are pruned.\nmodel RateLimitWindow {\n key String @id @db.VarChar(255)\n startedAt DateTime @map(\"started_at\") @db.Timestamptz(3)\n count Int\n\n @@index([startedAt])\n @@map(\"rate_limit_windows\")\n}\n\nmodel VerificationCode {\n ref String @id @default(uuid())\n type VerificationType\n code String @db.VarChar(6)\n value String @db.VarChar(255)\n expiresAt DateTime @map(\"expires_at\") @db.Timestamptz(3)\n attempts Int @default(0)\n consumedAt DateTime? @map(\"consumed_at\") @db.Timestamptz(3)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n\n // Indexes and maps\n @@index([code], type: Hash)\n @@index([type, value])\n @@map(\"verification_codes\")\n}\n\n/// One issued refresh token. Each is good for a single exchange (rotation); a\n/// second use of the same token revokes its whole family (reuse detection).\nmodel RefreshToken {\n jti String @id @db.VarChar(64)\n /// Every token rotated from the same sign-in shares a family.\n familyId String @map(\"family_id\") @db.VarChar(64)\n /// The user or API key the token was issued to.\n accessKeyId String @map(\"access_key_id\") @db.VarChar(255)\n expiresAt DateTime @map(\"expires_at\") @db.Timestamptz(3)\n usedAt DateTime? @map(\"used_at\") @db.Timestamptz(3)\n revokedAt DateTime? @map(\"revoked_at\") @db.Timestamptz(3)\n createdAt DateTime @default(now()) @map(\"created_at\") @db.Timestamptz(3)\n\n // Indexes and maps\n @@index([familyId])\n @@index([accessKeyId])\n @@map(\"refresh_tokens\")\n}\n\nenum VerificationType {\n EMAIL\n PHONE\n}\n\nenum WorkspaceMemberStatus {\n PENDING\n ACTIVE\n\n @@map(\"workspace_member_status\")\n}\n\nenum Role {\n USER\n WORKSPACE_ADMIN\n WORKSPACE_OWNER\n WORKSPACE_MEMBER\n\n @@map(\"role\")\n}\n",
271
+ "inlineSchemaHash": "3a64b21aca7defddf14d44df5a93bd8aaabe3640888a650ecbd3f16df4ddd4d2",
249
272
  "copyEngine": true
250
273
  }
251
274
  config.dirname = '/'
252
275
 
253
- config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"dbName\":\"users\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"60\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"emailVerified\",\"dbName\":\"email_verified\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"nativeType\":null,\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"dbName\":\"password_hash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"@encrypted\"},{\"name\":\"phoneNumber\",\"dbName\":\"phone_number\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"20\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumberVerified\",\"dbName\":\"phone_number_verified\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"nativeType\":null,\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"avatar\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"extended\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Json\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ownedWorkspaces\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"UserToWorkspace\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"memberships\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"WorkspaceMember\",\"nativeType\":null,\"relationName\":\"UserToWorkspaceMember\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Workspace\":{\"dbName\":\"workspaces\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"60\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"owner\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"nativeType\":null,\"relationName\":\"UserToWorkspace\",\"relationFromFields\":[\"ownerRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ownerRef\",\"dbName\":\"owner_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"members\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"WorkspaceMember\",\"nativeType\":null,\"relationName\":\"WorkspaceToWorkspaceMember\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKeys\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ApiKey\",\"nativeType\":null,\"relationName\":\"ApiKeyToWorkspace\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"WorkspaceMember\":{\"dbName\":\"workspace_members\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"WorkspaceMemberStatus\",\"nativeType\":null,\"default\":\"PENDING\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Role\",\"nativeType\":null,\"default\":\"WORKSPACE_MEMBER\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"nativeType\":null,\"relationName\":\"UserToWorkspaceMember\",\"relationFromFields\":[\"userRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"userRef\",\"dbName\":\"user_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspace\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"WorkspaceToWorkspaceMember\",\"relationFromFields\":[\"workspaceRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspaceRef\",\"dbName\":\"workspace_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"userRef\",\"workspaceRef\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"userRef\",\"workspaceRef\"]}],\"isGenerated\":false},\"ApiKey\":{\"dbName\":\"api_keys\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeySecret\",\"dbName\":\"access_key_secret\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"@encrypted\"},{\"name\":\"role\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Role\",\"nativeType\":null,\"default\":\"WORKSPACE_MEMBER\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiresAt\",\"dbName\":\"expires_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspace\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"ApiKeyToWorkspace\",\"relationFromFields\":[\"workspaceRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspaceRef\",\"dbName\":\"workspace_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"VerificationCode\":{\"dbName\":\"verification_codes\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"VerificationType\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"6\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiresAt\",\"dbName\":\"expires_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"VerificationType\":{\"values\":[{\"name\":\"EMAIL\",\"dbName\":null},{\"name\":\"PHONE\",\"dbName\":null}],\"dbName\":null},\"WorkspaceMemberStatus\":{\"values\":[{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null}],\"dbName\":\"workspace_member_status\"},\"Role\":{\"values\":[{\"name\":\"USER\",\"dbName\":null},{\"name\":\"WORKSPACE_ADMIN\",\"dbName\":null},{\"name\":\"WORKSPACE_OWNER\",\"dbName\":null},{\"name\":\"WORKSPACE_MEMBER\",\"dbName\":null}],\"dbName\":\"role\"}},\"types\":{}}")
276
+ config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"dbName\":\"users\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"60\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"emailVerified\",\"dbName\":\"email_verified\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"nativeType\":null,\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"dbName\":\"password_hash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"Legacy reversible storage, cleared once password_digest is written.\\\\n@encrypted\"},{\"name\":\"passwordDigest\",\"dbName\":\"password_digest\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"scrypt digest: scrypt$N$r$p$salt$hash\"},{\"name\":\"mustChangePassword\",\"dbName\":\"must_change_password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"nativeType\":null,\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"Set for invitees holding a one-time password; cleared when they set their own.\"},{\"name\":\"phoneNumber\",\"dbName\":\"phone_number\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"20\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumberVerified\",\"dbName\":\"phone_number_verified\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"nativeType\":null,\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"avatar\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"extended\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Json\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ownedWorkspaces\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"UserToWorkspace\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"memberships\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"WorkspaceMember\",\"nativeType\":null,\"relationName\":\"UserToWorkspaceMember\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Workspace\":{\"dbName\":\"workspaces\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"60\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"region\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"64\"]],\"default\":\"default\",\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"A public region id (`default`, `us-east-1`) or a private region ref (rg_…). Immutable.\"},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"owner\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"nativeType\":null,\"relationName\":\"UserToWorkspace\",\"relationFromFields\":[\"ownerRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ownerRef\",\"dbName\":\"owner_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"members\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"WorkspaceMember\",\"nativeType\":null,\"relationName\":\"WorkspaceToWorkspaceMember\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKeys\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ApiKey\",\"nativeType\":null,\"relationName\":\"ApiKeyToWorkspace\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"WorkspaceMember\":{\"dbName\":\"workspace_members\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"WorkspaceMemberStatus\",\"nativeType\":null,\"default\":\"PENDING\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Role\",\"nativeType\":null,\"default\":\"WORKSPACE_MEMBER\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"nativeType\":null,\"relationName\":\"UserToWorkspaceMember\",\"relationFromFields\":[\"userRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"userRef\",\"dbName\":\"user_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspace\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"WorkspaceToWorkspaceMember\",\"relationFromFields\":[\"workspaceRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspaceRef\",\"dbName\":\"workspace_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"userRef\",\"workspaceRef\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"userRef\",\"workspaceRef\"]}],\"isGenerated\":false},\"ApiKey\":{\"dbName\":\"api_keys\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accessKeySecret\",\"dbName\":\"access_key_secret\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"@encrypted\"},{\"name\":\"role\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Role\",\"nativeType\":null,\"default\":\"WORKSPACE_MEMBER\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"dbName\":\"updated_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiresAt\",\"dbName\":\"expires_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspace\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Workspace\",\"nativeType\":null,\"relationName\":\"ApiKeyToWorkspace\",\"relationFromFields\":[\"workspaceRef\"],\"relationToFields\":[\"ref\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"workspaceRef\",\"dbName\":\"workspace_ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"RateLimitWindow\":{\"dbName\":\"rate_limit_windows\",\"schema\":null,\"fields\":[{\"name\":\"key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"startedAt\",\"dbName\":\"started_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"count\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false,\"documentation\":\"Fixed-window counters of the send and reset limits (verification codes, password resets),\\\\nshared by every Identity replica (ST-4). Rows of past windows are pruned.\"},\"VerificationCode\":{\"dbName\":\"verification_codes\",\"schema\":null,\"fields\":[{\"name\":\"ref\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"nativeType\":null,\"default\":{\"name\":\"uuid\",\"args\":[4]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"VerificationType\",\"nativeType\":null,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"6\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiresAt\",\"dbName\":\"expires_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"attempts\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"nativeType\":null,\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"consumedAt\",\"dbName\":\"consumed_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"RefreshToken\":{\"dbName\":\"refresh_tokens\",\"schema\":null,\"fields\":[{\"name\":\"jti\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"64\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"familyId\",\"dbName\":\"family_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"64\"]],\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"Every token rotated from the same sign-in shares a family.\"},{\"name\":\"accessKeyId\",\"dbName\":\"access_key_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"nativeType\":[\"VarChar\",[\"255\"]],\"isGenerated\":false,\"isUpdatedAt\":false,\"documentation\":\"The user or API key the token was issued to.\"},{\"name\":\"expiresAt\",\"dbName\":\"expires_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"usedAt\",\"dbName\":\"used_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"revokedAt\",\"dbName\":\"revoked_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"dbName\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"nativeType\":[\"Timestamptz\",[\"3\"]],\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false,\"documentation\":\"One issued refresh token. Each is good for a single exchange (rotation); a\\\\nsecond use of the same token revokes its whole family (reuse detection).\"}},\"enums\":{\"VerificationType\":{\"values\":[{\"name\":\"EMAIL\",\"dbName\":null},{\"name\":\"PHONE\",\"dbName\":null}],\"dbName\":null},\"WorkspaceMemberStatus\":{\"values\":[{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null}],\"dbName\":\"workspace_member_status\"},\"Role\":{\"values\":[{\"name\":\"USER\",\"dbName\":null},{\"name\":\"WORKSPACE_ADMIN\",\"dbName\":null},{\"name\":\"WORKSPACE_OWNER\",\"dbName\":null},{\"name\":\"WORKSPACE_MEMBER\",\"dbName\":null}],\"dbName\":\"role\"}},\"types\":{}}")
254
277
  defineDmmfProperty(exports.Prisma, config.runtimeDataModel)
255
278
  config.engineWasm = undefined
256
279
  config.compilerWasm = undefined
@@ -128,6 +128,8 @@ exports.Prisma.UserScalarFieldEnum = {
128
128
  email: 'email',
129
129
  emailVerified: 'emailVerified',
130
130
  password: 'password',
131
+ passwordDigest: 'passwordDigest',
132
+ mustChangePassword: 'mustChangePassword',
131
133
  phoneNumber: 'phoneNumber',
132
134
  phoneNumberVerified: 'phoneNumberVerified',
133
135
  avatar: 'avatar',
@@ -140,6 +142,7 @@ exports.Prisma.WorkspaceScalarFieldEnum = {
140
142
  ref: 'ref',
141
143
  accessKeyId: 'accessKeyId',
142
144
  name: 'name',
145
+ region: 'region',
143
146
  createdAt: 'createdAt',
144
147
  updatedAt: 'updatedAt',
145
148
  ownerRef: 'ownerRef'
@@ -166,12 +169,30 @@ exports.Prisma.ApiKeyScalarFieldEnum = {
166
169
  workspaceRef: 'workspaceRef'
167
170
  };
168
171
 
172
+ exports.Prisma.RateLimitWindowScalarFieldEnum = {
173
+ key: 'key',
174
+ startedAt: 'startedAt',
175
+ count: 'count'
176
+ };
177
+
169
178
  exports.Prisma.VerificationCodeScalarFieldEnum = {
170
179
  ref: 'ref',
171
180
  type: 'type',
172
181
  code: 'code',
173
182
  value: 'value',
174
183
  expiresAt: 'expiresAt',
184
+ attempts: 'attempts',
185
+ consumedAt: 'consumedAt',
186
+ createdAt: 'createdAt'
187
+ };
188
+
189
+ exports.Prisma.RefreshTokenScalarFieldEnum = {
190
+ jti: 'jti',
191
+ familyId: 'familyId',
192
+ accessKeyId: 'accessKeyId',
193
+ expiresAt: 'expiresAt',
194
+ usedAt: 'usedAt',
195
+ revokedAt: 'revokedAt',
175
196
  createdAt: 'createdAt'
176
197
  };
177
198
 
@@ -222,7 +243,9 @@ exports.Prisma.ModelName = {
222
243
  Workspace: 'Workspace',
223
244
  WorkspaceMember: 'WorkspaceMember',
224
245
  ApiKey: 'ApiKey',
225
- VerificationCode: 'VerificationCode'
246
+ RateLimitWindow: 'RateLimitWindow',
247
+ VerificationCode: 'VerificationCode',
248
+ RefreshToken: 'RefreshToken'
226
249
  };
227
250
 
228
251
  /**