Commit Graph

9 Commits

Author SHA1 Message Date
anonsaber 7331cb7d31 fix(push): verification key should never expire (TTL 0)
User feedback: any finite TTL causes push to silently stop working
eventually. Stalwart does not re-verify (RFC 8620 §7.2 sends the
verification request once at subscription creation). The key is
explicitly deleted by forget_push_subscription when the subscription
is retired, so no TTL is needed.

Changes:
- PUSH_SUBSCRIPTION_SECONDS: WEEK → 0 (never expires)
- remember_push_subscription: ttl_seconds=0 → SET without EX (Redis)
  / expiry=i64::MAX (MemoryState)
- ttl_contract_is_pinned test: assert 0
- docs: reference/opengaps/design updated to 'never expires'
2026-10-12 23:57:24 +08:00
anonsaber d452f95485 fix(push): PUSH_SUBSCRIPTION_SECONDS 300→WEEK (604800)
Root cause of push notifications failing while cron works:
- Stalwart sends the verification request (RFC 8620 §7.2) once at
  subscription creation; event pushes (§7.3) arrive without
  verificationCode and rely on dedup_exists("push:subscription:{id}")
  to confirm prior verification.
- TTL was 300s (5 min): key expired → every event push 401'd.
- Cron path bypasses this key entirely (polls /changes directly),
  which is why cron-delivered emails still arrived.

Fix: align with PUSH_REGISTRATION_SECONDS (1 week). Stalwart does not
re-verify; the key must survive restarts and any gap between
subscription creation and events.

Also fixes: removed fictional push:subscription-code:{code} from
opengaps TTL table (no such key exists in code); corrected
reference.md caller from register_push→jmap_push verification path;
fixed 前→EX typo in reference.zh-CN.md; design.md updated with
fifth 'why' bullet and historical context.
2026-10-12 23:42:28 +08:00
anonsaber 21e91765d0 feat(reconcile): filter initial baseline to 7-day unread emails
New mailbox onboarding no longer floods Telegram with the entire
mailbox history.  The initial baseline walk (ReconcileCursor::Walk,
any position) now passes an EmailQueryFilter to list_emails_page that
bounds Email/query to messages received within the last 7 days and
not yet seen ($seen keyword, RFC 8621 §4.1.2).

- EmailQueryFilter { received_after: Option<i64>, unread_only: bool }
  in src/domain/jmap.rs (backend-agnostic domain type).
- StalwartJmap::fetch_email_page builds a compound Filter::and from
  the filter conditions (after + not_keyword "$seen").
- walk_baseline computes the 7-day cutoff once and passes it to
  every page fetch, so resumed walks stay filtered.
- Replay(state) path returns early and never calls list_emails_page,
  so /changes incremental is unaffected.
- const INITIAL_BASELINE_WINDOW_DAYS: u64 = 7.
- New test first_reconcile_filters_the_initial_baseline_to_recent_unread
  pins the filter on every Walk page and the cursor transition to Replay.
- 3 doc anchors re-anchored (worker.rs:227→241, client.rs:485→513 ×2).

GATE-P0: 104 passed / 0 failed / 4 ignored.
2026-10-12 22:08:51 +08:00
anonsaber 1bdda7c471 fix: reconcile lock robustness — TTL 300s→60s, heartbeat 90s→30s, renewal interval 10s
- state.rs: RECONCILE_LOCK_SECONDS 300→60, RECONCILE_HEARTBEAT_SECONDS 90→30,
  new RECONCILE_HEARTBEAT_INTERVAL_SECONDS=10; ttl_contract_is_pinned asserts
  interval*2 <= TTL < 60 and interval < LOCK
- notify.rs: heartbeat sleep uses ttl::RECONCILE_HEARTBEAT_INTERVAL_SECONDS
- docs: 7 files updated (reference/charter/opengaps/design × en+zh + index.js
  comments); retired.md/opengaps.md anchor line numbers shifted for state.rs
  (+9) and notify.rs (+3); notify.rs:1484-1485 range trimmed to avoid blank
- GATE-DOCS 6/6, cargo fmt/clippy/test clean (103/0/4)
2026-10-12 22:03:11 +08:00
anonsaber 7aedcd4145 docs: merge deployment.md into README, delete deployment files
- Move operational content (env var reference, multi-instance prerequisites,
  troubleshooting, cron-drain, CF Dashboard Git integration, BACKEND_ORIGINS_JSON
  format, security checklist) into README and README.zh-CN
- Delete docs/deployment.md and docs/deployment.zh-CN.md
- Update 5 validator DOCS lists to remove deployment entries
- Update charter §7 doc boundary table, AGENTS §2.5 line-anchor exception
- Fix cross-doc references in design/reference/opengaps/retired/worker READMEs
- Fix cron-drain.sh header comment reference (deployment.md §6.3 → README §3.10)
- GATE-DOCS 6/6 PASS (55 anchors / 441 sec-refs / 699 path-refs, 0 errors)
2026-10-10 18:53:43 +08:00
anonsaber baa6d8a6a1 docs: reanchor the notify.rs and state.rs line refs the backend moved
The retire-on-change commit inserted ~500 lines into notify.rs and ~110
into state.rs, shifting every anchor at or after the insertion point.
The ANCHOR audit only proves the referenced line exists and is
non-empty, so all of these passed while pointing at the wrong code:

  deployment.md/.zh-CN   register_telegram_webhook 1619 -> 1623
                         register_push             1464 -> 1468 (EN)
                         register_telegram_webhook 1439 -> 1623 (zh)
                         register_push             1315 -> 1468 (zh)
  retired.md/.zh-CN      registration_lock fmt      1328-1330 -> 1481-1483
                         register_push              1315 -> 1468
                         state.rs read_batch        491 -> 506
                         state.rs query_async       531 -> 546
                         state.rs XGROUP CREATE     499-507 -> 514-522
  opengaps.md/.zh-CN     get_reconcile_state        777 -> 792
                         set_reconcile_state        785 -> 800
                         acquire_lock               1076 -> 1130

Every target was verified against the source before editing: two of the
pre-existing anchors pointed inside a different function than the one
they named, and the EN deployment.md had both register anchors off while
the zh twin still carried the original pre-move numbers.

Also documents the new push:registration:current key in the Redis key
table (writer, readers, TTL, and why its literal suffix cannot collide
with the hex session_digest suffix) and carries the zh twin the EN
version already got. Mirror the retire-on-change contract in
deployment.zh-CN.md - the zh twin has its own callback section, which
the EN update skipped.
2026-10-01 11:35:06 +08:00
anonsaber af89a17f7f feat(auth): extend admin session to 30 minutes 2026-10-01 09:19:49 +08:00
anonsaber e4a0a4b7db docs: translate Chinese document headings 2026-10-01 03:21:57 +08:00
anonsaber 7a27f7ff00 docs: add bilingual guides and callback setup in SPA 2026-10-01 02:36:03 +08:00