MedBase Extensibility Platform
Extend anything with no core code changes: JSON configs, webhooks, and Deno edge functions.
Your tech team extends anything. No core code changes. JSON configs, webhooks, and Deno edge functions.
What is MedBase?
MedBase is a Supabase-based (PostgreSQL + Realtime + Deno) orchestration layer that sits between the Moleculer microservices (MongoDB) and all frontend applications. It serves as:
- Event ingestion hub — receives
hospital_eventsfrom MongoDB via webhooks - Read model projector — normalizes encounter state into query-optimized Postgres tables
- Business rules engine host — runs RCM, CDS, and coding rules as Deno Edge Functions
- Realtime broadcaster — Supabase Realtime streams queue updates to web/mobile clients
- Configuration management — hospital-wide settings configurable via UI, no code deploys
Key Principle: MedBase NEVER owns business logic or writes to MongoDB. It projects, caches, validates, and broadcasts.
Architecture Diagram
┌──────────────────────────────────────────────────────────────────────────────┐
│ MOLECULER MICROSERVICES (MongoDB) │
│ Source of Truth — All Mutations Here │
│ │
│ ever-api-clinical ever-api-financial ever-api-medications ... │
└──────────────────────────────────┬───────────────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ hospital_events TABLE │
│ (Postgres INSERT) │
└─────────────┬──────────────┘
│
┌─────────────┴──────────────┐
│ PostgreSQL Trigger │
│ notify_encounter_ │
│ orchestrator() │
└─────────────┬──────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ MEDBASE (Supabase + Deno) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 18 EDGE FUNCTIONS (Deno Deploy) │ │
│ │ │ │
│ │ ORCHESTRATION BUSINESS RULES INTEGRATIONS │ │
│ │ ──────────── ────────────── ──────────── │ │
│ │ encounter- rcm-rule-engine eclaim-connector │ │
│ │ orchestrator clinical-rules- terminology-server │ │
│ │ migration- engine chula-daily-cash- │ │
│ │ orchestrator coding-rules- push │ │
│ │ engine report-template- │ │
│ │ AI ASSISTANTS coding-ai-assistant engine │ │
│ │ ───────────── │ │
│ │ claim-coder ANALYTICS SIDECARS │ │
│ │ diagnosis-assistant ───────── ──────── │ │
│ │ patient-screener gold-layer-refresh prm-sidecars/ │ │
│ │ usage-aggregator n8n + Dify + OpenClaw │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ READ MODEL TABLES (Postgres) │ │
│ │ │ │
│ │ encounter_journey_cache department_queues patient_clinical_cache │ │
│ │ rcm_financial_alert rcm_claim_batch coding_worklist │ │
│ │ prm_opportunities cds_rule_definitions medbase_config │ │
│ │ workflow_templates terminology_cache eclaim_delivery_log │ │
│ │ │ │
│ │ GOLD LAYER (Materialized Views) │ │
│ │ gold_fact_claims gold_coding_metrics gold_monthly_kpi │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ SUPABASE REALTIME (WebSocket) │ │
│ │ department_queues → filter: location_id=eq.{clinicId} │ │
│ │ encounter_journey_cache → filter: encounter_id=eq.{id} │ │
│ │ eclaim_delivery_log → all authenticated users │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ FRONTEND APPS (React / React Native) │
│ │
│ Reads from Supabase (realtime subscriptions) │
│ Writes to Moleculer APIs (never to MedBase directly) │
└──────────────────────────────────────────────────────────────────────────────┘
5 Ways Your Tech Team Extends MedBase (Zero Core Code Changes)
Pattern 1: Add a New RCM Country/Insurance Scheme
Effort: 1 JSON file. Zero code.
Create country-packs/{cc}-{scheme}.json:
{
"countryCode": "SG",
"schemeCode": "MEDISAVE",
"schemeName": "Singapore MediSave",
"rules": {
"encounterOverlap": { "opdToIpdMaxGapHours": 24 },
"latePenalty": { "baseRate": 500, "baseRateUnit": "SGD/DRG", "tiers": [...] },
"losReclassification": { "minIpHours": 4 }
},
"messages": {
"RCM_LATE_SUBMISSION_RISK": {
"local": "Submission risk tier {tierIndex}",
"en": "Late penalty tier {tierIndex}: {daysSince} days"
}
}
}
Register the scheme code, deploy. 13 generic evaluators (encounter overlap, late penalty, LOS reclassification, bariatric BMI, palliative quota, drug catalogue, etc.) evaluate against the JSON config automatically.
Developer Guide: medbase/functions/rcm-rule-engine/RCM_COUNTRY_PACK_DEVELOPER_GUIDE.md
Pattern 2: Add a Clinical Decision Support (CDS) Rule
Effort: 1 SQL INSERT or UI form. Zero code.
INSERT INTO cds_rule_definitions
(rule_code, rule_type, description, parameters, severity, alert_tier)
VALUES (
'RENAL_NSAID_CHECK',
'LAB_MED_CROSS',
'Block NSAIDs when creatinine > 2.0',
'{"labCode": "CREATININE", "operator": ">", "threshold": 2.0,
"targetMedCodes": ["NSAID", "IBUPROFEN"], "action": "BLOCK"}',
'high', 1
);
Supported rule types:
STALE_TTL— age-based data freshness alertsCRITICAL_LAB— threshold + medication cross-checkLAB_MED_CROSS— drug-lab interaction warningsTIMING— event sequencing (e.g., antibiotic prophylaxis window)
The clinical-rules-engine Deno function evaluates all rules at runtime. Pharmacists can configure rules without developer involvement.
Pattern 3: Add a Workflow Variant per Clinic/Location
Effort: JSON workflow template + 1 SQL binding. Zero code.
- Create workflow template (visual builder or JSON):
{
"nodes": [
{ "id": "check-in", "type": "workflow-node", "data": {
"type": "check-in", "title": "เช็คอิน", "transitions": ["wait-doctor"] }},
{ "id": "wait-doctor", "type": "workflow-node", "data": {
"type": "wait-doctor", "title": "รอพบแพทย์", "transitions": ["consultation"] }},
{ "id": "consultation", "type": "workflow-node", "data": {
"type": "doctor-in-process", "title": "พบแพทย์" }}
]
}
- Bind to location with priority resolution:
INSERT INTO workflow_template_bindings
(workflow_kind, scope_type, scope_id, template_id, priority)
VALUES ('patient-intake', 'location', 'loc_derma_123', 'tmpl_uuid', 100);
Resolution order: location (100) > sub_clinic (50) > clinic (10). Each department can have its own patient flow without affecting others.
Pattern 4: Build External Side-Apps via Webhooks
Effort: Register a webhook subscription. Your app receives events.
The WebhookDispatcher in Moleculer emits HMAC-signed HTTP POSTs for any domain event:
POST https://your-app.com/webhook
Headers:
X-Vajira-Event: clinical.order.created
X-Vajira-Signature: sha256=abc123...
X-Vajira-Delivery-ID: uuid-for-dedup
Body: { encounter_id, patient_id, payload: {...} }
Available event families:
clinical.*— orders, results, alerts, notesfinancial.*— claims, invoices, settlementsmedication.*— prescriptions, administrations, reconciliationadministration.*— patient registration, department changesprm.*— care gap opportunities, outreach, consent
Example side-apps already built this way:
- n8n workflow: care-gap → HubSpot → Dify AI → WhatsApp outreach
- OpenClaw skill: insurance coverage verification (Python)
- Dify personas: Protocol Scout (clinical analyst), Brand Concierge (VIP liaison)
All webhooks are optional. If deleted, the hospital still works — the guaranteed internal path (hospital_events → Deno → cache) always fires.
Pattern 5: Toggle Features via Configuration UI
Effort: 1 row in medbase_config. Zero code.
INSERT INTO medbase_config
(code, name, setting_group, value_type, value)
VALUES
('ai.mode', 'AI Mode', 'ai', 'choice', 'lite'),
('ai.active', 'AI Active', 'ai', 'boolean', 'false'),
('cds.engine_enabled', 'CDS Engine', 'cds', 'boolean', 'true');
Value types: string, boolean, number, choice (with dropdown options)
Frontend reads medbase_config at runtime. Non-developers toggle features via Settings UI. Per-hospital overrides via hospital_id column.
Pre-configured settings:
- AI mode (lite/pro), AI model selection, AI feature flags
- CDS engine toggles (stale check, critical lab, renal dose)
- Event retention days, cache TTL, alert limits per encounter
Database Schema (17 Migration Files)
| Migration | Key Tables |
|---|---|
| 001 | encounter_journey_cache, medbase_dead_letter_queue, medbase_config |
| 003 | department_queues (Realtime-enabled, location-filtered) |
| 003b | patient_clinical_cache, cds_rule_definitions |
| 004 | gdl_rule_sets, workflow_entity_defaults |
| 005 | conference_decisions, conference_participants |
| 006 | workflow_form_models, workflow_form_sessions, workflow_form_responses |
| 007 | workflow_template_bindings (site-specific resolution) |
| 008 | order_dispatch_policies |
| 010 | prm_scout_rules, prm_opportunities, prm_patient_consent, prm_outreach_log |
| 010b | rcm_financial_alert, rcm_claim_batch, rcm_rep_response, rcm_ai_suggestion_log |
| 011 | eclaim_delivery_log |
| 012 | terminology_cache |
| 013 | gold_fact_claims (materialized view) |
| 015 | coding_worklist |
| 016 | gold_coding_metrics (materialized view) |
| 017 | Migration tables (9 tables + indexes) |
RLS Pattern (Row-Level Security): Authenticated users get read-only. Service role (Deno functions) gets full access. Frontend never writes directly.
Why This Matters for CTOs
| Concern | How MedBase Addresses It |
|---|---|
| Vendor lock-in | JSON config packs. Switch RCM rules, CDS rules, workflows without code |
| Time to market | New country/scheme = 1 JSON file. New CDS rule = 1 SQL row |
| Team autonomy | Hospital tech teams extend without touching core codebase |
| Side-app ecosystem | HMAC-signed webhooks enable third-party integrations |
| Compliance | Per-country compliance profiles, PHI masking levels, data residency controls |
| Observability | Dead letter queue, audit fields, event retention, latency logging |
| AI readiness | Config-driven model selection. Toggle AI features per hospital |