206 lines
8 KiB
Markdown
206 lines
8 KiB
Markdown
# Signal Support Manual
|
|
|
|
Curated operations knowledge for the Signal CGM documentation readiness platform.
|
|
Support bot reads this + support-api-ref.json + Barrier Log for troubleshooting.
|
|
See signal/docs/support-api-ref.json for auto-generated API routes and error codes.
|
|
|
|
---
|
|
|
|
## CSV Import
|
|
|
|
Signal ingests order data from any DME order management CSV export.
|
|
|
|
### Required Columns
|
|
|
|
Column names are matched case-insensitively. At minimum, the CSV must contain
|
|
identifying and status fields. Signal evaluates each row against documentation
|
|
requirements and produces a status per patient.
|
|
|
|
| Column | Required | Purpose |
|
|
|--------|----------|---------|
|
|
| patient_name | Yes | Patient identifier |
|
|
| cgm_type | Yes | Device type for LCD rule matching |
|
|
| sw0_status | No | Signed written order status |
|
|
| qualifying_visit_date | No | Last qualifying visit date |
|
|
| pa_status | No | Prior authorization status |
|
|
| next_shipment_date | No | Expected resupply date |
|
|
| payer | No | Payer name for routing checks |
|
|
|
|
If a column is absent, Signal treats the requirement as "not evaluated" —
|
|
not a gap. This prevents false negatives when a supplier's export format
|
|
omits fields they don't track.
|
|
|
|
### Validation Rules
|
|
|
|
- Rows with empty patient_name are skipped
|
|
- Unknown cgm_type values log a warning and skip LCD matching
|
|
- Date columns must be ISO 8601 (YYYY-MM-DD) or a parseable US format
|
|
- Files over 10MB are rejected (supplier sends manageable subsets)
|
|
|
|
### Error Messages (common)
|
|
|
|
| Error | Cause | Fix |
|
|
|-------|-------|-----|
|
|
| "Missing required columns" | CSV missing patient_name or cgm_type | Check export template |
|
|
| "Upload failed — auth error" | API key missing or expired | Generate new key in Railway env |
|
|
| "Upload failed — CORS error" | Frontend domain not in allow list | Add domain to ALLOWED_ORIGINS_REGEX |
|
|
| "Upload failed — server error" | Backend crashed or timed out | Check Railway logs |
|
|
| "No parsable rows found" | All rows failed validation | Check column names in export |
|
|
|
|
---
|
|
|
|
## API Reference
|
|
|
|
See `signal/docs/support-api-ref.json` for full auto-generated route listing.
|
|
|
|
### Authentication
|
|
|
|
- All endpoints require `X-API-Key` header matching the value in Railway env vars
|
|
- Clerk-authenticated endpoints use Bearer JWT tokens
|
|
- Dev keys are for sandbox only; rotate before any external user accesses the app
|
|
|
|
### Key Endpoints
|
|
|
|
| Endpoint | Method | Purpose |
|
|
|----------|--------|---------|
|
|
| /api/health | GET | Health check — returns {"status": "ok"} |
|
|
| /api/upload-csv | POST | Upload and process CSV file |
|
|
| /api/patients | GET | List all patients with status summary |
|
|
| /api/patients/{id} | GET | Single patient detail and cascade |
|
|
| /api/confirm-visit | POST | Record qualifying visit confirmation |
|
|
| /api/update-doc-status | POST | Update document status for a requirement |
|
|
| /api/export | GET | Download Signal Report as CSV |
|
|
|
|
### Common Response Codes
|
|
|
|
| Code | Meaning | Likely Cause |
|
|
|------|---------|--------------|
|
|
| 200 | Success | — |
|
|
| 400 | Bad request | Missing or malformed parameters |
|
|
| 401 | Unauthorized | Missing or invalid API key |
|
|
| 403 | Forbidden | Valid key, insufficient scope |
|
|
| 404 | Not found | Patient ID doesn't exist |
|
|
| 500 | Server error | Backend exception (check logs) |
|
|
| 503 | Service unavailable | Database connection issue or deployment cycling |
|
|
|
|
---
|
|
|
|
## Status Labels
|
|
|
|
Signal uses 4 UI tabs. The backend computes 8 internal flags that map to these.
|
|
|
|
### Internal Flags (backend)
|
|
|
|
| Flag | Meaning | Trigger |
|
|
|------|---------|---------|
|
|
| SUPPLY_LAPSED | Patient is past resuppy date | next_shipment_date passed |
|
|
| VISIT_REQUIRED | 6-month qualifying visit expired | qualifying_visit_date > 6 months ago |
|
|
| RENEWAL_CRITICAL | Prescription renewal due within 15 days | Calculated from renewal date |
|
|
| RENEWAL_ELEVATED | Renewal due within 30 days | |
|
|
| RENEWAL_SOON | Renewal due within 60 days | |
|
|
| RESUPPLY_READY | All requirements met, ready to ship | SWO on file + PA approved + visit current + no cascade gaps |
|
|
| ACTIVE | Patient is stable, no flags | Nothing due, no gaps |
|
|
| TRANSFER_PENDING | Incoming from another supplier | Set manually in CSV or UI |
|
|
|
|
### UI Tabs (frontend, mapped from internal flags)
|
|
|
|
| Tab | Internal Flags Included |
|
|
|-----|------------------------|
|
|
| At Risk | SUPPLY_LAPSED |
|
|
| Action Needed | VISIT_REQUIRED, RENEWAL_CRITICAL, RENEWAL_ELEVATED |
|
|
| Clear to Ship | RESUPPLY_READY (with no cascade items) |
|
|
| On Track | ACTIVE, RENEWAL_SOON, TRANSFER_PENDING, NO_RECENT_SHIPMENT |
|
|
|
|
---
|
|
|
|
## Documentation Requirements (Cascade)
|
|
|
|
Each patient has a cascade — a list of documentation actions needed to
|
|
reach Clear to Ship. Cascade items are only shown when their source column
|
|
was supplied in the CSV.
|
|
|
|
### Possible Cascade Items
|
|
|
|
| Item | Cause | Cleared By |
|
|
|------|-------|------------|
|
|
| Signed Written Order (SWO) | sw0_status is not "On File" | Update sw0_status or use "Confirm Visit" |
|
|
| Qualifying Visit | qualifying_visit_date missing or > 6 months | Schedule and confirm visit |
|
|
| Prior Authorization | pa_status is not "Approved" | Submit PA and update status in CSV |
|
|
| Prescription Renewal | renewal_date approaching or passed | Obtain new prescription |
|
|
|
|
---
|
|
|
|
## Common Failures & Resolutions
|
|
|
|
Issues from the Barrier Log that appear most often. Full history at
|
|
`STTIL-Vault/Projects/Barrier-Log.md`.
|
|
|
|
### Uploads Fail Silently
|
|
|
|
**Symptoms:** CSV uploads return success but worklist stays empty or shows
|
|
wrong statuses. No error message shown to user.
|
|
|
|
**Root cause:** `api.js` had `catch { return null }` blocks swallowing all
|
|
errors. Fixed by re-throwing real errors and adding toast notifications.
|
|
|
|
**Status:** Fixed and deployed. If it recurs, check that:
|
|
|
|
1. The frontend is deployed from the fix branch (vercel --prod)
|
|
2. The backend is deployed from the matching fix (railway up --detach)
|
|
3. ALLOWED_ORIGINS_REGEX includes the domain
|
|
|
|
### Clear to Ship Never Goes Green
|
|
|
|
**Symptoms:** All patients show amber status, even resupply-ready ones.
|
|
Green count is permanently 0.
|
|
|
|
**Root cause:** The backend scored missing CSV columns as doc gaps. An
|
|
absent "sw0_status" column meant every patient had a "missing SWO" cascade
|
|
item. Green = "no cascade items" so green was unreachable.
|
|
|
|
**Fix:** Added "supplied" sentinel flags. An absent column is "not evaluated,"
|
|
not a gap. Green means "no known blocker from the data provided."
|
|
|
|
**Status:** Fixed and deployed. Verify by uploading a CSV with resupply-ready
|
|
patients — they should show green.
|
|
|
|
### CORS Errors on Vercel Deploy
|
|
|
|
**Symptoms:** Upload fails with browser CORS error on preview URLs.
|
|
|
|
**Root cause:** ALLOWED_ORIGINS was a fixed list. Vercel preview URLs
|
|
(project-xxxx.vercel.app) weren't included.
|
|
|
|
**Fix:** Changed to ALLOWED_ORIGINS_REGEX to accept *.vercel.app patterns.
|
|
|
|
### Status Count Mismatch (Stat Card vs Row Count)
|
|
|
|
**Symptoms:** The stat card shows a different green count than filtering
|
|
by "Clear to Ship" tab.
|
|
|
|
**Root cause:** Stat card counted RESUPPLY_READY. Tab counted
|
|
RESUPPLY_READY AND cascade empty. Cascade was never empty (see above).
|
|
|
|
**Fix:** Both now use the same logic: RESUPPLY_READY with no cascade gaps.
|
|
|
|
---
|
|
|
|
## Known Issues (Active)
|
|
|
|
| Issue | Status | Workaround |
|
|
|-------|--------|------------|
|
|
| Clerk production migration deferred | Blocking real supplier login | Use sandbox keys for dev; manual Google OAuth setup needed |
|
|
| Gaboro demo API key in Railway env | Security risk before external access | Rotate before Robert Robinson pilot |
|
|
| granola-ingest portable path | Needs path update | Script works from full path; symlink/alias pending |
|
|
|
|
---
|
|
|
|
## Cross-References
|
|
|
|
- **State machine code:** python-backend/core/doc_state_machine.py
|
|
- **Cascade builder:** python-backend/core/doc_state_machine.py (_build_cascade)
|
|
- **Frontend status mapping:** signal-ui/src/components/WorklistTable.jsx
|
|
- **Upload handler:** signal-ui/src/lib/api.js
|
|
- **API auth:** python-backend/api/main.py (X-API-Key middleware)
|
|
- **Barrier Log (all resolved issues):** STTIL-Vault/Projects/Barrier-Log.md
|
|
- **TriLane research library:** Signal workspace (research docs, payer matrix, synthesis)
|