feat: add opt-in daily Discord reminders with quiet hours

This commit is contained in:
syntaxbullet
2026-09-04 18:45:42 +02:00
parent 16d92f171c
commit 1208e93953
22 changed files with 2367 additions and 9 deletions

View File

@@ -0,0 +1,22 @@
# Launch feature verification — September 4, 2026
| Feature | Implementation and verification |
| --- | --- |
| Historical check-ins | Calendar selection and date picker open dated count, checkbox, and task controls. Integration coverage changes a habit's method and corrects yesterday without changing today. Browser verified a saved historical count and refreshed calendar. |
| Account settings | Timezone changes refresh the dashboard; JSON exports include owned records without session credentials. Typed-confirmation deletion removes dependent records and revokes sessions. API tests cover ownership, Origin checks, confirmation, foreign keys, and another account remaining intact. Browser verified timezone persistence. |
| Discord sharing controls | SQLite reservations enforce one new post per user per minute and ten per channel per minute; duplicate checks remain safe. Tests cover cooldowns, channel quotas, allowlists, and rejected/uncertain delivery behavior. |
| Backup and recovery | Production snapshots, pre-migration snapshot, retention, optional replica directory, and fresh-path recovery. Tests restore committed WAL progress, revoke sessions, disable recovered reminders, verify replicas and retention, reject unavailable storage and existing destinations, and execute both CLIs. |
| Monitoring | Request IDs and sanitized structured error events; database/backup-aware health; independent monitor with sustained-failure and recovery transitions. Tests exercise a closed database and live HTTP probes; one-shot CLI passed against the disposable server. |
| Archive and restore | Dashboard archive action, history view, and restore. Integration and browser checks confirm a restored habit returns to today's dashboard while earlier completion remains intact. |
| Daily reminders | Opt-in settings, timezone/quiet hours, unfinished-only private messages, persistent daily reservations, rate-limit deferral, and delivery status. Tests cover concurrent workers, DST fall-back, opt-out during channel creation, uncertain sends, ownership, export, and deletion. Browser saved the selected time, delivered one message through the local stub, showed Delivered, and saved opt-out. |
Validation commands: `bun run typecheck`, `bun test`, `bun run test:smoke`, and
`git diff --check`. Browser checks used the in-memory preview on port 3107 and
verified desktop and narrow layouts (480px minimum layout viewport available in
the in-app browser), with no page-level horizontal overflow in settings.
Live Discord messages, production account deletion, and deployment were not
performed. Set the production origin, bot credentials/permissions, any sharing
allowlist, durable backup volume/replica, and independent monitor/log collection
when deploying. Off-machine storage and an external alert destination must be
provided by the deployment environment; their provisioning is outside the app.

View File

@@ -71,3 +71,14 @@ failures, and emits one `health_recovered` event on recovery. It stays quiet whi
state is unchanged. Run it under a process supervisor and route these JSON events
to your deployment platform's alerting/log collection. No external alert provider
or off-machine monitor is provisioned automatically by this repository.
## Reminder worker
The production process checks opt-in reminders every minute, with a lock preventing
overlapping runs within the process and transactional delivery reservations across
processes. A crash after reservation may leave a reminder unconfirmed; the worker
chooses not to resend it that day. Known rate-limit rejections defer until Discord's
retry deadline. Quiet hours and completion are checked again immediately before
posting. Recovery disables saved reminder opt-ins to avoid replaying notifications
from an old backup. Use the disposable preview and stubbed transport tests for QA;
real Discord delivery depends on the bot token, shared server, and user DM permissions.