• v1.0.0 — pacing-safe fan-out, ETA preview, redesigned tabs

    yiekheng released this 2026-05-10 15:43:53 +08:00 | 74 commits to master since this release

    Phase 1 (concurrency, shipped):

    • Per-account async mutex serialises same-account fan-outs.
    • Per-account token-bucket rate limiter (default 40 msg/min).
    • MediaUploadCache uploads each unique mediaId once per run.
    • pg-boss localConcurrency=8 lets different-account reminders fire
      in parallel.
    • fire-reminder.ts rewritten for bulk-loaded targets, bounded
      per-group concurrency, and 200..499ms part jitter (replaces the
      rigid 1.5s sleep).

    Phase 2 (ETA preview + delivery deadline, shipped):

    • Reminders gain an optional 'pause sending by' deadline hour.
    • HourSelect splits hour and AM/PM into two side-by-side menus.
    • Wizard Review shows a green "Fits before deadline" or amber
      "Likely to pause" pill above the Schedule button.
    • windowEndAt helper lives in @cmbot/shared (and on its own subpath
      export so the client bundle doesn't pull in the rrule shim).

    Tab redesign:

    • PageShell + EmptyState components unify chrome and empty surfaces.
    • Mobile floating action button replaces the wasted top button row.
    • Accounts list rows swipe — right reveals Pair/Unpair, left
      reveals Groups + Delete.
    • Account label editable via /accounts/[id]/edit/label.
    • Disconnected accounts greyed out and unclickable in the new
      reminder wizard.

    Tests: 345 web, 39 shared, 54 bot — 438 total, all green.

    Phase 3 (window enforcement, paused/resume, paused notification,
    auto-resume) is queued and not in this release.

    Downloads