From 7f1f8767a874b7a4891518c9af96f4f5f29531e7 Mon Sep 17 00:00:00 2001 From: Daniel Wong Date: Thu, 8 Jan 2026 17:30:26 -0600 Subject: [PATCH] docs: instructor ORA api spec (#37775) * docs: instructor ORA api spec --- .../docs/decisions/0003-ora-api-spec.rst | 112 +++++++ .../instructor-v2-ora-api-spec.yaml | 289 ++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst create mode 100644 lms/djangoapps/instructor/docs/references/instructor-v2-ora-api-spec.yaml diff --git a/lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst b/lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst new file mode 100644 index 0000000000..4b1fd828e1 --- /dev/null +++ b/lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst @@ -0,0 +1,112 @@ +Instructor Dashboard – Open Response Assessment (ORA) API Specification +====================================================================== + +Status +====== +Accepted + +Context +======= + +The Instructor Dashboard is being migrated to a Micro-Frontend (MFE) architecture, +which requires stable, well-defined, and RESTful API endpoints. + +The existing Open Response Assessment (ORA) functionality exposes summary and +detailed assessment data through legacy endpoints that are tightly coupled to +server-rendered views. These endpoints do not meet the requirements for MFE +consumption, including consistent URL patterns, centralized permission handling, +and standardized API documentation. + +Additionally, ORA functionality is implemented in the edx-ora2 library, which +is maintained as a separate Django app from the main platform. Historically, +Instructor Dashboard APIs have been implemented directly in the platform and +coupled to ORA data sources, rather than being owned by or exposed directly from +edx-ora2. While edx-ora2 is expected to be installed in the platform, this +cross-app coupling is not an ideal long-term pattern. + +As part of this work, the new versioned ORA APIs will continue to rely on the +existing OraAggregateData interface to retrieve assessment data. This ensures +consistency with current ORA behavior and avoids introducing tighter coupling or +duplicate business logic as part of this migration. + +Refactoring or relocating these REST endpoints into the edx-ora2 library +itself—so that the Instructor Dashboard consumes them as an external dependency— +is acknowledged as a potential future improvement. However, this architectural +change is explicitly out of scope for the current effort. + +To support the MFE migration in the short term, this work introduces a new +versioned ORA API that follows RESTful principles and aligns with existing +Instructor v2 APIs, while preserving current data access patterns and interfaces. + +Decisions +========= + +1. RESTful Resource-Oriented Design +---------------------------------- + +Introduce a versioned API under ``/api/instructor/v2/`` using resource-oriented +URLs and clear HTTP semantics. + +**Summary endpoint** + +.. code-block:: http + + GET /api/instructor/v2/courses/{course_key}/ora/summary/ + +Returns aggregated ORA statistics for a course, including: + +- Total units +- Total assessments +- Total responses +- Counts by assessment type (training, peer, self, waiting, staff) +- Number of final grades received + +**Assessments list endpoint** + +.. code-block:: http + + GET /api/instructor/v2/courses/{course_key}/ora/ + +Returns a collection of Open Response Assessments (ORAs) for the specified course. +Each item in the response represents a single assessment and includes +per-assessment metrics such as response counts, grading progress, and assessment +state. + +2. Permissions Aligned with Instructor Dashboard +------------------------------------ + +The permission checks for these new API endpoints align with existing +Instructor Dashboard permissions: +- Only users with instructor or staff roles for the course can access these endpoints. + +3. Serializer-Based Business Logic +--------------------------------- + +Use Django REST Framework serializers (``ORASummarySerializer`` and +``ORASerializer``) to encapsulate business logic for data retrieval and formatting. + +Views remain thin and focused on request handling. + +4. OpenAPI Specification +------------------------ + +Maintain an OpenAPI specification at ``../references/instructor-v2-ora-api-spec.yaml`` to guide implementation. +This static specification serves as a reference during development, but ``/api-docs/`` is the source of truth for what is actually deployed. +Once implementation is complete and the endpoints are live in ``/api-docs/``, the static spec file will be deleted to avoid maintaining outdated documentation. + +Consequences +============ + +- Reduced the complexity of client-side code by providing structured data + tailored for MFE consumption +- Centralized business logic ensures consistent permission checks and data + formatting +- Simplified client-side logic for the Instructor Dashboard MFE +- OpenAPI documentation enables type-safe client generation and easier + integration + +References +========== + +- OpenAPI Specification: ``../references/instructor-v2-ora-api-spec.yaml`` +- Live API Documentation: ``/api-docs/`` diff --git a/lms/djangoapps/instructor/docs/references/instructor-v2-ora-api-spec.yaml b/lms/djangoapps/instructor/docs/references/instructor-v2-ora-api-spec.yaml new file mode 100644 index 0000000000..f88c4fe4b9 --- /dev/null +++ b/lms/djangoapps/instructor/docs/references/instructor-v2-ora-api-spec.yaml @@ -0,0 +1,289 @@ +swagger: '2.0' +info: + title: Instructor Dashboard ORA API v2 + version: 2.0.0 + description: | + REST API for Open Response Assessment (ORA) operations in the Instructor Dashboard. + Designed to support the Instructor Dashboard Micro-Frontend (MFE). + + **Design Principles:** + - RESTful resource-oriented URLs + - Course-scoped endpoints + - Read-only operations + - Centralized permission checks + - Consistent error handling + +host: courses.example.com +basePath: / +schemes: + - https + +securityDefinitions: + JWTAuth: + type: apiKey + in: header + name: Authorization + description: JWT token authentication (e.g. `JWT `). + +security: + - JWTAuth: [] + +tags: + - name: ORA + description: Open Response Assessment instructor data + +paths: + /api/instructor/v2/courses/{course_id}/ora/summary: + get: + tags: + - ORA + summary: Get ORA summary statistics + description: | + Retrieve an overview of Open Response Assessments (ORA) for a course, + including total assessments, responses, and grading state breakdowns. + operationId: getORASummary + produces: + - application/json + parameters: + - $ref: '#/parameters/CourseId' + responses: + 200: + description: ORA summary retrieved successfully + schema: + $ref: '#/definitions/ORASummary' + 400: + $ref: '#/responses/BadRequest' + 401: + $ref: '#/responses/Unauthorized' + 403: + $ref: '#/responses/Forbidden' + 404: + $ref: '#/responses/NotFound' + + /api/instructor/v2/courses/{course_id}/ora: + get: + tags: + - ORA + summary: List ORA assessments with detailed statistics + description: | + Retrieve detailed information for all Open Response Assessments (ORA) + in a course, including response counts and grading states per assessment. + operationId: listORA + produces: + - application/json + parameters: + - $ref: '#/parameters/CourseId' + responses: + 200: + description: ORA assessment list retrieved successfully + schema: + $ref: '#/definitions/ORAList' + 400: + $ref: '#/responses/BadRequest' + 401: + $ref: '#/responses/Unauthorized' + 403: + $ref: '#/responses/Forbidden' + 404: + $ref: '#/responses/NotFound' + +parameters: + CourseId: + name: course_id + in: path + required: true + description: Course identifier in format `course-v1:{org}+{course}+{run}` + type: string + pattern: '^course-v1:[^/+]+(\\+[^/+]+)+(\\+[^/]+)$' + x-example: "course-v1:edX+DemoX+Demo_Course" + +responses: + BadRequest: + description: Bad request - Invalid parameters or malformed request + schema: + $ref: '#/definitions/Error' + examples: + application/json: + error: "INVALID_PARAMETER" + message: "Invalid course key format" + + Unauthorized: + description: Unauthorized - Authentication required + schema: + $ref: '#/definitions/Error' + examples: + application/json: + error: "AUTHENTICATION_REQUIRED" + message: "You must be authenticated to access this endpoint" + + Forbidden: + description: Forbidden - Insufficient permissions + schema: + $ref: '#/definitions/Error' + examples: + application/json: + error: "PERMISSION_DENIED" + message: "You do not have instructor permissions for this course" + + NotFound: + description: Not found - Resource does not exist + schema: + $ref: '#/definitions/Error' + examples: + application/json: + error: "RESOURCE_NOT_FOUND" + message: "The specified resource does not exist" + +definitions: + ORASummary: + type: object + description: Aggregated ORA statistics for a course + required: + - total_units + - total_assessments + - total_responses + - training + - peer + - self + - waiting + - staff + - final_grade_received + properties: + total_units: + type: integer + minimum: 0 + description: Total number of ORA units in the course + example: 12 + total_assessments: + type: integer + minimum: 0 + description: Total number of ORA assessments + example: 25 + total_responses: + type: integer + minimum: 0 + description: Total number of learner responses + example: 350 + training: + type: integer + minimum: 0 + description: Responses in training step + example: 40 + peer: + type: integer + minimum: 0 + description: Responses in peer grading + example: 120 + self: + type: integer + minimum: 0 + description: Responses in self assessment + example: 60 + waiting: + type: integer + minimum: 0 + description: Responses waiting for grading + example: 30 + staff: + type: integer + minimum: 0 + description: Responses requiring staff grading + example: 20 + final_grade_received: + type: integer + minimum: 0 + description: Responses with final grade assigned + example: 80 + + ORAList: + type: object + description: List of ORA assessments with detailed statistics + required: + - assessments + properties: + assessments: + type: array + items: + $ref: '#/definitions/ORAAssessment' + + ORAAssessment: + type: object + description: Detailed ORA assessment statistics + required: + - block_id + - unit_name + - display_name + - total_responses + - training + - peer + - self + - waiting + - staff + - final_grade_received + properties: + block_id: + type: string + description: ORA block usage key + example: "block-v1:edX+DemoX+Demo_Course+type@openassessment+block@ora1" + unit_name: + type: string + description: Name of the unit containing the ORA assessment + example: "Week 1: Introduction" + display_name: + type: string + description: Display name of the ORA assessment + example: "Peer Review Assignment 1" + total_responses: + type: integer + minimum: 0 + description: Total responses submitted + example: 120 + training: + type: integer + minimum: 0 + description: Responses in training step + example: 15 + peer: + type: integer + minimum: 0 + description: Responses in peer grading + example: 50 + self: + type: integer + minimum: 0 + description: Responses in self assessment + example: 20 + waiting: + type: integer + minimum: 0 + description: Responses waiting for grading + example: 10 + staff: + type: integer + minimum: 0 + description: Responses requiring staff grading + example: 5 + final_grade_received: + type: integer + minimum: 0 + description: Responses with final grade assigned + example: 20 + + Error: + type: object + description: Error response + required: + - error + - message + properties: + error: + type: string + description: Machine-readable error code + message: + type: string + description: Human-readable error message + field_errors: + type: object + description: Field-specific validation errors + additionalProperties: + type: string