create-authhero 0.6.0 → 0.8.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.
@@ -0,0 +1,845 @@
1
+ /**
2
+ * AuthHero Database Schema for Cloudflare D1
3
+ *
4
+ * This schema is used by Drizzle Kit to generate migrations.
5
+ * Runtime queries use the @authhero/kysely-adapter.
6
+ *
7
+ * To add custom tables or modify the schema:
8
+ * 1. Edit this file
9
+ * 2. Run: npm run db:generate
10
+ * 3. Run: npm run db:migrate:local (or db:migrate:remote)
11
+ */
12
+
13
+ import { sqliteTable, text, integer, primaryKey, uniqueIndex, index } from "drizzle-orm/sqlite-core";
14
+
15
+ // ============================================================================
16
+ // TENANTS
17
+ // ============================================================================
18
+
19
+ export const tenants = sqliteTable("tenants", {
20
+ id: text("id", { length: 255 }).primaryKey(),
21
+ name: text("name", { length: 255 }),
22
+ audience: text("audience", { length: 255 }),
23
+ sender_email: text("sender_email", { length: 255 }),
24
+ sender_name: text("sender_name", { length: 255 }),
25
+ language: text("language", { length: 255 }),
26
+ logo: text("logo", { length: 255 }),
27
+ primary_color: text("primary_color", { length: 255 }),
28
+ secondary_color: text("secondary_color", { length: 255 }),
29
+ created_at: text("created_at", { length: 255 }).notNull(),
30
+ updated_at: text("updated_at", { length: 255 }).notNull(),
31
+ support_url: text("support_url", { length: 255 }),
32
+ idle_session_lifetime: integer("idle_session_lifetime"),
33
+ session_lifetime: integer("session_lifetime"),
34
+ session_cookie: text("session_cookie"),
35
+ allowed_logout_urls: text("allowed_logout_urls"),
36
+ ephemeral_session_lifetime: integer("ephemeral_session_lifetime"),
37
+ idle_ephemeral_session_lifetime: integer("idle_ephemeral_session_lifetime"),
38
+ default_redirection_uri: text("default_redirection_uri"),
39
+ enabled_locales: text("enabled_locales"),
40
+ default_directory: text("default_directory", { length: 255 }),
41
+ error_page: text("error_page"),
42
+ flags: text("flags"),
43
+ friendly_name: text("friendly_name", { length: 255 }),
44
+ picture_url: text("picture_url"),
45
+ support_email: text("support_email", { length: 255 }),
46
+ sandbox_version: text("sandbox_version", { length: 50 }),
47
+ sandbox_versions_available: text("sandbox_versions_available"),
48
+ legacy_sandbox_version: text("legacy_sandbox_version", { length: 50 }),
49
+ change_password: text("change_password"),
50
+ guardian_mfa_page: text("guardian_mfa_page"),
51
+ device_flow: text("device_flow"),
52
+ default_token_quota: text("default_token_quota"),
53
+ default_audience: text("default_audience", { length: 255 }),
54
+ default_organization: text("default_organization", { length: 255 }),
55
+ sessions: text("sessions"),
56
+ oidc_logout: text("oidc_logout"),
57
+ allow_organization_name_in_authentication_api: integer("allow_organization_name_in_authentication_api"),
58
+ customize_mfa_in_postlogin_action: integer("customize_mfa_in_postlogin_action"),
59
+ acr_values_supported: text("acr_values_supported"),
60
+ mtls: text("mtls"),
61
+ pushed_authorization_requests_supported: integer("pushed_authorization_requests_supported"),
62
+ authorization_response_iss_parameter_supported: integer("authorization_response_iss_parameter_supported"),
63
+ });
64
+
65
+ // ============================================================================
66
+ // USERS
67
+ // ============================================================================
68
+
69
+ export const users = sqliteTable("users", {
70
+ user_id: text("user_id", { length: 255 }).notNull(),
71
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
72
+ email: text("email", { length: 255 }),
73
+ given_name: text("given_name", { length: 255 }),
74
+ family_name: text("family_name", { length: 255 }),
75
+ nickname: text("nickname", { length: 255 }),
76
+ name: text("name", { length: 255 }),
77
+ picture: text("picture", { length: 2083 }),
78
+ tags: text("tags", { length: 255 }),
79
+ phone_number: text("phone_number", { length: 17 }),
80
+ phone_verified: integer("phone_verified", { mode: "boolean" }),
81
+ username: text("username", { length: 128 }),
82
+ created_at: text("created_at", { length: 255 }).notNull(),
83
+ updated_at: text("updated_at", { length: 255 }).notNull(),
84
+ linked_to: text("linked_to", { length: 255 }),
85
+ last_ip: text("last_ip", { length: 255 }),
86
+ login_count: integer("login_count").notNull(),
87
+ last_login: text("last_login", { length: 255 }),
88
+ provider: text("provider", { length: 255 }).notNull(),
89
+ connection: text("connection", { length: 255 }),
90
+ email_verified: integer("email_verified", { mode: "boolean" }).notNull(),
91
+ is_social: integer("is_social", { mode: "boolean" }).notNull(),
92
+ app_metadata: text("app_metadata", { length: 4096 }).notNull().default("{}"),
93
+ user_metadata: text("user_metadata", { length: 4096 }).notNull().default("{}"),
94
+ profileData: text("profileData", { length: 2048 }),
95
+ locale: text("locale", { length: 255 }),
96
+ }, (table) => [
97
+ primaryKey({ columns: [table.user_id, table.tenant_id], name: "users_tenants" }),
98
+ uniqueIndex("unique_email_provider").on(table.email, table.provider, table.tenant_id),
99
+ uniqueIndex("unique_phone_provider").on(table.phone_number, table.provider, table.tenant_id),
100
+ index("users_email_index").on(table.email),
101
+ index("users_linked_to_index").on(table.linked_to),
102
+ index("users_name_index").on(table.name),
103
+ index("users_phone_tenant_provider_index").on(table.tenant_id, table.phone_number, table.provider),
104
+ ]);
105
+
106
+ export const passwords = sqliteTable("passwords", {
107
+ id: text("id", { length: 21 }).primaryKey(),
108
+ tenant_id: text("tenant_id", { length: 255 }).notNull(),
109
+ user_id: text("user_id", { length: 255 }).notNull(),
110
+ created_at: text("created_at", { length: 255 }).notNull(),
111
+ updated_at: text("updated_at", { length: 255 }).notNull(),
112
+ password: text("password", { length: 255 }).notNull(),
113
+ algorithm: text("algorithm", { length: 16 }).notNull().default("bcrypt"),
114
+ is_current: integer("is_current").notNull().default(1),
115
+ });
116
+
117
+ export const passwordHistory = sqliteTable("password_history", {
118
+ id: text("id", { length: 21 }).primaryKey(),
119
+ user_id: text("user_id", { length: 191 }).notNull(),
120
+ tenant_id: text("tenant_id", { length: 191 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
121
+ password: text("password", { length: 255 }).notNull(),
122
+ algorithm: text("algorithm", { length: 255 }).notNull().default("bcrypt"),
123
+ created_at: text("created_at", { length: 35 }).notNull(),
124
+ updated_at: text("updated_at", { length: 35 }).notNull(),
125
+ is_current: integer("is_current").notNull().default(1),
126
+ });
127
+
128
+ // ============================================================================
129
+ // CLIENTS
130
+ // ============================================================================
131
+
132
+ export const clients = sqliteTable("clients", {
133
+ client_id: text("client_id", { length: 191 }).notNull(),
134
+ tenant_id: text("tenant_id", { length: 191 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
135
+ name: text("name", { length: 255 }).notNull(),
136
+ description: text("description", { length: 140 }),
137
+ global: integer("global").notNull().default(0),
138
+ client_secret: text("client_secret", { length: 255 }),
139
+ app_type: text("app_type", { length: 64 }).default("regular_web"),
140
+ logo_uri: text("logo_uri", { length: 2083 }),
141
+ is_first_party: integer("is_first_party").notNull().default(0),
142
+ oidc_conformant: integer("oidc_conformant").notNull().default(1),
143
+ callbacks: text("callbacks").notNull(),
144
+ allowed_origins: text("allowed_origins").notNull(),
145
+ web_origins: text("web_origins").notNull(),
146
+ client_aliases: text("client_aliases").notNull(),
147
+ allowed_clients: text("allowed_clients").notNull(),
148
+ allowed_logout_urls: text("allowed_logout_urls").notNull(),
149
+ session_transfer: text("session_transfer").notNull(),
150
+ oidc_logout: text("oidc_logout").notNull(),
151
+ grant_types: text("grant_types").notNull(),
152
+ jwt_configuration: text("jwt_configuration").notNull(),
153
+ signing_keys: text("signing_keys").notNull(),
154
+ encryption_key: text("encryption_key").notNull(),
155
+ sso: integer("sso").notNull().default(0),
156
+ sso_disabled: integer("sso_disabled").notNull().default(1),
157
+ cross_origin_authentication: integer("cross_origin_authentication").notNull().default(0),
158
+ cross_origin_loc: text("cross_origin_loc", { length: 2083 }),
159
+ custom_login_page_on: integer("custom_login_page_on").notNull().default(0),
160
+ custom_login_page: text("custom_login_page"),
161
+ custom_login_page_preview: text("custom_login_page_preview"),
162
+ form_template: text("form_template"),
163
+ addons: text("addons").notNull(),
164
+ token_endpoint_auth_method: text("token_endpoint_auth_method", { length: 64 }).default("client_secret_basic"),
165
+ client_metadata: text("client_metadata").notNull(),
166
+ mobile: text("mobile").notNull(),
167
+ initiate_login_uri: text("initiate_login_uri", { length: 2083 }),
168
+ native_social_login: text("native_social_login").notNull(),
169
+ refresh_token: text("refresh_token").notNull(),
170
+ default_organization: text("default_organization").notNull(),
171
+ organization_usage: text("organization_usage", { length: 32 }).default("deny"),
172
+ organization_require_behavior: text("organization_require_behavior", { length: 32 }).default("no_prompt"),
173
+ client_authentication_methods: text("client_authentication_methods").notNull(),
174
+ require_pushed_authorization_requests: integer("require_pushed_authorization_requests").notNull().default(0),
175
+ require_proof_of_possession: integer("require_proof_of_possession").notNull().default(0),
176
+ signed_request_object: text("signed_request_object").notNull(),
177
+ compliance_level: text("compliance_level", { length: 64 }),
178
+ par_request_expiry: integer("par_request_expiry"),
179
+ token_quota: text("token_quota").notNull(),
180
+ created_at: text("created_at", { length: 35 }).notNull(),
181
+ updated_at: text("updated_at", { length: 35 }).notNull(),
182
+ connections: text("connections").notNull().default("[]"),
183
+ }, (table) => [
184
+ primaryKey({ columns: [table.tenant_id, table.client_id], name: "clients_tenant_id_client_id" }),
185
+ ]);
186
+
187
+ export const clientGrants = sqliteTable("client_grants", {
188
+ id: text("id", { length: 21 }).notNull(),
189
+ tenant_id: text("tenant_id", { length: 191 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
190
+ client_id: text("client_id", { length: 191 }).notNull(),
191
+ audience: text("audience", { length: 191 }).notNull(),
192
+ scope: text("scope").default("[]"),
193
+ organization_usage: text("organization_usage", { length: 32 }),
194
+ allow_any_organization: integer("allow_any_organization").default(0),
195
+ is_system: integer("is_system").default(0),
196
+ subject_type: text("subject_type", { length: 32 }),
197
+ authorization_details_types: text("authorization_details_types").default("[]"),
198
+ created_at: text("created_at", { length: 35 }).notNull(),
199
+ updated_at: text("updated_at", { length: 35 }).notNull(),
200
+ }, (table) => [
201
+ primaryKey({ columns: [table.tenant_id, table.id], name: "pk_client_grants" }),
202
+ index("idx_client_grants_audience").on(table.audience),
203
+ ]);
204
+
205
+ // ============================================================================
206
+ // CONNECTIONS
207
+ // ============================================================================
208
+
209
+ export const connections = sqliteTable("connections", {
210
+ id: text("id", { length: 255 }).primaryKey(),
211
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
212
+ name: text("name", { length: 255 }).notNull(),
213
+ response_type: text("response_type", { length: 255 }),
214
+ response_mode: text("response_mode", { length: 255 }),
215
+ strategy: text("strategy", { length: 64 }),
216
+ options: text("options", { length: 2048 }).notNull().default("{}"),
217
+ created_at: text("created_at", { length: 255 }).notNull(),
218
+ updated_at: text("updated_at", { length: 255 }).notNull(),
219
+ display_name: text("display_name", { length: 255 }),
220
+ is_domain_connection: integer("is_domain_connection"),
221
+ show_as_button: integer("show_as_button"),
222
+ metadata: text("metadata", { length: 4096 }),
223
+ }, (table) => [
224
+ index("connections_tenant_id_index").on(table.tenant_id),
225
+ ]);
226
+
227
+ // ============================================================================
228
+ // SESSIONS & TOKENS
229
+ // ============================================================================
230
+
231
+ export const sessions = sqliteTable("sessions", {
232
+ id: text("id", { length: 21 }).notNull(),
233
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
234
+ user_id: text("user_id", { length: 255 }),
235
+ created_at: text("created_at", { length: 35 }).notNull(),
236
+ updated_at: text("updated_at", { length: 35 }).notNull(),
237
+ expires_at: text("expires_at", { length: 35 }),
238
+ idle_expires_at: text("idle_expires_at", { length: 35 }),
239
+ authenticated_at: text("authenticated_at", { length: 35 }),
240
+ last_interaction_at: text("last_interaction_at", { length: 35 }),
241
+ used_at: text("used_at", { length: 35 }),
242
+ revoked_at: text("revoked_at", { length: 35 }),
243
+ device: text("device").notNull(),
244
+ clients: text("clients").notNull(),
245
+ login_session_id: text("login_session_id", { length: 21 }),
246
+ }, (table) => [
247
+ primaryKey({ columns: [table.tenant_id, table.id], name: "sessions_pk" }),
248
+ index("IDX_sessions_login_session_id").on(table.login_session_id),
249
+ ]);
250
+
251
+ export const refreshTokens = sqliteTable("refresh_tokens", {
252
+ id: text("id", { length: 21 }).notNull(),
253
+ tenant_id: text("tenant_id", { length: 255 }).notNull(),
254
+ client_id: text("client_id", { length: 191 }).notNull(),
255
+ session_id: text("session_id", { length: 21 }).notNull(),
256
+ user_id: text("user_id", { length: 255 }),
257
+ resource_servers: text("resource_servers").notNull(),
258
+ device: text("device").notNull(),
259
+ rotating: integer("rotating", { mode: "boolean" }).notNull(),
260
+ created_at: text("created_at", { length: 35 }).notNull(),
261
+ expires_at: text("expires_at", { length: 35 }),
262
+ idle_expires_at: text("idle_expires_at", { length: 35 }),
263
+ last_exchanged_at: text("last_exchanged_at", { length: 35 }),
264
+ }, (table) => [
265
+ primaryKey({ columns: [table.tenant_id, table.id], name: "refresh_tokens_pk" }),
266
+ ]);
267
+
268
+ export const loginSessions = sqliteTable("login_sessions", {
269
+ id: text("id", { length: 21 }).notNull(),
270
+ tenant_id: text("tenant_id", { length: 255 }).notNull(),
271
+ session_id: text("session_id", { length: 21 }),
272
+ csrf_token: text("csrf_token", { length: 21 }).notNull(),
273
+ authParams_client_id: text("authParams_client_id", { length: 191 }).notNull(),
274
+ authParams_vendor_id: text("authParams_vendor_id", { length: 255 }),
275
+ authParams_username: text("authParams_username", { length: 255 }),
276
+ authParams_response_type: text("authParams_response_type", { length: 255 }),
277
+ authParams_response_mode: text("authParams_response_mode", { length: 255 }),
278
+ authParams_audience: text("authParams_audience", { length: 255 }),
279
+ authParams_scope: text("authParams_scope"),
280
+ authParams_state: text("authParams_state"),
281
+ authParams_nonce: text("authParams_nonce", { length: 255 }),
282
+ authParams_code_challenge_method: text("authParams_code_challenge_method", { length: 255 }),
283
+ authParams_code_challenge: text("authParams_code_challenge", { length: 255 }),
284
+ authParams_redirect_uri: text("authParams_redirect_uri"),
285
+ authParams_organization: text("authParams_organization", { length: 255 }),
286
+ authParams_prompt: text("authParams_prompt", { length: 32 }),
287
+ authParams_act_as: text("authParams_act_as", { length: 256 }),
288
+ authParams_ui_locales: text("authParams_ui_locales", { length: 32 }),
289
+ authorization_url: text("authorization_url"),
290
+ created_at: text("created_at", { length: 35 }).notNull(),
291
+ updated_at: text("updated_at", { length: 35 }).notNull(),
292
+ expires_at: text("expires_at", { length: 35 }).notNull(),
293
+ ip: text("ip", { length: 39 }),
294
+ useragent: text("useragent"),
295
+ auth0Client: text("auth0Client", { length: 255 }),
296
+ login_completed: integer("login_completed").default(0),
297
+ }, (table) => [
298
+ primaryKey({ columns: [table.tenant_id, table.id], name: "login_sessions_pk" }),
299
+ index("login_sessions_id_index").on(table.id),
300
+ ]);
301
+
302
+ export const codes = sqliteTable("codes", {
303
+ code_id: text("code_id", { length: 255 }).notNull(),
304
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
305
+ user_id: text("user_id", { length: 255 }),
306
+ login_id: text("login_id", { length: 255 }),
307
+ connection_id: text("connection_id", { length: 255 }),
308
+ code_type: text("code_type", { length: 255 }).notNull(),
309
+ created_at: text("created_at", { length: 255 }).notNull(),
310
+ expires_at: text("expires_at", { length: 255 }).notNull(),
311
+ used_at: text("used_at", { length: 255 }),
312
+ code_verifier: text("code_verifier", { length: 128 }),
313
+ code_challenge: text("code_challenge", { length: 128 }),
314
+ code_challenge_method: text("code_challenge_method", { length: 5 }),
315
+ redirect_uri: text("redirect_uri", { length: 1024 }),
316
+ nonce: text("nonce", { length: 1024 }),
317
+ state: text("state", { length: 2048 }),
318
+ }, (table) => [
319
+ primaryKey({ columns: [table.code_id, table.code_type], name: "PK_codes_code_id_code_type" }),
320
+ index("codes_expires_at_index").on(table.expires_at),
321
+ ]);
322
+
323
+ export const authenticationCodes = sqliteTable("authentication_codes", {
324
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
325
+ code: text("code", { length: 255 }).primaryKey(),
326
+ client_id: text("client_id", { length: 255 }).notNull(),
327
+ user_id: text("user_id", { length: 255 }).notNull(),
328
+ nonce: text("nonce", { length: 255 }),
329
+ state: text("state", { length: 8192 }),
330
+ scope: text("scope", { length: 1024 }),
331
+ response_type: text("response_type", { length: 256 }),
332
+ response_mode: text("response_mode", { length: 256 }),
333
+ redirect_uri: text("redirect_uri", { length: 1024 }),
334
+ created_at: text("created_at", { length: 255 }).notNull(),
335
+ expires_at: text("expires_at", { length: 255 }).notNull(),
336
+ used_at: text("used_at", { length: 255 }),
337
+ });
338
+
339
+ export const otps = sqliteTable("otps", {
340
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
341
+ id: text("id", { length: 255 }).primaryKey(),
342
+ client_id: text("client_id", { length: 255 }).notNull(),
343
+ code: text("code", { length: 255 }).notNull(),
344
+ email: text("email", { length: 255 }).notNull(),
345
+ user_id: text("user_id", { length: 255 }),
346
+ send: text("send", { length: 255 }),
347
+ nonce: text("nonce", { length: 255 }),
348
+ state: text("state", { length: 1024 }),
349
+ scope: text("scope", { length: 1024 }),
350
+ response_type: text("response_type", { length: 256 }),
351
+ response_mode: text("response_mode", { length: 256 }),
352
+ redirect_uri: text("redirect_uri", { length: 1024 }),
353
+ created_at: text("created_at", { length: 255 }).notNull(),
354
+ expires_at: text("expires_at", { length: 255 }).notNull(),
355
+ used_at: text("used_at", { length: 255 }),
356
+ audience: text("audience", { length: 255 }),
357
+ ip: text("ip", { length: 64 }),
358
+ }, (table) => [
359
+ index("otps_email_index").on(table.email),
360
+ index("otps_expires_at_index").on(table.expires_at),
361
+ ]);
362
+
363
+ export const tickets = sqliteTable("tickets", {
364
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
365
+ id: text("id", { length: 255 }).primaryKey(),
366
+ client_id: text("client_id", { length: 255 }).notNull(),
367
+ email: text("email", { length: 255 }).notNull(),
368
+ nonce: text("nonce", { length: 255 }),
369
+ state: text("state", { length: 1024 }),
370
+ scope: text("scope", { length: 1024 }),
371
+ response_type: text("response_type", { length: 256 }),
372
+ response_mode: text("response_mode", { length: 256 }),
373
+ redirect_uri: text("redirect_uri", { length: 1024 }),
374
+ created_at: text("created_at", { length: 255 }).notNull(),
375
+ expires_at: text("expires_at", { length: 255 }).notNull(),
376
+ used_at: text("used_at", { length: 255 }),
377
+ });
378
+
379
+ // ============================================================================
380
+ // ORGANIZATIONS
381
+ // ============================================================================
382
+
383
+ export const organizations = sqliteTable("organizations", {
384
+ id: text("id", { length: 21 }).primaryKey(),
385
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
386
+ name: text("name", { length: 256 }).notNull(),
387
+ display_name: text("display_name", { length: 256 }),
388
+ branding: text("branding"),
389
+ metadata: text("metadata"),
390
+ enabled_connections: text("enabled_connections"),
391
+ token_quota: text("token_quota"),
392
+ created_at: text("created_at", { length: 35 }).notNull(),
393
+ updated_at: text("updated_at", { length: 35 }).notNull(),
394
+ }, (table) => [
395
+ index("idx_organizations_tenant_id").on(table.tenant_id),
396
+ ]);
397
+
398
+ export const userOrganizations = sqliteTable("user_organizations", {
399
+ id: text("id", { length: 21 }).primaryKey(),
400
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
401
+ user_id: text("user_id", { length: 191 }).notNull(),
402
+ organization_id: text("organization_id", { length: 21 }).notNull(),
403
+ created_at: text("created_at", { length: 35 }).notNull(),
404
+ updated_at: text("updated_at", { length: 35 }).notNull(),
405
+ }, (table) => [
406
+ uniqueIndex("user_organizations_unique").on(table.tenant_id, table.user_id, table.organization_id),
407
+ index("idx_user_organizations_tenant_id").on(table.tenant_id),
408
+ index("idx_user_organizations_user_id").on(table.user_id),
409
+ index("idx_user_organizations_organization_id").on(table.organization_id),
410
+ ]);
411
+
412
+ export const invites = sqliteTable("invites", {
413
+ id: text("id", { length: 21 }).primaryKey(),
414
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
415
+ organization_id: text("organization_id", { length: 21 }).notNull(),
416
+ inviter: text("inviter").notNull(),
417
+ invitee: text("invitee").notNull(),
418
+ client_id: text("client_id", { length: 191 }).notNull(),
419
+ connection_id: text("connection_id", { length: 21 }),
420
+ invitation_url: text("invitation_url").notNull(),
421
+ created_at: text("created_at", { length: 35 }).notNull(),
422
+ expires_at: text("expires_at", { length: 35 }).notNull(),
423
+ app_metadata: text("app_metadata"),
424
+ user_metadata: text("user_metadata"),
425
+ roles: text("roles"),
426
+ ticket_id: text("ticket_id", { length: 191 }),
427
+ ttl_sec: integer("ttl_sec"),
428
+ send_invitation_email: integer("send_invitation_email"),
429
+ }, (table) => [
430
+ index("idx_invites_tenant_id").on(table.tenant_id),
431
+ index("idx_invites_organization_id").on(table.organization_id),
432
+ index("idx_invites_expires_at").on(table.expires_at),
433
+ index("idx_invites_tenant_created").on(table.tenant_id, table.created_at),
434
+ ]);
435
+
436
+ // ============================================================================
437
+ // ROLES & PERMISSIONS
438
+ // ============================================================================
439
+
440
+ export const roles = sqliteTable("roles", {
441
+ id: text("id", { length: 21 }).notNull(),
442
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
443
+ name: text("name", { length: 50 }).notNull(),
444
+ description: text("description", { length: 255 }),
445
+ created_at: text("created_at", { length: 35 }).notNull(),
446
+ updated_at: text("updated_at", { length: 35 }).notNull(),
447
+ }, (table) => [
448
+ primaryKey({ columns: [table.tenant_id, table.id], name: "roles_pk" }),
449
+ ]);
450
+
451
+ export const rolePermissions = sqliteTable("role_permissions", {
452
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
453
+ role_id: text("role_id", { length: 21 }).notNull(),
454
+ resource_server_identifier: text("resource_server_identifier", { length: 191 }).notNull(),
455
+ permission_name: text("permission_name", { length: 191 }).notNull(),
456
+ created_at: text("created_at", { length: 35 }).notNull(),
457
+ }, (table) => [
458
+ primaryKey({
459
+ columns: [table.tenant_id, table.role_id, table.resource_server_identifier, table.permission_name],
460
+ name: "role_permissions_pk"
461
+ }),
462
+ index("role_permissions_role_fk").on(table.tenant_id, table.role_id),
463
+ index("role_permissions_permission_fk").on(table.tenant_id, table.resource_server_identifier, table.permission_name),
464
+ ]);
465
+
466
+ export const userPermissions = sqliteTable("user_permissions", {
467
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
468
+ user_id: text("user_id", { length: 191 }).notNull(),
469
+ resource_server_identifier: text("resource_server_identifier", { length: 21 }).notNull(),
470
+ permission_name: text("permission_name", { length: 191 }).notNull(),
471
+ organization_id: text("organization_id", { length: 21 }).notNull().default(""),
472
+ created_at: text("created_at", { length: 35 }).notNull(),
473
+ }, (table) => [
474
+ primaryKey({
475
+ columns: [table.tenant_id, table.user_id, table.resource_server_identifier, table.permission_name, table.organization_id],
476
+ name: "user_permissions_pk"
477
+ }),
478
+ index("user_permissions_user_fk").on(table.tenant_id, table.user_id),
479
+ index("user_permissions_permission_fk").on(table.tenant_id, table.resource_server_identifier, table.permission_name),
480
+ index("user_permissions_organization_fk").on(table.organization_id),
481
+ ]);
482
+
483
+ export const userRoles = sqliteTable("user_roles", {
484
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
485
+ user_id: text("user_id", { length: 191 }).notNull(),
486
+ role_id: text("role_id", { length: 21 }).notNull(),
487
+ organization_id: text("organization_id", { length: 191 }).notNull().default(""),
488
+ created_at: text("created_at", { length: 35 }).notNull(),
489
+ }, (table) => [
490
+ primaryKey({
491
+ columns: [table.tenant_id, table.user_id, table.role_id, table.organization_id],
492
+ name: "user_roles_pk"
493
+ }),
494
+ index("user_roles_user_fk").on(table.tenant_id, table.user_id),
495
+ index("user_roles_role_fk").on(table.tenant_id, table.role_id),
496
+ index("user_roles_organization_fk").on(table.organization_id),
497
+ ]);
498
+
499
+ export const resourceServers = sqliteTable("resource_servers", {
500
+ id: text("id", { length: 21 }).notNull(),
501
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
502
+ identifier: text("identifier", { length: 191 }).notNull(),
503
+ name: text("name", { length: 255 }).notNull(),
504
+ scopes: text("scopes", { length: 4096 }),
505
+ signing_alg: text("signing_alg", { length: 64 }),
506
+ signing_secret: text("signing_secret", { length: 2048 }),
507
+ token_lifetime: integer("token_lifetime"),
508
+ token_lifetime_for_web: integer("token_lifetime_for_web"),
509
+ skip_consent_for_verifiable_first_party_clients: integer("skip_consent_for_verifiable_first_party_clients"),
510
+ allow_offline_access: integer("allow_offline_access"),
511
+ verification_key: text("verification_key", { length: 4096 }),
512
+ options: text("options", { length: 4096 }),
513
+ created_at: text("created_at", { length: 35 }).notNull(),
514
+ updated_at: text("updated_at", { length: 35 }).notNull(),
515
+ }, (table) => [
516
+ primaryKey({ columns: [table.tenant_id, table.id], name: "resource_servers_pk" }),
517
+ ]);
518
+
519
+ // ============================================================================
520
+ // BRANDING & UI
521
+ // ============================================================================
522
+
523
+ export const branding = sqliteTable("branding", {
524
+ tenant_id: text("tenant_id", { length: 255 }).primaryKey().references(() => tenants.id, { onDelete: "cascade" }),
525
+ logo_url: text("logo_url", { length: 512 }),
526
+ favicon_url: text("favicon_url", { length: 512 }),
527
+ font_url: text("font_url", { length: 512 }),
528
+ colors_primary: text("colors_primary", { length: 8 }),
529
+ colors_page_background_type: text("colors_page_background_type", { length: 32 }),
530
+ colors_page_background_start: text("colors_page_background_start", { length: 8 }),
531
+ colors_page_background_end: text("colors_page_background_end", { length: 8 }),
532
+ colors_page_background_angle_dev: integer("colors_page_background_angle_dev"),
533
+ });
534
+
535
+ export const themes = sqliteTable("themes", {
536
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
537
+ themeId: text("themeId", { length: 255 }).notNull(),
538
+ displayName: text("displayName", { length: 255 }).notNull(),
539
+ colors_primary_button_label: text("colors_primary_button_label", { length: 24 }).notNull(),
540
+ colors_primary_button: text("colors_primary_button", { length: 24 }).notNull(),
541
+ colors_secondary_button_border: text("colors_secondary_button_border", { length: 24 }).notNull(),
542
+ colors_secondary_button_label: text("colors_secondary_button_label", { length: 24 }).notNull(),
543
+ colors_base_focus_color: text("colors_base_focus_color", { length: 24 }).notNull(),
544
+ colors_base_hover_color: text("colors_base_hover_color", { length: 24 }).notNull(),
545
+ colors_body_text: text("colors_body_text", { length: 24 }).notNull(),
546
+ colors_captcha_widget_theme: text("colors_captcha_widget_theme", { length: 24 }).notNull(),
547
+ colors_error: text("colors_error", { length: 24 }).notNull(),
548
+ colors_header: text("colors_header", { length: 24 }).notNull(),
549
+ colors_icons: text("colors_icons", { length: 24 }).notNull(),
550
+ colors_input_background: text("colors_input_background", { length: 24 }).notNull(),
551
+ colors_input_border: text("colors_input_border", { length: 24 }).notNull(),
552
+ colors_input_filled_text: text("colors_input_filled_text", { length: 24 }).notNull(),
553
+ colors_input_labels_placeholders: text("colors_input_labels_placeholders", { length: 24 }).notNull(),
554
+ colors_links_focused_components: text("colors_links_focused_components", { length: 24 }).notNull(),
555
+ colors_success: text("colors_success", { length: 24 }).notNull(),
556
+ colors_widget_background: text("colors_widget_background", { length: 24 }).notNull(),
557
+ colors_widget_border: text("colors_widget_border", { length: 24 }).notNull(),
558
+ borders_button_border_radius: integer("borders_button_border_radius").notNull(),
559
+ borders_button_border_weight: integer("borders_button_border_weight").notNull(),
560
+ borders_buttons_style: text("borders_buttons_style", { length: 24 }).notNull(),
561
+ borders_input_border_radius: integer("borders_input_border_radius").notNull(),
562
+ borders_input_border_weight: integer("borders_input_border_weight").notNull(),
563
+ borders_inputs_style: text("borders_inputs_style", { length: 24 }).notNull(),
564
+ borders_show_widget_shadow: integer("borders_show_widget_shadow", { mode: "boolean" }).notNull(),
565
+ borders_widget_border_weight: integer("borders_widget_border_weight").notNull(),
566
+ borders_widget_corner_radius: integer("borders_widget_corner_radius").notNull(),
567
+ fonts_body_text_bold: integer("fonts_body_text_bold").notNull(),
568
+ fonts_body_text_size: integer("fonts_body_text_size").notNull(),
569
+ fonts_buttons_text_bold: integer("fonts_buttons_text_bold").notNull(),
570
+ fonts_buttons_text_size: integer("fonts_buttons_text_size").notNull(),
571
+ fonts_font_url: text("fonts_font_url", { length: 255 }).notNull(),
572
+ fonts_input_labels_bold: integer("fonts_input_labels_bold").notNull(),
573
+ fonts_input_labels_size: integer("fonts_input_labels_size").notNull(),
574
+ fonts_links_bold: integer("fonts_links_bold", { mode: "boolean" }).notNull(),
575
+ fonts_links_size: integer("fonts_links_size").notNull(),
576
+ fonts_links_style: text("fonts_links_style", { length: 24 }).notNull(),
577
+ fonts_reference_text_size: integer("fonts_reference_text_size").notNull(),
578
+ fonts_subtitle_bold: integer("fonts_subtitle_bold", { mode: "boolean" }).notNull(),
579
+ fonts_subtitle_size: integer("fonts_subtitle_size").notNull(),
580
+ fonts_title_bold: integer("fonts_title_bold", { mode: "boolean" }).notNull(),
581
+ fonts_title_size: integer("fonts_title_size").notNull(),
582
+ page_background_background_color: text("page_background_background_color", { length: 24 }).notNull(),
583
+ page_background_background_image_url: text("page_background_background_image_url", { length: 255 }).notNull(),
584
+ page_background_page_layout: text("page_background_page_layout", { length: 24 }).notNull(),
585
+ widget_header_text_alignment: text("widget_header_text_alignment", { length: 24 }).notNull(),
586
+ widget_logo_height: integer("widget_logo_height").notNull(),
587
+ widget_logo_position: text("widget_logo_position", { length: 24 }).notNull(),
588
+ widget_logo_url: text("widget_logo_url", { length: 255 }).notNull(),
589
+ widget_social_buttons_layout: text("widget_social_buttons_layout", { length: 24 }).notNull(),
590
+ created_at: text("created_at", { length: 35 }).notNull(),
591
+ updated_at: text("updated_at", { length: 35 }).notNull(),
592
+ }, (table) => [
593
+ primaryKey({ columns: [table.tenant_id, table.themeId], name: "themes_pkey" }),
594
+ index("themes_tenant_id_idx").on(table.tenant_id),
595
+ ]);
596
+
597
+ export const forms = sqliteTable("forms", {
598
+ id: text("id", { length: 255 }).primaryKey(),
599
+ name: text("name", { length: 255 }).notNull(),
600
+ tenant_id: text("tenant_id", { length: 255 }).notNull(),
601
+ messages: text("messages", { length: 255 }),
602
+ languages: text("languages", { length: 255 }),
603
+ translations: text("translations", { length: 4096 }),
604
+ nodes: text("nodes", { length: 4096 }),
605
+ start: text("start", { length: 255 }),
606
+ ending: text("ending", { length: 255 }),
607
+ style: text("style", { length: 1042 }),
608
+ created_at: text("created_at", { length: 255 }).notNull(),
609
+ updated_at: text("updated_at", { length: 255 }).notNull(),
610
+ }, (table) => [
611
+ index("forms_tenant_id_idx").on(table.tenant_id),
612
+ ]);
613
+
614
+ export const flows = sqliteTable("flows", {
615
+ id: text("id", { length: 21 }).primaryKey(),
616
+ tenant_id: text("tenant_id", { length: 191 }).notNull(),
617
+ name: text("name", { length: 150 }).notNull(),
618
+ actions: text("actions"),
619
+ created_at: text("created_at", { length: 35 }).notNull(),
620
+ updated_at: text("updated_at", { length: 35 }).notNull(),
621
+ }, (table) => [
622
+ index("flows_tenant_id_idx").on(table.tenant_id),
623
+ ]);
624
+
625
+ export const promptSettings = sqliteTable("prompt_settings", {
626
+ tenant_id: text("tenant_id", { length: 64 }).primaryKey(),
627
+ universal_login_experience: text("universal_login_experience", { length: 16 }).notNull().default("new"),
628
+ identifier_first: integer("identifier_first", { mode: "boolean" }).notNull().default(true),
629
+ password_first: integer("password_first", { mode: "boolean" }).notNull().default(false),
630
+ webauthn_platform_first_factor: integer("webauthn_platform_first_factor", { mode: "boolean" }).notNull().default(false),
631
+ });
632
+
633
+ export const emailProviders = sqliteTable("email_providers", {
634
+ tenant_id: text("tenant_id", { length: 255 }).primaryKey(),
635
+ name: text("name", { length: 255 }).notNull(),
636
+ enabled: integer("enabled", { mode: "boolean" }).notNull(),
637
+ default_from_address: text("default_from_address", { length: 255 }),
638
+ credentials: text("credentials", { length: 2048 }).notNull().default("{}"),
639
+ settings: text("settings", { length: 2048 }).notNull().default("{}"),
640
+ created_at: text("created_at", { length: 29 }).notNull(),
641
+ updated_at: text("updated_at", { length: 29 }).notNull(),
642
+ });
643
+
644
+ export const hooks = sqliteTable("hooks", {
645
+ hook_id: text("hook_id", { length: 255 }).primaryKey(),
646
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
647
+ url: text("url", { length: 512 }).notNull(),
648
+ trigger_id: text("trigger_id", { length: 255 }).notNull(),
649
+ enabled: integer("enabled", { mode: "boolean" }).notNull(),
650
+ created_at: text("created_at", { length: 255 }).notNull(),
651
+ updated_at: text("updated_at", { length: 255 }).notNull(),
652
+ synchronous: integer("synchronous", { mode: "boolean" }).notNull().default(false),
653
+ priority: integer("priority"),
654
+ form_id: text("form_id"),
655
+ url_tmp: text("url_tmp", { length: 512 }),
656
+ });
657
+
658
+ export const keys = sqliteTable("keys", {
659
+ kid: text("kid", { length: 255 }).primaryKey(),
660
+ tenant_id: text("tenant_id", { length: 255 }).references(() => tenants.id, { onDelete: "cascade" }),
661
+ created_at: text("created_at", { length: 255 }).notNull(),
662
+ revoked_at: text("revoked_at", { length: 255 }),
663
+ cert: text("cert", { length: 4096 }),
664
+ pkcs7: text("pkcs7", { length: 4096 }),
665
+ fingerprint: text("fingerprint", { length: 256 }),
666
+ thumbprint: text("thumbprint", { length: 256 }),
667
+ current_since: text("current_since", { length: 256 }),
668
+ current_until: text("current_until", { length: 256 }),
669
+ type: text("type", { length: 50 }).notNull().default("jwt_signing"),
670
+ connection: text("connection", { length: 255 }).references(() => connections.id, { onDelete: "cascade" }),
671
+ });
672
+
673
+ // ============================================================================
674
+ // LOGS
675
+ // ============================================================================
676
+
677
+ export const logs = sqliteTable("logs", {
678
+ log_id: text("log_id", { length: 21 }).primaryKey(),
679
+ category: text("category", { length: 255 }),
680
+ tenant_id: text("tenant_id", { length: 64 }),
681
+ user_id: text("user_id", { length: 64 }),
682
+ ip: text("ip", { length: 255 }),
683
+ type: text("type", { length: 8 }).notNull(),
684
+ date: text("date", { length: 25 }).notNull(),
685
+ client_id: text("client_id", { length: 255 }),
686
+ client_name: text("client_name", { length: 255 }),
687
+ user_agent: text("user_agent", { length: 255 }),
688
+ description: text("description", { length: 255 }),
689
+ details: text("details", { length: 2048 }),
690
+ isMobile: integer("isMobile"),
691
+ user_name: text("user_name", { length: 255 }),
692
+ connection: text("connection", { length: 255 }),
693
+ connection_id: text("connection_id", { length: 255 }),
694
+ audience: text("audience", { length: 255 }),
695
+ scope: text("scope", { length: 255 }),
696
+ strategy: text("strategy", { length: 255 }),
697
+ strategy_type: text("strategy_type", { length: 255 }),
698
+ hostname: text("hostname", { length: 255 }),
699
+ auth0_client: text("auth0_client", { length: 8192 }),
700
+ session_connection: text("session_connection", { length: 255 }),
701
+ country_code: text("country_code", { length: 2 }),
702
+ city_name: text("city_name", { length: 255 }),
703
+ latitude: text("latitude", { length: 255 }),
704
+ longitude: text("longitude", { length: 255 }),
705
+ time_zone: text("time_zone", { length: 255 }),
706
+ continent_code: text("continent_code", { length: 2 }),
707
+ }, (table) => [
708
+ index("logs_user_id").on(table.user_id),
709
+ index("logs_tenant_id").on(table.tenant_id),
710
+ index("logs_date").on(table.date),
711
+ index("IDX_logs_tenant_date_type_user").on(table.tenant_id, table.date, table.type, table.user_id),
712
+ ]);
713
+
714
+ // ============================================================================
715
+ // LEGACY TABLES (for migration compatibility)
716
+ // ============================================================================
717
+
718
+ export const tenantSettings = sqliteTable("tenant_settings", {
719
+ tenant_id: text("tenant_id", { length: 191 }).primaryKey().references(() => tenants.id, { onDelete: "cascade" }),
720
+ idle_session_lifetime: integer("idle_session_lifetime"),
721
+ session_lifetime: integer("session_lifetime"),
722
+ session_cookie: text("session_cookie"),
723
+ enable_client_connections: integer("enable_client_connections"),
724
+ default_redirection_uri: text("default_redirection_uri"),
725
+ enabled_locales: text("enabled_locales"),
726
+ default_directory: text("default_directory", { length: 255 }),
727
+ error_page: text("error_page"),
728
+ flags: text("flags"),
729
+ friendly_name: text("friendly_name", { length: 255 }),
730
+ picture_url: text("picture_url"),
731
+ support_email: text("support_email", { length: 255 }),
732
+ support_url: text("support_url"),
733
+ sandbox_version: text("sandbox_version", { length: 50 }),
734
+ sandbox_versions_available: text("sandbox_versions_available"),
735
+ change_password: text("change_password"),
736
+ guardian_mfa_page: text("guardian_mfa_page"),
737
+ default_audience: text("default_audience", { length: 255 }),
738
+ default_organization: text("default_organization", { length: 255 }),
739
+ sessions: text("sessions"),
740
+ });
741
+
742
+ export const members = sqliteTable("members", {
743
+ id: text("id", { length: 255 }).primaryKey(),
744
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
745
+ sub: text("sub", { length: 255 }),
746
+ email: text("email", { length: 255 }),
747
+ name: text("name", { length: 255 }),
748
+ status: text("status", { length: 255 }),
749
+ role: text("role", { length: 255 }),
750
+ picture: text("picture", { length: 2083 }),
751
+ created_at: text("created_at", { length: 255 }).notNull(),
752
+ updated_at: text("updated_at", { length: 255 }).notNull(),
753
+ });
754
+
755
+ export const applications = sqliteTable("applications", {
756
+ id: text("id", { length: 255 }).primaryKey(),
757
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
758
+ name: text("name", { length: 255 }).notNull(),
759
+ client_secret: text("client_secret", { length: 255 }),
760
+ allowed_logout_urls: text("allowed_logout_urls", { length: 255 }),
761
+ authentication_settings: text("authentication_settings", { length: 255 }),
762
+ addons: text("addons", { length: 4096 }).notNull().default("{}"),
763
+ callbacks: text("callbacks", { length: 1024 }).notNull().default("[]"),
764
+ allowed_origins: text("allowed_origins", { length: 1024 }).notNull().default("[]"),
765
+ web_origins: text("web_origins", { length: 1024 }).notNull().default("[]"),
766
+ allowed_clients: text("allowed_clients", { length: 1024 }).notNull().default("[]"),
767
+ options_kid: text("options_kid", { length: 32 }),
768
+ options_team_id: text("options_team_id", { length: 32 }),
769
+ options_client_id: text("options_client_id", { length: 128 }),
770
+ options_client_secret: text("options_client_secret", { length: 255 }),
771
+ options_scope: text("options_scope", { length: 255 }),
772
+ options_realms: text("options_realms", { length: 255 }),
773
+ options_app_secret: text("options_app_secret", { length: 1024 }),
774
+ email_validation: text("email_validation", { length: 255 }),
775
+ disable_sign_ups: text("disable_sign_ups"),
776
+ created_at: text("created_at", { length: 255 }).notNull(),
777
+ updated_at: text("updated_at", { length: 255 }).notNull(),
778
+ });
779
+
780
+ export const migrations = sqliteTable("migrations", {
781
+ id: text("id", { length: 255 }).primaryKey(),
782
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
783
+ provider: text("provider", { length: 255 }),
784
+ client_id: text("client_id", { length: 255 }),
785
+ origin: text("origin", { length: 255 }),
786
+ domain: text("domain", { length: 255 }),
787
+ created_at: text("created_at", { length: 255 }).notNull(),
788
+ updated_at: text("updated_at", { length: 255 }).notNull(),
789
+ });
790
+
791
+ export const logins = sqliteTable("logins", {
792
+ login_id: text("login_id", { length: 255 }).primaryKey(),
793
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
794
+ authParams_client_id: text("authParams_client_id", { length: 255 }).notNull(),
795
+ authParams_vendor_id: text("authParams_vendor_id", { length: 255 }),
796
+ authParams_username: text("authParams_username", { length: 255 }),
797
+ authParams_response_type: text("authParams_response_type", { length: 255 }),
798
+ authParams_response_mode: text("authParams_response_mode", { length: 255 }),
799
+ authParams_audience: text("authParams_audience", { length: 255 }),
800
+ authParams_scope: text("authParams_scope", { length: 511 }),
801
+ authParams_state: text("authParams_state", { length: 511 }),
802
+ authParams_code_challenge_method: text("authParams_code_challenge_method", { length: 256 }),
803
+ authParams_code_challenge: text("authParams_code_challenge", { length: 256 }),
804
+ authParams_redirect_uri: text("authParams_redirect_uri", { length: 256 }),
805
+ authParams_organization: text("authParams_organization", { length: 256 }),
806
+ authorization_url: text("authorization_url", { length: 1024 }),
807
+ created_at: text("created_at", { length: 255 }).notNull(),
808
+ updated_at: text("updated_at", { length: 255 }).notNull(),
809
+ expires_at: text("expires_at", { length: 255 }).notNull(),
810
+ ip: text("ip", { length: 255 }),
811
+ useragent: text("useragent", { length: 512 }),
812
+ auth0Client: text("auth0Client", { length: 256 }),
813
+ authParams_nonce: text("authParams_nonce", { length: 255 }),
814
+ authParams_ui_locales: text("authParams_ui_locales", { length: 32 }),
815
+ authParams_prompt: text("authParams_prompt", { length: 16 }),
816
+ authParams_act_as: text("authParams_act_as", { length: 255 }),
817
+ });
818
+
819
+ export const customDomains = sqliteTable("custom_domains", {
820
+ custom_domain_id: text("custom_domain_id", { length: 256 }).primaryKey(),
821
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
822
+ domain: text("domain", { length: 255 }).notNull(),
823
+ primary: integer("primary", { mode: "boolean" }).notNull(),
824
+ status: text("status", { length: 50 }).notNull(),
825
+ type: text("type", { length: 50 }).notNull(),
826
+ origin_domain_name: text("origin_domain_name", { length: 255 }),
827
+ verification: text("verification", { length: 2048 }),
828
+ custom_client_ip_header: text("custom_client_ip_header", { length: 50 }),
829
+ tls_policy: text("tls_policy", { length: 50 }),
830
+ domain_metadata: text("domain_metadata", { length: 2048 }),
831
+ created_at: text("created_at", { length: 35 }).notNull(),
832
+ updated_at: text("updated_at", { length: 35 }).notNull(),
833
+ });
834
+
835
+ export const domains = sqliteTable("domains", {
836
+ id: text("id", { length: 255 }).primaryKey(),
837
+ tenant_id: text("tenant_id", { length: 255 }).notNull().references(() => tenants.id, { onDelete: "cascade" }),
838
+ domain: text("domain", { length: 255 }).notNull(),
839
+ email_service: text("email_service", { length: 255 }),
840
+ email_api_key: text("email_api_key", { length: 255 }),
841
+ dkim_private_key: text("dkim_private_key", { length: 2048 }),
842
+ dkim_public_key: text("dkim_public_key", { length: 2048 }),
843
+ created_at: text("created_at", { length: 255 }).notNull(),
844
+ updated_at: text("updated_at", { length: 255 }).notNull(),
845
+ });