V1 Web PWA · Journey

Journey: Themis academic-integrity flag → student appeal → teacher override

A source-reconciled journey record for V1 Web PWA — shipped behavior, state boundaries, failure modes, and the automation evidence available today.

automated · 3 specs verdict: partial· 2026-06-26
9sections7 minread1table

On this page
Journey at a glance
ActorsLearnerMetis operator / teacherThemis canonical bridgeAssigned adjudicatorCustomer message center
Automation3 E2E spec(s) · verdict: partial· 2026-06-26

Journey flow#

Generated from the authored steps below — click a node to jump to that section.

flowchart TD s1["1. Learner submits and receives a canonical v…"] s2["2. Learner opens the appeal workspace"] s3["3. Learner files the appeal"] s4["4. Operator reviews the live queue"] s5["5. Operator decides and closes the case"] s6["6. Gradebook and in-app message reflect the d…"] s7["7. Learner and operator inspect the resulting…"] s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 click s1 href "#1-learner-submits-and-receives-a-canonical-verdict" click s2 href "#2-learner-opens-the-appeal-workspace" click s3 href "#3-learner-files-the-appeal" click s4 href "#4-operator-reviews-the-live-queue" click s5 href "#5-operator-decides-and-closes-the-case" click s6 href "#6-gradebook-and-in-app-message-reflect-the-decision" click s7 href "#7-learner-and-operator-inspect-the-resulting-record" s7 --> v(["verdict: partial"]) click v href "../results/themis-assessment-appeal.html" style v stroke:#d6a531,color:#d6a531

This journey is a real browser-to-BFF chain: a Metis assessment submission runs detection and canonical Themis adjudication, an eligible learner files an appeal, an operator decides it in /operator/metis, the gradebook receives a terminal correction, and the learner receives an in-app message. The chain is deep but process-local: verdicts, disputes, appeal ids, and the gradebook adapter are memory stores with no restart hydration in these modules.

Stage Source of record in this implementation
Detection and verdict MetisThemisCanonicalBridge
Appeal workspace In-memory AcademicIntegrityAppealStore
Operator decision POST /v1/metis/integrity/appeals/:id/decision
Grade correction In-memory MetisGradebookStore
Learner notice Customer message-center in-app incident
External delivery Not implemented for this decision

Personas#

  • Learner — submits the assessment, reads only their own verdict/audit record, and may file an allowed appeal.
  • Metis operator / teacher — holds an admin Metis scope, reads the full appeal queue, selects an outcome, and supplies the resolution note.
  • Themis canonical bridge — detects/classifies the record, owns the verdict, dispute, due-process profile, timeline, and audit model.
  • Assigned adjudicator — optional bridge participant selected from the registered shortlist.
  • Customer message center — receives the learner-facing decision notice after the workspace closes.

Pre-conditions#

  • The learner is signed in with Metis scope and opens /metis/assessment.
  • The submitted answer satisfies the assessment editor's rubric gate.
  • The BFF has a default academic-integrity policy binding and the canonical bridge is available.
  • A non-clear verdict is required for an appeal; clear verdicts carry appealAllowed: false.
  • The operator has the admin scope required by hasOperatorScope.
  • Browser continuity assumes the same BFF process because the appeal and gradebook stores are not durable.

Steps#

1. Learner submits and receives a canonical verdict#

  • MetisAssessmentEditor posts assessment id, course id, answer, and timestamp to POST /v1/metis/assessment-submissions.
  • The route derives a submission/verdict id, runs detectAcademicIntegritySignals, and passes detection signals, excerpts, classifier outputs, and model versions into the bridge.
  • The bridge returns a verdict, classification, enforcement outcome, and audit record with sourceOfRecord: themis.
  • Appealable non-clear verdicts emit a gradebook entry with integrityVerdict: pending.
  • The assessment editor locks the submitted answer and renders compact verdict class, severity, signal count, source, recommended action, and appeal link.
  • The compact panel is not the full evidence record; the learner-safe audit detail is on the appeal page.

2. Learner opens the appeal workspace#

  • The verdict-provided route /integrity/:verdictId/appeal loads GET /v1/metis/integrity/:verdictId/audit.
  • Ownership is fail-closed: a learner may read only a verdict whose learner id matches their authenticated user id. A mismatch returns the same 404 as an unknown record.
  • The page renders rationale, policy binding, signal/evidence counts, learner-safe excerpts, and classifier provenance.
  • A clear/teacher-cleared verdict renders an appeal-not-allowed state without a form; a direct POST returns 409.

3. Learner files the appeal#

  • The form collects narrative, requested relief, and an optional preferred adjudicator id.
  • POST /v1/metis/integrity/:verdictId/appeal checks verdict ownership and opens the canonical dispute.
  • The bridge reuses the verdict's evidence excerpts as dispute evidence, shortlists adjudicators, assigns one when available, and returns dispute, evidence, timeline, deadlines, events, and due-process summary.
  • Filed confirmation renders status plus optional case and adjudicator fields.
  • There is no learner evidence-upload field; only the canonical excerpts travel into the dispute.

4. Operator reviews the live queue#

  • /operator/metis reads GET /v1/metis/integrity/appeals with operator scope.
  • Each row renders dispute parties, evidence count, deadline stages, and due-process summary.
  • The decision form blocks a blank resolution note.
  • Outcome controls expose Uphold, Revise ( inconclusive), Dismiss (clear), and Escalate (severe).
  • This queue is process-local; an appeal disappears on BFF restart.

5. Operator decides and closes the case#

  • The UI posts outcome, resolutionNote, and closeCase to POST /v1/metis/integrity/appeals/:appealId/decision.
  • uphold retains the prior verdict class; the other controls map directly to violation | inconclusive | clear | severe.
  • The route constructs a server-side teacher override, re-adjudicates the canonical verdict, then closes the dispute and records the resolution timeline note.
  • A changed class becomes overturned; an unchanged class becomes upheld.
  • A second decision against an already closed appeal returns 409.
  • The sibling /resolve endpoint can close a workspace without selecting a new verdict class. The browser decision flow uses /decision and should not be described as the same transition.

6. Gradebook and in-app message reflect the decision#

  • The decision route emits a terminal gradebook version with trigger integrity_verdict_change and cascadeFrom: appeal.
  • The correction preserves the prior version and exposes the corrected version through GET /v1/metis/gradebook/:assessmentId/latest.
  • Severe results receive an evidence-pack reference when one was not already present.
  • The message center receives a high-priority in-app incident named Academic integrity appeal decided with the appeal-record deep link.
  • Following the link records a clicked receipt without implicitly marking the row read; mark-read is separate.
  • No push, email, or institution webhook adapter is invoked.

7. Learner and operator inspect the resulting record#

  • Learner and operator can re-read the canonical audit record; unrelated learners receive 404.
  • The updated decision rationale includes the teacher-override line.
  • The appeal workspace reads closed, and the gradebook correction is available to the permitted role.
  • The learner sees the message in /messages and can return to the appeal record.
  • These records are not a durable institutional audit ledger; they live in the singleton bridge and memory gradebook store.

Post-conditions#

  • The appeal dispute is closed with a resolution note and terminal verdict status.
  • A terminal gradebook version corrects the pending version when the assessment had an appealable verdict.
  • The learner has an in-app decision message and explicit delivery/read/click receipts.
  • Learner ownership checks remain enforced on verdict, audit, and workspace reads.
  • Restart durability, external notification, and LMS grade export are not implied by the completed browser flow.

Failure modes#

  • Unknown or another learner's verdict — an unknown record and another learner's record both return 404.
  • Appeal disabled — clear verdicts show no form and POST returns academic_integrity_appeal_not_allowed.
  • No adjudicator registered — the appeal can remain triaged with no assignment.
  • Blank decision note — client and route validation block it.
  • Parallel operator decisions — the first close wins at the HTTP guard, but the underlying bridge maps have no general optimistic concurrency version.
  • BFF restart — verdict, appeal, gradebook, and their indexes are lost.
  • Notification duplicate or suppression — the decision remains closed; notification status reports the delivery outcome.
  • External delivery expected — no push/email path exists for this event.
  • Learner evidence needed — the current appeal accepts narrative and relief, not an uploaded evidence bundle.
  • Bias review needed — the enum admits paused_bias_review, but this route does not drive that transition.

E2E coverage#

Coverage is deep for one-process behavior. It does not prove persistence across restart, external delivery, learner evidence upload, or bias-pause routing.

Per-view files touched by this journey#

Cross-references#

  • metis-lesson-completion.md — upstream learning path.
  • tenant-audit-log-investigation.md — a different persistent/admin audit surface.
  • apps/oshun/bff/src/routes/metis-integrity.ts — HTTP ownership, decision, notification, and gradebook orchestration.
  • apps/oshun/bff/src/metis/academic-integrity-appeal-store.ts — process-local canonical bridge holder.
  • apps/oshun/bff/src/metis/gradebook-store.ts — in-memory gradebook emitter and correction index.
  • libs/metis/integrations/src/themis-canonical-wiring.ts — adjudication, disputes, due process, and audit model.

Open questions#

  • Which durable store owns verdicts, disputes, audit records, and gradebook corrections in production?
  • What concurrency token prevents two teacher decisions from racing before the closed-state check?
  • How can a learner attach and safely disclose supporting evidence?
  • Which external channels, if any, deliver academic-integrity decisions?
  • How does a terminal grade correction leave this memory adapter for the tenant LMS?
  • What policy and UI drive paused_bias_review?
  • Should the generic /resolve endpoint remain distinct from the verdict-selecting /decision path?