chore: update readme
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
A clinical records digitization platform built with ASP.NET Core 8, PostgreSQL, MinIO, Redis, and a Vue 3 workstation UI. The domain models the scan-to-approved lifecycle at the center of any paper chart digitization system: scanned document upload, human data entry, dual-human verification with separation of duties, site-configurable clinical approval routing, atomic promotion to live clinical tables, and governed correction via supersession.
|
||||
|
||||
**Implementation status:** Phases 1–10 are complete. Phase 7 delivers the digitization workstation UI (`vigilcare-records-web`) with role-specific views for intake, entry, verification, clinical approval, live capture, patient history, and supervisor dashboard. Phase 8 adds Prometheus metrics, supervisor work-queue overview, cursor-paginated batch audit trails, promotion deferral with exponential backoff retry, and a Docker monitoring stack (Prometheus on **9095**, Grafana on **3013**). Phase 9 adds extended demo seed data (10 batches across all types, tracks, and statuses), the E2E verification script (`scripts/run-vigilcare-records-verification-p9.sh`), and clinical scenario documentation ([digitization-workstation-guide.md](docs/digitization-workstation-guide.md)). Phase 10 adds barcode/QR cover sheets for high-volume backfill: generate printable cover pages with encoded batch type, track, optional patient, and optional entry-clerk pre-assignment; barcode-assisted upload auto-creates batches and skips manual classification. Post-phase hardening includes health check endpoints, user management APIs, auth rate limiting, document access audit events, batch cancellation, list/queue sorting (`sortBy`/`sortDirection`), unified promotion retry logic, normalized patient deduplication, and assignment-time `IN_ENTRY` transitions. Phase 11 (HL7 FHIR R4 read API) is planned next — see [docs/plans/phase-11-plan.md](docs/plans/phase-11-plan.md). See [Implemented Phases](#implemented-phases) and the [gap analysis](docs/vigilcare-records-gap-analysis.md) for remaining work.
|
||||
**Implementation status:** Phases 1–11 are complete. Phase 7 delivers the digitization workstation UI (`vigilcare-records-web`) with role-specific views for intake, entry, verification, clinical approval, live capture, patient history, and supervisor dashboard. Phase 8 adds Prometheus metrics, supervisor work-queue overview, cursor-paginated batch audit trails, promotion deferral with exponential backoff retry, and a Docker monitoring stack (Prometheus on **9095**, Grafana on **3013**). Phase 9 adds extended demo seed data (10 batches across all types, tracks, and statuses), the E2E verification script (`scripts/run-vigilcare-records-verification-p9.sh`), and clinical scenario documentation ([digitization-workstation-guide.md](docs/digitization-workstation-guide.md)). Phase 10 adds barcode/QR cover sheets for high-volume backfill: generate printable cover pages with encoded batch type, track, optional patient, and optional entry-clerk pre-assignment; barcode-assisted upload auto-creates batches and skips manual classification. Phase 11 adds an HL7 FHIR R4 read-only API for promoted clinical data (`Patient`, `Encounter`, `Observation`) with LOINC code mapping, search bundles with pagination links, `$everything`, and an administrator FHIR Explorer view at `/fhir-explorer`. Post-phase hardening includes health check endpoints, user management APIs, auth rate limiting, document access audit events, batch cancellation, list/queue sorting (`sortBy`/`sortDirection`), unified promotion retry logic, normalized patient deduplication, and assignment-time `IN_ENTRY` transitions. Phase 12 (backend-driven batch-type field requirements) is planned next — see [docs/plans/phase-12-plan.md](docs/plans/phase-12-plan.md). See [Implemented Phases](#implemented-phases) and the [gap analysis](docs/vigilcare-records-gap-analysis.md) for remaining work.
|
||||
|
||||
## Domain Model — How It Maps to a Real Clinical System
|
||||
|
||||
@@ -62,7 +62,9 @@ Append-only audit log entry for every state transition, field-level correction,
|
||||
- **Batch Audit Trail API** — `GET /digitization-batches/:id/events` returns cursor-paginated digitization events with actor username and full name; accessible by administrator, verifier, and clinical approver roles
|
||||
- **User Directory and Management** — `GET /users?role=` lists active users for batch assignment; administrators can `POST /users` (create), `PATCH /users/:id` (update name, role, active flag), `POST /users/:id/reset-password`, and any authenticated user can `POST /users/me/change-password` with current-password verification
|
||||
- **Document Access Audit** — `GET /digitization-batches/:id` writes a `document_accessed` digitization event (deduplicated per user within 5 minutes) whenever a presigned scan URL is issued
|
||||
- **Digitization Workstation UI** — Vue 3 SPA at `vigilcare-records-web`: role-based routing and nav (intake, cover sheets, entry, verification, clinical approval, live capture, patient history, supervisor dashboard); split-pane scan viewer with zoom/pan/rotate; cover sheet management view (generate, list, print PDF); barcode-assisted intake (scan/type cover sheet code to auto-fill batch type, track, patient, then upload); draft entry with auto-save and batch-type-aware fields (allergies, medications, discharge diagnosis); field-level verification checkboxes; clinical approval queue with scan review, approve/reject, and retroactive alert toggle; live capture form for new or existing encounters with attestation and password confirm; patient history timeline with correction chain and audit trail; presigned URL refresh for long sessions; JWT refresh interceptor and toast notifications
|
||||
- **Digitization Workstation UI** — Vue 3 SPA at `vigilcare-records-web`: role-based routing and nav (intake, cover sheets, entry, verification, clinical approval, live capture, patient history, supervisor dashboard, FHIR Explorer); split-pane scan viewer with zoom/pan/rotate; cover sheet management view (generate, list, print PDF); barcode-assisted intake (scan/type cover sheet code to auto-fill batch type, track, patient, then upload); draft entry with auto-save and batch-type-aware fields (allergies, medications, discharge diagnosis); field-level verification checkboxes; clinical approval queue with scan review, approve/reject, and retroactive alert toggle; live capture form for new or existing encounters with attestation and password confirm; patient history timeline with correction chain and audit trail; presigned URL refresh for long sessions; JWT refresh interceptor and toast notifications
|
||||
- **HL7 FHIR R4 Read API** — read-only FHIR endpoints at `/fhir` for promoted clinical data: `GET /fhir/metadata` (anonymous `CapabilityStatement`); authenticated read and search for `Patient`, `Encounter`, and `Observation`; MRN search via `Patient?identifier=`; LOINC bidirectional mapping for observation codes (e.g. `HEART_RATE` ↔ `8867-4`); vital-signs category search; date filtering on `recordedAt`; `GET /fhir/Patient/{id}/$everything` composite bundle; search bundles with `self`/`next` pagination links; `404` responses as FHIR `OperationOutcome`; `application/fhir+json` content negotiation via `FhirJsonOutputFormatter`
|
||||
- **FHIR Explorer UI** — administrator-only Vue view at `/fhir-explorer`: browse Patient/Encounter/Observation resources, run FHIR searches, inspect raw JSON, load Patient `$everything`, and open the CapabilityStatement metadata link; dev proxy at `/fhir` → API port 5217
|
||||
- **Live Capture (Track B)** — `POST /live-capture/encounters/{encounterId}/observations` and `POST /live-capture/encounters` for credentialed clinicians entering vitals at bedside; clinician attestation + password re-confirm replaces the dual-human verification gate; observations promote synchronously to live tables in a single transaction with `source = live_capture`; critical threshold evaluation runs before the response returns, with inline `criticalAlert` per observation, committed `ClinicalAlert` rows, and `observation.recorded` / `alert.generated` outbox events; `422 ATTESTATION_REQUIRED`, `422 PASSWORD_CONFIRM_INVALID`, `422 EMPTY_OBSERVATIONS`, `409 ENCOUNTER_NOT_ACTIVE`, `409 ACTIVE_ENCOUNTER_EXISTS`
|
||||
- **Batch Status Machine** — explicit transition matrix enforced in the service layer; illegal transitions return `409`; `PROMOTED` and `CANCELLED` are terminal — corrections require a new batch with `supersedesBatchId`
|
||||
- **JWT Authentication** — `POST /auth/login` returns access token (15 min) and refresh token (7 days); `POST /auth/refresh` rotates tokens; `POST /auth/logout` revokes server-side; `GET /auth/me` returns authenticated user profile; BCrypt password hashing; login and refresh rate-limited to 10 requests per 5 minutes per client (`429`)
|
||||
@@ -102,6 +104,7 @@ HTTP request
|
||||
├── LiveCaptureService (Track B synchronous promotion + critical alert evaluation)
|
||||
├── CoverSheetService (generate, lookup, redeem, list cover sheets)
|
||||
├── CoverSheetPdfGenerator (printable PDF with QR codes)
|
||||
├── FhirService (FHIR R4 read/search/$everything over promoted clinical tables)
|
||||
├── DocumentStorageService (MinIO upload, SHA-256, presigned URLs)
|
||||
├── PlausibilityValidator (per-code numeric range guard)
|
||||
├── PostgreSQL (EF Core — writes, keyed reads, clinical schema for live tables)
|
||||
@@ -147,6 +150,7 @@ HTTP request
|
||||
| Metrics | Prometheus (`prometheus-net`) + Grafana |
|
||||
| Docs | Swagger / OpenAPI (Swashbuckle) |
|
||||
| Barcode / PDF | QRCoder (cover sheet QR codes; raw PDF generation) |
|
||||
| FHIR | Hl7.Fhir.R4 5.x (Firely SDK — Patient, Encounter, Observation, Bundle, OperationOutcome) |
|
||||
| Testing | xUnit + FluentAssertions + WebApplicationFactory |
|
||||
|
||||
---
|
||||
@@ -162,6 +166,7 @@ VigilCareRecords/
|
||||
│ │ ├── ApprovalController.cs # Batch approval, promotion deferral (202), promotion to live tables
|
||||
│ │ ├── AuthController.cs # JWT login, token refresh, logout, authenticated user profile
|
||||
│ │ ├── CoverSheetController.cs # Cover sheet generate, lookup, list, PDF export
|
||||
│ │ ├── Fhir/ # FHIR R4 read/search controllers (Patient, Encounter, Observation, metadata)
|
||||
│ │ ├── DigitizationBatchesController.cs # Batch CRUD, document upload, assignment, events, promote
|
||||
│ │ ├── DraftController.cs # Draft data entry: patient, encounter, observations, submit
|
||||
│ │ ├── PatientsController.cs # Patient search and digitization history
|
||||
@@ -171,22 +176,24 @@ VigilCareRecords/
|
||||
│ │ └── WorkQueueController.cs # Work queues and supervisor overview
|
||||
│ ├── HealthChecks/MinioHealthCheck.cs # MinIO bucket-exists readiness probe
|
||||
│ ├── Domain/ … # Entities, enums (batch, draft, clinical, user)
|
||||
│ ├── Services/ … # Auth, batch, draft, verification, promotion, work queue, patient registry, user directory, live capture
|
||||
│ ├── Services/ … # Auth, batch, draft, verification, promotion, FHIR, work queue, patient registry, user directory, live capture
|
||||
│ ├── Infrastructure/Fhir/ … # FHIR mappers, JSON formatter, OperationOutcome helpers
|
||||
│ ├── Models/Records/ … # Request/response DTOs
|
||||
│ ├── Data/ … # EF Core context, configurations, migrations, seed
|
||||
│ └── … # Middleware, Common, Infrastructure
|
||||
├── vigilcare-records-web/ # Vue 3 digitization workstation UI
|
||||
│ ├── src/
|
||||
│ │ ├── api/client.ts # Axios client with JWT interceptor and proactive refresh
|
||||
│ │ ├── api/fhirClient.ts # Authenticated FHIR GET client (`Accept: application/fhir+json`)
|
||||
│ │ ├── stores/ # Pinia: auth, batches, liveCapture
|
||||
│ │ ├── router/index.ts # Role-based routes and navigation guards
|
||||
│ │ ├── views/ # Login, Intake, CoverSheets, Entry, Verification, Approval, LiveCapture, PatientHistory, QueueDashboard
|
||||
│ │ ├── views/ # Login, Intake, CoverSheets, Entry, Verification, Approval, LiveCapture, PatientHistory, QueueDashboard, FhirExplorer
|
||||
│ │ ├── components/ # ScanViewer, EntryForm, VerificationForm, BatchList, PatientSearch, AppHeader, ToastContainer, AssignClerkDialog
|
||||
│ │ ├── composables/ # usePresignedUrl (URL refresh), useToast (notifications)
|
||||
│ │ └── types/index.ts # TypeScript interfaces matching API response shapes
|
||||
│ ├── vite.config.ts # Dev server on port 3028; proxies /api → localhost:5217
|
||||
│ ├── vite.config.ts # Dev server on port 3028; proxies /api and /fhir → localhost:5217
|
||||
│ └── tailwind.config.js # Clinical color palette and layout component classes
|
||||
├── VigilCareRecordsAPI.Tests/ # Integration tests (Phases 1–10)
|
||||
├── VigilCareRecordsAPI.Tests/ # Integration tests (Phases 1–11)
|
||||
├── prometheus.yml # Prometheus scrape config (API on host.docker.internal:5217)
|
||||
├── docker-compose.yml # PostgreSQL, Redis, Seq, MinIO, Prometheus, Grafana
|
||||
├── scripts/
|
||||
@@ -198,10 +205,10 @@ VigilCareRecords/
|
||||
│ ├── run-vigilcare-records-phase-6-verification.sh
|
||||
│ ├── run-vigilcare-records-phase-8-verification.sh # Prometheus metrics, overview, events, retry
|
||||
│ ├── run-vigilcare-records-verification-p9.sh # E2E workflow + work queue overview smoke test
|
||||
│ └── run-vigilcare-records-phase-10-verification.sh # Cover sheets, barcode upload, PDF, auto-assign
|
||||
│ └── run-vigilcare-records-phase-11-verification.sh # FHIR metadata, read/search, $everything, integration tests
|
||||
│ ├── run-vigilcare-records-phase-10-verification.sh # Cover sheets, barcode upload, PDF, auto-assign
|
||||
│ └── run-vigilcare-records-phase-11-verification.sh # FHIR metadata, read/search, $everything, LOINC mapping
|
||||
└── docs/
|
||||
├── plans/ # Phase 1–11 implementation guides
|
||||
├── plans/ # Phase 1–13 implementation guides
|
||||
├── digitization-workstation-guide.md # Clinical scenarios and clerk workflow reference
|
||||
├── vigilcare-records-gap-analysis.md # Known gaps and hardening backlog
|
||||
└── vigilcare-records-prd.md # Product requirements and phase roadmap
|
||||
@@ -366,7 +373,7 @@ npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:3028`. The Vite dev server proxies `/api` requests to the API on port 5217.
|
||||
Open `http://localhost:3028`. The Vite dev server proxies `/api` and `/fhir` requests to the API on port 5217.
|
||||
|
||||
| Username | Password | Default route |
|
||||
|---|---|---|
|
||||
@@ -375,7 +382,7 @@ Open `http://localhost:3028`. The Vite dev server proxies `/api` requests to the
|
||||
| `verifier1` | `password` | `/verification` — field-level verification |
|
||||
| `approver1` | `password` | `/approval` — clinical sign-off before promotion |
|
||||
| `clinician1` | `password` | `/live-capture` — bedside vitals with attestation |
|
||||
| `admin1` | `password` | `/dashboard` — supervisor queue overview |
|
||||
| `admin1` | `password` | `/dashboard` — supervisor queue overview; `/fhir-explorer` — FHIR resource browser |
|
||||
|
||||
All roles can access `/patients` for patient search and digitization history.
|
||||
|
||||
@@ -410,6 +417,7 @@ Integration tests use `WebApplicationFactory` with PostgreSQL, Redis, and MinIO
|
||||
| `UserManagementTests` | 9 | User create/update/deactivate, admin password reset, self-service password change, duplicate username guard, weak password validation |
|
||||
| `CoverSheetBatchTests` | 10 | Cover sheet redeem on upload, reuse prevention, auto-assign from pre-assigned cover sheet |
|
||||
| `CoverSheetPdfTests` | 10 | Single and batch PDF generation, valid PDF structure with QR metadata |
|
||||
| `FhirIntegrationTests` | 11 | FHIR metadata, Patient/Encounter/Observation read and search, LOINC mapping, `$everything`, content-type, 404 OperationOutcome, bundle pagination |
|
||||
| `BatchOperationsTests` | — | Batch cancellation (status guards, Redis lock release), list/queue `sortBy`/`sortDirection` validation |
|
||||
|
||||
### Verification Scripts
|
||||
@@ -426,9 +434,11 @@ With the API running (`dotnet run`) and Docker Compose up:
|
||||
./scripts/run-vigilcare-records-phase-8-verification.sh # Phase 8 — Prometheus metrics, work-queue overview, batch events, promotion retry
|
||||
./scripts/run-vigilcare-records-verification-p9.sh # E2E workflow + work queue overview smoke test
|
||||
./scripts/run-vigilcare-records-phase-10-verification.sh # Phase 10 — cover sheets, barcode upload, PDF, auto-assign
|
||||
./scripts/run-vigilcare-records-phase-11-verification.sh # Phase 11 — FHIR R4 read/search, $everything, LOINC, integration tests
|
||||
./scripts/run-vigilcare-records-phase-11-verification.sh # Phase 11 — FHIR R4 read/search, $everything, LOINC mapping, clinical fixture seed
|
||||
```
|
||||
|
||||
The Phase 11 script auto-seeds a minimal clinical fixture for `VCR-000001` when PostgreSQL is available (updates existing patients or inserts deterministic demo rows). Run `dotnet test --filter FullyQualifiedName~FhirIntegrationTests` separately for WebApplicationFactory integration coverage.
|
||||
|
||||
---
|
||||
|
||||
## API Reference
|
||||
@@ -861,6 +871,32 @@ Unauthenticated probe endpoints for orchestrators and load balancers:
|
||||
|
||||
Returns `503` when a required dependency is unhealthy.
|
||||
|
||||
### HL7 FHIR R4 (Read-Only)
|
||||
|
||||
FHIR endpoints live at `/fhir` (not under `/api/v1`). Responses use `application/fhir+json`. Errors return FHIR `OperationOutcome` resources.
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|---|---|---|---|
|
||||
| GET | `/fhir/metadata` | Anonymous | Server `CapabilityStatement` (supported resources, interactions, search params) |
|
||||
| GET | `/fhir/Patient/{id}` | JWT | Read a promoted patient by logical ID |
|
||||
| GET | `/fhir/Patient` | JWT | Search patients by `name`, `birthdate`, `identifier` (MRN); supports `_count`, `_offset` |
|
||||
| GET | `/fhir/Patient/{id}/$everything` | JWT | Bundle of Patient + all Encounters + all Observations for the patient |
|
||||
| GET | `/fhir/Encounter/{id}` | JWT | Read a promoted encounter by logical ID |
|
||||
| GET | `/fhir/Encounter` | JWT | Search encounters by `patient`, `status`, `date`; supports `_count`, `_offset` |
|
||||
| GET | `/fhir/Observation/{id}` | JWT | Read a promoted observation by logical ID |
|
||||
| GET | `/fhir/Observation` | JWT | Search observations by `patient`, `code` (LOINC or VigilCare code), `date`, `category`, `encounter`; supports `_count`, `_offset` |
|
||||
|
||||
**Search notes:**
|
||||
|
||||
- Observation `code=8867-4` resolves LOINC to VigilCare `HEART_RATE` (and reverse mapping on read).
|
||||
- `category=vital-signs` filters vital-sign observation codes (`HEART_RATE`, `TEMP_C`, blood pressure, etc.).
|
||||
- Date parameters use FHIR prefixes (e.g. `date=ge2026-06-20`) against observation `recordedAt`.
|
||||
- Search bundles include `self` and `next` links when paginating.
|
||||
|
||||
**Status codes:** `404` with `OperationOutcome` issue code `not-found` when a resource ID does not exist.
|
||||
|
||||
**UI:** Administrators can browse FHIR resources interactively at `http://localhost:3028/fhir-explorer`.
|
||||
|
||||
---
|
||||
|
||||
## Data Models
|
||||
@@ -1203,7 +1239,7 @@ Response shape:
|
||||
|
||||
## Implemented Phases
|
||||
|
||||
Phases 1–10 are fully implemented and verified via integration tests and per-phase scripts. Post-phase hardening (health checks, user management, promotion retry unification, patient dedup normalization, assignment-time status transitions, document access audit, batch cancellation) is also in place. Phase 11 (HL7 FHIR R4 read API) is planned — see [docs/plans/phase-11-plan.md](docs/plans/phase-11-plan.md). See [docs/vigilcare-records-gap-analysis.md](docs/vigilcare-records-gap-analysis.md) for the remaining backlog.
|
||||
Phases 1–11 are fully implemented and verified via integration tests and per-phase scripts. Post-phase hardening (health checks, user management, promotion retry unification, patient dedup normalization, assignment-time status transitions, document access audit, batch cancellation) is also in place. Phase 12 (backend-driven batch-type field requirements for entry/verification forms) is planned — see [docs/plans/phase-12-plan.md](docs/plans/phase-12-plan.md). See [docs/vigilcare-records-gap-analysis.md](docs/vigilcare-records-gap-analysis.md) for the remaining backlog.
|
||||
|
||||
| Phase | Feature | Status |
|
||||
|---|---|---|
|
||||
@@ -1217,5 +1253,6 @@ Phases 1–10 are fully implemented and verified via integration tests and per-p
|
||||
| 8 | Prometheus metrics (`GET /metrics`), custom digitization gauges/histograms/counters, `MetricsCollectorService`, supervisor `GET /work-queue/overview`, cursor-paginated `GET /digitization-batches/:id/events`, promotion deferral (202 / `PROMOTION_DEFERRED`), `PromotionRetryService` with exponential backoff, Docker Prometheus (9095) + Grafana (3013), Phase 8 verification script | Done |
|
||||
| 9 | Extended seed data (10 demo batches across all types/tracks/statuses), E2E verification script (`run-vigilcare-records-verification-p9.sh`), clinical scenario docs (`docs/digitization-workstation-guide.md`), `UserManagementTests` | Done |
|
||||
| 10 | Barcode/QR cover sheet system: `CoverSheet` entity, generate/lookup/list/PDF APIs, `coverSheetCode` on batch upload with redeem and auto-assign, printable PDF with QRCoder, `/cover-sheets` and barcode-assisted `/intake` UI views, `CoverSheetBatchTests`, `CoverSheetPdfTests`, Phase 10 verification script | Done |
|
||||
| 11 | HL7 FHIR R4 read-only API: `FhirService`, Patient/Encounter/Observation mappers with LOINC mapping, read/search/`$everything` controllers, `CapabilityStatement` metadata, bundle pagination links, `FhirJsonOutputFormatter`, `FhirIntegrationTests`, administrator FHIR Explorer UI (`/fhir-explorer`), Phase 11 verification script | Done |
|
||||
| — | Health probes (`/health/live`, `/health/ready`, `/health/startup`), user management CRUD + password endpoints, auth rate limiting, document access audit, batch cancellation, list/queue sorting, unified `ExecutePromotionCoreAsync` for approve + retry promote, assignment-time `IN_ENTRY` transition, CORS policy for production frontend origins | Done |
|
||||
| 11 | HL7 FHIR R4 read-only API for promoted clinical data (Patient, Encounter, Observation) | Planned |
|
||||
| 12 | Backend as single source of truth for batch-type field requirements (entry/verification form visibility metadata) | Planned |
|
||||
|
||||
Reference in New Issue
Block a user