Skip to content
AskFlorence
Main Navigation ArchitectureFlorence AIAgentsMembersAgent PlatformValidationInfrastructure

Appearance

Sidebar Navigation

Overview

Home

Glossary

System Architecture

Consumer & Agent Flow

Florence AI

Overview

Principles

Runtime

Tool surface

Adding a tool

Tool registry

Knowledge: SBC scenarios & CSR

Voice

Evals & observability

Provider risk & portability

Outage playbook

Roadmap

Build plan

Agents

Overview

Workflows & pain points

Members

Overview

Medicaid coverage gap

Carriers

Overview

Marketplaces

Overview

Agency

Overview

Regulations

Overview

Agent Platform

Overview

Auth Architecture

MongoDB Permissioning

Compliance Model

Data Models

Data Sources

Overview

CMS Marketplace API

CMS dependency map

PUF Data

State Subsidies

SBE Ingestion Playbook

SBE State Watchouts + Decisions

CA Phase C/D Playbook

NY Phase C/D Playbook

Validation

Overview

Methodology

APTC Formula

California 2026

New York 2026

CAPS Formula

Scenario Results

Infrastructure

Account Inventory

AWS Setup Runbook

AWS Organizations

CloudTrail

GuardDuty

Security Hub

Config

CloudFront + WAFv2

Data sources & ingest

Phase 4 DNS

Change Log

Vulnerability Management

MongoDB Setup

Access Control

Data Classification

Documentation Hosting

Post-deploy Smoke

Development

Preflight (local CI mirror)

Testing strategy

Compliance

Overview (auditor entry point)

SOC 2 Control Mapping

HIPAA Control Mapping

CMS EDE Appendix A Mapping

Risk Assessment

Encryption Policy

Data Retention Policy

Privacy Impact Assessment

Consent Capture & Versioning

Incident Response Plan

Access Control Policy

Marketing vs. Portal Analytics

Vendor / Subprocessor Register

Dependency Vulnerability Policy

BAA / Compliance Evidence

Compliance-Automation Integration

Compliance-Automation Vendor Evaluation

Penetration Test Reports

Architecture

Portal entry handoff

Mobile app strategy

Deferred architecture decisions

Session cookie architecture

Share flows

Decisions (ADRs)

Index

0001 — Atlas project isolation

0002 — Append-only audit log

0003 — Narrow-scoped Mongo users

0004 — Cross-cluster Atlas PrivateLink

0005 — Delayed-job architecture

0006 — Mongo user simplification

0007 — Terraform owns ECS task def

0008 — E2E testing strategy

0009 — Self-hosted analytics + observability (superseded)

0010 — PostHog HIPAA Cloud (supersedes 0009)

Runbooks

Security Incident Response

Break-Glass Root Login

Onboard Team Member

Offboard Team Member

Atlas user provisioning

Deploy via Terraform (ENG-277)

Rollback via Terraform (ENG-277)

S3 data bucket migration (planned Phase 11)

Access Reviews

2026-Q2 Review

Session log

Index

2026-04-23 — Phase 10 DNS cutover

2026-04-22 — Phase 8 prod AWS mirror

2026-04-22 — Phase 7 Atlas VPC peering

2026-04-22 — Phase 6 CloudFront + WAF

2026-04-21 — Phase 5 staging go-live

2026-04-17 — Atlas staging

Briefs

Index

Member portal plan (ENG-187)

2026-04-16/17 handoff

2026-04-17 Atlas handoff

System briefing (2026-04-17)

Creative AdBundance proposal brief

Creative AdBundance analytics brief

ElevenLabs RN integration research

Policies

Overview

On this page

2026-05-08 (continuation) — Phase D provider parity + facility autocomplete fix + CI guard Phase 1 ​

This entry continues the Phase 11 session from earlier the same UTC date (2026-05-08-phase-11-cross-cluster-privatelink). Phase 11 wired the cross-cluster Atlas PrivateLink path from prod → staging. This entry covers everything shipped on top of that read path the same day.

Scope ​

Three coherent ships:

  1. Phase D — provider-network-tier fallback. Mirror of the drug-tier fallback shipped earlier today (Eliquis verified). For providers: when CMS returns coverage=Covered without network_tier, fill the tier from providers_staging via the cross-cluster path.
  2. Facility/pharmacy autocomplete fix. User reported searching "Walmart" returned no results. Backend supports all 3 CMS provider types (Individual / Facility / Group), but the UI hook hardcoded type: "Individual" — every facility-class result silently filtered out for every user.
  3. CI guard Phase 1 — static check. Build-time enforcement that the staging cluster's data-classification posture (per ADR 0004) doesn't drift. Any PR adding a getReferenceDb() call against a non-allow-listed collection is rejected at CI before merge.

Actor ​

taha.abbasi@abbasiindustries.com driving from ~/Developer/ask-florence-doctor-rx/; agent: Claude Opus 4.7 (1M context).

Tickets / ADRs ​

  • Created: #106 / ENG-245 (pharmacy network lookup), #107 (drug coverage checker product idea, extracted from #17), #108 (clear-all button)
  • Closed: GH #17, #18, #20; Linear ENG-234, ENG-240, ENG-163
  • In Progress (Phase 1 done; Phase 2 carved out): #100 / ENG-239 CI guard
  • Built on: ADR 0004 (cross-cluster PrivateLink), Phase 11 session log

External systems touched ​

SystemAccount / ProjectDelta
AWS prod (039624954211)prod ECS cluster askflorence-prodDeploy run 25590973086 registered task def revision 54 + rolled service. Container image baked from merge commit including all three commits below. 2/2 tasks running, rolloutState=COMPLETED.
GitHub Actionsn/aFiled 3 new issues; closed 3 GH issues with closeout comments; CI Workflow Staging Collections Guard (static) ran first time at run 25591499570 on push of CI guard, success in 42s.
LinearEngineering teamClosed ENG-163 (SelectHealth POC), ENG-234 (Phase D); ENG-239 moved to In Progress with progress comment + due 2026-05-15; ENG-245 (NEW pharmacy network) due 2026-05-15 in Data ingestion project, cycle 1; bumped 7 stale due dates to 2026-05-11 (ENG-227, ENG-228, ENG-230, ENG-231, ENG-232, ENG-233, ENG-236).
Atlasn/aNo changes (everything reads through the Phase 11 path).

What shipped ​

Phase D — provider-network-tier fallback (commit 1465c6d) ​

  • src/lib/provider-network-fallback.ts (NEW) — exact mirror of drug-tier-fallback.ts. Function lookupStagingProviderNetworks(npiPlanPairs) returning Map<string, ProviderNetworkFallback> keyed by ${npi}|${plan_id}. One indexed query per NPI; reads providers_staging via getReferenceDb(). Internal canonical-tier strings mapped to CMS-style strings (Preferred, NonPreferred, Standard, etc.) via small mapping table.
  • src/app/api/providers/covered/route.ts — enrichment loop wired after CMS call. Filters CMS Covered / PartialCovered entries lacking network_tier; calls fallback; merges. CMS coverage stays authoritative; staging fills only the tier-metadata gap.

Facility/pharmacy autocomplete fix (same commit 1465c6d) ​

  • src/app/api/providers/autocomplete/route.ts — server-side fan-out: when caller passes type omitted or "All", executes 3 parallel providersAutocomplete() calls (Individual + Facility + Group), dedupes by NPI, returns merged. Backwards-compatible: a specific type returns the prior single-type behavior.
  • src/lib/hooks/use-doctor-autocomplete.ts — ProviderType union extended to include "Group" + "All"; default changed "Individual" → "All".
  • src/components/plans/CoveragePanel.tsx + src/components/plans/detail/PlanCoverageCheck.tsx — pass type: "All" with explanatory comment.

CI guard Phase 1 — static check (commit 67cb315) ​

  • src/lib/db.ts — new STAGING_ALLOWED_COLLECTIONS constant (10 collections: formularies_staging, providers_staging, zip_county, plans, regions, plan_years, mrpuf_issuers_staging, mrf_ingest_log_staging, coverage_disagreements_staging, mrf_file_state_staging) + StagingAllowedCollection type.
  • scripts/audit/staging-collections-guard.ts (NEW) — zero-dep regex-based static guard. Walks src/ + scripts/ (skipping node_modules, .next, .git, etc.), finds every await getReferenceDb() binding via regex, scans downstream <binding>.collection("…") calls + the inline (await getReferenceDb()).collection("…") form. Cross-checks each collection name against allow-list. Three violation classes: not_on_allow_list (string literal not in set), dynamic_name (variable argument — flagged because static analysis can't verify runtime safety), and inline-call equivalents.
  • Defensive choices: self-skip (the script literally documents its own regex patterns and would self-flag), comment-stripping (line + block comments stripped before regex scan so doc-strings don't trigger), allow-list duplicated in the script (defense-in-depth — prevents a developer from making the script "self-approve" by importing the source-of-truth list from db.ts).
  • .github/workflows/staging-collections-guard.yml (NEW) — runs on PRs to main / staging / doctor-rx-flow + on push to main + on demand. Sets up Node 20, installs tsx, runs the guard. On failure surfaces ::error:: annotations with pointer to ADR 0004.

Diagnostic + new issues filed ​

  • scripts/diag/check-walgreens-coverage.js (NEW, commit 40a4a3a) — Mongo aggregation script that surfaced the pharmacy-network finding. 20 of 22 retail pharmacy NPIs (Walgreens, CVS, Walmart, Smith's, Harmons) ARE in providers_staging with thousands of plan edges representing medical services they provide. NONE link to SelectHealth plan 68781UT0200014. Confirmed by reading SelectHealth's published §1311 index.json directly: provider file lists medical providers only; pharmacy network lives at separate RxEOB SPA tool (selecthealth.rxeob.com).
  • New GH issues: #106 pharmacy network lookup (Part A UX clarity + Part B data ingest), #107 drug coverage checker product idea (extracted from closed #17 to preserve flagship-product framing), #108 clear-all button for saved doctors + medications.

Verification ​

Phase D — end-to-end on prod ​

POST askflorence.health/api/providers/covered with Walgreens NPI 1023023066:

plan 42261UT0060023 → coverage=Covered, network_tier="Preferred"
plan 42261UT0060026 → coverage=Covered, network_tier="Preferred"

The network_tier="Preferred" field is only populated by lookupStagingProviderNetworks() reading from providers_staging via the cross-cluster path. CMS returned Covered without tier; staging filled it.

Autocomplete fan-out — end-to-end on prod ​

POST askflorence.health/api/providers/autocomplete:

  • {"q":"Walmart","zipcode":"84094"} (no type) → 13 results merging Facility (WALMART INC. NPIs) + Group (SLC WALMART EYE DOCS)
  • {"q":"Walgreens","zipcode":"84094"} → 21 results merging Individual (SARAH WALGREEN — actual person named Walgreen) + Facility (WALGREENS #XXXXX)

Pre-fix returned only Individual results, so Walmart returned [].

CI guard static check ​

  • Workflow run 25591499570 on first push to main — success in 42s on real code.
  • Synthetic positive test: dropped temporary file scripts/db/_test_violation.ts with 3 known-bad patterns:
    scripts/db/_test_violation.ts:7   collection: agent_audit_log    reason: not_on_allow_list    (string literal)
    scripts/db/_test_violation.ts:14  collection: name               reason: dynamic_name         (variable arg)
    scripts/db/_test_violation.ts:20  collection: members            reason: not_on_allow_list    (inline call)
    All 3 caught with correct diagnosis. Exit code 1 as expected.
  • Cleanup: removed synthetic file → guard returned to ✅ PASS, exit 0.

Deviations from plan ​

  • The user originally said the Walmart issue "could be a separate issue" but I addressed it inline in the Phase D commit since both touch the providers UX and were tightly coupled. Rationalized in the commit message.
  • Pharmacy-network finding emerged DURING Phase D verification — wasn't in the original Phase D scope. Filed as separate issue (#106) so it doesn't block the Phase D close-out.
  • CI guard Phase 2 (live nightly drift check) carved out as sub-task because the design has an open question: should the live check verify role-based permissions (Atlas API call on app_read_staging) or do collection enumeration (which would false-positive on legitimate staging-app collections that aren't cross-cluster-readable)? Phase 1 alone already protects the in-code contract.

Compliance posture impact ​

FrameworkControlUpdate
SOC 2CC7.2 (new additional row)Detection of unauthorized cross-cluster data-flow scope drift
SOC 2CC8.1 (new row)Change-management invariant guard for non-prod-isolation
SOC 2CC8.1 (this session)Phase D + Walmart fix + CI guard all landed via standard PR/commit/CI/Deploy chain — full evidence trail
HIPAA§164.312(e)(1)Unchanged — cross-cluster TLS + AWS-backbone path
EDE Phase 3Environment separationReinforced — CI guard algorithmically enforces what was previously hand-discipline

What was NOT done (deferred) ​

  • CI guard Phase 2 (live nightly drift check) — sub-task on #100 / ENG-239. Will likely be a separate session; opens the role-permissions-vs-collection-enumeration design question.
  • Pharmacy network UX clarity (Part A of #106) — separate issue, due 2026-05-15.
  • Pharmacy network data ingest (Part B of #106) — multi-week effort, no due date yet.
  • Architecture refresh (#102) — P2, separate session.
  • Re-validate §1311 audit at 100% (#92 / ENG-230) — cycle 1, due 2026-05-11.

Rollback ​

bash
# Code rollback (per commit):
git revert 67cb315   # CI guard Phase 1
git revert 1465c6d   # Phase D fallback + autocomplete fan-out
git revert 40a4a3a   # Diagnostic script
git push origin main

# Phase D rollback effect:
# - lookupStagingProviderNetworks() unwired from /api/providers/covered
# - CMS coverage stays authoritative; network_tier field becomes empty for
#   issuers that don't supply it directly. Drug-tier-fallback unaffected.

# Autocomplete rollback effect:
# - useDoctorAutocomplete() reverts to type: "Individual" default
# - Facility-class providers (pharmacies) silently filtered out again
# - Walmart search returns []

# CI guard rollback effect:
# - Static check no longer runs on PRs
# - Cross-cluster scope drift relies on hand-discipline + ADR review
# - Workflow file CAN be left in place but disabled (comment out the npx step)
#   to preserve the SOC 2 CC8.1 evidence trail
Pager
Next pageHome

AskFlorence Internal Documentation. Not for public distribution.

AskFlorence

Internal Documentation

Access restricted. Not for public distribution.