Skip to content

[API] Home Page Data — schema deprecation of GET /api/contentstore/v1/home - #39263

Open
Faraz32123 wants to merge 2 commits into
masterfrom
feat/fc-0118-home-page-data-schema-deprecation
Open

Faraz32123 wants to merge 2 commits into
masterfrom
feat/fc-0118-home-page-data-schema-deprecation

Conversation

@Faraz32123

@Faraz32123 Faraz32123 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Marks GET /api/contentstore/v1/home as deprecated: true in the published CMS schema by adding it to SUPERSEDED_PATHS in cms/lib/spectacular.py. The conforming replacement (GET /api/authoring/v3/home/) already exists and is tagged for SDK generation (@extend_schema(tags=["openedx-platform-sdk"])).

No view, serializer, or URL file is changed. The v1 endpoint remains live and its contract is unchanged. Callers who have not yet migrated are unaffected at runtime; they will see the deprecated: true flag in schema tooling.

Why in-place, not a new version: a conforming HomeViewSet already exists at /api/authoring/v3/home/. Adding deprecated: true to the schema of the superseded endpoint is a schema-only change and requires no new version directory under ADR 0037.

Tracking: #39068 · DEPR umbrella: #39128 · FC-0118

Change table

Commit Endpoint(s) Legacy behaviour kept New behaviour
feat: mark GET /api/contentstore/v1/home deprecated in schema GET /api/contentstore/v1/home Path live, response shape unchanged Schema gains deprecated: true; sibling /home/libraries is unaffected

ADRs applied

  • 0025 serializers — n/a: v1 is frozen; v3 already declares serializer_class = StudioHomeSerializer; no new serializer declaration in this pass
  • 0026 permissions — n/a: v1 already has permission_classes = (IsAuthenticated,) with no inline checks; v3 is conforming; no change needed
  • 0027 schema / docs — n/a: no @extend_schema annotation added or changed; the deprecated: true flag is set by the post-processing hook, not by annotation
  • 0028 viewsets — n/a: v1 is frozen as APIView; v3 HomeViewSet is the conforming view; no new ViewSet written
  • 0029 errors — n/a: v1 legacy error shape is frozen; v3 already has StandardizedErrorMixin; no error-shape change in this pass
  • 0030 GET idempotence — not met for replacement: GET /api/authoring/v3/home/ inherits the same write-on-GET as v1 — get_home_context → _get_course_creator_status → add_user_with_status_unrequested inserts a CourseCreator row and fires post_save for a non-staff user without a record on sites with ENABLE_CREATOR_GROUP (cms/djangoapps/contentstore/views/course.py:2144). This PR deprecates the schema of the legacy endpoint only; fixing the replacement's ADR 0030 violation is tracked under [API] Home Page Data #39068. v1 is frozen and not changed here.
  • 0031 merged endpoints — n/a: single endpoint in scope; no RPC-style action-URL family
  • 0032 pagination — n/a: singleton response, not a flat list
  • 0033 filtering — n/a: no operative query parameters; no ORM-backed list to filter
  • 0034 authentication — n/a: v1 authentication is frozen; v3 already removes Bearer; no authentication_classes declaration in this pass
  • 0035 MFE config — n/a: endpoint returns user-specific data; not a configuration-only endpoint
  • 0036 nested JSON — n/a: response is a flat singleton; not deeply nested or tree-shaped
  • 0037 versioning — partial: no edit to any file under rest_api/v{0..4}/; deprecation carried by schema hook and DEPR ticket only; conforming version is the existing v3 HomeViewSet; see test_v1_home_is_marked_deprecated_in_generated_schema. Deviations recorded: (1) no docstring marker on the superseded view — v1 is frozen; this matches the pattern other FC-0118 PRs record as a deviation; (2) no migration guide — v3 introduces ?fields= query filtering and drops Bearer authentication; callers should consult the v3 schema. Pending: entry on [DEPR]: Contentstore and enrollment API versions superseded by FC-0118 #39128 not yet posted; will be posted after approval.
  • 0038 URL structure — n/a: conforming address /api/authoring/v3/home/ already exists; no new URL work in this pass
  • OEP-66 queryset scoping — n/a: no get_queryset(), no ORM-backed record set
  • OEP-69 conventions — met: no ADR/OEP/PR identifiers in code; no deprecation notice on superseded view

Compliance matrix

Decision Status Evidence
0037 versioning Partial (see ADRs applied) git diff --name-only origin/master shows only cms/lib/spectacular.py and its test file; hygiene gate PASS
Schema deprecation Met /api/contentstore/v1/home added to SUPERSEDED_PATHS; exact-path hook sets deprecated: true; test_v1_home_is_marked_deprecated_in_generated_schema verifies path key is emitted without trailing slash
Sibling not affected (P31) Met test_v1_home_libraries_sibling_is_not_marked_deprecated
Conforming sibling path unaffected Met test_a_conforming_sibling_path_is_not_marked_deprecated
Snapshot guard Met test_both_spellings_of_each_superseded_path_are_listed fails if entry is missing
SDK replacement available Partial GET /api/authoring/v3/home/ is tagged @extend_schema(tags=["openedx-platform-sdk"]); replacement is marked x-internal (BFF surface); see Deprecations section

Backward compatibility

  • Versions gate: git diff --name-only origin/master — cms/djangoapps/contentstore/rest_api/v{0..4}/ absent from diff.
  • Legacy tests unmodified: cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py — 4 HomePageViewTest methods unchanged.
  • Schema change: one addition only — deprecated: true on GET /api/contentstore/v1/home. No path removed, no response shape changed.
  • Runtime behaviour: unchanged. SUPERSEDED_PATHS is consumed only by the drf-spectacular post-processing hook; no effect on routing or response handling.

Deprecations

GET /api/contentstore/v1/home is superseded by GET /api/authoring/v3/home/ and marked deprecated: true in the published CMS schema. The superseded view is unchanged: no response header and no deprecation notices in code.

Note on replacement availability: /api/authoring/v3/home/ is in INTERNAL_BFF_PATH_PREFIXES (cms/lib/spectacular.py:41) and is marked x-internal in the schema. Schema generators that skip x-internal operations will not include it. Callers that are not BFF consumers and whose tooling skips x-internal operations should coordinate with the team on an external-facing replacement; progress is tracked under #39068.

Tracked on the FC-0118 umbrella DEPR ticket #39128, which removes it one named release after the release this ships in.

Authorization

No permission mapping changed. E1 keeps permission_classes = (IsAuthenticated,).

Caller Expected Test
Anonymous 401 HomePageViewTest (existing, unmodified)
Authenticated user 200 HomePageViewTest (existing, unmodified)

Gate report

Gate Result Notes
Hygiene (check_code_hygiene.py) PASS — 0 FAIL, 0 WARN 2 files scanned
Frozen surfaces (git diff --name-only) PASS Only cms/lib/spectacular.py and cms/lib/tests/test_spectacular.py in diff
pytest — v1 home tests Not run locally; CI verifies HomePageViewTest (4 tests) unmodified
pytest — new hook tests Not run locally; CI verifies Updated CmsMarkSupersededPathsTest methods

Sequencing

This PR and #39238 both write to cms/lib/spectacular.py. #39238 appends entries to SUPERSEDED_PATHS and its test test_the_legacy_library_lists_are_marked_and_their_neighbours_are_not lists /api/contentstore/v1/home as a neighbour expected to remain unmarked. With both merged, that test will fail. Whichever lands second must drop the /api/contentstore/v1/home neighbour guard from #39238's test and merge the two SUPERSEDED_PATHS additions. cc #39238.

Follow-ups

  • org param no-op bug: both v1 and v3 document an org query parameter that has no effect — get_home_context never reads it (v3/views/home.py:92). v1 is frozen; the v3 fix belongs on the replacement, not on the DEPR removal. Tracked separately.
  • ADR 0030 fix for replacement: GET /api/authoring/v3/home/ has the same write-on-GET as v1; fix tracked under [API] Home Page Data #39068.
  • External MFE consumers: MFE teams receive the DEPR notice through umbrella [DEPR]: Contentstore and enrollment API versions superseded by FC-0118 #39128 and the schema flag.

🤖 Generated with Claude Code

Adds "/api/contentstore/v1/home" to SUPERSEDED_PATHS in
cms/lib/spectacular.py so the cms_mark_superseded_paths post-processing
hook sets deprecated: true on that path in the generated OpenAPI schema.

The conforming replacement (GET /api/authoring/v3/home/) already exists
and is fully ADR-compliant. No view, serializer, URL, or frozen version
directory is changed. The v1 endpoint remains live and its contract is
unchanged.

Adds three unit tests to CmsMarkSupersededPathsTest:
- TC-1: v1/home path is marked deprecated: true after hook runs
- TC-2: sibling /home/libraries is NOT marked (exact-path guard)
- TC-3: unrelated xblock path is unaffected

Tracking: #39068
DEPR umbrella: #39128

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Faraz32123 Faraz32123 linked an issue Oct 20, 2026 that may be closed by this pull request

@taimoor-ahmed-1 taimoor-ahmed-1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the change itself is small and the exact-path approach is right. Most of my comments are about whether /api/authoring/v3/home/ is the standardized replacement the description says it is, and about how this lands next to #39238.

ADR 0030 is marked n/a, but the replacement writes on GET. The description says "survey confirms no domain writes, signals, or events within three frames". Both v1 HomePageView.get and v3 HomeViewSet.list call get_home_context → _get_course_creator_status. On a site with ENABLE_CREATOR_GROUP, that calls add_user_with_status_unrequested for a non-staff user without a record (cms/djangoapps/contentstore/views/course.py:2144), inserting a CourseCreator row and sending post_save. #39238 records the same write and links it to #39068. So v3 isn't "fully standardized": it has the same ADR 0030 violation as the endpoint being deprecated. I'd rule 0030 as not met for the replacement, and either note that the fix is tracked under #39068 or hold the deprecation until it is.

The replacement is published as x-internal. /api/authoring/v3/home/ is in INTERNAL_BFF_PATH_PREFIXES (cms/lib/spectacular.py:41), so the schema flags it as a BFF surface, not a stable contract. The openedx-platform-sdk tag is there, but generators that skip x-internal drop the operation. That weakens "SDK consumers have a generated replacement". Could the Deprecations section tell callers that the replacement is internal, or say what external callers should use instead?

ADR 0037 is ticked as met, but these are missing:

  • There's no entry on #39128 for this path; none of its comments mention v1/home. The other areas post one.
  • The ADR asks for a migration guide. There's none here, even though v3 adds ?fields= and a different authentication set (no Bearer).
  • The docstring marker is left out, which other FC-0118 PRs record as a deviation. I'd mark the box partial and record it the same way.
  • The quote "more ADRs applied is not a breaking change" isn't in ADR 0037. It comes from the apply-api-adrs skill's pitfalls notes, so it shouldn't be cited as ADR text.

Smaller description points:

  • OEP-69 is shown as [ ] but described as "met".
  • The gate report lists the tests as "Expected green in CI", and the versions and schema gates as a git diff --name-only. It would help to say plainly that they weren't run, or to run them.
  • Follow-ups say v1's org parameter is a no-op whose fix "belongs in the DEPR ticket's removal". v3 HomeViewSet.list documents the same no-op parameter (v3/views/home.py:92, "Filter by course org"; get_home_context never reads it), so the fix belongs on the replacement, not on the removal of v1.

Comment thread cms/lib/spectacular.py
Comment thread cms/lib/tests/test_spectacular.py Outdated
Comment thread cms/lib/tests/test_spectacular.py Outdated
- Replace the redundant test_v1_home_is_marked_deprecated (which
  duplicated test_every_operation_of_a_superseded_path_is_marked)
  with test_v1_home_is_marked_deprecated_in_generated_schema, which
  exercises SchemaGenerator to verify the URL router emits the path
  key as /api/contentstore/v1/home (no trailing slash) before the
  hook marks it deprecated. A wrong trailing slash in the URLconf
  would silently match nothing in SUPERSEDED_PATHS; the synthetic
  _run() helper cannot catch that.

- Replace the misleading test_an_xblock_path_is_not_affected_by_home_deprecation
  with test_a_conforming_sibling_path_is_not_marked_deprecated. The
  xblock path is deprecated in the real schema via LEGACY_MIGRATED_PATH_PREFIXES
  and cms_mark_migrated_paths, making the old name incorrect. The
  new test uses /api/authoring/v3/home/courses/ — a real sibling of
  the replacement that no entry in SUPERSEDED_PATHS matches.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Faraz32123

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review — all points addressed:

  • ADR 0030: Updated to 'not met for replacement' and noted the write-on-GET is tracked under [API] Home Page Data #39068.
  • x-internal: Added a note in the Deprecations section about the BFF surface and what external callers should do.
  • ADR 0037: Changed to partial, updated test reference, recorded both deviations, removed the incorrect citation.
  • OEP-69: Fixed the checkbox — it was marked met in the text but unchecked.
  • Gate report: Replaced 'Expected green in CI' with 'Not run locally; CI verifies'.
  • Tests: Replaced the redundant test with a schema-gen test and fixed the misleading xblock one (pushed in a follow-up commit).

@Faraz32123
Faraz32123 marked this pull request as ready for review October 21, 2026 11:26
@Faraz32123
Faraz32123 requested a review from feanil October 21, 2026 11:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API] Home Page Data

2 participants