feat(space): 共享工作区增量3a —— Agent 编排按 Space 共享(纯 PG 打样)

引入 Space 中间容器(租户>Space>成员),资源作用域从 owner 改为 space_id,
让"个人私有/项目临时组队/整租户共享"出自同一模型(设计见 SPACE_DESIGN.md)。
先在纯 PG 的 Agent 上打样,零存储风险,验证协作+RBAC+切换 UX。

后端:
- 新表 Space{tenant_id,name,kind,creator,archived} + SpaceMember{space_id,user_id,role}
  (如 Tenant 般不 isTenantScoped);User.ActiveSpaceID;Agent 作用域 owner→space_id,
  owner 降级为创建人(供 UI 显示 / 删他人鉴权)
- store/space.go:个人空间幂等/活跃空间解析/切换/列表/建/成员CRUD/归档
- 迁移顺序坑:结构体只放非唯一 index,MigrateAgentSpaces 回填 space_id 后再建唯一
  索引 idx_agent_sn + DROP 旧 idx_agent_on(否则存量空 space_id 撞车);启动序4步幂等
- 中间件 SpaceContext(注入 space_id) + RequireSpaceRole(照 RequireTenantRole)
- handler/space.go 空间端点 + 路由;agent.go 改空间作用域(删/覆盖他人需 admin)
- 计费零改动(Space 与 ResolveBillingTenantID 正交)

桌面端:
- api.ts space 接口;顶栏 SpaceSwitcher(含新建项目空间);StudioView 随空间切换
  重拉编排 + viewer 禁保存;Agent 列表显示创建人 + 按 mine 控删除

验证:中间件6门控单测 + DB迁移(13个人空间/9 Agent全re-key/索引换新) + 后端HTTP全
场景(member见他人编排/删他人403、viewer存403、非成员切空间400+隔离、owner删他人200)
+ 浏览器实机(切换器3空间/Studio空间编排随切换隔离刷新/创建人显示/console无错)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-13 10:51:33 +08:00
parent bf5be08e96
commit addaa1b34f
16 changed files with 1077 additions and 46 deletions
+10
View File
@@ -54,6 +54,16 @@ func main() {
if err := db.BackfillRowTenants(context.Background()); err != nil {
log.Printf("[startup] 存量行 tenant_id 回填失败: %v", err)
}
// 增量3 共享工作区:给每个租户成员补个人空间,再把存量 Agent re-key 到其个人空间(幂等;顺序:
// 空间先建、Agent 后迁——迁移内先回填 space_id 再建唯一索引,避免存量空 space_id 撞车)。
if n, err := db.BackfillPersonalSpaces(context.Background()); err != nil {
log.Printf("[startup] 个人空间回填失败: %v", err)
} else if n > 0 {
log.Printf("[startup] 为 %d 个租户成员补建了个人空间", n)
}
if err := db.MigrateAgentSpaces(context.Background()); err != nil {
log.Printf("[startup] Agent 空间作用域迁移失败: %v", err)
}
cache := store.OpenRedis(redisAddr) // CacheDB: Session / Rate Limit(连不上则降级)
defer cache.Close()
bus := nats.MustConnect(natsURL) // 接入 NATS 零拷贝骨干网 + 声明任务流