A production-oriented prototype for converting remote treatment monitoring submissions into structured, auditable decision-support signals for clinician prioritization.
Architecture | Demo Workflow | Engineering Overview | Validation
Remote treatment monitoring produces asynchronous patient submissions that clinicians need to review efficiently. The system converts those submissions into structured quality, view, longitudinal, and timing signals so clinicians can prioritize review while retaining complete control over the final decision.
Prototype / Decision Support: This is a technical prototype, not a medical diagnostic system. AI/CV outputs are decision-support signals only, and clinical decisions remain with qualified clinicians.
In teledentistry and remote orthodontic monitoring, patients asynchronously submit monitoring photographs at regular intervals. Clinicians are tasked with reviewing hundreds of these submissions daily. The workflow problem is twofold:
- Administrative Overhead: Reviewing compliance and image quality manually consumes valuable clinical time.
- Lack of Prioritization: Clinicians lack an automated way to screen for incomplete uploads, blurry photos, or tracking deviations before manually inspecting a case.
The RTM Intelligence Layer solves this by automatically flagging quality and view anomalies, allowing clinicians to focus first on cases that require immediate retakes or clinical escalation. It does NOT diagnose dental disease, automate clinical decision-making, or replace clinicians.
The system isolates automated signal generation from final clinician decision-making:
Patient Submission
↓
Go API
↓
202 Accepted
↓
Redis Queue
↓
Go Worker
↓
CV / ML Analysis
↓
Quality + View Validation
↓
Longitudinal Comparison
↓
Explainable Triage
↓
Clinician Review
↓
Human Decision
↓
Audit Trail
By returning 202 Accepted immediately upon upload validation, the patient experience remains low-latency, while heavy computations (blur analysis, brightness parsing, ONNX neural net classification, longitudinal comparative hashing) are processed asynchronously in the queue.
The following diagram represents the actual containerized services in the repository:
PATIENT
│
▼
React Patient Portal
│
▼
Go API Gateway
│
202 Accepted
│
▼
Redis Queue
│
▼
Go Worker
/ \
/ \
▼ ▼
Python CV Service PostgreSQL
/ \
▼ ▼
OpenCV ONNX
\ /
▼ ▼
Quality + ML Signals
│
▼
Explainable Triage
│
▼
Clinician Workspace
│
▼
Human Review / Action
│
▼
Audit Trail
- Go: Selected for the API Gateway and background worker because of its compiled speed, extremely low memory usage, and native concurrency mechanisms (goroutines). This enables efficient handling of WebSocket connections and high-throughput background queues.
- Redis: Serves as the asynchronous job queue (
BLPopblocking consumer) and Pub/Sub broker, decoupling photo uploads from heavy image processing and facilitating real-time WebSocket synchronization across instances. - Python: Serves as the microservice runner for computer vision (
fastapi+OpenCV), grouping libraries like NumPy and OpenCV in a stable, isolated environment without bloating the Go binary or introducing Cgo bindings. - ONNX Runtime: Serializes and serves the trained
MobileNetV3-Smallmodel. Using ONNX decouples model training (PyTorch) from serving, allowing lightweight inference on the CPU without requiring a GPU or a PyTorch package dependency. - PostgreSQL: Serves as the relational system of record, storing patient profiles, active aligner stages, signals, explainable scoring metrics, and audit trail events inside transactional database blocks.
- WebSockets: Feeds real-time queue notifications and priority updates to the clinician dashboard immediately when the background worker commits assessments.
The local demonstration scenario contains pre-seeded credentials:
- Patient Portal:
patient_demo_1/password123 - Clinician Portal:
clinician_demo_1/password123
- Patient Login: Log in as
patient_demo_1. - View Protocol: Observe that the current treatment protocol requires
FRONT,LEFT, andRIGHTviews. - Upload Available Images: Choose image files for
FRONTandLEFT, but intentionally leaveRIGHTmissing. - Confirm Image Integrity: Check the mandatory box:
"I confirm these images have not been digitally modified." - Submit: Click submit. Confirm the warning dialog regarding the missing
RIGHTview. - 202 Accepted Response: The client receives a
202 Acceptedresponse immediately. The portal displays an active pipeline stepper:Submission received→Added to queue→Running Quality Checks→Running Triage Scoring - Background Processing: The worker dequeues the files, triggers CV analysis, runs longitudinal comparison against the previous approved stage, and calculates the triage score.
- Clinician Dashboard: Sign out and log in as
clinician_demo_1. The new card appears in the queue in real-time. - Triage Inspection: View the priorities and score contributors (+40 for missing required view).
- Visual Comparison: Inspect the
CURRENT STAGEvsPREVIOUS APPROVED STAGEside-by-side comparator showing visual change signals. - Review Telemetry: Observe the ML/Heuristic analysis telemetry card.
- Record Verdict: Type notes, defocus input, and press keyboard shortcut
R(Request Photos). - Audit Trail: Scroll down to verify the append-only audit trail logs the review transaction.
Scores are calculated deterministically on the backend (Ruleset: triage-v1):
- Base Score:
0 - Missing Required View:
+40 - Poor Quality (Blur/Exposure):
+30 - Stage Timing Deviation:
+15 - Previous Retake Requested:
+15 - Clamping: Clamped at a maximum of
100.
0 (Base) + 40 (Missing RIGHT view) + 15 (Stage timing deviation) = 55 (MEDIUM Priority)
Recommendation: REVIEW
Priority level: MEDIUM (Scores 30-59)
The comparator enables a detailed audit of progress photos against the last completed and approved stage:
CURRENT STAGE
↕
PREVIOUS APPROVED STAGE
- Similarity Index: Perceptual similarity score computed using 64-bit average hashing (aHash).
- Perceptual Difference: Relative Hamming distance between current and approved image hashes.
- Image Availability: Identifies if a comparative baseline image exists.
- Quality Status: Logs blur and exposure parameters of the current photo.
- Stage Timing: Registers days since the last clinician approval.
Visual comparison is a decision-support signal and is not a clinically validated determination of treatment outcome. [Decision Support Only]
The view classification pipeline is structured as follows:
Dataset
↓
Leakage Audit
↓
Train / Validation / Test Split
↓
PyTorch
↓
MobileNetV3-Small
↓
ONNX Export
↓
ONNX Runtime / CPU
↓
CV Service
↓
Clinician Workspace
The clinician dashboard renders the active model configuration or heuristic fallback:
- ML Active:
Analysis Method: ML Model: MobileNetV3-Small Version: view-classifier-v1 Inference: ONNX Runtime / CPU - Heuristic Fallback:
Analysis Method: HEURISTIC Model: heuristic-v1 Reason: ML inference unavailable (confidence < 0.85 threshold)
The current ML validation demonstrates training, export, runtime inference, integration, and dataset integrity checks. The available seed dataset is insufficient to estimate clinical generalization performance.
- Patient-level splits:
0subject overlaps (integrity verified). - Exact Duplicates:
0duplicate SHA-256 hashes (integrity verified). - Perceptual Duplicates:
0cross-split duplicate aHash values (integrity verified).
The independent validation report is available in EXTERNAL_DATASET_VALIDATION_REPORT.md.
- Laplacian Blur Sensitivity: Large intraoral photographs with smooth tooth surfaces and soft lighting gradients can naturally produce low Laplacian variance. The current blur heuristic therefore requires calibration against representative clinical imagery.
- Heuristic Thresholds: Basic thresholds serve as a priority triage filter rather than a diagnostic standard.
The verification commands have been executed and validated:
| Component | Verification | Result |
|---|---|---|
| Go | Unit tests | PASS (go test ./...) |
| Go | Race detector | PASS (go test -race ./...) |
| Python | Pytest | PASS (pytest) |
| Frontend | Production build | PASS (npm run build / zero build warnings) |
| E2E | Playwright flows | PASS (node e2e_test.js) |
| Security | Path traversal review | PASS (storage.go Rel validation checks) |
| Dataset | Leakage audit | PASS (check_leakage.py duplicate audits) |
The prototype implements the following security controls:
- JWT & RBAC: Gateway verifies role permissions (
PATIENTorCLINICIAN) embedded in signed JWT tokens. - Bcrypt Hashing: Passwords are fully salted and hashed using Bcrypt (cost factor 12) before database write.
- Upload Validation: Capped at 10MB; gateway uses
http.DetectContentTypemagic-byte inspection to verifyimage/jpegorimage/pngtypes. - Path Traversal Prevention: The file storage system cleans keys using
filepath.Cleanand validates that the resolved path is sub-nested under the base storage root usingfilepath.Rel:rel, err := filepath.Rel(s.basePath, fullPath) if err != nil || strings.HasPrefix(rel, "..") { return filepath.Join(s.basePath, filepath.Base(cleanKey)) }
- SQL Parameterization: Queries use PGX parameter syntax (
$1,$2), preventing SQL injection vectors. - CORS Policies: Configured restricted origin maps for local dev tools.
The following screenshots (available in docs/screenshots/) demonstrate the complete end-to-end user flow:
Clinician and patient login interface with Bcrypt credentials validation.
Patient portal detailing treatment protocol, instructions, and stages progress.
Image upload section displaying view criteria, format guidelines, and safety integrity check.
Live pipeline steps tracking database audit events as they complete.
Patient visual feedback showing queued status and quality warning alerts.
Dashboard showing incoming submissions sorted by prioritized triage scores.
Comparator displaying visual change signal, telemetry card details, and rule weights.
Clinician notes panel and keyboard shortcuts trigger to request photo retakes.
Relational database audit history showing all lifecycle timestamps.