MODEL.md 2.65 KB

@drama/db 表关系设计纪律

本文件兑现任务文档 §2 验收标准 6:列出每张业务表到 users 表的外键可达路径,证明「user 级联可整体删除 / 可导出」的口子(架构基线 §10.1「数据可删除」)在一期就以纯纪律留好——二期实现 cascadeDeleteUser(db, userId) / exportUser(db, userId) 时无需穿透改表结构。

根锚:users

users 是全库唯一的级联根。本包 src/db/tables/users.cjs 提供这一张跨域共享的根表。其余业务表由各领域包(@drama/auth / @drama/account / @drama/billing / @drama/payment / @drama/email / ...)自己的 src/db/tables/* 提供。

硬约束(领域包建表时必须遵守)

每张业务表必须满足下列其一,保证到 users.id 有可遍历的外键路径:

  1. 直接挂:表含 user_id BIGINT 外键,references users.id。适用于 user 直属数据(资料、积分账户、订阅、播放历史、收藏、创建的 drama)。
  2. 一层可达:表经父表的外键间接可达 users。例如 episode.drama_id → drama.id,而 drama.user_id → users.id;则 episode 经 drama 一层可达。
  3. 全局共享、无属主:不挂 user 的纯字典 / 素材池(如官方种子素材、系统枚举)显式标注「无属主」,级联删除时跳过、导出时不含。这类表必须在其领域包 MODEL.md 中明示,避免被误判为「漏挂 user_id」。

级联可达路径示意(领域表二期落地后填充)

一期本包只锚定根表,下表是约定示意(实际由各领域包 table definition 落地并在各自文档登记其可达路径):

  • users ← drama.user_id(直接)
  • drama ← episode.drama_id(一层经 drama 到 users)
  • drama ← play_record.drama_id + play_record.user_id(直接 + 冗余直挂,便于按 user 整段删)
  • users ← subscription.user_id / credit_account.user_id / favorite.user_id(直接)

软删除约定

deleted_at TIMESTAMP NULL 为软删除标记,与 helpers.notDeleted(qb)(where deleted_at is null)配套。需要软删除语义的表统一用此列名,保证 helper 复用。

二期实现留口子(本包不实现,仅此设计支撑)

  • cascadeDeleteUser(db, userId):从 users.id 出发,沿上述外键路径自顶向下删除(或软删)所有归属该 user 的行。
  • exportUser(db, userId):同一遍历,收集而非删除,产出可导出的 user 数据快照(GDPR/CCPA 数据导出)。

只要领域包建表时遵守上述硬约束,这两个遍历器二期可纯靠外键元数据驱动实现,无需回头改表结构。