112
lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst
Normal file
112
lms/djangoapps/instructor/docs/decisions/0003-ora-api-spec.rst
Normal file
@@ -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/``
|
||||
@@ -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 <token>`).
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user