complete scheduled email digest reports (#154)#278
Merged
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finishes the digest feature whose foundation landed in #209 and shipped disabled since 1.0.0-beta. Closes #154.
What changed
Scheduling redesign. Per-org cron jobs registered at worker boot are replaced by a single static hourly
digest-dispatchcron that sweeps enableddigest_configs, matchesdelivery_hour/delivery_day_of_weekagainst the current UTC hour and enqueuesdigest-generationjobs. graphile-worker cron items are fixed once the runner starts, so per-org registration could never pick up config changes at runtime; the sweep keeps config CRUD live on both queue backends. Hour-keyed dedup jobKeys plus alast_sent_atdouble-fire guard (migration 053).Report sections. The generator grows from log volume only to five sections, each with a quiet empty state:
reservoir.topValueserror_groups.first_seen)detection_events(avoids continuous-aggregate staleness on the most recent day), plus open/investigating incident countmonitor_uptime_daily, omitted for orgs without monitorsHTML email.
generateDigestEmailjoins the sharedemail-templates.tscomponent library (inline CSS, escaped user-controlled strings, en-US number formatting) with the full report duplicated in the plaintext fallback. The base template footer gains anunsubscribeUrlvariant so digest recipients, who may have no account, get a one-click unsubscribe instead of the channel-settings link.Management API. Session-auth CRUD under
/api/v1/digests: config upsert/delete, recipient add/remove/resubscribe (resubscribe rotates the token so old email links cannot flip the state back). Membership for reads, owner/admin for writes, audit-logged asdigest.*, recipients capped by a newdigests.max_recipientscapability (default unlimited) with the canonical 4-case tests.Public unsubscribe.
POST /api/v1/digests/unsubscribe: the 32-byte random token is the credential, idempotent, returns a masked email. Consumed by the new frontend/unsubscribepage linked from the email footer.Frontend. New "Email Digests" settings page (schedule card with UTC delivery time, frequency and day-of-week; recipient management with subscribe state badges), nav entry under Notifications.
Worker. The 1.0.0-beta disable is removed; the dispatch cron registers at boot, so digests go out once this merges.
Testing
check:tenant-scopinggreen (new sweep/token sites carrytenant-scope-okmarkers),tsc --noEmitclean, svelte-check has no new errors, frontend unit suite green