feat: auto committed
This commit is contained in:
@@ -2,35 +2,57 @@
|
||||
|
||||
> 负责人:ai06
|
||||
> 关联:[matrix.md](./matrix.md)、[iam.proto](../../../packages/shared-proto/proto/iam.proto)、[events.proto](../../../packages/shared-proto/proto/events.proto)
|
||||
> 裁决依据:[coord-final-decisions](../../coord-final-decisions.md) I1-I8、[president-final-rulings](../../president-final-rulings.md) §2.15/§2.16/§5.5
|
||||
|
||||
---
|
||||
|
||||
## §1 我提供什么(对外接口)
|
||||
|
||||
### 1.1 gRPC 接口(如有)
|
||||
> **双入口策略**(president §2.16):REST 供 gateway 透传 + admin-portal 直连,gRPC 供 BFF 聚合调用。同一 Application Service 同时被 REST Controller + gRPC Controller 调用,业务逻辑不重复。gateway 保持 HTTP 透传(不改为 gRPC 客户端)。
|
||||
|
||||
| Service | RPC | 请求 | 响应 | 端口 |
|
||||
| ---------- | ----------------------- | ------------------------------ | ---------------------------- | ----- |
|
||||
| IamService | Register | RegisterRequest | AuthResponse | 50052 |
|
||||
| IamService | Login | LoginRequest | AuthResponse | 50052 |
|
||||
| IamService | RefreshToken | RefreshTokenRequest | TokenPair | 50052 |
|
||||
| IamService | Logout | LogoutRequest | LogoutResponse | 50052 |
|
||||
| IamService | GetUserInfo | GetUserInfoRequest | UserInfo | 50052 |
|
||||
| IamService | BatchGetUsers | BatchGetUsersRequest | BatchGetUsersResponse | 50052 |
|
||||
| IamService | GetEffectivePermissions | GetEffectivePermissionsRequest | EffectivePermissionsResponse | 50052 |
|
||||
| IamService | GetEffectiveAccess | GetEffectiveAccessRequest | EffectiveAccessResponse | 50052 |
|
||||
| IamService | GetEffectiveDataScope | GetEffectiveDataScopeRequest | DataScopeResponse | 50052 |
|
||||
| IamService | GetViewports | GetViewportsRequest | ViewportsResponse | 50052 |
|
||||
| IamService | GetPublicKey | GetPublicKeyRequest | PublicKeyResponse | 50052 |
|
||||
| IamService | GetChildrenByParent | GetChildrenByParentRequest | ChildrenResponse | 50052 |
|
||||
### 1.1 gRPC 接口(供 BFF 聚合调用)
|
||||
|
||||
### 1.2 HTTP 端点(如有)
|
||||
> 端口 50052,P2 即启用(I1 裁决)。⚠️ 当前 iam.proto 仅 4 RPC,待 coord 补全至 12 RPC(ISSUE-005)。
|
||||
|
||||
无对外 HTTP 端点,仅 gRPC。
|
||||
| Service | RPC | 请求 | 响应 | 端口 | 消费方 |
|
||||
| ---------- | ----------------------- | ------------------------------ | ---------------------------- | ----- | ---------------------------------------- |
|
||||
| IamService | Register | RegisterRequest | AuthResponse | 50052 | api-gateway(REST 透传)/ admin-portal |
|
||||
| IamService | Login | LoginRequest | AuthResponse | 50052 | api-gateway(REST 透传)/ admin-portal |
|
||||
| IamService | RefreshToken | RefreshTokenRequest | TokenPair | 50052 | api-gateway(REST 透传) |
|
||||
| IamService | Logout | LogoutRequest | LogoutResponse | 50052 | api-gateway(REST 透传) |
|
||||
| IamService | GetUserInfo | GetUserInfoRequest | UserInfo | 50052 | teacher-bff / student-bff / parent-bff |
|
||||
| IamService | BatchGetUsers | BatchGetUsersRequest | BatchGetUsersResponse | 50052 | teacher-bff / admin-portal |
|
||||
| IamService | GetEffectivePermissions | GetEffectivePermissionsRequest | EffectivePermissionsResponse | 50052 | teacher-bff / student-bff / parent-bff |
|
||||
| IamService | GetEffectiveAccess | GetEffectiveAccessRequest | EffectiveAccessResponse | 50052 | teacher-bff / student-bff / parent-bff |
|
||||
| IamService | GetEffectiveDataScope | GetEffectiveDataScopeRequest | DataScopeResponse | 50052 | teacher-bff / data-ana |
|
||||
| IamService | GetViewports | GetViewportsRequest | ViewportsResponse | 50052 | teacher-bff / student-bff / parent-bff |
|
||||
| IamService | GetPublicKey | GetPublicKeyRequest | PublicKeyResponse | 50052 | api-gateway(JWKS 验签) |
|
||||
| IamService | GetChildrenByParent | GetChildrenByParentRequest | ChildrenResponse | 50052 | parent-bff |
|
||||
|
||||
### 1.2 HTTP 端点(供 gateway 透传 + admin-portal 直连)
|
||||
|
||||
> REST 与 gRPC 双入口并存(president §2.16)。REST 路径统一加 `/v1` 前缀(I7 裁决)。gateway 路由 `/iam/v1/*` → iam 服务 `/v1/iam/*`(透传不改路径)。
|
||||
|
||||
| Method | Path | 权限 | 说明 | 消费方 |
|
||||
| ------ | --------------------------------- | ----------------- | -------------------------------------- | -------------------- |
|
||||
| POST | `/iam/v1/register` | 公开 | 注册 + 自动分配 teacher 角色 | api-gateway / admin |
|
||||
| POST | `/iam/v1/login` | 公开 | 登录,返回 accessToken + refreshToken | api-gateway |
|
||||
| POST | `/iam/v1/refresh` | 公开 | 刷新令牌(轮换 + 旧 token 黑名单) | api-gateway |
|
||||
| POST | `/iam/v1/logout` | `IAM_USER_READ` | 登出(refresh token 加黑名单) | api-gateway |
|
||||
| GET | `/iam/v1/me` | `IAM_USER_READ` | 当前用户信息 | api-gateway / admin |
|
||||
| GET | `/iam/v1/viewports` | `IAM_USER_READ` | 当前用户视口(L1 导航) | api-gateway |
|
||||
| GET | `/iam/v1/permissions/effective` | `IAM_USER_READ` | 当前用户有效权限(I8 统一路径) | api-gateway |
|
||||
| GET | `/iam/v1/.well-known/jwks.json` | 公开 | RS256 公钥 JWK Set(Gateway 拉取验签) | api-gateway |
|
||||
| GET | `/iam/v1/children` | `IAM_USER_READ` | 当前家长的孩子列表(I6 裁决) | api-gateway / parent |
|
||||
| GET | `/iam/v1/roles` | `IAM_ROLE_MANAGE` | 角色列表(管理端) | admin-portal |
|
||||
| GET | `/iam/v1/permissions` | `IAM_ROLE_MANAGE` | 权限点列表(管理端) | admin-portal |
|
||||
| GET | `/healthz` | 无 | liveness | k8s / 监控 |
|
||||
| GET | `/readyz` | 无 | readiness(5 依赖检查) | k8s / 监控 |
|
||||
| GET | `/metrics` | 无 | Prometheus 指标 | Prometheus |
|
||||
|
||||
### 1.3 GraphQL schema(如 BFF)
|
||||
|
||||
不适用。
|
||||
不适用。iam 是业务服务,不暴露 GraphQL(GraphQL 由 BFF 层提供)。
|
||||
|
||||
### 1.4 Kafka 事件发布(如有)
|
||||
|
||||
@@ -66,16 +88,23 @@
|
||||
|
||||
### 3.1 我依赖的上游就绪标志
|
||||
|
||||
无上游依赖。
|
||||
iam 是身份根服务,无业务上游依赖。但依赖以下基础设施契约(coord 提供):
|
||||
|
||||
| 依赖项 | 提供方 | 就绪标志 | 状态 |
|
||||
| ------ | ------ | -------- | ---- |
|
||||
| iam.proto 补全至 12 RPC | coord | proto 含 12 RPC + 全部 message | ❌ 仅 4 RPC(ISSUE-005) |
|
||||
| events.proto 补全 UserEvent/RoleEvent/AuditEvent | coord | proto 含 3 个 message | ❌ 缺失(ISSUE-002) |
|
||||
| shared-ts Outbox 工具包 | coord | outbox.service.ts 可导入 | ✅ 已就绪 |
|
||||
|
||||
### 3.2 我的就绪标志(供下游消费)
|
||||
|
||||
- [ ] iam gRPC 50052 启用(HealthService.Check 返回 SERVING)
|
||||
- [ ] IamService.Register/Login/RefreshToken/Logout 可调用(返回 AuthResponse/TokenPair)
|
||||
- [ ] IamService 12 RPC 全部可调用(Register/Login/RefreshToken/Logout/GetUserInfo/BatchGetUsers/GetEffectivePermissions/GetEffectiveAccess/GetEffectiveDataScope/GetViewports/GetPublicKey/GetChildrenByParent)
|
||||
- [ ] IamService.GetPublicKey 可用(返回 RS256 PEM 公钥,供 api-gateway 验签)
|
||||
- [ ] IamService.GetChildrenByParent 可用(供 parent-bff 查孩子列表)
|
||||
- [ ] edu.iam.user.events / edu.iam.role.events / edu.iam.audit.created topic 可发布
|
||||
- [ ] JWT RS256 签发链路打通(access_token + refresh_token)
|
||||
- [ ] JWT RS256 签发链路打通(access_token 15min + refresh_token 7day 轮换)
|
||||
- [ ] /iam/v1/* REST 端点可用(供 gateway 透传 + admin-portal 直连,双入口策略)
|
||||
|
||||
---
|
||||
|
||||
@@ -83,13 +112,15 @@
|
||||
|
||||
### 4.1 我提供的 mock
|
||||
|
||||
在 iam 真实服务就绪前,为下游(api-gateway / 各 BFF)提供以下 mock:
|
||||
在 iam 真实服务就绪前,为下游(api-gateway / 各 BFF / admin-portal)提供以下 mock(双入口):
|
||||
|
||||
- **gRPC mock**:使用 grpc-mock 拦截 50052 端口,Register/Login 返回固定 AuthResponse(user.id="mock-user-001", tokens.access_token="mock-access-token")
|
||||
- **gRPC mock**(供 BFF):使用 grpc-mock 拦截 50052 端口,Register/Login 返回固定 AuthResponse(user.id="mock-user-001", tokens.access_token="mock-access-token")
|
||||
- **REST mock**(供 gateway / admin-portal):MSW 或 express mock 拦截 /iam/v1/* 路径,返回与 gRPC mock 一致的结构
|
||||
- **GetPublicKey mock**:返回固定 RS256 公钥 PEM(与 mock 私钥配对),供 api-gateway 验签 mock JWT
|
||||
- **GetChildrenByParent mock**:返回固定 ChildInfo 列表(2 个孩子)
|
||||
- **JWKS mock**:GET /iam/v1/.well-known/jwks.json 返回固定 JWK Set
|
||||
- **Kafka mock**:iam 服务就绪前不发布真实事件,下游订阅方使用本地 stub
|
||||
|
||||
### 4.2 我消费的 mock
|
||||
|
||||
不适用(无上游依赖)。
|
||||
不适用(iam 是身份根服务,无业务上游依赖)。
|
||||
|
||||
@@ -6,6 +6,124 @@
|
||||
|
||||
---
|
||||
|
||||
## §1 已有仲裁核查
|
||||
|
||||
> 对已生效的仲裁(coord-final-decisions I1-I8、president-final-rulings 相关条款、coord.md ARB-001/ARB-002)逐条核查落地情况。
|
||||
|
||||
### 1.1 coord-final-decisions I1-I8(iam 专项)核查
|
||||
|
||||
| 裁决 | 内容摘要 | 核查结论 | 证据 |
|
||||
| ---- | -------- | -------- | ---- |
|
||||
| I1 | P2 即启用 gRPC server 50052,REST + gRPC 并存 | ⚠️ **02 文档未回写**:[02-architecture-design.md](../../../services/iam/docs/02-architecture-design.md) §1/§7.1/§8.1 决策点 5 仍写"P2 仅 REST,P3 随 core-edu 引入 gRPC";iam.proto 仅 4 RPC 未补全 | [iam.proto](../../../packages/shared-proto/proto/iam.proto) 仅 4 RPC;[02 文档 §8.1](../../../services/iam/docs/02-architecture-design.md) 决策点 5 |
|
||||
| I2 | 直接建 shared-ts Outbox 工具包,iam 首次实现即用 | ✅ **工具包已建立**:`packages/shared-ts/src/outbox/` 存在 outbox.service.ts + outbox.module.ts;⚠️ 02 文档 §8.1 决策点 4 仍写"iam 自建轻量 Outbox",未回写 | [shared-ts/outbox](../../../packages/shared-ts/src/outbox/) |
|
||||
| I3 | 首次实现即 DB 驱动 + Redis 缓存,废弃本地 map | ❌ **源码未改造**:[permission.guard.ts](../../../services/iam/src/middleware/permission.guard.ts) 第 30-39 行仍用硬编码 `ROLE_PERMISSIONS` map(admin/teacher);02 文档 §8.1 决策点 9 描述为"待改造" | [permission.guard.ts](../../../services/iam/src/middleware/permission.guard.ts) |
|
||||
| I4 | 首次实现即注册 AuthMiddleware,Controller 用 @Req() 注入 | ❌ **源码未注册**:[app.module.ts](../../../services/iam/src/app.module.ts) 仅注册 PermissionGuard 为 APP_GUARD,未在 configure() 消费 AuthMiddleware;02 文档 §1.1/§1.2/§8.1 决策点 10 仍写"P2 仍不注册" | [app.module.ts](../../../services/iam/src/app.module.ts) |
|
||||
| I5 | P2 本地文件 IAM_PRIVATE_KEY_PATH / IAM_PUBLIC_KEY_PATH | ⚠️ **源码未实现**:[iam.service.ts](../../../services/iam/src/iam/iam.service.ts) 第 170-186 行仍用 `env.JWT_SECRET`(HS256 单密钥);02 文档 §8.1 决策点 1 已对齐(本地文件→P6 Vault)但未落地 | [iam.service.ts](../../../services/iam/src/iam/iam.service.ts) |
|
||||
| I6 | P2 即补全 iam_student_guardians 表 + GetChildrenByParent RPC + GET /iam/children | ❌ **02 文档表名错误**:[02 文档 §3.1.2](../../../services/iam/docs/02-architecture-design.md) 用 `iam_parent_student_relations`,裁决表名为 `iam_student_guardians`;源码未实现 | 02 文档 §3.1.2 |
|
||||
| I7 | 采用 /iam/v1/* 前缀,Gateway 透传 | ❌ **02 文档未回写**:[02 文档 §4.1](../../../services/iam/docs/02-architecture-design.md) REST API 清单全部用 `/iam/*` 无 `/v1` 前缀;源码 Controller 用 `@Controller("iam")` 无版本前缀 | [iam.controller.ts](../../../services/iam/src/iam/iam.controller.ts)、[rbac.controller.ts](../../../services/iam/src/iam/rbac.controller.ts) |
|
||||
| I8 | 统一 GET /iam/permissions/effective | ✅ **源码已对齐**:[rbac.controller.ts](../../../services/iam/src/iam/rbac.controller.ts) 第 33 行用 `@Get("permissions/effective")` | [rbac.controller.ts](../../../services/iam/src/iam/rbac.controller.ts) |
|
||||
|
||||
### 1.2 president-final-rulings 相关条款核查
|
||||
|
||||
| 条款 | 内容摘要 | 核查结论 |
|
||||
| ----- | -------- | -------- |
|
||||
| §2.15 | /iam/v1/* 版本化规则(Controller 加 v1 前缀) | ❌ 同 I7,未落地 |
|
||||
| §2.16 | gRPC 与 REST 双入口策略(gateway HTTP 透传 + BFF gRPC 调用) | ⚠️ 02 文档未体现双入口设计,仅描述 REST 单入口;contract.md §1.2 写"无对外 HTTP 端点,仅 gRPC"与此冲突 |
|
||||
| §3.2 | iam P2 拆分 P2.1(8 RPC 核心)+ P2.2(扩展) | ⚠️ workline.md 仅粗略列出 P2.1,P2.2-P6 未细化(见 worklines/iam_workline.md) |
|
||||
| §5.5 | 审计日志归 iam(AuditEvent + edu.iam.audit.created topic + user_audit_log 表) | ❌ 02 文档未包含审计日志设计;events.proto 未定义 AuditEvent message |
|
||||
| §5.1 | events.proto 补全 UserEvent/RoleEvent | ❌ events.proto 实际仅含 ClassEvent/ExamEvent/HomeworkEvent/GradeEvent,缺 UserEvent/RoleEvent/AuditEvent(coord-final-decisions §5.1 标注"✅ 已补全"与实际不符) |
|
||||
|
||||
### 1.3 coord.md ARB-001 / ARB-002 核查
|
||||
|
||||
| 仲裁 | 内容摘要 | 核查结论 |
|
||||
| ------ | -------- | -------- |
|
||||
| ARB-001 | teacher-bff GraphQL schema 第一版(5 Query) | ✅ schema 中 `me: User!`、`viewports` 依赖 iam,与 iam GetUserInfo/GetViewports RPC 对齐,无冲突 |
|
||||
| ARB-002 | MF Shell 暴露清单 | ✅ 不涉及 iam 直接交付物,无冲突 |
|
||||
|
||||
---
|
||||
|
||||
## §2 新提请异议
|
||||
|
||||
### ISSUE-001-ai06:01/02 文档未回写 I1-I8 裁决,中间过渡方案残留
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确 / 其他
|
||||
- **描述**:coord-final-decisions §0.1 强制覆盖声明要求各 AI 在 3 个工作日内回写 02 文档,删除所有"中间过渡方案"。president-final-rulings §3.4 也明确要求 ai06 回写 iam 02(I1-I8,§3.4)。但当前 [01-understanding.md](../../../services/iam/docs/01-understanding.md) 和 [02-architecture-design.md](../../../services/iam/docs/02-architecture-design.md) 仍残留大量过渡方案:
|
||||
- 02 §1/§7.1/§8.1 决策点 5:P2 仅 REST → P3 gRPC(违反 I1)
|
||||
- 02 §8.1 决策点 4:iam 自建 Outbox(违反 I2)
|
||||
- 02 §8.1 决策点 9:PermissionGuard 待改造(违反 I3)
|
||||
- 02 §1.1/§1.2/§8.1 决策点 10:AuthMiddleware P2 不注册(违反 I4)
|
||||
- 02 §3.1.2:表名 iam_parent_student_relations(违反 I6)
|
||||
- 02 §4.1:API 路径无 /v1 前缀(违反 I7)
|
||||
- 01 §1:teacher-bff HTTP 调用 iam(违反 B2,应 gRPC)
|
||||
- **建议方案**:ai06 立即回写 01/02 文档,删除全部中间过渡方案描述,对齐 I1-I8 + §2.15/§2.16/§5.5 最终方案。
|
||||
- **状态**:待 coord 仲裁(确认回写范围与验收标准)
|
||||
|
||||
### ISSUE-002-ai06:events.proto 缺少 UserEvent/RoleEvent/AuditEvent message
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:前置依赖缺失
|
||||
- **描述**:coord-final-decisions §5.1 标注"events.proto ✅ 已补全(UserEvent/RoleEvent/NotificationEvent/MasteryEvent/AIUsageEvent/KnowledgePointEvent/QuestionEvent)",president §5.5 也要求"events.proto 补 AuditEvent 在批次 0.10 完成"。但实际 [events.proto](../../../packages/shared-proto/proto/events.proto) 仅定义 ClassEvent/ExamEvent/HomeworkEvent/GradeEvent 4 个 message,**完全缺少** UserEvent/RoleEvent/AuditEvent 等 iam 依赖的事件契约。这直接阻塞 iam Outbox 事件发布(iam 无法写入未定义 schema 的事件)。
|
||||
- **建议方案**:coord 立即补全 events.proto,至少新增 UserEvent、RoleEvent、AuditEvent 三个 message(按 02 文档 §5.2 和 president §5.5 的字段定义)。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-003-ai06:Topic 命名三方不一致(edu.identity.* vs edu.iam.*)
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确
|
||||
- **描述**:iam 事件 Topic 命名存在三方不一致:
|
||||
- [004 §7.2](../../../docs/architecture/004_architecture_impact_map.md) 行 620-621:`edu.identity.user.created` / `edu.identity.user.updated`(用 `identity` 域名)
|
||||
- [matrix.md §4](../matrix.md) / [iam_contract.md §1.4](../contracts/iam_contract.md):`edu.iam.user.events` / `edu.iam.role.events` / `edu.iam.audit.created`(用 `iam` 域名)
|
||||
- president §5.5:`edu.iam.audit.created`(用 `iam` 域名)
|
||||
- coord-final-decisions G16 规则:`edu.<domain>.<aggregate>.<action>`
|
||||
- **建议方案**:统一用 `edu.iam.*`(服务名为 iam,非 identity),coord 同步修正 004 §7.2 的 `edu.identity.*` → `edu.iam.*`。同时明确 Topic 粒度:matrix.md 用聚合 topic(`edu.iam.user.events` 含多 action),004 §7.2 用具体动作 topic(`edu.iam.user.created`),需统一为一种风格。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-004-ai06:DataScope 枚举三方不一致
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确
|
||||
- **描述**:DataScope 6 级枚举存在三方不一致:
|
||||
- [004 §5.3 表](../../../docs/architecture/004_architecture_impact_map.md) 行 463-470:SELF/CLASS/GRADE/SCHOOL/DISTRICT/ALL
|
||||
- [004 §5.3](../../../docs/architecture/004_architecture_impact_map.md) 行 505:all/grade_managed/class_taught/children/owned + 自定义(语义命名,与表不同)
|
||||
- president §3.2 P2.2:ALL/SCHOOL/GRADE/CLASS/SUBJECT/SELF(**SUBJECT 替代 DISTRICT**)
|
||||
- 源码 [iam.schema.ts](../../../services/iam/src/iam/iam.schema.ts) 第 16-25 行:self/class/grade/school/district/all(与 004 表一致,与 president 不一致)
|
||||
- **建议方案**:coord 统一裁定最终枚举值。若采用 president 的 SUBJECT(学科级数据范围,K12 场景更实用),需同步修改源码 schema + 004 §5.3 表 + 02 文档;若保留 DISTRICT,需修正 president §3.2。同时修正 004 行 505 的语义命名使其与枚举表一致。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-005-ai06:iam.proto 仅 4 RPC,未补全至 12 RPC
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:前置依赖缺失
|
||||
- **描述**:coord-final-decisions §5.1 要求 iam.proto 在"P2 启动前"补全 8 个新 RPC(GetViewports / GetEffectivePermissions / GetEffectiveAccess / Logout / GetPublicKey / BatchGetUsers / GetEffectiveDataScope / GetChildrenByParent),president §6 批次 0 任务 0.3 也明确"coord 补全 iam.proto 8 RPC"。但实际 [iam.proto](../../../packages/shared-proto/proto/iam.proto) 仍仅 4 RPC(Register/Login/RefreshToken/GetUserInfo),未补全。这阻塞 iam P2.1 的 8 RPC 实现(proto 是契约先行前提)。
|
||||
- **建议方案**:coord 立即补全 iam.proto 至 12 RPC(含对应 message 定义),对齐 [iam_contract.md §1.1](../contracts/iam_contract.md) 的 12 RPC 清单。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-006-ai06:01/02 文档 AI 身份署名错误
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:其他
|
||||
- **描述**:[01-understanding.md](../../../services/iam/docs/01-understanding.md) 和 [02-architecture-design.md](../../../services/iam/docs/02-architecture-design.md) 署名"AI:ai02(TS / 身份认证)"、"AI Agent: ai02 (iam-module)"。但 coord-final-decisions §3.1、president §3.2、[matrix.md](../matrix.md)、[workline.md](../workline.md)、[iam_workline.md](../worklines/iam_workline.md)、[iam_contract.md](../contracts/iam_contract.md) 全部指明 iam 由 **ai06** 负责。ai02 实际负责 push-gateway(coord-final-decisions §3.7)。文档署名错误会导致多 AI 协作时身份混淆。
|
||||
- **建议方案**:回写时将 01/02 文档署名从 ai02 改为 ai06。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
### ISSUE-007-ai06:contract.md §1.2 与双入口策略冲突
|
||||
|
||||
- **提请方**:ai06
|
||||
- **日期**:2026-07-10
|
||||
- **类型**:契约不明确
|
||||
- **描述**:[iam_contract.md §1.2](../contracts/iam_contract.md) 写"无对外 HTTP 端点,仅 gRPC"。但 president §2.16 裁决双入口策略:REST 供 gateway 透传 + gRPC 供 BFF 聚合调用,"gateway 保持 HTTP 透传"。若 iam 不暴露 HTTP 端点,gateway 无法透传(gateway 不改为 gRPC 客户端)。
|
||||
- **建议方案**:修正 contract.md §1.2,补充 REST 端点清单(/iam/v1/* 系列),标明"REST 供 gateway 透传 + admin-portal 直连,gRPC 供 BFF 聚合调用"。
|
||||
- **状态**:待 coord 仲裁
|
||||
|
||||
---
|
||||
|
||||
## 问题列表
|
||||
|
||||
<!--
|
||||
@@ -21,4 +139,4 @@
|
||||
- **状态**:待 coord 仲裁 / 已裁决(见 coord.md §X)
|
||||
-->
|
||||
|
||||
(暂无问题)
|
||||
见上方 §2 新提请异议(ISSUE-001 ~ ISSUE-007)。
|
||||
|
||||
@@ -3,54 +3,154 @@
|
||||
> 负责人:ai06
|
||||
> 关联:[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/iam_contract.md](../contracts/iam_contract.md)
|
||||
> 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,最后统一集成测试)
|
||||
> 裁决依据:[coord-final-decisions](../../coord-final-decisions.md) I1-I8、[president-final-rulings](../../president-final-rulings.md) §3.2/§2.15/§2.16/§5.5
|
||||
|
||||
---
|
||||
|
||||
## §1 总览
|
||||
|
||||
iam 是身份认证服务,全阶段目标:gRPC 50052 + 12 RPC + /readyz 深度 + iam_student_guardians + DataScope + 审计日志 + Outbox。
|
||||
iam 是身份认证服务,全阶段目标:gRPC 50052 + 12 RPC + REST 双入口 + /readyz 深度 + iam_student_guardians + DataScope 6 级 + 审计日志 + Outbox + RBAC CRUD 完整化。
|
||||
|
||||
**核心裁决约束**(coord-final-decisions I1-I8):
|
||||
|
||||
- I1:P2 即启用 gRPC server 50052(REST + gRPC 双入口并存,非"P2 仅 REST → P3 gRPC")
|
||||
- I2:直接用 shared-ts Outbox 工具包(非 iam 自建)
|
||||
- I3:首次实现即 DB 驱动 + Redis 缓存 PermissionGuard(废弃硬编码 ROLE_PERMISSIONS map)
|
||||
- I4:首次实现即注册 AuthMiddleware(Controller 通过 @Req() 注入用户上下文)
|
||||
- I5:P2 本地文件 RS256 密钥(IAM_PRIVATE_KEY_PATH / IAM_PUBLIC_KEY_PATH),P6 迁 Vault
|
||||
- I6:P2 即补全 iam_student_guardians 表 + GetChildrenByParent RPC + GET /iam/children
|
||||
- I7:/iam/v1/* 前缀(Controller 加 v1 前缀,Gateway 透传)
|
||||
- I8:统一 GET /iam/permissions/effective
|
||||
|
||||
**工作量分级**(president §3.2):iam 实际工作量 26-27 天,拆分 P2.1(核心,阻塞批次 2)+ P2.2(扩展,P3 期间持续补,不阻塞)。
|
||||
|
||||
---
|
||||
|
||||
## §2 全阶段甘特图(P2-P6,各 AI 自行细化)
|
||||
## §2 全阶段甘特图(P2-P6)
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title ai06 iam 全阶段排期
|
||||
title ai06 iam 全阶段排期(P2.1/P2.2 拆分版)
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %m-%d
|
||||
|
||||
section P2.1 核心
|
||||
gRPC server 50052启用 :crit, a6a, 2026-07-10, 2d
|
||||
12 RPC实现 :crit, a6b, after a6a, 4d
|
||||
/readyz深度(5依赖) :a6c, after a6b, 1d
|
||||
iam_student_guardians+DataScope :a6d, after a6b, 1d
|
||||
section P2.1 核心(阻塞批次2)
|
||||
1.1 proto 契约确认(依赖coord补全iam.proto) :crit, a1, 2026-07-10, 1d
|
||||
1.2 gRPC server 50052 + AuthMiddleware注册 :crit, a2, after a1, 2d
|
||||
1.3 8 RPC实现(GetViewports/GetEffectivePermissions/GetEffectiveAccess/Logout/GetPublicKey/BatchGetUsers/GetEffectiveDataScope/GetChildrenByParent) :crit, a3, after a2, 4d
|
||||
1.4 JWT RS256本地文件+refresh轮换 :crit, a4, after a2, 2d
|
||||
1.5 /iam/v1/*前缀迁移+端点统一(I7/I8) :crit, a5, after a3, 1d
|
||||
1.6 iam_student_guardians表+GetChildrenByParent(I6) :crit, a6, after a3, 1d
|
||||
1.7 shared-ts Outbox接入+事件发布(I2) :crit, a7, after a3, 2d
|
||||
1.8 DB驱动PermissionGuard基础(I3) :crit, a8, after a3, 2d
|
||||
1.9 /readyz深度(5依赖:DB/Redis/Kafka/gRPC/JWKS) :a9, after a8, 1d
|
||||
1.10 02文档回写(I1-I8对齐) :crit, a10, 2026-07-10, 1d
|
||||
|
||||
section P2.2-P6 扩展
|
||||
审计日志+Outbox :a6e, after a6d, 3d
|
||||
持续补全 :a6f, after a6e, 5d
|
||||
section P2.2 扩展(P3期间持续补)
|
||||
2.1 三层角色模型(system/organization/temporary) :b1, after a8, 3d
|
||||
2.2 DataScope 6级实现(待ISSUE-004裁决) :b2, after a8, 2d
|
||||
2.3 视口4层+getEffectivePermissions完整 :b3, after b1, 3d
|
||||
2.4 审计日志(user_audit_log表+AuditEvent发布) :b4, after b1, 3d
|
||||
2.5 Redis缓存完整实现(I3完整) :b5, after b1, 2d
|
||||
2.6 密码策略(强度/过期/重用限制) :b6, after b4, 2d
|
||||
2.7 单元测试+集成测试(覆盖率≥80%) :b7, after b6, 3d
|
||||
|
||||
section P3-P6 持续优化
|
||||
3.1 RBAC CRUD完整化(角色/权限/视口增删改) :c1, after b3, 3d
|
||||
3.2 2FA实现(TOTP) :c2, after b6, 3d
|
||||
3.3 JWT密钥迁移Vault(P6) :c3, after c2, 2d
|
||||
3.4 /readyz硬化+性能优化 :c4, after c1, 2d
|
||||
```
|
||||
|
||||
> **注意**:以上为 coord 初始规划,ai06 接管后必须自行细化为完整 P2-P6 排期。
|
||||
|
||||
---
|
||||
|
||||
## §3 详细任务
|
||||
|
||||
### P2.1:gRPC + 12 RPC + /readyz + DataScope
|
||||
### P2.1:gRPC + 8 RPC + RS256 + AuthMiddleware + Outbox(阻塞批次 2)
|
||||
|
||||
- **负责人**:ai06
|
||||
- **批次**:批次 1(P2)
|
||||
- **预估**:5-7 天
|
||||
- **前置依赖**:
|
||||
- coord 补全 iam.proto 至 12 RPC(ISSUE-005,阻塞项)
|
||||
- coord 补全 events.proto UserEvent/RoleEvent(ISSUE-002,阻塞 Outbox 事件发布)
|
||||
- shared-ts Outbox 工具包已就绪(✅ 已存在)
|
||||
- **交付物**:
|
||||
- gRPC server 50052 + 12 RPC(见 iam.proto)
|
||||
- /readyz 5 项依赖检查
|
||||
- iam_student_guardians 表 + DataScope=CHILDREN
|
||||
- **依赖**:iam.proto(批次 0 已完成)
|
||||
- **验收标准**:12 RPC 全部可用 + /readyz 返回 5 项状态
|
||||
- **完整 P2.2-P6 任务**:⚠️ 由 ai06 自行补充
|
||||
1. gRPC server 50052 启用(NestJS gRPC transport)
|
||||
2. 8 RPC 实现:GetViewports / GetEffectivePermissions / GetEffectiveAccess / Logout / GetPublicKey / BatchGetUsers / GetEffectiveDataScope / GetChildrenByParent
|
||||
3. AuthMiddleware 注册(app.module.ts configure 消费),Controller 改用 @Req() 注入用户上下文(I4)
|
||||
4. JWT RS256 本地文件加载(IAM_PRIVATE_KEY_PATH / IAM_PUBLIC_KEY_PATH)+ refresh token 轮换 + 旧 token 黑名单(I5)
|
||||
5. /iam/v1/* 前缀迁移(Controller `@Controller('v1/iam')`)+ 端点路径统一 I8(I7)
|
||||
6. iam_student_guardians 表 + GET /iam/v1/children REST + GetChildrenByParent gRPC(I6)
|
||||
7. shared-ts Outbox 接入,发布 UserEvent/RoleEvent(I2)
|
||||
8. DB 驱动 PermissionGuard 基础(废弃 permission.guard.ts 硬编码 ROLE_PERMISSIONS map,改调 IamService.getEffectivePermissions)(I3)
|
||||
9. /readyz 深度检查 5 项依赖(DB SELECT 1 / Redis PING / Kafka 连接 / gRPC 自身可达 / JWKS 可读)
|
||||
10. 01/02 文档回写(删除全部中间过渡方案,对齐 I1-I8 + §2.15/§2.16/§5.5)
|
||||
- **验收标准**:
|
||||
- gRPC 50052 HealthService.Check 返回 SERVING
|
||||
- 8 RPC 全部可调用并返回正确响应
|
||||
- GetPublicKey 返回 RS256 PEM 公钥(供 api-gateway 验签)
|
||||
- GetChildrenByParent 返回学生列表(供 parent-bff P4 消费)
|
||||
- /iam/v1/* 前缀生效,旧路径不保留
|
||||
- AuthMiddleware 注入 req.user(userId/roles/dataScope)
|
||||
- /readyz 返回 5 项依赖状态
|
||||
- **就绪信号**:gRPC 50052 启用 + GetPublicKey RPC 可用 + HealthService.Check 返回 SERVING
|
||||
|
||||
### P2.2:三层角色 + DataScope + 视口 + 审计 + 缓存(P3 期间持续补,不阻塞)
|
||||
|
||||
- **负责人**:ai06
|
||||
- **批次**:批次 2-3 期间(P3 进行中持续补)
|
||||
- **预估**:12-15 天
|
||||
- **前置依赖**:P2.1 完成 + ISSUE-004(DataScope 枚举裁决)
|
||||
- **交付物**:
|
||||
1. 三层角色模型(system / organization / temporary,iam_roles 表扩展 role_type + level 字段)
|
||||
2. DataScope 6 级实现(ALL / SCHOOL / GRADE / CLASS / SUBJECT|DISTRICT / SELF,待 ISSUE-004 裁决)
|
||||
3. 视口 4 层(admin / teacher / student / parent)+ getEffectivePermissions 完整聚合
|
||||
4. 审计日志(user_audit_log 表 + AuditEvent 发布到 edu.iam.audit.created topic,president §5.5)
|
||||
5. Redis 缓存完整实现(getEffectivePermissions TTL 5min + 角色变更主动 DEL + getUserViewports 缓存)
|
||||
6. 密码策略(强度校验 / 过期提醒 / 重用限制)
|
||||
7. 单元测试 + 集成测试(覆盖率 ≥ 80%,对齐 classes 黄金模板)
|
||||
- **验收标准**:
|
||||
- 三层角色可创建/分配/查询
|
||||
- DataScope 在 Repository 层动态注入 WHERE 条件
|
||||
- 审计事件可发布到 Kafka
|
||||
- Redis 缓存命中率可观测(iam_permission_cache_hits_total 指标)
|
||||
- 测试覆盖率 ≥ 80%
|
||||
|
||||
### P3-P6:RBAC CRUD + 2FA + Vault 迁移 + 硬化
|
||||
|
||||
- **负责人**:ai06
|
||||
- **批次**:批次 4-5(P5-P6 期间)
|
||||
- **预估**:8-10 天
|
||||
- **交付物**:
|
||||
1. RBAC CRUD 完整化(角色/权限/视口增删改,系统角色禁止删除)
|
||||
2. 2FA 实现(TOTP,pending-features §P2 提及)
|
||||
3. JWT 密钥迁移 Vault(P6,president X8)
|
||||
4. /readyz 硬化 + 性能优化(连接池调优、缓存策略优化)
|
||||
- **验收标准**:
|
||||
- RBAC CRUD 全部端点可用 + 权限装饰器覆盖
|
||||
- 2FA 可启用/验证/禁用
|
||||
- Vault 密钥轮换不中断服务
|
||||
|
||||
---
|
||||
|
||||
## §4 依赖与就绪信号
|
||||
|
||||
- **我依赖**:无(iam 是基础服务)
|
||||
- **我的就绪信号**:gRPC 50052 启用 + GetPublicKey RPC 可用 + HealthService.Check 返回 SERVING
|
||||
### 4.1 我依赖的上游就绪标志
|
||||
|
||||
| 依赖项 | 提供方 | 就绪标志 | 状态 |
|
||||
| ------ | ------ | -------- | ---- |
|
||||
| iam.proto 补全至 12 RPC | coord | proto 文件含 12 RPC + 全部 message | ❌ 仅 4 RPC(ISSUE-005) |
|
||||
| events.proto 补全 UserEvent/RoleEvent/AuditEvent | coord | proto 文件含 3 个 message | ❌ 缺失(ISSUE-002) |
|
||||
| shared-ts Outbox 工具包 | coord | outbox.service.ts + outbox.module.ts 可导入 | ✅ 已就绪 |
|
||||
| shared-ts Redis 工具包 | coord | redis client 单例可导入 | ⏳ 待确认 |
|
||||
|
||||
### 4.2 我的就绪信号(供下游消费)
|
||||
|
||||
- [ ] iam gRPC 50052 启用(HealthService.Check 返回 SERVING)
|
||||
- [ ] IamService 12 RPC 全部可调用(Register/Login/RefreshToken/Logout/GetUserInfo/BatchGetUsers/GetEffectivePermissions/GetEffectiveAccess/GetEffectiveDataScope/GetViewports/GetPublicKey/GetChildrenByParent)
|
||||
- [ ] IamService.GetPublicKey 可用(返回 RS256 PEM 公钥,供 api-gateway 验签)
|
||||
- [ ] IamService.GetChildrenByParent 可用(供 parent-bff 查孩子列表)
|
||||
- [ ] edu.iam.user.events / edu.iam.role.events / edu.iam.audit.created topic 可发布
|
||||
- [ ] JWT RS256 签发链路打通(access_token 15min + refresh_token 7day 轮换)
|
||||
- [ ] /iam/v1/* REST 端点可用(供 gateway 透传 + admin-portal 直连)
|
||||
|
||||
Reference in New Issue
Block a user