Skip to content
bitzorcas
中EN

Reference

AIManage 测试、运维与商业 GA 门禁

汇总 AIManage 当前测试证据、威胁模型、Provider 与流式故障演练、幂等与所有权覆盖、指标、SLO、密钥恢复、容量和商业发布阻断项。

Last updated

AIManage 已具备可运行的持久化和 Provider 调用骨架,但 AI 请求同时跨越身份、Secret、外部网络、不可确定输出和计费边界。商业 GA 的证据强度必须高于普通 CRUD 模块。

1. 当前自动化证据

测试面已覆盖
Persistence工作区、Provider、模型、对话、消息、技能的核心 Store 行为
TenantProvider 查询与默认项的租户范围
Client factoryProvider/Model/Key 变化产生不同缓存项,Builder 被调用
RAG / AgentAdapter 参数转发和返回映射
ArchitectureInfrastructure ORM 中立、失败关闭注册、非对称子表、应用层 Id/Clock 规则
IntegrationAIManage Store 在 SqlSugar / EF Core 的 parity 场景
Host smoke未配置 Provider 时解析为 Unavailable adapter
所有权跨租户/非所有者 ConversationId 返回 ConversationNotOwner
幂等IAIMessageRequestCoordinator 的 claim/replay/conflict/failed 状态
流式NDJSON kind 帧、预取 403 映射、终态错误帧、取消行为

没有覆盖:真实 Provider、首字节、取消与 Provider 取消的竞态、密钥损坏/轮换、文件技能权限、内容安全、容量、SLO 和恢复。

2. 最小回归组合

Terminal window
dotnet test tests/BitzOrcas.Application.Tests/BitzOrcas.Application.Tests.csproj \
--filter "FullyQualifiedName~AIManage|FullyQualifiedName~SemanticKernelChatClientFactory|FullyQualifiedName~RagServiceAdapter|FullyQualifiedName~AgentServiceAdapter"
dotnet test tests/BitzOrcas.Architecture.Tests/BitzOrcas.Architecture.Tests.csproj \
--filter "FullyQualifiedName~AIManage"
# 需要 Docker 与两种真实 ORM adapter。
dotnet test tests/BitzOrcas.Integration.Tests/BitzOrcas.Integration.Tests.csproj \
--filter "FullyQualifiedName~AIManageStores_Should_Behave_The_Same_On_SqlSugar_And_EfCore"

候选版本还必须在隔离的 Provider stub 上跑 HTTP contract test,固定认证、Problem Details、NDJSON schema、超时、取消、usage、错误脱敏和幂等行为。

3. 威胁与授权矩阵

场景当前行为GA 预期
租户 A 猜到租户 B ConversationIdConversationNotOwner(Forbidden)已强制;持续测试
同租户用户读取他人对话Send/Stream/History 绑定租户+用户已强制;持续测试
重复 RequestId in-flightAI.Message.RequestInProgress(Conflict)已强制;持续测试
任意认证用户 reload 文件技能当前允许skill.manage/ops 权限
Provider Endpoint 指向内网无显式 allowlistSSRF 策略与出站代理
Data Protection key 丢失密文原样当 Key失败关闭并告警
Prompt 含 Secret/PII原样外发分类、阻断/脱敏、审计
模型返回工具调用当前不执行将来逐次授权与确认
任意 ModelId当前透传受管模型 allowlist

4. 幂等与一致性

同一轮次只调用 Provider 一次
// 两个并发请求携带完全相同的稳定 RequestId。
var command = new SendMessage.Command(conversationId, "turn-42", content, modelId);
var results = await Task.WhenAll(
sender.Send(command, cancellationToken).AsTask(),
sender.Send(command, cancellationToken).AsTask());
results.ShouldAllBe(result => result.IsSuccess);
// 同时固定外部计费边界和最终持久化结果。
await provider.Received(1).CompleteAsync(Arg.Any<ChatRequest>(), Arg.Any<CancellationToken>());
await store.ShouldContainOneUserAndOneAssistantAsync("turn-42", cancellationToken);

RequestId 必填,IAIMessageRequestCoordinator 的 claim 状态机已强制执行。还要覆盖 Provider 成功/保存 Assistant 失败、用户消息保存后进程崩溃、流式部分保存、重复完成回调(重放不调 Provider)、消息计数并发、双默认 Provider、缓存构建竞争和账本结算重放。

5. Provider 故障注入

至少模拟:DNS 失败、TLS/证书失败、401/403、404 模型不存在、429+Retry-After、连接超时、首字节超时、分块中断、无效 UTF-8/超大帧、usage 缺失、空响应、内容过滤结束、慢流、连接池耗尽和 Provider 恢复。

错误映射不得返回 Endpoint、ApiKey、供应商原始 body 或堆栈。是否重试由错误类别、幂等 attempt 和预算共同决定;429 不能无限重试,401 不应重试,流式已产生内容后不能偷偷切 Provider 拼接答案。

6. 流式验收

真实测试必须测时间而非只枚举结果:Provider stub 在 t=0/200/400ms 发三块,客户端应在约定阈值内分别收到,而不是 400ms 后一次收到。断开测试要断言数据库状态、Provider cancellation、无后台泄漏和客户端可恢复合同。

代理层同时验证 Kestrel、IIS/Nginx/Ingress 的 buffering、compression、idle timeout 和最大连接时长。X-Accel-Buffering: no 只对部分代理有效,不能代替部署验证。

7. 容量与成本基线

矩阵至少包括 1/10/50/500 条历史、1KB/32KB 输入、1KB/100KB/1MB 输出、1/10/100 并发流、1/8/32/64 个 Provider+Model 缓存键,以及长慢流。记录 P50/P95/P99、first byte、full duration、分配、GC、活动连接、Provider QPS、Token、费用和数据库 round trips。

预算门禁应覆盖租户日/月上限、用户/工作区速率、单轮最大输入输出、并发上限、异常消费突增和账单对账差异。

8. 指标与日志

建议最少指标:

  • ai_request_total/failed/denied,按 workspace/provider/model/error code;
  • ai_first_byte_duration、ai_completion_duration、ai_stream_gap;
  • ai_input_tokens/output_tokens/cost 与 budget denied;
  • ai_provider_status、429、timeout、circuit state;
  • ai_client_cache_hit/build/evict/size;
  • ai_partial_response、cancel、orphan turn、reconcile lag;
  • ai_skill_reload、parse failure、unauthorized;
  • ai_rag_search_duration/results/denied 与 index lag。

日志可包含 TenantId、WorkspaceId、ConversationId、TurnId、ProviderId、ModelId、ErrorCode、CorrelationId;不得包含 ApiKey、Prompt、SystemPrompt、模型正文、检索片段或未经分类的文件名。需要内容级取证时走受控审计存储,不走普通日志。

9. 密钥与恢复演练

备份必须涵盖四个聚合/子表数据、消息、用量账本(落地后)和 Data Protection key ring。恢复演练验证存量 Provider 可解密、旧/新 key 均可用、错误 key ring 会红灯而不是把密文外发、对话计数与消息一致、失败 attempt 可调和、索引/外部向量库可重建。

10. 建议 SLO

把平台处理与 Provider 质量分开。例如:99.9% 受理决策在 100ms 内完成;在 Provider SLA 范围内,99% 流式请求在 2s 内收到首帧;99.9% 已完成 turn 的消息与用量账本在 1 分钟内一致。SLO 必须按模型、区域和响应大小分层,不能用一个平均值掩盖慢模型。

11. GA 阻断项

已交付:对话所有权(绑定租户 + 用户)、幂等 turn(RequestId + IAIMessageRequestCoordinator)、带类型化 kind 帧的增量流式、稳定不泄漏的流式错误合同。剩余阻断项:

  1. 对话可引用不存在/停用工作区;
  2. 任意 ModelId 与固定参数绕过模型目录;
  3. 凭据解密失败仍回退原字符串,key ring 未形成部署契约;
  4. Provider 默认项、模型归属和缓存并发未收敛;
  5. 文件技能端点只有认证,技能/RAG/Agent 被过度宣传;
  6. 数据分类、脱敏、内容安全、Prompt Injection 与保留策略缺失;
  7. Token、成本、预算、配额和对账缺失;
  8. Provider 健康、超时、熔断、可审计 fallback 和告警缺失;
  9. HTTP、安全、Provider contract、流式时序、容量和恢复证据缺失。

12. 分阶段落地

P0:工作区校验、模型 allowlist、密钥失败关闭。P1:用量账本、预算、内容安全、Provider resilience、文件技能权限、观测与恢复。P2:在逐次授权和审计完成后接入 RAG 与工具;多 Agent、复杂编排和 Provider marketplace 属于后续产品能力。

Terminal window
# 高风险现状应持续可见。
rg -n "GetConversationAsync\(|CancellationToken.None|return cipherKey|DisableRequestTimeout" \
src/Platform/AIManage src/Hosts/BitzOrcas.Api -g '*.cs'
# 省略、待办和临时实现不应进入候选版本。
rg -n "TODO|FIXME|// \.\.\.|省略" src/Platform/AIManage tests -g '*.cs'

AIManage 总览 · 技能、RAG 与 Agent · 流式与用量

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%