anonsaber
afa6cec8ef
debug: 新增 /debug/* 远程联调面,双因子门禁默认绝对关闭(01a0e319)
...
新增 src/debug.rs:/debug/ping、/config、/redis、/jmap、/telegram、/worker 六个只读
探针 + POST /debug/notify 一条测试出站消息。
SAF-DEBUG-GATE 双因子,缺任一即完全不挂载路由(请求落到通用 404,无"未配置即放行"
降级):
- 启动命令带 --debug(main.rs 最小 std::env::args 解析,未新增依赖)
- Secret 环境变量 DEBUG_TOKEN 非空
两层执行点:main.rs 推导 debug_token 并传入 router builder(None 则 debug_router 不被
merge);debug.rs 侧 auth_token 缺失时直接返回空 Router。
SAF-DEBUG-AUTH:每个 handler 先做 Authorization: Bearer DEBUG_TOKEN 常数时间比较
(复用 worker_authorized),失败 401,鉴权通过前不产生任何副作用。
探针只读侧全部复用现成实现,不另写一套:Redis 走 is_enabled,JMAP 走
probe_jmap_session,Telegram 走 probe_telegram_get_me,出站走唯一构造点
business_client(notify.rs 新增 pub(crate))到 send_text,/debug/notify 与
refresh_business_config 共用同一条客户端构造路径。
SAF-NO-SECRET-ECHO / SAF-LOG-PURITY:/debug/config 只回"是否配置"、计数与超时等
运行时参数,bot token / JMAP password / worker / webhook / reconcile token / LLM key
一律不出现在响应体;DEBUG_TOKEN 只在鉴权内部暴露,不回显、不入日志,日志仅一条
"debug endpoints enabled" 且不含令牌值。allowlist 用 chat_allowlist_snapshot 取生效值
(运行时业务配置优先、否则启动值),/debug/notify 显式 chat_id 不在 allowlist 则 403。
ARCH-LB-WORKER 白名单不含 /debug/*,该面仅供直连 origin 联调,公网入口不可达。
AGENTS.md 登记 4 个稳定 ID:MOD-DEBUG / SAF-DEBUG-GATE / SAF-DEBUG-AUTH /
REQ-DEBUG-ENDPOINTS(§2 第 19 条硬边界、§5 测试条、§7 索引 4 行)。
调试路由测试(4 项,notify.rs + debug.rs 内):Bearer 放行 200、缺失/错误令牌 401、
未提供 DEBUG_TOKEN 因子时 /debug/* 完全不注册而落 404、/debug/notify POST 未认证 401。
门禁四段全绿(rust:1-slim-bookworm):cargo fmt --all -- --check / cargo check --locked
/ cargo clippy --locked --all-targets -- -D warnings / cargo test --locked =
49 passed / 0 failed / 1 ignored。
2026-09-28 15:00:49 +08:00
anonsaber
800d6e0d00
notify: SPA 管理凭据改用 CONFIG_ENCRYPTION_KEY,解除与 Redis ACL 密码耦合
...
原实现把 SPA 管理凭据派生自 REDIS_URL 的 ACL 密码,并在 handler 侧用
`.is_empty()` 直接拒绝空凭据。托管 Redis 常见配置是 TLS-only 无密码,
那种情况下 `.is_empty()` 恒为真,管理界面永久 401 —— `POST /api/bootstrap`
与 `POST /api/admin/session` 双双不可用,无法完成初始化。
改为直接取 CONFIG_ENCRYPTION_KEY:它本就是启动必填 Secret(64 位 hex /
32 字节,见 config::encryption_key_from_env),启动时已校验,因此生产环境
不可能出现空凭据,handler 侧的空串守卫随之失效,一并移除。Redis ACL 密码
回归本职:只用于数据库连接。
- main.rs:env 只读一次(encryption_key_raw),admin_token 与已校验值不可能
分叉;删除 Url::parse(redis_url).password() 分支。
- notify.rs:AppState 字段 bootstrap_token → admin_token(4 个构造点同步),
两处 handler 删除空串守卫,bootstrap() 文档不再称 Redis ACL bootstrap。
- 测试更名 bootstrap_rejects_missing_admin_credential:断言语义不变(测试态
空凭据收到 Bearer 仍 401),名称改为反映新语义。
门禁全绿:cargo fmt --check / check --locked / clippy --all-targets -D warnings
/ test --locked = 45 passed, 0 failed, 1 ignored。
2026-09-28 12:43:33 +08:00
anonsaber
c5bc7b8d82
fix(notify): /ready JMAP 探针对齐真实客户端(Basic 认证 + 路径归一)
...
架构师复核指出两点会致全站不可用的缺陷(notify.rs):
- 探针未带认证:真实 jmap_client 以 .credentials() 取 session,Stalwart
session 端点需认证;无认证必 401 → /ready 永久 503 → ingress 停止路由。
改为从 business_runtime 快照取 jmap_username/jmap_password,
basic_auth 随请求发送(零新增依赖,凭据仅入请求头,绝不日志)。
- session URL 未归一:配置若是裸 origin,GET 根路径必 404 → 误报。
改为复用 normalize_session_url(client.rs 改为 pub(crate))并请求
标准 /.well-known/jmap,与 JmapClientBackend::connect_with_runtime 同路径。
顺带:两探针 tokio::join! 并行,/ready 最坏耗时 3s→3s(原 6s)。
门禁 4/4 绿(45 passed, 0 failed, 1 ignored)。
2026-09-28 10:37:22 +08:00
anonsaber
c0aab5e966
feat(notify): /ready 接入 JMAP session 与 Telegram getMe 端到端探测
...
ARCH-READY-BASELINE 从「配置完整性 + Redis 可达性」升级为端到端就绪:
- PROBE_TIMEOUT=3000ms 各探针独立超时(notify.rs:69)
- cached_jmap_session_url / cached_bot_token 先克隆后 await,
避免跨 .await 持有 RwLockReadGuard(非 Send)
- probe_jmap_session:GET JMAP session URL,error_for_status
- probe_telegram_get_me:bot token 仅用于拼 URL,绝不日志
- ready():四者全过返 200 + 就绪报告 JSON(jmap/telegram 真实结果),
任一失败 503 + Retry-After: 30(标准错误 envelope)
- 探针只读、无状态写入;token 永不回显(SAF-NO-SECRET-ECHO)
门禁:fmt / check / clippy / test 4/4 绿(45 passed, 0 failed, 1 ignored)。
2026-09-28 10:15:52 +08:00
anonsaber
ed93358e29
feat(notify): unify /ready not-ready 503 into the error envelope
...
- GET /ready: ready -> 200 + diagnostic report (unchanged success body);
not ready -> 503 + {"error":"service_unavailable","request_id":id}
+ Retry-After: 30, consistent with the other public entry points
- drop the legacy {"status":"not_ready"} diagnostic block from the 503 body
(backward compatibility not required)
- HTTP 200/503 semantics preserved, so Uptime Kuma HTTP(s) monitors
(status-code based) keep working
- sync docs: README.md, README.zh-CN.md, docs/design.md, docs/deployment.md,
AGENTS.md, docs/todo.md
2026-09-27 13:11:29 +08:00
anonsaber
f16b747672
feat(notify): unify public-route error envelope and add push route tests
...
- all public write routes now return {"error":code,"request_id":id};
retryable 503 responses add Retry-After: 30; 204 and success bodies unchanged
- GET /ready keeps its structured diagnostic JSON (Uptime Kuma runtime contract)
- add HTTP tests for the push register/disable routes
2026-09-27 12:53:22 +08:00
anonsaber
309a38c503
fix(worker,state,jmap,config): close independent-review findings
...
- worker/state: paginate Email/changes by widening maxChanges on the same
sinceState (jmap-client 0.4.2 has no upToId) to avoid skipping a batch when
advancing per page; make dedup+enqueue atomic via claim_dedup_and_enqueue
(Lua SET NX EX then XADD); scale the XAUTOCLAIM idle threshold by batch size;
XACK payload-less malformed stream entries out of the PEL via ack_malformed;
fail closed on unknown streams (Err); tighten SET NX EX TTL to .max(1);
derive the CSPRNG fallback owner-token from time+PID+counter instead of a
constant; clear the push verification digest on push:disable
- worker: /help menu now lists only the consent triggers the parser accepts
- jmap/config: complete client and configuration validation
2026-09-27 12:53:05 +08:00
anonsaber
956ef6a1d3
feat(config): add global Redis-backed enable switch
2026-09-25 20:11:35 +08:00
anonsaber
4ecfa44485
fix(redis): install explicit rustls crypto provider
2026-09-25 18:02:21 +08:00
anonsaber
a57cb4f75d
fix(redis): enable TLS for Upstash connections
2026-09-25 17:45:24 +08:00
anonsaber
e18cecca16
refactor: remove legacy project identity
2026-09-25 10:40:10 +08:00
anonsaber
8a24ec7e9e
fix: report all missing setup requirements
2026-09-25 09:42:15 +08:00
anonsaber
e5ec3aef4c
feat: provide configuration setup mode
2026-09-25 09:30:45 +08:00
anonsaber
dceecaf2f4
feat: initial MessageWeave release
2026-09-25 09:14:04 +08:00