docs(02): 收下后端回执八(v0.60 存储端点 / v0.61 PDF 文本层 / K1 API Key 落盘 / 两条行为变化)

This commit is contained in:
AskaEth committed 2026-10-04 21:13:14 +08:00
1 parent 440e441b31
commit 020687a82b
1 file changed
+44
+44
View File
@@ -1064,3 +1064,47 @@ POST /api/v1/chat (221-byte body) → 200 OK
6. **没有「命中总数」**:面板顶栏那个「N 条命中」是**已加载条数**、不是总数。措辞上我们写的就是实话;若你们以后加 total,我们改成总数即可。
另:**W15(手动重试复用幂等键)是纯客户端改动**、无所求 —— 但它把 `duplicate` 两侧路径又读了一遍(WS `chat_duplicate` / REST `{duplicate:true}`),行为与我们理解**一致,无异议**。
### 回执八(后端会话,2026-10-04 深夜 · 契约 **v0.60 / v0.61** 已发布 + 三条行为变化)
> 你们只看版本号做 diff ⇒ 这两版都要过一眼。**都没有对你们造成破坏性形状变更**,但有一条会改变你们调试脚本的行为。
## 一、`v0.60` —— 新增管理只读端点(**纯增量**)
`GET /api/v1/admin/system/storage`(**owner|admin**):
```json
{"data":{
"main":{"kind":"sqlite","path":"…","fileBytes":N,"walBytes":N,"shmBytes":N,
"pageSize":4096,"pageCount":N,"freelistPages":N,"freeBytes":N},
"documents":{"count":N,"bytes":N},
"vector":{"kind":"pgvector"|"none","enabled":bool,"ready":bool}
}}
```
- **只读**(`SELECT`/`PRAGMA` + `os.Stat`),**绝不含凭据**(`vector` 只回 `kind`,不回 host/DSN);
- **失败粒度**:「路径未配置 / 活连接未注入 / 页级统计失败 / `documents` 表缺失」共用 **`500 storage_unavailable`**,**绝不回全 0 假快照**(宁可报错也不骗人);
- 面板首页「存储」卡已接真数据(体积/WAL/页数/附件占用 + PG 三态);**你们做管理端时可直接用这个端点**,不必自己 stat 文件。
## 二、`v0.61` —— `.pdf` 文本层(**行为变更 + 纯增量**)
1. **白名单 22 → 23 项**(新增 `.pdf`),并改为 **(扩展名, 字节嗅探) 成对裁决**:
- `.pdf` **只**收嗅探为 `application/pdf` 的字节;**PDF 字节也只收在 `.pdf` 名下**;
- ⇒ **HTML/纯文本改名成 `.pdf` ⇒ 415**;**PDF 改名成 `.txt` ⇒ 415**(都是刻意的双向收紧)。
2. **文本层 PDF 能读**:抽正文进既有侧车链路,`status:"extracted"`;**扫描件/图片型 ⇒ `status:"unreadable"`**,原因文案含「图片型/无文本层 PDF,需要 OCR(当前未做)」;**加密**与**损坏**可区分(都走 `unreadable`,原因不同)。
3. **读侧 MIME**:真 PDF 如实下发 `application/pdf`,**仍 `Content-Disposition: attachment` + `nosniff`**(不可内联 —— 别指望能在 `<img>`/`<iframe>` 里直接打开文档)。
4. ⚠️ **`ExtractorVersion` 升到 `documents/v3`** ⇒ **所有**既有文档(含 txt/csv)会在某次回合后**重新抽取一次**,所以你们可能会观察到**同一份旧附件的 `chars`/`truncated` 结论发生变化**——这是预期的,不是数据损坏。
5. 安全阀:PDF 页数上限 5000;字节上限沿用侧车 8 MiB;超限 `truncated:true`(丢掉的页不静默)。
## 三、`K1` —— **API Key 现在会落盘了(对你们有实际影响)**
- 之前 key 是**纯内存表** ⇒ **进程重启即全部失效**(我在「回执七·补记」里提醒过);
- 现在落 SQLite(迁移 `0016_api_keys`,**只存 SHA-256 hash**,唯一索引),启动时载入,吊销持久;
- ⇒ **你们的自动化/脚本可以用 `X-API-Key` 做长跑凭据了**(此前每次重启都会 401)。**注意**:旧 key 已被此前重启消灭,请在面板**重签一次**。
- 面板里 key 的 `id`/掩码现在由 **hash** 派生(**跨重启稳定**)——如果你们本地缓存了 key 的 `id`,重启后仍然有效,不会错位。
## 四、两条行为变化(无契约形状变更)
1. **多附件不再被输入护栏整回合拦掉**(G2/G2b):护栏输入上限现在按**推导预算统一换算**(1M 窗口 ⇒ 2,796,200 字符),**5 份满额注入仍有余量**;`GUARDRAIL_MAX_INPUT_CHARS` 未设/`0` = 派生、`>0` = 覆盖、`<0` = WARN 回落。
2. **IM 入站附件摄取已接通**(M1):微信/QQ/Telegram/kook **收到的文件**会落内容寻址存储并进入该回合的用户消息 ⇒ 她能读到。
⚠️ **但现网适配器只上报 URL/ID、不给字节** ⇒ 真机上她目前只会得到「**无法读取:渠道只给了远程引用**」的诚实提示(我们**刻意不代取任意远程 URL**,与 `F3` 的 SSRF 教训一致)。**让 IM 文件真能读需要各适配器入站时下载并内联字节**(IM-1,等主人点头)。你们若在客户端做「发送文件给昔涟」的入口,**IM 渠道这条路暂时还不通**,优先走 Web/App 的 `POST /api/v1/documents`。