update CLAUDE.md and coverage calculator; add n8n content radar workflow, vercel SPA rewrite, and ui workspace config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kisa 2026-06-02 00:41:49 -04:00
parent d4e5187350
commit 07120ec062
5 changed files with 112 additions and 42 deletions

112
CLAUDE.md
View file

@ -1,11 +1,11 @@
# STTIL Solutions — Signal | Level 1 Active Context # STTIL Solutions — Signal | Active Build Context
## What This Tool Does ## What This Tool Does
Signal is a B2B CGM documentation readiness tracker for DMEPOS suppliers. Signal is a B2B DMEPOS documentation readiness tracker for CGM suppliers.
It ingests order data from any DME order management CSV export (e.g., Brightree), It ingests order data from any DME order management CSV export (e.g., Brightree),
evaluates each patient against documentation requirements (6-month qualifying evaluates each patient against documentation requirements (6-month qualifying
visit, PECOS enrollment, SWO, resupply eligibility), and produces a Signal Report visit, PECOS enrollment, SWO, resupply eligibility), and produces an actionable
so supplier staff can prioritize outreach and capture revenue before it leaks. worklist for supplier staff to prioritize outreach and capture revenue before it leaks.
NOTE: Signal identifies gaps. It does not conduct outreach. Never write copy NOTE: Signal identifies gaps. It does not conduct outreach. Never write copy
implying Signal contacts prescribers or patients directly. implying Signal contacts prescribers or patients directly.
@ -24,53 +24,85 @@ and stays predictable.
quantity, payer — NOTHING else quantity, payer — NOTHING else
- All logs use hashed patient_id, never raw - All logs use hashed patient_id, never raw
## Level 1 Stack (Active) ## Current Stack (Updated 2026-05-29)
- Hosting: Hostinger VPS (self-hosted, data never leaves VPS) - Backend: Railway (Python/FastAPI) — live at https://signal-api-production-91c2.up.railway.app
- Language: Python (FastAPI or Flask) - Database: Supabase (PostgreSQL + RLS policies + Third Party Auth with Clerk)
- Database: PostgreSQL (encrypted at rest, audit logs) - Auth: Clerk — app name: eternal-goblin-1, domain: eternal-goblin-1.clerk.accounts.dev
- Orchestration: n8n self-hosted (24-hr batch trigger) - Frontend: Vite/React (signal-ui) — local dev only at localhost:5173, NOT YET deployed publicly
- Notifications: Self-hosted Mailcow — encrypted email to DME staff only - Orgs in Clerk: STTIL Solutions (default), Gaboro DME (org_3EPAEcAw06V2yGMSkxE3UjqIA3c)
- Frontend: Simple dashboard (Vercel or self-hosted)
- Auth: Session tokens in PostgreSQL (no Convex needed for MVP) ## Run Commands
- Frontend (local): `cd signal-ui && pnpm dev` → localhost:5173
- Backend deploy (code change): `railway up --detach` from project root — forces fresh build
- Backend redeploy (no code change): `railway redeploy` — reuses existing image
## Active Files ## Active Files
- python-backend/core/coverage_calculator.py - signal-ui/src/App.jsx — Clerk auth gate, OrganizationSwitcher
- signal-ui/src/components/WorklistTable.jsx — main worklist display
- signal-ui/src/components/CSVImport.jsx — CSV upload
- signal-ui/src/components/CSVExport.jsx — CSV export
- python-backend/core/coverage_calculator.py — gap detection logic (see Known Bugs)
- python-backend/core/audit_logger.py - python-backend/core/audit_logger.py
- python-backend/core/persistence.py
- python-backend/core/supabase_client.py
- python-backend/api/main.py
- python-backend/api/normalizer.py
- python-backend/config/payer_rules.json - python-backend/config/payer_rules.json
- research/dmepos-research-v3.md (market context)
- docs/hipaa-deployment-analysis-v1.md (compliance)
- docs/sttil-brand-system-v1.md (brand)
## Current BAA Obligations (Level 1 Only) ## Known Bugs — Fix Before Pilot
- Hostinger VPS: Request BAA (PHI host) 1. ~~**Payer matching**~~ — FIXED 2026-05-29. `_normalize_payer()` added to `coverage_calculator.py`. Handles: "Medicare Part B" → medicare, "Tricare for Life" / "TFL" → medicare, "Medicaid - GA" → medicaid, commercial insurer names → commercial.
- Anthropic API: Request BAA if AI layer touches PHI 2. **Visit date**: coverage_calculator.py uses shipment_date as proxy for qualifying visit, not an actual visit date. Fix: use stored confirmed visit date when available; fall back to shipment_date - 30 days labeled as estimated.
- Everything else: self-hosted = you are the operator
## Workload Impact Model (Build This) ## Features Not Yet Built — Pilot Priority
Two-curve graph showing supplier staff time over months: - **Confirm Visit workflow**: staff button on each worklist row to record a confirmed visit date. Signal stores it against patient_id in Supabase. This is Signal's core persistent value — without it, visit dates never improve beyond estimates.
- Curve A: Appeals/denials workload (reactive) — starts HIGH, trends DOWN - **Frontend public URL**: DEPLOYED 2026-05-29 — https://signal-ui-xi.vercel.app
- Curve B: Proactive outreach via Signal — starts MANAGEABLE, stays FLAT - **25 CSV variant test suite**: whitepaper requirement. Generate and test 25 mock CSVs with different column orders, headers, date formats, and payer name variants.
- X-axis: Months 112 post-onboarding - **Mapping review interface**: confidence score display, user override dropdown per column (per whitepaper spec).
- Crossover point = ROI moment to show on discovery calls
## What Is Tabled (Do Not Build Yet) ## Pilot Readiness — Authoritative Gauge
**Progress is measured against the whitepaper checklist only. Do not estimate % from feel.**
| Item | Phase | Reason deferred | Whitepaper: `/Users/sttil-solutions/Documents/Obsidian_Vault/STTIL-Vault/Projects/2026-05-18-pilot-readiness-whitepaper.md`
|------|-------|----------------|
| AWS infrastructure (any service) | Post-pilot | Jakub (coach, 2026-05-28): mock data is sufficient for demos and pilots. AWS takes 2 hours to set up — do it right before signing live PHI contracts. Do not start during MVP or pilot phase. | ### Checklist Status (as of 2026-05-29) — 40-45% pilot-ready
| Dexcom OAuth API integration | Phase 2 | Requires vendor agreement + PHI scope expansion |
| Billing system API integration (Brightree, Bonafide, Fastrack, etc.) | Phase 2 | Build after pilot reveals which systems suppliers use; vendor agreements required; PHI scope expands significantly | | Checklist Item | Status |
| CMS and contact management integration (Salesforce, etc.) | Phase 2 | Pilot feedback will reveal if suppliers have CMS and what they use; do not assume | |---|---|
| Prescriber fax automation | Phase 2 | Workflow complexity; Level 1 manual outreach sufficient | | App hosted behind stable URL | PASS — https://signal-ui-xi.vercel.app (deployed 2026-05-29) |
| Patient-facing SMS (Twilio, not SignalWire) | Phase 3 | PHI transmission to third-party; requires BAA + consent layer | | Demo login / controlled access working | PASS |
| Consortium strategy (Level 2/3) | 1824 months | Depends on 15+ paying Level 1 suppliers first | | Synthetic sample data loads end to end | NOT VERIFIED as Gaboro org |
| Convex | Phase 2+ | Not needed until real-time sync requirements emerge | | 25 CSV variants pass ingestion tests | NOT DONE |
| Import flow: mapping, validation, warnings | PARTIAL — CSVImport exists, full mapping review unconfirmed |
| Report generation calculates from backend | PASS |
| Each status has reason + recommended action | PARTIAL — payer bug fixed; visit date still uses shipment proxy |
| Export CSV works and opens cleanly | NOT VERIFIED end to end |
| Placeholder content removed | NOT VERIFIED |
| Browser smoke test passes | NOT RUN |
| Data handling rules documented | PASS |
| Real PHI blocked | PASS |
| Pilot success metrics written down | PASS |
Update this table every build session. Re-count PASS items before quoting a % to anyone.
## What Is Tabled — Do Not Build Yet
| Item | Phase | Reason |
|---|---|---|
| AWS infrastructure | Post-pilot | Railway is sufficient until live PHI contracts signed |
| Dexcom OAuth API | Phase 2 | Requires vendor agreement + PHI scope expansion |
| Billing system API (Brightree, etc.) | Phase 2 | Build after pilot reveals which systems suppliers use |
| CMS / Salesforce integration | Phase 2 | Pilot feedback needed first |
| Prescriber fax automation | Phase 2 | Manual outreach sufficient for pilot |
| Patient-facing SMS | Phase 3 | PHI transmission requires BAA + consent layer |
| Doc upload + AI validation | Phase 2 | Explicitly deferred |
| Consortium strategy | 18-24 months | Need 15+ paying Level 1 suppliers first |
## Instructions for Claude Code Sessions ## Instructions for Claude Code Sessions
- Work only on Level 1 scope - Work only on pilot-scope items from the checklist above
- Never suggest adding PHI fields beyond patient_id - Never suggest adding PHI fields beyond patient_id
- Flag any vendor integration that would require a new BAA - Flag any vendor integration that would require a new BAA
- When building calculations, reference payer_rules.json for wear days - When building calculations, reference payer_rules.json for wear days
- When building audit logs, always hash patient_id before storing - When building audit logs, always hash patient_id before storing
- If asked about Phase 2/3, acknowledge and defer — do not spec or build - Use "resupply" not "refill" — CGM supply allowances are exempt from Medicare refill rules
- Use "resupply" not "refill". CGM supply allowances are exempt from Medicare refill rules - Always calculate progress against the whitepaper checklist table above — not subjective feel
- Before quoting any % complete to Kisa, count the PASS items in the checklist

File diff suppressed because one or more lines are too long

View file

@ -97,9 +97,43 @@ def _get_wear_days(rules: dict, device_type: str, component: str) -> int:
return wear_days return wear_days
_COMMERCIAL_KEYWORDS = {
"aetna", "united", "unitedhealthcare", "cigna", "humana",
"bcbs", "blue cross", "blue shield", "anthem", "molina",
"centene", "wellcare", "oscar", "ambetter", "carefirst",
"highmark", "geisinger", "kaiser", "commercial",
}
def _normalize_payer(payer: str) -> str:
"""
Map raw DME CSV payer strings to canonical payer_rules.json keys.
"Medicare Part B" "medicare"
"Medicaid - GA" "medicaid"
"Aetna PPO" "commercial"
Preserves original value in CoverageResult.payer for display.
"""
s = payer.strip().lower()
if "medicare" in s:
return "medicare"
if "tricare for life" in s or s == "tfl":
return "medicare"
if "medicaid" in s:
return "medicaid"
if "tricare" in s:
return "commercial"
for keyword in _COMMERCIAL_KEYWORDS:
if keyword in s:
return "commercial"
return s
def _get_payer_config(rules: dict, payer: str) -> dict: def _get_payer_config(rules: dict, payer: str) -> dict:
payer_rules = rules.get("payer_rules", {}) payer_rules = rules.get("payer_rules", {})
return payer_rules.get(payer.lower(), payer_rules.get("default", {})) normalized = _normalize_payer(payer)
return payer_rules.get(normalized, payer_rules.get("default", {}))
def _compute_priority(flag: CoverageFlag, days_until_end: int) -> int: def _compute_priority(flag: CoverageFlag, days_until_end: int) -> int:

View file

@ -1,2 +1,2 @@
allowBuilds: allowBuilds:
'@clerk/shared': set this to true or false '@clerk/shared': true

3
signal-ui/vercel.json Normal file
View file

@ -0,0 +1,3 @@
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}