learningequality / learningequality/studio

[QTI] Serve legacy assessment items as QTI through the API endpoint (dual-read)

Open
#6,030 3 comments 1 reaction 1 assignee View on GitHub

@rtibblesbot is already working on this.

Since Jul 31, 2026.

DEV: backend
Dominant language
Python
Stars
191
Forks
307
Avg merge
5d 6h
Merged PRs (30d)
10

Description

This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Overview

During a short transition window, the AssessmentItem API endpoint converts legacy items to QTI on read — via the reusable conversion (#6003) — so the frontend only ever receives QTI and needs no backward-compatibility handling. The one-time global backfill that makes this permanent and removes the dual-read is #6007.

Complexity: Medium
Target branch: unstable

Context
  • The reusable legacy→QTI conversion is #6003; this issue wires it into the endpoint's read path.
  • The transitional conversion lives in the API layer (dual-read), not the database — no schema change.
  • Leave perseus_question items as raw Perseus — out of scope here; handled by mixed publishing (#6006).
The Change
  • On read, the AssessmentItem endpoint returns QTI (type='QTI', raw_data XML) for a still-legacy row by converting it via #6003.
  • Pass perseus_question rows through unchanged.
  • The dual-read is removed once the global backfill (#6007) lands.
Acceptance Criteria
  • The API endpoint returns QTI for a still-legacy row (dual-read), so the frontend only ever receives QTI
  • perseus_question rows are returned unchanged
  • Conversion failures are surfaced, not silently dropped
  • Tests cover the API dual-read across the supported legacy types
References
  • #6003 — reusable legacy→QTI conversion (consumed here)
  • #6007 — global backfill that later removes this dual-read
  • #5980 — legacy types in the QTI editor (superseded once this lands)

AI usage

Architecture decided with the maintainer across an iterative session: blanket QTI type with the item XML in raw_data; XSD-authoritative validation across all sources; a legacy→QTI global migration with an API-layer dual-read; ricecooker upload delegating to the AssessmentItem serializer; and a Perseus custom-interaction contract confirmed against the QTI 3.0 specification. Claude mapped the existing publish/validation/ricecooker code, proposed the breakdown, and drafted each issue; the maintainer steered every decision and reviewed throughout.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.