Skip to content
bitzorcas
中EN

Reference

Guidance 流式、测试、运维与商业 GA 门禁

汇总 Guidance NDJSON 协议、错误与取消、当前测试证据、内容/助手故障注入、容量、指标、恢复和商业 GA 阻断项。

Last updated

Guidance 已有可运行的内容 Store、助手 Adapter 和双 ORM 基础,但商业 GA 必须证明 Draft 不泄漏、发布不中断线上指南、旧 Prompt 可撤销、跨模块会话创建可恢复、NDJSON 在错误/取消/超时下有稳定合同。

1. NDJSON 正常流

手写端点从 Mediator 获得 IAsyncEnumerable<string> 并包装进 NdjsonTextStreamResult,把每个 chunk 序列化为类型化 {"kind":"data","text":"..."} 帧,每行 Flush,最后写 {"kind":"done"}。失败时恰好产生一个终态 {"kind":"error",...} 帧。响应设置:

  • application/x-ndjson; charset=utf-8;
  • Cache-Control: no-cache;
  • X-Accel-Buffering: no;
  • userPolicy;
  • DisableRequestTimeout。
发送一条流式 Guidance 消息
POST /api/v1/guidance/sessions/guidance-100-hash/messages/stream
Content-Type: application/json
Accept: application/x-ndjson
Authorization: Bearer <token>
{
"content": "如何筛选未开票记录?",
"modelId": "managed-model-id"
}

2. 当前错误帧不统一

空消息、助手关闭或 Session 不存在时,Application/Adapter 返回字符串 [ERROR: description];Host 把它当普通 text frame。Host 捕获未处理异常时改写 {"error":"Guidance stream response failed."}。正常结束才有 done。

客户端必须猜测 text 是否以 [ERROR: 开头;错误没有稳定 code/retryable/correlation,也可能没有 done。GA 应使用版本化 union frame。

目标 NDJSON 帧
{"type":"meta","version":1,"correlationId":"corr-1"}
{"type":"delta","sequence":1,"text":"先打开筛选条件。"}
{"type":"error","code":"Guidance.Assistant.SessionNotFound","retryable":false}
{"type":"done","finishReason":"error"}

这是目标协议,不是当前输出。

3. 取消与超时

Host 使用 RequestAborted 发送 Query,并对枚举调用 WithCancellation;OperationCanceledException 被视为客户端断开。底层 Adapter 又把 token 传给 AIManage Stream Handler。

但端点禁用标准请求超时,没有替代最大持续时间、最大 idle、token/bytes/chunk 或 tenant concurrency。恶意/失控 Provider 可长期占用连接和计费资源。

4. 当前自动化证据

测试面已覆盖
Content Store四级选择、角色/语言、列表/删除、损坏状态
Assistant ApplicationPrompt 内容、稳定 SessionId、空消息
Assistant Adapterdisabled/workspace fail-closed、Session 聚合恢复
ArchitectureLayer 1 无 AI、统一聚合、9 生成路由、流 Host 纯度
IntegrationContent 与 Session SqlSugar/EF Core parity、迁移

未覆盖真实 HTTP 权限、平台 Draft 泄漏、发布并发、会话成功路径/竞态/补偿、旧 Prompt 撤销、AIManage owner 策略、真实 NDJSON 错误、Provider 故障、容量和恢复。

5. 最小回归组合

Terminal window
# 复用一个过滤表达式,确保三类证据覆盖同一模块边界。
GUIDANCE_FILTER="FullyQualifiedName~Guidance"
# Guidance 应用、Store 与 Adapter 测试。
dotnet test tests/BitzOrcas.Application.Tests/BitzOrcas.Application.Tests.csproj \
--filter "$GUIDANCE_FILTER"
# 模块边界、路由和持久化形态。
dotnet test tests/BitzOrcas.Architecture.Tests/BitzOrcas.Architecture.Tests.csproj \
--filter "$GUIDANCE_FILTER"
# 双 ORM 内容与 Session parity。
dotnet test tests/BitzOrcas.Integration.Tests/BitzOrcas.Integration.Tests.csproj \
--filter "$GUIDANCE_FILTER"

发布证据还必须通过真实 API Host 和实际支持数据库,不能只用内存 EntitySet/NSubstitute。

6. 内容 HTTP 矩阵

测试匿名、普通 Published 读者、Draft 管理员、平台管理员、跨租户 ID、角色不匹配、平台 Draft、未知语言、重复发布、并发 Revise/Publish 和删除竞态。每个拒绝都查询数据库证明没有副作用。

目标:修订不影响当前已发布正文
var published = await api.GetContextualAsync(route, cancellationToken);
await admin.ReviseDraftAsync(published.ContentId, newBody, published.ETag, cancellationToken);
// Draft 修改期间,终端用户继续得到旧 PublishedRevision。
var stillLive = await api.GetContextualAsync(route, cancellationToken);
stillLive.RevisionId.ShouldBe(published.RevisionId);
stillLive.BodyMarkdown.ShouldBe(published.BodyMarkdown);

当前 DTO 没有 ETag/RevisionId;这是 GA 目标测试。

7. Session 故障注入

在 FindSession、CreateConversation、Session Add、唯一提交、首问 Send、响应前依次注入失败。断言没有孤儿或孤儿可恢复;同 IdempotencyKey 重放返回同一 Session;并发 Start 不创建多个 Conversation。

目标:并发 Start 收敛为一个会话
var request = NewStartRequest(idempotencyKey: "guide-session-2026-42");
// 两个请求同时跨越 AIManage 与 Guidance 持久化边界。
var results = await Task.WhenAll(
client.StartAsync(request, cancellationToken),
client.StartAsync(request, cancellationToken));
results[0].SessionId.ShouldBe(results[1].SessionId);
await evidence.AssertSingleConversationAndSessionAsync(request, cancellationToken);

8. Prompt 与授权回归

先启动包含受限指南的 Session,再撤销角色、删除/修订指南、关闭 Feature 或切换 Workspace,确认后续 Send/Stream 拒绝或刷新 Prompt。不能只检查新的 Start,因为风险来自复用旧 Session。

测试 Prompt 不含原始 TenantId/UserId、不记录正文;Secret/PII detector 命中时按政策拒绝或脱敏。

9. NDJSON 合同测试

使用真实 HTTP 流分别覆盖 meta/delta/done、校验 error、Session NotFound、Provider error、Host exception、取消、代理缓冲、慢消费者、断线和字符边界。解析器按行增量读取,不能假设一个网络 chunk 等于一条 JSON。

每个流只允许一个 done;error 后必须 done(error) 或连接合同明确终止。取消不写虚假成功。

10. Markdown 安全测试

覆盖 raw HTML、script、javascript/data URL、事件属性、SVG、远程像素、超大图片、Unicode 混淆、嵌套列表和代码块。管理预览与终端显示必须用同一 sanitizer policy,并用浏览器测试证明无 XSS。

同一正文进入 Prompt 时另测 prompt injection、Secret 和 PII;浏览器 sanitizer 无法保护模型路径。

11. 容量基线

至少测每租户 100/1万/100万指南、候选重复 1/10/100、正文 1KB/100KB/1MB、用户 1/100/1000 并发流、Prompt 16K 字符、长响应与慢消费者。记录 P50/P95/P99、数据库扫描、首字节、tokens、bytes、连接时长、内存和成本。

FindBestMatch 当前把候选全部 List 到内存再排序;候选自然键不唯一时数据增长会放大。应评估数据库 rank 查询或预计算 Published projection。

12. 指标与告警

  • content create/revise/publish/delete/conflict;
  • contextual hit/miss by rank、language、audience;
  • platform-draft access denial;
  • session start/reuse/refresh/expire/orphan;
  • conversation/session compensation;
  • prompt chars/policy denial,不记录正文;
  • stream first-byte/duration/chunks/bytes/cancel/error;
  • tokens/cost/quota/provider failure;
  • outbox/event lag 与清理积压。

告警重点是 Draft 泄漏、发布后无线上版本、孤儿 Conversation、旧 Prompt 继续使用、流无终态、超时/成本激增。

13. 备份与恢复

备份 GuidanceContent 当前/历史/发布指针、Session 映射、相关 AIManage Conversation 引用和 Outbox。恢复后验证平台 null Tenant 语义、Audience、Published 指针、软删除、Session owner、Prompt revision 和孤儿映射。

若 AIManage 与 Guidance 恢复到不同时间点,需要 reconciliation job:关闭指向不存在 Conversation 的 Session,并按策略归档无 Session 的 Guidance Conversation。

14. GA 阻断项

  1. 平台 Draft 可能经 Detail/List 暴露;
  2. Published 同行修订导致线上内容消失且无历史;
  3. 自然键、发布唯一与并发控制不足;
  4. Markdown 渲染安全合同缺失;
  5. 助手没有独立 Permission/Feature/Quota,UserId 可为 0;
  6. Prompt 外发原始身份/角色且无敏感策略;
  7. 复用 Session 不刷新指南/角色/权限;
  8. Conversation/Session 创建无幂等、原子或补偿证据;
  9. 直接 AIManage Handler 可能绕过 owner Pipeline 政策;
  10. NDJSON 错误帧不稳定;
  11. DisableRequestTimeout 没有资源上限替代;
  12. HTTP、并发、故障、隐私、容量与恢复证据不足。

15. 扫尾命令

Terminal window
# P0 后应归零或只保留登记兼容入口。
rg -n "UserId\?\.ToString.*\?\? \"0\"|DisableRequestTimeout|\[ERROR:" \
src/Platform/Guidance src/Hosts/BitzOrcas.Api/Endpoints/GuidanceEndpointGroup.cs -g '*.cs'
# 目标发布与会话治理能力。
rg -n "PublishedRevision|IdempotencyKey|PromptHash|ExpiresAt|AssistantUse" \
src/Platform/Guidance -g '*.cs'

Guidance 总览 · 内容生命周期 · 助手安全

100%

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