Skip to content

LTI Proctoring Assessment Control Service (both roles)

Status: accepted

Date: 2026-06-25

Relates to: ADR-0033 (emergent as an LTI 1.3 Tool), ADR-0040 (emergent as an LTI 1.3 Platform).

LTI Proctoring Services 1.0 defines, alongside the StartProctoring → StartAssessment → EndAssessment launch lifecycle, an Assessment Control Service (ACS): a back-channel REST endpoint the proctoring tool calls on the platform during a live attempt to report an incident and request a control action (flag, pause/suspend, resume, terminate, or grant extra time). The platform records the incident and MAY act on it.

In both conformance requirements the platform/tool already satisfy — PLAT-PROC-2 (“a platform MUST accept the LtiEndAssessment … and MAY honour an Assessment Control Service verdict”) and LTI-PROC-2 (“the tool returns control … and MAY surface an Assessment Control Service verdict during it”) — ACS is the parenthetical MAY. The MUST (StartProctoring + Start/EndAssessment) shipped in ADR-0040 slice 7 (platform) and ADR-0033 (tool); ACS was deliberately deferred on both sides as the optional clause.

We are now building ACS as a real product capability: a proctoring tool flagging, pausing, or terminating an in-flight attempt — and emergent acting on those signals — is genuinely useful, in both directions (emergent-as-platform receiving from an external proctoring tool, and emergent-as-tool sending to an external platform). This is not a conformance gap (the requirements already pass); it is the deliberate product decision the MAY invites.

The contract is already published by conform-ed (@conform-ed/contracts/lti/proctoring/v1_0): AssessmentControlRequest / …Response / …Severity, and assessmentProctoringSettings.assessmentControlUrl. No cross-repo work is required for the wire shapes.

  1. Honour the full action set (not audit-only). When emergent is the platform and receives an ACS request, it both (a) records every incident to an immutable audit log and (b) acts on the action: terminate ends the attempt, flag surfaces to the teacher, pause/suspend + resume gate assessment access, and update with extra_time accrues granted time on the session. The action vocabulary is open per spec; unknown actions are logged but not acted upon (never rejected — a conformant request always gets a 200 with the current status).

  2. terminate ends emergent’s own native attempt. When the proctored resource link targets a native emergent assessment (a learning unit carrying an assessment), terminate voids the in-flight attempt (transitions it to invalidated) and so blocks resubmission. ACS is thus coupled to the native assessment lifecycle, not merely a side record. When the resource link targets an external tool’s content (no native attempt), the control state is recorded and surfaced but there is no native attempt to mutate. extra_time is accrued on the proctoring session and surfaced to the teacher; the native assessment has no per-attempt countdown to auto-extend today (it uses a fixed, definition-level due_at, not a per-attempt timer), so the accumulated value is recorded for the teacher to act on and is the ready input for when per-attempt timing lands.

  3. Proctor UI on both teacher-portal and admin-console. The teacher running an offering sees that offering’s proctoring incidents and, when emergent is the proctoring tool, can fire control actions from a proctor console; admin-console gets a cross-organisation operational view of the same. Both surfaces, both roles (platform-side incident view + tool-side action console).

ACS is a back-channel service call authenticated with a Bearer service token scoped https://purl.imsglobal.org/spec/lti-ap/scope/control.all — exactly like AGS/NRPS. The platform adds the scope to SUPPORTED_LTI_SERVICE_SCOPES, mints it via the existing standalone token endpoint (client_credentials + private_key_jwt), and gates the control route with the existing authorizeService helper. The tool obtains the token via the existing @lti-tool/core token.service (the same machinery it uses for AGS) and POSTs to the persisted assessmentControlUrl.

  • Advertise assessment_control_url in the StartProctoring proctoring_settings claim (the wire shape already models it; only the URL value is newly plumbed).
  • POST /lti/platform/proctoring/control → validate against AssessmentControlRequestSchema → resolve the calling tool’s deployment + the pairwise user → person + resourceLink + attemptNumber → the proctoring session (mirrors AGS score resolution) → record a lti_platform_proctoring_control_event → apply the honour semantics → return AssessmentControlResponse (status + granted extra_time).
  • Session lifecycle gains assessment_paused and terminated states (plus a flagged flag and an extra_time_seconds accumulator).
  • terminate resolves the resource link’s learning unit to the in-flight native assessment attempt and voids it (invalidated, via invalidateInFlightNativeAttemptWithDb); extra_time accrues on the proctoring session for the teacher to act on (no per-attempt timer exists to auto-extend).
  • sendAssessmentControl builds + validates an AssessmentControlRequest, acquires a control-scoped token, POSTs to the persisted assessmentControlUrl, and records the outbound action + the platform’s response in lti_tool_proctoring_control_event.
  • An authed proctor endpoint (POST /workflow/lti-tool/proctoring/sessions/:id/control) lets a human proctor fire an action; the same service is reusable by a future automated incident policy.

Two new audit tables — lti_platform_proctoring_control_event (inbound, on the platform session) and lti_tool_proctoring_control_event (outbound, on the tool session) — each cascading from its proctoring session and carrying the action, incident time, severity, reason code/message, granted extra time, and the raw payload. Both are added to the erasure registry (reason text + payloads are scrub-class, cascading with the session/person). Pre-launch, migrations are regenerated per docs/runbooks/regenerate-migrations.md; applying them is the operator’s step.

No new conformance requirement and no map change: PLAT-PROC-2 and LTI-PROC-2 already exist with ACS as their embedded MAY, and both are already done on the MUST. The overlay notes for those two requirements are strengthened to record that the MAY is now honoured, with the ACS interop evidence keys. The board does not move (LTI 1.3 stays 54/56).

  • Apply the regenerated migrations (the two control-event tables + the session-state columns) via the recreate runbook (operator-only).
  • No new environment: ACS reuses the existing platform token secret / RS256 keypair and the tool’s proctoring signer.