Support program-specific pathway schools in learner record sharing - #3802
Support program-specific pathway schools in learner record sharing#3802AhtishamShahid wants to merge 12 commits into
Conversation
The new import in courses/serializers/v1/programs.py shifted 8 pre-existing ORM001 violations down one line, and routing partner_schools through the courses.api helper removed the violation formerly at line 368. The baseline matches on exact line numbers, so it needed realigning. Edited surgically rather than regenerated: a full --generate-baseline run also dropped 24 stale entries for files this branch does not touch (v1/courses.py, v2/programs.py, v3/courses.py), which is unrelated churn.
OpenAPI ChangesShow/hide changesUnexpected changes? Ensure your branch is up-to-date with |
There was a problem hiding this comment.
Pull request overview
Adds support for program-specific “pathway school” assignments when learners share program records, including per-program recipient routing and validation, shipped behind a new feature flag (default OFF) to preserve existing behavior until rollout.
Changes:
- Introduces
PartnerSchoolProgramthrough model to link partner schools to programs with per-program recipient email(s) (andalt_emailstored for reference only). - Filters/validates learner-visible partner schools via a shared helper (
partner_schools_for_program) and rejects sharing to non-assigned schools when the flag is ON. - Updates email sending to support multiple recipients (one email per recipient) when the flag is ON, plus extensive test coverage and admin UI for assignment entry.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| main/features.py | Adds the ENABLE_PROGRAM_SPECIFIC_PATHWAY_SCHOOLS feature flag constant. |
| drf_lint_baseline.json | Updates baseline line references after serializer changes. |
| courses/views/v1/views_test.py | Adds endpoint-level tests for program-scoped validation and partner school filtering behavior. |
| courses/views/v1/init.py | Adds optional ?program= filtering to partner schools endpoint and enforces program-scoped school validation for record sharing. |
| courses/serializers/v1/programs.py | Routes partner school serialization through the shared helper to keep dropdown + validation consistent. |
| courses/serializers/v1/programs_test.py | Adds serializer tests for program-specific filtering, ordering, deduplication, and flag-off behavior. |
| courses/models.py | Adds PartnerSchoolProgram model, PartnerSchool↔Program M2M through it, alphabetical ordering, and recipient resolution helper. |
| courses/models_test.py | Adds unit tests for per-program recipient resolution, alt-email non-usage, and default ordering. |
| courses/migrations/0101_partnerschoolprogram.py | Creates the new through table, index, constraint, and ordering state change. |
| courses/mail_api.py | Adds feature-flag-gated per-program recipient routing and multi-recipient sending. |
| courses/mail_api_test.py | Adds mail routing tests for per-program, multi-recipient, alt-email exclusion, fallback, and flag-off behavior. |
| courses/factories.py | Adds PartnerSchoolProgramFactory for test data creation. |
| courses/api.py | Adds partner_schools_for_program helper with feature-flag gating and deduplication via distinct(). |
| courses/api_test.py | Adds API helper tests for flag-on filtering, flag-off behavior, and deduplication. |
| courses/admin.py | Adds admin inline and changelist enhancements for program assignments and filtering. |
| courses/admin_test.py | Adds admin tests ensuring inline presence and changelist filtering by program. |
| conftest.py | Defaults the new feature flag to OFF in tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
courses/models.py:2739
PartnerSchoolnow has a globalMeta.ordering = ["name"], which changes the default ordering for allPartnerSchool.objects...queries immediately (including whenENABLE_PROGRAM_SPECIFIC_PATHWAY_SCHOOLSis off). This appears to contradict the PR description’s claim that legacy behavior is preserved until the feature flag is enabled, and could affect any existing API/UI consuming partner schools where ordering was previously insertion/PK-based.
Consider either (a) gating ordering changes behind the feature flag (e.g., apply an explicit .order_by("name") only in the flagged code paths) or (b) updating the PR description/rollout expectations to acknowledge the behavior change if the new ordering is intentional.
class Meta:
ordering = ["name"]
A failure for one recipient aborted the loop, so remaining per-program recipients were never attempted and the log did not say which were skipped. Raised in review on PR #3802.
Hi , @pdpinch I need a second review on this from someone who can take a look at it from a product point of view. Thanks. |
|
How will you migrate existing data in mitxonline? This looks good to me from a product point of view. I'd like to take another look at the admin once it's on RC, but I think this will work well -- better than I expected, TBH. |
This requires manual data entry, i.e from the provided CSV files in the ticket to the Django admin. |
|
@pdpinch Please let me know if I should merge it or if there are any other concerns about it |
|
Yes, let's merge. Let me know when it's on RC so I can do some more review. Am I correct in understanding that we will need to recreate the existing data in production after this is deployed? |
…m-specific-pathway-schools # Conflicts: # courses/serializers/v1/programs.py # courses/serializers/v1/programs_test.py # drf_lint_baseline.json # main/features.py
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 35028761 | Triggered | Generic High Entropy Secret | aa87ed7 | ecommerce/fixtures.py | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.


Closes mitodl/hq#12321
This pull request introduces program-specific pathway school assignments, allowing each program to be linked to specific partner schools and enabling per-program recipient addresses for learner record sharing. The changes are carefully feature-flagged to preserve legacy behavior until the new logic is enabled. Major updates span the admin interface, API, mail delivery, and test coverage.
These changes lay the groundwork for program-specific pathway school sharing, while ensuring that no behavioral changes occur until the feature flag is enabled.
Feature flag
Flag:
mitxonline-12321-program-specific-pathway-schools, ships off.Two functions read it, both deliberate and both commented:
courses.api.partner_schools_for_program— the learner's dropdown and the share endpoint's validationcourses.mail_api.send_partner_school_sharing_message— recipient routingGating mail matters because assignments are entered before the flip. Without it, a mistyped address among ~122 hand-entered rows would receive a real learner record — name, email, grades — while the flag still claimed nothing had changed.
With the flag off, the set of schools shown and accepted is unchanged, and the email recipient is unchanged, whether or not any assignments have been entered.
pathway-schools-walkthrough.mp4
Rollout checklist
mitxonline-12321-program-specific-pathway-schoolsin PostHog, offPOSTHOG_ENABLED=True. If not, the flag falls back to theFEATURESenv var, and the name must beFEATURE_mitxonline-12321-program-specific-pathway-schools—get_features()strips theFEATURE_prefix and uses the remainder verbatim, so the hyphens are required and an underscored name silently never matches/admin/courses/partnerschool/if is_enabled(...)branches