Per-module threshold configuration plus the policy-derived limits the configuration UI needs to
render and validate the threshold form. Computed server-side so the exemption rule and the
minimum/default values live in one place instead of being duplicated in the frontend.
Modules with at most this many chapters are exempt from the minimum threshold; for them any
duration >= 0 is allowed, where 0 turns the duration check off.
Modules with at most this many exercises are exempt from the minimum threshold; for them any
duration >= 0 is allowed, where 0 turns the duration check off.
Confirms that a student cheated and applies the consequence: their completions in the course are
failed (passed = false, grade = 0), with the previous values snapshotted so the confirmation can
be undone by dismiss_by_user_id_and_course_id. Atomic.
Dismisses the suspicion against a student (marks it a false alarm), clears the
“needs to be reviewed” flag on their completions, and restores any grade that a prior cheating
confirmation had failed (a no-op if the student was never confirmed). Atomic.
Returns the configured threshold (if any) and the policy-derived minimum/default for every
non-deleted module in the course. The exemption rule is applied here so the configuration UI
does not have to recompute module sizes or duplicate the threshold constants.
The smallest threshold (in seconds) a teacher may configure for a module of the given size:
0 for small (exempt) modules, otherwise MINIMUM_CHEATER_THRESHOLD_SECONDS.
Whether a module of the given size is exempt from the minimum cheater threshold. Small modules
can legitimately be completed fast, so for them any duration >= 0 is allowed (0 disables the
duration check). This is the single source of truth for the exemption rule – both the save-time
validation and the configuration UI derive their behaviour from it (the latter via
get_threshold_info_for_course).
Guards the invariant that a stored threshold is never negative. progressing.rs treats a
stored value of <= 0 as “duration check disabled”, so a stray negative write would silently
turn off cheater detection; rejecting it here protects every writer, not just the HTTP handler.