Skip to content

AI Review Flow

End-to-end view of how a case flows from client submission through AI inference to a projected diagnosis.

Note on the admin dashboard: the "AI inferences" card and "AI diagnosis breakdown" donut on the admin dashboard are sourced from clinical-api.DermReview (the direct-call audit table that records each request/response against DERM), not from the Diagnosis projection described in step 5 below. DermReview is populated even by product integrations that go straight from clinical-api → DERM without engaging the orchestrator-mediated flow on this page, so it's the more reliable signal for "have we ever asked DERM about this case." Failure metrics on the dashboard partition DermReview.status='failed' (non-2xx / pre-flight) from 2xx responses whose result_json.analysisResult is not PROCESSING_ANSWER_TYPE_SUCCESSFUL_PROCESSING.

Steps

  1. Case submission — A client posts POST /v1/clinical-api/cases with case metadata and image references. clinical-api persists the Case row and associated Image rows (patient PHI fields encrypted at rest with the patient's DEK), and returns 201.

  2. Workflow instantiationclinical-api emits case.created to the Redis Stream. orchestrator consumes the event, looks up the active WorkflowDefinition for the organisation and product, snapshots it into a new WorkflowInstance, and schedules a workflow deadline via BullMQ.

  3. Consent check (if configured) — If the definition includes a gate_on_consent step, orchestrator dispatches consent.check.requested. The consent service evaluates the patient's ConsentRecord and emits consent.check.completed with a granted boolean. Orchestrator advances (on_pass) or halts (on_fail).

  4. AI dispatch — Orchestrator dispatches ai_review.requested. The payload includes presigned image URLs from clinical-api. ai-review creates an AiReview row, enqueues a BullMQ job, and sends the images to DERM AI. It persists the raw response in AiReviewResult and per-lesion detail in AiReviewLesion.

  5. Diagnosis projectionai-review emits ai_review.completed. clinical-api consumes this event and projects the AI diagnoses into its Diagnosis table (source field: ai). These become the system-of-record diagnoses for the case unless overridden by a human review.

  6. Workflow completion — Orchestrator also consumes ai_review.completed, evaluates the next-step expression, and (if no further steps are configured) dispatches the terminal emit_final step, which causes orchestrator to emit case.workflow.completed to clinical-api.

Code paths

  • Case creation: services/clinical-api/src/cases/cases.controller.ts / cases.service.ts
  • case.created emission: services/clinical-api/src/cases/cases.service.ts
  • Orchestrator case.created consumer: services/orchestrator/src/consumers/case-created.consumer.ts
  • Orchestrator completion consumer: services/orchestrator/src/consumers/completion-events.consumer.ts
  • Orchestrator dispatcher: services/orchestrator/src/dispatcher/dispatcher.service.ts
  • AI review inbound consumer: services/ai-review/src/events/ai-review-requested.consumer.ts
  • AI review event publisher: services/ai-review/src/reviews/review.events.ts
  • Diagnosis projection (clinical-api): services/clinical-api/src/ai-review/ai-review-consumer.service.ts

The Mermaid sequence source is at docs/diagrams/ai-review-sequence.mmd.