DataTalksClub / DataTalksClub/website

Epic: Preserve target-native course registration, enrollment, and learner flows

Open
#54 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accessibility admin auth courses data-migration epic frontend integration P0 security testing
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Product outcome

Adopted course registration becomes an account-owned, Cohort-isolated website workflow without losing learner history. A verified durable account and completed accounts.MemberProfile lead to one immutable Cohort registration, optional course-specific evidence, cohort-unique Enrollment, preserved preferences/progress/dashboard/calendar behavior, and target-native management through Studio and /api/v1/admin/.

#54 is the P0 coordination epic, not an engineer-sized change. Each child follows _docs/PROCESS.md independently. A groomed child remains blocked while any hard dependency is open; a source-only merge never implies activation, protected-data execution, owner approval, or completion of this epic.

Normative authority

  • _docs/PROCESS.md
  • _docs/specs/04-courses-and-cohorts.md
  • _docs/specs/06-studio-and-admin-api.md
  • _docs/specs/07-security-privacy-operations.md
  • _docs/specs/09-migration-rollout-roadmap.md
  • _docs/specs/10-verification-strategy.md
  • _docs/specs/open-decisions.md, resolved course-registration, privacy, high-risk, and MemberProfile decisions
  • _docs/architecture/app-boundaries.md
  • _docs/adoption/course-platform/upstream-sync.md

Child outcomes and ownership

  1. #242 — additive target-native CourseRegistration schema, mapping/quarantine, deterministic preflight/reconciliation source, and compatibility-preserving synthetic migration evidence. No writer or contraction.
  2. #243 — verified public registration, MemberProfile resume, atomic logical delivery intent/job creation, and explicit registration-to-Enrollment service.
  3. #244 — Cohort-isolated learner preferences, work/progress/score/certificate, dashboard, legacy-route, and calendar preservation.
  4. #245 — private Studio/admin API registration and Enrollment reads, metrics, masked/PII policy, and bounded export.
  5. #246 — target-native registration conversion and Enrollment correction/archive/restore commands and durable bulk operations.
  6. #286 — blocked owner decision and later product contract for pre-Cohort CourseInterest.
  7. #287 — blocked owner decision and future destructive legacy registration contract after the accepted rollback window and operational evidence.

#288 is a shared #54/#108 owner-decision dependency for one non-PII masked-member presentation. It is not implementation.

#59 retains broader course-management parity. #133 owns aggregate-only public signup totals. #64 owns the shared rights/retention/erasure system. #60 owns full production-like course migration/compatibility rehearsal. These boundaries are not permission to duplicate their work.

Exact delivery DAG

course/profile foundation:
  #224 -> #51
  (#51 + #231 + #234) -> #247 -> #248

registration source:
  #247 -> #242
  #286 owner decision -> later separately groomed CourseInterest work

public registration:
  (#242 + #248 + accepted ordinary #49 delivery slice) -> #243

learner preservation:
  (#230 + #242 + #248) -> #244
  accepted #243 conversion interface -> #244 final integration acceptance

management:
  #288 owner decision
  (#243 + #244 + #32 + #33 + #52 + #288) -> re-groom/engineer #245
  accepted #245 field/mask/operation policy -> #246

later destructive contract:
  (#242 deployed + target flows deployed + owner exit decision + selected clean-window,
   reconciliation, restore and rollback evidence) -> re-groom/engineer #287

Transitive relationships are not repeated as fake direct blockers: #231/#234 reach registration through #247/#248; #230 is a direct prerequisite only for #244's adopted peer-review preservation; #224 reaches downstream work through #51. #108 is a parent epic, not an implementation interface. #46 is event-only and is not a course dependency.

Decision, source, activation, and migration gates

Owner decisions
  • #286 retains the I1/I2/I3 CourseInterest identity/verification/retention choice. No option is approved; no CourseInterest model, route, evidence, conversion, or retention behavior may be inferred.
  • #287 retains the E1/E2/E3 legacy-exit choice. No elapsed time, green local test, or additive migration authorizes dropping a field, reader, writer, mapping, constraint, or rollback projection.
  • #288 retains the shared masked-member presentation choice. Until approval, #245 remains decision / needs grooming; engineering may not invent an email/name mask or reuse the event-provider helper.
  • #250 separately retains its Slack manual-resend interval/rate-cost choice; that does not become #54 product authority.
Source-only gates
  • #242 may begin only after accepted/integrated #247. It is additive and execution-disabled: synthetic migration/reconciliation evidence only, no public/profile/management adapter, production data, target-writer activation, final completeness constraint, or legacy contraction.
  • #243 may consume closed/integrated #242 without waiting for #286 or #287 because those outcomes are now separate. It also requires accepted #248 and the ordinary #49 delivery interface. The #49 recovery-only dependency on #284 is not a transitive blocker for ordinary registration delivery.
  • #244 consumes #230 and the accepted additive registration/profile foundations. It may characterize preservation separately, but final acceptance includes #243's conversion interface.
  • #245 is not engineer-ready until #288 is owner-approved and PM removes needs grooming. #246 cannot freeze or test a management candidate before accepted/integrated #245.
Activation and protected-data gates
  • A merged #242 source slice does not authorize production/protected-data reconciliation or non-null/unique activation across unresolved rows.
  • A #243 source candidate creates one logical website delivery intent/job only through #49. Production dispatch remains disabled until #50's separately approved purpose/sender cutover proves exactly one active sender and no Datamailer fallback.
  • #244 evidence feeds #60; it does not perform full migration, redirect/DNS cutover, or production-data rehearsal.
  • #245/#246 management activation requires the accepted #32/#33/#52 production identity, capability, object/field, reauthentication, audit, operation, and API mechanisms. No is_staff, superuser, legacy token, numeric-ID, or Django-admin shortcut is authority.
  • #287 is last and separately reviewed. It cannot start from source intent; it requires the selected owner gate and actual deployed evidence.

Parent acceptance

This epic completes only when all seven child outcomes are delivered or explicitly dispositioned by PM and the combined accepted state proves:

  • one verified-account-owned immutable Cohort registration identity under replay/concurrency, with independent later-Cohort registration and no nullable-Cohort substitute for interest;
  • completed MemberProfile ownership, minimized immutable profile snapshot, separate normalized-email/target/comment/privacy/optional-marketing evidence, and no anonymous or required/inferred marketing path;
  • one cohort-isolated Enrollment conversion with no lost or silently rewritten learner preference, submission, score, certificate, dashboard, calendar, or compatibility history;
  • Studio/admin API parity for the accepted read/export and command set over shared courses services and accepted capability/audit policies;
  • production-like forward/backward migration, reconciliation, quarantine, restore and rollback evidence without PII leakage;
  • one approved delivery intent/job after commit, no request-time network call, no direct Datamailer/SES path, and exactly one approved sender per purpose before activation;
  • focused/full Django, API/OpenAPI, migration, security, browser, accessibility and container evidence; independently inspected screenshots for every changed render; PM acceptance; focused commits/local no-ff merges; and exact-SHA green on-call results.

An owner may explicitly defer #286 or select #287's retain-indefinitely option; PM must record that disposition. Silence, a recommendation, or implementation convenience is not a decision.

Cross-cutting gates

  • Registration/profile/Enrollment/Studio/API/export/audit/log/metric/error/screenshot evidence exposes no unnecessary email, profile, comment, consent, certificate/work content, token, secret, provider data, or production record.
  • Public mutations are CSRF-safe, enumeration-resistant, bounded and replay-safe. Private surfaces are authorized before lookup, private/no-store/noindex, and absent from public serializers/search/sitemap.
  • Business mutations live in courses-owned application services shared by public views, Studio, API and jobs. Network side effects occur only after commit through durable jobs.
  • Expand/backfill/validate/activate/contract phases preserve IDs, timestamps, mappings, consent facts and #133 boundaries. Unknown, duplicate, ambiguous or mismatched state fails closed.
  • Ordinary public pages use templates/core/content_page.html; Studio uses its established private shell. Every render change receives graph-selected Playwright plus independent desktop/mobile inspection.
  • Every child records exact base/head, source pin, migration leaves, graph/plan digests and every rerun/reuse/not-applicable disposition. No required skip or pending screenshot can pass tester or PM gates.

Explicit non-goals

  • No accountless course registration, required/inferred marketing, campaign repointing of history, duplicate account, or cross-Cohort learner-data sharing.
  • No inferred CourseInterest contract and no inferred legacy-exit approval.
  • No duplication of #224/#51 Course/Cohort work, #247/#248 profile work, #133 aggregate import, #49/#50 delivery ownership, #32/#33/#52 management foundations, #60 rehearsal, #64 privacy system, or #59's unrelated management surface.
  • No copied staff-token/numeric-ID mutation APIs rejected by #235; no direct model adapter write, broad immutable snapshot PATCH, direct Datamailer/SES/provider call, or automatic resend after ambiguity.
  • No production import, protected-data access, workflow dispatch, provider mutation, secret handling, deployment, or lifecycle shortcut inside grooming/engineering/testing.

Lifecycle

Each child is groomed only when its own decisions, dependencies, acceptance, tests, browser/operations scenarios and activation boundary are exact. Engineer → independent tester/screenshots → PM acceptance → focused commit → local --no-ff merge/push → on-call applies independently. Child commits use Closes #N and may use Refs #54; source-only work never closes a decision/activation issue. PM closes #54 only after combined parent acceptance.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

This is a coordination epic rather than an engineer-sized change. Start with _docs/PROCESS.md and the listed course, Studio/API, security, migration, and verification specs, then review child issues #242–#248 and #286–#288 with their dependency gates. Done means all child outcomes are delivered or explicitly dispositioned and the parent acceptance evidence is complete.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, databases, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
10/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.