滑动续期、网络错误归类、API Key 激活乐观锁与生效提示

This commit is contained in:
2026-08-11 11:45:03 +08:00
parent 23b2820101
commit e63af49831
21 changed files with 679 additions and 15 deletions
+10
View File
@@ -42,6 +42,16 @@ func sanitizeURLError(err error) error {
**约定**:识别特定语义一律走 `internal/oci/errors.go` 的判定函数(`IsModelUnavailable` / `IsEntityNotFound` / `IsOnDemandUnsupported`),用 `errors.As` 取 `common.ServiceError` 后按 状态码+消息片段 匹配;调用方(探测/网关路由)据此决定「定论、换候选、换渠道、是否计熔断」,不得在业务层散落字符串匹配。
连接层失败(拿不到 OCI 响应)与服务错误分开归类:`UpstreamNetworkError`
识别代理拨号 / SOCKS 握手 / 超时等网络类错误,api 层 `respondError` 据此回
502(`code: UpstreamNetwork` + 中文 hint),不落 500「服务器内部错误」;
url.Error 的 URL 一律压缩为主机名(防 userinfo / 长查询串外流,呼应上文
敏感信息约定)。脱敏必须覆盖嵌套 `url.Error` 及普通拨号错误文本中的
`userinfo@host`;`[NET]` 日志记录与 502 响应相同的脱敏详情,不得再打印原始
错误链。代理配置的独立 Host 字段拒绝 `@`,用户名/密码只走专用字段。
新增网络类特征时扩这个判定函数,不要在 handler 里散判。测试同时断言响应体
与捕获日志均不含用户名、密码,并保留一条存量非法 Host 的普通错误文本用例。
## 外部响应体必须限长,超限报错而非静默截断
读上游/外部响应体一律 `io.LimitReader(max+1)` 再判长度:恰好读到 max+1 说明超限,返回带上限值的错误;不得截断后当成功继续(截断的 JSON/流式响应会以 200 返回坏数据,2026-07-22 审查 #13,genai_responses.go `readCompatBody`)。