create-m5kdev 0.41.1 → 0.43.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.
- package/package.json +1 -1
- package/templates/minimal-app/CLAUDE.md.tpl +2 -2
- package/templates/minimal-app/README.md.tpl +12 -6
- package/templates/minimal-app/apps/e2e/servers.ts.tpl +22 -6
- package/templates/minimal-app/apps/server/AGENTS.md.tpl +1 -1
- package/templates/minimal-app/apps/server/drizzle-postgresql/0000_glorious_warhawk.sql +522 -0
- package/templates/minimal-app/apps/server/drizzle-postgresql/meta/0000_snapshot.json.tpl +3555 -0
- package/templates/minimal-app/apps/server/drizzle-postgresql/meta/_journal.json.tpl +13 -0
- package/templates/minimal-app/apps/server/drizzle.config.ts.tpl +1 -1
- package/templates/minimal-app/apps/server/mastra.ts.tpl +42 -0
- package/templates/minimal-app/apps/server/package.json.tpl +62 -57
- package/templates/minimal-app/apps/server/src/app.ts.tpl +20 -16
- package/templates/minimal-app/apps/server/src/drizzle.schema.ts.tpl +2 -0
- package/templates/minimal-app/apps/server/src/modules/conversation/conversation.mastra.ts.tpl +48 -0
- package/templates/minimal-app/apps/server/src/modules/conversation/conversation.persistence.ts.tpl +47 -0
- package/templates/minimal-app/apps/server/src/modules/posts/posts.db.ts.tpl +7 -6
- package/templates/minimal-app/apps/server/src/modules/posts/posts.repository.ts.tpl +2 -2
- package/templates/minimal-app/apps/shared/.env.example.tpl +6 -3
- package/templates/minimal-app/apps/shared/.env.production.example.tpl +7 -2
- package/templates/minimal-app/apps/shared/.env.tpl +6 -3
- package/templates/minimal-app/apps/shared/Dockerfile.pgbouncer +6 -0
- package/templates/minimal-app/apps/shared/compose.yaml.tpl +27 -0
- package/templates/minimal-app/apps/shared/fly.toml.tpl +0 -4
- package/templates/minimal-app/apps/shared/pgbouncer.ini +13 -0
- package/templates/minimal-app/apps/shared/pgbouncer.users +1 -0
- package/templates/minimal-app/apps/webapp/translations/en/{{APP_SLUG}}.json.tpl +1 -1
- package/templates/minimal-app/package.json.tpl +5 -0
- package/templates/minimal-app/pnpm-workspace.yaml.tpl +16 -13
- package/templates/minimal-app/template.manifest.json +9 -0
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ Guidance for Claude Code when working in this repository.
|
|
|
8
8
|
|
|
9
9
|
This is a pnpm + Turborepo monorepo built on the **m5kdev framework**:
|
|
10
10
|
|
|
11
|
-
- `@m5kdev/backend` — backend kernel: Express, Better Auth, Drizzle (
|
|
11
|
+
- `@m5kdev/backend` — backend kernel: Express, Better Auth, Drizzle (PostgreSQL), and tRPC. Apps compose it via `createBackendApp(config, [modules])`.
|
|
12
12
|
- `@m5kdev/commons` — shared runtime utilities and contracts.
|
|
13
13
|
- `@m5kdev/config` — configuration loading and validation.
|
|
14
14
|
// m5k:server:start
|
|
@@ -68,7 +68,7 @@ First-time setup: `pnpm install`, then `drizzle:migrate` and `drizzle:seed`, the
|
|
|
68
68
|
End-to-end tests: `pnpm --filter ./apps/e2e test:e2e` (Playwright).
|
|
69
69
|
// m5k:test-harness:end
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Runtime uses PostgreSQL through PgBouncer (`DATABASE_URL`); migrations and initialization require `DATABASE_DIRECT_URL`. Keep app, Mastra, and vector schemas separately owned. Start the local PostgreSQL/PgBouncer Compose stack and provision pgvector before applying reviewed migrations. Agents must not generate or hand-author migration SQL or metadata. Local auth emails are written to `apps/server/.emails`. Demo login: `admin@{{APP_SLUG}}.local` / `password1234`.
|
|
72
72
|
// m5k:server:end
|
|
73
73
|
|
|
74
74
|
// m5k:server:start
|
|
@@ -32,8 +32,11 @@ pnpm --filter ./apps/server drizzle:migrate
|
|
|
32
32
|
pnpm --filter ./apps/server drizzle:seed
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
The starter uses
|
|
36
|
-
Database tables are registered
|
|
35
|
+
The starter uses PostgreSQL through PgBouncer and writes local auth emails to `apps/server/.emails`. Start `docker compose -f apps/shared/compose.yaml up -d --build`, configure runtime `DATABASE_URL` and direct `DATABASE_DIRECT_URL`, and provision pgvector in `public` before migration/initialization.
|
|
36
|
+
Database tables are registered in `apps/server/src/schema.ts`; `src/drizzle.schema.ts` adds schema metadata for migration generation. After changing any `*.db.ts`, the maintainer runs `drizzle:generate`, reviews the output, then runs `drizzle:migrate`.
|
|
37
|
+
// m5k:ai:start
|
|
38
|
+
Run `pnpm --filter ./apps/server mastra:init` after migrations and before seed or runtime startup. App migrations own `app`; Mastra owns `mastra` and the embedding adapter owns `vectors`.
|
|
39
|
+
// m5k:ai:end
|
|
37
40
|
|
|
38
41
|
## Demo Credentials
|
|
39
42
|
|
|
@@ -83,7 +86,6 @@ cp apps/shared/.env.production.example apps/shared/.env.production
|
|
|
83
86
|
# fill in URLs, BETTER_AUTH_SECRET, REDIS_URL, …
|
|
84
87
|
|
|
85
88
|
fly apps create {{APP_SLUG}}-app
|
|
86
|
-
fly volumes create libsql_data --app {{APP_SLUG}}-app --region iad --size 1
|
|
87
89
|
pnpm app:secrets
|
|
88
90
|
pnpm app:deploy
|
|
89
91
|
// m5k:server:end
|
|
@@ -97,7 +99,11 @@ pnpm landing:deploy
|
|
|
97
99
|
`m5kdev-fly-secrets`). A missing env file errors with a copy-the-example
|
|
98
100
|
message.
|
|
99
101
|
// m5k:server:start
|
|
100
|
-
`app:deploy` does the same for the product image.
|
|
101
|
-
`
|
|
102
|
-
|
|
102
|
+
`app:deploy` does the same for the product image. Provision provider-neutral
|
|
103
|
+
PostgreSQL with pgvector in `public` and a transaction-mode PgBouncer endpoint.
|
|
104
|
+
Set `DATABASE_URL` to the runtime pool and `DATABASE_DIRECT_URL` to the direct
|
|
105
|
+
database endpoint. App migrations own `app`; Mastra owns `mastra` and vectors
|
|
106
|
+
use `vectors`. Run reviewed app migrations and, when AI is selected, `mastra:init`
|
|
107
|
+
through direct connections before starting the server. Redis and database URLs
|
|
108
|
+
are server secrets, not image layers. No local database volume is required.
|
|
103
109
|
// m5k:server:end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared webServer definitions for the Playwright configs. Each profile runs
|
|
3
|
-
* an isolated stack: own port pair, own
|
|
3
|
+
* an isolated stack: own port pair, own PostgreSQL database, own email output dir, and
|
|
4
4
|
* own Redis DB index (queue names are identical across profiles — sharing a
|
|
5
5
|
* Redis DB would let one profile's workers consume the other's jobs).
|
|
6
6
|
*/
|
|
@@ -48,11 +48,27 @@ function serverEnv(profile: E2EProfile, expo: boolean): Record<string, string> {
|
|
|
48
48
|
const serverPort = expo ? ports.expoServer : ports.server;
|
|
49
49
|
const webPort = expo ? ports.expoWeb : ports.web;
|
|
50
50
|
const suffix = expo ? `${profile}-expo` : profile;
|
|
51
|
+
const databaseConnection = (key: string): string => {
|
|
52
|
+
const value = process.env[key];
|
|
53
|
+
if (!value) throw new Error(`${key} is required for PostgreSQL E2E tests`);
|
|
54
|
+
const url = new URL(value);
|
|
55
|
+
url.pathname = `${url.pathname}_e2e_${suffix.replaceAll("-", "_")}`;
|
|
56
|
+
return url.toString();
|
|
57
|
+
};
|
|
51
58
|
return {
|
|
52
59
|
PORT: String(serverPort),
|
|
53
60
|
VITE_SERVER_URL: `http://127.0.0.1:${serverPort}`,
|
|
54
61
|
VITE_APP_URL: `http://127.0.0.1:${webPort}`,
|
|
55
|
-
DATABASE_URL:
|
|
62
|
+
DATABASE_URL: databaseConnection("E2E_DATABASE_URL"),
|
|
63
|
+
DATABASE_DIRECT_URL: databaseConnection("E2E_DATABASE_DIRECT_URL"),
|
|
64
|
+
DATABASE_SCHEMA: "app",
|
|
65
|
+
DATABASE_DISPOSABLE: process.env.E2E_DATABASE_DISPOSABLE ?? "false",
|
|
66
|
+
MASTRA_DATABASE_URL: "",
|
|
67
|
+
MASTRA_DATABASE_DIRECT_URL: "",
|
|
68
|
+
VECTOR_DATABASE_URL: "",
|
|
69
|
+
VECTOR_DATABASE_DIRECT_URL: "",
|
|
70
|
+
MASTRA_DATABASE_SCHEMA: "mastra",
|
|
71
|
+
VECTOR_DATABASE_SCHEMA: "vectors",
|
|
56
72
|
EMAIL_OUTPUT_DIRECTORY: `.e2e/emails-${suffix}`,
|
|
57
73
|
PROVISIONED_EMAIL_DOMAIN: "provisioned.auth-e2e.local",
|
|
58
74
|
REDIS_URL: `redis://127.0.0.1:6379/${expo ? PORTS[profile].expoRedisDb : PORTS[profile].redisDb}`,
|
|
@@ -62,9 +78,6 @@ function serverEnv(profile: E2EProfile, expo: boolean): Record<string, string> {
|
|
|
62
78
|
BETTER_AUTH_SECRET: "auth-e2e-local-secret-auth-e2e-local-secret",
|
|
63
79
|
SYSTEM_NOTIFICATION_EMAIL: "ops@auth-e2e.local",
|
|
64
80
|
NODE_ENV: "development",
|
|
65
|
-
// hermetic: shared/.env Turso credentials must not leak into drizzle-kit
|
|
66
|
-
TURSO_DATABASE_URL: "",
|
|
67
|
-
TURSO_AUTH_TOKEN: "",
|
|
68
81
|
// hermetic: a real key in the invoking shell would flip email mode to
|
|
69
82
|
// "send" and the stored-email assertions would find nothing
|
|
70
83
|
RESEND_API_KEY: "",
|
|
@@ -84,7 +97,10 @@ export function serverWebServer(profile: E2EProfile, { expo = false } = {}) {
|
|
|
84
97
|
return {
|
|
85
98
|
command: [
|
|
86
99
|
`${SERVER_FILTER} tsx db.ts reset`,
|
|
87
|
-
`${SERVER_FILTER}
|
|
100
|
+
`${SERVER_FILTER} tsx db.ts migrate`,
|
|
101
|
+
// m5k:ai:start
|
|
102
|
+
`${SERVER_FILTER} tsx mastra.ts`,
|
|
103
|
+
// m5k:ai:end
|
|
88
104
|
`${SERVER_FILTER} tsx db.e2e.ts seed`,
|
|
89
105
|
`${SERVER_FILTER} tsx src/index.ts`,
|
|
90
106
|
].join(" && "),
|
|
@@ -35,7 +35,7 @@ apps/server/src/modules/<module>/
|
|
|
35
35
|
// m5k:ai:start
|
|
36
36
|
- `AIModule` is registered in `app.ts` with an app-owned Mastra Agent (`assistant`). Conversation HTTP lives on `/ai`. Set `OPENROUTER_API_KEY` for live replies. Do not add a Starter service wrapper around `AIService` chat.
|
|
37
37
|
// m5k:ai:end
|
|
38
|
-
- Database commands live in server `db.ts`
|
|
38
|
+
- Database commands live in server `db.ts` and call Kernel `runDb` through `DATABASE_DIRECT_URL`, without importing `app.ts`. Runtime uses `DATABASE_URL` through PgBouncer. Reset requires a disposable environment and preserves Mastra/vector data.
|
|
39
39
|
|
|
40
40
|
## Avoid Trivial Service Delegation
|
|
41
41
|
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
CREATE SCHEMA "app";
|
|
2
|
+
--> statement-breakpoint
|
|
3
|
+
CREATE TABLE "app"."account_claim_magic_links" (
|
|
4
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
5
|
+
"claim_id" text NOT NULL,
|
|
6
|
+
"user_id" text NOT NULL,
|
|
7
|
+
"email" text NOT NULL,
|
|
8
|
+
"token" text NOT NULL,
|
|
9
|
+
"url" text NOT NULL,
|
|
10
|
+
"expires_at" timestamp with time zone,
|
|
11
|
+
"created_at" timestamp with time zone NOT NULL
|
|
12
|
+
);
|
|
13
|
+
--> statement-breakpoint
|
|
14
|
+
CREATE TABLE "app"."account_claims" (
|
|
15
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
16
|
+
"claim_user_id" text NOT NULL,
|
|
17
|
+
"status" text NOT NULL,
|
|
18
|
+
"code" text,
|
|
19
|
+
"expires_at" timestamp with time zone,
|
|
20
|
+
"claimed_at" timestamp with time zone,
|
|
21
|
+
"claimed_email" text,
|
|
22
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
23
|
+
"updated_at" timestamp with time zone
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
CREATE TABLE "app"."accounts" (
|
|
27
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
28
|
+
"account_id" text NOT NULL,
|
|
29
|
+
"issuer" text DEFAULT 'local:credential' NOT NULL,
|
|
30
|
+
"provider_id" text NOT NULL,
|
|
31
|
+
"user_id" text NOT NULL,
|
|
32
|
+
"access_token" text,
|
|
33
|
+
"refresh_token" text,
|
|
34
|
+
"id_token" text,
|
|
35
|
+
"access_token_expires_at" timestamp with time zone,
|
|
36
|
+
"refresh_token_expires_at" timestamp with time zone,
|
|
37
|
+
"scope" text,
|
|
38
|
+
"password" text,
|
|
39
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
40
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
41
|
+
);
|
|
42
|
+
--> statement-breakpoint
|
|
43
|
+
CREATE TABLE "app"."ai_usage" (
|
|
44
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
45
|
+
"user_id" text,
|
|
46
|
+
"member_id" text,
|
|
47
|
+
"team_id" text,
|
|
48
|
+
"organization_id" text,
|
|
49
|
+
"feature" text NOT NULL,
|
|
50
|
+
"provider" text NOT NULL,
|
|
51
|
+
"model" text NOT NULL,
|
|
52
|
+
"input_tokens" integer,
|
|
53
|
+
"output_tokens" integer,
|
|
54
|
+
"total_tokens" integer,
|
|
55
|
+
"cost" double precision,
|
|
56
|
+
"trace_id" text,
|
|
57
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
58
|
+
"metadata" jsonb
|
|
59
|
+
);
|
|
60
|
+
--> statement-breakpoint
|
|
61
|
+
CREATE TABLE "app"."apikeys" (
|
|
62
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
63
|
+
"name" text,
|
|
64
|
+
"start" text,
|
|
65
|
+
"prefix" text,
|
|
66
|
+
"key" text NOT NULL,
|
|
67
|
+
"config_id" text DEFAULT 'default' NOT NULL,
|
|
68
|
+
"reference_id" text NOT NULL,
|
|
69
|
+
"user_id" text,
|
|
70
|
+
"refill_interval" integer,
|
|
71
|
+
"refill_amount" integer,
|
|
72
|
+
"last_refill_at" timestamp with time zone,
|
|
73
|
+
"enabled" boolean NOT NULL,
|
|
74
|
+
"rate_limit_enabled" boolean NOT NULL,
|
|
75
|
+
"rate_limit_time_window" integer,
|
|
76
|
+
"rate_limit_max" integer,
|
|
77
|
+
"request_count" integer NOT NULL,
|
|
78
|
+
"remaining" integer,
|
|
79
|
+
"last_request" timestamp with time zone,
|
|
80
|
+
"expires_at" timestamp with time zone,
|
|
81
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
82
|
+
"updated_at" timestamp with time zone NOT NULL,
|
|
83
|
+
"permissions" text,
|
|
84
|
+
"metadata" text
|
|
85
|
+
);
|
|
86
|
+
--> statement-breakpoint
|
|
87
|
+
CREATE TABLE "app"."chats" (
|
|
88
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
89
|
+
"user_id" text NOT NULL,
|
|
90
|
+
"title" text,
|
|
91
|
+
"type" text,
|
|
92
|
+
"conversation" jsonb,
|
|
93
|
+
"created_at" timestamp with time zone,
|
|
94
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
95
|
+
);
|
|
96
|
+
--> statement-breakpoint
|
|
97
|
+
CREATE TABLE "app"."files" (
|
|
98
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
99
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
100
|
+
"updated_at" timestamp with time zone,
|
|
101
|
+
"deleted_at" timestamp with time zone,
|
|
102
|
+
"user_id" text,
|
|
103
|
+
"member_id" text,
|
|
104
|
+
"organization_id" text,
|
|
105
|
+
"bucket" text NOT NULL,
|
|
106
|
+
"key" text NOT NULL,
|
|
107
|
+
"original_name" text NOT NULL,
|
|
108
|
+
"original_extension" text,
|
|
109
|
+
"content_type" text NOT NULL,
|
|
110
|
+
"size_bytes" bigint,
|
|
111
|
+
"etag" text,
|
|
112
|
+
"checksum_sha256" text,
|
|
113
|
+
"metadata" jsonb,
|
|
114
|
+
"status" text NOT NULL,
|
|
115
|
+
"uploaded_at" timestamp with time zone
|
|
116
|
+
);
|
|
117
|
+
--> statement-breakpoint
|
|
118
|
+
CREATE TABLE "app"."invitations" (
|
|
119
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
120
|
+
"organization_id" text NOT NULL,
|
|
121
|
+
"member_id" text,
|
|
122
|
+
"email" text NOT NULL,
|
|
123
|
+
"role" text,
|
|
124
|
+
"status" text NOT NULL,
|
|
125
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
126
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
127
|
+
"inviter_id" text NOT NULL
|
|
128
|
+
);
|
|
129
|
+
--> statement-breakpoint
|
|
130
|
+
CREATE TABLE "app"."jwks" (
|
|
131
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
132
|
+
"public_key" text NOT NULL,
|
|
133
|
+
"private_key" text NOT NULL,
|
|
134
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
135
|
+
"expires_at" timestamp with time zone,
|
|
136
|
+
"alg" text,
|
|
137
|
+
"crv" text
|
|
138
|
+
);
|
|
139
|
+
--> statement-breakpoint
|
|
140
|
+
CREATE TABLE "app"."mcp_allowlist_entries" (
|
|
141
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
142
|
+
"oauth_client_id" text NOT NULL,
|
|
143
|
+
"user_id" text NOT NULL,
|
|
144
|
+
"organization_id" text NOT NULL,
|
|
145
|
+
"created_at" timestamp with time zone NOT NULL
|
|
146
|
+
);
|
|
147
|
+
--> statement-breakpoint
|
|
148
|
+
CREATE TABLE "app"."members" (
|
|
149
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
150
|
+
"organization_id" text NOT NULL,
|
|
151
|
+
"user_id" text,
|
|
152
|
+
"email" text,
|
|
153
|
+
"name" text DEFAULT '' NOT NULL,
|
|
154
|
+
"image" text,
|
|
155
|
+
"role" text NOT NULL,
|
|
156
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
157
|
+
"deleted_at" timestamp with time zone,
|
|
158
|
+
"preferences" jsonb DEFAULT '{}'::jsonb,
|
|
159
|
+
"metadata" jsonb DEFAULT '{}'::jsonb,
|
|
160
|
+
"onboarding" integer,
|
|
161
|
+
"flags" text[] DEFAULT '{}'
|
|
162
|
+
);
|
|
163
|
+
--> statement-breakpoint
|
|
164
|
+
CREATE TABLE "app"."notification_devices" (
|
|
165
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
166
|
+
"user_id" text NOT NULL,
|
|
167
|
+
"platform" text NOT NULL,
|
|
168
|
+
"endpoint" text,
|
|
169
|
+
"subscription" jsonb,
|
|
170
|
+
"token" text,
|
|
171
|
+
"label" text,
|
|
172
|
+
"enabled" boolean DEFAULT true NOT NULL,
|
|
173
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
174
|
+
"updated_at" timestamp with time zone NOT NULL,
|
|
175
|
+
CONSTRAINT "notification_devices_endpoint_unique" UNIQUE("endpoint"),
|
|
176
|
+
CONSTRAINT "notification_devices_token_unique" UNIQUE("token")
|
|
177
|
+
);
|
|
178
|
+
--> statement-breakpoint
|
|
179
|
+
CREATE TABLE "app"."notification_preferences" (
|
|
180
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
181
|
+
"member_id" text NOT NULL,
|
|
182
|
+
"kind" text NOT NULL,
|
|
183
|
+
"channel" text NOT NULL,
|
|
184
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
185
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
186
|
+
);
|
|
187
|
+
--> statement-breakpoint
|
|
188
|
+
CREATE TABLE "app"."notification_send_logs" (
|
|
189
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
190
|
+
"batch_id" text NOT NULL,
|
|
191
|
+
"notification_id" text NOT NULL,
|
|
192
|
+
"user_id" text NOT NULL,
|
|
193
|
+
"device_id" text,
|
|
194
|
+
"channel" text NOT NULL,
|
|
195
|
+
"provider" text,
|
|
196
|
+
"title" text NOT NULL,
|
|
197
|
+
"body" text NOT NULL,
|
|
198
|
+
"data" jsonb,
|
|
199
|
+
"status" text NOT NULL,
|
|
200
|
+
"error" text,
|
|
201
|
+
"job_id" text,
|
|
202
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
203
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
204
|
+
);
|
|
205
|
+
--> statement-breakpoint
|
|
206
|
+
CREATE TABLE "app"."notifications" (
|
|
207
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
208
|
+
"member_id" text NOT NULL,
|
|
209
|
+
"user_id" text NOT NULL,
|
|
210
|
+
"kind" text NOT NULL,
|
|
211
|
+
"title" text NOT NULL,
|
|
212
|
+
"body" text NOT NULL,
|
|
213
|
+
"data" jsonb,
|
|
214
|
+
"visible_in_inbox" boolean DEFAULT false NOT NULL,
|
|
215
|
+
"armed_channels" text[] DEFAULT '{}' NOT NULL,
|
|
216
|
+
"web_pushed_at" timestamp with time zone,
|
|
217
|
+
"mobile_pushed_at" timestamp with time zone,
|
|
218
|
+
"emailed_at" timestamp with time zone,
|
|
219
|
+
"read_at" timestamp with time zone,
|
|
220
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
221
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
222
|
+
);
|
|
223
|
+
--> statement-breakpoint
|
|
224
|
+
CREATE TABLE "app"."oauth_access_tokens" (
|
|
225
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
226
|
+
"token" text,
|
|
227
|
+
"client_id" text NOT NULL,
|
|
228
|
+
"session_id" text,
|
|
229
|
+
"user_id" text,
|
|
230
|
+
"reference_id" text,
|
|
231
|
+
"authorization_code_id" text,
|
|
232
|
+
"resources" text[],
|
|
233
|
+
"requested_user_info_claims" text[],
|
|
234
|
+
"refresh_id" text,
|
|
235
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
236
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
237
|
+
"revoked" timestamp with time zone,
|
|
238
|
+
"confirmation" jsonb,
|
|
239
|
+
"scopes" text[] NOT NULL,
|
|
240
|
+
CONSTRAINT "oauth_access_tokens_token_unique" UNIQUE("token")
|
|
241
|
+
);
|
|
242
|
+
--> statement-breakpoint
|
|
243
|
+
CREATE TABLE "app"."oauth_client_assertions" (
|
|
244
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
245
|
+
"expires_at" timestamp with time zone NOT NULL
|
|
246
|
+
);
|
|
247
|
+
--> statement-breakpoint
|
|
248
|
+
CREATE TABLE "app"."oauth_client_resources" (
|
|
249
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
250
|
+
"client_id" text NOT NULL,
|
|
251
|
+
"resource_id" text NOT NULL,
|
|
252
|
+
"metadata" jsonb,
|
|
253
|
+
"created_at" timestamp with time zone
|
|
254
|
+
);
|
|
255
|
+
--> statement-breakpoint
|
|
256
|
+
CREATE TABLE "app"."oauth_clients" (
|
|
257
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
258
|
+
"client_id" text NOT NULL,
|
|
259
|
+
"client_secret" text,
|
|
260
|
+
"client_discovery_id" text,
|
|
261
|
+
"disabled" boolean DEFAULT false,
|
|
262
|
+
"skip_consent" boolean,
|
|
263
|
+
"enable_end_session" boolean,
|
|
264
|
+
"subject_type" text,
|
|
265
|
+
"scopes" text[],
|
|
266
|
+
"client_credentials_scopes" text[] DEFAULT '{}',
|
|
267
|
+
"user_id" text,
|
|
268
|
+
"created_at" timestamp with time zone,
|
|
269
|
+
"updated_at" timestamp with time zone,
|
|
270
|
+
"name" text,
|
|
271
|
+
"uri" text,
|
|
272
|
+
"icon" text,
|
|
273
|
+
"contacts" text[],
|
|
274
|
+
"tos" text,
|
|
275
|
+
"policy" text,
|
|
276
|
+
"software_id" text,
|
|
277
|
+
"software_version" text,
|
|
278
|
+
"software_statement" text,
|
|
279
|
+
"redirect_uris" text[] NOT NULL,
|
|
280
|
+
"post_logout_redirect_uris" text[],
|
|
281
|
+
"backchannel_logout_uri" text,
|
|
282
|
+
"backchannel_logout_session_required" boolean,
|
|
283
|
+
"token_endpoint_auth_method" text,
|
|
284
|
+
"application_type" text,
|
|
285
|
+
"jwks" text,
|
|
286
|
+
"jwks_uri" text,
|
|
287
|
+
"grant_types" text[],
|
|
288
|
+
"response_types" text[],
|
|
289
|
+
"require_pkce" boolean,
|
|
290
|
+
"dpop_bound_access_tokens" boolean DEFAULT false,
|
|
291
|
+
"reference_id" text,
|
|
292
|
+
"metadata" jsonb,
|
|
293
|
+
CONSTRAINT "oauth_clients_client_id_unique" UNIQUE("client_id")
|
|
294
|
+
);
|
|
295
|
+
--> statement-breakpoint
|
|
296
|
+
CREATE TABLE "app"."oauth_consents" (
|
|
297
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
298
|
+
"client_id" text NOT NULL,
|
|
299
|
+
"user_id" text,
|
|
300
|
+
"reference_id" text,
|
|
301
|
+
"resources" text[],
|
|
302
|
+
"requested_user_info_claims" text[],
|
|
303
|
+
"scopes" text[] NOT NULL,
|
|
304
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
305
|
+
"updated_at" timestamp with time zone NOT NULL
|
|
306
|
+
);
|
|
307
|
+
--> statement-breakpoint
|
|
308
|
+
CREATE TABLE "app"."oauth_refresh_tokens" (
|
|
309
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
310
|
+
"token" text NOT NULL,
|
|
311
|
+
"client_id" text NOT NULL,
|
|
312
|
+
"session_id" text,
|
|
313
|
+
"user_id" text NOT NULL,
|
|
314
|
+
"reference_id" text,
|
|
315
|
+
"authorization_code_id" text,
|
|
316
|
+
"resources" text[],
|
|
317
|
+
"requested_user_info_claims" text[],
|
|
318
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
319
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
320
|
+
"revoked" timestamp with time zone,
|
|
321
|
+
"rotated_at" timestamp with time zone,
|
|
322
|
+
"rotation_replay_response" text,
|
|
323
|
+
"rotation_replay_expires_at" timestamp with time zone,
|
|
324
|
+
"auth_time" timestamp with time zone,
|
|
325
|
+
"confirmation" jsonb,
|
|
326
|
+
"scopes" text[] NOT NULL,
|
|
327
|
+
CONSTRAINT "oauth_refresh_tokens_token_unique" UNIQUE("token")
|
|
328
|
+
);
|
|
329
|
+
--> statement-breakpoint
|
|
330
|
+
CREATE TABLE "app"."oauth_resources" (
|
|
331
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
332
|
+
"identifier" text NOT NULL,
|
|
333
|
+
"name" text NOT NULL,
|
|
334
|
+
"access_token_ttl" integer,
|
|
335
|
+
"refresh_token_ttl" integer,
|
|
336
|
+
"signing_algorithm" text,
|
|
337
|
+
"signing_key_id" text,
|
|
338
|
+
"allowed_scopes" text[],
|
|
339
|
+
"custom_claims" jsonb,
|
|
340
|
+
"dpop_bound_access_tokens_required" boolean DEFAULT false,
|
|
341
|
+
"disabled" boolean DEFAULT false,
|
|
342
|
+
"created_at" timestamp with time zone,
|
|
343
|
+
"updated_at" timestamp with time zone,
|
|
344
|
+
"policy_version" integer DEFAULT 1,
|
|
345
|
+
"metadata" jsonb,
|
|
346
|
+
CONSTRAINT "oauth_resources_identifier_unique" UNIQUE("identifier")
|
|
347
|
+
);
|
|
348
|
+
--> statement-breakpoint
|
|
349
|
+
CREATE TABLE "app"."organizations" (
|
|
350
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
351
|
+
"name" text NOT NULL,
|
|
352
|
+
"slug" text,
|
|
353
|
+
"logo" text,
|
|
354
|
+
"type" text,
|
|
355
|
+
"parent_id" text,
|
|
356
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
357
|
+
"onboarding" integer,
|
|
358
|
+
"preferences" jsonb DEFAULT '{}'::jsonb,
|
|
359
|
+
"metadata" jsonb DEFAULT '{}'::jsonb,
|
|
360
|
+
"flags" text[] DEFAULT '{}',
|
|
361
|
+
"locale" text,
|
|
362
|
+
"currency" text,
|
|
363
|
+
"stripe_customer_id" text,
|
|
364
|
+
"stripe_sandbox_customer_id" text,
|
|
365
|
+
"billing_exempt" boolean DEFAULT false NOT NULL,
|
|
366
|
+
"allow_cardless_trial" boolean DEFAULT false NOT NULL,
|
|
367
|
+
"cardless_trial_consumed" jsonb DEFAULT '{}'::jsonb,
|
|
368
|
+
"closed_at" timestamp with time zone,
|
|
369
|
+
CONSTRAINT "organizations_slug_unique" UNIQUE("slug"),
|
|
370
|
+
CONSTRAINT "organizations_stripe_customer_id_unique" UNIQUE("stripe_customer_id"),
|
|
371
|
+
CONSTRAINT "organizations_stripe_sandbox_customer_id_unique" UNIQUE("stripe_sandbox_customer_id")
|
|
372
|
+
);
|
|
373
|
+
--> statement-breakpoint
|
|
374
|
+
CREATE TABLE "app"."posts" (
|
|
375
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
376
|
+
"author_user_id" text,
|
|
377
|
+
"member_id" text,
|
|
378
|
+
"organization_id" text,
|
|
379
|
+
"team_id" text,
|
|
380
|
+
"title" text NOT NULL,
|
|
381
|
+
"slug" text NOT NULL,
|
|
382
|
+
"excerpt" text,
|
|
383
|
+
"content" text NOT NULL,
|
|
384
|
+
"status" text DEFAULT 'draft' NOT NULL,
|
|
385
|
+
"published_at" timestamp with time zone,
|
|
386
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
387
|
+
"updated_at" timestamp with time zone,
|
|
388
|
+
"deleted_at" timestamp with time zone,
|
|
389
|
+
CONSTRAINT "posts_slug_unique" UNIQUE("slug")
|
|
390
|
+
);
|
|
391
|
+
--> statement-breakpoint
|
|
392
|
+
CREATE TABLE "app"."sessions" (
|
|
393
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
394
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
395
|
+
"token" text NOT NULL,
|
|
396
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
397
|
+
"updated_at" timestamp with time zone NOT NULL,
|
|
398
|
+
"ip_address" text,
|
|
399
|
+
"user_agent" text,
|
|
400
|
+
"user_id" text NOT NULL,
|
|
401
|
+
"impersonated_by" text,
|
|
402
|
+
"active_organization_id" text,
|
|
403
|
+
"active_organization_member_id" text,
|
|
404
|
+
"active_organization_role" text,
|
|
405
|
+
"active_organization_type" text,
|
|
406
|
+
CONSTRAINT "sessions_token_unique" UNIQUE("token")
|
|
407
|
+
);
|
|
408
|
+
--> statement-breakpoint
|
|
409
|
+
CREATE TABLE "app"."users" (
|
|
410
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
411
|
+
"name" text NOT NULL,
|
|
412
|
+
"email" text NOT NULL,
|
|
413
|
+
"email_verified" boolean NOT NULL,
|
|
414
|
+
"image" text,
|
|
415
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
416
|
+
"updated_at" timestamp with time zone NOT NULL,
|
|
417
|
+
"role" text,
|
|
418
|
+
"banned" boolean,
|
|
419
|
+
"ban_reason" text,
|
|
420
|
+
"ban_expires" timestamp with time zone,
|
|
421
|
+
"preferences" jsonb DEFAULT '{}'::jsonb,
|
|
422
|
+
"metadata" jsonb DEFAULT '{}'::jsonb,
|
|
423
|
+
"onboarding" integer,
|
|
424
|
+
"flags" text[] DEFAULT '{}',
|
|
425
|
+
"locale" text,
|
|
426
|
+
"closed_at" timestamp with time zone,
|
|
427
|
+
CONSTRAINT "users_email_unique" UNIQUE("email")
|
|
428
|
+
);
|
|
429
|
+
--> statement-breakpoint
|
|
430
|
+
CREATE TABLE "app"."verifications" (
|
|
431
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
432
|
+
"identifier" text NOT NULL,
|
|
433
|
+
"value" text NOT NULL,
|
|
434
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
435
|
+
"created_at" timestamp with time zone,
|
|
436
|
+
"updated_at" timestamp with time zone
|
|
437
|
+
);
|
|
438
|
+
--> statement-breakpoint
|
|
439
|
+
CREATE TABLE "app"."waitlist" (
|
|
440
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
441
|
+
"name" text,
|
|
442
|
+
"email" text,
|
|
443
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
444
|
+
"updated_at" timestamp with time zone,
|
|
445
|
+
"status" text DEFAULT 'WAITLIST' NOT NULL,
|
|
446
|
+
"code" text,
|
|
447
|
+
"expires_at" timestamp with time zone,
|
|
448
|
+
"user_id" text
|
|
449
|
+
);
|
|
450
|
+
--> statement-breakpoint
|
|
451
|
+
CREATE TABLE "app"."workflows" (
|
|
452
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
453
|
+
"user_id" text,
|
|
454
|
+
"job_id" text NOT NULL,
|
|
455
|
+
"job_name" text NOT NULL,
|
|
456
|
+
"queue_name" text NOT NULL,
|
|
457
|
+
"timeout" integer,
|
|
458
|
+
"tags" text[],
|
|
459
|
+
"input" jsonb,
|
|
460
|
+
"output" jsonb,
|
|
461
|
+
"status" text NOT NULL,
|
|
462
|
+
"error" text,
|
|
463
|
+
"retries" integer DEFAULT 0 NOT NULL,
|
|
464
|
+
"finished_at" timestamp with time zone,
|
|
465
|
+
"processed_at" timestamp with time zone,
|
|
466
|
+
"created_at" timestamp with time zone NOT NULL,
|
|
467
|
+
"updated_at" timestamp with time zone NOT NULL,
|
|
468
|
+
CONSTRAINT "workflows_job_id_unique" UNIQUE("job_id")
|
|
469
|
+
);
|
|
470
|
+
--> statement-breakpoint
|
|
471
|
+
ALTER TABLE "app"."account_claim_magic_links" ADD CONSTRAINT "account_claim_magic_links_claim_id_account_claims_id_fk" FOREIGN KEY ("claim_id") REFERENCES "app"."account_claims"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
472
|
+
ALTER TABLE "app"."account_claim_magic_links" ADD CONSTRAINT "account_claim_magic_links_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
473
|
+
ALTER TABLE "app"."account_claims" ADD CONSTRAINT "account_claims_claim_user_id_users_id_fk" FOREIGN KEY ("claim_user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
474
|
+
ALTER TABLE "app"."accounts" ADD CONSTRAINT "accounts_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
475
|
+
ALTER TABLE "app"."ai_usage" ADD CONSTRAINT "ai_usage_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
476
|
+
ALTER TABLE "app"."ai_usage" ADD CONSTRAINT "ai_usage_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
477
|
+
ALTER TABLE "app"."ai_usage" ADD CONSTRAINT "ai_usage_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
478
|
+
ALTER TABLE "app"."apikeys" ADD CONSTRAINT "apikeys_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
479
|
+
ALTER TABLE "app"."chats" ADD CONSTRAINT "chats_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
480
|
+
ALTER TABLE "app"."files" ADD CONSTRAINT "files_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
481
|
+
ALTER TABLE "app"."files" ADD CONSTRAINT "files_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
482
|
+
ALTER TABLE "app"."files" ADD CONSTRAINT "files_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
483
|
+
ALTER TABLE "app"."invitations" ADD CONSTRAINT "invitations_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
484
|
+
ALTER TABLE "app"."invitations" ADD CONSTRAINT "invitations_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
485
|
+
ALTER TABLE "app"."invitations" ADD CONSTRAINT "invitations_inviter_id_users_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
486
|
+
ALTER TABLE "app"."mcp_allowlist_entries" ADD CONSTRAINT "mcp_allowlist_entries_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
487
|
+
ALTER TABLE "app"."mcp_allowlist_entries" ADD CONSTRAINT "mcp_allowlist_entries_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
488
|
+
ALTER TABLE "app"."members" ADD CONSTRAINT "members_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
489
|
+
ALTER TABLE "app"."members" ADD CONSTRAINT "members_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
490
|
+
ALTER TABLE "app"."notification_devices" ADD CONSTRAINT "notification_devices_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
491
|
+
ALTER TABLE "app"."notification_preferences" ADD CONSTRAINT "notification_preferences_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
492
|
+
ALTER TABLE "app"."notification_send_logs" ADD CONSTRAINT "notification_send_logs_notification_id_notifications_id_fk" FOREIGN KEY ("notification_id") REFERENCES "app"."notifications"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
493
|
+
ALTER TABLE "app"."notification_send_logs" ADD CONSTRAINT "notification_send_logs_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
494
|
+
ALTER TABLE "app"."notification_send_logs" ADD CONSTRAINT "notification_send_logs_device_id_notification_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "app"."notification_devices"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
495
|
+
ALTER TABLE "app"."notifications" ADD CONSTRAINT "notifications_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
496
|
+
ALTER TABLE "app"."notifications" ADD CONSTRAINT "notifications_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
497
|
+
ALTER TABLE "app"."oauth_access_tokens" ADD CONSTRAINT "oauth_access_tokens_client_id_oauth_clients_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "app"."oauth_clients"("client_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
498
|
+
ALTER TABLE "app"."oauth_access_tokens" ADD CONSTRAINT "oauth_access_tokens_session_id_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "app"."sessions"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
499
|
+
ALTER TABLE "app"."oauth_access_tokens" ADD CONSTRAINT "oauth_access_tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
500
|
+
ALTER TABLE "app"."oauth_access_tokens" ADD CONSTRAINT "oauth_access_tokens_refresh_id_oauth_refresh_tokens_id_fk" FOREIGN KEY ("refresh_id") REFERENCES "app"."oauth_refresh_tokens"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
501
|
+
ALTER TABLE "app"."oauth_client_resources" ADD CONSTRAINT "oauth_client_resources_client_id_oauth_clients_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "app"."oauth_clients"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
502
|
+
ALTER TABLE "app"."oauth_client_resources" ADD CONSTRAINT "oauth_client_resources_resource_id_oauth_resources_identifier_fk" FOREIGN KEY ("resource_id") REFERENCES "app"."oauth_resources"("identifier") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
503
|
+
ALTER TABLE "app"."oauth_clients" ADD CONSTRAINT "oauth_clients_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
504
|
+
ALTER TABLE "app"."oauth_consents" ADD CONSTRAINT "oauth_consents_client_id_oauth_clients_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "app"."oauth_clients"("client_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
505
|
+
ALTER TABLE "app"."oauth_consents" ADD CONSTRAINT "oauth_consents_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
506
|
+
ALTER TABLE "app"."oauth_refresh_tokens" ADD CONSTRAINT "oauth_refresh_tokens_client_id_oauth_clients_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "app"."oauth_clients"("client_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
507
|
+
ALTER TABLE "app"."oauth_refresh_tokens" ADD CONSTRAINT "oauth_refresh_tokens_session_id_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "app"."sessions"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
508
|
+
ALTER TABLE "app"."oauth_refresh_tokens" ADD CONSTRAINT "oauth_refresh_tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
509
|
+
ALTER TABLE "app"."organizations" ADD CONSTRAINT "organizations_parent_id_organizations_id_fk" FOREIGN KEY ("parent_id") REFERENCES "app"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
510
|
+
ALTER TABLE "app"."posts" ADD CONSTRAINT "posts_author_user_id_users_id_fk" FOREIGN KEY ("author_user_id") REFERENCES "app"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
511
|
+
ALTER TABLE "app"."posts" ADD CONSTRAINT "posts_member_id_members_id_fk" FOREIGN KEY ("member_id") REFERENCES "app"."members"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
512
|
+
ALTER TABLE "app"."posts" ADD CONSTRAINT "posts_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "app"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
513
|
+
ALTER TABLE "app"."sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
514
|
+
ALTER TABLE "app"."waitlist" ADD CONSTRAINT "waitlist_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
515
|
+
ALTER TABLE "app"."workflows" ADD CONSTRAINT "workflows_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "app"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
516
|
+
CREATE UNIQUE INDEX "accounts_issuer_account_id_unique" ON "app"."accounts" USING btree ("issuer","account_id");--> statement-breakpoint
|
|
517
|
+
CREATE UNIQUE INDEX "files_bucket_key_unique" ON "app"."files" USING btree ("bucket","key");--> statement-breakpoint
|
|
518
|
+
CREATE UNIQUE INDEX "mcp_allowlist_client_user_org_unique" ON "app"."mcp_allowlist_entries" USING btree ("oauth_client_id","user_id","organization_id");--> statement-breakpoint
|
|
519
|
+
CREATE UNIQUE INDEX "members_attached_user_organization_unique" ON "app"."members" USING btree ("user_id","organization_id") WHERE "app"."members"."user_id" is not null;--> statement-breakpoint
|
|
520
|
+
CREATE UNIQUE INDEX "members_live_pending_email_organization_unique" ON "app"."members" USING btree ("email","organization_id") WHERE "app"."members"."user_id" is null and "app"."members"."deleted_at" is null;--> statement-breakpoint
|
|
521
|
+
CREATE UNIQUE INDEX "notification_preferences_member_kind_channel_unique" ON "app"."notification_preferences" USING btree ("member_id","kind","channel");--> statement-breakpoint
|
|
522
|
+
CREATE UNIQUE INDEX "oauth_client_resources_client_resource_unique" ON "app"."oauth_client_resources" USING btree ("client_id","resource_id");
|