1CREATE TABLE "users" (
2 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
3 "github_login" VARCHAR,
4 "admin" BOOLEAN,
5 "email_address" VARCHAR(255) DEFAULT NULL,
6 "name" TEXT,
7 "invite_code" VARCHAR(64),
8 "invite_count" INTEGER NOT NULL DEFAULT 0,
9 "inviter_id" INTEGER REFERENCES users (id),
10 "connected_once" BOOLEAN NOT NULL DEFAULT false,
11 "created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
12 "metrics_id" TEXT,
13 "github_user_id" INTEGER NOT NULL,
14 "accepted_tos_at" TIMESTAMP WITHOUT TIME ZONE,
15 "github_user_created_at" TIMESTAMP WITHOUT TIME ZONE,
16 "custom_llm_monthly_allowance_in_cents" INTEGER
17);
18
19CREATE UNIQUE INDEX "index_users_github_login" ON "users" ("github_login");
20
21CREATE UNIQUE INDEX "index_invite_code_users" ON "users" ("invite_code");
22
23CREATE INDEX "index_users_on_email_address" ON "users" ("email_address");
24
25CREATE UNIQUE INDEX "index_users_on_github_user_id" ON "users" ("github_user_id");
26
27CREATE TABLE "access_tokens" (
28 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
29 "user_id" INTEGER REFERENCES users (id),
30 "impersonated_user_id" INTEGER REFERENCES users (id),
31 "hash" VARCHAR(128)
32);
33
34CREATE INDEX "index_access_tokens_user_id" ON "access_tokens" ("user_id");
35
36CREATE TABLE "contacts" (
37 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
38 "user_id_a" INTEGER REFERENCES users (id) NOT NULL,
39 "user_id_b" INTEGER REFERENCES users (id) NOT NULL,
40 "a_to_b" BOOLEAN NOT NULL,
41 "should_notify" BOOLEAN NOT NULL,
42 "accepted" BOOLEAN NOT NULL
43);
44
45CREATE UNIQUE INDEX "index_contacts_user_ids" ON "contacts" ("user_id_a", "user_id_b");
46
47CREATE INDEX "index_contacts_user_id_b" ON "contacts" ("user_id_b");
48
49CREATE TABLE "rooms" (
50 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
51 "live_kit_room" VARCHAR NOT NULL,
52 "environment" VARCHAR,
53 "channel_id" INTEGER REFERENCES channels (id) ON DELETE CASCADE
54);
55
56CREATE UNIQUE INDEX "index_rooms_on_channel_id" ON "rooms" ("channel_id");
57
58CREATE TABLE "projects" (
59 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
60 "room_id" INTEGER REFERENCES rooms (id) ON DELETE CASCADE,
61 "host_user_id" INTEGER REFERENCES users (id),
62 "host_connection_id" INTEGER,
63 "host_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE CASCADE,
64 "unregistered" BOOLEAN NOT NULL DEFAULT FALSE
65);
66
67CREATE INDEX "index_projects_on_host_connection_server_id" ON "projects" ("host_connection_server_id");
68
69CREATE INDEX "index_projects_on_host_connection_id_and_host_connection_server_id" ON "projects" ("host_connection_id", "host_connection_server_id");
70
71CREATE TABLE "worktrees" (
72 "project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
73 "id" INTEGER NOT NULL,
74 "root_name" VARCHAR NOT NULL,
75 "abs_path" VARCHAR NOT NULL,
76 "visible" BOOL NOT NULL,
77 "scan_id" INTEGER NOT NULL,
78 "is_complete" BOOL NOT NULL DEFAULT FALSE,
79 "completed_scan_id" INTEGER NOT NULL,
80 PRIMARY KEY (project_id, id)
81);
82
83CREATE INDEX "index_worktrees_on_project_id" ON "worktrees" ("project_id");
84
85CREATE TABLE "worktree_entries" (
86 "project_id" INTEGER NOT NULL,
87 "worktree_id" INTEGER NOT NULL,
88 "scan_id" INTEGER NOT NULL,
89 "id" INTEGER NOT NULL,
90 "is_dir" BOOL NOT NULL,
91 "path" VARCHAR NOT NULL,
92 "canonical_path" TEXT,
93 "inode" INTEGER NOT NULL,
94 "mtime_seconds" INTEGER NOT NULL,
95 "mtime_nanos" INTEGER NOT NULL,
96 "is_external" BOOL NOT NULL,
97 "is_ignored" BOOL NOT NULL,
98 "is_deleted" BOOL NOT NULL,
99 "git_status" INTEGER,
100 "is_fifo" BOOL NOT NULL,
101 PRIMARY KEY (project_id, worktree_id, id),
102 FOREIGN KEY (project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
103);
104
105CREATE INDEX "index_worktree_entries_on_project_id" ON "worktree_entries" ("project_id");
106
107CREATE INDEX "index_worktree_entries_on_project_id_and_worktree_id" ON "worktree_entries" ("project_id", "worktree_id");
108
109CREATE TABLE "project_repositories" (
110 "project_id" INTEGER NOT NULL,
111 "abs_path" VARCHAR,
112 "id" INTEGER NOT NULL,
113 "entry_ids" VARCHAR,
114 "legacy_worktree_id" INTEGER,
115 "branch" VARCHAR,
116 "scan_id" INTEGER NOT NULL,
117 "is_deleted" BOOL NOT NULL,
118 "current_merge_conflicts" VARCHAR,
119 "branch_summary" VARCHAR,
120 "head_commit_details" VARCHAR,
121 PRIMARY KEY (project_id, id)
122);
123
124CREATE INDEX "index_project_repositories_on_project_id" ON "project_repositories" ("project_id");
125
126CREATE TABLE "project_repository_statuses" (
127 "project_id" INTEGER NOT NULL,
128 "repository_id" INTEGER NOT NULL,
129 "repo_path" VARCHAR NOT NULL,
130 "status" INT8 NOT NULL,
131 "status_kind" INT4 NOT NULL,
132 "first_status" INT4 NULL,
133 "second_status" INT4 NULL,
134 "scan_id" INT8 NOT NULL,
135 "is_deleted" BOOL NOT NULL,
136 PRIMARY KEY (project_id, repository_id, repo_path)
137);
138
139CREATE INDEX "index_project_repos_statuses_on_project_id" ON "project_repository_statuses" ("project_id");
140
141CREATE INDEX "index_project_repos_statuses_on_project_id_and_repo_id" ON "project_repository_statuses" ("project_id", "repository_id");
142
143CREATE TABLE "worktree_settings_files" (
144 "project_id" INTEGER NOT NULL,
145 "worktree_id" INTEGER NOT NULL,
146 "path" VARCHAR NOT NULL,
147 "content" TEXT,
148 "kind" VARCHAR,
149 PRIMARY KEY (project_id, worktree_id, path),
150 FOREIGN KEY (project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
151);
152
153CREATE INDEX "index_worktree_settings_files_on_project_id" ON "worktree_settings_files" ("project_id");
154
155CREATE INDEX "index_worktree_settings_files_on_project_id_and_worktree_id" ON "worktree_settings_files" ("project_id", "worktree_id");
156
157CREATE TABLE "worktree_diagnostic_summaries" (
158 "project_id" INTEGER NOT NULL,
159 "worktree_id" INTEGER NOT NULL,
160 "path" VARCHAR NOT NULL,
161 "language_server_id" INTEGER NOT NULL,
162 "error_count" INTEGER NOT NULL,
163 "warning_count" INTEGER NOT NULL,
164 PRIMARY KEY (project_id, worktree_id, path),
165 FOREIGN KEY (project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
166);
167
168CREATE INDEX "index_worktree_diagnostic_summaries_on_project_id" ON "worktree_diagnostic_summaries" ("project_id");
169
170CREATE INDEX "index_worktree_diagnostic_summaries_on_project_id_and_worktree_id" ON "worktree_diagnostic_summaries" ("project_id", "worktree_id");
171
172CREATE TABLE "language_servers" (
173 "id" INTEGER NOT NULL,
174 "project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
175 "name" VARCHAR NOT NULL,
176 PRIMARY KEY (project_id, id)
177);
178
179CREATE INDEX "index_language_servers_on_project_id" ON "language_servers" ("project_id");
180
181CREATE TABLE "project_collaborators" (
182 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
183 "project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
184 "connection_id" INTEGER NOT NULL,
185 "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
186 "user_id" INTEGER NOT NULL,
187 "replica_id" INTEGER NOT NULL,
188 "is_host" BOOLEAN NOT NULL
189);
190
191CREATE INDEX "index_project_collaborators_on_project_id" ON "project_collaborators" ("project_id");
192
193CREATE UNIQUE INDEX "index_project_collaborators_on_project_id_and_replica_id" ON "project_collaborators" ("project_id", "replica_id");
194
195CREATE INDEX "index_project_collaborators_on_connection_server_id" ON "project_collaborators" ("connection_server_id");
196
197CREATE INDEX "index_project_collaborators_on_connection_id" ON "project_collaborators" ("connection_id");
198
199CREATE UNIQUE INDEX "index_project_collaborators_on_project_id_connection_id_and_server_id" ON "project_collaborators" (
200 "project_id",
201 "connection_id",
202 "connection_server_id"
203);
204
205CREATE TABLE "room_participants" (
206 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
207 "room_id" INTEGER NOT NULL REFERENCES rooms (id),
208 "user_id" INTEGER NOT NULL REFERENCES users (id),
209 "answering_connection_id" INTEGER,
210 "answering_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE CASCADE,
211 "answering_connection_lost" BOOLEAN NOT NULL,
212 "location_kind" INTEGER,
213 "location_project_id" INTEGER,
214 "initial_project_id" INTEGER,
215 "calling_user_id" INTEGER NOT NULL REFERENCES users (id),
216 "calling_connection_id" INTEGER NOT NULL,
217 "calling_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE SET NULL,
218 "participant_index" INTEGER,
219 "role" TEXT,
220 "in_call" BOOLEAN NOT NULL DEFAULT FALSE
221);
222
223CREATE UNIQUE INDEX "index_room_participants_on_user_id" ON "room_participants" ("user_id");
224
225CREATE INDEX "index_room_participants_on_room_id" ON "room_participants" ("room_id");
226
227CREATE INDEX "index_room_participants_on_answering_connection_server_id" ON "room_participants" ("answering_connection_server_id");
228
229CREATE INDEX "index_room_participants_on_calling_connection_server_id" ON "room_participants" ("calling_connection_server_id");
230
231CREATE INDEX "index_room_participants_on_answering_connection_id" ON "room_participants" ("answering_connection_id");
232
233CREATE UNIQUE INDEX "index_room_participants_on_answering_connection_id_and_answering_connection_server_id" ON "room_participants" (
234 "answering_connection_id",
235 "answering_connection_server_id"
236);
237
238CREATE TABLE "servers" (
239 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
240 "environment" VARCHAR NOT NULL
241);
242
243CREATE TABLE "followers" (
244 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
245 "room_id" INTEGER NOT NULL REFERENCES rooms (id) ON DELETE CASCADE,
246 "project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
247 "leader_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
248 "leader_connection_id" INTEGER NOT NULL,
249 "follower_connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
250 "follower_connection_id" INTEGER NOT NULL
251);
252
253CREATE UNIQUE INDEX "index_followers_on_project_id_and_leader_connection_server_id_and_leader_connection_id_and_follower_connection_server_id_and_follower_connection_id" ON "followers" (
254 "project_id",
255 "leader_connection_server_id",
256 "leader_connection_id",
257 "follower_connection_server_id",
258 "follower_connection_id"
259);
260
261CREATE INDEX "index_followers_on_room_id" ON "followers" ("room_id");
262
263CREATE TABLE "channels" (
264 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
265 "name" VARCHAR NOT NULL,
266 "created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
267 "visibility" VARCHAR NOT NULL,
268 "parent_path" TEXT NOT NULL,
269 "requires_zed_cla" BOOLEAN NOT NULL DEFAULT FALSE
270);
271
272CREATE INDEX "index_channels_on_parent_path" ON "channels" ("parent_path");
273
274CREATE TABLE IF NOT EXISTS "channel_chat_participants" (
275 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
276 "user_id" INTEGER NOT NULL REFERENCES users (id),
277 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
278 "connection_id" INTEGER NOT NULL,
279 "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE
280);
281
282CREATE INDEX "index_channel_chat_participants_on_channel_id" ON "channel_chat_participants" ("channel_id");
283
284CREATE TABLE IF NOT EXISTS "channel_messages" (
285 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
286 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
287 "sender_id" INTEGER NOT NULL REFERENCES users (id),
288 "body" TEXT NOT NULL,
289 "sent_at" TIMESTAMP,
290 "edited_at" TIMESTAMP,
291 "nonce" BLOB NOT NULL,
292 "reply_to_message_id" INTEGER DEFAULT NULL
293);
294
295CREATE INDEX "index_channel_messages_on_channel_id" ON "channel_messages" ("channel_id");
296
297CREATE UNIQUE INDEX "index_channel_messages_on_sender_id_nonce" ON "channel_messages" ("sender_id", "nonce");
298
299CREATE TABLE "channel_message_mentions" (
300 "message_id" INTEGER NOT NULL REFERENCES channel_messages (id) ON DELETE CASCADE,
301 "start_offset" INTEGER NOT NULL,
302 "end_offset" INTEGER NOT NULL,
303 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
304 PRIMARY KEY (message_id, start_offset)
305);
306
307CREATE TABLE "channel_members" (
308 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
309 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
310 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
311 "role" VARCHAR NOT NULL,
312 "accepted" BOOLEAN NOT NULL DEFAULT false,
313 "updated_at" TIMESTAMP NOT NULL DEFAULT now
314);
315
316CREATE UNIQUE INDEX "index_channel_members_on_channel_id_and_user_id" ON "channel_members" ("channel_id", "user_id");
317
318CREATE TABLE "buffers" (
319 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
320 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
321 "epoch" INTEGER NOT NULL DEFAULT 0,
322 "latest_operation_epoch" INTEGER,
323 "latest_operation_replica_id" INTEGER,
324 "latest_operation_lamport_timestamp" INTEGER
325);
326
327CREATE INDEX "index_buffers_on_channel_id" ON "buffers" ("channel_id");
328
329CREATE TABLE "buffer_operations" (
330 "buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
331 "epoch" INTEGER NOT NULL,
332 "replica_id" INTEGER NOT NULL,
333 "lamport_timestamp" INTEGER NOT NULL,
334 "value" BLOB NOT NULL,
335 PRIMARY KEY (buffer_id, epoch, lamport_timestamp, replica_id)
336);
337
338CREATE TABLE "buffer_snapshots" (
339 "buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
340 "epoch" INTEGER NOT NULL,
341 "text" TEXT NOT NULL,
342 "operation_serialization_version" INTEGER NOT NULL,
343 PRIMARY KEY (buffer_id, epoch)
344);
345
346CREATE TABLE "channel_buffer_collaborators" (
347 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
348 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
349 "connection_id" INTEGER NOT NULL,
350 "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE,
351 "connection_lost" BOOLEAN NOT NULL DEFAULT false,
352 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
353 "replica_id" INTEGER NOT NULL
354);
355
356CREATE INDEX "index_channel_buffer_collaborators_on_channel_id" ON "channel_buffer_collaborators" ("channel_id");
357
358CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_channel_id_and_replica_id" ON "channel_buffer_collaborators" ("channel_id", "replica_id");
359
360CREATE INDEX "index_channel_buffer_collaborators_on_connection_server_id" ON "channel_buffer_collaborators" ("connection_server_id");
361
362CREATE INDEX "index_channel_buffer_collaborators_on_connection_id" ON "channel_buffer_collaborators" ("connection_id");
363
364CREATE UNIQUE INDEX "index_channel_buffer_collaborators_on_channel_id_connection_id_and_server_id" ON "channel_buffer_collaborators" (
365 "channel_id",
366 "connection_id",
367 "connection_server_id"
368);
369
370CREATE TABLE "feature_flags" (
371 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
372 "flag" TEXT NOT NULL UNIQUE,
373 "enabled_for_all" BOOLEAN NOT NULL DEFAULT false
374);
375
376CREATE INDEX "index_feature_flags" ON "feature_flags" ("id");
377
378CREATE TABLE "user_features" (
379 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
380 "feature_id" INTEGER NOT NULL REFERENCES feature_flags (id) ON DELETE CASCADE,
381 PRIMARY KEY (user_id, feature_id)
382);
383
384CREATE UNIQUE INDEX "index_user_features_user_id_and_feature_id" ON "user_features" ("user_id", "feature_id");
385
386CREATE INDEX "index_user_features_on_user_id" ON "user_features" ("user_id");
387
388CREATE INDEX "index_user_features_on_feature_id" ON "user_features" ("feature_id");
389
390CREATE TABLE "observed_buffer_edits" (
391 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
392 "buffer_id" INTEGER NOT NULL REFERENCES buffers (id) ON DELETE CASCADE,
393 "epoch" INTEGER NOT NULL,
394 "lamport_timestamp" INTEGER NOT NULL,
395 "replica_id" INTEGER NOT NULL,
396 PRIMARY KEY (user_id, buffer_id)
397);
398
399CREATE UNIQUE INDEX "index_observed_buffers_user_and_buffer_id" ON "observed_buffer_edits" ("user_id", "buffer_id");
400
401CREATE TABLE IF NOT EXISTS "observed_channel_messages" (
402 "user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
403 "channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
404 "channel_message_id" INTEGER NOT NULL,
405 PRIMARY KEY (user_id, channel_id)
406);
407
408CREATE UNIQUE INDEX "index_observed_channel_messages_user_and_channel_id" ON "observed_channel_messages" ("user_id", "channel_id");
409
410CREATE TABLE "notification_kinds" (
411 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
412 "name" VARCHAR NOT NULL
413);
414
415CREATE UNIQUE INDEX "index_notification_kinds_on_name" ON "notification_kinds" ("name");
416
417CREATE TABLE "notifications" (
418 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
419 "created_at" TIMESTAMP NOT NULL default CURRENT_TIMESTAMP,
420 "recipient_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
421 "kind" INTEGER NOT NULL REFERENCES notification_kinds (id),
422 "entity_id" INTEGER,
423 "content" TEXT,
424 "is_read" BOOLEAN NOT NULL DEFAULT FALSE,
425 "response" BOOLEAN
426);
427
428CREATE INDEX "index_notifications_on_recipient_id_is_read_kind_entity_id" ON "notifications" ("recipient_id", "is_read", "kind", "entity_id");
429
430CREATE TABLE contributors (
431 user_id INTEGER REFERENCES users (id),
432 signed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
433 PRIMARY KEY (user_id)
434);
435
436CREATE TABLE extensions (
437 id INTEGER PRIMARY KEY AUTOINCREMENT,
438 external_id TEXT NOT NULL,
439 name TEXT NOT NULL,
440 latest_version TEXT NOT NULL,
441 total_download_count INTEGER NOT NULL DEFAULT 0
442);
443
444CREATE TABLE extension_versions (
445 extension_id INTEGER REFERENCES extensions (id),
446 version TEXT NOT NULL,
447 published_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
448 authors TEXT NOT NULL,
449 repository TEXT NOT NULL,
450 description TEXT NOT NULL,
451 schema_version INTEGER NOT NULL DEFAULT 0,
452 wasm_api_version TEXT,
453 download_count INTEGER NOT NULL DEFAULT 0,
454 provides_themes BOOLEAN NOT NULL DEFAULT FALSE,
455 provides_icon_themes BOOLEAN NOT NULL DEFAULT FALSE,
456 provides_languages BOOLEAN NOT NULL DEFAULT FALSE,
457 provides_grammars BOOLEAN NOT NULL DEFAULT FALSE,
458 provides_language_servers BOOLEAN NOT NULL DEFAULT FALSE,
459 provides_context_servers BOOLEAN NOT NULL DEFAULT FALSE,
460 provides_slash_commands BOOLEAN NOT NULL DEFAULT FALSE,
461 provides_indexed_docs_providers BOOLEAN NOT NULL DEFAULT FALSE,
462 provides_snippets BOOLEAN NOT NULL DEFAULT FALSE,
463 PRIMARY KEY (extension_id, version)
464);
465
466CREATE UNIQUE INDEX "index_extensions_external_id" ON "extensions" ("external_id");
467
468CREATE INDEX "index_extensions_total_download_count" ON "extensions" ("total_download_count");
469
470CREATE TABLE rate_buckets (
471 user_id INT NOT NULL,
472 rate_limit_name VARCHAR(255) NOT NULL,
473 token_count INT NOT NULL,
474 last_refill TIMESTAMP WITHOUT TIME ZONE NOT NULL,
475 PRIMARY KEY (user_id, rate_limit_name),
476 FOREIGN KEY (user_id) REFERENCES users (id)
477);
478
479CREATE INDEX idx_user_id_rate_limit ON rate_buckets (user_id, rate_limit_name);
480
481CREATE TABLE IF NOT EXISTS billing_preferences (
482 id INTEGER PRIMARY KEY AUTOINCREMENT,
483 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
484 user_id INTEGER NOT NULL REFERENCES users (id),
485 max_monthly_llm_usage_spending_in_cents INTEGER NOT NULL,
486 model_request_overages_enabled bool NOT NULL DEFAULT FALSE,
487 model_request_overages_spend_limit_in_cents integer NOT NULL DEFAULT 0
488);
489
490CREATE UNIQUE INDEX "uix_billing_preferences_on_user_id" ON billing_preferences (user_id);
491
492CREATE TABLE IF NOT EXISTS billing_customers (
493 id INTEGER PRIMARY KEY AUTOINCREMENT,
494 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
495 user_id INTEGER NOT NULL REFERENCES users (id),
496 has_overdue_invoices BOOLEAN NOT NULL DEFAULT FALSE,
497 stripe_customer_id TEXT NOT NULL,
498 trial_started_at TIMESTAMP
499);
500
501CREATE UNIQUE INDEX "uix_billing_customers_on_user_id" ON billing_customers (user_id);
502
503CREATE UNIQUE INDEX "uix_billing_customers_on_stripe_customer_id" ON billing_customers (stripe_customer_id);
504
505CREATE TABLE IF NOT EXISTS billing_subscriptions (
506 id INTEGER PRIMARY KEY AUTOINCREMENT,
507 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
508 billing_customer_id INTEGER NOT NULL REFERENCES billing_customers (id),
509 stripe_subscription_id TEXT NOT NULL,
510 stripe_subscription_status TEXT NOT NULL,
511 stripe_cancel_at TIMESTAMP,
512 stripe_cancellation_reason TEXT,
513 kind TEXT,
514 stripe_current_period_start BIGINT,
515 stripe_current_period_end BIGINT
516);
517
518CREATE INDEX "ix_billing_subscriptions_on_billing_customer_id" ON billing_subscriptions (billing_customer_id);
519
520CREATE UNIQUE INDEX "uix_billing_subscriptions_on_stripe_subscription_id" ON billing_subscriptions (stripe_subscription_id);
521
522CREATE TABLE IF NOT EXISTS processed_stripe_events (
523 stripe_event_id TEXT PRIMARY KEY,
524 stripe_event_type TEXT NOT NULL,
525 stripe_event_created_timestamp INTEGER NOT NULL,
526 processed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
527);
528
529CREATE INDEX "ix_processed_stripe_events_on_stripe_event_created_timestamp" ON processed_stripe_events (stripe_event_created_timestamp);
530
531CREATE TABLE IF NOT EXISTS "breakpoints" (
532 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
533 "project_id" INTEGER NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
534 "position" INTEGER NOT NULL,
535 "log_message" TEXT NULL,
536 "worktree_id" BIGINT NOT NULL,
537 "path" TEXT NOT NULL,
538 "kind" VARCHAR NOT NULL
539);
540
541CREATE INDEX "index_breakpoints_on_project_id" ON "breakpoints" ("project_id");