LyraLearn AI Learning Platform
Exams
← Module 10 Β· Designing the Transcript Review Service
🎧 Listen

Workflow, Audit, and the Portable Report

Three concerns turn this from a CRUD app into a defensible public-sector service: background processing, an audit trail that survives scrutiny, and a report worth carrying between programs.

Queued background processing

Extraction and AI analysis take seconds to minutes β€” far too long for a request thread. The pattern is queue and poll: the upload action writes the submission with status Extracting and enqueues a job; a background worker picks it up, runs the pipeline, and advances the status; the EPP's status page (or a small poll from jQuery) reflects progress.

The idiomatic Core shape is a hosted BackgroundService reading a queue table (or Azure Storage Queue). Hangfire backed by SQL Server is a fine step up when you want persistent jobs, retries, and a dashboard without new infrastructure. Either way, obey two rules: jobs must be idempotent (a retry after a crash must not duplicate findings β€” key them on submission + methodology version), and a poison message must move to a dead-letter state that shows up on the ops dashboard, not silently retry forever.

The immutable audit trail

The Commission must be able to reconstruct any determination years later. That means an append-only audit log: every status transition, every AI suggestion, every analyst accept or override (with reason code), and the final determination β€” each with actor, UTC timestamp, and before/after values.

Implementation is deliberately boring: an AuditEvent table written inside the same transaction as the change it records, so audit and data can never disagree. No UPDATE or DELETE grants on the table. Corrections are new events ("determination amended, superseding event 4417"), never edits. If your agency uses SQL Server temporal tables, they're a nice belt-and-suspenders under the explicit log, but they don't replace it β€” temporal tables capture what changed, while the audit log captures who intended what and why.

The portable report

The end product is a standardized PDF: candidate identity, institutions and coursework considered, per-SMR-domain outcomes, identified gaps with the remediation paths (coursework or exam), the analyst determination, and β€” critically β€” the methodology version applied. Generate it server-side from a template (a Razor-to-PDF pipeline or a report library your shop already licenses), store the generated file alongside its hash, and treat regeneration as a new versioned artifact. The report must stand alone: another EPP reading it should need no login and no phone call.

Versioning the methodology

SMR definitions and matching rules will change. If findings only point at "the current rules," every past determination becomes unexplainable the day the rules change. So the methodology β€” SMR hierarchy, rule set, prompt/model configuration for the AI step β€” is a versioned, immutable snapshot, and every finding, determination, and report references its MethodologyVersionId. New submissions use the newest version; old decisions keep the version that produced them. This one design decision is what lets a five-year-old report remain defensible, and Module 11 leans on it hard.

🧠 Quiz yourself on this lesson →

Ask the AI Tutor

Grounded in the course lessons β€” it cites its sources and says when it doesn't know.