feat(db): teams schema + preferences.mutable migration (#175)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #175.
This commit is contained in:
44
packages/db/drizzle/0002_nebulous_mimic.sql
Normal file
44
packages/db/drizzle/0002_nebulous_mimic.sql
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
CREATE TABLE "team_members" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"team_id" uuid NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"role" text DEFAULT 'member' NOT NULL,
|
||||||
|
"invited_by" text,
|
||||||
|
"joined_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "teams" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"slug" text NOT NULL,
|
||||||
|
"owner_id" text NOT NULL,
|
||||||
|
"manager_id" text NOT NULL,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
CONSTRAINT "teams_slug_unique" UNIQUE("slug")
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "project_id" uuid;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "owner_id" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "system_prompt" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "allowed_tools" jsonb;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "skills" jsonb;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD COLUMN "is_system" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "conversations" ADD COLUMN "agent_id" uuid;--> statement-breakpoint
|
||||||
|
ALTER TABLE "preferences" ADD COLUMN "mutable" boolean DEFAULT true NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "projects" ADD COLUMN "team_id" uuid;--> statement-breakpoint
|
||||||
|
ALTER TABLE "projects" ADD COLUMN "owner_type" text DEFAULT 'user' NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "team_members" ADD CONSTRAINT "team_members_team_id_teams_id_fk" FOREIGN KEY ("team_id") REFERENCES "public"."teams"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "team_members" ADD CONSTRAINT "team_members_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "team_members" ADD CONSTRAINT "team_members_invited_by_users_id_fk" FOREIGN KEY ("invited_by") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "teams" ADD CONSTRAINT "teams_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "teams" ADD CONSTRAINT "teams_manager_id_users_id_fk" FOREIGN KEY ("manager_id") REFERENCES "public"."users"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "team_members_team_user_idx" ON "team_members" USING btree ("team_id","user_id");--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD CONSTRAINT "agents_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "agents" ADD CONSTRAINT "agents_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "conversations" ADD CONSTRAINT "conversations_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "projects" ADD CONSTRAINT "projects_team_id_teams_id_fk" FOREIGN KEY ("team_id") REFERENCES "public"."teams"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
CREATE INDEX "agents_project_id_idx" ON "agents" USING btree ("project_id");--> statement-breakpoint
|
||||||
|
CREATE INDEX "agents_owner_id_idx" ON "agents" USING btree ("owner_id");--> statement-breakpoint
|
||||||
|
CREATE INDEX "agents_is_system_idx" ON "agents" USING btree ("is_system");--> statement-breakpoint
|
||||||
|
CREATE INDEX "conversations_agent_id_idx" ON "conversations" USING btree ("agent_id");
|
||||||
2435
packages/db/drizzle/meta/0002_snapshot.json
Normal file
2435
packages/db/drizzle/meta/0002_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,13 @@
|
|||||||
"when": 1773602195609,
|
"when": 1773602195609,
|
||||||
"tag": "0001_magical_rattler",
|
"tag": "0001_magical_rattler",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 2,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1773625181629,
|
||||||
|
"tag": "0002_nebulous_mimic",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
uuid,
|
uuid,
|
||||||
jsonb,
|
jsonb,
|
||||||
index,
|
index,
|
||||||
|
uniqueIndex,
|
||||||
real,
|
real,
|
||||||
integer,
|
integer,
|
||||||
customType,
|
customType,
|
||||||
@@ -72,6 +73,44 @@ export const verifications = pgTable('verifications', {
|
|||||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ─── Teams ───────────────────────────────────────────────────────────────────
|
||||||
|
// Declared before projects because projects references teams.
|
||||||
|
|
||||||
|
export const teams = pgTable('teams', {
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
name: text('name').notNull(),
|
||||||
|
slug: text('slug').notNull().unique(),
|
||||||
|
ownerId: text('owner_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: 'restrict' }),
|
||||||
|
managerId: text('manager_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: 'restrict' }),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const teamMembers = pgTable(
|
||||||
|
'team_members',
|
||||||
|
{
|
||||||
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
teamId: uuid('team_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => teams.id, { onDelete: 'cascade' }),
|
||||||
|
userId: text('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: 'cascade' }),
|
||||||
|
role: text('role', { enum: ['manager', 'member'] })
|
||||||
|
.notNull()
|
||||||
|
.default('member'),
|
||||||
|
invitedBy: text('invited_by').references(() => users.id, { onDelete: 'set null' }),
|
||||||
|
joinedAt: timestamp('joined_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
},
|
||||||
|
(t) => ({
|
||||||
|
uniq: uniqueIndex('team_members_team_user_idx').on(t.teamId, t.userId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// ─── Brain ───────────────────────────────────────────────────────────────────
|
// ─── Brain ───────────────────────────────────────────────────────────────────
|
||||||
// Declared before Chat because conversations references projects.
|
// Declared before Chat because conversations references projects.
|
||||||
|
|
||||||
@@ -83,6 +122,10 @@ export const projects = pgTable('projects', {
|
|||||||
.notNull()
|
.notNull()
|
||||||
.default('active'),
|
.default('active'),
|
||||||
ownerId: text('owner_id').references(() => users.id, { onDelete: 'set null' }),
|
ownerId: text('owner_id').references(() => users.id, { onDelete: 'set null' }),
|
||||||
|
teamId: uuid('team_id').references(() => teams.id, { onDelete: 'cascade' }),
|
||||||
|
ownerType: text('owner_type', { enum: ['user', 'team'] })
|
||||||
|
.notNull()
|
||||||
|
.default('user'),
|
||||||
metadata: jsonb('metadata'),
|
metadata: jsonb('metadata'),
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
@@ -320,6 +363,7 @@ export const preferences = pgTable(
|
|||||||
.notNull()
|
.notNull()
|
||||||
.default('general'),
|
.default('general'),
|
||||||
source: text('source'),
|
source: text('source'),
|
||||||
|
mutable: boolean('mutable').notNull().default(true),
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user