Commit Graph

8 Commits

Author SHA1 Message Date
anonsaber 6bb57801ac feat(lb): POST /worker 加入路由 safelist,走独立长超时且不故障转移
外部 cron 触发排空队列时,/worker 走 Worker 域名会被 404 route not forwarded
挡掉,只能直连后端 origin;而 /reconcile 早就能走 Worker。cron 脚本因此被迫
维护两个域名。现把 /worker 与 /reconcile 成对放进 safelist(17 -> 18 条),
cron 只需一个平台域名。

同时给它配独立超时:全局 LB_REQUEST_TIMEOUT_MS 默认 10s 会把一次正常的排空
误判成失败,而 maxAttempts=2 切到第二实例毫无意义——第二个实例只会重复排
同一批消息。故新增 LB_WORKER_TIMEOUT_MS(默认 300000ms,等于后端单条事件
下界 state.rs SINGLE_EVENT_CEILING_FLOOR_MS),并强制 maxAttempts=1。

- SAFE_ROUTES 加 "/worker";ROUTE_METHODS 加 "/worker": ["POST"](GET => 405)
- 新增 DEFAULT_WORKER_TIMEOUT_MS = 300_000 与 per-route 覆盖分支
- LB_VERSION 2026.10.2 -> 2026.10.3(改 LB 逻辑须 bump)
- test/index.test.js 新增回归:/worker maxAttempts=1、默认 300s、env 覆盖、
  GET /worker => 405 且不打到后端
- test/backends.test.js safelist 用例补 /worker 与 /api/business-config/preflight

node --test:37 通过 / 0 失败(index 14 / backends 6 / health 5 / lb 12)。
2026-09-30 23:08:41 +08:00
anonsaber 89dfe5cf3d feat(lb): /healthz 透传到源站,LB 聚合探针改挂 /healthz-worker
源站自己也暴露 /healthz;两者同路径时走 Worker 域名只能看到 LB 的聚合
结果,看不到源站自己的健康状态。现在拆开:

- GET /healthz        透传到源站(源站自己的健康检查)
- GET /healthz-worker LB 聚合探针(LB_VERSION + 后端汇总)

SAFE_ROUTES 增列 /healthz、ROUTE_METHODS 增列 /healthz: [GET],白名单 16 -> 17。
LB 探测源站的路径仍是 /healthz,不变。LB_VERSION 2026.10.1 -> 2026.10.2。

GATE-DOCS 6/6;node --check 全部通过。
2026-09-30 21:36:37 +08:00
anonsaber 15fa7f1e35 feat(lb): /healthz 回显版本号 LB_VERSION,确认线上是哪次部署在回答
上次生产事故里「改了代码不知道有没有生效」缺少直接证据;现在 /healthz 的
JSON 多一个 version 字段,取 env.LB_VERSION(写在 wrangler.toml 的 [vars],
当前 2026.10.1),未配置回退 unknown,探针永不因缺该字段而失败。

healthResponse(summary, version) 的第二参数可选:省略时 JSON 不含该字段
(JSON.stringify 丢弃 undefined),既有调用与用例不受影响。

放 [vars] 而不是 dashboard Add Variable 的理由:它必须跟代码同版本、可 diff,
写进 dashboard 反而容易漂。代价是改 LB 逻辑的提交要顺手 bump 它。

文档同步:§10.4 响应体形状加 version、§10.9 [vars] 示例与验证步骤、
README 环境变量表补一行;用例计数 32 → 35。

验证:node --test 35/35;wrangler deploy --dry-run 通过;docs gate 6/6。
2026-09-30 20:21:48 +08:00
anonsaber aa78c13161 worker: BACKEND_ORIGINS_JSON 写入 wrangler.toml 的 [vars](明文例外)
Cloudflare Git 集成会提示"Update your Wrangler configuration with these changes to
keep deployments in sync",原因是 UI 上的 origin 列表没在仓库里。接受该建议:origin
列表只是公开可达的 https 地址,不是凭据,所以可以随仓库走——配置在 PR 里可审,
预览环境也能拿到它(secret 只存在于 dashboard,preview 拿不到)。

wrangler.toml 加了「明文例外的边界」评论:一旦出现内网地址 / 带内嵌凭据的 URL /
不想公开的 staging 主机名,立刻从 [vars] 删掉改用 wrangler secret put(git 历史
不可逆)。其余三个 LB_* 保持可调参数不写死。

已用实际解析器验证:parseBackendOrigins 返回 [{url: https://messageweave-eu-1.motofans.club,
healthPath: /healthz}];npm test 32 通过 0 失败;wrangler deploy --dry-run 通过,
配置里可见 env.BACKEND_ORIGINS_JSON 绑定。
2026-09-30 19:07:17 +08:00
anonsaber 826b41e781 worker: 修掉两个会让 Worker 部署直接失败的配置错误
- wrangler.toml 用 JSDoc 的 /** */ 注释,TOML 解析器把 '*' 当未知字符
  (wrangler 报 Unknown character 47),deploy/secret put/dev 在读取配置阶段
  就失败,根本走不到你的 secret。全部展开成 '#' 行。
- npm test 写成 node --test test/,Node 22.23 会把 test/ 当模块路径去
  require,报 MODULE_NOT_FOUND。改成 node --test(无参数自动发现 test/),
  仍为 32 个用例全通过(backends 6 / health 4 / index 12 / lb 10)。

wrangler deploy --dry-run 现通过(wrangler 3.114.17,上传 31.48 KiB)。
2026-09-30 16:24:32 +08:00
anonsaber e0882c7c68 docs: de-projectize AGENTS.md into language-agnostic norms; add docs/charter.md
AGENTS.md (276 -> 239 lines) is now a language-agnostic engineering-norms
document: code style, config and secrets handling, build environment,
testing gates, document governance. It states no project fact and names no
language, framework, dependency, or file. Verified: zero hits for JMAP,
Telegram, Redis, axum, Cloudflare, LLM, *.rs, and every project env var.

All project-specific content moved to the new docs/charter.md (~276 lines):
project goals, locked technology choices, 23 numbered security invariants,
implementation stages, prohibitions, test/acceptance gates with the full
GATE-P0 command and baseline, document boundary rules, and the stable ID
registry.

docs/charter.md §8 is the single authority index for stable IDs: 83 rows,
no duplicates, ID | definition file | one-line statement | category. Four
IDs that were referenced across the docs but never registered are now
registered: ARCH-STATE-REDIS, C-REDIS-EXTERNAL, GATE-UPTIME-KUMA, GATE-DOCS.
All previously registered IDs are preserved.

Defect fixed while rebuilding the registry: SAF-ADMIN-SESSION cited
src/config.rs `admin_session_digest`, a name that has 0 hits in src/ -- a
phantom identifier that survived in the authoritative registry since before
this restructure. Corrected to `session_digest` (src/config.rs:7). All 8
distinct backticked symbols in the registry's definition-file column now
verify against src/.

Two false project facts removed from the docs (both claimed the SPA writes
through POST /api/bootstrap, which web/config.js never calls -- 0 hits; the
actual path is PUT /api/business-config): README.md, README.zh-CN.md,
docs/reference.md. The first successful write creates the configuration and
later writes hot-reload it; POST /api/bootstrap remains the one-shot
automation endpoint.

Cross-reference redirections in 9 files: README.md, README.zh-CN.md,
docs/deployment.md, docs/design.md, docs/reference.md,
cloudflare-worker/README.md, cloudflare-worker/src/index.js,
cloudflare-worker/wrangler.toml now point project facts at charter.md and
language-agnostic quality rules at AGENTS.md.

Four validators extended to cover docs/charter.md: DOCS lists in
audit_anchors.py, check_tables.py, validate_docs.py, check_sec_refs.py, plus
charter.md added to check_sec_refs.py's TARGET_BEFORE regex and to
validate_docs.py's index-file cross-doc exemption.

Gates: GATE-DOCS PASS 4/4 (VALIDATION 0 errors, TABLE STRUCTURE 0
mismatches, ANCHOR AUDIT 227 line-refs / 0 errors, SECTION-REF AUDIT 191
refs / 0 errors). GATE-P0 PASS, baseline unchanged 62 passed / 0 failed /
1 ignored. Anchor audit proves line reachability only, not that the line
contains what the prose claims.
2026-09-28 23:39:26 +08:00
anonsaber c75858fda0 refactor: rename project to MessageWeave 2026-09-25 10:29:18 +08:00
anonsaber dceecaf2f4 feat: initial MessageWeave release 2026-09-25 09:14:04 +08:00