Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesStaff NewsletterStaff Newsletter — QA Plan

Staff Newsletter — QA Plan

1. Rollout

#ScenarioExpected
1.1Deploy, org has never saved a configExactly one daily update at 06:00 UTC with the cancellation and follow-up sections; no other staff mail
1.2Deploy dayNo org receives the old retention digest — its job is gone, and the stale schedule is removed at boot
1.3Owner opens SettingsThe Updates tab is there with no flag set

2. Permissions

#ScenarioExpected
2.1Owner opens the tabRenders, all 7 rows
2.2Admin opens the tabRenders
2.3Coach navigates to /dashboard/settings/notificationsBounced to their first visible route
2.4Coach PATCHes the endpoint directly403, not 404
2.5Member of another org GETs this org’s config403

3. Cadence configuration

#ScenarioExpected
3.1Change one event, savePATCH body carries exactly that one key
3.2Save with nothing changedNo request; save bar hidden
3.3Open the retentionCaseAttention selectNo “Immediately” option
3.4PATCH {"retentionCaseAttention":"immediately"} by hand400, message names the event
3.5PATCH {"newLead":"hourly"}400 from class-validator
3.6Set an event to off explicitly, reloadStill off — a default must not switch it back on
3.7Save, then reloadValues persist; save bar hidden

4. Immediate sends

#ScenarioExpected
4.1newLead = immediately, a lead is createdOne mail per active owner/admin, subject names the lead
4.2newLead = daily, a lead is createdNo immediate mail; the lead appears in tomorrow’s digest
4.3newMember = immediately, a coach is addedNo mail
4.4newMember = immediately, a member activatesOne mail
4.5paymentFailed = immediately, first declineOne mail; amount formatted in each recipient’s locale
4.6Same subscription’s 3rd decline with newDebt = immediatelyBoth a paymentFailed and a newDebt mail
4.74th decline (balance grows)paymentFailed only — no second newDebt
4.8Debt cleared, then a new debt opensnewDebt fires again (debt_since was reset to null)
4.9The listener’s DB read failsError logged; the member’s cancellation / charge record is unaffected
4.10Member requests cancellation in-app, cancellationRequest = immediatelyOne mail; the member’s request itself still succeeds
4.11Staff record a notice for the same subscription afterwardsNo second immediate mail (kind promotes to notice)

5. Digests

#ScenarioExpected
5.1Daily tick, nothing happened in the windowNo mail, and no audit claim — so a later run can still report it
5.2Daily tick, two events have rowsOne mail with two sections, in catalog order
5.3Daily tick runs twiceSecond sends nothing
5.4Manual trigger races the scheduled tickOne sends; the other logs the held lock
5.5Weekly tick on Monday, then re-triggered WednesdaySecond skipped — same ISO week key
5.6Weekly tick spanning a new year (e.g. 2027-01-01)Key is 2026-W53; a Monday and a Sunday of one week share a key
5.7One org’s digest query throwsLogged; later orgs still get theirs
5.8retentionCaseAttention = dailyTwo sub-sections under their own headings — the split the old digest made, in this feature’s own friendlier wording
5.9An open case is both past SLA and in its final weekAppears in both sub-sections
5.10Org has an active admin but no ownerStill in orgIdsWithStaff(); the admin is mailed
5.11Suspended ownerNot mailed

6. Email rendering

Run pnpm email:preview and read staff-newsletter-* in all three locales.

#ScenarioExpected
6.1Hebrew recipientRTL throughout; sections and rows read correctly
6.2Money row in en vs ruBoth show 240; formatting differs — proof it is per recipient
6.3Person name contains <script>Escaped in the body
6.4Person name contains an apostropheLiteral in the subject, not &#39;
6.5Unresolvable personLocalized fallback, never the English “Unknown”
6.6Org has no logoLetterhead degrades as every other template does
6.7Org has no contact_emailNo Reply-To, no “just reply” footer line
6.8Section with zero rowsHeading omitted too

7. Regression — the retired retention digest

#ScenarioExpected
7.1Default configThe same three sections the retention digest carried arrive daily, in the newsletter’s structure
7.2Org sets cancellationRequest = offThe notices section disappears; the follow-up sections stay
7.3Org sets both retention events offNo staff mail about cancellations at all — the escalation audit rows and cancellation_review tasks still happen