feat(identity): 完成 A1 身份认证与用户管理全栈落地
ci / 质量门禁 (push) Canceled after 0s

背景:
- 开发计划 A1 批次要求登录/刷新/登出、用户生命周期、路由与按钮权限、
  权限三态用例;视觉已选定方案 B(主从分栏 + 分屏登录)。

改动:
- packages/shared:新增 identity 契约(User/Me/Login/Refresh/Department/Role)
  与 user:view 权限点;写接口 strict 校验。
- apps/api:新增 identity 模块与 Prisma expand 迁移(departments/users/roles/
  user_roles/role_permissions/refresh_tokens);Argon2id、JWT access+refresh
  旋转与 jti 吊销、登录失败锁定、首登强改、守卫链、/me、@Audit 上下文、幂等种子。
- apps/web:按方案 B 落地 /users、/users/new、/users/:id、分屏登录与 403;
  usePermission/<Can>、路由守卫、401 单飞刷新、停用会话兜底、Semi + token。
- e2e:新增 A1-QA-01 六类端到端用例(A1_E2E 门控)。
- openapi 与前端生成类型同步;.env.example 登记认证变量;实施报告入库。

影响面:
- 新增运行时依赖 @nestjs/jwt、argon2(计划 A1-BE-02 已批准,版本精确锁定)。
- 迁移为 expand,不改既有表;本地需 prisma migrate 后重新 seed。
- 平台导航「用户与组织」由 /platform/users 调整为 /users。

回滚方式:
- 代码整体回滚本提交;迁移为 expand,回滚代码不需删表;
- 本地如需彻底回退按实施报告 §6 处理。

验证证据:
- pnpm format:check / lint / typecheck 通过;
- pnpm test:shared 95 / api 60 / web 55;
- pnpm test:int:7 个(真实 PG/Redis);
- A1_E2E=1 playwright test e2e/a1-identity.spec.ts:6/6;
- 报告:docs/开发计划/灵犀_A1身份认证与用户管理_实施报告_V0.1.md
This commit is contained in:
Stev_Wang committed 2026-11-03 00:03:33 +08:00
1 parent f0d218bd99
commit 4d9eb980af
120 files changed
+13112 -314

No files matched your search

+43 -12
View File
@@ -1,17 +1,48 @@
# 种子数据状态(A0)
# 种子数据状态(A1)
A0-INF-02 的计划要求种子包含「超管、示例角色、核心字典、电商行业包占位」。但这四类数据依赖的用户 / 角色 / 字典 / 行业包表分别在 A1(identity)、A3(industry)、A4(catalog)与 B0 批次才建表,A0 阶段提前建表会越过批次边界、造成后续迁移冲突。
A0 只 seed「已建表」的 `system_configs`;A1 建表完成后补齐组织、账号与角色种子。全部种子按业务唯一键 upsert,**幂等**:重复执行不重复插入,也不覆盖已存在的密码 / 人工调整值。
A0 的处理:
## 已 seed(`prisma/seed.ts`)
- 已 seed(`prisma/seed.ts`):`system_configs` 中平台级配置项,按 `config_key` 幂等 upsert,重复执行不重复插入、不覆盖人工调整值。
- 待后续批次接入(保持 TODO,不在 A0 建表):
| 数据 | 来源 | 幂等键 | 说明 |
| ------------------------------ | ---------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 平台系统配置 7 项 | `system_configs` | `config_key` | 平台名、导出链接有效期、上传上限、分页大小、AI 预算比例等,A0 起延续 |
| 部门 / 小组 9 个(两级) | `departments` | `code` | 内容生产中心(素材一组 / 素材二组 / 设计组)、交付中心(客户成功组)、平台技术部(AI 工程组 / 平台运维组);一级部门负责人取 `leader_account`,用户种子之后回填 `leader_user_id` |
| 角色 8 个 + 角色权限点 | `roles` / `role_permissions` | 角色 `code`;权限映射先清后建 | 超级管理员(`is_system=true`,全部权限点)、平台管理员、素材运营、设计师、文案策划、审核员、AI 工程师、客户负责人;权限点取值来自 `@lingxi/shared` `PERMISSION_CODES`(本文件按字符串固化) |
| 用户 11 个(超管 1 + 示例 10) | `users` / `user_roles` | `account`;用户角色先清后建 | 超管 `admin`,示例用户与 A1 原型口径一致(陈默、林清、周岸、赵一诺、高岑、苏禾、沈知远、江岚、唐嘉、何岸);唐嘉 / 何岸为停用态,用于「停用即时失效」联调 |
| 用户初始密码 | `users.password_hash` | — | 统一 `lingxi2026`(Argon2id),`must_change_password=true`:首登强制改密 |
| 种子 | 依赖批次 | 说明 |
| -------------------------------- | ----------- | ------------------------------------------------------------------------ |
| 超级管理员账号 | A1 identity | 需 `users` / `user_roles` 表 |
| 示例角色与权限点 | A2 identity | 需 `roles` / `role_permissions` 表,权限点常量已在 `@lingxi/shared` 定义 |
| 核心字典(素材类型、脚本状态等) | A4 catalog | 需 `dict_types` / `dict_items` 表 |
| 电商行业包占位 | A3 industry | 需 `industry_packs` 表与行业包 schema |
## 登录账号(本地联调)
> 【待确认 Q-A0-01】开发计划 A0-INF-02 的种子验收与批次建表顺序冲突,A0 按「只种已建表数据」执行,待产品/架构确认是否调整该 WBS 描述。
| 账号 | 姓名 | 角色 | 部门 / 小组 | 状态 |
| -------------- | ---------- | -------------------- | ----------------------- | ---- |
| `admin` | 灵犀管理员 | 超级管理员 | 平台技术部(直属) | 在职 |
| `chen.mo` | 陈默 | 素材运营、客户负责人 | 内容生产中心 / 素材一组 | 在职 |
| `lin.qing` | 林清 | 设计师 | 内容生产中心 / 设计组 | 在职 |
| `zhou.an` | 周岸 | 文案策划 | 内容生产中心 / 素材二组 | 在职 |
| `zhao.yinuo` | 赵一诺 | 审核员 | 内容生产中心 / 素材二组 | 在职 |
| `gao.cen` | 高岑 | 客户负责人 | 交付中心 / 客户成功组 | 在职 |
| `su.he` | 苏禾 | AI 工程师 | 平台技术部 / AI 工程组 | 在职 |
| `shen.zhiyuan` | 沈知远 | 超级管理员 | 平台技术部(直属) | 在职 |
| `jiang.lan` | 江岚 | 平台管理员 | 平台技术部 / 平台运维组 | 在职 |
| `tang.jia` | 唐嘉 | 素材运营 | 内容生产中心 / 素材一组 | 停用 |
| `he.an` | 何岸 | 客户负责人 | 交付中心 / 客户成功组 | 停用 |
> 登录账号按共享契约 `accountSchema` 不含 `@`(邮箱本地部分 / 工号风格);邮箱由种子自动生成 `账号@lingxi.cn`。
## 使用
```bash
pnpm db:migrate # 应用 a1_identity 迁移(expand)
pnpm db:seed # 幂等写入上述种子(可重复执行)
# 本地重置:pnpm db:reset(会重新执行全部迁移与 seed)
```
## 与 A0 遗留 TODO 的关系
A0 记录的「超管 / 角色 / 示例用户待 A1」已在本次迁移与种子中补齐;字典(A4)、行业包(A3)仍按批次留待后续建表,不在 A1 种子内。原 `Q-A0-01`(种子验收与建表顺序冲突)随 A1 建表落地而解除。
## 已知限制
- 客户数据(客户、客户组)属 A3,客户转交接口当前返回占位错误 `42201`(`客户转交将在客户模块(A3)提供`),种子不含客户。
- 审计表属 A5,`@Audit` 当前写结构化日志;A5 落库后在此扩展日志 + 审计表双写。