01-projects/printables-product/reviews

Review-and-plan: lifecycle email/SMS (2026-09-29)

2026-09-29·review·status: gated-iterate-fixes-applied
printablesscribble-workslifecycleemailsms

2026-09-29 review-and-plan: lifecycle email and text messages

1. Reviewed

origin/main @ 1f3848c; pull request (PR) #373 branch 36b6cea; read-only gh run logs; queue, escalations, charter §2, rulings.

Delta since [[2026-09-22-lifecycle-email-sms]]: one commit (09-23 guide publish); lifecycle code untouched since 09-19 (diff from 222bf3a) except a generated catalog. Landed: queue.md:265. Stalled: :238, :294, all four 09-22 asks (escalations.md:405-410).

2. Findings (ranked)

  1. Daily-playset Worker unverified since 09-23. Release run 35887356007 failed post-activation; production unread since (#373 incident doc :30-34); workers/daily-playset/README.md:15 says "Verified 2026-09-10". escalations.md:445/:454 say merge #353 first, but it edits ci.yml, a daily input (daily.mjs:15): merging it selects a daily release (deploy-daily.yml:3-6) before the incident doc's §5 read (:118-120). Code-read only.
  2. This slot owns the broadcast sender check (02-sops/2026-09-14-scribble-works-email-sending-domains.md:44) and never ran it. First trigger (09-23) dry-ran, all variables empty (run 35887356191). GUIDES.md:398-399 suggests root hello@, barred by the rule (:24, :28) and unchecked (guides-broadcast.mjs:138-139). The footer claims "you opted in" (:111); no opt-in exists (GUIDES.md:355-356; 0017:49-52). No postal address (:102-116).
  3. Sign-in and invite send failures go unlogged. functions/api/auth/request.js:132 and invite.js:39 discard send results; mail.js:89-91 logs nothing. Sign-in doubles as password recovery (continue.js:2). The :238 plan misses them: report:email counts daily-playset only (email-report.mjs:69). Sanity Check shares the 1Password key item (workers/daily-playset/README.md:155; vault 08-tooling/2026-04-24-resend-setup.md:18); shared account inferred.

Still open: welcome email (09-15 #1); text-message schema block (09-22 #3); _dmarc p=none (DNS today); List-Unsubscribe (send.js:13-14); :255 sender bug (workers/feedback-intake/src/index.js:50).

3. Proposed queue.md changes

@@ :238 @@
 - [engineering, S, NEW 2026-09-15] Wire … cap …
+  - [engineering] RESCOPED 2026-09-29: also count sign-in/invite sends via a reason-only (no address) log.
@@ :294 @@
-- [engineering, S, NEW 2026-09-22] Re-check daily-playset live state …
+- ~~Re-check daily-playset live state~~ [product] FOLDED into R28 §5 (founder-gated).
@@ :295 @@
+- [engineering, S, NEW 2026-09-29] guides-broadcast.mjs: refuse non-`news.` senders; fix GUIDES.md:398-399; add the rail to ARCHITECTURE.md. Merge after R28 §5 (daily.mjs:15).

4. Decisions needed

  1. Authorize R28 §5 before the next merge; #353 and most open PRs are daily inputs (daily.mjs:15). Bear: a release's own prepare re-checks /health and pinned settings (daily-release.mjs:132-137).
  2. Before broadcasts: an opt-in source (build or drop the claim) and a postal address (15 United States Code 7704(a)(5)(A)(iii)). Enabling sends the 09-23 guide next deploy (guides-broadcast.mjs:178-185).
  3. Which Resend plan backs the shared key (email-plan.js:1 is a baseline).
  4. Carried: p=quarantine, per-kid pricing (#332). Default: stop re-asking nudges (ROADMAP.md:68) and Twilio (:109).