Skip to content

Changelog

All notable changes to VitaraVox

This project adheres to Semantic Versioning.


[4.3.0] - 2026-03-09

SMS Booking Confirmation + OSCAR REST Production + Provider Config

Three major features merged to main: SMS confirmations via Telnyx, OSCAR REST protocol extension for Kai-hosted instances, and 3-level provider configuration inheritance.

SMS Booking Confirmation

  • Telnyx API v2 integration via native fetch (no SDK) — sms.service.ts (353 lines)
  • Fire-and-forget pattern: setImmediate() in webhook handler ensures SMS never delays Vapi tool response
  • 5-guard chain (sms.service.ts:55-100): TELNYX_API_KEY → smsSenderNumber → smsConsent → valid phone → smsEnabled
  • Opt-out consent model: Default smsConsent: true; only false when patient explicitly declines during Patient-ID phase
  • 6 default templates: 3 actions (booking, reschedule, cancel) × 2 languages (EN, ZH)
  • Custom templates: Per-clinic JSON in ClinicConfig.smsTemplates with {{patientName}}, {{date}}, {{time}}, {{providerName}} variables
  • Platform-level Telnyx: Single API key + messaging profile in env vars; per-clinic sender numbers in DB
  • Phone normalization: normalizeToE164() handles North American formats (10/11 digit, with/without +1)
  • 3 API endpoints: GET /api/clinic/config/sms, POST /api/clinic/config/sms, POST /api/clinic/config/sms/validate
  • Voice agent updates: smsConsent param added to create_appointment, update_appointment, cancel_appointment tools; smsSent response field; consent disclosure in Patient-ID prompt
  • 79 unit tests covering guard chain, templates, normalization, service, API routes

OSCAR REST Protocol Extension

  • OAuth 1.0a 3-leg flow: POST /api/oscar/oauth/initiate → callback → token exchange (oscar-oauth.ts:45-269)
  • 11 REST endpoints: demographics CRUD, appointment CRUD, provider search, schedule data
  • preferRest flag: Per-clinic setting for Kai-hosted OSCAR behind Cloudflare WAF (which blocks SOAP content-inspection)
  • Provider 3-tier fallback: JSON (Accept: application/json) → XML (Accept: application/xml) → DB cache
  • Split circuit breakers: SOAP and REST adapters have independent Opossum breakers
  • AES-256-GCM storage: OAuth tokens encrypted at rest, scope-isolated resolution (NEVER mix clinic + env)
  • Token monitor: 6 AM + 6 PM daily check for expiring tokens (10-year TTL default)
  • 98 unit + 8 integration tests

Provider Configuration v3.1

  • 3-level inheritance: Global defaults → clinic_configclinic_providers (resolved in provider-config-resolver.ts)
  • 8 new clinic_config columns: defaultVisitMode, defaultVisitReason, defaultIsNewPatient, defaultPreferredTime, scheduleIntelligenceEnabled, bookingBufferMinutes, maxDailyBookings, allowDoubleBooking
  • 4 new clinic_providers columns: visitMode, visitReason, isNewPatient, preferredTime
  • Settings UI redesign: 4-card layout (General, Voice & Booking, OSCAR Configuration, Privacy & Compliance)

Database Changes

Table New Columns
ClinicConfig smsSenderNumber, smsEnabled, smsLanguage, smsTemplates, smsBookingTemplate, smsRescheduleTemplate, smsCancelTemplate, smsCustomTemplates, smsWebhookUrl
CallLog smsConsent, smsSentAt
ClinicConfig defaultVisitMode, defaultVisitReason, defaultIsNewPatient, defaultPreferredTime, scheduleIntelligenceEnabled, bookingBufferMinutes, maxDailyBookings, allowDoubleBooking
ClinicProviders visitMode, visitReason, isNewPatient, preferredTime

[4.2.1] - 2026-03-07

v3.1 Provider Configuration + REST Schedule Intelligence + P1 Fixes

Comprehensive update covering provider-level configuration, REST protocol hardening, FreshBay E2E validation, Settings UI redesign, and resolution of all P1 known issues.

Provider Configuration (v3.1)

  • 3-level config inheritance: Global defaults → clinic config → provider-level overrides via new provider-config-resolver.ts
  • 8 new clinic_config columns: defaultVisitMode, defaultVisitReason, defaultIsNewPatient, defaultPreferredTime, scheduleIntelligenceEnabled, bookingBufferMinutes, maxDailyBookings, allowDoubleBooking
  • 4 new clinic_providers columns: visitMode, visitReason, isNewPatient, preferredTime
  • Tool parameter expansion: create_appointment and find_earliest_appointment now accept visitMode, visitReason, isNewPatient, preferredTime

REST Protocol Hardening

  • quickSearch fix: Correct param is ?query= (not searchString or term). OSCAR CXF @QueryParam("query") annotation.
  • startTime fix: .replace(/:\d{2}$/, '') on "14:00" produced "14". Fixed to .slice(0, 5).
  • Provider XML fallback: JSON returns 406 (JAXB bug) → XML Accept: application/xml returns 200. 28 providers from Kai.
  • warmUp lifecycle: EmrAdapterFactory now awaits warmUp for preferRest adapters. Prevents cold TLS (~6s) exceeding 4s breaker.
  • PM2 startup warmUp: IIFE in index.ts warms all preferRest clinic adapters on restart.

FreshBay E2E Validation (5/5 PASS)

  • searchPatient, getScheduleSlots, createAppointment, getAppointments, cancelAppointment — all validated on Kai OSCAR
  • Test appointment ID 314132 created+cancelled (provider 124, 2026-03-19)
  • OAuth consumer Vitaradev re-authorized with TTL=-1 (permanent)

Settings UI Redesign

  • Settings page reorganized into 4 cards: General, Voice & Booking, OSCAR Configuration, Privacy & Compliance
  • New VoiceBookingConfig component for booking rule management

P1 Fixes Resolved

Fix Details
ZH CONVERSATION STYLE FALSE ALARM — all 4 ZH prompts already have ## 对话风格
Past-date clamp Added in bookAppointment handler (vapi-webhook.ts)
EMR adapter warmup IIFE in index.ts warms preferRest adapters on PM2 startup
transfer_call tool Added to 6 agents: Patient-ID EN/ZH, Booking EN/ZH, Registration EN/ZH
handoff_to_router_v3 Added to Patient-ID-ZH in squad YAML
Lock degradation acquireAdvisoryLock returns false on error (was true)

Fax Fixes

  • Response shape: Fax list returns data: {docs, pagination} (not flat array)
  • Verify method: Changed from POST to PUT

[4.1.1] - 2026-02-25

Fixed -- Fax Intelligence Pipeline Hardening

4 bug fixes and 1 enhancement to the Fax Intelligence pipeline, discovered during end-to-end upload testing.

Bug Fixes

  • Original uploads deleted after extraction -- The cleanup step was deleting ALL image paths including the original uploaded file. Now tracks temp files (PDF→PNG, TIFF→PNG conversions) separately and only deletes those. Original uploads are preserved on disk.
  • Hardcoded image/png MIME type -- All 3 AI providers (Anthropic, OpenAI, Google) were sending media_type: 'image/png' regardless of actual file type. Added dynamic MIME detection based on file extension (.jpgimage/jpeg, .pngimage/png, etc.).
  • TIFF files accepted but unsupported -- Multer accepted TIFF uploads but no AI vision API supports TIFF natively. Added TIFF→PNG conversion using sharp library with multi-page support (sharp({ pages: -1 })).
  • Wrong Anthropic model ID -- Hardcoded claude-sonnet-4-6-20250514 does not exist in the Anthropic API. Changed to claude-sonnet-4-6 (confirmed available via /v1/models query).

Enhancement

  • Configurable AI model -- Added FAX_ANTHROPIC_MODEL env var (default: claude-sonnet-4-6) so model changes don't require code edits. Wired through config/env.ts Zod schema and consumed in fax-extraction.service.ts.

Files Changed

File Change
services/fax-extraction.service.ts MIME detection, TIFF conversion, temp file tracking, configurable model
middleware/upload.ts Added fs.mkdirSync(UPLOAD_DIR, { recursive: true }) for missing directory
config/env.ts Added FAX_ANTHROPIC_MODEL with Zod default

Dependencies Added

  • sharp@0.34.5 -- High-performance image processing for TIFF→PNG conversion

[4.2.0] - 2026-02-23

Pipecat Migration Analysis — Enterprise Architecture Review

Comprehensive CTO-level analysis of migrating from Vapi.ai to Pipecat (open-source) + AWS ECS Fargate. Expert-reviewed by CTO Architect and Senior Voice AI Engineer agents.

New Documentation

  • Pipecat Migration Analysis (8-upgrade-plans/pipecat-migration-analysis.md) — Full enterprise migration plan with 14 sections covering:
    • Current state inventory (9 Vapi assistants, 14 tools, OSCAR SOAP adapter)
    • Target architecture (ECS Fargate + Pipecat Flows + Azure OpenAI Canada Central)
    • CTO-level strategic comparison (Vapi vs Pipecat across 14 dimensions)
    • Component migration map with effort estimates
    • AWS ca-central-1 deployment architecture (VPC, ALB, Fargate, RDS, S3)
    • HIPAA/PHIPA/PIPA compliance architecture with BAA chain
    • Cost analysis: 45% infrastructure savings ($5,950 → $3,275/month at 10 clinics)
    • 4-phase migration (804 hours / $120,600 / 22 weeks — revised after expert review)
    • Devil's advocate review with 6 challenges addressed
    • Risk register with 20+ risks across technical, compliance, operational, financial categories
    • Go/No-Go decision framework with phase gates

Key Decisions Documented

  • ECS Fargate over Lambda — Lambda's 15-min timeout and stateless model incompatible with voice sessions
  • Azure OpenAI Canada Central over Bedrock — GPT-4o in Canada, same model as current prompts, automatic BAA
  • Keep Node.js OSCAR adapters — 1,212 lines battle-tested; call from Python via HTTP
  • Gated approach — Phase A ($0 HIPAA fix) → Phase B ($6K POC) → Phase C ($120K full)

[4.1.0] - 2026-02-21

Fax Intelligence -- AI-Powered Document Processing

Complete fax intake automation: AI extracts patient data from fax PDFs, matches against OSCAR EMR, and presents to MOA for one-click verification. Reduces per-fax processing from 5-15 minutes to 30 seconds.

Backend (8 new files, ~1,276 lines TypeScript)

  • Multi-provider AI extraction (fax-extraction.service.ts) -- PDF-to-PNG via pdftoppm, then AI vision analysis. Supports 3 providers via FAX_AI_PROVIDER env var:
    • anthropic (default) -- Claude Sonnet 4.6
    • openai -- GPT-4o-mini
    • google -- Gemini 2.0 Flash
  • Patient matching cascade (fax-matching.service.ts) -- PHN exact match (100%) -> Name+DOB (95%) -> Name-only (85%) -> No match (review needed). Reuses existing EmrAdapterFactory for OSCAR search.
  • Fax provider abstraction (IFaxProvider.ts + MockSRFaxProvider.ts) -- Interface with mock implementation for demo. Loads synthetic PDFs + JSON sidecars from fixtures directory.
  • Automated polling (fax-poller.service.ts) -- Configurable interval polling with deduplication via faxId tracking. Start/stop lifecycle controlled by admin UI.
  • Orchestrator service (fax.service.ts) -- Complete pipeline: file -> extract -> match -> persist. CRUD operations with pagination and status filtering.
  • 10 API endpoints (routes/fax.ts) -- Upload, list, detail, verify match, polling start/stop/status, seed, reset, fixtures list. All behind JWT auth.
  • Upload middleware (middleware/upload.ts) -- Multer disk storage for PDF/PNG/JPG/TIFF, 10MB max, UUID-based filenames.
  • 5 synthetic fax fixtures -- Referral, lab results, specialist report, prescription renewal, insurance pre-auth. Each with PDF + JSON sidecar.

Database

  • FaxDocument model (23 columns) -- Status enum (pending -> processing -> extracted -> matched/review_needed -> verified/error), AI extraction fields (documentType, urgency, extractedData JSON, confidence, model, cost), patient match fields (demographicId, confidence, method), review tracking.
  • FaxStatus enum -- 7 states: pending, processing, extracted, matched, review_needed, verified, error
  • 3 indexes: clinic_id, status, created_at. FK constraint to clinics table.

Frontend

  • Fax Intelligence page (FaxIntelligence.tsx) -- Controls bar with polling toggle, upload button, seed/reset (demo). Detail panel with extraction results and OSCAR match card. Paginated history table with status badges and confidence bars. Auto-refresh every 5s when poller is running.
  • Sidebar navigation -- "Fax Intelligence" item with FileSearch icon added to clinic portal nav.

Configuration

  • 6 new environment variables: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_AI_API_KEY, FAX_AI_PROVIDER, FAX_PROVIDER, FAX_POLL_INTERVAL_MS

Dependencies Added

  • @anthropic-ai/sdk -- Claude vision API
  • openai -- GPT-4o-mini vision API
  • @google/generative-ai -- Gemini 2.0 Flash API
  • multer / @types/multer -- File upload middleware
  • pdf-lib -- Synthetic fax PDF generation (dev tooling)
  • System: poppler-utils (pdftoppm binary for PDF-to-PNG conversion)

[4.0.1] - 2026-02-16

Added

  • OSCAR SOAP API Reference -- Complete documentation for all 14 OSCAR SOAP web services at /oscar/ws/, covering 80+ operations across DemographicService, ProviderService, ScheduleService, AllergyService, PrescriptionService, MeasurementService, DocumentService, PreventionService, BookingService, ProgramService, FacilityService, LabUploadService, LoginService, and SystemInfoService
  • Includes WS-Security authentication details, credential format, two-step auth flow, SOAP header examples
  • Documents all transfer object field definitions (demographicTransfer, appointmentTransfer, drugTransfer with 55 fields, etc.)
  • Non-bookable schedule codes reference table (14 codes: L, P, V, A, a, B, H, R, E, G, M, m, d, t)
  • REST Bridge to SOAP operation mapping table (13 bridge methods)
  • VitaraVox services-used subset (7 of 14 services actively consumed by OscarSoapAdapter)
  • Cross-references to existing docs: Schedule Deep Dive, Adapter Implementations, SOAP Integration Evidence
  • Router maxTokens 150->400 -- was causing GPT-4o silent truncation (tool-call JSON alone = 80-120 tokens)
  • Circuit breaker timeout 10s->4s -- both SOAP and bridge phone search timeouts
  • Router prompt rewritten -- removed rigid scripting, replaced with warm acknowledgment + get_clinic_info dynamic greeting
  • request-start messages on all 14 tools (4 audible, 10 silent)
  • firstMessage removed from Patient-ID EN/ZH squad members (was causing 16s silence)
  • FILLER PHRASE RULES deleted from Booking + Modification EN/ZH prompts
  • transferAssistant -> handoff_to_X in all 8 non-Router prompts (fixed to use actual handoff tool function names)

Changed

  • Filler phrase strategy now tool-level request-start instead of LLM-generated filler phrases

[4.0.0] - 2026-02-15

Onboarding Redesign + Admin Provisioning Workflow

Complete restructure of the clinic onboarding flow and addition of admin-side clinic activation workflow.

Onboarding Flow Redesign (4 Steps -- was 5)

  • New step order: Clinic Details -> EMR Connection -> Business Hours -> Validation
  • EMR Connection (Step 2): EMR type selector cards (OSCAR, TELUS PS Suite, Accuro, Other) -- OSCAR fully supported, others "coming soon" with contact support CTA
  • Business Hours (Step 3): Enhanced with explanatory guidance text about typical Mon-Fri 8AM-5PM hours
  • Validation (Step 4): Replaces old "Go Live" step with 6 parallel integration checks:
  • EMR Connection -- tests OSCAR connectivity
  • Provider Roster -- verifies at least 1 provider with OSCAR ID
  • Schedule Codes -- checks OSCAR config for template codes
  • Appointment Types -- verifies configured appointment types
  • Sample Availability -- retrieves actual schedule slots via adapter
  • Sample Patient Search -- tests patient search via adapter
  • EMR Connection and Provider Roster are REQUIRED; others are informational warnings
  • All 6 checks run in parallel via Promise.allSettled() for speed
  • Expandable data panels show raw JSON results per check
  • "Complete Onboarding" creates admin notification for provisioning

Admin Provisioning Workflow

  • Pending Activation Card: Admin dashboard shows amber card listing clinics with onboardingProgress.completedAt set but status=pending
  • Provisioning Checklist: Admin ClinicDetail page shows checklist:
  • Phone number assigned (check clinic.vapiPhone)
  • Squad linked (check config.vapiSquadId)
  • "Activate Clinic" button (enabled when phone + squad assigned)
  • Activation Endpoint: PUT /api/admin/clinics/:id/activate validates phone + squad, sets status=active, creates notification for clinic manager

10-Point Pre-Launch Validation (was 8)

  • 7 blocking checks: clinic info, business hours, providers, EMR connection, Vapi squad, privacy officer, credentials encrypted
  • 3 informational (non-blocking): test call passed, schedule data flow, OSCAR config synced (within 7 days)

OSCAR Config Management

  • New OscarConfig settings page (/clinic/settings/oscar-config)
  • Schedule template codes management (bookable/non-bookable)
  • Appointment type mappings configuration
  • Config pull from OSCAR with sync status tracking
  • oscarConfigPulledAt field tracks freshness (7-day staleness warning)

Booking Engine: SOAP Adapter Enhancements

  • OscarSoapAdapter now production path (OscarBridgeAdapter retained for dev/fallback)
  • OscarUniversalAdapter renamed to OscarBridgeAdapter (clarifies purpose)
  • Enhanced schedule slot parsing with normalizeTime() for JAXB Calendar objects
  • Non-bookable codes expanded (L, P, V + full OSCAR set documented)

New API Endpoints

Method Endpoint Description
POST /api/clinic/onboarding/complete Complete onboarding, notify admins
POST /api/clinic/onboarding/test-slots Test schedule slot retrieval
POST /api/clinic/onboarding/test-patient-search Test patient search
GET /api/clinic/oscar-config OSCAR config (codes, types, sync status)
POST /api/clinic/oscar-config/pull Pull config from OSCAR instance
GET /api/admin/clinics/pending-activation Clinics awaiting activation
GET /api/admin/clinics/:id/provisioning Provisioning status
PUT /api/admin/clinics/:id/activate Activate clinic

New Client API Methods

  • testScheduleSlots(), testPatientSearch(), completeOnboarding()
  • getOscarConfig(), pullOscarConfig()
  • getProvisioningStatus(clinicId), activateClinic(clinicId), getPendingActivationClinics()

New Shared Types

  • ValidationCheckResult, SlotTestResult, PatientSearchResult

Files Summary

  • 1 new file: StepValidation.tsx
  • 1 deprecated: StepGoLive.tsx (replaced by StepValidation)
  • ~12 modified files across client, server, and shared packages
  • 48 files changed total, +5239 / -1005 lines

[3.2.7] - 2026-02-14

Documentation

OSCAR Data Architecture -- REST API & Known Bugs Update

  • Updated OSCAR Data Architecture to v3.1
  • REST API Endpoint Reference: Full OAuth 1.0a flow endpoints, Demographics CRUD (5 endpoints with mandatory/optional fields), Schedule/Appointment CRUD (9 endpoints)
  • Known Bugs & Gotchas: 9 validated issues with workarounds -- secUserRole NPE, provider reference trap, DemographicConverter link bug, AppointmentConverter null return, scheduledate.hour naming, template name VARCHAR(20) limit, missing admissionProgramId crash, OAuth provider validation, endTime off-by-one
  • Entity Creation Order: 9-step sequence showing required creation dependencies
  • Scheduling Layer updates: Slot duration formula (1440 / len(timecode)), 96-char position reference table, 'W' (Same Week) code added
  • Cross-reference to new OSCAR Demo Data page

OSCAR Demo Data & Test Environment -- New Page

  • New page: OSCAR Demo Data & Test Environment
  • Design Principles: 6 rules for referential integrity in a no-FK database
  • Provider Set: 4 doctors (100 Anderson, 101 Chen, 102 Patel, 10 Lee) with required secUserRole and program_provider records
  • Schedule Templates: 16 templates (96-char) across 3 providers + 2 Public templates, fully decoded (FullDay, clinic, day-of-week variants)
  • Demographic Set: 12 patients with diverse BC demographics, health card numbers, MRP assignments
  • Appointment Set: 12 sample bookings across all providers and appointment types (Office Visit, Annual Physical, Consult, Prenatal, Mental Health, etc.)
  • OAuth Clients: Production (VitaraPlatform, 1hr TTL) and test (vitaraPostman, 10hr TTL)
  • Validation Checklist: 8 SQL checks for provider-role, patient-admission, demographic-provider, schedule-template, appointment reference integrity, secUserRole data quality, REST smoke tests
  • Automation: oscar-align-load.sh script documentation -- 4-phase lifecycle (pre-flight, alignment, load, verification), fully idempotent

[3.2.6] - 2026-02-14

Documentation

OSCAR EMR Data Architecture -- Complete Entity Reference

  • New page: OSCAR Data Architecture in EMR Integrations section
  • Identity Layer: provider, secUserRole, ServiceClient (OAuth) -- full column definitions, mandatory fields, REST prerequisites
  • Patient Layer: demographic (with DOB-as-3-strings quirk), admission (program_id=10034 hardcoded), program, demographicExt (EAV), demographiccust
  • Scheduling Layer: scheduletemplatecode (slot alphabet), scheduletemplate (timecode patterns), scheduledate (template assignment via name JOIN)
  • Appointment Layer: appointment (independent of schedule slots), appointmentType (free text, no FK), status codes (t/H/C/T/b/A/sc)
  • OAuth Layer: ServiceClient -> ServiceRequestToken -> ServiceAccessToken -- full 5-step flow with token TTL and expiry rules
  • Cross-Entity Dependency Graph: Visual showing all provider_no references across 5 entities
  • Documented critical traps: secUserRole NPE, provider reference NPE, no FK constraints, appointment/slot independence

[3.2.5] - 2026-02-13

Upgrade Plans

Booking Engine Upgrade -- Master Implementation Plan

  • New documentation section: Upgrade Plans
  • Published Booking Engine Upgrade Plan for stakeholder review
  • Full current-state vs future-state ASCII architecture diagrams
  • 6-phase migration safety strategy with rollback checkpoints at every stage
  • Impact analysis: 2 files created, 5 files modified, 0 database migrations
  • 7 milestones (M0-M6) with 80+ acceptance criteria
  • Agent team orchestration: parallel M1+M2, sequential M3-M6
  • Comprehensive testing strategy: SOAP adapter, BookingEngine, and regression test cases
  • Risk registry with 7 identified risks and mitigations
  • Status: PLANNING -- awaiting stakeholder approval before any code changes

[3.2.4] - 2026-02-13

Architecture Decision

ADR-004: Booking Product Architecture

  • Decision: All booking intelligence lives in the VitaraVox platform layer. No custom code deployed on customer OSCAR instances.
  • Created ADR-004: Booking Product Architecture documenting three-layer architecture
  • Layer 1 (our servers): BookingEngine -- availability calculation, conflict detection, slot locking, double-booking prevention, bookinglimit enforcement
  • Layer 2 (pluggable adapters): SOAP Adapter (universal production), REST Adapter (OSCAR 15+), Bridge Adapter (dev/test only)
  • Layer 3 (customer's OSCAR): Connect via standard SOAP/OAuth APIs. Install nothing.
  • Corrected Schedule Deep Dive Section 7 -- booking intelligence belongs in platform, NOT in bridge
  • Bridge reclassified as dev/testing tool and reference implementation, not a portable production connector
  • Migration path: Phase 1 Bridge Adapter -> Phase 2 SOAP Adapter -> Phase 3 first customer on SOAP

[3.2.3] - 2026-02-13

Documentation

OSCAR Schedule System Deep Dive

  • New architecture decision page: OSCAR Schedule Deep Dive
  • Documented core 4-table relationship chain (scheduledate.hour -> scheduletemplate.name -> timecode -> scheduletemplatecode)
  • Documented bookinglimit advisory-only enforcement (OSCAR never implemented strict limits)
  • Critical finding: Appointments and schedule slots are completely independent (no FK between appointment and scheduledate)
  • Full API surface comparison: SOAP ScheduleWs vs OSCAR native REST vs our bridge -- identified gap in native REST (no schedule endpoints)
  • Duplicate booking vulnerability analysis: OSCAR SOAP addAppointment has zero conflict checking; BookingWs race condition in check-then-book flow
  • Commercial competitive analysis: Cortico, Ocean, Veribook, Porton, Phelix, OSCAR Self-Book -- all subtract booked slots from availability; our bridge does not
  • P0 required actions: subtract booked appointments from availability, pre-booking conflict check

[3.2.2] - 2026-02-13

Documentation

OSCAR Database ERD & Bridge Mapping

  • Added full OSCAR database entity relationship diagram to OSCAR REST Bridge (Section 2)
  • Documented all core tables: provider, demographic, appointment, allergies, drugs, measurements, measurementsExt, measurementType
  • Added schedule subsystem ERD: scheduledate -> scheduletemplate -> scheduletemplatecode JOIN architecture
  • Added detailed SOAP-to-REST bridge mapping tables (Section 6) showing exact SOAP method calls for all endpoints
  • Added bridge internal data flow diagram showing Routes -> Services -> SOAP Client / DB Service paths
  • Documented notable table quirks (varchar birth dates, Aria engine, no FK constraints, etc.)

[3.2.1] - 2026-02-12

Security Hardening Sprint (Post-Review)

5 targeted fixes addressing the highest-priority findings from the architecture review.

Fix 1: Production Security Enforcement

  • Set NODE_ENV=production -- activates fail-fast secret validation via Zod
  • Generated and configured ENCRYPTION_KEY for AES-256-GCM credential encryption
  • HMAC-SHA256 webhook verification now mandatory (was skipped in dev mode)

Fix 2: Waitlist Database Persistence

  • addToWaitlist tool handler now writes to PostgreSQL via Prisma (WaitlistEntry.create)
  • Previously the Prisma call was commented out -- patients were told they were added but nothing persisted

Fix 3: PHI Log Redaction

  • Added redactPhi() helper that strips names, DOB, phone, email, health cards from all log output
  • Redacted 7 log sites in vapi-webhook.ts that were dumping full patient data
  • Caller phone logged as [SET]/[NOT SET] instead of actual number
  • End-of-call-report logs only callId and durationSeconds

Fix 4: OSCAR Route Authentication

  • Moved 15 /api/oscar/* routes to a dedicated sub-router with explicit authMiddleware
  • GET /api/oscar/health remains public (monitoring)
  • All other OSCAR proxy routes now require JWT authentication

Fix 5: Graceful Shutdown Handler

  • Added SIGTERM/SIGINT handler that drains in-flight requests before exit
  • 10-second forced shutdown timeout with .unref() to prevent Node.js hang
  • Critical for update_appointment which does book-new + cancel-old (non-atomic)

Production Launch Backlog Documented

ID Issue Priority
BL-01 JWT token revocation Medium
BL-02 Redis-backed rate limiting Medium
BL-03 Multi-tenant OSCAR wiring High
BL-08 Webhook integration tests High
BL-09 Monitoring + alerting High

[3.2.0] - 2026-02-12

Fixed - Phone Number Linking & Human Handover (Theme 7)

Bug Fix

  • transfer-destination-request webhook now returns the actual clinic phone number for call transfers, fixing human handover routing

Added

Vapi Phone Number Listing - New GET /api/admin/vapi/phone-numbers endpoint -- lists all Vapi phone numbers (admin only) - Server-side VapiService method to fetch phone numbers from Vapi API

Client API Methods - New client API methods for Vapi phone management (getVapiPhoneNumbers, assignPhoneToClinic, unassignPhoneFromClinic)

Admin Phone Management Page (/admin/phones) - Stat cards: total phone numbers, assigned, available, clinics without phone - Clinic assignments table with assign/unassign actions - Vapi phone numbers table showing all numbers with assignment status - Assign modal for linking unassigned phone numbers to clinics

Database Backup Scripts - scripts/backup-db.sh -- PostgreSQL backup script with retention - scripts/install-cron.sh -- Cron job installer for automated daily backups


[3.1.0] - 2026-02-11

Added - Platform Maturity (5 Themes)

Complete platform hardening across compliance, reliability, onboarding, clinical control, and support -- transforming from prototype to production-grade multi-tenant SaaS.

Theme 2: Compliance (PIPEDA/PIPA)

Credential Encryption (AES-256-GCM) - New lib/crypto.ts: encrypt(), decrypt(), isEncrypted() -- AES-256-GCM with random IV - OSCAR credentials (oscarConsumerSecretEnc, oscarTokenSecretEnc) encrypted at rest - ENCRYPTION_KEY (32-byte hex) required in production; dev warns on missing key - API responses mask encrypted fields (never expose plaintext)

Audit Logging - New middleware/audit.ts: Auto-captures POST/PUT/DELETE -> AuditLog table - Redacts password, secret, key, token fields from stored details - New services/audit.service.ts: Non-blocking writes, paginated admin queries - New GET /api/admin/audit with date/action/user filters

Privacy & Retention - Privacy officer fields: privacyOfficerName, privacyOfficerEmail, privacyOfficerPhone - BAA/DPA tracking: baaVapiSigned, baaHostingSigned with timestamps - Data retention: transcriptRetentionDays (default 90), callLogRetentionDays (default 365) - New jobs/data-retention.ts + jobs/scheduler.ts: node-cron daily 3 AM purge - Nulls transcripts after retention period, deletes call logs after longer period

Theme 3: Reliability & Production Standards

Security Hardening - Helmet security headers (CSP, HSTS, X-Frame-Options, etc.) - Rate limiting: 5/min auth, 300/min webhooks, 100/min API - Env validation: Zod schema in config/env.ts, fail-fast on missing secrets in production

Observability - Pino structured logging (lib/logger.ts) -- JSON in prod, pretty-print in dev - pino-http request logger with x-request-id correlation - Replaced ~30 console.log/error calls with structured logger

Resilience - Circuit breaker (Opossum) wrapping all OSCAR Bridge calls - Real health checks: DB ping + OSCAR Bridge /health + Vapi API check with latency - PostgreSQL backup automation (scripts/backup-db.sh, daily 2 AM, 14 retained)

Validation - 18 Zod schemas with .strict() enforcement in validation/schemas.ts - validate() middleware factory for all POST/PUT endpoints

Theme 1: Onboarding

  • New services/onboarding.service.ts: getProgress(), updateStep(), validatePreLaunch(), goLive()
  • 8-point pre-launch validation
  • POST /api/admin/clinics -- Transaction creating Clinic + User + ClinicConfig + OnboardingProgress + 7 ClinicHours
  • 5-step onboarding wizard (pages/clinic/Onboarding.tsx)

Theme 4: Clinical Control

  • ClinicConfig fields: customGreeting, customGreetingZh, transferPhoneNumber, defaultProviderId, preferredPharmacy*, appointmentTypeMappings
  • PUT /api/clinic/clinical-settings endpoint
  • Clinical Settings page

Theme 5: Support & Notifications

  • New Prisma models: SupportTicket, TicketMessage, Notification
  • 11 route endpoints (4 clinic, 4 admin, 3 notifications)
  • isInternal enforced server-side
  • NotificationBell.tsx component with 30-second polling

Database Changes

Migration New Models New ClinicConfig Fields
Audit log AuditLog --
Privacy/retention -- privacyOfficer*, transcriptRetentionDays, callLogRetentionDays, baaVapi*, baaHosting*
Onboarding OnboardingProgress --
Clinical control -- customGreeting*, transferPhoneNumber, defaultProviderId, preferredPharmacy*, appointmentTypeMappings
Support tickets SupportTicket, TicketMessage --
Notifications Notification --

Total models: 8 -> 13


[3.0.0] - 2026-02-10

Added - Dual-Track Bilingual Voice Agent (v3.0)

9-Agent Dual-Track Squad Architecture

  • New squad: 9 assistants organized as Router + 4 roles x 2 language tracks (EN/ZH)
  • Squad ID: 13fdfd19-a2cd-4ca4-8e14-ad2275095e32
  • Router (vitara-router-v3): Pure language gate -- detects EN/ZH from first utterance, routes to correct track
  • Patient-ID (EN/ZH): Identifies caller by phone, detects intent, routes to role agent
  • Booking (EN/ZH): Finds slots, books appointments with create_appointment
  • Modification (EN/ZH): Consolidated reschedule + cancel + check (was 2 separate agents)
  • Registration (EN/ZH): Collects 7 fields, registers new patients
  • Confirmation agent eliminated -- log_call_metadata absorbed into every role agent

Per-Language STT/TTS Configuration

  • Router STT: AssemblyAI Universal (bilingual auto-detect)
  • EN STT: Deepgram nova-2 en
  • ZH STT: Deepgram nova-2 zh
  • EN TTS: ElevenLabs eleven_multilingual_v2
  • ZH TTS: Azure zh-CN-XiaoxiaoNeural

Vapi GitOps (Config-as-Code)

  • All 9 assistants, 14 tools, and squad YAML managed in vapi-gitops/ directory
  • Slug-based tool references
  • Environment separation (dev/staging/prod)

Server-Side Changes

  • callMetadataCache: In-memory Map bridging tool-call and end-of-call-report webhooks
  • v3 parameter support (demographicId, appointmentId, providerId, startTime ISO 8601)
  • Appointment type validation against ['B', '2', '3', 'P']
  • Dual squad resolution (vapi_squad_id_v3 column)

[2.3.0] - 2026-02-09

Added - Production Voice Quality & Silent Transfers

  • 6-agent squad (Router + Booking + Reschedule + Cancel + Registration + Confirmation)
  • AssemblyAI Universal transcriber (replaces Deepgram multi — was forcing English on Mandarin)
  • ElevenLabs eleven_multilingual_v2 TTS for all agents
  • Silent transfers (patient doesn't hear handoff between agents)
  • Inline confirmation flow (Confirmation agent handles call summary)
  • Slot collision checking before booking
  • Non-numeric providerId handling ("any" / "任何" → search all providers)

[2.2.0] - 2026-02-06

Added - Voice Agent Server Consolidation & Multi-Clinic Hardening

  • IEmrAdapter pattern (ADR-003) -- TypeScript rewrite
  • Caller phone auto-detection (server-side extraction from call.customer.number)
  • find_earliest_appointment -- smart slot finder with 1-slot return, past-date clamping, provider name resolution
  • 6-assistant squad architecture
  • Multi-auth webhook middleware (HMAC-SHA256 + API key + Bearer)
  • Robust appointment booking with dual parameter support

[2.1.0] - 2026-02-03

Added - Admin Vapi Management & Call Log Integration

  • 1 Assistant to 1 Clinic linking in admin dashboard
  • Vapi config fields in clinic_config (vapi_assistant_id, vapi_squad_id, vapi_webhook_secret)
  • Admin API endpoints for Vapi management
  • Webhook call log saving on end-of-call-report
  • OSCAR Bridge integration fixes

[2.0.0] - 2026-02-02

Changed - Voice Agent Squad Architecture v2.0

  • 5-agent squad architecture (Router, Patient ID, Registration, Booking, Modification)
  • 6 new tool handlers
  • Language handling (English + Mandarin with mid-conversation switching)
  • Emergency/frustration detection

[1.5.2] - 2026-01-21

Added - Marketing Website Documentation

  • Marketing website documentation and code review
  • Identified 20 issues (2 critical, 4 high, 6 medium, 8 low)

[1.5.1] - 2026-01-16

Fixed - Admin Dashboard Data Display

  • API response pagination fix
  • Frontend field name mapping to PostgreSQL column names
  • JSONB safeJsonParse helper
  • Nginx authorization header forwarding

[1.5.0] - 2026-01-14

Added - Admin System with Per-Clinic EMR Control

  • Multi-tenant admin dashboard (React)
  • Two user roles: Vitara Admin and Clinic Manager
  • PassportJS + JWT authentication
  • Per-clinic EMR live status
  • 125 new unit tests

[1.4.0] - 2026-01-14

Added - EMR Abstraction Layer (Epic 1.2)

  • IEmrAdapter interface + OscarUniversalAdapter
  • EmrAdapterFactory with 5-minute TTL cache
  • Feature flags system for controlled rollout
  • 224 total tests (86% statement coverage)

[1.3.2] - 2026-01-14

Added - OSCAR REST Bridge v1.3.0

  • Admission records on patient registration
  • Configuration centralization (environment variables)
  • Health check improvements
  • Graceful shutdown

[1.3.1] - 2026-01-13

Added - OSCAR REST Bridge v1.2.0 (DB-Based Availability)

  • Provider availability endpoint (direct database query)
  • Schedule pattern parsing (48-char/96-char templates)
  • Voice agent integration

[1.3.0] - 2026-01-13

Added - Vapi Production Integration

  • Bearer token authentication with Vapi credentialId
  • Phone number normalization
  • Name spelling confirmation
  • OSCAR phone search
  • Deepgram Nova-3 transcriber

[1.2.0] - 2026-01-13

Added - Infrastructure Hardening

  • Input validation (Joi, 12 schemas)
  • Structured logging (Pino with PHI redaction)
  • Circuit breaker (Opossum)
  • Health checks (Kubernetes-ready)
  • Error standardization
  • Rate limiting

[1.1.0] - 2026-01-12

Added

  • BC Health registration requirements (PHN, BC Services Card)
  • get_clinic_info and add_to_waitlist endpoints
  • Comprehensive compliance documentation (PIPEDA, PHIPA, SOC2)

[1.0.0] - 2025-12-29

Added

  • Multi-clinic support with phone number routing
  • PostgreSQL database for configuration
  • New patient registration flow
  • Waitlist management
  • Mandarin Chinese language support
  • Admin dashboard (basic)
  • Docker Compose deployment
  • NGINX reverse proxy with SSL/TLS

[0.5.0] - 2025-12-19

Added

  • Initial release
  • Single-clinic appointment booking
  • Patient lookup by phone and name
  • OSCAR EMR integration (OAuth 1.0a)
  • English language support
  • Node.js Express webhook handler
  • PM2 process management

Future — Planned

Planned Features

  • FAQ Knowledge Base (v3.1 — common clinic questions)
  • Fax Intelligence v2 (SRFax production provider)
  • French Canadian language track
  • Cantonese language track
  • Appointment reminders (outbound)

Planned Technical

  • Structured Logging Tier 1-3
  • v3.0 E5 Testing (76 test cases)
  • Family Doctor Routing (v3.2)
  • Clinic timezone from DB (replace hardcoded America/Vancouver)
  • Pipecat POC Phase B ($6K budget)

Version Numbering

Given a version number MAJOR.MINOR.PATCH:

Component Meaning
MAJOR Incompatible API changes
MINOR Backwards-compatible functionality
PATCH Backwards-compatible bug fixes

Release Schedule

Version Target Status
v0.5.0 Dec 19, 2025 Released
v1.0.0 Dec 29, 2025 Released
v1.1.0 Jan 12, 2026 Released
v1.2.0 Jan 13, 2026 Released
v1.3.0 Jan 13, 2026 Released
v1.3.1 Jan 13, 2026 Released
v1.3.2 Jan 14, 2026 Released
v1.4.0 Jan 14, 2026 Released
v1.5.0 Jan 14, 2026 Released
v1.5.1 Jan 16, 2026 Released
v1.5.2 Jan 21, 2026 Released
v2.0.0 Feb 02, 2026 Released
v2.1.0 Feb 03, 2026 Released
v2.2.0 Feb 06, 2026 Released
v2.3.0 Feb 09, 2026 Released (production hardening)
v3.0.0 Feb 10, 2026 Released (deployed, testing)
v3.1.0 Feb 11, 2026 Released (5 themes)
v3.2.0 Feb 12, 2026 Released (phone linking)
v3.2.1 Feb 12, 2026 Released (security hardening)
v3.2.2 Feb 13, 2026 Released (OSCAR ERD)
v3.2.3 Feb 13, 2026 Released (Schedule Deep Dive)
v3.2.4 Feb 13, 2026 Released (ADR-004)
v3.2.5 Feb 13, 2026 Released (Booking Engine Plan)
v3.2.6 Feb 14, 2026 Released (OSCAR entity reference)
v3.2.7 Feb 14, 2026 Released (REST API, demo data)
v4.0.0 Feb 15, 2026 Released (onboarding redesign)
v4.0.1 Feb 16, 2026 Released (P0/P1/P2 fixes)
v4.1.0 Feb 21, 2026 Released (Fax Intelligence)
v4.1.1 Feb 25, 2026 Released (Fax pipeline hardening)
v4.2.0 Feb 23, 2026 Released (Pipecat migration analysis)
v4.2.1 Mar 07, 2026 Released (provider config, REST hardening, P1 fixes)
v4.3.0 Mar 09, 2026 Released (SMS booking confirmation, OSCAR REST, provider config)