NestJS (6 services): implement @RequirePermission decorator with SetMetadata+Reflector, register APP_GUARD globally, fix as assertions to type guards, add explicit return types, fix import type for express, fix /metrics implicit any, replace native Error with ApplicationError, remove typeorm remnants, register LifecycleService. teacher-bff: add logger, ApplicationError, GlobalErrorFilter, forward real userId to downstream, log downstream failures, migrate health controller to shared/health. Go (2 services): interface to any, doc comments, CORS dev whitelist, JWT secret fail-fast, push-gateway internal API auth, metrics and readyz endpoints, remove dead code. Python (2 services): lifespan return type, dev_mode to bool, data-ana APIRouter, ai POST body model, ClickHouse async wrapping.
177 lines
9.2 KiB
Markdown
177 lines
9.2 KiB
Markdown
# 服务审计表 — ai04
|
||
|
||
> AI 标识:ai04
|
||
> 阶段:阶段 1(自检)
|
||
> 日期:2026-07-09
|
||
> 审计对象:student-bff(P3 待实现)、parent-bff(P4 待实现)
|
||
> 对照基准:classes 黄金模板(已实现)+ teacher-bff BFF 模板(已实现)
|
||
> 模板来源:[ai-allocation.md §10](../../docs/architecture/ai-allocation.md)
|
||
|
||
---
|
||
|
||
## 1. 审计状态说明
|
||
|
||
| 标记 | 含义 |
|
||
| ---- | --------------------------------------------------- |
|
||
| ✅ | 已对齐黄金模板(实施时复制 + 改名即可) |
|
||
| ⚠️ | 有差异但已识别缓解方案(需 coord 仲裁或实施时调整) |
|
||
| ❌ | 未对齐,需补齐 |
|
||
| 🆕 | 全新服务,尚未实现,审计结果为"设计目标" |
|
||
|
||
由于 student-bff 和 parent-bff 均为**全新服务(未实现)**,本审计表为**设计目标审计**,列出实施时需对齐的各项。
|
||
|
||
---
|
||
|
||
## 2. ai04 服务审计表
|
||
|
||
| 服务 | 权限装饰器 | 错误码前缀 | logger | metrics | tracer | /healthz | /readyz | 优雅关闭 | 测试覆盖率 | Dockerfile |
|
||
| ---------------------------- | ---------- | ----------------- | ------- | -------------- | ------- | -------- | ------- | ---------- | ------------ | ---------- |
|
||
| **student-bff**(P3 待实现) | ⚠️ 不对齐 | ✅ `STUDENT_BFF_` | ✅ pino | ✅ prom-client | ✅ OTel | ✅ | ✅ | ✅ SIGTERM | 🆕 目标 ≥80% | ✅ 多阶段 |
|
||
| **parent-bff**(P4 待实现) | ⚠️ 不对齐 | ✅ `PARENT_BFF_` | ✅ pino | ✅ prom-client | ✅ OTel | ✅ | ✅ | ✅ SIGTERM | 🆕 目标 ≥80% | ✅ 多阶段 |
|
||
|
||
---
|
||
|
||
## 3. 审计项详解
|
||
|
||
### 3.1 权限装饰器 `@RequirePermission` — ⚠️ 不对齐
|
||
|
||
**classes 黄金模板**:全部 Controller 方法用 `@RequirePermission(Permissions.XXX)` 装饰,全局 `PermissionGuard` 校验。
|
||
|
||
**ai04 服务决策**:**不对齐**。理由:
|
||
|
||
- BFF 是纯聚合层,权限由下游业务服务校验(对齐 teacher-bff 现状)
|
||
- BFF 透传 `x-user-id` 头给下游,下游 Repository 按 DataScope 过滤
|
||
- parent-bff 在 BFF 层做"DataScope=CHILDREN 越权校验"(家长查询的 childId 必须在绑定列表内),但用普通 Service 层校验,不用装饰器
|
||
|
||
**风险**:若 coord 要求 BFF 也加权限装饰器(双重校验),需在 student-bff/parent-bff 引入 `middleware/permission.guard.ts`(复制 classes 实现)。
|
||
|
||
### 3.2 错误码前缀 — ✅ 对齐
|
||
|
||
| 服务 | 前缀 | 示例 |
|
||
| ----------- | -------------- | --------------------------------------------------------------------------------- |
|
||
| student-bff | `STUDENT_BFF_` | `STUDENT_BFF_UNAUTHORIZED`、`STUDENT_BFF_BAD_GATEWAY` |
|
||
| parent-bff | `PARENT_BFF_` | `PARENT_BFF_UNAUTHORIZED`、`PARENT_BFF_BAD_GATEWAY`、`PARENT_BFF_CHILD_NOT_BOUND` |
|
||
|
||
对齐 teacher-bff 的 `TEACHER_BFF_` 模式。
|
||
|
||
### 3.3 logger — ✅ 对齐
|
||
|
||
复制 teacher-bff `shared/observability/logger.ts`,仅改 `service` 字段:
|
||
|
||
- student-bff: `service: 'student-bff'`
|
||
- parent-bff: `service: 'parent-bff'`
|
||
|
||
### 3.4 metrics — ✅ 对齐
|
||
|
||
复制 teacher-bff `shared/observability/metrics.ts` + `main.ts` 中 `/metrics` 端点注册,仅改指标名前缀:
|
||
|
||
- student-bff: `student_bff_requests_total`、`student_bff_request_duration_seconds`
|
||
- parent-bff: `parent_bff_requests_total`、`parent_bff_request_duration_seconds`
|
||
|
||
### 3.5 tracer — ✅ 对齐
|
||
|
||
复制 teacher-bff `shared/observability/tracer.ts`,仅改 `serviceName`:
|
||
|
||
- student-bff: `serviceName: 'student-bff'`
|
||
- parent-bff: `serviceName: 'parent-bff'`
|
||
|
||
### 3.6 /healthz — ✅ 对齐
|
||
|
||
复制 teacher-bff `shared/health/health.controller.ts`,仅改 `SERVICE_NAME`:
|
||
|
||
- student-bff: `service: 'student-bff'`
|
||
- parent-bff: `service: 'parent-bff'`
|
||
|
||
### 3.7 /readyz — ✅ 对齐
|
||
|
||
BFF 不查 DB,`/readyz` 直接返回 ok(对齐 teacher-bff)。
|
||
|
||
**可选增强**(P3 后期):检查下游服务可达性(HEAD 请求 iam/core-edu 的 `/healthz`),但 P3 阶段建议先简单返回 ok,下游可达性由 Prometheus 监控。
|
||
|
||
### 3.8 优雅关闭 — ✅ 对齐
|
||
|
||
复制 teacher-bff `main.ts` 中 SIGTERM 处理:
|
||
|
||
```ts
|
||
process.on("SIGTERM", async () => {
|
||
await app.close();
|
||
await shutdownTracer();
|
||
});
|
||
```
|
||
|
||
BFF 无 DB 连接需关闭(无 LifecycleService),仅需关闭 HTTP server + tracer。
|
||
|
||
### 3.9 测试覆盖率 — 🆕 目标 ≥ 80%
|
||
|
||
**测试重点**:
|
||
|
||
- Service 层聚合逻辑(mock 下游 fetch,验证 Promise.allSettled 容错)
|
||
- Controller 层入参校验(Zod schema)
|
||
- 错误处理(BadGatewayError、UnauthorizedError、ValidationError)
|
||
- parent-bff 特有:DataScope=CHILDREN 越权校验
|
||
|
||
**测试框架**:Jest(对齐 classes,待确认 classes 是否已配置 Jest)。
|
||
|
||
### 3.10 Dockerfile — ✅ 对齐
|
||
|
||
复制 teacher-bff `Dockerfile`(多阶段构建:builder + runtime),仅改 `EXPOSE`:
|
||
|
||
- student-bff: `EXPOSE 3009`
|
||
- parent-bff: `EXPOSE 3010`
|
||
|
||
---
|
||
|
||
## 4. 与 teacher-bff 模板对比(克隆基线)
|
||
|
||
teacher-bff 是已实现的最小 BFF 模板,student-bff/parent-bff 应 1:1 克隆后改造。
|
||
|
||
### 4.1 完全复制的部分(无需改动)
|
||
|
||
| 文件/目录 | 说明 |
|
||
| -------------------------------------- | ----------------------------------- |
|
||
| `shared/errors/global-error.filter.ts` | 全局错误过滤器(仅错误码前缀不同) |
|
||
| `shared/health/health.module.ts` | 健康检查模块 |
|
||
| `shared/observability/logger.ts` | pino logger(仅 service 名不同) |
|
||
| `shared/observability/metrics.ts` | prom-client(仅指标名前缀不同) |
|
||
| `shared/observability/tracer.ts` | OTel tracer(仅 serviceName 不同) |
|
||
| `app.module.ts` | 根模块(仅 imports 的业务模块不同) |
|
||
| `main.ts` | 启动流程(仅端口和日志不同) |
|
||
| `tsconfig.json` | ESM 配置 |
|
||
| `nest-cli.json` | NestJS CLI 配置 |
|
||
|
||
### 4.2 需要改造的部分
|
||
|
||
| 文件 | 改造点 |
|
||
| --------------------------------------- | ---------------------------------------------------------- |
|
||
| `package.json` | name 字段、dependencies(按下游服务需求扩展) |
|
||
| `src/config/env.ts` | PORT default、下游服务 URL 配置项 |
|
||
| `src/<context>/` 目录名 | teacher → student / parent |
|
||
| `src/<context>/<context>.controller.ts` | @Controller 装饰器前缀、端点路由 |
|
||
| `src/<context>/<context>.service.ts` | 聚合逻辑(按场景域不同) |
|
||
| `src/<context>/<context>.module.ts` | 模块注册 |
|
||
| `shared/errors/application-error.ts` | 错误码前缀、新增错误类(parent-bff 加 ChildNotBoundError) |
|
||
| `shared/health/health.controller.ts` | SERVICE_NAME |
|
||
| `Dockerfile` | EXPOSE 端口 |
|
||
|
||
### 4.3 teacher-bff 模板的可改进点(ai04 实施时可优化)
|
||
|
||
| 改进点 | teacher-bff 现状 | ai04 建议改进 |
|
||
| ------------ | ----------------------------- | ------------------------------------------------------------ |
|
||
| 聚合响应类型 | 大量用 `unknown` | 用 Zod schema 推导强类型响应 |
|
||
| 下游调用封装 | 原生 `fetch()` 散落在 Service | 抽取 `DownstreamClient` 工具类(带超时、重试、traceId 透传) |
|
||
| 错误信封 | 下游错误直接吞掉返回 null | 下游错误结构化记录(service/endpoint/status),透传 traceId |
|
||
| 缓存 | 无缓存 | 引入 NestJS CacheInterceptor + Redis(5-30s 短缓存) |
|
||
|
||
> ⚠️ 这些改进点需 coord 仲裁是否回写到 teacher-bff(避免技术栈分裂),还是仅用于 student-bff/parent-bff。
|
||
|
||
---
|
||
|
||
## 5. 审计结论
|
||
|
||
| 服务 | 总体对齐度 | 阻塞项 | 备注 |
|
||
| ----------- | ------------ | -------------------------------------- | ---------------------------------------------------------------- |
|
||
| student-bff | 🟢 高(90%) | 无 P0 阻塞 | P3 阶段可直接克隆 teacher-bff 实施,data-ana/ai 端点延后到 P4/P5 |
|
||
| parent-bff | 🟡 中(70%) | **P0 阻塞:iam 家长-学生关联接口缺失** | 需 coord 协调 ai02 在 P3 阶段补全 iam 接口,否则 P4 无法启动实施 |
|
||
|
||
**ai04 阶段 1 审计完成。两份理解确认书 + 本审计表已交付,请 coord 审核。**
|