Skip to content

feat: apply ADR 0040 — canonical MFE configuration endpoint#38797

Open
taimoor-ahmed-1 wants to merge 13 commits into
openedx:feat/axim-api_improvementsfrom
edly-io:feat/apply_canonical_mfe_config_adr
Open

feat: apply ADR 0040 — canonical MFE configuration endpoint#38797
taimoor-ahmed-1 wants to merge 13 commits into
openedx:feat/axim-api_improvementsfrom
edly-io:feat/apply_canonical_mfe_config_adr

Conversation

@taimoor-ahmed-1

Copy link
Copy Markdown
Contributor

Summary

Applies ADR 0040 — Canonical MFE Configuration Endpoint to its actual targets in `lms/djangoapps/mfe_config_api`.

Unlike the previous ADR ports (which targeted the 6 standardized contentstore/enrollment APIs), ADR 0040 is scoped to MFE configuration endpoint topology, not per-endpoint patterns. The actionable changes are confined to:

  • `lms/djangoapps/mfe_config_api/views.py` — the two configuration views
  • `lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst` — the partial-supersede note explicitly required by ADR 0040

3 focused commits.

# Commit Target
1 `feat(adr-0040)`: designate `FrontendSiteConfigView` as canonical `mfe_config_api/views.py`
2 `feat(adr-0040)`: mark `MFEConfigView` legacy + point at canonical successor same
3 `docs(adr-0040)`: mark ADR 0001 as partially superseded by ADR 0040 `mfe_config_api/docs/decisions/0001-mfe-config-api.rst`

ADR 0040 decisions and where they land in this PR

Decision Implementation in this PR
1. Canonical endpoint: `/api/frontend_site_config/v1/` is canonical for MFE / front-end runtime configuration Class summary on `FrontendSiteConfigView` restated as "Canonical MFE / front-end runtime configuration endpoint"; ADR-0040 section added
2. Legacy endpoint deprecation: `/api/mfe_config/v1` deprecated, target Verawood (2026-04) Strengthened `.. deprecated::` block on `MFEConfigView`; primary DEPR #37255 referenced (was previously only cross-linked via #37210)
3. No new configuration endpoints — extend via versioning Stated explicitly in `FrontendSiteConfigView` docstring
4. User-contextual data is NOT configuration Called out on both views as the most actionable forward-looking rule: `AllowAny` + `cache_page` makes per-user data unsafe via the shared cache, regardless of intent
5. Client request-count concerns solved client-side (BFF / batching) Out of scope; mentioned in the linked ADR for readers

ADR 0040 itself explicitly requires the partial-supersede note on ADR 0001 ("Per ADR convention, 0001 carries a one-line Superseded (partially) by ADR 0040 status note pointing here"); commit 3 implements that.

Behaviour

No code-behaviour changes anywhere — docstrings, ADR cross-links, and a single Status-line edit on ADR 0001. The DEPR ticket #37255 remains the authoritative tracker for actually removing `/api/mfe_config/v1`; this PR doesn't accelerate or alter that timeline.

Why this PR has 3 commits, not 6

The previous two ADR ports (#38773 for ADR 0036, #38796 for ADR 0034) ran 6 commits across the 6 standardized contentstore/enrollment APIs because those ADRs prescribed per-endpoint patterns (`?view=minimal`, removing `BearerAuthentication`, etc.). ADR 0040 prescribes endpoint topology (one canonical configuration surface, no per-user data on cached endpoints), so its actionable targets are the two configuration views themselves and the cross-link from ADR 0001 — three commits is the natural scope.

For completeness: I audited each of the 6 standardized APIs against ADR 0040. None of them are configuration endpoints (all are authenticated resource endpoints — exactly what ADR 0040 says you should have instead of stuffing per-user data into config endpoints), so the ADR has no prescriptive rule for them. I considered adding 6 docs-only "out of scope" audit commits to match the previous PR pattern, but the value would be pure bookkeeping; happy to add them if reviewers prefer.

Test plan

  • Existing test suite for `lms/djangoapps/mfe_config_api` still passes (`pytest lms/djangoapps/mfe_config_api/tests/ -v`) — no view-class changes, only docstrings, so no regression expected
  • Sphinx doc build (if run in CI) parses ADR 0001's new Status section cleanly
  • OpenAPI / Swagger UI now shows the deprecation marker on `MFEConfigView` and the canonical designation on `FrontendSiteConfigView` after schema regeneration

Related

🤖 Generated with Claude Code

taimoor-ahmed-1 and others added 13 commits June 22, 2026 18:46
Standardize HomePageCoursesView
Co-authored-by: Taimoor  Ahmed <taimoor.ahmed@A006-01711.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
)

* feat: apply ADRs to home v1 apis

* feat: apply ADR 0029 error envelope to home v3 viewset

Wires HomeViewSet (v3) into openedx/core/lib/api/exceptions's
standardized_error_exception_handler via a v3-local StandardizedErrorMixin
that overrides DRF's per-view get_exception_handler. Project-wide
EXCEPTION_HANDLER setting is intentionally left unchanged so v0/v1/v2
endpoints are unaffected.

* feat: refactor mixin so that both v3 and v4 can use it
…d APIs (openedx#38773)

* feat: apply ADR 0036 to Xblock v1 (?view=minimal)

Adds a ``?view=minimal`` query parameter on ``XblockViewSet.retrieve``
that filters the (tree-shaped) xblock response down to a small set of
structural fields — id, display_name, category, children, has_children,
studio_url — dropping heavy/contextual fields such as data, metadata,
fields, student_view_data, edited_on, published.

Default response shape is unchanged (full xblock payload) to avoid
breaking the existing Studio frontend. The pre-existing ``?fields=...``
query parameter retains its legacy "type of response" semantics
(?fields=graderType, ?fields=ancestorInfo, ?fields=customReadToken);
ADR 0036's CSV-subset interpretation is deferred to a future API
version to avoid breaking those callers.

Adds 4 regression tests covering: default response untouched, minimal
strips heavy fields, minimal keeps structural fields, minimal is a
no-op for non-dict response bodies (legacy ?fields=graderType path).

* feat: apply ADR 0036 to CourseHome v3 (?fields= on list action)

The v3 ``HomeViewSet.list`` action returns a wide ``StudioHomeSerializer``
payload with ~25 top-level keys (courses, archived_courses, libraries,
allowed_organizations, allowed_organizations_for_libraries, plus Studio
settings). Adds a ``?fields=`` query parameter so clients can request a
subset of those keys explicitly.

The flat-list ``courses`` and ``libraries`` actions are out of scope
(each returns a single-key dict wrapping a list of small items — no
nested or wide structure to filter).

Adds a shared ``apply_field_selection`` helper to ``v3/utils.py`` so
future v3 viewsets can opt into the same convention without
re-implementing it. Adds 2 regression tests: default keeps all keys,
``?fields=courses,libraries`` restricts to exactly those keys.

* docs: audit CourseHome v4 against ADR 0036 (out of scope)

Adds an ADR 0036 entry to ``HomeCoursesViewSet``'s compliance list
explicitly marking this endpoint as out of scope.

Rationale: the v4 home endpoint returns a flat paginated list
governed by ADR 0032 (DefaultPagination 7-field envelope). ADR 0036
excludes flat lists from its ``?view=`` / ``?depth=`` / minimal-by-default
requirements — those apply to tree-shaped responses or wide flat
objects with embedded sub-objects. Each course item is a thin 9-field
record with no nested children, no embedded sub-objects, and no tree
structure to bound.

Per-item ``?fields=`` subset filtering remains a possible follow-up
(would require a dynamic-fields serializer mixin and per-field schema
documentation) but is deferred to keep the v4 contract stable for the
existing Studio frontend.

* feat: apply ADR 0036 to Enrollment v2 (?view=minimal flattens course_details)

Each enrollment record returned by the v2 ``EnrollmentViewSet.list`` and
``EnrollmentRetrieveView.get`` actions embeds a full ``course_details``
sub-object (which itself includes a ``course_modes`` list and other
heavy course-overview fields). Server-to-server callers and AI agents
that only need to know which courses a user is enrolled in shouldn't
have to parse the embedded sub-object on every row.

Adds a ``?view=minimal`` query parameter on both actions that collapses
the embedded ``course_details`` to a single ``course_id`` string. The
enrollment-level fields (``created``, ``mode``, ``is_active``, ``user``)
are preserved. Default response shape is unchanged.

Adds 2 regression tests (mocked, MongoDB-free): default list keeps the
full shape, ``?view=minimal`` collapses each row's course_details to a
flat course_id and the heavy fields are dropped.

* feat: apply ADR 0036 to Course Detail v3 (?view=minimal + ?fields=)

The v3 ``CourseDetailsViewSet.retrieve`` action returns a wide
``CourseDetailsSerializer`` payload with ~40 top-level fields plus a
nested ``instructor_info`` sub-object (instructor names, bios, image
URLs) and a ``learning_info`` long-form list. The default full payload
is preserved; two new opt-in query parameters apply ADR 0036:

  * ``?view=minimal``  drops heavy fields (overview, syllabus,
    description, short_description, instructor_info, learning_info,
    banner_image_name / banner_image_asset_path, video_thumbnail
    assets, license) — leaving only identification (course_id, org,
    run, title, subtitle, language), schedule (start_date, end_date,
    enrollment_start, enrollment_end, certificate_available_date),
    and flags (self_paced, certificates_display_behavior, has_changes).

  * ``?fields=a,b,c``  keeps an explicit CSV subset of top-level keys.
    Composes with ``?view=minimal`` — the preset is applied first,
    then the explicit subset.

Reuses ``apply_field_selection`` from ``v3/utils.py`` (introduced in
the CourseHome v3 commit) so the convention is consistent across v3.

Adds 3 regression tests (mocked, MongoDB-free): default keeps all
fields, ?view=minimal drops the heavy/embedded ones and keeps
identification/schedule/flags, ?fields=course_id,title restricts to
exactly those keys.

* docs: audit AuthorGrading v3 against ADR 0036 (largely out of scope)

Adds an ADR 0036 entry to ``AuthoringGradingViewSet``'s compliance list.

Rationale: the v3 grading response is a single top-level ``graders``
list of small fixed-shape objects (type, min_count, drop_count,
short_label, weight, id) — no tree nesting, no embedded sub-objects,
no ``children`` field, no wide flat object. ``?view=minimal`` and
``?fields=`` would have no fields to drop; the only ADR 0036 concern
that applies is anti-pattern #3 (unbounded child list).

In practice each course has ≤8 graders (Homework, Lab, Exam, etc.)
and the update flow is exercised only by course-authoring staff,
so the real-world payload is always small. The hard cap is enforced
upstream by ``CourseGradingModel.update_from_json``; documented as a
note rather than re-implemented at the view layer.
…fig endpoint

Per ADR 0040 (Canonical MFE Configuration Endpoint),
``/api/frontend_site_config/v1/`` (``FrontendSiteConfigView``) is the
canonical endpoint for MFE / front-end runtime configuration, aligned
with frontend-base's ``SiteConfig`` format under OEP-65. New consumers
MUST target it; the sibling ``/api/mfe_config/v1`` (``MFEConfigView``,
ADR 0001) is legacy and on the OEP-21 DEPR path (openedx#37255, targeting
Verawood 2026-04).

Docstring updates:
  * Restated as "Canonical MFE / front-end runtime configuration
    endpoint" in the class summary.
  * Added an explicit ADR 0040 section with three decisions: canonical
    designation, no-per-user-data rule, no-new-config-endpoints rule.
  * Linked the ADR file path so the relationship is discoverable from
    the source.

The no-per-user-data rule is the most actionable piece going forward:
this view declares ``permission_classes = [AllowAny]`` and is wrapped
in ``cache_page``, so any per-user field added to this payload would
leak across users via the shared cache. User roles, enrollments, and
course-specific permissions are first-class resources, not
configuration.

No code-behaviour change — docstring annotations only.
ADR 0040 designates ``/api/frontend_site_config/v1/``
(``FrontendSiteConfigView``) as the canonical MFE configuration endpoint
and partially supersedes ADR 0001 for that role.

Updated ``MFEConfigView``'s docstring to:
  * Restate it as the "Legacy" endpoint in the class summary (was
    "Provides an API endpoint to get the MFE configuration ...", which
    didn't carry any deprecation signal at the summary level).
  * Add an explicit ``.. deprecated::`` block pointing at
    ``FrontendSiteConfigView`` as the replacement.
  * Reference the primary DEPR ticket openedx#37255 (the current docstring
    mentioned only the cross-linked openedx#37210) and the Verawood (2026-04)
    target release.
  * Carry the same no-per-user-data note as the canonical endpoint:
    ``AllowAny`` + ``cache_page`` makes per-user fields unsafe via the
    shared cache.
  * Link to the ADR 0040 file path so the relationship is discoverable
    from the source.

No code-behaviour change — docstring annotations only. The DEPR ticket
(openedx#37255) remains the authoritative removal tracker; this commit just
makes the relationship visible from the legacy view itself.
ADR 0040 (Canonical MFE Configuration Endpoint) explicitly instructs:

  > Per ADR convention, 0001 carries a one-line "Superseded (partially)
  > by ADR 0040" status note pointing here, so the relationship is
  > discoverable from either direction.

Updated ADR 0001's Status section accordingly with a relative link to
ADR 0040 and a short summary of which parts of 0001 are superseded
(the endpoint-of-record role) vs. which remain in effect (runtime-vs-
build rationale, no-auth posture, cache behaviour). Also referenced the
OEP-21 DEPR ticket openedx#37255 and the Verawood (2026-04) target release for
``/api/mfe_config/v1`` removal.

No code change. Pure documentation cross-linking so a reader of
ADR 0001 lands on ADR 0040 (the canonical reference for the
configuration-endpoint topology going forward).
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @taimoor-ahmed-1!

This repository is currently maintained by @openedx/wg-maintenance-openedx-platform.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Jun 23, 2026
@github-project-automation github-project-automation Bot moved this to Needs Triage in Contributions Jun 23, 2026
@mphilbrick211 mphilbrick211 moved this from Needs Triage to Ready for Review in Contributions Jun 23, 2026
@Faraz32123 Faraz32123 force-pushed the feat/axim-api_improvements branch from 0147d14 to 3d7b57d Compare June 24, 2026 11:57
@Faraz32123 Faraz32123 requested a review from a team as a code owner June 24, 2026 11:57
@Faraz32123 Faraz32123 force-pushed the feat/axim-api_improvements branch 2 times, most recently from cc04d6b to b1c8acb Compare June 24, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Ready for Review

Development

Successfully merging this pull request may close these issues.

4 participants