Signup nudge eligibility treats subscribed-then-unsubscribed members as never subscribed
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 35/100
Rechercherichtung
Start with app/services/signup_nudge_email_service.rb#never_subscribed and app/controllers/subscriptions_controller.rb#destroy, then inspect the subscription and activity data model. Confirm which persistence direction maintainers choose before implementing it. Done means a member who subscribed and later unsubscribed is not treated as never subscribed, while group-specific eligibility and followup behavior remain correct.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
SignupNudgeEmailService#never_subscribed defines eligibility as "has no row in subscriptions". But SubscriptionsController#destroy deletes the subscription row when a member unsubscribes from a chapter group. A member who subscribed and later left is therefore indistinguishable from a member who never subscribed at all — and becomes nudge-eligible again.
Real production case
Member 31302 (dump of 2026-09-24), full timeline from activities + workshop_invitations:
| Time (2026-09, UTC) | Event |
|---|---|
| 09-02 11:16 | Signs up |
| 09-02 11:18 | RSVPs as Coach (2 minutes after signup) |
| 09-09 18:30 | Attends London workshop |
| 09-17 09:16 | RSVPs to the next London workshop |
| 09-17 09:34 | Unsubscribes from London Coaches group (subscription.removed activity, id 569) |
| 09-17 13:04 | Receives a "Let's get you connected with codebar!" signup nudge |
Four hours after choosing to leave the chapter group, this actively engaged coach got an email whose premise is "you never connected with codebar". The unsubscribe made him eligible again; the nudge arrived same-day.
Two compounding facts:
subscription.createdactivity tracking only started 2026-09-13 (65 events / 41 members) andsubscription.removedon 2026-09-14 (61 events / 45 members). His subscription predates tracking, so its removal left no "was subscribed" evidence — only the removal event exists.- In the dump, 37 of the 45 members with a tracked unsubscribe now have zero subscription rows — i.e. the nudge service currently classifies all 37 as "never subscribed". One of them is inside the current nudge window and not banned.
Why this is separate from #2919
The daily duplicate-send bug (#2919, .merge clobbering the delivery anti-join) causes the same member to be emailed repeatedly, but fixing it does not fix this: a subscribe-then-unsubscribe member with no prior nudge is genuinely selected by the corrected query. The eligibility rule itself needs to account for unsubscribes.
Scope of the wrongness
- Messaging mismatch: the nudge copy assumes a dormant lurker; unsubscribers made an active choice to leave. Re-pitching them risks reading as ignoring their opt-out.
- Same-day turnarounds are possible for any churn event shortly before the daily 12:00 UTC run, as the timeline shows.
- The unsubscribe may have been from one group only (e.g. left Coaches, still interested in Students) — naive "any unsubscribe = never eligible" would over-correct. Today's schema can't tell, because the row is gone.
Possible directions (for discussion)
- Tombstone subscriptions — soft-delete/discards (
discarded_at) or astatecolumn, so history survives; eligibility then reads "never had an active subscription". Most robust; biggest change. - Eligibility excludes members with a
subscription.removedactivity — cheap, but blind to all pre-2026-09-13 subscriptions, and depends on activity rows never being cleaned (nothing prunesactivitiestoday, but nothing guarantees that). - Member-level flag set on unsubscribe (mirroring the
received_student/coach_welcome_emailpattern) — simple, but loses which group/chapter was left.
Happy to take whichever direction maintainers prefer; option 1 is the only one that also preserves the data for the followup email logic (which keys off member_email_deliveries.created_at and would otherwise send a followup to someone who already left).
Environment
app/services/signup_nudge_email_service.rb(never_subscribed) andapp/controllers/subscriptions_controller.rb#destroyata50b5214- Rails 8.1 / Ruby 4.0, verified against
codebar_production_dump2026-09-24
- Vorherrschende Sprache
- Ruby
- Sterne
- 106
- Forks
- 208
- Ø Merge
- 18 Std. 3 Min.
- Gemergte PRs (30 T.)
- 74
Entwicklungsumgebung
- Enthält ein Dockerfile oder eine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus codebar/planner
-
DashboardQuery eager-loads workshop_host with :sponsors in one join (same host-loss trap as #2975)Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
enhancement
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
Maintainer antworten meist innerhalb von 1 Tag
-
Dual Invitiation issueEvtl. vergeben @mroderick hat das vor 10 Tagen übernommen. Offen
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 42/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 28/100
codebar/planner#3008 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in codebar/planner
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
up-for-grabs/up-for-grabs.net#6330 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 72/100
TheOdinProject/curriculum#31490 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
hotwired/turbo-rails#791 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
FinanceFlash/unvibecode#273 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
Maintainer antworten meist innerhalb von 1 Tag