Skip to content

Writing and editing a question

/questions/manage is the list. /questions/:id and /questions/new are the editor.

Both are gated on being able to manage questions — a moderator, or the holder of any editorial grant — not on the moderator role. The server then refuses anything outside the grant.

The list

/questions/manage asks for only what you may edit. It puts an Edit and a Delete on every row, so listing the whole bank to somebody whose grant covers nine categories was a page that lied about what it was offering.

The four tiles

One-click filters, and a health check:

Tile Counts
All questions Everything in scope
Uncategorized question_category_id is null
No explanation Empty or whitespace
No difficulty Not set

A grantee's counts are their branches' counts, not the bank's.

Filters

Search over stem, options and #id; category (your branches, or the whole tree for a moderator); folder; difficulty. 25 to a page.

Bulk actions

Select rows and a bar appears. POST /questions/bulk, at most 500 ids per action.

Action Notes
Set category The destination must be a category you hold. A moderator holds all of them; a grantee can move a question between their own branches but never out of them.
Set difficulty
Add to folder Through the folder picker
Delete Moderator only, and see the warning below

Bulk delete is not the bin

A single row's Delete is a soft delete: deleted_at is set and the question goes to /trash, where a moderator can restore it.

Bulk delete is a hard delete. POST /questions/bulk with action: "delete" removes the rows outright, along with the additional category links and every answer anybody ever gave them. The dialog says so — "They go permanently… This cannot be undone" — and it is accurate. There is no bin behind it and no restore.

The editor

The question itself

Field Notes
Stem Markdown, with a formatting toolbar and a live preview. May carry tables and $maths$.
Type mcq, true_false, fill_blank
Options Up to eight (A–H). One is marked correct with a radio.
Per-option explanation Why this option is right or wrong. Markdown, same toolbar. Shown in the option's own colour once the answer is revealed — and only where there is something to say.
Explanation The one for the whole question.
Attending tip One nudge, read before answering. Leave it empty and learners are offered no button at all — an empty panel is worse than no panel. Opening it before answering counts as a hint.

Validation, in the browser and again at the server: text required, a correct answer required, at least two options for an MCQ, and the correct answer must be one of them.

Filing

A primary category decides where it is filed; also appears in adds any number of additional links. additional_category_ids is a full replacement set — send the list you want to end up with, not a delta.

Both pickers offer only what you may file into. A grantee shown the whole tree could put a question somewhere they then cannot edit.

The rest of the panel

Panel Does
Difficulty easy / medium / hard, or not set
Topic reading The articles offered after answering this question. Point at a section where the answer lives in one part of the topic. Unlinking is moderator-only.
History Every earlier version, with Restore
Feedback Reports learners have left about this question, beside the fields they are about
Figures Any number, each with a role (stem or explanation) and a label the explanation can refer to

Duplicate copies the question into a new one with "(copy)" appended. It is moderator-only, because duplicating is creating.

Opening one you may not edit

You get the stem and a sentence saying why, not a form full of blanks. The answer side is redacted, not missing, and typing into empty boxes would only earn a 403.

What an edit does to answers already given

PATCH /questions/{id} snapshots the question first, then settles the answers that already exist. Three different outcomes:

You changed What happens
The wording only Nothing. The answer is to the same question.
The correct answer Every stored answer is regraded, and the scores of the attempts they sit in are recounted. A fixed key is a fact about the question, not about the day it was fixed — somebody who chose the right option before the fix was right. Void rows stay void.
The options Answers held in sessions still open are withdrawn and marked void. Those learners have the old options on screen, so nothing they send can be compared to the new ones. Finished attempts are left alone: they were marked against the question as it stood, and that is history.

A void row is kept and shown in the review with a note. It counts nowhere. This is why a score can stay stable while the bank underneath it changes.

History

Every edit is snapshotted into question_versions before any field changes — the stem, type, options, key, explanation, per-option explanations, key points, attending tip, difficulty, category and the two legacy image paths.

The whole history is kept. It used to be trimmed to the last five, which is enough to undo a recent mistake and not enough to answer "what did this question say in March"; a question body is a few kilobytes and edits are rare.

Restoring snapshots the current state first, so a mistaken restore has a way back.

The editor's own copy is stale

With no versions yet the panel reads "The last 5 edits are kept." That is no longer true. The list itself shows every version.

Deleting

DELETE /questions/{id} Soft. deleted_at is set; the row and the id survive, so anything pointing at it can be put back. Moderator only.
/trash The bin. Restore with PATCH /questions/{id}/restore.
DELETE /questions/{id}/permanent For good. Moderator only.

There is no scheduled purge: the bin never empties itself.

Trashing a question also withdraws the answers to it held in sessions still open — the same withdraw above.