Files
tamabox/.workbuddy/memory/MEMORY.md
T
2026-09-10 18:04:19 +08:00

71 lines
5.9 KiB
Markdown
Raw 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.
# TamaBox-v4 项目长期笔记
## 审计/失败分级惯例(沿用用户偏好)
- 结论分级:P0/P1/P2,配 🔴(阻断级)/🟠(高)。给修复建议前先做根因取证与并行诊断。
- 改代码前先出「方案/变更清单」获批准,再分批落地;用户倾向方案 A 或明确指定方向。
- 工作场景用 `@scene#N:"名称"` 标记(如 `@scene#15:"日常开发"`)。
- 用户常说「你先继续,后面我发现问题再和你说」→ 可自主推进,但重大问题仍要显式指出。
## 构建与测试(Windows 沙箱)
- **本机无 libwebp / GCC**,而 `chai2010/webp`(cgo)会挡住 `go build ./...`。
必须用 overlay 把 `internal/storage/s3.go` 换成 `dev/s3stub/s3_stub.go`:
```
go build -overlay="C:/Users/Tamakyi Gekka/AppData/Local/Temp/tb-webpcheck/overlay.json" ./...
go test -overlay="C:/Users/Tamakyi Gekka/AppData/Local/Temp/tb-webpcheck/overlay.json" ./...
```
(`dev/overlay.json` 里的路径指向 TAMAKY~1 短名,可能失效;用上面 Temp 里的那份。)
- `internal/db` 的测试需要真实 PostgreSQL/MySQL(否则报 `Unknown database type: ""`),
与业务改动无关,可跳过;`go vet` 已能覆盖其编译。
- **`proxy.golang.org` 在本沙箱返回 Bad Gateway**:拉新依赖 / `go mod tidy` 前先
`export GOPROXY=https://goproxy.cn,direct`。
- `internal/security/censor/censor.go`、`internal/security/censor/text_test.go` 存在**升级前就有**的
空格缩进(`gofmt -l` 会列出)。除非专门整理,否则不要顺手 gofmt,避免污染 diff。
## 内容审核架构(简洁版)
- 线上生效的审核通道是**七牛云**(`ai.qiniuapi.com/v3/text/censor`,scene=antispam);阿里云通道代码存在但 key 留空、不生效。
- **通道可选**:`[security] text_censor_source = qiniu | aliyun | auto`(留空同 auto=七牛优先、阿里云兜底,即历史行为)。
取值常量在 `conf`(`CensorSource*`),装配在 `censor.censorChain()`,启动校验在 `conf.validateTextCensorSource`。
显式选通道却缺凭据会**启动报错**(避免运行期 fail-closed 导致整站不可用)。
- 关键事实:七牛 `IsPass()` 只硬拦 politics/terrorism/porn,`review` 一律放行;
七牛文本审核**不支持白名单**、自定义词库需提工单 → 服务端「拦得准不准」不可控。
- 因此本项目把「是否拦截」从服务商 Pass 判定剥离,收敛到策略层:
`internal/security/censor/policy.go`(档位裁决)+ `internal/security/moderation/moderation.go`(唯一入口 `Check`)。
- **任何新增的文本审核调用点都必须走 `moderation.Check`**,不要再直接调 `censor.Text`,
否则会绕过「审核严格度」档位。三场景:提问/回答、投票、私聊。
- 语义约定:`LabelScore.Score` 统一归一化 0~1(七牛本身即 0~1;阿里云 2.0 无逐标签置信度,
按 `riskLevel` 折算 high=1 / medium=0.6 / low=0.3,该响应内所有标签共用同一分值)。
- 审核服务不可用时 **fail-closed**(拒绝提交)—— 这是既有行为,未经批准不要改成 fail-open。
⚠️ 推论:**显式选定的通道一旦坏掉(账号未开通/欠费/权限不足),整站发布+私信会全部被拒**,现象隐蔽(只在日志)。
### 阿里云 green 通道(`/green/text/scan`, 2018-05-09)
- 实现与上游 NekoBox 及阿里云官方 Go 示例**逐字节一致**;`TextScanRequest` 无独立 `Content` 字段,
body 走内嵌 `RoaRequest.Content`。**SDK 的 ROA 默认 Content-Type 是 `application/octet-stream`**
(`sdk/auth/roa_signature_composer.go:88`),现已显式 `SetContentType(requests.Json)` 对齐接口契约。
- 已知故障:HTTP 200 + `data` 为空 → `"response data is empty"`。**该错误此前会吞掉顶层 code/msg/requestId**
(唯一的根因线索),现已把 code/msg/requestId + 原始响应摘要(≤512 字符)写进错误。
✅ 2026-09-10 实证根因:`code=596 "You have not opened Yundun Content Moderation Service"` ——
阿里云回的是 **HTTP 200 + `success:false` + 无 data**,即「请求被拒也返回 200」。
⚠️ **硬门槛:「内容安全 1.0」开通前提是账号完成企业实名认证**(官方 69806),个人认证账号**永远开不了**。
开通入口是 `common-buy.aliyun.com/?commodityCode=cdi#/open`,不是产品介绍页 `aliyun.com/product/lvwang`。
替代方案:迁「内容安全增强版 2.0」(`green-cip`,个人认证可开,但标签体系完全不同、需改代码),
或退回 `auto`/`qiniu`。RAM 用户需 `AliyunYundunGreenWebFullAccess`;欠费停服同理。
- `data[].code != 200`(任务级失败)仍 fail-closed 置 block,但现在会打 Warn ——
否则「审核失败」与「真的违规」在日志里无法区分。
- ⚠️ `SetContentType(requests.Json)` 已加,但**已证伪与上述故障无关**,保留原因仅是接口契约对齐。
## 文件工具陷阱(重要)
- `templates/user/moderation-strictness.html`:**用 Write/Edit 写它会被自动注入 `data-page-node-id` 属性**
(每次一批新 id);**用 shell(sed)改则不会**。注入方是「文件工具触发的后处理钩子」,不是文件监听。
→ **该文件今后只用 shell 修改**。相关断言(`templates/render_test.go`)已改成不依赖属性顺序的正则。
- 往 gofmt 对齐组**中间**插 map 键,会把「拆分后剩余组」整组重新对齐 → 污染 diff。
新键应插在组末尾或独立成组(前后留空行)。i18n 字典已因此返工过一次。
## 仓库状态
- **git 仓库已损坏**(`.git/refs` 缺失、index 截断、对象库近乎空),用户明确要求「不要动 git」。
备份/回滚一律用 tar.gz(排除 `.git`、`.workbuddy`),放在项目同级目录:
`C:/OtherFiles/Github/TamaBox-v4-mainline-<描述>-<日期>.tar.gz`。