Skip to content

[API] Libraries #39069

Open

Description

@FuaadZam

Functional Area: Libraries

Endpoints under this functional area:

Module API Version Resource / Endpoint HTTP Method Description
Home v1 /contentstore/v1/home/libraries GET Retrieves all libraries on the home page. Supports optional query parameters: org (filter by organization) and is_migrated (boolean, true or false to filter legacy libraries by migration status). Returns display name, library key, URL, edit permissions, and migration info. Useful for AI systems or external tools managing library content or migration tracking.

Activity

  1. added theissue type on Sep 2, 2026
  2. Faraz32123 commented on Oct 15, 2026

    @Faraz32123
    Contributor

    Standardization PR open: #39238

    PR: #39238 — feat: apply FC-0118 ADRs to legacy libraries API
    State: open

    What this does

    Standardizes the Libraries functional area (#39069, part of #38137). This area has one operation: "list the legacy (v1, modulestore) libraries the requester can read". Today it is served at three addresses across two versions; this PR adds its v4 at /api/authoring/v4/legacy_libraries/.

    New addresses

    • GET /api/authoring/v4/legacy_libraries/ (supersedes GET /api/contentstore/v1/home/libraries, GET /api/contentstore/v3/home/libraries/ and GET /api/authoring/v3/home/libraries/, now deprecated: true in the CMS schema)

    ADRs applied

    10 of 16 decisions applied on this pass; every one left open carries its reason.

    The evidence for each tick is the compliance matrix in the PR body; nothing is ticked without a named test or gate line.

    Backward compatibility

    Schema: 0 breaking changes (69 → 70 paths). URLs: every base route keeps its pattern, name and view (2162 → 2163). The 24 legacy tests pass unmodified; v4 responses match v3 field for field (parity test, 20 rows).

    Gates

    ==================== summary ====================
      versions             PASS
      hygiene              PASS
      schema               PASS
      urls                 PASS
      old-tests            PASS
      tests                PASS
    ALL GATES PASSED
    

    Deprecations

    GET /api/contentstore/v1/home/libraries, GET /api/contentstore/v3/home/libraries/ and GET /api/authoring/v3/home/libraries/ are superseded by GET /api/authoring/v4/legacy_libraries/. They are marked deprecated: true in the published CMS schema; the v3 contentstore address was already marked through its /api/contentstore/v3/home/ prefix. The superseded views are unchanged: no response header, and no deprecation notes in code. /api/authoring/v3/home/ and /api/authoring/v3/home/courses/ remain current.

    Tracked on the FC-0118 umbrella DEPR ticket, #39128, which removes them one named release after the release this ships in. This area's entry: #39128 (comment)

    Migration notes for callers:

    • The list is paginated: {count, num_pages, current_page, start, next, previous, results}, 10 per page by default, page_size up to 100. Each item in results has the fields of an item in the old libraries array, under the same names.
    • Items are ordered by display name (case-insensitive), then library key.
    • org now filters by the organization in the library key, as an exact, case-sensitive match; v1 and v3 documented it but ignored it. is_migrated behaves as before. An empty value for either is a 400.
    • The trailing slash is required.
    • Errors use the standardized envelope (v1 callers previously got {"detail": ...} or a bare list).
    • Bearer tokens are not accepted on v4: use JWT or a session. v1 accepts them until it is removed.
    • The v4 GET has no side effects. On sites with ENABLE_CREATOR_GROUP, v1 and v3 created an unrequested course-creator record (CourseCreator) as a side effect of this read, for a non-staff user who had none. Two other Studio reads still create it: the Studio home context (get_home_context, cms/djangoapps/contentstore/utils.py:1714, behind the v1 and v3 home endpoints) and the course rerun context (get_course_rerun_context, utils.py:1740).
    • POST /request_course_creator depends on that record (cms/djangoapps/contentstore/views/user.py:27-31). It calls user_requested_access, which does CourseCreator.objects.get(user=user) (cms/djangoapps/course_creators/views.py:89). On a site with ENABLE_CREATOR_GROUP, a non-staff author whose client has loaded neither the Studio home nor a course rerun context gets a 500 from that POST. No v4 endpoint creates the record (neither this list nor /api/authoring/v4/courses/), and this PR adds no POST to do it. A client that offers course-creator requests must still load the Studio home for the user first. The fix is tracked with the Studio home standardization, [API] Home Page Data #39068.

    /api/authoring/v3/home/libraries/ was added by #39078, merged 2026-10-12 (cc @Abdul-Muqadim-Arbisoft). It is deprecated here because v4 is now this operation's current version.

    Follow-ups

    • SDK: the view carries the openedx-platform-sdk tag, so the next openedx-platform-sdk regeneration gains v4_legacy_libraries_list. The v3 addresses are x-internal and drop out of generators that skip it.

    • frontend-app-authoring:

      • The libraries tab calls v1 and searches, filters and paginates the whole list client-side. Moving to v4 means paging (at most 100 per page) or asking for server-side search, before v1 and v3 are removed.
      • The draft FAA Make paver respect NO_PREREQ_INSTALL #3140 migrates to /api/contentstore/v3/home/libraries/, which is deprecated. It should target v4 instead (to be noted on FAA#3127).
    • Course-creator record, for [API] Home Page Data #39068: standardizing the Studio home endpoints under [API] Home Page Data #39068 would remove one of the two reads that still create the unrequested CourseCreator record; the course rerun context is the other. Before that happens, POST /request_course_creator needs a write that creates the record: an explicit endpoint, or user_requested_access creating it when it is missing. This PR records the dependency and adds no POST.

    • edx-drf-extensions (library changes, not made here):

      1. DefaultPagination.get_paginated_response_schema documents four of the seven keys, and the inherited page_size description gives neither the default nor the cap. The library fix should cover both. This PR adds the second local subclass, after CourseTextbookPagination. The two now differ, since only this one carries the page_size text. Keeping a second copy is an accepted risk for this PR; both subclasses go once the library fix is released. No issue or PR exists for it (searched 2026-10-14).
      2. MethodNotAllowed and NotAcceptable are not cataloged, so a 405 or 406 is enveloped as internal / "Internal Server Error".
      3. The exception handler returns the generic 500 envelope without logging the exception, so no traceback reaches the server log.
      4. A keyed ValidationError is rendered into detail as the Python repr of the whole error dict.

      Items 2 to 4 were not searched for existing issues.

    • CMS JSON 404: an address below /api/authoring/v4/legacy_libraries/ gets the CMS's HTML 404 page, even when the client asked for JSON. Fixing that for unmatched /api/ addresses belongs to the CMS handler404, or to a catch-all route under each collection.

    • Shared test helpers: the v4 tests import PASSWORD, SignalRecorder, generate_cms_schema, logged_in_client, resolve_ref and writes from cms/djangoapps/contentstore/rest_api/v2/views/tests/helpers.py, a module scoped to the v2 tests. Hoist them next to routed_actions in cms/djangoapps/contentstore/tests/utils.py, and leave a re-export in v2. Then a v2-only edit cannot change what the v4 tests prove, and retiring v2 cannot break them. Not done here, because it edits frozen v2 test code.

    • Later category-2 opt-ins (no version bump needed): an ordering parameter and a text-search parameter on v4.

    • Test environment: run in a Tutor container (openedx-dev:23.0.0-main) with openedx-core 1.11.0, openedx-authz 1.24.0 and openedx-forum 0.4.8 installed to match the pins (the image ships older releases). CI is the authoritative run.

    🤖 Generated with Claude Code

    Review on the PR, please — this issue stays open until it merges.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions