Files
ZY-Agent/docs/multi-tenant-redesign/03-impl/pr3-workspaces.zh-CN.md
T
1445043649 240c6bd0e2 docs(mt): 统一 multi-tenant-redesign 命名约定 + README 补执行层索引
命名统一为 .zh-CN.md 后缀(与既有 17 个文件 + README 一致):
- 03-impl/{pr1-8,STATUS}.md → *.zh-CN.md
- Stage 1 spec 去日期前缀、加 .zh-CN,对齐 01-redesign 语义命名

README.zh-CN.md 修复 4 处不统一:
- 顶部加进度指引(现状只信 STATUS,本文是设计/路线导航)
- §0 文档总图补 03-impl 层 + Stage 1 spec + 命名约定注
- §1 表加 Stage 1 spec 行;新增 §1.1 执行记录层(STATUS + 8 impl note 索引)
- §7 阅读路径首次进项目/Stage 1 均加 STATUS + spec 入口

同步更新所有交叉链接(STATUS/pr/spec 自引用、database-schema-as-built、
根 README_zh.md、Stage 0 master plan);全树相对链接校验可达。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 10:40:42 +08:00

5.4 KiB
Raw Blame History

PR3 · workspaces + workspace_memberships 表 + 仓储

实现笔记。对应 docs/superpowers/plans/2026-05-10-stage-0-multi-tenant-foundation.md PR3T3.1-T3.10)。

状态:已落地9 commits 提交在 branch feat/stage-0-pr3-workspaces

范围

新建 workspaces + workspace_memberships 两张表 + 仓储 + ContextVar + 47 个单测。这是 Stage 0 schema 基础设施的核心——后续 PR4 注册改造、PR5 ALTER 现有表、PR6 入口校验都依赖这层。

不在范围(后续 PR):

  • 注册流程改造 / JWT 加 wid+rolePR4
  • alembic revisionPR4 起,因 ALTER 现有表才需要)
  • workspace_id 列加到 threads_meta 等(PR5
  • 入口路由 (wid, tid) 校验(PR6

验收

  • 47 个新单测全过(16 workspace_context + 23 workspace_repo + 8 membership_repo
  • 全套 pytest tests/ 3134 passed + 25 skipped + 0 failedPR2 末 3087 + 47 新;+2 PG-only skip
  • partial unique on owner 在 SQLite ephemeral DBtest_cannot_add_second_owner+ 远程 RDS PG 17.9live 验证)双驱动通过
  • CASCADE 在 SQLite 上验过(test_delete_cascades_to_memberships / test_cascade_delete_user_removes_memberships
  • RDS 上 workspaces + workspace_memberships 表 + 索引(含 partial uniquelive create_all 出来:
    idx_one_owner_per_workspace
      UNIQUE INDEX ... (workspace_id) WHERE ((role)::text = 'owner'::text)
    idx_workspace_memberships_user (user_id, workspace_id)
    workspace_memberships_pkey UNIQUE (workspace_id, user_id)
    
  • CI workflow 上跑 @pytest.mark.postgres → 实跑 partial-unique PG twin — 待 PR push 后 GH Actions 验

关键决策(LOCK 项 — 与 plan §横切 + workspace-schema-design §5 对齐)

选择 理由
表名 workspaces + workspace_memberships workspace-schema-design 锁定
ID 类型 String(36) UUID v4 字符串 users.id 类型对齐,跨 SQLite/PG 可移植
Membership PK 复合 (workspace_id, user_id) 工业实践默认;surrogate id 没必要
Role 类型 String(16) + 应用层校验 不用 PG enumALTER TYPE 加值痛苦);Stage 0 写 ownerStage 2 开 admin/member
Partial unique on owner Index(..., sqlite_where=text(...), postgresql_where=text(...)) 双 where 并存 SQLite + PG 都支持;T3.8 PG twin 验语义一致
Owner FK 删除策略 ON DELETE RESTRICT 删 user 时阻拦(必须先转让 owner);transfer 流程放 PR4
Membership FK 删除策略 ON DELETE CASCADE (workspace_id + user_id) 删 workspace / 删 user 时自动清成员;逻辑上正确
invited_by 删除策略 ON DELETE SET NULL 邀请人离开不影响成员;只清字段
Slug 校验位置 应用层 _validate_slug + DB UNIQUE DB 不知道 regex / 黑名单;应用层规则可演进
Slug 黑名单 25 个保留字(admin/api/auth/...frozenset 在 workspace/sql.py workspace-schema-design §2.1 完整列表
WorkspaceRepository.create 不自动建 owner 成员 单一职责;注册流程在事务内同时写 workspace + membership
WorkspaceRepository.get JOIN memberships 做 access 检查 默认安全;显式 user_id=None 跳过用于迁移
WorkspaceRepository.get_by_slug 做 access 检查 path-based routing 用:先 slug→wid 再 route handler 查成员
Owner transfer 不在仓储层实现 需要两行事务原子 swap,应在 auth router 内带权限检查

跟进项(不在 PR3 范围)

  • PR4 注册流程:/auth/initialize + /auth/registerWorkspaceRepository.create + WorkspaceMembershipRepository.add(role='owner') 在一个事务里建
  • PR4 alembic 0001:加 users.default_workspace_id 列(也 FK 到 workspaces
  • PR4 _auto_workspace_context autouse fixture:现在 tests/test_workspace_repo 测试自己 set/reset 而不依赖 autousePR4 引入后简化
  • backend/CLAUDE.md:等 PR4 完成时一并补 Database + Workspace 段(PR2 follow-up + 现在的 schema

涉及文件

类别 文件
ContextVar runtime/workspace_context.py
ORM persistence/workspace/{__init__.py, model.py, sql.py}
ORM persistence/workspace_membership/{__init__.py, model.py, sql.py}
注册 persistence/models/__init__.py(加 2 个 import
测试 tests/test_workspace_context.py16 test
测试 tests/test_workspace_repo.py23 test
测试 tests/test_workspace_membership_repo.py8 test
测试 tests/test_workspace_partial_unique_postgres.py2 PG-only

提交记录

9 commits(含 T3.9 live verification 不发 commit):

f63089ae feat(runtime): add workspace_context module + tests             T3.1 + T3.2
8323bf68 feat(persistence): add WorkspaceRow ORM model                   T3.3
d2d2d29c feat(persistence): add WorkspaceMembershipRow ORM model         T3.6
a40df035 feat(persistence): WorkspaceRepository + 23 unit tests          T3.4 + T3.5
36ffe271 feat(persistence): WorkspaceMembershipRepository + 8 unit tests T3.7
3313047f test(workspace): partial unique on owner — Postgres twin test  T3.8

T3.6 比 T3.4/T3.5 早提(plan 中 T3.4-T3.5 写仓储要 JOIN memberships,所以 T3.6 必须先)。

T3.9 是 live verification,不产 commit;记在本文档的"验收"段。 T3.10impl doc)即本文件。