fix(gateway)+docs(api): F5 区分「字段缺失/值为空白」+ E4/E5 契约文档治理
- F5:PATCH /sessions/{id} 的 400 文案区分两类——都缺 → at least one of title or pinned is required;
存在但空白 → title must not be blank(此前空白也回 title is required,误导排查方向)。
「空串不能清空标题」的既有语义保持不变(用例显式钉住),新增 history_write_test.go 4 段断言
- E4:/auth/logout 的两种真实响应形状(单撤 {revoked} / 全撤 {revoked,revokedCount})+ 错误码;
/auth/refresh 补 role;登录响应与一次性接入段补 refreshToken(两份文档一致)
- E5:api-reference §3.2 补 pinned/unreadCount/lastMessage/personaId 与准确排序规则
(pinned DESC, (type='main') DESC, created_at ASC ⇒ 置顶的次级会话可排在主会话之前);
新增 §3.6a PATCH /sessions/{id}(请求体/错误码/部分更新/title 不可清空)与 §3.6b POST /sessions/{id}/read;
端点表补 read 行
- api-client 删掉「主会话恒在前」的错误断言(两处),PATCH 错误码文案同步
- DevDocs/02-development-constraints.md:上传上限 50MB → **硬 5 MiB**(常量、无配置项)
This commit is contained in:
1 parent
5fb0cf5e19
commit
20d452a51a
4 files changed
+198
-20
No files matched your search
@@ -42,8 +42,13 @@ const maxSessionTitleRunes = 80
|
||||
|
||||
// handlePatchSession 更新持久化会话的显示元数据 —— 其标题
|
||||
// (A4)与置顶标志(D5)。二者都是元数据:与 DELETE 不同,它们
|
||||
// 允许作用于固定的主会话。两个字段都不携带的请求返回 400,
|
||||
// 空/仅空白或过长的标题亦然,未知会话 id(照常 404/500)。
|
||||
// 允许作用于固定的主会话。未知会话 id 照常 404/500。
|
||||
//
|
||||
// 两种 400 刻意用不同文案区分「缺字段」与「字段在、值非法」:
|
||||
// title 与 pinned 都没给 → 「至少需要 title 或 pinned」;
|
||||
// 给了 title 但 trim 后为空白 → 「title 不得为空白」;过长 → 明确的上限提示。
|
||||
// title 的空串/仅空白**没有**清空语义(不回落自动命名),
|
||||
// 因而客户端不提供「恢复自动命名」入口;要换名只能给非空白标题。
|
||||
//
|
||||
// 携带 personaId 键的请求体对任何取值都返回 400,且该检查
|
||||
// 在会话被查找之前执行:会话角色在创建时固定(design/22
|
||||
@@ -74,14 +79,14 @@ func (s *Server) handlePatchSession(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if req.Title == nil && req.Pinned == nil {
|
||||
writeError(w, apperr.Wrap(apperr.ErrBadRequest, "bad_request", "title or pinned is required"))
|
||||
writeError(w, apperr.Wrap(apperr.ErrBadRequest, "bad_request", "at least one of title or pinned is required"))
|
||||
return
|
||||
}
|
||||
resp := map[string]any{"id": id}
|
||||
if req.Title != nil {
|
||||
title := strings.TrimSpace(*req.Title)
|
||||
if title == "" {
|
||||
writeError(w, apperr.Wrap(apperr.ErrBadRequest, "bad_request", "title is required"))
|
||||
writeError(w, apperr.Wrap(apperr.ErrBadRequest, "bad_request", "title must not be blank"))
|
||||
return
|
||||
}
|
||||
if utf8.RuneCountInString(title) > maxSessionTitleRunes {
|
||||
|
||||
Reference in new issue
Block a user