diff --git a/README.md b/README.md index 0a82310..02bd449 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ | 立项建议 | [灵犀_信息流素材生产平台_立项建议书_V0.1.md](docs/立项建议/灵犀_信息流素材生产平台_立项建议书_V0.1.md) | V0.1 | 背景、目标、投入产出论证(不约束实现) | | **工程规范** | [docs/工程规范/](docs/工程规范/README.md) | V1.0 | Git、代码风格、格式化、API、数据库、测试、Review、日志、密钥、资产命名 | | **A0 报告** | [灵犀_A0工程骨架与契约基线_实施报告_V0.1.md](docs/开发计划/灵犀_A0工程骨架与契约基线_实施报告_V0.1.md) | V0.1 | A0 完成范围、门禁实测、环境适配与待确认事项 | +| **A1 报告** | [灵犀_A1身份认证与用户管理_实施报告_V0.1.md](docs/开发计划/灵犀_A1身份认证与用户管理_实施报告_V0.1.md) | V0.1 | A1 完成范围、契约/实现/测试、遗留与下一步 | +| **A2 报告** | [灵犀_A2角色权限与数据范围_实施报告_V0.1.md](docs/开发计划/灵犀_A2角色权限与数据范围_实施报告_V0.1.md) | V0.1 | A2 完成范围、H1 决策、前后端/测试、遗留与下一步 | +| **ADR** | [docs/adr/](docs/adr/README.md) | — | 架构决策记录(ADR-001 权限点目录与六类数据范围) | | 历史 PRD | `docs/PRD/灵犀_信息流素材生产平台_PRD_V0.1~V0.3.md` | 归档 | 仅作沿革参考,**不具约束力** | > 阅读顺序:`AGENTS.md` → PRD §1/§6 → 技术架构 §0.2/§3 → 按任务查 `docs/工程规范/`。 diff --git a/docs/adr/ADR-001-权限点目录与六类数据范围.md b/docs/adr/ADR-001-权限点目录与六类数据范围.md new file mode 100644 index 0000000..41e91de --- /dev/null +++ b/docs/adr/ADR-001-权限点目录与六类数据范围.md @@ -0,0 +1,104 @@ +# ADR-001 角色权限模型:权限点目录、特殊权限、SoD 与六类数据范围 + +| 项 | 内容 | +| --- | --- | +| 状态 | 已接受(2026-11-03,H1 权限门用户确认) | +| 决策人 | 产品 / 技术负责人(用户) | +| 记录人 | 工程 Lead | +| 关联 | 开发计划 V0.1 §3.4 H1 门、§6.3 A2、§7.2、§10.3、§13 DP-14;技术架构 V0.4 §5.5 / §6.1–6.3 / §7.1 / §8.7;PRD V1.6 §5.4.3、R-16~R-18 | +| 影响范围 | `packages/shared` 权限点与数据范围契约、`identity` 模块、`prisma` 迁移与种子、`apps/web` 角色管理页、A3 客户模块、后续所有受保护端点 | + +## 背景 + +A2「角色权限与数据范围」开卡前必须完成 H1 权限门(开发计划 §3.4):确认权限点目录、六类数据范围、SoD 互斥对、特殊权限授予规则,否则权限模型返工会影响全部页面。 + +现状与文档存在差异: + +- `packages/shared/src/permissions.ts` 是 A0 骨架,共 25 个 `read/write` 风格编码;缺少 `role:view`、`customer_field:apply`、`customer:transfer`、`customer_group:manage`、`asset:delete`。 +- 开发计划附录 B 使用 `view/manage` 风格并列出更多编码;但其自身注明「最终以 `packages/shared` 为准」。 +- PRD §5.4.3 的权限粒度更细(如图片生成 / 视频生成拆开),完整实现会显著增加权限点数量与配置成本。 +- A3 客户模块尚未开发,而六类数据范围中的「指定客户组 / 负责客户 / 本人创建」依赖客户与客户组数据。 + +## 决策 + +### D1 权限点目录:保留现有编码,只增不改 + +以 `packages/shared` 现有 25 个编码为基线,补齐 A2 必需的 5 个编码: + +`role:view`、`customer_field:apply`、`customer:transfer`、`customer_group:manage`、`asset:delete`。 + +合计 **30 个权限点 / 10 个模块**。命名保持 `<模块>:<动作>` 与 `read/write` 动作词;后续新增权限点通过代码目录注册并同步 `permissions` 表,**不手写迁移**。 + +### D2 特殊权限:M0 五项 6 编码 + +| 特殊权限 | 编码 | +| --- | --- | +| 导出 | `delivery:export` | +| AI 配置 | `ai:configure` | +| 审计查看 | `audit:read` | +| 审计导出 | `audit:export` | +| 行业包发布 | `industry:publish` | +| 字段审批 | `customer_field:approve` | + +规则:默认关闭、单独授予、不随角色复制带入、授予与撤销二次确认并写入审计。PRD 中的「跨客户复用授权」「批量删除」按开发计划 DP-14 留到 M2/M3,届时先回写技术架构并补编码,**A2 不实现**。 + +### D3 SoD 三对互斥:按现有编码映射 + +| 互斥对 | 编码 | +| --- | --- | +| 脚本生成与审核 | `script:write` × `script:review` | +| 行业包编辑与发布 | `industry:manage` × `industry:publish` | +| 字段申请与审批 | `customer_field:apply` × `customer_field:approve` | + +保存角色时校验,命中返回 `40304`;仅角色级校验(同一角色不可同时持有),超级管理员豁免。用户通过多个角色组合持有的情况不在 A2 校验范围(PRD 表述为「不可同属一个角色」)。 + +### D4 六类数据范围:全链路实现,客户集合通过端口隔离 + +A2 建立 `data_scopes` 表、六类范围解析引擎、`ScopeContext` 注入链路与 Repository 客户维度强制参数;角色保存时持久化范围类型与目标(指定客户组可多个)。 + +客户集合解析通过 `CustomerDirectory` 端口完成: + +- A2 实现 `EmptyCustomerDirectory`,在 A3 客户模块落地前返回空集; +- 测试使用 fake 客户目录覆盖非空场景; +- A3 接入真实 `customers` / `customer_groups` 后替换实现,`ScopeContext` 与 Repository 契约不变。 + +失败处理:数据范围解析失败一律 403,**不降级为「全部客户」**。多角色取并集;任一角色为「全部客户」则结果为全部。 + +### D5 超级管理员:隐式全集 + +`is_system = true` 的角色自动拥有全部权限点、全部特殊权限与全部数据范围,不依赖、也不可编辑 `role_permissions` / `data_scopes` 记录;仅显示名可改,不可删除、不可停用。 + +角色数量 > 20、超管人数 > 2 仅做非阻断提示(PRD 为「建议值」)。相关建议值当前以共享常量表达,A4 系统配置落地后迁入 `system_configs`(R-26 单一存放处)。 + +### D6 变更审计:A2 结构化日志,A5 落库 + +角色变更(新建 / 编辑 / 复制 / 停用 / 删除 / 特殊权限授予)记录结构化日志:操作人、账号、IP、trace_id、目标角色、权限点前后值、特殊权限前后值、影响用户数。 + +同时写 `outbox_events`(`role.permissions.changed`,payload 含受影响用户 ID)作为「受影响用户通知」占位,消费方随 A5/A6 接入。审计表落库、检索与导出由 A5 完成;`@Audit` 装饰器签名保持不变。 + +## 后果 + +### 正面 + +- A1 已实现代码零迁移,A2 可在现有 25 编码上平滑扩展。 +- 六类范围与 ScopeContext 一次建好,A3 只需实现 `CustomerDirectory` 与客户表,避免范围逻辑二次返工。 +- 超管隐式全集避免新增权限点后超管缺权,减少权限事故。 +- 权限目录代码化 + 启动同步,新增权限点无需手写迁移。 + +### 代价与约束 + +- 权限点命名保留 `read/write`,与开发计划附录 B 的 `view/manage` 不一致;后续文档引用以 `packages/shared` 为准,附录 B 需在下一版修订时对齐(不改语义)。 +- A2 的 `客户组 / 负责客户 / 本人创建` 三类范围在 A3 前无可选目标,UI 需提供空态;A2 验收以解析引擎与 fake 客户目录单测为准,不等同于真实客户隔离验收。 +- 「审计查看」作为特殊权限后,普通角色默认无法查看审计;符合 PRD「审计单独授权」原则。 +- 权限点数(30)与 PRD 操作级粒度仍有差距,图片 / 视频生成等细分待 M1 前按需补充,遵循「只增不改」。 + +## 待办 / 回写 + +| 项 | 责任 | 时点 | +| --- | --- | --- | +| 开发计划附录 B 权限点表与 ADR-001 对齐(命名/增补) | 产品 / 架构 | A2 收口时 | +| 技术架构 §6.3 补 `role:view`、`customer_field:apply` 等编码说明 | 架构 | A2 收口时 | +| A3 实现 `CustomerDirectory` 真实客户目录并补范围验收 | 研发 | A3 | +| DP-14 两项特殊权限编码与架构回写 | 架构 | M2/M3 前 | +| 角色数量 / 超管数量建议值迁入 `system_configs` | 研发 | A4 | +| 审计落库、检索、导出 | 研发 | A5 | diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..863258c --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,15 @@ +# ADR 索引 + +> 架构决策记录(Architecture Decision Record)。格式:`ADR-xxx-标题.md`,编号连续不复用。 +> 一个 ADR 只记录一个决策及其后果;被推翻时保留原文并标「已废弃 / 被 ADR-xxx 取代」。 + +| 编号 | 决策 | 状态 | 日期 | 关联 | +| --- | --- | --- | --- | --- | +| [ADR-001](ADR-001-权限点目录与六类数据范围.md) | 角色权限模型:权限点目录保留 `read/write` 只增不改、特殊权限五项 6 编码、SoD 三对互斥、六类数据范围全链路 + `CustomerDirectory` 端口、超管隐式全集、A2 审计先结构化日志 | 已接受 | 2026-11-03 | A2 / A3 / DP-14 | + +## 新增流程 + +1. 复制 `ADR-001` 的章节结构:背景 → 决策 → 后果 → 待办 / 回写。 +2. 编号取当前最大值 +1,文件名用中文短标题。 +3. 涉及多模块或权限 / 数据口径的决策,须在开发计划的对应 H 门确认后记录。 +4. 更新本索引与根 `README.md` 文档索引。 diff --git a/docs/开发计划/灵犀_A2角色权限与数据范围_实施报告_V0.1.md b/docs/开发计划/灵犀_A2角色权限与数据范围_实施报告_V0.1.md new file mode 100644 index 0000000..606f2ab --- /dev/null +++ b/docs/开发计划/灵犀_A2角色权限与数据范围_实施报告_V0.1.md @@ -0,0 +1,129 @@ +# 灵犀 A2 角色权限与数据范围 · 实施报告 V0.1 + +| 项 | 内容 | +| --- | --- | +| 实施日期 | 2026-11-03 | +| 批次 | A2(角色权限与数据范围) | +| 状态 | 已完成,门禁通过;未推送 | +| 依据 | 开发计划 V0.1 §3.4 H1 门、§6.3、§7.2、§10.3、附录 B;技术架构 V0.4 §5.5 / §6.1–6.3 / §7.1 / §8.7;PRD V1.6 §5.4.3、R-16~R-18 | +| 决策记录 | [ADR-001 权限点目录与六类数据范围](../adr/ADR-001-权限点目录与六类数据范围.md) | +| 视觉基线 | A0「方向 A · 云白蓝」+ A1 已选定「B 主从分栏」;本轮 UI 门选定 **B 主从分栏** | + +--- + +## 1 范围与完成度 + +| 任务 | 内容 | 状态 | +| --- | --- | --- | +| A2-BE-01 | 角色 CRUD / 复制 / 停用 / 删除、系统角色保护、重名校验 | ✅ | +| A2-BE-02 | 权限点目录 30 个 / 10 模块代码注册,启动同步 `permissions` 表,`GET /permissions` 树 | ✅ | +| A2-BE-03 | 角色权限绑定、特殊权限 6 编码单独授予、特殊权限分桶校验 | ✅ | +| A2-BE-04 | 六类数据范围、`data_scopes`、`ScopeContext`、`CustomerDirectory` 端口、fail-closed | ✅(A3 前客户集为空集) | +| A2-BE-05 | SoD 三对保存即校验(40304)、变更审计(前后值 / 影响用户数)、outbox 占位通知 | ✅ | +| A2-FE-01 | 角色列表、权限点树、六类范围、特殊权限区、保存影响面、SoD 冲突 | ✅ | +| A2-FE-02 | 模板 / 复制 / 停用 / 删除 / 系统角色改名 / 绑定用户 / 只读态 | ✅ | +| A2-QA-01 | 角色端点权限三态、SoD 三对、即时生效、特殊权限分桶、浏览器 e2e | ✅ | + +H1 权限门口径(用户确认):权限点保留现有 `read/write` 编码只补缺(30 个 / 10 模块);特殊权限五项 6 编码;SoD 三对按现有编码映射;六类数据范围全链路 + A3 前空客户集;超管隐式全集;A2 审计先结构化日志、A5 落库。详见 ADR-001。 + +--- + +## 2 交付物 + +### 2.1 共享契约(`packages/shared`) + +- `permissions.ts`:30 个权限点常量与元数据目录(`module` / `moduleLabel` / `name` / `description` / `isSpecial` / `sortOrder`)、10 个模块顺序、`SPECIAL_PERMISSIONS`(6)、`SOD_PAIRS`(3)、`PERMISSION_CATALOG`、`permissionsByModule()`、`splitPermissions()`、`findSodConflicts()`、软上限常量。 +- `schemas/roles.ts`:`RoleListItem` / `RoleDetail` / `RoleBoundUser` / `RoleSaveResult` / `CreateRoleInput` / `UpdateRoleInput` / `RoleListQuery` / `PermissionTree` / SoD pair;写接口 `.strict()`,特殊权限分桶校验。 +- `schemas/identity.ts`:`DataScope` 增 `targetIds` / `customerIds`;`MeResponse.dataScopes: DataScope[]`(多角色并集,超管 `[{type:'all'}]`)。 +- 模块与权限点显示名与 `design/a2-ui-v1/brief.md` 逐条对齐;权限点只增不改。 + +### 2.2 数据库与种子 + +- 迁移 `prisma/migrations/20261103025415_a2_role_permissions_data_scopes/`(expand):新增 `permissions`(目录,code 主键)与 `data_scopes`(role_id + scope_type + target_id,复合唯一索引、FK);未删改既有字段。空库与存量库各验证一次。 +- `prisma/seed.ts` 幂等更新:30 权限点、10 角色、角色权限映射(普通权限数 24/12/9/4/2/4/3/5/4/5)、data_scopes(含客户负责人 `customer_groups` 空目标行)、特殊权限 8 项授予(超管 6 + 平台管理员 `audit:read` + AI 工程师 `ai:configure`);`prisma/SEED.md` 同步。 +- 说明:种子用户沿用 A1 的 11 个示例账号(12 条角色绑定),不扩种原型示例的 28 名用户。 + +### 2.3 后端(`apps/api`) + +- identity 模块:`GET/POST /roles`、`GET/PATCH/DELETE /roles/{id}`、`GET /permissions`;`GET /roles` 默认 `status=active` 兼容 A1 用户页角色多选,同时接受 `role:view` / `user:view`;角色管理页显式传 `status=all`。 +- 权限解析:每请求实时读 DB;`is_system` 超管隐式全部权限点、特殊权限与全部数据范围;停用角色即时失效;未登记权限点被丢弃。 +- 数据范围:`ScopeGuard` 解析六类范围为 `ScopeContext`;`CustomerDirectory` 端口 + `EmptyCustomerDirectory`(A3 前空集,不降级);`customerScopeWhere` / `isCustomerVisible` / `assertCustomerAccess` / `requireScopeContext` 与单测;多角色并集,任一 `all` 即全部;解析失败 40302。 +- SoD:三对互斥保存即校验,命中 40304 并返回 `details.conflicts`;系统角色不可改权限/范围/状态,仅显示名可改;超管只在系统角色自身豁免。 +- 审计:角色新建/更新/停用/删除记录前后值、权限 diff、影响用户数、IP/UA/trace_id;`outbox_events` 写 `role.permissions.changed`(含 affectedUserIds)占位通知。 +- 测试:`roles.service.spec.ts`、`permission-catalog.service.spec.ts`、`scope.spec.ts`、`roles.int.spec.ts`。 + +### 2.4 前端(`apps/web`) + +- 路由:`/system/roles`(`role:view`,左 400 角色列表 + 右详情)、`/system/roles/:id`(编辑器,Tab:基本信息/权限点/数据范围/特殊权限 + 底部唯一保存)、`/system/roles/new`(`role:manage`,左模板 + 右表单);导航 `/system/roles` 权限由 `ROLE_MANAGE` 调整为 `ROLE_VIEW`;面包屑补角色三页。 +- API/Query:`api/roles.ts`、`hooks/queries/use-roles.ts`、`query-keys`、`endpoints`;全部用 shared Zod schema 解析。 +- 页面能力:权限树 10 模块/30 点三态 + 搜索 + 展开;特殊权限 6 项二次确认;数据范围六类单选 + 客户组空态;模板预填(特殊不带入);复制/停用/删除/系统角色改名;保存前影响确认;SoD 实时冲突与 40304 回填;未保存离开拦截;权限点目录抽屉;只读态;加载/空/错误态;1024 适配。 +- 样式:`styles/roles.css`、`styles/role-editor.css`,复用 `--lx-*` token 与现有 `.lx-*` 组件类;未新增依赖、未内联 SVG。 + +### 2.5 UI 原型与决策 + +- 三套候选原型:`design/a2-ui-v1/`(A 独立编辑器 / B 主从分栏 / C 卡片墙 + 向导),共享口径 `brief.md`,对比页 `index.html` + `style-explorer-*.html`。 +- 独立视觉评审:A 8 / B 8 / C 7,均无阻断;推荐 B。用户于 2026-11-03 选定 **B 主从分栏**,实现以 `design/a2-ui-v1/b/` 为准。 +- 实现截图:`design/a2-ui-v1/shots/impl/final/`(clean seed);QA e2e 截图:`design/a2-ui-v1/shots/impl/e2e/`(含测试数据)。 + +--- + +## 3 验证结果 + +| 门禁 | 命令 | 结果 | +| --- | --- | --- | +| 格式 | `pnpm format:check` | ✅ | +| Lint | `pnpm lint` | ✅ 0 warning | +| 类型 | `pnpm typecheck` | ✅ 10/10 tasks | +| 单测 | `pnpm test` | ✅ shared 119 / api 85 / web 102,共 306 | +| 集成 | `pnpm test:int` | ✅ 3 文件 / 27 条(health 1 + identity 13 + roles 13) | +| 浏览器 e2e | `A2_E2E=1 pnpm exec playwright test e2e/a2-roles.spec.ts` | ✅ 1 passed(18.9s),复跑 1 passed(19.3s) | +| OpenAPI | `pnpm openapi:export` | ✅ 新增 `/roles`、`/roles/{id}`、`/permissions` 路径 | + +A2-QA-01 覆盖:6 个角色端点权限三态(200/201/204 vs 403 `40301`)、40401、40903、40302 fail-closed;SoD 三对 40304 + `details.conflicts`、失败不落库、系统角色豁免边界;特殊权限分桶与单独授予、复制不带入;同一 access token 的改权限/授特殊/停用/恢复即时生效;outbox 变更审计。 + +--- + +## 4 本地运行 + +```bash +pnpm check:dev # 确认 PG 5432 / Redis 6379 +pnpm db:reset # 迁移 + 种子(admin / lingxi2026,首次登录须改密) +pnpm dev # API :3000 + Web :5173 +# 浏览器打开 http://127.0.0.1:5173/login → 管理中心 / 角色权限 +``` + +种子账号:`admin` 超管、`jiang.lan` 平台管理员等 11 个账号;初始密码 `lingxi2026`,首次登录强制修改。 + +--- + +## 5 已知差异与遗留 + +| 编号 | 项 | 说明 / 建议 | +| --- | --- | --- | +| 1 | 客户组 / 负责客户 / 本人创建 | A2 已落解析引擎与 `ScopeContext`,但 A3 前 `CustomerDirectory` 返回空集;「指定客户组」只能先保存范围、A3 后再补授权对象。A3 接入真实客户目录并补范围验收。 | +| 2 | 审计落库 | A2 角色变更审计为结构化 Pino 日志 + outbox 事件;审计表落库、检索、导出按 A5。A2-QA-01「越权访问有审计记录」当前以结构化日志 + outbox 为准。 | +| 3 | DP-14 两项特殊权限 | 「跨客户复用授权」「批量删除」暂未实现,待 M2/M3 前回写架构并补编码。 | +| 4 | 导航模块权限 | 管理中心模块级 permission 仍为 `USER_VIEW`;仅 `role:view` 无 `user:view` 的用户侧栏不可见该模块(路由直达可用)。建议后续统一模块级导航口径。 | +| 5 | 面包屑 | 角色编辑器面包屑末级为静态「角色编辑」,未显示角色名;原型为角色名,可在后续接入路由 handle 或上下文数据。 | +| 6 | 原型示例数据 | 原型「28 名绑定用户」为 UI 示例;种子实际 11 个账号(12 条绑定)。实现页显示真实种子数据。 | +| 7 | OpenAPI schema | 路径已导出,请求/响应 schema 仍缺(Zod 入参无 DTO 类),沿用 A1 遗留;前端直接使用 shared 类型。 | +| 8 | e2e 数据 | A2 e2e 每次新增 1 个仅停用的 `qa2.roles.*` 用户(用户不可删除,与 A1 同口径),本地库会累积停用用户;角色在解绑后删除。 | +| 9 | 前端可访问性 | Semi Modal 复用 `semi-modal-title` id,关闭动画期间两个弹窗同时挂载可能导致可访问名串台;e2e 已用按钮/文案定位规避,建议后续给 Modal 传唯一 `aria-label`。 | + +--- + +## 6 回滚方式 + +- 代码:整体回滚本批 commit;前端三页、共享契约、identity 角色接口与测试一并回退。 +- 数据库:本批为 expand 迁移,回滚代码不需要删表;如需彻底回退,用 `prisma migrate resolve` 标记后手工 drop `permissions` / `data_scopes`(仅本地)。 +- 数据:种子可重跑;角色权限映射幂等重建;`data_scopes` 随角色删除级联。 +- 配置:未新增环境变量。 + +--- + +## 7 下一步 + +1. **A3 客户与行业目录**:实现真实 `CustomerDirectory`、客户组 / 负责客户 / 本人创建范围验收;替换用户停用前客户转交占位。 +2. **A5 审计**:`@Audit` 与角色变更审计落库、检索、导出,A2 e2e 增加审计断言。 +3. **DP-14**:M2/M3 前回写架构并补「跨客户复用授权」「批量删除」编码。 +4. **工程补强**:OpenAPI schema 由 shared Zod 生成;模块级导航权限口径统一;角色编辑器面包屑显示角色名;Semi Modal 唯一 aria-label。 diff --git a/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md b/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md index 88b9ed9..cbc8d89 100644 --- a/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md +++ b/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md @@ -10,7 +10,7 @@ | 文档名称 | 灵犀 · 信息流素材生产平台 项目开发计划 | | 版本 | V0.1(初稿,待评审) | | 日期 | 2026-11-02 | -| 状态 | **执行中**:A0 工程骨架与契约基线已完成(2026-11-02);A1 身份认证与用户管理已完成(2026-11-03);A2 待启动 | +| 状态 | **执行中**:A0 工程骨架与契约基线已完成(2026-11-02);A1 身份认证与用户管理已完成(2026-11-03);A2 角色权限与数据范围已完成(2026-11-03);下一步 A3 | | 需求基线 | PRD V1.6([灵犀-信息流广告素材一站式生产平台PRD.md](../PRD/灵犀-信息流广告素材一站式生产平台PRD.md)) | | 技术基线 | 技术架构 V0.4([灵犀_信息流素材生产平台_技术架构_V0.1.md](../技术架构/灵犀_信息流素材生产平台_技术架构_V0.1.md))+ `AGENTS.md` V1.0 + `docs/工程规范/` V1.0 | | 覆盖范围 | **M0 任务级;M1–M4 迭代级 + 任务组级;M5 预研边界(不排期)** | @@ -379,7 +379,7 @@ flowchart LR | --- | --- | --- | --- | --- | --- | --- | --- | | **A0** | ✅ 已完成 | 工程骨架与契约基线 | — | 6 | 4–5 日 | W0 | lint / typecheck / test / CI 全绿;三依赖可起;api / web / worker 可启动;OpenAPI 可导出 | | **A1** | ✅ 已完成 | 身份认证与用户管理 | A0 | 6 | 4–5 日 | W1 | 登录 / 刷新 / 登出;用户生命周期;路由权限;权限三态用例 | -| **A2** | 未开始 | 角色权限与数据范围 | A1 | 5.5 | 4–5 日 | W2 | 角色可配;SoD 命中拒绝;特殊权限默认关闭;范围过滤生效 | +| **A2** | ✅ 已完成 | 角色权限与数据范围 | A1 | 5.5 | 4–5 日 | W2 | 角色可配;SoD 命中拒绝;特殊权限默认关闭;范围过滤生效 | | **A3** | 未开始 | 客户与行业目录 | A1 / A2 | 7 | 4–5 日 | W2 | 行业 / 客户 / 客户组可用;唯一性;状态只读;字段审批 | | **A4** | 未开始 | 数据字典与系统配置 | A3 | 4 | 3–4 日 | W3 | 三层合并;编码不可改;阈值同源;配置版本 + 审计 | | **A5** | 未开始 | 审计与日志 | A1 / A4 | 4 | 3–4 日 | W2–W3 | 关键操作全留痕;不可篡改;导出自身审计 | @@ -395,6 +395,8 @@ flowchart LR > **A0 进度(2026-11-02)**:✅ 已完成。10/10 项 WBS 通过;本批门禁 `format:check / lint / typecheck / test / build / test:int / openapi:export / openapi:diff / e2e` 与本地 CI `pnpm ci:local` 全绿;`/health`、`/api/docs`、web 布局与登录壳、worker 启动均实测通过。实现记录与偏差见 [A0 实施报告](./灵犀_A0工程骨架与契约基线_实施报告_V0.1.md)。环境适配:本地 PG/Redis 复用已有 Docker、对象存储使用公网 RustFS、种子仅 `system_configs`(`Q-A0-01`)、Gitea 暂无 runner 时以 `pnpm ci:local` 为准。 > > **A1 进度(2026-11-03)**:✅ 已完成。8/8 项 WBS 通过;`format:check / lint / typecheck / test` 全绿(shared 95 / api 60 / web 55),`test:int` 7 项(真实 PG / Redis),A1-QA-01 浏览器 e2e 6/6;登录 → 首次登录强改 → 用户列表 / 新建 / 详情 / 停用启用 / 角色调整 / 客户转交占位全链路实测。实现记录、口径与遗留见 [A1 实施报告](./灵犀_A1身份认证与用户管理_实施报告_V0.1.md)。已知遗留:六类数据范围(A2)、客户转交真实接口(A3)、审计落库(A5)。 +> +> **A2 进度(2026-11-03)**:✅ 已完成。8/8 项 WBS 通过;H1 权限门已确认并记录 [ADR-001](../adr/ADR-001-权限点目录与六类数据范围.md);UI 门三套原型独立评审 A 8 / B 8 / C 7,用户选定 **B 主从分栏**。`format:check / lint / typecheck / test` 全绿(shared 119 / api 85 / web 102),`test:int` 27 项(真实 PG / Redis),A2-QA-01 浏览器 e2e 1/1(复跑通过);角色可配、SoD 40304、特殊权限默认关闭、六类范围解析与 `ScopeContext` 全链路、系统角色保护、变更审计与 outbox 均实测。实现记录、口径与遗留见 [A2 实施报告](./灵犀_A2角色权限与数据范围_实施报告_V0.1.md)。已知遗留:A3 前客户目录为空集、A5 审计落库、DP-14 两项特殊权限、导航模块级权限口径。 ### 5.3 批次依赖图 @@ -561,6 +563,8 @@ PRD §7 把 **M-27(素材元素级拆解)** 与「自动字幕 → TTS 配 | A2-FE-02 | 复制 / 模板 / 停用 | FE | 从角色或示例模板复制;停用倒计时与在线用户提示;角色详情展示绑定用户 | A2-FE-01 | 复制后可独立编辑;停用后在线用户下次请求失效 | 1.0 | | A2-QA-01 | 权限三态与 SoD 用例 | QA | 每个角色相关端点 3 类用例(有 / 无 / 范围外)+ 3 对 SoD 用例;权限变更即时生效 | A2-BE-05 | 用例全部通过;越权访问有审计记录 | 0.5 | +> **A2 完成情况(2026-11-03)**:8/8 项 WBS 完成。H1 权限门确认:30 权限点 / 10 模块(保留 `read/write` 只补缺)、特殊权限五项 6 编码、SoD 三对、六类数据范围全链路、超管隐式全集、A2 审计先结构化日志;见 [ADR-001](../adr/ADR-001-权限点目录与六类数据范围.md)。UI 三套原型评审 A 8 / B 8 / C 7,用户选定 B 主从分栏。`test:int` 27 项、A2 e2e 1/1,门禁全绿;实现与遗留见 [A2 实施报告](./灵犀_A2角色权限与数据范围_实施报告_V0.1.md)。 + **本批门禁**:角色可配、范围可解析、SoD 可拦截;权限三态用例全绿;特殊权限默认关闭;人类完成 **H1 权限门**(§3.4)。 ### 6.4 A3 客户与行业目录