Commit Graph

3 Commits

Author SHA1 Message Date
Chiguyong 3cf29f4633 fix(enterprise): ce-code-review P1 fixes — SSO is_active + span leak + Helm chart integration
Stage 5c applied safe P1/P2/P3 fixes from multi-agent code review:

- SEC-1 (P1, security): SSO 登录绕过 is_active 检查 — _sso_issue_token_pair
  入口加显式校验,与本地 login(auth.py:377)一致。已停用用户无法再通过
  IDP 回调拿 JWT,封堵 R1b deprovisioning 绕过。

- PERF-2/3 (P2, reliability): gateway chat() span 泄漏 + 异常未记录 — try 块
  扩展到覆盖整个 span 生命周期(含 cache 设置),新增 except 分支调用
  record_exception + set_status(ERROR),失败调用在 trace 中不再显示为成功。

- API-3 (P1, test isolation): SCIM router 使用 import-time 捕获的
  DEFAULT_AUTH_DB_PATH — 改为 resolve_auth_db_path() 在调用时读取 env var,
  让测试 monkeypatch.setenv 可见。

- MAINT-1 (P3, dead code): 删除 BitableRepository.delete_view(被
  delete_view_if_not_last 取代,无生产调用方,仅 docs 残留引用)。

- PERF-4/5 (P3, performance): pii_filter._record_pii_metrics 的 from import
  提升至模块顶部 + except: pass 改为 logger.debug 记录失败原因。

- DEPLOY-3 (P1, chart integration): ConfigMap 不可达 — deployment.yaml
  args 增加 --config /etc/agentkit/agentkit.yaml,让应用能加载 chart 渲染
  的非密配置。

- DEPLOY-6/7 (P3, doc/chart consistency): values.yaml 注释残留旧 slot 名
  redisPgPasswords → redisPassword;slot 计数 10 → 11(5 处 chart + 3 处
  deployment docs 同步修正)。

Verification:
- ruff check + format clean (7 modified .py files)
- pytest tests/unit/{auth,bitable} + test_{pii_filter,oidc_provider,
  saml_provider,scim_router,auth_audit,telemetry,prompt_cache_layers}.py
  → 336 passed, 145 skipped
- helm lint + helm template 验证 secret key 一致性

Residual findings (deferred to follow-up):
- PERF-1: PII filter 未接入 gateway 生产路径(manual, 需配置接入决策)
- API-1/2/4/5: SCIM RFC 7644 合规性(totalResults/error format/Location
  header/SSO 预配联动)— manual, 需设计决策
- DEPLOY-1/2/4: Helm chart ↔ app 集成断裂(部署名引用/Redis 鉴权/PG 密码双源)
  — manual, 需 app+chart 联动修改
2026-07-06 08:36:59 +08:00
Chiguyong 86bce129a4 refactor(enterprise): simplify U1-U6 — fix span leak, dedup helpers, stdlib parsing
lfg Step 3 (ce-simplify-code) — 16 files, -89 net lines.

P1 fixes (functional):
- audit.py / scim/router.py: fix OTel span leak — start_span() returned a
  context manager but was used as a plain object, so spans never ended
  and never exported. Wrap in `with`.
- helm chart: split combined `redisPgPasswords` slot (single JSON key)
  into `redisPassword` + `postgresPassword` slots — the combined `key`
  field was dead config never referenced by any template; deployment.yaml
  hardcoded `redis-password`/`postgres-password` keys were inconsistent
  with values.yaml schema.

P2 dedup (reuse):
- Promote `resolve_auth_db_path()` to models.py (canonical); remove 3
  duplicate `_resolve_db_path` defs in oidc.py / saml.py / audit.py.
- Reuse `_now_iso` from models.py; remove 5 duplicates across audit /
  oidc / saml / scim / local providers.
- Reuse `_row_to_user` from local.py in oidc.py / saml.py (verbatim
  copies removed).
- pii_filter._redact: collapse redundant `finditer` + `sub` (2 regex
  passes + 2x sha256 per match on hot path) into a single `sub` with a
  callback that collects matches and computes hashes once.

P3 simplifications:
- RoleChangeRequest.role: `str` + manual `if not in (...)` → `Literal`
  (Pydantic validates automatically).
- Extract `_record_pii_metrics(status, redacted_count)` helper to dedup
  3 nearly-identical OTel metric emission blocks.
- Extract `LLMGateway._record_prompt_cache_metric(usage, model)` to dedup
  non-stream + stream cache hit/miss counters; switch to use the
  `TokenUsage.cache_hit` property (previously added but unused).
- middleware: split `WHITELIST_PATHS` + `PREFIX_MATCH_PATHS` (redundant
  cross-reference) into `WHITELIST_PATHS` (exact) + `PREFIX_WHITELIST_PATHS`
  (prefix) — single source of truth per kind.
- OIDC token exchange: replace f-string form body with `urlencode` to
  correctly escape `&` / `=` in code / redirect_uri.
- auth.py OIDC redirect route: replace hand-rolled `url.split("state=")`
  with `urlparse + parse_qs`.
- PII module docstring: clarify that `PIIMatch.original` is in-memory
  only (must not be logged / persisted) — the previous "仅 hash, 不含
  原文" wording was misleading.

Skipped findings (false-positive or not worth):
- OIDC/SAML `_find_or_create_user` JIT 60-line dedup — high blast
  radius across SQL + transaction boundaries; defers to dedicated refactor.
- SAML `_extract_host` hand-rolled split — already has ponytail comment;
  stdlib `urlparse` swap is behavior-equivalent for current inputs but
  changes OneLogin `http_host` field semantics; conservative keep.
- gateway.py department-quota / usage-record sequential await —
  concurrency gain unclear when dept count is typically ≤2.

Verification:
- ruff check (scoped to 12 touched files) clean
- ruff format (1 file reformatted)
- pytest (PII + OIDC + SAML + SCIM + audit + bitable + team_orchestrator):
  265 passed, 145 skipped (PG/Docker), 0 failures
- helm lint clean; helm template renders correctly for both
  sealed-secrets + external-secrets backends
2026-07-06 08:02:40 +08:00
Chiguyong af9cb9496c feat(deploy): U5 — K8s Helm Chart + Sealed Secrets + 离线安装包
U5 产出政企生产级 K8s 部署 artifacts:

Helm Chart — deploy/helm/agentkit/ 含 Chart.yaml + values.yaml +
8 个 templates(deployment/service/ingress/configmap/sealed-secret/
external-secret/serviceaccount/_helpers)。

values.yaml 显式列出 10 个 secret slot(KTD-4):JWT 签名密钥 /
API Key / DB 凭据 / IDP 签名证书 / 第三方 API Key / TLS 服务器证书 /
mTLS 客户端证书 / KMS-HSM PIN / OTel exporter token / Redis-PG 密码。

Sealed Secrets + External Secrets Operator 双模板,禁用 plain
Kubernetes Secret + Git 提交。serviceaccount 配置 projected token
注入支持 KMS/HSM workload identity。

离线安装包 — build-images.sh 构建镜像 tarball +
package-chart.sh 打包 chart tarball + install.sh 离线安装,
覆盖原生 K8s 1.28+ / Helm 3.x。

运维文档 — k8s-install.md 部署指南 + key-rotation-runbook.md
密钥轮换 runbook(10 slot)+ secret-inventory.md 密钥清单。
2026-07-06 07:21:41 +08:00