chore: sync worktree changes - update protocols, trellis workspace, and config

This commit is contained in:
qzl
2026-04-23 16:04:04 +08:00
parent eeed737949
commit dcb0eb4c65
13 changed files with 519 additions and 40 deletions
+13 -6
View File
@@ -64,13 +64,20 @@
## Error Codes
推荐错误码(由后端映射为 4xx
当前实现(`backend/src/v1/schedule_items/service.py`)实际返回以下稳定错误码
- `INVALID_DATETIME_FORMAT`
- `NAIVE_DATETIME_FORBIDDEN`
- `INVALID_TIMEZONE`
- `TIMEZONE_REQUIRED`
- `INVALID_TIME_RANGE`
- `SCHEDULE_ITEM_DATETIME_TIMEZONE_REQUIRED`:输入 datetime 缺少时区偏移
- `SCHEDULE_ITEM_START_AT_TIMEZONE_REQUIRED``end_at` 校验阶段缺少可用的 `start_at` 时区信息
- `SCHEDULE_ITEM_INVALID_TIME_RANGE``end_at <= start_at`
说明:`timezone` 非法、`start_at/end_at` 无时区等基础结构错误在 schema 校验阶段由 FastAPI/Pydantic 返回 `422`,业务错误码表(`docs/protocols/common/http-error-codes.md`)目前仅登记服务层稳定码。
---
## Compatibility Strategy
- 策略:`backward-compatible`
- 本次为文档对齐更新,不改变线上接口行为;客户端若仅按 HTTP 状态码处理不受影响。
---
+25 -17
View File
@@ -12,28 +12,29 @@
### 1) 作用域级别
- `anonymous`:未登录态(或未绑定用户上下文)
当前实现仅启用以下作用域:
- `user:<user_id>`:已登录用户态
未登录态实现说明:
- `apps/lib/app/services/session_scope_manager.dart` 在登出后会调用 `CacheScope.resetProvider()`
- 当 provider 未配置时,`apps/lib/data/cache/cached_repository.dart` 会跳过 scoped cache 读写,而不是写入 `anonymous` 命名空间。
### 2) 键格式
客户端持久缓存最终键必须按以下格式生成:
`cache:<scope>:<feature-key>`
其中 `<scope>` 可以附带会话代际后缀(推荐)
当前实现未使用会话代际后缀(epoch/version token),最终键格式为
- `user:<user_id>:v<epoch>`
- `anonymous:v<epoch>`
该后缀用于切号并发场景,确保旧会话异步回写落在旧命名空间。
- `cache:user:<user_id>:<feature-key>`
示例:
- `cache:user:8ef4...:chat:history:first:default`
- `cache:user:8ef4...:v12:chat:history:first:default`
- `cache:user:8ef4...:v12:calendar:day:2026-03-29`
- `cache:anonymous:v13:inbox:list:all`
- `cache:user:8ef4...:calendar:day:2026-03-29`
---
@@ -47,18 +48,18 @@
### 应用层(必须)
- 在认证状态变化时更新当前缓存作用域:
- 登录成功 -> `user:<user_id>`
- 登出/失效 -> `anonymous`
- 登录成功 -> `user:<user_id>`
- 登出/失效 -> 清空当前用户作用域并重置 provider(不进入 `anonymous` 作用域)
---
## 并发与切号安全
- 切号后,旧账号异步请求结果不得回写到新账号 UI 状态。
- 推荐使用会话代际(epoch/token)保护异步回写。
- 缓存分区与 UI 状态隔离必须同时存在:
- 仅有分区,无代际保护:仍可能出现瞬时回流显示。
- 仅有代际保护,无分区:仍可能读取到旧持久缓存
- 当前实现依赖 `user:<user_id>` 级别缓存分区 + 认证切换时清理上一用户前缀:
- - 登录切换:清理上一用户 `cache:user:<old_user_id>:` 前缀
- - 登出:清理当前用户前缀并关闭 scoped cache 读写
- 当前实现未引入 epoch/token 代际保护;若未来出现“切号后旧请求晚到并覆盖新 UI”问题,需要另行升级协议与实现
---
@@ -67,7 +68,7 @@
### 向后兼容
- 旧无作用域键允许保留在本地存储中,不参与新读取路径。
- 新版本只读取带 `cache:<scope>:` 前缀的键。
- 新版本只读取带 `cache:user:<user_id>:` 前缀的键。
### 迁移方式
@@ -79,5 +80,12 @@
## 验收标准
1. 同设备 A/B 账号来回切换,不出现跨账号历史/列表串读。
2. 登录后首次读取命中当前用户作用域键;登出后读取命中匿名作用域键
2. 登录后首次读取命中当前用户作用域键;登出后 scoped cache 不再参与读取。
3. Feature 仓库不再自行实现 userId 拼 key 逻辑。
---
## Compatibility Strategy
- 策略:`backward-compatible`
- 本次为文档对齐更新,收敛未落地的 `anonymous`/epoch 设计,不改变现有应用行为。
+13
View File
@@ -215,12 +215,18 @@ data: {"event_id":"6f0d...","occurred_at":"2026-03-30T07:00:00Z","user_id":"..."
"occurred_at": "datetime",
"user_id": "uuid",
"message_id": "uuid",
"event_type": "INBOX_MESSAGE_CREATED | INBOX_MESSAGE_READ_CHANGED | INBOX_MESSAGE_STATUS_CHANGED | INBOX_SNAPSHOT_REQUIRED",
"op": "created | read_changed | status_changed | snapshot_required",
"version": 1743313300000,
"data": {}
}
```
说明:
- SSE 帧的 `event:` 行与 payload 内 `event_type` 当前实现保持一致。
- 客户端可优先使用 SSE `event`,也可在 payload 内读取 `event_type` 做调试或补偿。
### Delta 约定
- `created`:
@@ -275,3 +281,10 @@ data: {"event_id":"6f0d...","occurred_at":"2026-03-30T07:00:00Z","user_id":"..."
- 对 `message_type=calendar`,前端必须按 `content.type` 严格分发:`invite | updated | deleted`。
- 若 `content` 缺少协议必填字段(`schema_version/item/actor/summary`,以及 `updated` 的 `changes`),前端必须进入协议异常展示路径。
- 禁止将协议异常消息兜底渲染为“默认日历邀请”或其他正常业务消息。
---
## Compatibility Strategy
- 策略:`backward-compatible`
- 本次仅补全文档遗漏字段 `event_type`,不改变现有 SSE wire 协议。
+8 -1
View File
@@ -43,7 +43,7 @@ Base URL: `/api/v1/users`
字段说明:
- `id`: 用户唯一标识符 (UUID)
- `username`: 用户名,3-30 字符
- `username`: 用户名,当前后端更新接口约束为最大 30 字符(最小长度未在 API 层强制)
- `phone`: E.164 格式手机号,可为 null
- `avatar_url`: 头像 URL,可为 null
- `bio`: 个人简介,最大 200 字符,可为 null
@@ -142,3 +142,10 @@ Base URL: `/api/v1/users`
### Response
`UserContext` 对象。
---
## Compatibility Strategy
- 策略:`backward-compatible`
- 本次仅修正文档约束描述与实现一致,不改变接口字段与响应结构。