feat(ECR-012–016): 合规、题库、时辰刷新、头像、MBTI OEJTS 与埋点

落地输入合规、探索题库、报告日/时辰刷新、账号头像、OEJTS 量表,并补齐 H5 埋点与 Admin 漏斗;同步 ESS 工件、切至自建 Git、清理 GitHub Actions。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-13 01:27:58 +08:00
co-authored by Cursor
parent 13860bf1ef
commit 89756f65b4
227 changed files with 7405 additions and 1407 deletions
@@ -0,0 +1,123 @@
# Feature Spec: 用户文字输入合规校验
> Status: `Active` · Map: `横切 · 安全/合规` · Phase: `P2`
> 关联:[lexicon.md](../lexicon.md) · [.ai/security.md](../../security.md) · account-auth / profile / ask / companion
---
## 1. 功能定义
| 字段 | 内容 |
|---|---|
| Name | 文字输入合规(Text Compliance |
| Purpose | 所有用户提交的**自由文字**在服务端统一做合法性/合规校验;前端可做即时提示,**以后端拒绝为准** |
| Business Goal | 降低 XSS/注入、恐吓与医疗疗效话术、垃圾刷屏进入 DB 与模型上下文的风险 |
| In | Out |
|---|---|
| 昵称 · 档案显示名 · 问答 content · 心情/打卡 note · 成长计划 title/focus · 邀请 display_name · 意象场景自填 | 纯数字字段(生日年月日、分数、经纬度) |
| 长度 · 格式清洗 · XSS/控制字符 · lexicon 硬禁止 · 简易刷屏特征 | 完整内容审核平台 / 人工审 / 语音 |
| 错误码统一 | 改开放登录策略本身 |
---
## 2. 用户价值
1. 避免有害/违规文案入库与进模型。
2. 提交失败时得到可读中文原因。
3. N/A(安全横切,非付费面)。
---
## 3. 用户角色
Visitor / User / Admin 凡提交自由文字均适用(Admin 运营文案可后续加强;本 Spec **先 C 端用户 API**)。
---
## 4. 用户流程
```text
用户输入文字 →(可选)前端即时校验
→ API Handler/Service 调用 textsafe.Check(kind, text)
→ OK:规范化后入库/进模型
→ 拒绝:HTTP 400 · code 40060 · message 可读原因
```
---
## 56. 页面 / 状态
各既有表单;Error 态展示 `message`。无新页面。
---
## 7. Business Rules
| ID | Rule |
|---|---|
| R1 | **后端必须校验**所有用户自由文字;前端校验不得替代后端 |
| R2 | 种类与上限(rune):`nickname` 116`display_name` 124`ask_content` 12000`note` 0200`title` 140`focus` 040`scene` 180 |
| R3 | 拒绝控制字符(允许消息内 `\n` `\t`);拒绝 HTML/脚本片段(如 `<script``javascript:` |
| R4 | 命中 lexicon 硬禁止子串(占卜/算命/改命恐吓/疗效承诺/「测测」品牌自称等)→ 拒绝 |
| R5 | 刷屏特征:连续相同字 ≥8,或可见字符全相同且长度 ≥6 → 拒绝 |
| R6 | 密码字段不做 lexicon,仅拒空字节;手机号走既有数字规则 |
| R7 | 校验通过后写库的是 **Normalize** 后的文本(Trim;压缩首尾空白) |
| R8 | 错误码:`40060`;文案过 lexicon(勿用恐吓语气) |
---
## 8. 数据模型
无新表。进程内可选短时计数(本版刷屏以内容特征为主,不做跨请求配额表)。
---
## 9. API
既有写接口;拒绝时统一:
```json
{ "code": 40060, "message": "文案不合规:…", "data": null }
```
---
## 10. 权限
同各业务接口鉴权;校验在鉴权之后、写库之前。
---
## 11. 埋点
可选:`text_rejected{kind}`(本版可不接)。
---
## 12. 验收
| Given | When | Then |
|---|---|---|
| nickname 含「算命」 | PATCH /auth/me | 40060 |
| ask content 含 `<script` | POST messages | 40060 |
| display_name 正常「小愈」 | POST profile | 200 |
| note=`啊啊啊啊啊啊啊啊` | POST mood | 40060 |
---
## 13. AI 检查
- [x] lexicon
- [x] 后端权威
- [x] 不扩开放登录
---
## 14. Implementation
| 项 | 内容 |
|---|---|
| Package | `apps/api/internal/textsafe` |
| Mirror | `@yuxingu/utils` `validateUserText`(即时提示) |
| Wire | auth · profile · ask · companion · growth · synastry accept |