DataTalksClub / DataTalksClub/website
Epic: Add event registration and durable transactional email
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Normative authority:
_docs/specs/05-events-registration-email.md, for Event, registration, preference, Relay, and durable-delivery behavior;_docs/specs/06-studio-and-admin-api.md, for shared-service, capability, audit, and Studio/admin-API parity;_docs/specs/07-security-privacy-operations.md, for privacy, minimization, retention, redaction, and operational safety;_docs/specs/09-migration-rollout-roadmap.md#milestone-6---events-and-transactional-email, for the milestone boundary and exit gate; and_docs/PROCESS.md, for the issue lifecycle and evidence gates.
Outcome
Deliver the Milestone 6 Event and transactional-email capability:
- one database-owned Event lifecycle with canonical public pages, Person relationships, calendars, and management parity;
- OAuth-preferred or verified email-only accountless Event registration, protected operations, attendance, and lifecycle notifications;
- one website-owned logical
EmailDeliveryintent plus durable job committed with the business mutation; - Relay-owned immutable templates, rendering, sender policy, transport, attempts/events, suppression, callbacks, reconciliation, and authoritative status;
- specification-described Event, Course/Cohort, account, Slack, and marketing/newsletter purposes only when their owning domain trigger and recipient contract exist; and
- retirement of new Datamailer/direct-SES sending without introducing a fallback or dual sender.
Marketing/newsletter is in scope as a distinct optional category under resolved #22 and #227. Tracking pixels, Event capacity/waitlists, inferred consent, public attendee identity, and a website renderer/provider stack remain out of scope.
Authority boundary
This epic coordinates source delivery; it does not grant provider, credential, protected-data, production, DNS, sender/domain, broad-recipient, Datamailer queue, or email-send authority.
- Relay source acceptance is not a deployment receipt.
- A deployed development contract is not production authorization.
- The only live development action contemplated here is one separately authorized, allowlisted, one-recipient
coursescanary after every named safeguard passes. - #73 is a later full development rehearsal and cannot authorize or precede that canary.
- #74 alone coordinates separately authorized production activation, Datamailer freeze/drain/retirement, and cutover. Closing #6 must not be read as #73 or #74 acceptance.
Resolved product inputs
| Issue | Status | Authority supplied |
|---|---|---|
| #17 | Closed | OAuth-preferred Event registration with a verified email-only fallback; neither path creates a learner account |
| #18 | Closed | No Event capacity or waitlist in MVP |
| #19 | Closed | Legacy naive Event times use Europe/Berlin and fold=0 |
| #22 | Closed | Specification-described purposes do not need a second per-purpose approval ceremony; missing business triggers/routing still fail closed |
| #23 | Closed | Accepted privacy defaults and erasure policy; implementation and protected-data operations remain separate gates |
| #21 | Open coordination epic | Relay is the sole new template/render/transport owner; its #48-#50 implementation and operational gates remain incomplete |
Current phase ledger
“Accepted” below means independently tested, PM-accepted, committed, locally merged/pushed, and terminal-green at an exact interface identity. An issue body, local candidate, old CI run, or source commit alone is not accepted evidence.
| Phase | Owning issues | Current disposition |
|---|---|---|
| Source and Event core | #253 -> #40; green release/source baseline -> #289; then #40 + #289 -> #45 | #40 is back in needs grooming pending reproducible #253 output. #289 is groomed but on the clean-green-base start hold. #45 is groomed and blocked on accepted #40/#289. |
| Historical aggregate | #112 -> optional aggregate display in #45 | #112 has an uncommitted candidate on lifecycle hold and a separate protected-source HUMAN gate. Its exact N registered contract creates no native registration, recipient, attendance, or send authority. |
| Event registration and operations | #45 -> recorded #46/#227 accountless-preference interface; #45 + ordinary #49 + that interface -> #46; #45 + #46 -> #47 | #46 is blocked on the three named gates. #47 is groomed/non-sending and blocked on accepted #45/#46. |
| Relay templates | Relay #1 -> website #48 | Relay #1 and #48 are open. #48 also consumes accepted website identity/high-risk foundations #31-#33; no live test-send is part of template management. |
| Ordinary delivery | Relay #1 -> Relay #2 -> Relay #3; #48 + Relay #2/#3 + website #31-#33 -> #49 | Relay #1/#2/#3 and website #48/#49 remain open; no accepted exact deployed Relay commit/OpenAPI consumer receipt exists. |
| Restore-safe delivery | #264 -> #284 -> recovery-specific #49 | #264 and #284 are open. #284 is deliberately non-activating and supplies definitions/receipts only; it grants no retry, resend, worker, restore, or provider authority. |
| Recipient policy | ordinary #49 + accepted #46 identity -> #227 | #227 is groomed but blocked. Its product policy is authoritative; implementation must use the canonical website preference center and cannot create an address-based parallel identity. |
| Purpose integration and legacy retirement | accepted #46/#47/#227/#48/#49 plus accepted course/account/Slack triggers; #149 where peer/score notification semantics are selected -> #50 | #50 is groomed, HUMAN, and dependency-blocked. A purpose without an accepted owning trigger remains absent. #149 remains an owner-decision blocker only for the affected peer/score routes. |
| Controlled development canary | accepted #48/#49 + accepted automated/source #50 + accepted #60 send-disabled rehearsal + exact Relay deployment/OpenAPI/credential/callback/reconciliation/alarm/allowlist safeguards | Not authorized or ready. A separately authorized operator runs exactly one allowlisted courses recipient; PM then records #50 HUMAN acceptance. |
| Full development rehearsal | accepted #50 HUMAN identity -> #73 | #73 remains NO-GO. It is downstream of the canary and uses outbound-disabled or contract-faithful zero-write evidence; it is not a canary prerequisite or authority source. |
| Production activation | accepted #73 plus all release/privacy/restore/infra gates and separate explicit operator authority -> #74 | #74 remains NO-GO. No earlier issue, test, rehearsal, elapsed time, or epic closure grants this authority. |
Non-circular delivery DAG
#253 -> final #40 grooming -> #40 --+
green release/source -> #289 --------+-> #45
Relay #1 -> #48 -------------------------+
Relay #1 -> Relay #2 -> Relay #3 --------+-> #49 ordinary
#264 -> #284 ----------------------------+-> #49 recovery-specific
#45 -> record the #46/#227 accountless-preference interface
#45 + #49 ordinary + interface -> #46
#49 ordinary + #46 -> #227
#45 + #46 -> #47
#46 + #47 + #227 + #48 + #49
+ accepted course/account/Slack triggers
+ #149 disposition where applicable
-> #50 automated/source integration
-> separately authorized development canary
-> #50 HUMAN acceptance
-> #73 full development rehearsal
-> separately authorized #74 production activation
#46 does not wait for a completed #227 implementation: it waits for the shared interface decision, then #227 implementation consumes the accepted #46 identity. #47 creates non-sending domain triggers and is upstream of #50. #73 and #74 are consumers, not source-implementation prerequisites.
Epic completion gate
- Product decisions #17, #18, #19, #22, and #23 are resolved and recorded without inferring implementation or operational authority.
- Accepted #40/#289/#45 provide one Event model, canonical public and calendar behavior, Person relationships, lifecycle/revision/window services, and management parity.
- Accepted #46/#47 provide both registration paths, cancellation/reactivation, attendance/export, immutable non-sending Event triggers, abuse/privacy controls, and accessible browser flows.
- Relay #1/#2/#3 are accepted and deployed at an exact development commit/OpenAPI identity; #48/#49 pass consumer, concurrency, callback, reconciliation, ambiguity, suppression, redaction, and operator-recovery tests with no website renderer/provider fallback.
- Accepted #227 enforces Event and marketing/newsletter preferences through one canonical recipient service; suppressed optional mail creates no unintended delivery/job/provider work.
- Accepted automated/source #50 maps every included purpose exactly once from an accepted domain trigger to #49/Relay, leaves missing-owner purposes absent, makes new Datamailer/direct-SES send and requeue paths unreachable, and proves one-active-sender/rollback invariants.
- Studio/admin API parity, PII permissions, fault injection, accessibility, desktop/mobile browser evidence, independent tester PASS, and PM acceptance are complete for every rendered or protected workflow.
- The separately authorized one-recipient development
coursescanary passes with redacted evidence and PM records the immutable #50 HUMAN acceptance identity.
Epic closure proves the Milestone 6 exit gate only. It does not close, waive, or imply the Milestone 7 #73 rehearsal or Milestone 8 #74 production-cutover gates.
Direct implementation children
- #21 — Relay integration and Datamailer-retirement coordination
- #45 — Event lifecycle, public pages, people, and calendars
- #46 — verified accountless Event registration
- #47 — protected registration operations, attendance, exports, and non-sending notification triggers
- #48 — Relay-owned template management through Studio/admin API
- #49 — website delivery intent, durable job, Relay projection, callbacks, and reconciliation
- #50 — purpose wiring, send-disabled legacy migration, development canary, and Datamailer retirement evidence
Supporting issues such as #40, #112, #149, #227, #264, #284, and #289 are dependencies or nested children in their owning lanes; #73/#74 are downstream release phases. They are intentionally not presented as direct #6 implementation children.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with _docs/specs/05-events-registration-email.md, _docs/specs/06-studio-and-admin-api.md, and _docs/specs/09-migration-rollout-roadmap.md#milestone-6---events-and-transactional-email. Then read the direct implementation children #45-#50 and the current phase ledger to identify an unblocked lane. Done means all listed completion gates are accepted without granting the downstream #73 or #74 authority.
Written by the indexing model from the issue text.
Assessment
- Domain
- backend-api-design, databases, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 20/100