Files
mindfulness/spec_kit/Policy Links/plan.md
2026-02-03 17:43:58 +08:00

123 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Policy Links技术计划
## 1. 目标与原则
**目标**:让客户端所有「隐私协议 / 使用协议」入口(至少包含:首次同意页 + 个人主页弹窗)统一通过后端接口获取链接,并支持按设备语言分发,缺省回退 EN。
**原则**
- 客户端不写死协议 URL避免发版更新
- 请求失败不阻塞主流程(尤其是首次同意页)
- 语言选择策略一致、可解释、可排查(返回 `resolvedLang`
## 2. 接口与契约
### 2.1 HTTP 接口
- **方法与路径**`GET /v1/legal/links`
- **请求头**
- `Accept-Language`: `en` / `tc`(当前仅支持 EN / TC客户端可按 i18n/设备语言映射为其中之一)
- **响应**JSON
- `privacyPolicyUrl: string`
- `termsOfUseUrl: string`
- `resolvedLang: "en" | "tc"`
### 2.2 语言回退(服务端决策)
-`Accept-Language` 缺失/无法解析:回退 `en`
- 若目标语言的链接未配置:回退 `en`
- `resolvedLang` 表示服务端最终命中的语言(用于排查)
## 3. 后端实现方案FastAPI
### 3.1 配置来源
采用环境变量Pydantic Settings承载各语言链接配置
- 推荐配置EN
- `LEGAL_PRIVACY_URL_EN`
- `LEGAL_TERMS_URL_EN`
- 可选:
- `LEGAL_PRIVACY_URL_TC` / `LEGAL_TERMS_URL_TC`
> 补充:若未配置 `LEGAL_*`,后端将使用**内置协议内容页**作为兜底,保证客户端点击后“必有内容”。
### 3.2 路由与业务逻辑
- 新增 `v1/legal` 路由模块
- 读取 `Accept-Language` 做轻量解析(只关心 en/tc其他回退 en
- 根据解析结果选择 URL如缺失则回退到 EN URL
### 3.3 内置协议内容页(兜底,保证有内容)
- **页面接口**
- `GET /v1/legal/privacy`隐私协议HTML
- `GET /v1/legal/terms`使用协议HTML
- **内容来源**
- 直接使用仓库文档:`设计说明文档/隐私协议.md``设计说明文档/用户使用协议.md`
- **语言策略**
- 仍按 `Accept-Language` 解析 `en/tc`;若文档缺少 tc 段落则回退 en
- **链接下发回退**
-`LEGAL_*` 未配置(或显式走内置)时,`GET /v1/legal/links` 返回当前服务域名下的上述内置页面绝对 URL
### 3.4 兼容性与安全
- 要求链接为 HTTPS推荐返回前做基本 URL 校验(通过响应模型约束)
- 不引入数据库变更
### 3.5 后端测试(建议)
- 单测覆盖:
- `Accept-Language` 缺失 → `resolvedLang=en`
- `tc` 命中/缺失回退
- `zh-hant/zh-hk/zh-tw` 等输入能解析为 `tc`
## 4. 客户端实现方案React Native + Expo
### 4.1 统一 service
- 新增 `src/services/legalApi.ts`
- 统一拼接 `API_BASE_URL + /v1/legal/links`
- 统一设置 `Accept-Language`
- 统一超时与错误处理(抛错由调用方兜底)
### 4.2 接入点
- **首次同意页**`app/(splash)/splash.tsx`
- 页面展示时拉取链接
- 拉取失败:不崩溃、不阻塞「同意并继续」
- 点击协议入口:使用 `expo-web-browser` 打开下发链接
- **个人主页弹窗**`components/home/ProfileModal.tsx`
- 弹窗打开时拉取链接
- 点击「隐私协议/使用协议」时打开下发链接(不再 `toastTodo`
### 4.3 语言映射策略(客户端)
- 将客户端当前语言映射到 `en / tc` 二选一:
- 任意 `zh*``tc`
- 其他语言 → `en`
## 5. 可观测与排障
- 开发环境打印:
- 请求地址、请求头(含 `Accept-Language`
- 拉取失败原因(仅 dev
- 线上环境:
- 不打印用户相关敏感信息(本接口仅链接配置,风险较低,但仍应克制日志)
## 6. 发布与回滚策略
- **灰度**dev 环境可先不配 `LEGAL_*`,直接验证内置页面能打开;再逐步切到外部托管链接
- **补齐多语言**:逐步补齐 `zh-CN` / `zh-TW` 链接配置
- **回滚**
- 后端:回滚到仅 EN 配置仍可运行(客户端自动回退)
- 客户端:即使接口失败也不阻塞主流程(保持可用)
## 7. 验收映射(对应 spec
- 首次同意页 + 个人主页弹窗均从 API 获取链接
- 设备语言为 EN/TC 时分别打开对应链接
- 不支持语言回退 EN
- 后端不可达时 App 不崩溃,且同意流程可继续