DataTalksClub / DataTalksClub/website
D3.1 phase 3: Switch identity-window readers to accounts_ext.IdentityState
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Part of the D3.1 umbrella (#334): phase 3 of 6. Switches the identity-window and importer reader surface for normalized_email/identity_state to accounts_ext.IdentityState, refreshed against current main. Can run concurrently with phase 2 (#391) — both depend only on phase 1, not on each other.
Normative sources
| Source | What it governs |
|---|---|
community-base repo: docs/plan/phase-3.md D3.1; docs/03-playbooks.md P7 DTC step 3 |
Reader-migration expectation |
| Phase 1 issue (#390) | accounts_ext.IdentityState model this phase reads/writes |
_docs/audits/2026-09-07-backend-security-audit.md (BE-08, REL-04) |
Quarantine-revocation and claims-store behavior this phase must not regress |
Goal
Every read and write of normalized_email/identity_state goes through user.identity_state (the new accounts_ext.IdentityState OneToOne) instead of the CustomUser fields. Both stay in sync until phase 4 removes the CustomUser copy.
Scope: reader surface (verify each by reading current main — this table corrects and extends #334's original inventory)
| Area | Files | Note |
|---|---|---|
| Identity core | accounts/identity_inventory.py, accounts/identity_resolution.py, accounts/middleware.py, accounts/backends.py, accounts/auth.py, accounts/api.py, accounts/development_owner.py |
Unchanged from #334 |
| Events | events/models.py |
Unchanged from #334; events/identity.py (originally also listed) was deleted in commit 4c9b5239 ("Retire legacy event redirects, EventAlias, and events/identity.py", 2026-09-11) — its live resolve_*/canonical_*/create_event_identity primitives moved into events/models.py itself |
| Events (corrected path) | scripts/prod/registrant_import.py |
Was events/registrant_import.py in #334's original table; moved out of the events app to scripts/prod/ in the same 2026-09-11 commit. Update any reference to the old path. |
| Importers and prod scripts | accounts/services/cmp_learner_import.py, courses/services/cmp_learner_history_import.py, scripts/prod/account_reconciliation/, scripts/prod/import_cmp_learners.py, scripts/prod/legacy_zoomcamp/ |
Unchanged from #334 |
| New quarantine-enforcement call sites (added after #334's grooming; verified read-only, no field-literal change needed) | accounts/studio_authorization.py, accounts/studio_sessions.py, management_api/authentication.py |
These call accounts.identity_resolution.identity_state_eligible(user) rather than reading user.identity_state directly, so once identity_resolution.py itself is switched to user.identity_state (the new relation), no separate edit is needed here — confirm this with a grep in the PR rather than assuming it. |
Also required: the identity_inventory.py literal fallout already flagged in #334's own grooming comments (ACCOUNT_MANY_TO_MANY_RELATIONS's owner_model/through_table/user_field, ACCOUNT_RELATIONS's first entry) is a phase 5 (rename) concern, not this phase — do not pre-edit those literals here; they still say accounts.CustomUser correctly until the rename lands.
Non-goals
- No change to the ten
courses.LearnerProfilefields' readers (phase 2, independent). - No removal of
normalized_email/identity_state/the unique constraint fromCustomUser(phase 4). - No rename (phase 5), no AISL field additions (phase 6).
- No behavior change to quarantine enforcement, alias resolution, or the CMP claims store beyond the read/write relocation.
Dependencies
- Depends on: #390 (
accounts_ext.IdentityStatemust exist and be backfilled). - Blocks: #393.
Acceptance criteria
Django and integration
-
make django-check/make migrations-checkpass. -
make testpasses, includingaccounts/tests/test_identity_quarantine_revocation.pyand the CMP import/claims tests, unmodified in behavior. - A grep-backed inventory in the PR body lists every file that read/wrote
normalized_email/identity_statebefore this change (using the corrected table above) and confirms each now goes throughidentity_state. - Email login still authenticates through the Django test client (login, session, member page 200); quarantined accounts are still denied on session, legacy-token, and management-API paths with the same generic denial.
-
AccountIdentityAliassurvivor resolution and the CMP learner import's claims store (CmpLearnerClaim/CmpLearnerImportBinding, added since #334's original grooming) still pass their existing tests unmodified.
Repository and operations
- Versioned verification plan per
_docs/ci/change-selective-ci.mdrecorded in the engineer handoff.
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 phase 1 issue #390 and the listed identity files, especially accounts/identity_resolution.py, accounts/identity_inventory.py, accounts/auth.py, accounts/api.py, and events/models.py. Use a grep-backed inventory to trace normalized_email and identity_state reads and writes, including the corrected importer paths. Run make django-check, make migrations-check, make test, and the named quarantine-revocation and CMP tests; done means all readers use identity_state without changing quarantine, alias, or claims behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- authentication, backend, database
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100