Commit graph

21 commits

Author SHA1 Message Date
sososttil
65d0e13008 fix(auth): stop redirecting sign-in to the dead Vercel origin
signal-ui/src/main.jsx hardcoded WEBAPP_URL to https://signal-ui-xi.vercel.app
and passed it to signInUrl/signUpUrl/afterSignInUrl/afterSignUpUrl. The
production Clerk instance (clerk.sttilsolutions.com) rejects that origin with
400 origin_invalid on every write path, so sign-in was handed back to an origin
that cannot authenticate. Verified live: POST /v1/client/sign_ins returns 400
from the Vercel origin and 200/422 from signal.sttilsolutions.com.

Redirect target now derives from window.location.origin, overridable via
VITE_APP_URL, so it cannot drift from the deployed domain again. Also replaced
afterSignInUrl/afterSignUpUrl with signInFallbackRedirectUrl/
signUpFallbackRedirectUrl, deprecated in Clerk Core 2.

Build verified: pnpm build succeeds, dead Vercel URL absent from dist output.
NOT verified: a real sign-in completing end to end. Needs deploy first.

Also updates the pilot readiness table: hosted-URL row now names
signal.sttilsolutions.com (confirmed canonical by Kisa 2026-07-27), login row
moved from PASS to OPEN. Honest count 11/13 clean, 1 open, 1 disputed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aqzsyo1PudjabuV9XQzxwp
2026-07-27 19:41:49 -04:00
Kisa
6181de74ed feat: patient-nested worklist — the true-green display (plan 02, P6)
The worklist now shows one row per patient carrying the rollup verdict,
expanding into device coverage lines with doc checklists and rule citations.
Green is earned only from the readiness verdict. Kisa-approved design
(mockup v2, decisions A/B/C/D/E locked 2026-07-07): purple Plan Type Needed
badge + Map-the-plan-type CTA; ◇ column-not-mapped chips; not-processed
strip with download; Data-gaps filter (honest labels, no sixth status);
extended legend; per-line work-queue export (backend lines[] support,
audit-logged). Tabs count patients. SWO/PA cycling is device-scoped and
returns the re-rolled patient through the P4 echo contract; Confirm Visit
fans out across the patient's echoed lines. Legacy table remains at
?legacy=1 (its DOCS_REQUIRED stopgap intentionally kept while it exists —
literal deviation from the plan's remove-in-same-change line, logged).
Independent audit: SHIP; its MEDIUM (line-identity merge collision) and two
LOWs fixed in-commit. 171 backend tests green; frontend builds clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 06:37:04 -04:00
Kisa
f28b5bf39e feat: plan-type enforcement in the live path (plan 02, P5)
Full client-mapped plan_type pipeline: complete header alias set (bare
'plan'/'plan_name' stay payer aliases), value canonicalization map (Medicare
Part B / FFS / MA / Part C / private / employer etc), unrecognized values
grade Plan Type Needed with a hashed once-per-value warning. Once-per-batch
deprecation fence when records lack plan_type (timing guesses from payer,
legacy; readiness never does). CSVImport mapping review gains Plan Type.
All 66 demo/drift fixture CSVs authored with plan_type columns (variant
headers + variant values on the drift corpus); corpus sweep: 66/66 map, 100%
typed. Echo paths canonicalize through the same value map (audit Low fixed).
_normalize_payer and the default config entry remain untouched (Phase 2c,
Kisa-gated). Independent audit: SHIP. 169 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 05:46:03 -04:00
Kisa
a53728e424 feat: device-keyed staff overrides + recompute contract (plan 02, P4)
Ends the override leak: an SWO/PA save now applies to one device's line, not
every device the patient has. doc_status gains device_type ('' = legacy
patient-scoped row, applies until re-saved); the old unique key is dropped by
introspected name and replaced with the 4-col scope key. Staff overrides now
FEED THE VERDICT (device-scoped, staff wins over the CSV cell) instead of
display-only; visit overrides keep their patient-scoped fan-out via
confirmed_visits. PUT /api/doc-status and /api/confirm-visit accept an
optional echo of the patient's lines and return {lines, rollup_status}
recomputed through the same engine (stateless, no batch rebuild). Frontend
minimal fix: doc-status state and writes keyed patient:device. Independent
audit: SHIP (migration reproduced empirically on both old-key shapes; guard
scoped per its nit). 162 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 05:36:26 -04:00
Kisa
25f65326d4 security: rotate leaked Signal API key, remove it from frontend + source
The backend master SIGNAL_API_KEY had leaked via two paths:
- baked into the public Vite bundle via VITE_SIGNAL_API_KEY (Vercel)
- hardcoded as a fallback in scripts/signal_e2e_test.py

The key has been rotated on Railway (old value now returns 401) and the
VITE_SIGNAL_API_KEY var removed from Vercel. This commit removes the two
code paths so the master key can never be re-baked or re-committed:

- signal-ui/src/lib/api.js: drop the X-API-Key fallback entirely; the
  frontend now authenticates only with the signed-in user's Clerk token
- scripts/signal_e2e_test.py: read SIGNAL_API_KEY from env only; exit if unset

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 14:00:54 -04:00
Kisa
42a79c6682 add pitch assets, fix UI and backend bugs, add test utilities
- add 3 signal pitch assets (workflow flowchart, market opportunity, win-win-win) as HTML + PNG
- fix doc_state_machine cascade and supplied sentinel flags
- fix CSVImport mapping review, WorklistTable colored bullets and expand row
- fix App.jsx auth gate, api.js CORS handling
- add signal E2E test script and stress test generator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 12:52:29 -04:00
Kisa
ca65185ba2 feat(signal-ui): Clerk redirect fix, stoplight colors, Clear to Ship checkmark, tab counts
- ClerkProvider now sets signInUrl/afterSignInUrl to signal-ui-xi.vercel.app so
  invitation emails and sign-in links land on the webapp not Clerk's hosted page
- Stoplight colors on status badges (red/amber/teal/green)
- Clear to Ship shows checkmark instead of dot
- Filter tabs include count + percentage
- EmptyState V2: "Drop your file here" heading
- Legend bar removed from worklist header (redundant with tabs)
- Pilot readiness at 13/13 (100%) as of 2026-06-16
- Signal Intelligence spec added to docs

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-16 15:01:39 -04:00
Kisa
320b365fde add graphify-out to gitignore, fix badge for resupply_ready cascade state
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-14 12:25:52 -04:00
Kisa
1d95bb2ab2 feat: doc status persistence, empty state, status legend, and Clear to Ship guard
- Doc status click-to-update: SWO and PA cycle through states and persist to Supabase
- Status legend added to worklist header
- Empty state with file-open prompt for first-time users
- Device normalizer expanded for broader CGM variant coverage
- Warm cream text applied globally for secondary/muted UI elements
- Drag-drop CSV import support
- CORS root cause fixed via Railway ALLOWED_ORIGINS env var
- DOCS_REQUIRED badge: RESUPPLY_READY patients with open cascade items now show
  amber Docs Required instead of green Clear to Ship, preventing premature shipment

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-14 05:09:06 -04:00
Kisa
cc2a5f4b47 coverage calculator and UI refinements; add demo MVP gap analysis and quality review docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:04:23 -04:00
Kisa
63093990d2 Add empty state, mapping review, confirmation step, copy rewrites, active patient indicator
- Empty state UI: first-time prompt with file selector
- Mapping review step in CSVImport with confidence scores and override dropdowns
- Confirmation step in ConfirmVisitModal (one last look before save)
- Next-priority toast after visit confirmation
- Active patient banner with autosave and one-click return for interruptions
- Simplified cascade to 2-step (what is missing, device shipment at risk)
- Copy rewrites: status labels, doc checklist text, action messages, cascade language
- Pilot readiness updated to 85% (11/13)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 17:13:16 -04:00
Kisa
d197c529ce fix: demo readiness — filter flags, auth, active display, sidebar org, visit validation
- coverage.js: correct 7-tier flag names matching backend (was OUT_OF_COVERAGE etc.)
- Sidebar: dynamic org name from Clerk useOrganization (was hardcoded "Demo Supplier")
- App.jsx: fix undefined escalateCount/outreachCount crash
- Privacy.jsx: replace personal email with privacy@sttilsolutions.com
- api.js + ConfirmVisitModal: Confirm Visit uses Clerk Bearer token (was 401 on Vercel)
- WorklistTable: ACTIVE rows show next visit due date
- main.py: server-side 6-month qualifying visit validation
- CLAUDE.md: pilot readiness checklist updated to 65%
- pitch/legal/gaboro-nda.md: STTIL city + Robert Robinson email filled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:27:17 -04:00
Kisa
e8b15233ec feat: stoplight label system — At Risk / Action Needed / Clear to Ship / On Track
RED At Risk: SUPPLY_LAPSED, VISIT_REQUIRED, RENEWAL_CRITICAL
AMBER Action Needed: RENEWAL_ELEVATED, RENEWAL_SOON, TRANSFER_PENDING
GREEN: Clear to Ship (RESUPPLY_READY), On Track (ACTIVE)
Filter tabs updated to match 3-tier model.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 22:04:03 -04:00
Kisa
77a1cdb2c0 fix: update UI to 7-state display framework
- WorklistTable: consolidate 9 filter tabs to 8 matching 7-state labels
  (Docs Required, Escalate, Confirm Appt., Begin Outreach, Clear to Ship,
  New Patient, On Track) + add combined "escalate" filter key for
  RENEWAL_CRITICAL + VISIT_REQUIRED
- Sidebar: fix broken filter keys (REFILL_WINDOW/VISIT_DUE/OUT_OF_COVERAGE
  never matched any r.flag value) - replace with SUPPLY_LAPSED, escalate,
  RESUPPLY_READY; update labels to 7-state names
- App: rename Sidebar props to match new framework; update stat cards to
  Needs Attention / Outreach in Progress / Clear to Ship

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:27:25 -04:00
Kisa
76386bf175 feat: 7-state worklist framework — DMEPOS billing language
Labels: On Track, Clear to Ship, Begin Outreach, Confirm Appointment,
Escalate, Docs Required, New Patient

- SUPPLY_LAPSED → Docs Required
- VISIT_REQUIRED + RENEWAL_CRITICAL → Escalate
- RENEWAL_ELEVATED → Confirm Appointment
- RENEWAL_SOON → Begin Outreach
- RESUPPLY_READY → Clear to Ship (teal, checkmark, positive)
- ACTIVE → On Track
- TRANSFER_PENDING → New Patient (covers transfers + new CGM starts)
- Action text updated to DMEPOS billing staff language throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 16:07:26 -04:00
Kisa
bcb1a10fe6 feat: demo MVP — 90/60/45 priority tiers, doc state machine, confirm visit workflow
- New CoverageFlag enum: SUPPLY_LAPSED, VISIT_REQUIRED, TRANSFER_PENDING,
  RENEWAL_CRITICAL/ELEVATED/SOON, RESUPPLY_READY, ACTIVE
- Doc state machine: 5-item payer-dependent status per patient (SWO, Visit,
  PECOS, PA, Diagnosis) with cascade chain
- Confirm Visit endpoint: staff enters prescriber-confirmed date, persisted in
  Supabase confirmed_visits table, survives all future CSV imports
- Supabase migration: 001_add_confirmed_visits.sql (run manually in SQL editor)
- Frontend: Badge rebuilt for 8 flags, DocStatusBar 5-dot display,
  ConfirmVisitModal, expandable WorklistTable rows
- Legal: LOI, NDA, BAA drafts at pitch/legal/ for Nixon Law Group review
- Compliance docs: privacy policy, incident response, data handling
- CSV generator: market_data.json + PA/NJ generator scripts
- 15/15 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 11:29:33 -04:00
Kisa
d4e5187350 Add OrganizationSwitcher to header
Lets users switch between orgs (e.g. STTIL Solutions, Gaboro DME)
directly from the top bar without going into account settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 13:15:37 -04:00
Kisa
ec2cd24bd7 Add Phase 3: Clerk auth with org-scoped data isolation
Backend: JWT middleware validates Clerk tokens on every request,
extracts org ID from claims, enforces org-scoped queries via
Supabase RLS. Frontend: ClerkProvider wraps the app, auth gate
blocks unauthenticated access, UserButton in header, token
injected into every API call. Supabase production wired to trust
Clerk JWTs via Third-Party Auth integration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 12:12:17 -04:00
Kisa
4a0e043a6d add phase 2 supabase persistence layer
- supabase_client.py: lazy singleton client (no-ops when env vars absent)
- persistence.py: persist_upload writes batch, source_files, normalized_records,
  mapping_decisions, report_runs; persist_export records export_files
- schema.sql: 11-table schema with RLS + WORM rules for audit/raw tables
- main.py: wire persist_upload/persist_export; add ExportRequest body model
  so export accepts {records, batch_id}; batch_id returned on upload response
- api.js: add exportFromBackend helper passing batch_id through
- requirements.txt: add supabase>=2.0.0
- smoke_test.py: update export call to new body format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 06:50:34 -04:00
Kisa
cf171a3f87 add Phase 1 security hardening, mapping confidence, audit logging, pilot docs
- lock CORS to Vercel domain via ALLOWED_ORIGINS env var (removes allow_origins=*)
- add X-API-Key header auth on /api/upload and /api/export
- normalizer: add mapping confidence (high/inferred), new aliases for Acct #,
  Member ID, External Patient Ref, DME Description, dispensedate; 63/63 CSV files pass
- coverage_calculator: add RULE_VERSION = "v0.1", rule_version on every CoverageResult
- main.py: audit logging wired on upload + export, rule_version + mapping_summary in response
- generate_samples.py: 25 CSV files now use 25 different real-world header formats
- add generate_10k.py for 10,000-patient synthetic dataset
- add tests/smoke_test.py (passes against local backend)
- add docs/pilot-guide-v1.md for Robert Robinson pilot onboarding
- add docs/daniel-pilot-readiness-whitepaper.md and .pdf

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 05:41:25 -04:00
Kisa
a424ac9d13 feat: add reason strings per patient, fix export headers, add signal-ui source
- Add _build_reason() to backend — per-patient reason strings with specific
  day counts (e.g. "Supply lapsed 70 days ago. Prescriber contact required.")
- Add reason field to RecordOut model and backend /api/export CSV
- Fix export column headers: Coverage End Date → Resupply End Date,
  Days Until Coverage End → Days Until Resupply End
- Pass reason through apiRecordToLocal in frontend api.js
- Display reason as muted sub-line under status badge in WorklistTable
- Add reason column to client-side CSVExport
- Add signal-ui React source to repo (was untracked)
- CLAUDE.md: add Billing and CMS integrations to Phase 2 deferred table
- research: restore Section 14 stat verification (May 23 recovery)

Deployed to Railway production — health check confirmed live.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 09:45:02 -04:00