From bfd3fefd9731ef899e35550cdb32d2db750760ef Mon Sep 17 00:00:00 2001 From: anonsaber Date: Tue, 29 Sep 2026 19:59:33 +0800 Subject: [PATCH] docs: close SAF-DEBUG-ALLOWLIST by risk acceptance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PM accepts the residual on the strength of the two gates that are already the documented production posture, so the item leaves the gap file and docs/opengaps.md no longer has a 代码缺口 section at all. Both gates verified in code before agreeing to the premise: - closing debug is total: the dual-factor gate in src/main.rs:98-105 feeds src/notify.rs:1340-1342, which only then merges debug_router(); unset and the 7 routes do not exist, axum falls through to a generic 404, so it is not a 401 and does not disclose the path exists - the Worker refuses rather than forwards: cloudflare-worker/src/index.js :81-82 returns 404 route not forwarded for any path outside LB_ROUTES, and LB_ROUTES = SAFE_ROUTES holds exactly 15 entries with no /debug path. Confirmed by reading the list, not by trusting the README So either gate alone is sufficient, which is stronger than the assumption recorded in the gap entry, which treated the allowlist as the thing keeping the other two apart. The residual is already on paper and is the only real one: direct access to the backend origin bypasses both. docs/deployment.md:103 says exactly this, so nothing new had to be written, and design.md:349 now points there and to docs/design.md §7.6 instead of at a section that no longer exists. - drop the allowlist row from the 你要做的事 table as well, or the table would advertise a task whose gap no longer exists - docs/design.md:349 would have dangled on 「代码缺口」, so it now records the closure and its basis rather than a count of a deleted section - docs/retired.md:81 says 「代码缺口」4 → 3. That is the recorded effect of the deletion it documents, so it stays as a past-tense fact rather than being rewritten to the current state of 0 - the behavioral fact stays where it belongs: docs/deployment.md:102 still documents that an empty allowlist does not block, and charter.md:279 still registers the ID with its 启用须确认白名单已配置 condition. Only the gap status was removed - GATE-DOCS 6/6 pass: ANCHOR 270 (was 272), SECTION-REF 226 (was 224, the two new cross-refs I added), PATH 394 (was 393, net +1 swap) --- docs/design.md | 2 +- docs/opengaps.md | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/design.md b/docs/design.md index 4d0e67b..932c579 100644 --- a/docs/design.md +++ b/docs/design.md @@ -346,7 +346,7 @@ message-weave/ | `web` | axum | `/config` 静态页 + `include_str!` 嵌入 + CSP | 前端由 `web/config.test.mjs` 覆盖 | 已实现 | | `debug` | reqwest 0.13;redis 0.27 | 远端诊断面 `/debug/*`(`src/debug.rs`):6 条只读探针 `/debug/ping`、`/debug/config`、`/debug/redis`、`/debug/jmap`、`/debug/telegram`、`/debug/worker` + `POST /debug/notify`(走生产出站路径发一条测试消息,无独立实现) | 仅 `DEBUG_ENABLED`(或 `--debug`)+ `DEBUG_TOKEN` 双因子齐备时挂载路由;模块本身无条件编译 | 已实现,不进 Worker 白名单(`SAF-DEBUG-ORIGIN-ONLY`) | -> 注:「现状」列是**模块级**口径(模块已落地),不代表行为完备。行为级缺口不在本表内:`docs/opengaps.md`「代码缺口」中 `/search`、Telegram 429 退避、多实例重复投递窗口均已实现,仅剩 1 条按产品决策保留不改(`SAF-DEBUG-ALLOWLIST`)。`worker` 模块的 `/search` 路径已随 `bfe0fd8` 落地。 +> 注:「现状」列是**模块级**口径(模块已落地),不代表行为完备。行为级缺口不在本表内:`/search`、Telegram 429 退避、多实例重复投递窗口均已实现。此前记录的唯一一条产品决策项 `SAF-DEBUG-ALLOWLIST`(`POST /debug/notify` 在空白名单时不拦截任意 `chat_id`)已于 2026-09-29 按风险接受关闭并移出 `docs/opengaps.md`——其暴露面由 `SAF-DEBUG-GATE` 双因子挂载与 Worker 路由 safelist 共同约束,行为与残余风险(直连后端 origin 可同时绕过这两层)见 `docs/deployment.md` §2.1 与 `docs/design.md` §7.6。`worker` 模块的 `/search` 路径已随 `bfe0fd8` 落地。 --- diff --git a/docs/opengaps.md b/docs/opengaps.md index bae08d4..c504122 100644 --- a/docs/opengaps.md +++ b/docs/opengaps.md @@ -13,7 +13,6 @@ | 3 | 回调公网映射 | 你 | 只回答一个问题:用哪个组件做映射 | | 4 | `Email/changes` 的 `newState` 语义 | 你 + 我 | 腾一次停机窗口 | | 5 | 单飞锁 TTL 实测 | 我 | 不需要的,依赖 #2 成功后我自己跑 | -| 6 | 允许名单收紧 | 你 | 仅当你要收紧时改业务配置,代码不用动 | ## 阶段目标 @@ -94,12 +93,6 @@ TTL 参数已在代码里写死、单测也已覆盖,但真实场景下的实 我来做的:恢复后跑 `POST /reconcile`,再看 `/debug/worker` 的 `reconcile_cursor`。预期是重新变成一个**新的 `baseline:` 游标**(重新基线化成功),而不是报错或停在旧游标。实测语义回填本节。 -## 代码缺口(已定位) - -仅 1 条,按产品决策保留不改——**这不是待修项,也不需要你做任何事**。 - -- **`SAF-DEBUG-ALLOWLIST`** — `POST /debug/notify` 的收件人校验在允许名单为空时**无条件放行**任意 `chat_id`(`src/debug.rs:233-235`:`!allowlist.is_empty() && !allowlist.contains(&chat_id)`)。空名单即「未启用收紧」,是刻意行为。要收紧:在业务配置里把允许名单填上,代码不用改。要改代码:先推翻这个决策。 - ## 后续(多账号) 单账号由产品决策固定,不在阶段目标内。当前 JMAP 登录与 `Email/query` 均为单一邮箱账号。