docs(review): record residual review findings
Test / backend-test (pull_request) Waiting to run Details
Test / frontend-unit (pull_request) Waiting to run Details
Test / api-e2e (pull_request) Waiting to run Details
Test / frontend-e2e (pull_request) Waiting to run Details

This commit is contained in:
Chiguyong 2026-07-06 10:40:06 +08:00
parent 3cf29f4633
commit 444667e2f0
1 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,182 @@
# Residual Review Findings — feat/enterprise-agent-platform-p0
**Source**: ce-code-review run on commit range `8633f60..3cf29f4`
**Branch**: `feat/enterprise-agent-platform-p0`
**HEAD**: `3cf29f4`
**Tracker availability**: no named tracker documented; `gh` CLI not installed;
`any_sink_available = false` — all findings routed to `no_sink` bucket per
lfg `references/tracker-defer.md` non-interactive mode.
These findings were surfaced by the multi-agent code review (5 reviewer
subagents: security + adversarial, performance + reliability,
maintainability + standards, api-contract + data-migration, deployment
verification). They are **actionable** (`autofix_class: manual`) but were
**not applied** in Step 5 because they need design input or app+chart
coordinated changes. They are durably recorded here per lfg SKILL.md Step 6.
## P1 — High-impact defects
- **P1 / `src/agentkit/llm/pii_filter.py` + `src/agentkit/llm/gateway.py`**
PERF-1: PII 脱敏模块未接入生产 LLM 调用路径(死代码)。`filter_messages_pii`
仅被单元测试引用gateway.py 的 chat()/chat_stream() 直接透传原始 messages。
等保合规声称的 PII 保护实际未生效。**Fix**: 在 gateway chat() 接入
`filter_messages_pii(messages, fail_closed=True)`,从 `agentkit.yaml`
PII 配置开关和 ner_hook 路径。
- **P1 / `src/agentkit/server/auth/scim/router.py:233-238`**
API-1: SCIM GET /Users 的 `totalResults` 返回当前页条数而非全量总数
(违反 RFC 7644 3.4.2)。当用户总数 > count 时SCIM 客户端无法得知真实
总数,分页逻辑错误。**Fix**: 在列表查询前先执行 `SELECT COUNT(*) FROM
users {where}` 复用同一 where 子句和参数。
- **P1 / `src/agentkit/server/auth/scim/router.py:50-64,107-151,154-197,200-238`**
API-2: SCIM 错误响应使用 FastAPI 默认 `{"detail": "..."}` 而非 RFC 7644
3.12 规定的 `{"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "409", "detail": "..."}`。同文件中定义的 `SCIMErrorResponse`
死代码。**Fix**: 添加 SCIM 异常处理器转换所有 HTTPException 为 SCIM
ErrorResponse 格式。
- **P1 / `src/agentkit/server/routes/auth.py:804-815,823-827`**
API-4: `_sso_issue_token_pair` 用占位符 `refresh_token="__pending_sso__"`
创建 session并发 SSO 登录会触发 `refresh_token_hash` UNIQUE 约束冲突
抛 IntegrityError → 500。即使不考虑并发两步写入也不原子第二步失败
会留下孤儿 session。**Fix**: 先 `secrets.token_urlsafe(32)` 生成真实
refresh token 再 `SessionCreate` 一步创建。
- **P1 / `src/agentkit/server/auth/scim/router.py:107-151`**
API-5: SCIM `create_user` 不写入 `user_idp_links`,导致 SCIM 预配的用户
无法 SSO 登录OIDC 会 JIT 创建重复账户。SCIM 的核心价值就是预配 + SSO
联动,此处断裂使 SCIM 预配失效。**Fix**: SCIM create_user 接受
`externalId` 作为 idp_subjectINSERT users 后 INSERT user_idp_links。
- **P1 / `deploy/offline/scripts/install.sh:58` + docs**
DEPLOY-1: 部署名引用错误。fullname helper 在 release=agentkit 时渲染
Deployment 名为 `agentkit`,但 install.sh:58 + 11 处文档引用
`agentkit-agentkit`(不存在)。**Fix**: 改用标签选择器
`kubectl rollout restart deployment -l app.kubernetes.io/instance=${RELEASE}`
- **P1 / `deploy/helm/agentkit/templates/deployment.yaml:88-92`**
DEPLOY-2: Redis 鉴权断裂。`REDIS_PASSWORD` env 注入但应用从不消费
`src/agentkit/**/*.py` 零命中Redis 客户端通过 `redis_url` 构造
`redis://redis:6379/0`,无密码)。若 Redis 启用密码pod 全部 Redis
操作 NOAUTH 失败。**Fix**: 在 redis 客户端构造处读取 `REDIS_PASSWORD`
并以 `password=` 参数传入 `from_url`,或将密码拼入 redis_url。
## P2 — Moderate issues with meaningful downside
- **P2 / `src/agentkit/server/auth/scim/router.py:107-151`**
API-6: SCIM POST /Users 缺少 `Location` 响应头RFC 7644 3.14 强制要求)。
**Fix**: 用 `JSONResponse` + `response.headers["Location"] = ...`
- **P2 / `src/agentkit/server/auth/scim/router.py:183-187`**
API-7: SCIM PATCH userName 更新未处理 UNIQUE 约束冲突,返回 500 而非
409。**Fix**: 包在 try/except `aiosqlite.IntegrityError` 中返回 409。
- **P2 / `src/agentkit/server/routes/auth.py:812`**
API-8: `_sso_issue_token_pair` 硬编码 `auth_provider="sso"`,丢失 OIDC/SAML
区分。admin UI 无法按 IDP 筛选 session。**Fix**: 增加 `provider_name` +
`provider_type` 参数。
- **P2 / `src/agentkit/server/auth/scim/router.py:216-225`**
API-9: SCIM filter 语法不匹配时静默返回全量用户,可能导致数据泄露。
**Fix**: 不支持的 filter 返回 400 + `scimType=invalidFilter`
- **P2 / `src/agentkit/server/routes/auth.py:1040-1085,1097-1143`**
API-10: `deprovision_user` / `change_user_role` 返回 untyped `dict[str, Any]`
OpenAPI schema 无法文档化。**Fix**: 定义 `DeprovisionResponse` /
`RoleChangeResponse` Pydantic 模型。
- **P2 / `src/agentkit/server/auth/scim/router.py:94-104`**
API-11: SCIM `_user_to_scim``username` 作为 `displayName`,语义错误。
**Fix**: 改为 `None` 让客户端 fallback。
- **P2 / `src/agentkit/server/auth/models.py:612-620`**
MIG-1: `user_idp_links` 表无 ON DELETE 行为且无 FK 约束到 users。当前无
删除路径,但未来引入 GDPR 物理删除时会产生孤儿链接。**Fix**: 引入物理
删除时加 `REFERENCES users(id) ON DELETE CASCADE`
- **P2 / `deploy/helm/agentkit/templates/deployment.yaml:58-62,93-97`**
DEPLOY-4: PG 密码双源不一致。`DATABASE_URL`(被消费) 与 `POSTGRES_PASSWORD`
(死 env并存。runbook Slot 10 轮换 `postgres-password` 但应用实际用
`DATABASE_URL`。**Fix**: 明确单一可信源 — 若只用 `DATABASE_URL`,移除
`POSTGRES_PASSWORD` env 与 `postgresPassword` slot。
- **P2 / `deploy/helm/agentkit/templates/deployment.yaml:83-87`**
DEPLOY-5: OTel exporter token 值格式与 `OTEL_EXPORTER_OTLP_HEADERS` 语义
不符。期望 `key=value` 格式,但存储值为 `Bearer <token>`。**Fix**: 改为
`Authorization=Bearer <token>` 格式。
- **P2 / `src/agentkit/server/auth/scim/router.py` (7 处) + `scim/models.py`**
STAND-1: SCIM router 使用 `typing.Any` 7 处,违反 AGENTS.md 禁用 any 规则。
**Fix**: 定义 `SCIMUserResponse` / `SCIMUserListResponse` Pydantic 模型。
## P3 — Low-impact / narrow scope
- **P3 / `src/agentkit/server/auth/providers/oidc.py:185-197`**
SEC-2: OIDC id_token 未按规范验签key=None + 关闭 iss/exp。当前
authlib 1.6.12 fail-closed非直接绕过但规范违反且脆弱。**Fix**: 用
IDP JWKS 公钥验签,校验 iss/aud/exp。
- **P3 / `src/agentkit/server/auth/scim/router.py:170-185`**
SEC-3: SCIM PATCH deprovisioning`active=false`不写审计。admin 同等
操作有审计SCIM 没有。**Fix**: 检测到 active true→false 时调用
`record_deprovision(source=SOURCE_SCIM)`
- **P3 / `src/agentkit/llm/gateway.py:401-414`**
PERF-6: 流式路径在无 usage 数据时记录"cache miss",指标误导。**Fix**:
仅当 `final_usage` 非 None 时才记录 cache metric。
- **P3 / `src/agentkit/llm/gateway.py:450-457`**
PERF-7: 非 Anthropic provider 调用膨胀 `prompt_cache.miss` 计数器。
**Fix**: 仅对 Anthropic provider 记录 cache metric。
- **P3 / `src/agentkit/server/auth/scim/router.py:171-187`**
API-12: SCIM PATCH 静默忽略不支持的 op/path无错误反馈。**Fix**:
收集 skipped ops 并返回 400 + `scimType=noTarget`
- **P3 / `src/agentkit/server/auth/scim/router.py:200-238`**
API-13: SCIM filter 解析对属性名和操作符大小写敏感,违反 RFC 7644
3.4.2.2。**Fix**: 用 `filter.lower()` + 正则 `re.IGNORECASE`
- **P3 / `src/agentkit/server/auth/scim/router.py:154-197`**
API-14: SCIM PATCH `op.path==None` 时仅更新 active丢弃 value 中的其他
字段(部分实现静默丢数据)。**Fix**: 遍历 value 的 keys 对每个已知属性
执行对应 UPDATE。
- **P3 / `src/agentkit/server/auth/models.py:609-639`**
MIG-2: schema 迁移幂等但缺少 V4→V5 的显式迁移记录。**Fix**: 未来新增列
时按 schema_version 差值执行 ALTER TABLE。
- **P3 / `deploy/helm/agentkit/values.yaml:8-11`**
DEPLOY-9: 镜像仅 tag 固定0.1.0),未做 digest pinning。政企生产场景
要求 digest pinning 防篡改。**Fix**: 支持可选 `image.digest` 字段。
- **P3 / `docs/deployment/key-rotation-runbook.md:254-283`**
DEPLOY-8: runbook 仅 Slot 1-10缺独立 Slot 11PG 密码)段落。**Fix**:
拆为两节Slot 11 内注明须同步更新 `database-url`Slot 3
- **P3 / `src/agentkit/bitable/service.py:564-568`**
MAINT-2: `delete_view` 将两种不同失败原因统一抛 `LastViewDeletionError`
误导性错误信息。**Fix**: 区分 `DELETED`/`LAST_VIEW`/`NOT_FOUND` 三态。
- **P3 / `src/agentkit/server/frontend/src/stores/chatStream.ts:881-887,923-929`**
MAINT-3: `team_synthesis_chunk``team_synthesis` 重复同一 `findLastMessage`
谓词。**Fix**: 提取 `findStreamingSynthesisMilestone(conv, sid)` helper。
- **P3 / `src/agentkit/server/frontend/tests/unit/bitable-tokens.test.ts:75,81,85`**
MAINT-4: token 声明正则转义重复 3 次。**Fix**: 提取 `tokenDeclPattern(token)`
helper。
- **P3 / `src/agentkit/server/frontend/tests/unit/bitable-tokens.test.ts:92`**
STAND-2: test "outside root" 用 replace 仅替换首个 `:root` 块。**Fix**:
`g` 标志 `replace(/:root\s*\{[^}]*\}/g, '')`
- **P3 / `src/agentkit/server/app.py:1401`**
STAND-3: SCIM router 挂载在 `/api/v1` 前缀下,偏离 RFC 7644 标准 SCIM
路径 `/scim/v2`。**Fix**: SCIM router 单独挂载不加 `/api/v1` 前缀。
---
**Total residual findings**: 27 (P1=7, P2=10, P3=10)
**Applied in Step 5**: 9 fixes (commit `3cf29f4`)
**Deferred to follow-up**: 27 (this file)