Changelog
All notable changes to VitaraVox
This project adheres to Semantic Versioning.
[1.5.2] - 2026-01-21
Added - Marketing Website Documentation
Documentation Updates
- Added marketing website documentation (
3-whats-built/marketing-website.md)
- Created comprehensive code review for React frontend (
7-code-review/website-review.md)
- Updated navigation and indexes to include new sections
Marketing Website Code Review
- Architecture analysis: React 19.2, TypeScript 5.9, Vite 7.2, Tailwind CSS 4.1
- Identified 20 issues (2 critical, 4 high, 6 medium, 8 low)
- Critical: CSRF vulnerability in contact form, hardcoded API endpoint
- High: Weak input validation, console.error in production
- Created remediation backlog with prioritized fixes
Scores
| Metric |
Score |
| Architecture |
8/10 |
| TypeScript |
8/10 |
| Code Quality |
6/10 |
| Security |
5/10 |
| Performance |
8/10 |
[1.5.1] - 2026-01-16
Fixed - Admin Dashboard Data Display
API Response Handling
- Fixed pagination preservation in
api.js response unwrapping
- Paginated endpoints now return
{ data: [...], pagination: {...} } structure
- Non-paginated endpoints continue to return unwrapped data directly
Frontend Field Name Mapping
- Updated
ClinicsPage.jsx to use PostgreSQL column names (clinic_id, clinic_name, clinic_created_at)
- Updated
UsersPage.jsx clinic dropdown to use clinic_id and clinic_name
- Updated
AuditLogsPage.jsx for new response structure
JSONB Parsing Fix
- Added
safeJsonParse() helper in auditLogs.js route
- Handles PostgreSQL
pg driver auto-parsing of JSONB columns
- Prevents "Unexpected token o in JSON at position 1" errors
Nginx Proxy Configuration
- Added
proxy_set_header Authorization $http_authorization; to API locations
- JWT tokens now properly forwarded through nginx to backend
Seed Data Enhancement
- Added Calgary Health Partners as 5th clinic
- Added Emily Brown as 5th clinic manager
- Added 22 diverse audit log entries for dashboard activity widget
Files Changed
| File |
Changes |
admin-ui/src/services/api.js |
Preserve pagination in response unwrapping |
admin-ui/src/pages/ClinicsPage.jsx |
Use backend field names |
admin-ui/src/pages/UsersPage.jsx |
Use backend field names in dropdown |
admin-ui/src/pages/AuditLogsPage.jsx |
Handle new response structure |
routes/admin/auditLogs.js |
Add safeJsonParse helper |
nginx/conf.d/api.conf |
Forward Authorization header |
migrations/003_seed_data.sql |
Add 5th clinic, user, diverse audit logs |
[1.5.0] - 2026-01-14
Added - Admin System with Per-Clinic EMR Control
Multi-Tenant Admin Dashboard
- React-based admin UI served from
/admin/
- Two user roles: Vitara Admin (platform-wide) and Clinic Manager (single clinic)
- Role-based access control (RBAC) with middleware enforcement
- Responsive design with Tailwind CSS
Authentication System
- PassportJS + JWT authentication
- Access tokens (1 hour) + Refresh tokens (7 days)
- bcrypt password hashing (cost factor 12)
- Account lockout: 5 failed attempts = 15 minute lock
- Password requirements: 8+ chars, letter + number
Database Schema Additions
clinic_config - Enhanced with emr_live, emr_type, emr_config, preferences
admin_users - User accounts with roles and clinic assignments
audit_log - Immutable append-only audit trail
API Endpoints
/api/auth/* - Login, logout, refresh, change password, get current user
/api/admin/clinics/* - CRUD, EMR config, go-live workflow (Vitara Admin)
/api/admin/users/* - User management, password reset, unlock (Vitara Admin)
/api/admin/audit-logs/* - Query and summarize audit logs (Vitara Admin)
/api/clinic/* - Self-service preferences and go-live request (Clinic Manager)
Per-Clinic EMR Live Status
emr_live flag in clinic_config table controls EMR integration
- Demo mode when
emr_live = false - returns mock data
- Go-live validation workflow with checklist
- Voice agent checks
emr_live before real EMR operations
EmrService Demo Mode Integration
_isEmrLive() check on all EMR operations
- Demo responses for all endpoints (search, booking, providers)
- Demo patient: "Demo Patient" (DEMO-001)
- Demo provider: "Dr. Demo Doctor" (DEMO-DR-001)
Comprehensive Test Suite
- 125 new unit tests for admin system
- Validators: 58 tests (Joi schemas)
- AdminUserRepository: 23 tests
- AuditLogRepository: 20 tests
- Auth Middleware: 24 tests
Configuration
| Variable |
Default |
Description |
JWT_SECRET |
(required) |
Access token signing key |
JWT_REFRESH_SECRET |
(required) |
Refresh token signing key |
JWT_EXPIRES_IN |
1h |
Access token expiry |
JWT_REFRESH_EXPIRES_IN |
7d |
Refresh token expiry |
EMR_DEMO_MODE |
true |
Enable demo responses for non-live clinics |
Deployment Notes
# Run database migrations
psql -d vitara_db -f migrations/002_admin_system.sql
# Set JWT secrets (required!)
export JWT_SECRET="your-secure-secret-here"
export JWT_REFRESH_SECRET="your-refresh-secret-here"
# Access admin UI
open https://your-host/admin/
Files Created
| Path |
Description |
db/migrations/002_admin_system.sql |
Database schema |
db/repositories/ClinicConfigRepository.js |
Clinic data access |
db/repositories/AdminUserRepository.js |
User data access |
db/repositories/AuditLogRepository.js |
Audit log data access |
validators/adminSchemas.js |
Joi validation schemas |
middleware/auth.js |
PassportJS + RBAC middleware |
routes/auth.js |
Authentication endpoints |
routes/admin/*.js |
Admin API endpoints |
routes/clinic/*.js |
Clinic Manager endpoints |
admin-ui/ |
React admin dashboard source |
public/admin/ |
Built admin UI static files |
[1.4.0] - 2026-01-14
Added - EMR Abstraction Layer (Epic 1.2)
Phase 1: Adapter Pattern Implementation
IEmrAdapter.js - Interface defining all EMR operations
BaseEmrAdapter.js - Base class with common functionality
OscarUniversalAdapter.js - OSCAR REST Bridge adapter (first implementation)
EmrAdapterFactory.js - Factory pattern with adapter caching
PatientTransformer.js - EMR ↔ canonical patient format conversion
ProviderTransformer.js - EMR ↔ canonical provider format conversion
AppointmentTransformer.js - EMR ↔ canonical appointment format conversion
- System user filtering (admin0, system, etc.)
Phase 2: Integration Layer (NEW)
services/EmrService.js - Integration layer bridging adapters with vapiEndpoints.js
- Maintains backward compatibility with oscarRestService method signatures
- Response format translation (canonical → OSCAR-compatible)
- Per-clinic adapter configuration support
Phase 2: Feature Flags System (NEW)
config/featureFlags.js - Centralized feature flag configuration
USE_EMR_ADAPTER (env var) - Global toggle for new adapter pattern
EMR_ADAPTER_CLINICS (env var) - Comma-separated list for selective rollout
- Helper functions:
shouldUseAdapterForClinic(), getFeatureFlagStatus()
Phase 2: Database Migrations (NEW)
migrations/001_add_emr_columns.sql - Add emr_type and emr_config columns
migrations/001_add_emr_columns_rollback.sql - Rollback script
- Supports per-clinic EMR configuration
Phase 2: vapiEndpoints.js Integration (NEW)
- Replaced
const oscar = require('./oscarRestService') with EmrService
- All 14 Vapi tool endpoints now use EmrService for EMR operations
- Automatic fallback to legacy oscarRestService when adapter disabled
Comprehensive Unit Tests
- 224 total tests (160 Phase 1 + 64 Phase 2)
- 86% statement coverage, 80% branch coverage
__tests__/services/EmrService.test.js - 41 tests
__tests__/config/featureFlags.test.js - 23 tests
Technical Details
- Decouples voice agent from OSCAR-specific code
- Enables future EMR integrations (Oscar Pro, Telus Health, Juno)
- 5-minute adapter cache with TTL management
- Circuit breaker integration for fault tolerance
- Structured logging with metrics collection
- Instant rollback via
USE_EMR_ADAPTER=false
Architecture Decision Record
- ADR-003: EMR Abstraction Layer approved and documented
- Phase 2 integration plan:
docs/PHASE2_INTEGRATION_PLAN.md
- Database schema changes: emr_type, emr_config columns
Default Behavior (IMPORTANT)
By default, USE_EMR_ADAPTER=false (DISABLED)
This means the system uses the legacy oscarRestService unless explicitly enabled.
The new EMR adapter pattern is opt-in for controlled rollout.
| Environment Variable |
Default |
Effect |
USE_EMR_ADAPTER |
false |
Legacy oscarRestService (no adapter) |
EMR_ADAPTER_CLINICS |
'' |
Empty = all clinics (when enabled) |
Deployment Notes
# DEFAULT (legacy mode) - oscarRestService used
# No env vars needed, this is the fallback
# Enable adapter for all clinics (explicit opt-in)
export USE_EMR_ADAPTER=true
# Selective rollout to specific clinics only
export USE_EMR_ADAPTER=true
export EMR_ADAPTER_CLINICS=clinic-1,clinic-2
# Rollback to legacy mode (explicit)
export USE_EMR_ADAPTER=false
# Apply database migration (required before enabling adapter)
psql -d vitara_db -f migrations/001_add_emr_columns.sql
[1.3.2] - 2026-01-14
Added - OSCAR REST Bridge v1.3.0
Admission Records on Patient Registration
- New patients automatically get an admission record
- Links patient to OSCAR Service program (ID 10034 by default)
- Patient appears in provider rosters immediately
- Response includes
admissionId and programId
Configuration Centralization
- New environment variables with sensible defaults:
| Variable |
Default |
Purpose |
OSCAR_DEFAULT_PROGRAM_ID |
10034 |
Admission program |
OSCAR_DEFAULT_PROVIDER_ID |
(empty) |
Fallback provider |
OSCAR_DEFAULT_PROVINCE |
ON |
Patient province |
OSCAR_DEFAULT_COUNTRY |
CA |
Patient country |
OSCAR_DEFAULT_LANGUAGE |
English |
Patient language |
OSCAR_CHART_PREFIX |
NEW |
Chart number prefix |
Health Check Improvements
- Uses singleton instances (no longer creates services per request)
- Verifies both SOAP and database connectivity
- Returns detailed service status in response
Graceful Shutdown
- Database connection pool closes on SIGTERM/SIGINT
- Clean container restarts in Docker/Kubernetes
- Proper logging during shutdown sequence
Changed
src/config/environment.js - Added database config and Oscar defaults
src/services/database-service.js - Added createAdmission(), uses config
src/transformers/demographic-transformer.js - Uses config for defaults
src/index.js - Singleton services, improved health check, graceful shutdown
[1.3.1] - 2026-01-13
Added - OSCAR REST Bridge v1.2.0 (DB-Based Availability)
Provider Availability Endpoint
GET /appointments/availability?providerId=&date= queries database directly
- Bypasses buggy SOAP
getDayWorkSchedule method (returns empty for configured schedules)
- Parses Oscar schedule patterns (48-char = 8AM start, 96-char = midnight)
- Returns actual time slots with appointment type codes
Schedule Pattern Parsing
- Each character = 15-minute slot
_ = unavailable, letters = appointment type code
- Example:
____BBBBBBBBBBBB________BBBBBBBBBBBB____________
- Looks up template codes in
scheduletemplatecode table
Voice Agent Integration
oscarRestService.js - Added getAvailability() and getAppointmentTypes()
vapiEndpoints.js - find-earliest endpoint uses availability API
- Fallback to legacy search if availability returns empty slots
Documentation
- Updated oscar-rest-bridge.md with architecture diagram
- Added "Why Two Data Sources?" explanation
- Documented Oscar schedule pattern encoding
- Known Issues section with SOAP bug workaround
[1.3.0] - 2026-01-13
Added - Vapi Production Integration
Bearer Token Authentication
- Replaced API Key auth with Bearer Token + Vapi credentialId
- Created Vapi credential:
02698381-2c38-494d-858e-f8c679ab803a
- All 14 tools now use
server.credentialId for authentication
VAPI_BEARER_TOKEN environment variable in docker-compose.yml
authenticateBearerToken() middleware in vapiEndpoints.js
Phone Number Normalization
- Caller ID normalization:
+12367770690 → 2367770690
- System prompt updated with phone handling rules
- Endpoint descriptions updated for Vapi tool calls
- Both formats work: with/without +1 prefix
Name Spelling Confirmation
- System prompt updated with spelling confirmation logic
- Handles similar-sounding names (Dawn vs Don, Lee vs Li)
- Spelling verification flow for failed searches
OSCAR Phone Search
- Added phone search to REST-SOAP bridge on remote server
GET /api/v1/demographics/search?phone=XXX now works
- Uses existing
findPatientByPhone() method
- Normalizes phone before database lookup
Changed
- Transcriber: Gladia → Deepgram Nova-3 (multilingual)
- HIPAA Mode: Disabled for transcript storage
- Nginx: Fixed /api/vapi/* routing (removed rewrite, direct proxy)
- Tools: All 14 configured as separate Vapi records with toolIds
Infrastructure
- Production-ready Vapi integration validated
- End-to-end phone search tested successfully
- Bearer token auth tested with curl
[1.2.0] - 2026-01-13
Added - Infrastructure Hardening
validators/schemas.js - 12 endpoint-specific validation schemas
- Canadian healthcare patterns (health card, postal code, province codes)
- Phone number normalization and validation
middleware/validate.js - Validation middleware factory with sanitization
Structured Logging (Pino)
lib/logger.js - Pino-based structured logging
- PHI field redaction (phone, healthCard, dateOfBirth)
- Request correlation IDs throughout request lifecycle
- Separate log streams for production vs development
Circuit Breaker (Opossum)
lib/circuitBreaker.js - OSCAR API circuit breaker
- Configurable thresholds (5 failures / 30s window)
- Health status exposure for monitoring
- Graceful degradation during API outages
Health Checks (Kubernetes-ready)
lib/healthCheck.js - Comprehensive health check module
GET /health - Full dependency check (DB, OSCAR, circuit breaker)
GET /health/live - Kubernetes liveness probe
GET /health/ready - Kubernetes readiness probe
Error Standardization
lib/errors.js - APIError class hierarchy
- Voice-friendly error messages for Vapi
- Standardized JSON error response format
- Request ID correlation in all errors
Configuration Management
config/constants.js - Centralized configuration
- Environment validation on startup
- Service metadata and timeouts
- HTTP status code constants
Changed
vapiEndpoints.js - Full validation, logging, rate limiting integration
oscarRestService.js - Circuit breaker and structured logging
server.js - Health endpoints, graceful shutdown, global error handlers
- Authentication now fail-closed in production mode
Security
- Timing-safe API key comparison (prevents timing attacks)
- Request rate limiting (100 req/min general, 20 req/min booking)
- XSS sanitization in validation middleware
- Removed 40+ console.log statements
Code Review Progress
- 32/65 backlog items complete (49%)
- Security: 11/12 items (92%)
- Reliability: 10/13 items (77%)
- Quality: 11/18 items (61%)
[1.1.0] - 2026-01-12
Added
- BC Health registration requirements (PHN, BC Services Card)
get_clinic_info endpoint for registration status check
add_to_waitlist endpoint for new patient queue
- Clinic configuration table with registration toggle
- 3-second delay handling in voice agent
- Comprehensive compliance documentation (PIPEDA, PHIPA, SOC2)
Changed
- System prompt v2.0 - clinic-agnostic design
- Improved error messages for voice agent
- Updated tools definition to 14 endpoints
Fixed
- OSCAR REST Bridge response unwrapping
- Patient search by phone number format
[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)
- Call logging and analytics
- Docker Compose deployment
- NGINX reverse proxy with rate limiting
- SSL/TLS with Let's Encrypt
Database Schema
clinics - Clinic profiles
clinic_config - Per-clinic settings
clinic_hours - Working hours
clinic_holidays - Holiday closures
clinic_providers - Provider display names
waitlist - New patient queue
call_logs - Call analytics
users - Admin accounts
audit_logs - Admin action tracking
[0.5.0] - 2025-12-19
Added
- Initial release
- Single-clinic appointment booking
- Patient lookup by phone (caller ID)
- Patient lookup by name + DOB verification
- Find earliest appointment
- Book appointment
- Reschedule appointment
- Cancel appointment
- Transfer to clinic staff
- English language support
- OSCAR EMR integration (OAuth 1.0a)
Technical
- Node.js Express webhook handler
- OSCAR REST Bridge client
- Basic health check endpoint
- PM2 process management
[2.0.0] - Planned
Planned Features
- French Canadian language support
- Cantonese language support
- Punjabi language support
- Appointment reminders (outbound)
- SMS confirmation
- Admin UI v2 (React)
- Real-time analytics dashboard
- Multi-EMR support
- Prescription refill requests
Planned Technical
- Many-to-Many OSCAR routing
- GitOps configuration
- Intelligent failover
- Load balancing
- Webhook retry logic
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 |
| v2.0.0 |
Q1 2026 |
📋 Planned |