Skip to content

[QTI] Allow API endpoint to handle AssessmentItem.raw_data to store QTI data #5999

Description

@rtibbles

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

Overview

Store and round-trip the editor's authored QTI XML on AssessmentItem (type='QTI', full item XML in raw_data) through the save, sync, and internal API paths without altering it.

Complexity: Medium
Target branch: unstable

Context

  • AssessmentItem (contentcuration/contentcuration/models.py) holds type, question, answers, hints, raw_data. type choices are migration-defined (0152, 0154).
  • The endpoint already exists: AssessmentItemViewSet + AssessmentItemSerializer (viewsets/assessmentitem.py), registered in the sync API (viewsets/sync/base.py). This task extends them — not a new endpoint. Type validation already exists (Add validation for the "type" of AssessmentItem objects #4877).
  • Legacy items use structured question/answers; raw_data today carries raw Perseus JSON for perseus_question.
  • For QTI items the full item XML lives in raw_data; question/answers are unused, and the serializer's answers/hints coercion must be bypassed.
  • Nested-resource extraction today is markdown-only: AssessmentItemSerializer.set_files + get_filenames_from_assessment (viewsets/assessmentitem.py) scan question/answers/hints for ![...]($CONTENT_STORAGE/<checksum>.<ext>) and create/claim File rows (preset EXERCISE_IMAGE). QTI items carry references in XML attributes, so that scan finds nothing.
  • Sync is field-level last-write-wins over the single raw_data string.
  • Saves process asynchronously; validation errors return through the sync error channel, not synchronously.

The Change

  • Accept QTI as a valid AssessmentItem.type everywhere the backend enumerates or validates types.
  • Persist and return raw_data verbatim for QTI items through save and sync.
  • Apply no markdown/answer transformation to QTI items.
  • Extract referenced files from the QTI raw_data XML — checksums from src, srcset, href, and data attributes — and create/claim/delete File rows through the existing set_files flow.
  • Validate raw_data against the QTI schema ([QTI] QTI 3.0 schema XML validation utilities #6005) during async sync processing; reject invalid items.

Acceptance Criteria

  • QTI is an accepted AssessmentItem.type across model, validation, and serializers
  • A QTI item's raw_data round-trips byte-for-byte through save and sync
  • No markdown/answer transformation is applied to type='QTI' items
  • Files referenced in a QTI item's raw_data (via src/srcset/href/data) are linked as File rows through the existing claim/create/delete flow
  • Invalid QTI is rejected on save and surfaced to the client
  • Legacy item types save and sync unchanged
  • Tests cover create/update/read and file extraction for a QTI item via the sync API, asserting verbatim round-trip

References

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.

Activity

  1. added theissue type on Jun 28, 2026
  2. rtibblesbot commented on Jul 3, 2026

    @rtibblesbot
    Contributor

    Watching for resolution on behalf of #6002.

  3. rtibblesbot commented on Jul 3, 2026

    @rtibblesbot
    Contributor

    Plan: Store and round-trip the editor's authored QTI XML on AssessmentItem (type='QTI', full item XML in raw_data) through the save and sync API paths without altering it, extracting referenced files and validating the XML against the QTI 3.0 schema.

    • Add QTI as an AssessmentItem.type and make raw_data round-trip byte-for-byte
    • Skip answers/hints JSON-shape validation when type == "QTI"
    • Reject invalid QTI raw_data via the sync error channel
    • Extract src/srcset/href/data checksums from raw_data and wire into set_files
    • Full create → update → read round-trip test, file removal on update, and full-suite regression check

    @rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

    How was this generated?
    • Implemented code following the pre-approved plan using test-driven development (red-green-refactor)
    • Ran the project's full test suite and linter before committing
    • For UI changes: captured live screenshots to verify rendering
    • For backend changes: verified with example API/CLI output
  4. added a commit that references this issue on Jul 3, 2026
    397f1f7
  5. rtibblesbot commented on Jul 3, 2026

    @rtibblesbot
    Contributor

    The bot has been waiting for a response for 2 hour(s). It will resume automatically when someone replies.

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

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions