Skip to content

Port CMP registration country and malformed-email fixes #231

Description

@alexeygrigorev

Outcome

Selectively adapt the safe country-inventory corrections and malformed-email regression coverage now present in DataTalksClub/course-management-platform main at immutable SHA 8a4d05221051748e3d95bf446c0d1cfa46dc111a. The public course-registration form gains the final accepted 215-name current country inventory and proves that 13 known malformed email shapes create no registration.

The website source pin remains 98a235283904b4ef9ad29e196298540756cf1bcc. This is a target-owned bug-fix overlay, not a source sync.

Normative authority

  • _docs/specs/04-courses-and-cohorts.md — registration ownership, consent, Course/Cohort isolation, and explicit historical reconciliation.
  • _docs/specs/07-security-privacy-operations.md — no ghost registration, privacy-safe validation/evidence, and no provider side effect on invalid input.
  • _docs/specs/09-migration-rollout-roadmap.md — historical values are reconciled only by their owning migration issue.
  • _docs/adoption/course-platform/upstream-sync.md and _docs/adoption/course-platform/source-pin.json — immutable selective review and explicit overlays.

Parent preservation issue: #54.

Current lifecycle and dispatch gate

GROOMED / P1 / OPERATIONAL HOLD. There is no current implementation candidate: the registered issue-231-cmp-registration-fixes branch is an unrelated old commit and must not be treated as #231 evidence. Engineering starts from an exact clean green origin/main after the active release-recovery lane, records the fresh base/head and current source pin, and generates a new plan/evidence envelope.

#231 is independent of #224, #51, #230, and #234. Its accepted inventory is a hard input to #247. #247 remains blocked until #224, #51, #231, and #234 are accepted and integrated by exact merge SHA.

Exact accepted country inventory

Apply only these source commits to the target-owned adopted file:

  • f8f408593ec869247da6a43ac754f67cf3779890 — Taiwan;
  • 165d8ab3c5ff5861278d3307dc514dc6decd8d65 — Hong Kong;
  • 3fea1b5cc515366861cf5469f732212ad04ce376 — Macau and Guam;
  • 7331930fa9bc997aefd27f0b0b71b08750fdfa90 — remove current selectable United States of America;
  • a43ff5f5c24b3cbef4fc81a5661bd1af6c3ae979 — Gibraltar, Cook Islands, British Virgin Islands, and U.S. Virgin Islands;
  • b6b7badc7c7434e8b5e52941c3748b660820f429 — Isle of Man.

The resulting courses/countries.txt must be byte-identical to that path at CMP 8a4d052: SHA-256 a030b43fb91b368428b759e559fda4c859807a01d2ebb5d946841339bb1baae8. Excluding the [Top Countries] presentation aliases, it contains exactly 215 unique current names in source order: Africa 54, North America 32, South America 14, Asia 50, Europe 48, and Oceania 17, with no duplicate name. Canonical region<TAB>name<LF> serialization in that order has SHA-256 ad0f41850372b0884ee0116dc069c6890c7cbf1e6c9ea8f839f7bfa21a68c005.

United States of America is not a current selectable value. This issue does not rewrite historical rows. #247 alone owns its explicitly frozen retired alias United States of America -> US for MemberProfile reconciliation and canonical reverse projection.

Malformed-email characterization

Adapt source commit 2494371e3c64a058204e5f0dde44ad04dca75b28 as target tests of the live public campaign form. Each exact input below returns HTTP 200 with Enter a valid email address. and creates zero CourseRegistration rows:

  1. testuser42examplecom
  2. testuser@examplecom
  3. testuser@@example.com
  4. testuser@middle@example.com
  5. testuser@e
  6. testuser@protonmailclone
  7. test,user@example.com
  8. test;user@example.com
  9. testuser@example.com_extra
  10. testuser@example.com au
  11. testuser@okbankid
  12. plainusername42
  13. not sure what to type here

If current Django/model validation already supplies this behavior, tests plus adoption evidence are sufficient; do not add a parallel email validator or broaden account normalization.

Scope

  • Update only the adopted country inventory and its focused helper/form/inventory characterizations needed to prove the exact contract above.
  • Add the 13 malformed-email public-form regressions and prove invalid input creates no row, profile mutation, consent record, delivery intent, Datamailer/Relay/provider call, or other side effect.
  • Preserve optional registration fields, required newsletter consent, anonymous and authenticated registration behavior, normalization/duplicate detection, current region derivation, profile projection, campaign/Cohort isolation, and accessible error rendering.
  • Record exact source SHAs and target-owned adaptation in adoption overlay evidence.

Explicitly rejected upstream behavior and non-goals

  • Do not port bulk registration create/API behavior from 4d8956343de06242ecd392a5e3e275b95485b05f, per-registration admin correction endpoints from 93fa698b9988f21feed0dd4af0563938d9951d9d, Datamailer documentation/behavior, production-version metadata, or deployment changes.
  • No historical-row rewrite, country guessing, fuzzy/casefold country match, ISO-code migration, new geography beyond the exact inventory, MemberProfile implementation, registration workflow redesign, account email normalization change, source-pin advance, protected/production data, provider/network action, or deployment.

Acceptance criteria

  • courses/countries.txt matches the exact final byte hash, 215-name region counts/order, uniqueness, and canonical serialization digest above.
  • Taiwan, Hong Kong, Macau, Gibraltar, Isle of Man, Guam, Cook Islands, British Virgin Islands, and U.S. Virgin Islands are current selectable values in their exact regions; United States of America is absent from current choices and United States remains canonical.
  • All 13 exact malformed emails return the bound form error and create no registration or other mutation/side effect.
  • Valid anonymous/authenticated registration, trimming/normalization, duplicate registration, required consent, optional fields, region derivation, profile projection, invalid country, and Course/Cohort isolation remain passing.
  • No model/data migration or historical-row rewrite is introduced; migration drift and PII/log/provider canaries pass.
  • Adoption evidence names all seven exact source commits, records the country/test overlay, rejects unrelated upstream APIs/operations, and leaves the pin unchanged.
  • Focused Django/adoption/security tests, full graph-selected verification, container checks, and any render-selected browser/screenshot evidence are terminal green on a fresh frozen candidate.
  • A separate tester recomputes the plan and verifies the exact inventory/form behavior; PM accepts only the fresh tester-final report.

Closure semantics

After fresh engineer, independent tester, and PM gates pass, use one focused commit whose body contains Closes #231, merge locally with --no-ff, push, and require on-call green observation. No production import or HUMAN remainder stays in #231. #247 consumes the exact accepted merge SHA and inventory digests; #247 owns the retired-alias/code mapping rather than reopening this issue.

Selective-port reconstruction order

From one clean green recovery base, #230, #231, and #234 may be prepared in parallel. Integrate them in issue order #230 -> #231 -> #234 because their adoption-ledger edits overlap. Before each later tester/PM gate, replay only that issue's bounded current-head changes onto the latest accepted base and regenerate the plan, manifest, graph, and evidence; keep three separate closure commits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Important follow-upbugSomething isn't workingcoursesArea: coursesintegrationArea: integrationtestingArea: testing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions