You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(plans): close out welcome-notification (PR #99)
Closeout: flip to done, tick validations (8 new tests + 310/310 API
tests, lint + type-check clean), fill Notes (encodeURIComponent
defensive slug encoding, fire-and-forget spy timing works because
the promise is queued synchronously, no new env needed since
CFP_SITE_HOST already in place) + Follow-ups (Slack #welcome bump
when Slack DM lands, email verification reminder via bounce webhook,
A/B copy if marketing wants).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-[x] OAuth `create-fresh` path fires the notifier via spy assertion in github-oauth.test.ts — payload matches `{ email, fullName, slug }`.
92
+
-[x] Existing OAuth tests pass (15 pre-existing + 1 new = 16 in that file).
93
+
-[x] 310/310 API tests pass; `npm run type-check && npm run lint` clean.
93
94
94
95
## Risks / unknowns
95
96
@@ -100,8 +101,16 @@ Wiring-level test: the existing `github-oauth.test.ts` covers the `create-fresh`
100
101
101
102
## Notes
102
103
103
-
*(filled at done time)*
104
+
One-shot implementation across two commits (plan + impl/tests).
105
+
106
+
Surprises:
107
+
108
+
-**`encodeURIComponent` for the profile-link slug.** Slugs are `[a-z0-9-]` per the spec so they never need encoding today, but the template uses `encodeURIComponent` defensively. Test asserts that a hypothetical slug with spaces produces `name%20with%20spaces` in the href, which gives the template the same robustness as the existing interest/filled renderers.
109
+
-**Spy timing in the OAuth test.** Fire-and-forget worried me — would the spy assertion race the route handler's return? But `void notifier.notifyWelcomeOnSignup(...)` synchronously invokes the function (queuing the promise) before the next statement runs. By the time the route handler resolves and the test awaits the response, the spy has been called at least once. The Resend HTTPS send happens later in the promise chain; we don't await it.
110
+
-**No new env needed.** The notifier already had a `siteHost` from `CFP_SITE_HOST` (added in #82's email-notifier wiring); the welcome template reuses it for the profile/projects/help-wanted links. Zero new config.
104
111
105
112
## Follow-ups
106
113
107
-
*(filled at done time)*
114
+
-**Slack #welcome bump.** Once Slack DM lands (#95), the welcome path could DM the new user with a #welcome channel invite link. Out of scope here; tracked alongside the Slack notifier work.
115
+
-**Email verification reminder.** If the GitHub primary email later fails delivery (Resend bounces it), today the user has no recovery path beyond editing their profile. Tied to the bounce-webhook follow-up from #82.
116
+
-**A/B-able copy.** The body is currently hardcoded. If marketing ever wants to experiment, lift into a small key/value content table in a future plan. *Deferred* — premature for v1.
0 commit comments