Question Title PRD V1.2
Question Title PRD V1.2
Functional Requirements for Question Title
-
An MCQ’s question is its title. The title can be in one of three formats (
title_format):- TEXT_MCQ — plain text.
- IMAGE_MCQ — plain-text title + one image.
- RICH_MCQ — rich content (PlateJS).
-
Editor adds the title per the chosen format:
- TEXT_MCQ — types plain text.
- IMAGE_MCQ — types plain text and adds one image via ImageId (from the Image Bank). One image; the image is what makes it an IMAGE title.
- RICH_MCQ — rich content (formatting, image).
-
For RICH_MCQ, the system derives a plain-text
titlefrom the rich content. -
titleis always plain text and always present — it is what is displayed in listing. -
Client rendering in MCQ Screen:
- TEXT_MCQ — the title text.
- IMAGE_MCQ — the title text with the image rendered inline below it.
- RICH_MCQ — the rich content.
-
Client rendering in Listing Screen:
- the title text — in every format.
Technical Details (as built)
Implemented in PR #737 (feature/mcq-image-format-thumbnails). Design spec:
keystone/docs/superpowers/specs/2026-06-02-mcq-question-format-thumbnails-design.md.
Naming: PRD vs code
The codebase keeps the existing field names — there is no title rename. PRD
terms map to code as:
| PRD term | Code field |
|---|---|
| title | question |
title_format | question_format (QuestionContentFormatEnum) |
| plain-text title (listing) | question_preview (existing, auto-derived) |
Enum (QuestionContentFormatEnum, int-valued, wire format = 1/2/3)
TEXT_MCQ = 1(renamed fromSIMPLE_MCQ)RICH_MCQ = 2(renamed fromADVANCED_MCQ)IMAGE_MCQ = 3(new)
Rename is key-only; values unchanged → no data migration, no API payload change.
thumbnails field
thumbnails: List[str]on MCQ db + projection models — holds image-bank short_uids (raw passthrough on read; no hydration into image objects).- Capped at
MAX_MCQ_THUMBNAILS = 1(list kept for future multi-image).
Validation
| Rule | Enforced at | Error code |
|---|---|---|
len(thumbnails) ≤ 1, no duplicates | db_model field_validator + av1 request schema | INVALID_PARAMETERS |
thumbnails non-empty ⇒ question_format == IMAGE_MCQ (post-update state) | av1 schema + db_model model_validator + service | MCQ_INVALID_DATA |
every short_uid live (is_deleted=False) in same course_id | service via image_bank_repo.get_by_short_uids (one batched query) | ENTITY_NOT_FOUND |
Surface & semantics
- Write path = av1 (admin) only:
POSTcreate,PATCH update_by_id. v1/v2 are GET-only for MCQ. - Update semantics:
thumbnails=None→ unchanged;thumbnails=[]→ cleared. OnPATCH, format↔thumbnails rule is re-checked against the merged post-update state (flipping away from IMAGE_MCQ while thumbnails remain set → rejected). question_previewderivation:TEXT_MCQ+IMAGE_MCQuse the plain-text branch;RICH_MCQparses PlateJS.IMAGE_MCQallows 0-or-1 thumbnail at create (image may be added later via update).- No Typesense changes (MCQ has no search model).