DataTalksClub / DataTalksClub/website
Remove request-time certificate notification fanout
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Parent integration epic: #50. Upstream adoption coordination: #149.
PM disposition
GROOMED / P1 / DEPENDENCY-BLOCKED. Do not dispatch engineering yet.
Fresh CMP evidence is unchanged: DataTalksClub/course-management-platform main is
8a4d05221051748e3d95bf446c0d1cfa46dc111a, 30 commits ahead of the website pin
98a235283904b4ef9ad29e196298540756cf1bcc. The applicable source packet remains
da2c7ae6e11acc860fd98c6832e674d3f483785f (Split certificate upload and notification into separate endpoints). The later CMP certificate-normalization packet
77906c7acdf9a68adb0180e0dd70443d9aa3220f is owned separately by #234. This issue does not move
the global CMP pin.
The source diagnosis applies: the copied compatibility bulk-certificate path schedules one
transaction.on_commit Datamailer call per first-time certificate. With Datamailer configured, a
large request can perform unbounded synchronous network fanout after the database commit and exceed
the request-worker timeout.
The source remedy is not target-compatible. CMP makes upload return a notify flag and adds a
caller-driven POST .../certificates/notify endpoint that still performs one synchronous
Datamailer call. The website must not expose that endpoint, ask a caller to orchestrate delivery,
call Datamailer/SES/Relay from a request or on_commit callback, or treat a successful upload as
proof that notification happened.
Normative authority
_docs/specs/04-courses-and-cohorts.md— cohort-owned certificate lifecycle, preserved
compatibility behavior, shared services, and send-disabled Datamailer history._docs/specs/05-events-registration-email.md— the certificate purpose catalog, immutable Relay
routing, atomic business state + one logicalEmailDelivery+ one durable job, and leased
after-commit Relay submission._docs/specs/06-studio-and-admin-api.md— certificate operations use shared application services
with authorization, idempotency, audit, and adapter parity._docs/specs/07-security-privacy-operations.md— redaction, bounded retries, no direct provider or
Datamailer fallback, and safe failure behavior._docs/adoption/course-platform/upstream-sync.mdand
_docs/adoption/course-platform/source-pin.json— selective review only; no automatic sync or pin
movement.
Target-native upload/delivery split
- The compatibility upload adapter calls the accepted #58 certificate application service. #58
owns certificate issue/update/revoke/reissue state, version identity, first-issue semantics,
cohort isolation, and the immutable message-trigger-ready scalar contract. - The bounded certificate-purpose adapter contributed to #50 consumes that accepted trigger and
calls #49's accepted atomic intent/job interface inside the same owning database transaction.
The certificate transition, exactly one logical delivery intent, and exactly one durable job
commit together or all roll back. - The request returns the existing bounded per-item compatibility result after persistence. It
neither sends nor exposes a second notification command. A leased/fenced worker calls Relay only
after commit using the immutable template/version and stable certificate-purpose idempotency
inputs. - Relay failure leaves committed certificate state and durable work observable. Exact replay
converges; an uncertain acknowledgement becomesambiguousand is never automatically resent.
This issue is the bounded compatibility/certificate-routing slice under #50. It must consume #58
and #49; it must not recreate their domain, job, transport, preference, or status rules. Its focused
commit closes #233 and references #50. #50 remains open for other purposes, Datamailer inventory and
migration, operational safeguards, HUMAN canary, and retirement.
Scope after dependencies are accepted
- Replace the copied bulk endpoint's injected Datamailer callback and per-enrollment
on_commit
fanout with the accepted #58 + #49 application-service composition. - Register only the certificate issue/revoke/reissue purpose mapping owned by this bounded #50
slice, using #48's accepted immutable template/version boundary and the recipient-preference rule
supplied by the accepted delivery contract. - Preserve the compatibility route, authentication, input order/correlation, validation, and
per-item success/error shape unless an accepted #58 contract explicitly versions a change. - Make exact replay, duplicate batch rows, concurrent requests, replacement, revoke, and reissue
follow #58's certificate version semantics and #49's stable idempotency interface. - Remove runtime reachability of the certificate-specific Datamailer callback from this request
path; retain legacy artifacts only as send-disabled history/characterization input owned by #50. - Record source SHA
da2c7ae6e11acc860fd98c6832e674d3f483785fand the selective target adaptation in the adoption
overlay without moving the global pin.
Direct dependencies and interfaces
- #58: accepted certificate application-service symbol, transaction boundary, certificate
version/transition identity, first-issue/revoke/reissue semantics, authorization/audit contract,
and message-trigger-ready scalar payload. - #48: accepted immutable Relay certificate template key/version and sender/routing consumer
boundary. #233 does not author or render a template. - #49 ordinary delivery: accepted callable service/DTO for atomically creating or resolving one
logicalEmailDeliveryplus durable job, stable idempotency/request-hash inputs, preference
suppression result, redacted projection, ambiguity, and safe retry/reconciliation behavior.
Relay #1 is transitive through #48. Relay #2/#3 and accepted website #31/#32/#33 foundations are
transitive through #49. #22, #23, and #124 are accepted policy/specification inputs, not open
dependencies. #284 governs restore-generation reconciliation and is not a prerequisite for this
ordinary certificate-delivery slice; it remains required before #49/#50 can claim complete recovery
behavior. #234 coordinates normalized collision-safe lookup and must be replayed in integration
order if its accepted files overlap, but it supplies no model or interface required by this issue
and is not a hard dependency.
Before dispatch, PM must freeze the exact accepted #58/#48/#49 merge SHAs, service symbols and DTO
schemas, certificate-purpose route/template/version, idempotency/version tuple, preference result,
source pin, migration leaves, and overlapping #234 disposition. Until then this issue is blocked,
not raw intake.
No independent source-only runtime lane
There is no safe pre-dependency runtime subset:
- porting upload-only behavior would commit certificates while silently losing durable notification
work; - porting CMP's
/certificates/notifyendpoint would preserve forbidden request-time Datamailer
execution and caller-managed retries; - returning a
notifyflag is not an intent, job, recovery record, or delivery receipt; - adding a temporary table/outbox would invent the #49 interface and create migration debt; and
- disabling only this sender without a durable replacement would change certificate communication
semantics without an accepted product failure policy.
The deterministic static Datamailer source inventory is already owned by #290 under #50. It may
proceed independently but is not #233 implementation or acceptance evidence.
Non-goals
- No synchronous
/certificates/notifyport, caller-side notification loop, direct Relay,
Datamailer, SES, provider, oron_commitnetwork call. - No certificate eligibility, scoring, lifecycle, version, revoke/reissue, account resolution, or
template-authoring redesign; consume #58, #234 where integrated, and #48. - No second delivery/outbox/status model, local renderer, manual resend UI, production credential,
live recipient, canary, deployment, source-pin advance, or broad #50 retirement work. - No claim that source code, tests, or a Relay deployment grants protected/provider authority.
Acceptance criteria after unblocking
- The compatibility bulk-certificate request and every transaction/model/
on_commitcallback
it invokes make zero Relay, Datamailer, SES, or other notification network calls. - Every accepted #58 certificate transition that requires a message atomically commits exactly
one #49 logical intent and durable job; rollback creates neither certificate state nor delivery
work. - Exact replay, duplicate rows, concurrent requests, replacements, revoke, and reissue converge
according to the accepted certificate-version and delivery-idempotency contracts without duplicate
first-issue work. - Mixed valid/invalid input preserves stable indexes and safe per-item results; valid state and
corresponding delivery work commit consistently, while database failure rolls the transaction
back. - The compatibility API exposes no notification endpoint or caller-managed
notifyworkflow.
Only a leased/fenced worker contacts Relay after commit. - Preference suppression, Relay outage, timeout/response loss, ambiguity, reconciliation, and
job failure preserve certificate state and expose only the accepted redacted status/reason. - Certificate-specific Datamailer submit/requeue reachability is absent from the request path;
no SES/Datamailer fallback or second sender can activate. - Existing upload/export/learner compatibility and #234's accepted lookup behavior remain
passing. Adoption evidence names source SHA
da2c7ae6e11acc860fd98c6832e674d3f483785fand leaves the global pin unchanged. - Focused Django/API/job tests cover a large synthetic cohort, first issue/replacement/revoke/
reissue, replay/concurrency/rollback, mixed batches, preference suppression, Relay outage/
ambiguity, and outbound-network denial. Browser screenshots arenot_applicableonly if the
independently recomputed change graph proves no rendered impact.
Lifecycle
After #58, #48, and ordinary #49 are accepted and integrated, PM refreshes the frozen interfaces and
dispatches one isolated current-main engineer lane. Engineering remains uncommitted; a separate
tester recomputes the plan and verifies every criterion; PM accepts only a terminal tester PASS;
then the focused commit uses Closes #233 and Refs #50, followed by local --no-ff merge, push,
and on-call observation. No pull request and no live email/provider access.
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
Before implementation, read the listed _docs/specs/04-courses-and-cohorts.md through 07-security-privacy-operations.md and wait for frozen #58, #48, and #49 interfaces. Then inspect the compatibility bulk-certificate endpoint and focused Django/API/job tests. Done means the request path has no notification network calls and the acceptance tests pass after atomic certificate and delivery-job behavior is integrated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- api, backend, databases, testing-qa
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 18/100