# iam 下一步工作与上下游依赖(Next Steps) > 模块:iam(身份与访问管理服务,端口 3002 HTTP + 50052 gRPC) > 负责人:ai06 > 更新日期:2026-07-13 > 关联文档: > > - [iam_contract.md](../../docs/architecture/issues/contracts/iam_contract.md) > - [iam_workline.md](../../docs/architecture/issues/worklines/iam_workline.md) > - [02-architecture-design.md](./02-architecture-design.md) --- ## 1. 模块当前状态 iam 服务已完成 P2–P6 全部批次,包含 15 个 gRPC RPC + 完整 REST CRUD + TOTP 2FA + 审计日志 + Outbox 事件发布 + Redis 权限缓存(含 Prometheus 指标)。本地 Docker 验证通过(真实 MySQL/Redis/Kafka,无 mock 数据)。 ### 1.1 本地 Docker 验证结果(2026-07-13) 测试环境:`edu-iam-test` 容器(NODE_ENV=production, DEV_MODE=true),接入 `edu-full_default` 网络,直连 edu-mysql / edu-redis / edu-kafka。 | 验证项 | 状态 | 说明 | | ----------------------------------------------------------- | ---- | ------------------------------------------------------------------ | | Docker 镜像构建 | ✅ | node:20-alpine + shared-ts 预编译 + pnpm install --frozen-lockfile | | /healthz 健康检查 | ✅ | 200 `{"status":"ok","service":"iam"}` | | /metrics Prometheus 指标 | ✅ | 含 iam_permission_cache_hits/misses/invalidations 三个新指标 | | gRPC 50052 启动 | ✅ | 日志 `IAM service started (HTTP + gRPC dual entry)` | | GET /.well-known/jwks.json | ✅ | 返回 RS256 公钥(kid=iam-rs256-v1) | | POST /v1/iam/register | ✅ | 创建用户 + 返回 JWT token 对 | | POST /v1/iam/login | ✅ | 邮箱密码登录 + 返回 JWT token 对 | | GET /v1/iam/me | ✅ | 返回当前用户信息 | | PATCH /v1/iam/me | ✅ | 更新个人资料(name/email) | | POST /v1/iam/change-password | ✅ | 密码强度校验 + 历史重用检查 + token 撤销 | | GET /v1/iam/viewports | ✅ | 返回视口列表(含 level + componentConfig 字段) | | GET /v1/iam/permissions/effective | ✅ | 返回用户有效权限列表 | | GET /v1/iam/children | ✅ | 返回家长-学生关系 | | GET /v1/iam/users(分页) | ✅ | 返回用户列表 + total 总数 | | PATCH /v1/iam/users/:id | ✅ | 管理员更新用户 | | PATCH /v1/iam/users/:id/status | ✅ | 用户状态切换 | | GET /v1/iam/roles | ✅ | 返回角色列表(含三层角色模型) | | POST /v1/iam/roles | ✅ | 创建角色(system/organization/temporary) | | PATCH /v1/iam/roles/:id | ✅ | 更新角色 | | PATCH /v1/iam/roles/:id/permissions | ✅ | 批量更新角色权限 | | POST/DELETE /v1/iam/roles/:roleId/permissions/:permissionId | ✅ | 单条授权/撤销 | | GET /v1/iam/permissions | ✅ | 返回权限点列表 | | POST /v1/iam/permissions | ✅ | 创建权限点 | | PATCH /v1/iam/permissions/:id | ✅ | 更新权限点 | | DELETE /v1/iam/permissions/:id | ✅ | 删除权限点(级联清理 role_permissions) | | POST /v1/iam/viewports | ✅ | 创建视口(含 level + componentConfig) | | PATCH /v1/iam/viewports/:id | ✅ | 更新视口 | | DELETE /v1/iam/viewports/:id | ✅ | 删除视口 | | POST /v1/iam/totp/enable | ✅ | 生成 TOTP 密钥 + QR URL + 10 个备份码 | | POST /v1/iam/totp/verify | ✅ | 验证 TOTP 码(pending → active) | | POST /v1/iam/totp/disable | ✅ | 禁用 TOTP | | typecheck + lint | ✅ | 两项零错误 | ### 1.2 已完成的关键能力 | # | 能力 | 实现详情 | | --- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | 15 个 gRPC RPC | Register/Login/RefreshToken/Logout/GetUserInfo/GetUserProfile/UpdateProfile/ChangePassword/BatchGetUsers/GetEffectivePermissions/GetEffectiveAccess/GetEffectiveDataScope/GetViewports/GetPublicKey/GetChildrenByParent | | 2 | REST CRUD 完整 | 角色/权限/视口/用户/TOTP 全部 CRUD 端点 | | 3 | 三层角色模型 | system(level=0)/ organization(level=1)/ temporary(level=2) | | 4 | DataScope 6 级 | self/subject/class/grade/school/all | | 5 | 视口 4 层 + L4 数据级配置 | admin/teacher/student/parent + componentConfig JSON | | 6 | 密码策略 | bcrypt cost 12 + 强度校验 + 5 次历史重用限制 | | 7 | TOTP 2FA | RFC 6238 HMAC-SHA1 纯 JS 实现 + 10 备份码 | | 8 | 审计日志 | ip/userAgent/traceId 从请求头提取 + Outbox 事件发布 | | 9 | JWKS 端点 | `GET /v1/iam/.well-known/jwks.json` 暴露 RS256 公钥 | | 10 | Redis 权限缓存 | TTL 5min + 角色变更失效 + hit/miss/invalidation 指标 | | 11 | Outbox 模式 | iam_outbox 表 + Kafka publisher(edu.iam.user.events / edu.iam.role.events / edu.iam.audit.created) | | 12 | AuthMiddleware | 从 Gateway 注入的 x-user-* 头部解析用户身份 | | 13 | PermissionGuard | APP_GUARD + DB 驱动 + Redis 缓存 + dataScope=all 跳过校验 | --- ## 2. 上游依赖(iam 依赖谁) iam 作为身份基础设施服务,运行时依赖以下组件: ### 2.1 MySQL(基础设施)— P0 | 项 | 内容 | | -------- | ----------------------------------------------------------------- | | 依赖内容 | 用户/角色/权限/视口/审计日志/密码历史/TOTP/Outbox 表 | | 端点 | `mysql://edu:changeme@edu-mysql:3306/next_edu_cloud` | | 用途 | 所有业务数据持久化 | | 当前状态 | ✅ 本地 Docker edu-mysql 已就绪 | | 环境变量 | `DATABASE_URL=mysql://edu:changeme@edu-mysql:3306/next_edu_cloud` | ### 2.2 Redis(基础设施)— P0 | 项 | 内容 | | -------- | ---------------------------------------------- | | 依赖内容 | 权限缓存 + token 黑名单 | | 端点 | `redis://edu-redis:6379` | | 用途 | 1) 用户权限缓存(TTL 5min)2) 角色变更失效广播 | | 当前状态 | ✅ 本地 Docker edu-redis 已就绪 | | 环境变量 | `REDIS_URL=redis://edu-redis:6379` | ### 2.3 Kafka(基础设施)— P1 | 项 | 内容 | | -------- | ------------------------------------------------------------------------------------ | | 依赖内容 | Outbox 事件投递(edu.iam.user.events / edu.iam.role.events / edu.iam.audit.created) | | 端点 | `kafka:29092`(容器内 INSIDE listener) | | 用途 | 事务性事件发布(用户注册/登录/角色变更/审计日志) | | 当前状态 | ✅ 本地 Docker edu-kafka 已就绪 | | 环境变量 | `KAFKA_BROKERS=kafka:29092`、`KAFKA_CLIENT_ID=iam-service` | | 降级策略 | Kafka 不可用时 Outbox 表持续累积,Kafka 恢复后自动投递 | ### 2.4 shared-proto(协调 AI 维护)— P0 | 项 | 内容 | | -------- | ------------------------------------------------ | | 依赖内容 | `packages/shared-proto/proto/iam.proto` 契约定义 | | 用途 | gRPC 服务定义 + proto-loader 运行时加载 | | 当前状态 | ✅ 15 个 RPC 全部声明 | ### 2.5 shared-ts(协调 AI 维护)— P0 | 项 | 内容 | | -------- | ---------------------------------------------------- | | 依赖内容 | `@edu/shared-ts/outbox` OutboxModule + OutboxService | | 用途 | 事务性事件发布框架 | | 当前状态 | ✅ 已构建并集成 | --- ## 3. 下游依赖(谁依赖 iam) 以下 9 个模块依赖 iam 服务: ### 3.1 api-gateway(ai01 负责)— P0 | # | 依赖项 | 用途 | 状态 | | --- | ----------------------------------- | ---------------------------------------------------- | --------- | | 1 | `GET /v1/iam/.well-known/jwks.json` | RS256 公钥集(JWKS),TTL 5min 缓存 | ✅ 已就绪 | | 2 | RS256 JWT 签发 | api-gateway 用 JWKS 公钥校验 access_token | ✅ 已就绪 | | 3 | `GET /healthz` 端点 | /readyz 下游健康检查 | ✅ 已就绪 | | 4 | JWT claims 含 role/data_scope | api-gateway 注入 x-user-roles / x-user-data-scope 头 | ✅ 已就绪 | **验证结果**:JWKS 端点返回有效公钥,JWT token 可被 RS256 验签。 ### 3.2 push-gateway(ai09 负责)— P0 | # | 依赖项 | 用途 | 状态 | | --- | ---------------------------------------- | ----------------------------------------- | --------- | | 1 | `GET /v1/iam/.well-known/jwks.json` | WebSocket `/ws` 连接时校验客户端 JWT 签名 | ✅ 已就绪 | | 2 | shared-go/jwks Fetcher 每 5 分钟刷新缓存 | JWKS 缓存刷新 | ✅ 已就绪 | **环境变量**:`JWKS_URL=http://iam:3002/v1/iam/.well-known/jwks.json` ### 3.3 teacher-bff(ai03 负责)— P0 | # | 依赖项 | 用途 | 状态 | | --- | ------------------------------------------------ | ----------------------------- | --------- | | 1 | gRPC `GetUserInfo(userId)` :50052 | `currentUser`/`me` 查询 | ✅ 已就绪 | | 2 | gRPC `BatchGetUsers(userIds)` :50052 | `adminUsers` 查询 | ✅ 已就绪 | | 3 | gRPC `GetEffectivePermissions(userId)` :50052 | 用户有效权限列表 | ✅ 已就绪 | | 4 | gRPC `GetEffectiveDataScope(userId)` :50052 | 用户数据范围 | ✅ 已就绪 | | 5 | gRPC `GetViewports(userId)` :50052 | `adminViewports` 查询 | ✅ 已就绪 | | 6 | gRPC `GetPublicKey()` :50052 | RS256 公钥 | ✅ 已就绪 | | 7 | gRPC `GetChildrenByParent(parentId)` :50052 | 家长端学生列表 | ✅ 已就绪 | | 8 | REST `GET /v1/iam/roles` :3002 | `adminRoles` 查询 | ✅ 已就绪 | | 9 | REST `GET /v1/iam/permissions` :3002 | `adminPermissions` 查询 | ✅ 已就绪 | | 10 | REST `GET /v1/iam/audit` :3002 | `auditLogs` 查询 | ✅ 已就绪 | | 11 | REST `GET /v1/iam/viewports` :3002 | `adminViewports` 查询(备选) | ✅ 已就绪 | | 12 | REST `GET /v1/iam/permissions/effective` :3002 | 用户有效权限(备选) | ✅ 已就绪 | | 13 | `GET /.well-known/jwks.json` :3002 | RS256 JWKS | ✅ 已就绪 | | 14 | `POST /v1/iam/register` / `POST /v1/iam/login` | 用户注册/登录 | ✅ 已就绪 | | 15 | `PATCH /v1/iam/users/:id` | 用户更新 | ✅ 已就绪 | | 16 | `POST /v1/iam/roles` / `PATCH /v1/iam/roles/:id` | 角色创建/更新 | ✅ 已就绪 | **环境变量**:`IAM_GRPC_TARGET=iam:50052`、`IAM_SERVICE_URL=http://iam:3002` ### 3.4 student-bff(ai04 负责)— P0 | # | gRPC 方法 | 用途 | 状态 | | --- | ---------------- | ------------------------- | --------- | | 1 | `GetUserProfile` | `myProfile` Query | ✅ 已就绪 | | 2 | `UpdateProfile` | `updateProfile` Mutation | ✅ 已就绪 | | 3 | `ChangePassword` | `changePassword` Mutation | ✅ 已就绪 | **proto 位置**:`packages/shared-proto/proto/iam.proto` ### 3.5 parent-bff(ai05 负责)— P0 | # | RPC 方法 | 用途 | 状态 | | --- | --------------------------------- | ---------------------- | --------- | | 1 | `getUserInfo(userId)` | 获取家长个人信息 | ✅ 已就绪 | | 2 | `getChildrenByParent(parentId)` | 获取家长绑定的孩子列表 | ✅ 已就绪 | | 3 | `getViewports(userId)` | 获取家长可见视口 | ✅ 已就绪 | | 4 | `getEffectivePermissions(userId)` | 获取家长有效权限 | ✅ 已就绪 | | 5 | `GET /healthz` 端点 | /readyz 下游健康检查 | ✅ 已就绪 | | 6 | `GET /.well-known/jwks.json` | RS256 公钥集 | ✅ 已就绪 | **环境变量**:`IAM_GRPC_TARGET=iam:50052` ### 3.6 teacher-portal(ai13 负责)— P1 | # | 依赖项 | 用途 | 状态 | | --- | ----------------------------------- | ------------------------------------------ | --------- | | 1 | JWT RS256 签发 | 登录后获取 access_token + refresh_token | ✅ 已就绪 | | 2 | `POST /v1/iam/login` | 教师登录 | ✅ 已就绪 | | 3 | `POST /v1/iam/refresh` | 刷新 token | ✅ 已就绪 | | 4 | `POST /v1/iam/logout` | 登出 | ✅ 已就绪 | | 5 | `GET /v1/iam/me` | 获取当前用户信息 | ✅ 已就绪 | | 6 | `GET /v1/iam/viewports` | 获取视口配置(含 level + componentConfig) | ✅ 已就绪 | | 7 | `GET /v1/iam/permissions/effective` | 获取有效权限 | ✅ 已就绪 | ### 3.7 student-portal(ai14 负责)— P1 | # | 依赖项 | 用途 | 状态 | | --- | ------------------------------ | ------------ | --------- | | 1 | JWT RS256 签发 | 学生登录 | ✅ 已就绪 | | 2 | `POST /v1/iam/login` | 学生登录 | ✅ 已就绪 | | 3 | `PATCH /v1/iam/me` | 更新个人资料 | ✅ 已就绪 | | 4 | `POST /v1/iam/change-password` | 修改密码 | ✅ 已就绪 | ### 3.8 parent-portal(ai15 负责)— P1 | # | 依赖项 | 用途 | 状态 | | --- | ---------------------- | ------------------ | --------- | | 1 | JWT RS256 签发 | 家长登录 | ✅ 已就绪 | | 2 | `POST /v1/iam/login` | 家长登录 | ✅ 已就绪 | | 3 | `GET /v1/iam/children` | 获取绑定的学生列表 | ✅ 已就绪 | | 4 | `GET /v1/iam/me` | 获取家长个人信息 | ✅ 已就绪 | ### 3.9 admin-portal(ai16 负责)— P0 | # | 依赖项 | 用途 | 状态 | | --- | ------------------------------------------------- | --------------------------- | --------- | | 1 | `GET /v1/iam/users` | 用户管理列表(分页 + 搜索) | ✅ 已就绪 | | 2 | `PATCH /v1/iam/users/:id` | 用户更新 | ✅ 已就绪 | | 3 | `PATCH /v1/iam/users/:id/status` | 用户状态切换 | ✅ 已就绪 | | 4 | `POST/PATCH/DELETE /v1/iam/roles` | 角色 CRUD | ✅ 已就绪 | | 5 | `POST/PATCH/DELETE /v1/iam/permissions` | 权限 CRUD | ✅ 已就绪 | | 6 | `POST/PATCH/DELETE /v1/iam/viewports` | 视口 CRUD | ✅ 已就绪 | | 7 | `POST /v1/iam/totp/enable` / `verify` / `disable` | TOTP 2FA 管理 | ✅ 已就绪 | | 8 | `GET /v1/iam/audit` | 审计日志查询 | ✅ 已就绪 | --- ## 4. 剩余工作 ### 4.1 已完成 | 工作项 | 状态 | | ----------------------- | ---- | | P2-P6 全部批次 | ✅ | | 15 个 gRPC RPC | ✅ | | REST CRUD 完整 | ✅ | | TOTP 2FA | ✅ | | 密码策略 + 历史重用 | ✅ | | 审计日志 + Outbox | ✅ | | Redis 权限缓存 + 指标 | ✅ | | JWKS 端点 | ✅ | | Docker 本地测试通过 | ✅ | | typecheck + lint 零错误 | ✅ | ### 4.2 待办(非阻塞) | # | 工作项 | 优先级 | 阻塞条件 | | --- | --------------------------------------------------------------------------- | ------ | ------------ | | 1 | 单元测试 + 集成测试覆盖率 ≥ 80% | P2 | 无 | | 2 | 生产环境 JWT 密钥轮换流程 | P3 | 生产部署前 | | 3 | Kafka topic 创建自动化(edu.iam.user.events / role.events / audit.created) | P3 | K8s 部署阶段 | | 4 | 数据库迁移脚本(drizzle-kit) | P3 | 生产部署前 | --- ## 5. 联调待办 | # | 联调项 | 对端模块 | 状态 | | --- | ------------------------------------------------------- | --------------------- | --------- | | 1 | api-gateway JWKS 真实验签 | api-gateway (ai01) | ✅ 已就绪 | | 2 | push-gateway JWKS 真实验签 | push-gateway (ai09) | ✅ 已就绪 | | 3 | teacher-bff gRPC 全量调用 | teacher-bff (ai03) | ✅ 已就绪 | | 4 | student-bff GetUserProfile/UpdateProfile/ChangePassword | student-bff (ai04) | ✅ 已就绪 | | 5 | parent-bff getUserInfo/getChildrenByParent/getViewports | parent-bff (ai05) | ✅ 已就绪 | | 6 | admin-portal RBAC CRUD 全量 | admin-portal (ai16) | ✅ 已就绪 | | 7 | teacher-portal 登录 + 视口 | teacher-portal (ai13) | ✅ 已就绪 | | 8 | student-portal 登录 + 个人资料 | student-portal (ai14) | ✅ 已就绪 | | 9 | parent-portal 登录 + 孩子列表 | parent-portal (ai15) | ✅ 已就绪 | --- **本文件由 ai06 维护。iam 服务已全量就绪,所有下游模块可开始真实联调。**