@allbluecn/database 0.5.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.
Files changed (49) hide show
  1. package/generated/browser.ts +35 -0
  2. package/generated/client.ts +35 -0
  3. package/generated/internal/class.ts +74 -4
  4. package/generated/internal/prismaNamespace.ts +634 -2
  5. package/generated/internal/prismaNamespaceBrowser.ts +108 -1
  6. package/generated/models/EmailLog.ts +1345 -0
  7. package/generated/models/EmailPreference.ts +1257 -0
  8. package/generated/models/EmailSubscriber.ts +1233 -0
  9. package/generated/models/EmailVerificationToken.ts +1380 -0
  10. package/generated/models/InvitationCode.ts +65 -1
  11. package/generated/models/KnowledgeBase.ts +158 -0
  12. package/generated/models/KnowledgeDocument.ts +176 -0
  13. package/generated/models/NotificationPreference.ts +27 -1
  14. package/generated/models/OAuthProviderConfig.ts +1227 -0
  15. package/generated/models/User.ts +2405 -493
  16. package/generated/models/Workspace.ts +380 -0
  17. package/generated/models/WorkspaceKnowledgeBase.ts +1430 -0
  18. package/generated/models/WorkspaceQuickDoc.ts +2030 -0
  19. package/generated/models.ts +7 -0
  20. package/generated-sqlite/browser.ts +40 -0
  21. package/generated-sqlite/client.ts +40 -0
  22. package/generated-sqlite/internal/class.ts +84 -4
  23. package/generated-sqlite/internal/prismaNamespace.ts +722 -3
  24. package/generated-sqlite/internal/prismaNamespaceBrowser.ts +121 -2
  25. package/generated-sqlite/models/EmailLog.ts +1343 -0
  26. package/generated-sqlite/models/EmailPreference.ts +1255 -0
  27. package/generated-sqlite/models/EmailSubscriber.ts +1231 -0
  28. package/generated-sqlite/models/EmailVerificationToken.ts +1377 -0
  29. package/generated-sqlite/models/InvitationCode.ts +65 -1
  30. package/generated-sqlite/models/KnowledgeBase.ts +150 -0
  31. package/generated-sqlite/models/KnowledgeDocument.ts +168 -0
  32. package/generated-sqlite/models/NotificationPreference.ts +1313 -0
  33. package/generated-sqlite/models/OAuthProviderConfig.ts +1225 -0
  34. package/generated-sqlite/models/User.ts +2252 -160
  35. package/generated-sqlite/models/Workspace.ts +300 -0
  36. package/generated-sqlite/models/WorkspaceKnowledgeBase.ts +1426 -0
  37. package/generated-sqlite/models/WorkspaceQuickDoc.ts +2025 -0
  38. package/generated-sqlite/models.ts +8 -0
  39. package/migrations/20260909070745_workspace_kb_card/migration.sql +55 -0
  40. package/migrations/20260909123637_workspace_quick_doc_column_index/migration.sql +2 -0
  41. package/migrations/20260909123656_workspace_quick_doc_column_backfill/migration.sql +4 -0
  42. package/migrations/20260909144328_workspace_quick_doc_label/migration.sql +2 -0
  43. package/migrations/20260909154315_workspace_quick_doc_icon/migration.sql +2 -0
  44. package/migrations/20260911120000_add_pgvector_tables/migration.sql +28 -0
  45. package/migrations/20260911171433_email_auth_invitation/migration.sql +80 -0
  46. package/migrations/20260912032616_email_p4_p8/migration.sql +42 -0
  47. package/package.json +2 -2
  48. package/schema.prisma +141 -14
  49. package/schema.sqlite.prisma +141 -6
@@ -26,8 +26,15 @@ export type * from './models/LoginLog.ts'
26
26
  export type * from './models/InvitationCode.ts'
27
27
  export type * from './models/InvitationUse.ts'
28
28
  export type * from './models/PasswordResetToken.ts'
29
+ export type * from './models/EmailVerificationToken.ts'
30
+ export type * from './models/EmailLog.ts'
31
+ export type * from './models/EmailPreference.ts'
32
+ export type * from './models/OAuthProviderConfig.ts'
33
+ export type * from './models/EmailSubscriber.ts'
29
34
  export type * from './models/KnowledgeBase.ts'
30
35
  export type * from './models/ProjectKnowledgeBase.ts'
36
+ export type * from './models/WorkspaceKnowledgeBase.ts'
37
+ export type * from './models/WorkspaceQuickDoc.ts'
31
38
  export type * from './models/KnowledgeDocument.ts'
32
39
  export type * from './models/PRD.ts'
33
40
  export type * from './models/AgentConversation.ts'
@@ -90,4 +97,5 @@ export type * from './models/DeveloperLog.ts'
90
97
  export type * from './models/Story.ts'
91
98
  export type * from './models/Iteration.ts'
92
99
  export type * from './models/IterationAutoSchedule.ts'
100
+ export type * from './models/NotificationPreference.ts'
93
101
  export type * from './commonInputTypes.ts'
@@ -0,0 +1,55 @@
1
+ -- CreateTable
2
+ CREATE TABLE "workspace_knowledge_bases" (
3
+ "id" TEXT NOT NULL,
4
+ "workspaceId" TEXT NOT NULL,
5
+ "kbId" TEXT NOT NULL,
6
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
7
+
8
+ CONSTRAINT "workspace_knowledge_bases_pkey" PRIMARY KEY ("id")
9
+ );
10
+
11
+ -- CreateTable
12
+ CREATE TABLE "workspace_quick_docs" (
13
+ "id" TEXT NOT NULL,
14
+ "workspaceId" TEXT NOT NULL,
15
+ "docId" TEXT,
16
+ "externalGroup" TEXT,
17
+ "externalId" TEXT,
18
+ "displayTitle" TEXT NOT NULL,
19
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
20
+ "createdBy" TEXT NOT NULL,
21
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
22
+ "updatedAt" TIMESTAMP(3) NOT NULL,
23
+
24
+ CONSTRAINT "workspace_quick_docs_pkey" PRIMARY KEY ("id")
25
+ );
26
+
27
+ -- CreateIndex
28
+ CREATE INDEX "workspace_knowledge_bases_workspaceId_idx" ON "workspace_knowledge_bases"("workspaceId");
29
+
30
+ -- CreateIndex
31
+ CREATE INDEX "workspace_knowledge_bases_kbId_idx" ON "workspace_knowledge_bases"("kbId");
32
+
33
+ -- CreateIndex
34
+ CREATE UNIQUE INDEX "workspace_knowledge_bases_workspaceId_kbId_key" ON "workspace_knowledge_bases"("workspaceId", "kbId");
35
+
36
+ -- CreateIndex
37
+ CREATE INDEX "workspace_quick_docs_workspaceId_idx" ON "workspace_quick_docs"("workspaceId");
38
+
39
+ -- CreateIndex
40
+ CREATE INDEX "workspace_quick_docs_workspaceId_docId_idx" ON "workspace_quick_docs"("workspaceId", "docId");
41
+
42
+ -- AddForeignKey
43
+ ALTER TABLE "workspace_knowledge_bases" ADD CONSTRAINT "workspace_knowledge_bases_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
44
+
45
+ -- AddForeignKey
46
+ ALTER TABLE "workspace_knowledge_bases" ADD CONSTRAINT "workspace_knowledge_bases_kbId_fkey" FOREIGN KEY ("kbId") REFERENCES "knowledge_bases"("id") ON DELETE CASCADE ON UPDATE CASCADE;
47
+
48
+ -- AddForeignKey
49
+ ALTER TABLE "workspace_quick_docs" ADD CONSTRAINT "workspace_quick_docs_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
50
+
51
+ -- AddForeignKey
52
+ ALTER TABLE "workspace_quick_docs" ADD CONSTRAINT "workspace_quick_docs_docId_fkey" FOREIGN KEY ("docId") REFERENCES "knowledge_documents"("id") ON DELETE CASCADE ON UPDATE CASCADE;
53
+
54
+ -- AddForeignKey
55
+ ALTER TABLE "workspace_quick_docs" ADD CONSTRAINT "workspace_quick_docs_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "workspace_quick_docs" ADD COLUMN "columnIndex" INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,4 @@
1
+ -- 看板化回填:旧模型按 sortOrder % 5 轮转分列,迁移后按此初始化列归属
2
+ UPDATE "workspace_quick_docs"
3
+ SET "columnIndex" = "sortOrder" % 5
4
+ WHERE "columnIndex" = 0 AND "sortOrder" % 5 <> 0;
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "workspace_quick_docs" ADD COLUMN "label" TEXT;
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "workspace_quick_docs" ADD COLUMN "icon" TEXT;
@@ -0,0 +1,28 @@
1
+ -- pgvector 原生向量表(非 Prisma 模型,由 apps/web/src/lib/vector-store/pg-vector-store.ts 以 raw SQL 读写)
2
+ -- 此前仅在开发库手工建表,缺失即报 42P01(relation does not exist)。
3
+ -- 幂等:IF NOT EXISTS,已手工建过表的库安全跳过。
4
+ CREATE EXTENSION IF NOT EXISTS vector;
5
+
6
+ CREATE TABLE IF NOT EXISTS "knowledge_embeddings" (
7
+ "id" TEXT NOT NULL,
8
+ "content" TEXT NOT NULL,
9
+ "kbId" TEXT,
10
+ "documentId" TEXT,
11
+ "prdPageId" TEXT,
12
+ "chunkIndex" INTEGER,
13
+ "embedding" vector(1536) NOT NULL,
14
+ CONSTRAINT "knowledge_embeddings_pkey" PRIMARY KEY ("id")
15
+ );
16
+
17
+ CREATE TABLE IF NOT EXISTS "prd_embeddings" (
18
+ "id" TEXT NOT NULL,
19
+ "content" TEXT NOT NULL,
20
+ "prdPageId" TEXT,
21
+ "chunkIndex" INTEGER,
22
+ "embedding" vector(1536) NOT NULL,
23
+ CONSTRAINT "prd_embeddings_pkey" PRIMARY KEY ("id")
24
+ );
25
+
26
+ CREATE INDEX IF NOT EXISTS "knowledge_embeddings_kbid_idx" ON "knowledge_embeddings"("kbId");
27
+ CREATE INDEX IF NOT EXISTS "knowledge_embeddings_documentid_idx" ON "knowledge_embeddings"("documentId");
28
+ CREATE INDEX IF NOT EXISTS "prd_embeddings_prdpageid_idx" ON "prd_embeddings"("prdPageId");
@@ -0,0 +1,80 @@
1
+ -- AlterTable
2
+ ALTER TABLE "invitation_codes" ADD COLUMN "createdById" TEXT,
3
+ ADD COLUMN "disabledAt" TIMESTAMP(3);
4
+
5
+ -- CreateTable
6
+ CREATE TABLE "email_verification_tokens" (
7
+ "id" TEXT NOT NULL,
8
+ "token" TEXT NOT NULL,
9
+ "userId" TEXT NOT NULL,
10
+ "expiresAt" TIMESTAMP(3) NOT NULL,
11
+ "usedAt" TIMESTAMP(3),
12
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+
14
+ CONSTRAINT "email_verification_tokens_pkey" PRIMARY KEY ("id")
15
+ );
16
+
17
+ -- CreateTable
18
+ CREATE TABLE "email_logs" (
19
+ "id" TEXT NOT NULL,
20
+ "to" TEXT NOT NULL,
21
+ "templateKey" TEXT NOT NULL,
22
+ "category" TEXT NOT NULL,
23
+ "status" TEXT NOT NULL,
24
+ "provider" TEXT NOT NULL,
25
+ "messageId" TEXT,
26
+ "dedupeKey" TEXT,
27
+ "error" TEXT,
28
+ "userId" TEXT,
29
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
30
+ "sentAt" TIMESTAMP(3),
31
+
32
+ CONSTRAINT "email_logs_pkey" PRIMARY KEY ("id")
33
+ );
34
+
35
+ -- CreateTable
36
+ CREATE TABLE "email_preferences" (
37
+ "userId" TEXT NOT NULL,
38
+ "unsubscribedAll" BOOLEAN NOT NULL DEFAULT false,
39
+ "unsubscribedCategories" JSONB NOT NULL DEFAULT '[]',
40
+ "suppressed" BOOLEAN NOT NULL DEFAULT false,
41
+
42
+ CONSTRAINT "email_preferences_pkey" PRIMARY KEY ("userId")
43
+ );
44
+
45
+ -- CreateIndex
46
+ CREATE UNIQUE INDEX "email_verification_tokens_token_key" ON "email_verification_tokens"("token");
47
+
48
+ -- CreateIndex
49
+ CREATE UNIQUE INDEX "email_logs_dedupeKey_key" ON "email_logs"("dedupeKey");
50
+
51
+ -- CreateIndex
52
+ CREATE INDEX "email_logs_to_createdAt_idx" ON "email_logs"("to", "createdAt");
53
+
54
+ -- CreateIndex
55
+ CREATE INDEX "email_logs_userId_createdAt_idx" ON "email_logs"("userId", "createdAt");
56
+
57
+ -- CreateIndex
58
+ CREATE INDEX "email_logs_status_idx" ON "email_logs"("status");
59
+
60
+ -- AddForeignKey
61
+ ALTER TABLE "email_verification_tokens" ADD CONSTRAINT "email_verification_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
62
+
63
+ -- AddForeignKey
64
+ ALTER TABLE "email_preferences" ADD CONSTRAINT "email_preferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
65
+
66
+ -- 存量邮箱小写归一(注册流程从此统一 toLowerCase 写入)。
67
+ -- 零数据丢失策略:只归一,绝不删除任何用户行。
68
+ -- users.email 为 @unique,若线上已存在仅大小写不同的重复邮箱,直接 LOWER 会撞唯一约束
69
+ -- 导致整个迁移事务回滚。此处显式检测并 RAISE EXCEPTION,交人工裁决(手动改邮箱或合并账号)
70
+ -- 后再应用迁移,避免静默改邮箱或删账号造成的不可逆后果。
71
+ DO $$
72
+ DECLARE n integer;
73
+ BEGIN
74
+ SELECT count(*) INTO n
75
+ FROM (SELECT 1 FROM "users" GROUP BY LOWER("email") HAVING count(*) > 1) AS dupes;
76
+ IF n > 0 THEN
77
+ RAISE EXCEPTION '发现 % 组大小写重复邮箱,请先人工处理(改邮箱或合并账号)再应用本迁移', n;
78
+ END IF;
79
+ UPDATE "users" SET "email" = LOWER("email") WHERE "email" != LOWER("email");
80
+ END $$;
@@ -0,0 +1,42 @@
1
+ -- AlterTable
2
+ ALTER TABLE "notification_preferences" ADD COLUMN "emailCategories" JSONB NOT NULL DEFAULT '{}';
3
+
4
+ -- CreateTable
5
+ CREATE TABLE "oauth_provider_configs" (
6
+ "id" TEXT NOT NULL,
7
+ "provider" TEXT NOT NULL,
8
+ "clientId" TEXT NOT NULL,
9
+ "clientSecret" TEXT NOT NULL,
10
+ "enabled" BOOLEAN NOT NULL DEFAULT false,
11
+ "extra" JSONB,
12
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+ "updatedAt" TIMESTAMP(3) NOT NULL,
14
+
15
+ CONSTRAINT "oauth_provider_configs_pkey" PRIMARY KEY ("id")
16
+ );
17
+
18
+ -- CreateTable
19
+ CREATE TABLE "email_subscribers" (
20
+ "id" TEXT NOT NULL,
21
+ "email" TEXT NOT NULL,
22
+ "locale" TEXT NOT NULL DEFAULT 'zh',
23
+ "confirmToken" TEXT NOT NULL,
24
+ "confirmedAt" TIMESTAMP(3),
25
+ "unsubscribedAt" TIMESTAMP(3),
26
+ "source" TEXT NOT NULL DEFAULT 'changelog',
27
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
28
+
29
+ CONSTRAINT "email_subscribers_pkey" PRIMARY KEY ("id")
30
+ );
31
+
32
+ -- CreateIndex
33
+ CREATE UNIQUE INDEX "oauth_provider_configs_provider_key" ON "oauth_provider_configs"("provider");
34
+
35
+ -- CreateIndex
36
+ CREATE UNIQUE INDEX "email_subscribers_email_key" ON "email_subscribers"("email");
37
+
38
+ -- CreateIndex
39
+ CREATE UNIQUE INDEX "email_subscribers_confirmToken_key" ON "email_subscribers"("confirmToken");
40
+
41
+ -- CreateIndex
42
+ CREATE INDEX "email_subscribers_confirmedAt_unsubscribedAt_idx" ON "email_subscribers"("confirmedAt", "unsubscribedAt");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allbluecn/database",
3
- "version": "0.5.0",
3
+ "version": "0.8.0",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "pg": "^8.22.0",
16
16
  "sqlite-vec": "^0.1.9",
17
17
  "bcryptjs": "^3.0.2",
18
- "@allbluecn/kernel": "0.6.0"
18
+ "@allbluecn/kernel": "0.8.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/better-sqlite3": "^7.6.13",
package/schema.prisma CHANGED
@@ -60,6 +60,8 @@ model User {
60
60
  invitationUses InvitationUse[]
61
61
  loginLogs LoginLog[]
62
62
  passwordResetTokens PasswordResetToken[]
63
+ emailVerificationTokens EmailVerificationToken[]
64
+ emailPreference EmailPreference?
63
65
  prds PRD[]
64
66
  tags Tag[]
65
67
  knowledgeBases KnowledgeBase[]
@@ -114,6 +116,7 @@ model User {
114
116
  ssoMappings SsoMapping[]
115
117
  roleAssignments RoleAssignment[]
116
118
  subscription Subscription?
119
+ createdQuickDocs WorkspaceQuickDoc[]
117
120
 
118
121
  @@map("users")
119
122
  }
@@ -194,8 +197,10 @@ model Workspace {
194
197
  owner User @relation("workspaceOwner", fields: [ownerId], references: [id])
195
198
  projects Project[]
196
199
  members WorkspaceMember[]
197
- knowledgeBases KnowledgeBase[]
198
- usageRecords UsageRecord[]
200
+ knowledgeBases KnowledgeBase[]
201
+ workspaceKbLinks WorkspaceKnowledgeBase[]
202
+ quickDocs WorkspaceQuickDoc[]
203
+ usageRecords UsageRecord[]
199
204
  aiUsageLogs AiUsageLog[]
200
205
  createdAt DateTime @default(now())
201
206
  updatedAt DateTime @updatedAt
@@ -419,12 +424,14 @@ model LoginLog {
419
424
 
420
425
  // 邀请码
421
426
  model InvitationCode {
422
- id String @id @default(cuid())
423
- code String @unique
424
- maxUses Int @default(1)
425
- usedCount Int @default(0)
426
- expiresAt DateTime
427
- createdAt DateTime @default(now())
427
+ id String @id @default(cuid())
428
+ code String @unique
429
+ maxUses Int @default(1)
430
+ usedCount Int @default(0)
431
+ expiresAt DateTime
432
+ createdAt DateTime @default(now())
433
+ createdById String?
434
+ disabledAt DateTime?
428
435
 
429
436
  uses InvitationUse[]
430
437
 
@@ -458,6 +465,82 @@ model PasswordResetToken {
458
465
  @@map("password_reset_tokens")
459
466
  }
460
467
 
468
+ // 邮箱验证令牌
469
+ model EmailVerificationToken {
470
+ id String @id @default(cuid())
471
+ token String @unique
472
+ userId String
473
+ expiresAt DateTime
474
+ usedAt DateTime?
475
+ createdAt DateTime @default(now())
476
+
477
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
478
+
479
+ @@map("email_verification_tokens")
480
+ }
481
+
482
+ // 出站邮件日志
483
+ model EmailLog {
484
+ id String @id @default(cuid())
485
+ to String
486
+ templateKey String
487
+ category String
488
+ status String
489
+ provider String
490
+ messageId String?
491
+ dedupeKey String? @unique
492
+ error String?
493
+ userId String?
494
+ createdAt DateTime @default(now())
495
+ sentAt DateTime?
496
+
497
+ @@index([to, createdAt])
498
+ @@index([userId, createdAt])
499
+ @@index([status])
500
+ @@map("email_logs")
501
+ }
502
+
503
+ // 用户邮件偏好
504
+ model EmailPreference {
505
+ userId String @id
506
+ unsubscribedAll Boolean @default(false)
507
+ unsubscribedCategories Json @default("[]")
508
+ suppressed Boolean @default(false)
509
+
510
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
511
+
512
+ @@map("email_preferences")
513
+ }
514
+
515
+ // 第三方登录配置(admin 后台维护)
516
+ model OAuthProviderConfig {
517
+ id String @id @default(cuid())
518
+ provider String @unique
519
+ clientId String
520
+ clientSecret String // AES-256-GCM 密文
521
+ enabled Boolean @default(false)
522
+ extra Json?
523
+ createdAt DateTime @default(now())
524
+ updatedAt DateTime @updatedAt
525
+
526
+ @@map("oauth_provider_configs")
527
+ }
528
+
529
+ // 产品更新订阅者(changelog)
530
+ model EmailSubscriber {
531
+ id String @id @default(cuid())
532
+ email String @unique
533
+ locale String @default("zh")
534
+ confirmToken String @unique
535
+ confirmedAt DateTime?
536
+ unsubscribedAt DateTime?
537
+ source String @default("changelog")
538
+ createdAt DateTime @default(now())
539
+
540
+ @@index([confirmedAt, unsubscribedAt])
541
+ @@map("email_subscribers")
542
+ }
543
+
461
544
  enum Role {
462
545
  SUPER_ADMIN
463
546
  ADMIN
@@ -513,6 +596,7 @@ model KnowledgeBase {
513
596
  workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: SetNull)
514
597
  documents KnowledgeDocument[]
515
598
  projectLinks ProjectKnowledgeBase[]
599
+ workspaceLinks WorkspaceKnowledgeBase[]
516
600
 
517
601
  @@index([userId])
518
602
  @@index([workspaceId])
@@ -541,6 +625,7 @@ model KnowledgeDocument {
541
625
  children KnowledgeDocument[] @relation("DocumentTree")
542
626
  creator User @relation(fields: [createdBy], references: [id], onDelete: Cascade)
543
627
  linkedStories StoryDocLink[] @relation("DocStoryLinks")
628
+ workspaceQuickDocs WorkspaceQuickDoc[]
544
629
 
545
630
  @@index([kbId])
546
631
  @@index([parentId])
@@ -1590,6 +1675,47 @@ model ProjectKnowledgeBase {
1590
1675
  @@map("project_knowledge_bases")
1591
1676
  }
1592
1677
 
1678
+ // 工作空间关联知识库(join 表;仅允许 visibility=team)
1679
+ model WorkspaceKnowledgeBase {
1680
+ id String @id @default(cuid())
1681
+ workspaceId String
1682
+ kbId String
1683
+ createdAt DateTime @default(now())
1684
+
1685
+ workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
1686
+ kb KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade)
1687
+
1688
+ @@unique([workspaceId, kbId])
1689
+ @@index([workspaceId])
1690
+ @@index([kbId])
1691
+ @@map("workspace_knowledge_bases")
1692
+ }
1693
+
1694
+ // 工作空间快捷文档(单表双轨:docId 或 externalGroup+externalId 二选一非空,serverFn 层校验)
1695
+ model WorkspaceQuickDoc {
1696
+ id String @id @default(cuid())
1697
+ workspaceId String
1698
+ docId String?
1699
+ externalGroup String?
1700
+ externalId String?
1701
+ displayTitle String
1702
+ columnIndex Int @default(0)
1703
+ sortOrder Int @default(0)
1704
+ label String?
1705
+ icon String?
1706
+ createdBy String
1707
+ createdAt DateTime @default(now())
1708
+ updatedAt DateTime @updatedAt
1709
+
1710
+ workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
1711
+ doc KnowledgeDocument? @relation(fields: [docId], references: [id], onDelete: Cascade)
1712
+ creator User @relation(fields: [createdBy], references: [id], onDelete: Cascade)
1713
+
1714
+ @@index([workspaceId])
1715
+ @@index([workspaceId, docId])
1716
+ @@map("workspace_quick_docs")
1717
+ }
1718
+
1593
1719
  model StoryLink {
1594
1720
  id String @id @default(cuid())
1595
1721
  storyId String
@@ -2147,12 +2273,13 @@ model Notification {
2147
2273
 
2148
2274
  // 通知偏好(免打扰时段、分类开关)
2149
2275
  model NotificationPreference {
2150
- userId String @id
2151
- categories Json
2152
- dndEnabled Boolean @default(false)
2153
- dndStart String @default("22:00")
2154
- dndEnd String @default("08:00")
2155
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2276
+ userId String @id
2277
+ categories Json
2278
+ emailCategories Json @default("{}")
2279
+ dndEnabled Boolean @default(false)
2280
+ dndStart String @default("22:00")
2281
+ dndEnd String @default("08:00")
2282
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2156
2283
 
2157
2284
  @@map("notification_preferences")
2158
2285
  }