update the codebase poc ver1

This commit is contained in:
DatTT127
2026-07-07 15:54:17 +07:00
parent fed5f277f4
commit 1622dc8fc5
452 changed files with 83999 additions and 66328 deletions

View File

@@ -17,25 +17,30 @@ Build a reproducible, air-gapped-first musculoskeletal ultrasound analysis platf
### Functional (Sprint 1-2)
- [ ] FR-25: Load knee DICOM → segment joint structures → measure synovium thickness → grade synovitis 0-3
- [ ] Grad-CAM overlay on primary viewport (zero extra clicks)
- [ ] Circuit-breaker Socratic dialogue (radiologist challenges AI grade before finalizing)
- [ ] Circuit-breaker Socratic dialogue (radiologist challenges AI grade before finalizing) across 3-tier LLM system (Edge Gemma → Gemini → MedGemma)
- [ ] BERT drift monitor against baseline MOH corpus
- [ ] RAG-Referee validates every LLM-generated explanation against top-k retrieved MOH guideline chunks
- [ ] RAG-Referee validates every LLM-generated explanation against top-k retrieved MOH guideline chunks (mandatory for cloud tiers, lightweight for edge)
- [ ] Decree 13 PII scrubbing on all outbound text (client-side + FastAPI middleware)
- [ ] ladybugDB ontology traversal for anatomical entity disambiguation
- [ ] GemmaE2B/MedGemma Vietnamese LLM consult (browser WebLLM local OR cloud Vertex AI) with MOH guideline citations
- [ ] 3-model LLM consult system: Edge Gemma (browser WebLLM local), Gemini (GCP Vertex AI, orchestration/translation), MedGemma (Modal, clinical deep-reasoning) with MOH guideline citations and cost guarding (<20% MedGemma usage)
- [ ] Circular 46/2018 PDF report generation
- [ ] Immutable audit log append (NFR-17) and HITL digital signature gate (NFR-19)
### Non-Functional (Critical)
- [ ] NFR-4: 150 MB idle app bundle
- [ ] NFR-5: ≤1.5 s inference (on-prem Triton)
- [ ] NFR-7: ≤200 ms TTFT token streaming
- [ ] NFR-5: 1.5 s inference (on-prem Triton); cloud tiers targeted at <30s median
- [ ] NFR-7: 200 ms TTFT token streaming; progressive streaming with 25s timeout for cloud responses
- [ ] NFR-8: Fault-tolerant across Wi-Fi drops (state preserved)
- [ ] NFR-10: Automated Generative Safety Guardrails: <90% verification prohibited, 100% of LLM-generated patient text explanations must pass verification. 3-tier guardrail: prompt rules + BERT edge detection (Tier 1) Vertex AI safety filters (Tier 2) RAG-Referee mandatory validation (Tier 3)
- [ ] NFR-11: Onboarding 45 minutes
- [ ] NFR-12: Zero-Friction Explainability Integration
- [ ] NFR-13: Spatial Layer-Activation Mapping
- [ ] NFR-14: No client-side GPU/neural accelerator required
- [ ] NFR-15: Circular 46 EMR compliance
- [ ] NFR-16: Air-gapped primary; NFR-16a PoC fallback with redaction/consent/audit
- [ ] NFR-16: Air-gapped primary; NFR-16a PoC fallback with redaction/consent/audit for cloud LLM tiers (Gemini + MedGemma)
- [ ] NFR-16a: Emergency Cloud Fallback with Redaction (PoC-SCOPE). Cloud LLM API (GCP Vertex AI Gemini + Modal MedGemma) invoked ONLY when browser-side WebLLM (Edge Gemma) is unavailable or orchestrates cloud task. FastAPI Redaction Middleware MUST strip all Decree 13 PII fields before egress. GCP CSEK + 30-day lifecycle + 1-year auto-delete. Audit-log commit + consent before egress. MedGemma usage <20% target with alerting. NFR-16a retired upon PoC sign-off.
- [ ] NFR-17: Immutable audit log
- [ ] NFR-18: 100% LLM text cites MOH protocol via RAG
- [ ] NFR-18: 100% LLM text cites MOH protocol via RAG. Mandatory RAG pre-processing for all 3 tiers (not optional tool-calling). RAG-Referee validates MedGemma output.
- [ ] NFR-19: HITL digital signature before FINALIZED/ARCHIVED
---
@@ -79,7 +84,8 @@ System_Boundary(hospital_lan, "Hospital LAN (Air-Gapped, ≤10 Mbps)") {
System_Boundary(k3s_cluster, "K3s Orchestration Cluster") {
System_Boundary(edge_servers, "Application Server Cluster") {
Container(edge_inference, "Edge Inference Service", "FastAPI (Python 3.12, Uvicorn)", "DICOM ingest, 3-step ML pipeline orchestration, Grad-CAM generation, report assembly, consult SSE streaming.")
Container(rag_svc, "RAG & Knowledge Service", "FastAPI (Python 3.12, asyncpg)", "pgvector top-k retrieval, ladybugDB ontology wrapper, GemmaE2B/MedGemma consult route, RAG-Referee validation.")
Container(cloud_llm_gateway, "Cloud LLM Gateway", "FastAPI (Python 3.12, Uvicorn)", "Routes orchestration/translation to Gemini (GCP) and clinical deep-reasoning to MedGemma (Modal); NFR-16a redaction, consent, audit enforcement; consult_mode state machine extension; cost guarding for MedGemma usage.")
Container(rag_svc, "RAG & Knowledge Service", "FastAPI (Python 3.12, asyncpg)", "pgvector top-k retrieval, ladybugDB ontology wrapper, RAG-Referee validation for MedGemma output, mandatory RAG pre-processing for all tiers.")
Container(audit_svc, "Audit & EMR Service", "Node.js / FastAPI Worker", "Immutable append-only audit events; HL7/FHIR EMR push with outbox retry.")
Container(api_gw, "API Gateway", "Envoy", "TLS termination, rate limiting, routing, OIDC validation pass-through.")
Container(auth_svc, "Identity & Access", "Keycloak", "OIDC, RBAC, realm vkist-msk.")
@@ -94,11 +100,12 @@ System_Boundary(hospital_lan, "Hospital LAN (Air-Gapped, ≤10 Mbps)") {
}
}
System_Ext(triton, "Triton Inference Server", "NVIDIA Triton, ONNX/TensorRT, gRPC 8001", "3-step ML pipeline (angle → inflammation → segmentation) + embedding extraction.")
System_Ext(triton, "Triton Inference Server", "NVIDIA Triton, ONNX/TensorRT, gRPC 8001", "3-step ML pipeline (angle → inflammation → segmentation) + EmbeddingGemma RAG embeddings.")
System_Ext(emr, "Hospital EMR / HIS", "HL7/FHIR", "Finalized report storage, prescription sync, ground-truth records.")
System_Ext(pacs, "PACS / Ultrasound Device", "DICOM/C-MOVE", "Image capture and retrieval.")
System_Ext(gcp_cdn, "GCP CDN Emergency Fallback", "Signed-URL Cloud CDN (ap-southeast1)", "Non-clinical model weight distribution when intranet CDN unreachable.")
System_Ext(vertex_ai, "GCP Vertex AI", "GemmaE2B via REST", "PoC-only NFR-16a inference tier; redacted payloads only.")
System_Ext(vertex_ai, "GCP Vertex AI (Gemini)", "Gemini via REST", "PoC-only NFR-16a inference tier: orchestration, translation, UI planning; redacted payloads only.")
System_Ext(modal_medgemma, "Modal MedGemma", "FastAPI + Transformers (T4 GPU)", "PoC-only NFR-16a clinical deep-reasoning endpoint; redacted payloads with RAG-Referee validation; keep-warm instances for latency budget.")
Rel(radiologist, pwa, "Loads scan, reviews grade, finalizes report, views explanations", "HTTPS 443")
Rel(admin, nginx, "Deploys, monitors, configures", "HTTPS 443 / SSH")
@@ -118,9 +125,16 @@ Rel(edge_inference, minio, "DICOM, overlays, reports", "S3 API")
Rel(edge_inference, auth_svc, "Token introspection", "OIDC")
Rel(edge_inference, obs_stack, "/metrics", "HTTP 9090")
Rel(edge_inference, cloud_llm_gateway, "Routes cloud consult", "HTTP 8000")
Rel(cloud_llm_gateway, vertex_ai, "Gemini proxy (NFR-16a redacted)", "HTTPS 443 / REST")
Rel(cloud_llm_gateway, modal_medgemma, "MedGemma proxy (NFR-16a redacted)", "HTTPS 443 / REST")
Rel(cloud_llm_gateway, redis, "Consult mode, consent, rate-limit", "TCP 6379")
Rel(cloud_llm_gateway, postgres, "Audit log append", "SQL 5432")
Rel(rag_svc, postgres, "pgvector HNSW queries", "SQL 5432")
Rel(rag_svc, redis, "Guideline cache, pub/sub invalidation", "TCP 6379")
Rel(rag_svc, minio, "Guideline PDF ingestion staging", "S3 API")
Rel(rag_svc, edge_inference, "RAG + RAG-Referee results", "HTTP")
Rel(audit_svc, postgres, "Appends immutable audit events", "SQL 5432")
Rel(audit_svc, emr, "Finalized report push", "HL7/FHIR")
@@ -130,7 +144,6 @@ Rel(edge_inference, emr, "Report push (via audit-svc wrapper)", "HL7/FHIR")
Rel(pwa, pacs, "Direct DICOM capture / C-MOVE", "DICOM")
Rel(k3s_cluster, gcp_cdn, "Model weight fetch fallback (non-clinical)", "HTTPS 443 (signed URL)")
Rel(edge_inference, vertex_ai, "PoC-only cloud consult (NFR-16a redacted)", "HTTPS 443 / REST")
Rel(postgres, minio, "Backup checkpoint", "S3 API")
@enduml
@@ -143,8 +156,14 @@ Container communication summary:
| PWA | NGINX | HTTPS 443 | All API requests |
| NGINX | Envoy | HTTP 8000 | Route upstream |
| Envoy | Edge Inference | HTTP 8000 | `/api/*` |
| Envoy | Cloud LLM Gateway | HTTP 8000 | `/api/cloud-orchestrate`, `/api/cloud-consult` |
| Envoy | RAG Service | HTTP 8001 | `/rag/*` |
| Envoy | Keycloak | HTTP 8080 | OIDC validation |
| Edge Inference | Cloud LLM Gateway | HTTP 8000 | Route cloud consult |
| Cloud LLM Gateway | Gemini (Vertex AI) | HTTPS 443 / REST | Orchestration, translation, UI planning (NFR-16a) |
| Cloud LLM Gateway | MedGemma (Modal) | HTTPS 443 / REST | Clinical deep-reasoning, report finalization (NFR-16a) |
| Cloud LLM Gateway | Redis | TCP 6379 | Consult mode, consent, rate-limit |
| Cloud LLM Gateway | Postgres | TCP 5432 | Audit log append |
| Edge Inference | Triton | gRPC 8001 | 3-step ML pipeline + embeddings |
| Edge Inference | Postgres | TCP 5432 | SQL + pgvector HNSW |
| Edge Inference | Redis | TCP 6379 | Session, rate-limit, consult-mode |
@@ -165,23 +184,24 @@ Container communication summary:
!include <C4/C4_Component>
Container_Boundary(edge_svc, "edge-inference-svc (FastAPI)") {
Component(api, "API Controller", "REST + SSE", "/api/analyze, /api/consult/stream")
Component(api, "API Controller", "REST + SSE", "/api/analyze, /api/cloud-orchestrate redirect")
Component(stream, "SSE Token Streamer", "FastAPI StreamingResponse", "200 ms TTFT, heart-beat every 30s")
Component(preproc, "Image Preprocessor", "OpenCV + pydicom", "CLAHE, rescale, DICOM header scrub (client-side pre-check)")
Component(router, "Inference Router", "consult_mode state", "Tier selection: WASM→Triton→Vertex→Templates")
Component(breaker, "Circuit Breaker", "pybreaker", "Wrap Triton + EMR calls; fail-open to templates")
Component(router, "Inference Router", "consult_mode state", "Tier selection: Edge Gemma (tier_1) → Gemini (tier_2, orchestration) → MedGemma (tier_3, clinical) → Templates (tier_4)")
Component(breaker, "Circuit Breaker", "pybreaker", "Wrap Triton + EMR + Cloud LLM calls; fail-open to templates")
Component(pipeline, "ML Pipeline", "gRPC client", "Angle→Inflammation→Segmentation→Measurement")
Component(gradcam, "Grad-CAM Generator", "OpenCV", "Spatial activation overlay; base64 PNG to PWA")
Component(report, "Report Builder", "WeasyPrint / ReportLab", "Circular 46 PDF; HITL signature gate before FINALIZED")
Component(rag, "RAG Service", "pgvector SQL", "Retrieve top-5 MOH chunks; enforce NFR-18 citation")
Component(referee, "RAG-Referee", "BERT classifier", "Reject LLM text if citation confidence < threshold")
Component(rag, "RAG Service", "pgvector SQL", "Retrieve top-5 MOH chunks; mandatory pre-generation for all tiers; enforce NFR-18 citation")
Component(referee, "RAG-Referee", "BERT classifier", "Reject MedGemma text if citation confidence < threshold; mandatory for tier_3")
Component(nlp, "NLP Scrubber", "Microsoft Presidio", "Re-verify edge redaction; refine/clean residual PII; error if unresolvable")
Component(audit, "Audit Logger", "Append-only writer", "Every tier transition, consent, finalize, override")
Component(audit, "Audit Logger", "Append-only writer", "Every tier transition, consent, finalize, override; cloud_llm_escalation events")
}
Rel(api, stream, "delegates", "SSE")
Rel(api, preproc, "validates image", "sync")
Rel(api, router, "selects tier", "sync")
Rel(router, pipeline, "invokes", "gRPC")
Rel(router, api, "redirects cloud consult", "HTTP")
Rel(router, stream, "fallback text", "SSE")
Rel(api, gradcam, "requests overlay", "sync")
Rel(api, report, "generates PDF", "sync")
@@ -192,39 +212,27 @@ Rel(api, audit, "writes event", "sync")
@enduml
```
### 4.3 Component Diagrams (Tier 3)
**Edge Inference Service (edge-inference-svc)**
**Cloud LLM Gateway**
```plantuml
@startuml
!include <C4/C4_Component>
Container_Boundary(edge_svc, "edge-inference-svc (FastAPI)") {
Component(api, "API Controller", "REST + SSE", "/api/analyze, /api/consult/stream")
Component(stream, "SSE Token Streamer", "FastAPI StreamingResponse", "200 ms TTFT, heart-beat every 30s")
Component(preproc, "Image Preprocessor", "OpenCV + pydicom", "CLAHE, rescale, DICOM header scrub (client-side pre-check)")
Component(router, "Inference Router", "consult_mode state", "Tier selection: WASM→Triton→Vertex→Templates")
Component(breaker, "Circuit Breaker", "pybreaker", "Wrap Triton + EMR calls; fail-open to templates")
Component(pipeline, "ML Pipeline", "gRPC client", "Angle→Inflammation→Segmentation→Measurement")
Component(gradcam, "Grad-CAM Generator", "OpenCV", "Spatial activation overlay; base64 PNG to PWA")
Component(report, "Report Builder", "WeasyPrint / ReportLab", "Circular 46 PDF; HITL signature gate before FINALIZED")
Component(rag, "RAG Service", "pgvector SQL", "Retrieve top-5 MOH chunks; enforce NFR-18 citation")
Component(referee, "RAG-Referee", "BERT classifier", "Reject LLM text if citation confidence < threshold")
Component(nlp, "NLP Scrubber", "Microsoft Presidio", "Re-verify edge redaction; refine/clean residual PII; error if unresolvable")
Component(audit, "Audit Logger", "Append-only writer", "Every tier transition, consent, finalize, override")
Container_Boundary(cloud_gw, "cloud-llm-gateway (FastAPI)") {
Component(api, "Cloud API Controller", "REST + SSE", "/api/cloud-orchestrate, /api/cloud-consult, /api/cloud-consult/stream")
Component(gateway, "Cloud LLM Router", "task_type matcher", "Routes orchestration/translation → Gemini (tier_2); clinical deep-reasoning → MedGemma (tier_3)")
Component(consent, "Consent Enforcer", "Redis + NFR-16a checklist", "Validates consent token + redaction manifest before egress")
Component(audit, "Cloud Audit Emitter", "PostgreSQL append-only", "egress_consent, egress_response, cloud_llm_escalation events")
Component(cost, "Cost Guard", "Redis counter + Prometheus", "Tracks MedGemma usage ratio; alerts if >20% over 24h window")
Component(referee, "RAG-Referee Trigger", "BERT classifier", "Mandatory validation for MedGemma output before SSE to PWA")
Component(rag, "RAG Pre-processing", "pgvector SQL", "Mandatory top-k injection before any cloud LLM generation")
}
Rel(api, stream, "delegates", "SSE")
Rel(api, router, "selects tier", "sync")
Rel(router, pipeline, "invokes", "gRPC")
Rel(router, stream, "fallback text", "SSE")
Rel(api, preproc, "validates image", "sync")
Rel(api, gradcam, "requests overlay", "sync")
Rel(api, report, "generates PDF", "sync")
Rel(api, rag, "queries MOH", "SQL")
Rel(rag, referee, "validates citations", "sync")
Rel(api, nlp, "scrubs output", "sync")
Rel(api, audit, "writes event", "sync")
Rel(api, consent, "verifies", "sync")
Rel(api, gateway, "routes", "sync")
Rel(gateway, rag, "injects chunks", "sync")
Rel(gateway, referee, "validates output", "sync")
Rel(gateway, audit, "logs egress", "sync")
Rel(gateway, cost, "increments counter", "sync")
@enduml
```
@@ -309,13 +317,14 @@ app/
│ ├── auth.py # Keycloak OIDC validation
│ ├── phi_scrub.py # Microsoft Presidio redaction gate (NFR-16a); refine edge output; error if unresolvable PII
│ └── audit.py # Append-only event emitter
├── routers/
├── routers/ # FastAPI route handlers (existing + new cloud LLM)
│ ├── analyze.py # POST /api/analyze (sync 3-step pipeline)
│ ├── consult.py # SSE /api/consult/stream (GemmaE2B/MedGemma + RAG + guardrail session management)
│ ├── pacs.py # C-MOVE proxy + DICOM upload
│ ├── emr.py # HL7/FHIR push with outbox
── admin.py # Model update, drift review, cache invalidation
├── services/
── admin.py # Model update, drift review, cache invalidation
│ ├── cloud_orchestrate.py # POST /api/cloud-orchestrate (Gemini proxy for orchestration/translation)
│ └── cloud_consult.py # POST /api/cloud-consult + GET /api/cloud-consult/stream (MedGemma proxy)
├── services/ # Business logic modules (existing + new cloud gateway)
│ ├── inference_router.py # consult_mode state machine
│ ├── triton_client.py # gRPC with retry decorator
│ ├── rag.py # pgvector top-k + citation formatter
@@ -324,11 +333,12 @@ app/
│ ├── redaction.py # Presidio AnonymizerEngine; re-verify edge redaction; refine residual PII; error if unresolvable
│ ├── report.py # Circular 46 PDF + HITL signature
│ ├── ontology.py # ladybugDB C++ bindings wrapper
── audit_writer.py # WAL append
── audit_writer.py # WAL append
│ └── cloud_llm_gateway.py # Routes between Gemini (tier_2) and MedGemma (tier_3) based on task_type + consult_mode; NFR-16a consent/redaction/audit enforcement
├── models/
│ ├── dto.py # Request/response schemas (Pydantic v2)
│ ├── domain.py # Case, Session, Grade, Embedding entities
│ └── enums.py # ConsultMode, Grade, Tier
│ └── enums.py # ConsultMode (tier_1..tier_4), Grade, Tier
└── infra/
├── cache.py # Redis client (5 data types only)
├── db.py # SQLAlchemy async engine + pgvector
@@ -443,22 +453,31 @@ Server-side FastAPI contracts:
| Method | Path | Auth | Request | Response | Notes |
|--------|------|------|---------|----------|-------|
| POST | `/api/analyze` | JWT | multipart DICOM | JSON + Grad-CAM PNG | Sync, 1.5 s target |
| GET | `/api/consult/stream` | JWT + consent | SSE text stream | NDJSON chunks | Token streaming ≤200 ms TTFT |
| POST | `/api/cloud-orchestrate` | JWT + consent | JSON (task_type, prompt) | JSON text + tier | Gemini proxy; orchestration/translation/UI tasks |
| POST | `/api/cloud-consult` | JWT + consent | JSON (task_type, prompt) | JSON text + tier | MedGemma proxy; clinical deep-reasoning |
| GET | `/api/cloud-consult/stream` | JWT + consent | query params | SSE text stream | MedGemma streaming; 25s timeout, 30s budget |
| POST | `/api/emr/push` | JWT | case_id | 202 Accepted | Outbox if offline |
| POST | `/api/admin/models` | Admin | modelZip | 200 OK | K3s rolling restart |
| GET | `/api/rag/citations?q=` | JWT | query string | JSON top-5 chunks | NFR-18 |
| POST | `/api/safety/guardrail-check` | JWT | payload | GuardrailResult | NFR-10 edge guardrail |
| GET | `/api/health` | | | HealthStatus | Liveness |
| GET | `/api/model-registry` | JWT | | ModelCatalog | Model registry |
| POST | `/api/models/register` | Admin | modelZip | RegistrationResult | Model upload |
### 6.2 SSE Consult Stream Contract
```
event: token
data: {"text":"The","confidence":0.92}
data: {"text":"The","confidence":0.92,"tier":"tier_2"}
event: citation
data: {"source":"MOH guideline 2024 §3.2","page":12}
data: {"source":"MOH guideline 2024 §3.2","page":12,"tier":"tier_2"}
event: tier_change
data: {"from":"tier_1","to":"tier_2","reason":"edge_unavailable"}
event: done
data: {"tier":"tier_2","latency_ms":340}
data: {"tier":"tier_2","latency_ms":340,"model":"gemini-2.5-pro"}
```
---
@@ -475,6 +494,9 @@ data: {"tier":"tier_2","latency_ms":340}
| Redis | | OSS | **Use** | Scoped to 5 types; self-hosted |
| MinIO | | OSS | **Use** | S3-compatible; self-hosted |
| Auth | Build (Keycloak) | Auth0/Okta SaaS | **Build** | NFR-16: Keycloak on-prem, no SaaS identity |
| Cloud LLM Gateway | Build | | **Build** | FastAPI service enforcing NFR-16a redaction/consent/audit; routes Gemini/MedGemma based on task_type |
| Gemini (Vertex AI) | | GCP PoC | **Use (NFR-16a)** | Orchestration, translation, UI planning; PoC only with redaction |
| MedGemma (Modal) | | Modal deploy | **Deploy (NFR-16a)** | Clinical deep-reasoning; PoC only with redaction + RAG-Referee |
| EMR integration | Build | Mirth Connect | **Build** | Thin HL7 wrapper FastAPI EMR; keeps surface area small |
| CI/CD | Jenkins in K3s | SaaS GitHub Actions | **Build** | Jenkins inside LAN; cloud GitLab via SSH |
| Issue tracking | Self-hosted Jira | Atlassian Cloud | **Build (NFR-16a)** | Cloud VM, compensating controls |
@@ -520,15 +542,20 @@ data: {"tier":"tier_2","latency_ms":340}
SNOMED-CT knee/hip subset; MSK entity relationships; C++ embedded bindings in FastAPI.
- [ ] **T3-C RAG service + RAG-Referee** (M)
`/rag/query`; top-5 retrieval; BERT classifier to validate LLM citations; reject if threshold fail.
`/rag/query`; top-5 retrieval; BERT classifier to validate LLM citations; reject if threshold fail. Mandatory for MedGemma (Tier 3) output; lightweight for Gemini (Tier 2) and Edge Gemma (Tier 1).
- [ ] **T3-D Browser WebLLM + Cloud MedGemma LLM endpoints** (L)
Browser: WebLLM (GemmaE2B-Q4) loaded via Service Worker from intranet/GCP CDN; runs in separate WebWorker from CV pipeline.
Cloud: MedGemma on GCP Vertex AI (NFR-16a governed); FastAPI wrapper with streaming + Decree 13 redaction middleware.
Triton: EmbeddingGemma only (768-dim RAG embeddings), no LLM hosting.
- [ ] **T3-D 3-Model LLM System: Edge Gemma + Gemini + MedGemma** (L)
Tier 1 (Edge Gemma): Browser WebLLM (GemmaE2B-Q4) loaded via Service Worker from intranet/GCP CDN; runs in dedicated WebWorker.
Tier 2 (Gemini): GCP Vertex AI (GCP Vertex AI Gemini) for orchestration, translation, UI planning; FastAPI wrapper with streaming + Decree 13 redaction middleware.
Tier 3 (MedGemma): Modal-deployed MedGemma large-24b for clinical deep-reasoning and report finalization; FastAPI gateway with keep-warm instances, 30s timeout, RAG-Referee validation.
Tier 4: MOH guideline templates (rule-based fallback).
Consult mode state machine extended: `tier_1` `tier_2` `tier_3` `tier_4`.
- [ ] **T3-E Decree 13 scrubber (client + server)** (M)
Client: Dexie.js pre-egress regex. Server: FastAPI middleware for NFR-16a redaction; role-hash tokens.
Client: Dexie.js pre-egress regex. Server: FastAPI middleware for NFR-16a redaction; role-hash tokens. Applied to all cloud tiers (Tier 2 + Tier 3).
- [ ] **T3-F Cloud LLM Gateway** (M)
FastAPI service (`/api/cloud-orchestrate`, `/api/cloud-consult`, `/api/cloud-consult/stream`); routes based on `task_type`; enforces consent + redaction + audit before egress; tracks MedGemma usage for <20% cost guard target; extends consult_mode state machine.
### Phase 4: Compliance & HITL
- [ ] **T4-A Immutable audit log** (M)
@@ -561,13 +588,13 @@ Deliverables: K3s cluster up, DB VM ready, CI/CD pipeline green, PWA shell live.
Deliverables: `/api/analyze` end-to-end; Grad-CAM overlay visible in PWA; circuit-breaker handles Triton failure.
### Week 5-6: Phase 3
Deliverables: RAG queries return MOH citations; GemmaE2B/MedGemma streams Vietnamese explanations; RAG-Referee blocks unmapped LLM text.
Deliverables: RAG queries return MOH citations; Edge Gemma (WebLLM) primary, Gemini (Vertex AI) for orchestration/translation, MedGemma (Modal) for clinical deep-reasoning; RAG-Referee validates MedGemma output; consult_mode state machine extended to tier_1→tier_2→tier_3→tier_4.
### Week 7: Phase 4
Deliverables: Audit log immutable; HITL signature enforces finalization; Circular 46 PDF exports.
Deliverables: Audit log immutable with new event types (egress_consent_gemini, egress_consent_medgemma, cloud_llm_escalation); HITL signature enforces finalization; Circular 46 PDF exports; cost guarding (<20% MedGemma usage) enforced.
### Week 8: Phase 5 + Sprint Review
Deliverables: Dashboards, drift monitor, integration tests, demo-ready PWA.
Deliverables: Dashboards (tier transitions, MedGemma usage count, latency p50/p99, consent events), drift monitor, integration tests, demo-ready PWA with 3-model routing status.
---