ABDM OPD Queue (today): - New EAtriaBridgeConnector: opdQueueFetch/opdTokenCreate/opdTokenUpdateStatus + patch() helper - New AbdmOpdQueue controller: index/list/fetchQueue/createToken/updateTokenStatus/processScannedToken - fetchQueue syncs gateway tokens into abdm_opd_tokens (local DB) and enriches with HMS patient data - processScannedToken auto-finds/creates patient_master record from ABHA scan data, marks token CALLED - New migration: abdm_opd_tokens table (gateway_token_id, source, status, patient_id, opd_id, processed_at) - New view: abdm/opd_queue.php - reception screen with auto-refresh 30s, HMS Patient column (green row when OPD registered) - Sidebar: ABDM OPD Queue nav link added - Routes: AbdmOpdQueue with abdmPermFilter ABHA Register tab (earlier this session): - New Abha controller: initiate/verifyOtp/communication/verifyCommOtp/validateAbha/card + autoCreateOrFindPatient - New views: abha/card.php, partials/abha_create_panel.php, partials/abha_otp_modal.php - Patient_V.php: ABHA Register tab with 4-method wizard (ABHA number, QR scan, facility QR, mobile OTP) Patient ABHA search fix: - Patient::search() now detects ABHA column (abha_id/abha_no/abha/abha_address) and searches by it ABDM Bridge infrastructure: - EAtriaBridgeConnector: new connector for e-atria.in ABDM bridge gateway - AbdmConnectorFactory/Interface updated - AbdmGatewaySettings controller + view - SNOMED/CSNOTK terminology service skeleton - Finance payout OPD consult views - Migration: AddAbdmPushFieldsToOpdAndPatient, CreateSnomedCoreTables - Docs: abdm/ API specs, architecture, gateway guides
297 lines
9.6 KiB
Markdown
297 lines
9.6 KiB
Markdown
# Dual-Bridge Architecture Configuration Guide
|
|
|
|
## Architecture Overview
|
|
|
|
```
|
|
HMS CI4 Queues Events
|
|
↓ Routes by event_type prefix
|
|
├─→ snomed.* events
|
|
│ ↓ POST to BRIDGE_SYNC_URL
|
|
│ https://csnotk.e-atria.in/api/bridge
|
|
│ (CSNOtk Bridge: Codes diagnosis → FHIR)
|
|
│
|
|
└─→ abdm.* events
|
|
↓ POST to ABDM_BRIDGE_URL
|
|
https://abdm-bridge.e-atria.in/api/v1/bridge
|
|
(ABDM Bridge: Routes to ABDM M1 server)
|
|
```
|
|
|
|
---
|
|
|
|
## Event Type Routing Table
|
|
|
|
| Event Type | Destination | Purpose |
|
|
|-----------|-------------|---------|
|
|
| `snomed.diagnosis.validate` | CSNOtk `/api/bridge` | Validate & code diagnosis with SNOMED CT |
|
|
| `snomed.medication.validate` | CSNOtk `/api/bridge` | Validate & code medication with SNOMED CT |
|
|
| `abdm.abha.validate` | ABDM Bridge `/api/v1/bridge` | Validate ABHA number with ABDM M1 |
|
|
| `abdm.scan_share.lookup` | ABDM Bridge `/api/v1/bridge` | QR code lookup for health records |
|
|
| `abdm.fhir.share.requested` | ABDM Bridge `/api/v1/bridge` | Push FHIR bundle to ABDM M1 |
|
|
| `abdm.opd.prescription.share.requested` | ABDM Bridge `/api/v1/bridge` | Push OPD prescription bundle |
|
|
| `abdm.ipd.discharge.share.requested` | ABDM Bridge `/api/v1/bridge` | Push IPD discharge bundle |
|
|
| `abdm.diagnosis.report.share.requested` | ABDM Bridge `/api/v1/bridge` | Push diagnosis report bundle |
|
|
| `abdm.consent.requested` | ABDM Bridge `/api/v1/bridge` | Request patient consent for data access |
|
|
|
|
---
|
|
|
|
## HMS .env Configuration Required
|
|
|
|
### Step 1: Dual Bridge URLs
|
|
|
|
Replace the current BRIDGE configuration with this:
|
|
|
|
```env
|
|
# ==================== CSNOtk Bridge (SNOMED CT Terminology) ====================
|
|
# Purpose: Receive diagnosis/medication events, validate with SNOMED CT, return FHIR-coded data
|
|
# Endpoint: POST /api/bridge
|
|
# Used by: BridgeSyncService when routing snomed.* events
|
|
BRIDGE_SYNC_URL = https://csnotk.e-atria.in/api/bridge
|
|
BRIDGE_SYNC_TOKEN =
|
|
BRIDGE_SYNC_TIMEOUT = 20
|
|
|
|
# ==================== ABDM Bridge (ABDM M1 Communication) ====================
|
|
# Purpose: Receive ABDM events, route to ABDM Live/Sandbox M1 server
|
|
# Endpoint: POST /api/v1/bridge
|
|
# Used by: BridgeSyncService when routing abdm.* events
|
|
# Architecture: Multiple HMS instances → Single ABDM Bridge → ABDM M1 Server
|
|
ABDM_BRIDGE_URL = https://abdm-bridge.e-atria.in/api/v1/bridge
|
|
ABDM_BRIDGE_TOKEN =
|
|
|
|
# ==================== Bridge Configuration ====================
|
|
BRIDGE_SOURCE_CODE = SBXID_033661
|
|
BRIDGE_SYNC_PROVIDER = bridge
|
|
|
|
# ==================== SNOMED CT Terminology Service (Direct REST API) ====================
|
|
# Purpose: Direct access to CSNOtk REST API for autocomplete (OPD diagnosis search)
|
|
# Endpoints: /rest/search/suggest, /rest/search/lookup, /rest/search/validate/id
|
|
# Used by: CsnotkTerminologyService in OPD_Prescription controller
|
|
snomed.csnotk.baseUrl = https://csnotk.e-atria.in/csnoserv
|
|
snomed.csnotk.enabled = true
|
|
snomed.csnotk.timeoutSec = 10
|
|
```
|
|
|
|
### Step 2: Generate Bearer Tokens
|
|
|
|
Generate TWO random tokens (one for each bridge):
|
|
|
|
```bash
|
|
# Token 1 for CSNOtk Bridge
|
|
openssl rand -hex 32
|
|
# Example: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
|
|
|
|
# Token 2 for ABDM Bridge
|
|
openssl rand -hex 32
|
|
# Example: f2e1d0c9b8a7z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1
|
|
```
|
|
|
|
### Step 3: Update .env Tokens
|
|
|
|
```env
|
|
BRIDGE_SYNC_TOKEN = a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
|
|
ABDM_BRIDGE_TOKEN = f2e1d0c9b8a7z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1
|
|
```
|
|
|
|
---
|
|
|
|
## BridgeSyncService Routing Logic (To Be Implemented)
|
|
|
|
Update `app/Libraries/BridgeSyncService.php` buildBridgeDispatchContext() to route based on event prefix:
|
|
|
|
### Pseudocode Logic
|
|
|
|
```php
|
|
private function buildBridgeDispatchContext(array $row, array $payload): array
|
|
{
|
|
$eventType = (string) ($row['event_type'] ?? '');
|
|
|
|
// Route snomed.* events to CSNOtk
|
|
if (str_starts_with($eventType, 'snomed.')) {
|
|
return [
|
|
'ok' => true,
|
|
'channel' => 'csnotk',
|
|
'endpoint' => $this->readSetting('BRIDGE_SYNC_URL'), // CSNOtk bridge
|
|
'method' => 'POST',
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $this->readSetting('BRIDGE_SYNC_TOKEN'),
|
|
],
|
|
'body' => [
|
|
'queue_id' => (int) ($row['id'] ?? 0),
|
|
'source' => $source,
|
|
'event_type' => $eventType,
|
|
'payload' => $payload,
|
|
'occurred_at' => (string) ($row['created_at'] ?? ''),
|
|
],
|
|
];
|
|
}
|
|
|
|
// Route abdm.* events to ABDM Bridge
|
|
if (str_starts_with($eventType, 'abdm.')) {
|
|
return [
|
|
'ok' => true,
|
|
'channel' => 'abdm',
|
|
'endpoint' => $this->readSetting('ABDM_BRIDGE_URL'), // ABDM bridge
|
|
'method' => 'POST',
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $this->readSetting('ABDM_BRIDGE_TOKEN'),
|
|
],
|
|
'body' => [
|
|
'queue_id' => (int) ($row['id'] ?? 0),
|
|
'source' => $source,
|
|
'event_type' => $eventType,
|
|
'payload' => $payload,
|
|
'occurred_at' => (string) ($row['created_at'] ?? ''),
|
|
],
|
|
];
|
|
}
|
|
|
|
// Unknown event type
|
|
return ['ok' => false, 'error' => 'Unsupported event_type prefix'];
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## CSNOtk Bridge `/api/bridge` Contract
|
|
|
|
### Request Format
|
|
|
|
```json
|
|
{
|
|
"queue_id": 12345,
|
|
"source": "SBXID_033661",
|
|
"event_type": "snomed.diagnosis.validate",
|
|
"payload": {
|
|
"diagnosis_text": "fever",
|
|
"return_limit": 10
|
|
},
|
|
"occurred_at": "2024-05-13T10:30:00+05:30"
|
|
}
|
|
```
|
|
|
|
### Response Format (Expected)
|
|
|
|
```json
|
|
{
|
|
"ok": 1,
|
|
"event_type": "snomed.diagnosis.validate",
|
|
"data": [
|
|
{
|
|
"concept_id": "25064002",
|
|
"term": "Headache",
|
|
"hierarchy": "disorder",
|
|
"is_preferred": 1,
|
|
"concept_fsn": "Headache (disorder)"
|
|
}
|
|
],
|
|
"request_id": "REQ-abc123"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## ABDM Bridge `/api/v1/bridge` Contract
|
|
|
|
**(See `gateway-php-ci4/README.md` for full API contract)**
|
|
|
|
### Request Format
|
|
|
|
```json
|
|
{
|
|
"queue_id": 12345,
|
|
"source": "SBXID_033661",
|
|
"event_type": "abdm.abha.validate",
|
|
"payload": {
|
|
"abha_id": "00-0000-0000-0000"
|
|
},
|
|
"occurred_at": "2024-05-13T10:30:00+05:30"
|
|
}
|
|
```
|
|
|
|
### Response Format (Expected)
|
|
|
|
```json
|
|
{
|
|
"ok": 1,
|
|
"event_type": "abdm.abha.validate",
|
|
"request_id": "REQ-abc123",
|
|
"data": {
|
|
"abha": "00-0000-0000-0000",
|
|
"status": "VALID"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Checklist
|
|
|
|
### Phase 1: Configuration
|
|
- [ ] Update HMS `.env` with both `BRIDGE_SYNC_URL` (CSNOtk) and `ABDM_BRIDGE_URL` (ABDM)
|
|
- [ ] Generate two separate bearer tokens
|
|
- [ ] Set `BRIDGE_SYNC_TOKEN` and `ABDM_BRIDGE_TOKEN` in .env
|
|
- [ ] Document tokens in secure location (password manager)
|
|
|
|
### Phase 2: Code Changes
|
|
- [ ] Update `BridgeSyncService::buildBridgeDispatchContext()` with routing logic
|
|
- [ ] Update `BridgeSyncService::buildDispatchContext()` to handle snomed.* routing
|
|
- [ ] Update `BridgeSyncService::readSetting()` to support `ABDM_BRIDGE_URL` and `ABDM_BRIDGE_TOKEN`
|
|
- [ ] Add logging to distinguish between CSNOtk and ABDM bridge calls in `abdm_api_logs` table
|
|
|
|
### Phase 3: Testing
|
|
- [ ] Queue a `snomed.diagnosis.validate` event and verify it goes to CSNOtk
|
|
- [ ] Queue an `abdm.abha.validate` event and verify it goes to ABDM Bridge
|
|
- [ ] Check `abdm_api_logs` for successful routing
|
|
- [ ] Verify CSNOtk returns SNOMED-coded data
|
|
- [ ] Verify ABDM Bridge routes to ABDM M1 correctly
|
|
|
|
### Phase 4: Deployment
|
|
- [ ] Deploy PHP gateway to https://abdm-bridge.e-atria.in (if not already live)
|
|
- [ ] Configure gateway `.env` with `GATEWAY_BEARER_TOKEN` matching HMS `ABDM_BRIDGE_TOKEN`
|
|
- [ ] Run `php spark bridge:sync --limit 10` to test both bridge types
|
|
- [ ] Monitor logs for any routing or authentication errors
|
|
|
|
---
|
|
|
|
## Database Logging
|
|
|
|
The `abdm_api_logs` table will now record:
|
|
- `channel` = 'csnotk' or 'abdm' (for routing differentiation)
|
|
- `event_type` = snomed.* or abdm.*
|
|
- `endpoint` = CSNOtk or ABDM bridge URL used
|
|
- `status` = 'success' or 'error'
|
|
- `error_message` = 403 Unauthorized, 404 Not Found, etc.
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Problem: 403 Unauthorized on CSNOtk
|
|
- **Check:** BRIDGE_SYNC_TOKEN matches CSNOtk Bridge expectation
|
|
- **Verify:** Request to `https://csnotk.e-atria.in/api/bridge` includes bearer token
|
|
|
|
### Problem: 403 Unauthorized on ABDM Bridge
|
|
- **Check:** ABDM_BRIDGE_TOKEN matches PHP gateway `GATEWAY_BEARER_TOKEN`
|
|
- **Verify:** PHP gateway `.env` has the same token as HMS `ABDM_BRIDGE_TOKEN`
|
|
|
|
### Problem: Events stuck in pending status
|
|
- **Check:** Routing logic correctly identifies event prefix (snomed.* vs abdm.*)
|
|
- **Query:** `SELECT * FROM bridge_sync_queue WHERE status='pending' ORDER BY created_at DESC`
|
|
- **Debug:** Add logging to see which endpoint was called
|
|
|
|
### Problem: CSNOtk returns 404 on /api/bridge
|
|
- **Cause:** `/api/bridge` endpoint may not be exposed on the CSNOtk public server
|
|
- **Fallback:** Check if CSNOtk only exposes `/rest/search/*` endpoints (direct API calls only)
|
|
- **Action:** If needed, create intermediate queue processor for CSNOtk terminology service
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- **CSNOtk REST API Reference:** `docs/CSNOTK_API_REFERENCE.md`
|
|
- **CSNOtk Database:** `SnomedCT_InternationalRF2_PRODUCTION_20260501T120000Z/`
|
|
- **ABDM PHP Gateway:** `gateway-php-ci4/` (deployment guide: `ABDM_GATEWAY_PHP_DEPLOYMENT.md`)
|
|
- **Current CSNOtk Direct API Integration:** `app/Libraries/CsnotkTerminologyService.php`
|
|
- **Bridge Service:** `app/Libraries/BridgeSyncService.php`
|