Review: Win/lose email notifications via Gmail (re-review)

review-832-2026-04-05-r2 Doc

review ready

Verdict: APPROVED

RE-REVIEW of board item #832. Previous review identified the need to specify googleapis npm package and make cross-repo deployment dependency explicit. Both refinements are now present in the issue body. Scope is solid and ready for agent dispatch.

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- winner-payout story
  • [x] Repo -- forgejo_admin/twitch-2k-wager
  • [x] User Story -- present with standard As/I want/So that
  • [x] Context -- thorough: identifies stubs, specifies googleapis not gmail-sdk, names dedicated Gmail account
  • [x] File Targets -- 4 targets across 2 repos, all specific
  • [x] Acceptance Criteria -- 4 criteria, all testable
  • [x] Test Expectations -- 3 expectations with concrete verification
  • [x] Constraints -- 4 constraints including cross-repo flag and email approval gate
  • [x] Checklist -- 6 items including both PRs
  • [x] Related -- references story slugs and related issue #65

Traceability

  • [x] story:winner-payout label -- present on board item
  • [ ] story note NOT VERIFIED -- no project-twitch-2k-wager project page exists in pal-e-docs. User stories section cannot be checked. [SCOPE] Create project page project-twitch-2k-wager with user-stories section.
  • [x] arch:dataflow-twitch-2k-wager label -- present on board item
  • [ ] arch note NOT VERIFIED -- search for arch-dataflow-twitch-2k-wager returned no results. [SCOPE] Create architecture note arch-dataflow-twitch-2k-wager. (Note: this same gap has been flagged on multiple prior reviews for this board -- it is a known project-level gap, not a blocker for this individual ticket.)
  • [x] Forgejo issue -- forgejo_admin/twitch-2k-wager#60, state: open

File Targets

  • [x] package.json -- verified: exists, currently has pg + stripe deps. googleapis not yet present (expected, this is the addition).
  • [x] src/lib/email.ts -- verified: exists, 185 lines. Line 156 has // TODO: Wire up Gmail OAuth transport exactly as described. sendWinnerEmail() and sendLoserEmail() are exported stubs that log in dev mode and return error when EMAIL_ENABLED=true. HTML templates already exist.
  • [x] src/routes/api/admin/result/+server.ts -- verified: exists. Currently does NOT import email functions (expected). handleChallengerWin and handleMarcusWin are the correct insertion points for email calls after status transitions.
  • [x] overlays/twitch-2k-wager/prod/deployment-patch.yaml (pal-e-deployments) -- verified: exists at ~/pal-e-deployments/overlays/twitch-2k-wager/prod/deployment-patch.yaml. Currently has DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, ADMIN_SECRET, KEYCLOAK_* env vars. Gmail env vars not yet present (expected).

Repo Placement

Correct. Issue is filed on forgejo_admin/twitch-2k-wager which is the primary repo. Cross-repo dependency on pal-e-deployments is explicitly called out in File Targets, Constraints, and Checklist (separate PR required). Two PRs needed: one for twitch-2k-wager, one for pal-e-deployments.

Dependencies

  • [x] Prerequisites section documents 4 manual blocking steps (Gmail account creation, OAuth app, refresh token, K8s secret). Correctly flagged as non-automatable. Agent cannot complete this ticket until Lucas completes the prerequisites.
  • [x] Board item #842 (issue #65, "asymmetric odds") also references email and shares the arch:dataflow-twitch-2k-wager label. The Related section in #60 correctly references #65 as a downstream consumer.
  • [x] No blockers in in_progress -- all board items are in backlog or done.

Acceptance Criteria

4 criteria, all verifiable:
  • "Winner gets email with payout claim link" -- verifiable in dev mode via console logs; real verification requires manual Gmail check per test expectations.
  • "Loser gets email with thanks message" -- same as above.
  • "Emails send via Gmail OAuth (googleapis npm package)" -- verifiable by code inspection + unit tests.
  • "Test emails to draneylucas@gmail.com verified on phone" -- requires Lucas manual verification. Correctly flagged in test expectations and aligns with feedback_never_email_without_approval.
Criteria are complete and testable. The manual verification gate is appropriate.

Blast Radius

Low. Email module is self-contained in src/lib/email.ts. Only one test file (src/lib/__tests__/email.test.ts) covers the module. The result endpoint modification adds email calls but does not change existing Stripe/payout logic. No other services in the platform use the googleapis npm package for email (basketball-api uses Python gmail-sdk). No cross-service impact. Rollback is straightforward (revert the email calls, remove env vars).

Decomposition Assessment

4 file targets across 2 repos, 4 acceptance criteria. Borderline but acceptable as a single agent pass:
  • The twitch-2k-wager changes are tightly coupled (email.ts transport + result endpoint import = one logical change).
  • The pal-e-deployments change is 3 env var additions to an existing patch file (trivial).
  • No independent subtasks that would benefit from parallelization -- the email transport must be wired before the endpoint can call it.
  • Estimated agent time: 3-4 minutes. Under the 5-minute threshold.
No decomposition needed. The two-PR requirement is inherent to cross-repo work, not a decomposition signal.

Recommendation

No blocking issues. Two [SCOPE] items are project-level gaps that pre-date this ticket and do not block dispatch:
  • [SCOPE] Create project page project-twitch-2k-wager with user-stories section (project-level gap).
  • [SCOPE] Create architecture note arch-dataflow-twitch-2k-wager (project-level gap, flagged on multiple prior reviews).
No [BODY], [LABEL], or [DECOMPOSE] recommendations. Issue body is well-refined after the first review cycle.