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

Marketing vs. Portal Analytics — Auth-Wall Isolation Control ​

Audience: SOC 2 / HIPAA / EDE Phase 3 auditors, AskFlorence engineering + compliance, performance-marketing partners (Creative AdBundance and any future agency).

Scope: The operational control that lets us run third-party performance-marketing tools (ad pixels, heatmaps, A/B testing, audience builders, email/CRM) on pre-enrollment surfaces without putting PHI or post-enrollment member data in the same blast radius as those tools.

Last updated: 2026-05-11


1. The control ​

AskFlorence operates two distinct surfaces with a hard architectural boundary between them:

SurfaceDomainData classThird-party scripts
Apex marketingaskflorence.health and www.askflorence.healthPublic + PII at most (email, ZIP, age, income range, NPN, name)Permitted after a one-shot per-tool compliance review
Member portalapp.askflorence.health (Phase 5 portal subdomain, working name)PHI in scope (SSN, DOB, income docs, enrollment records, agent-assisted interactions)Architecturally forbidden via CSP; enforced at the browser layer, not by runtime checks

The boundary is the subdomain split. Cookies set on askflorence.health are scoped Domain=askflorence.health (apex only, NOT .askflorence.health), so the browser drops them when the user crosses into app.askflorence.health. Pixels physically cannot follow a user across the cut. This is what we mean by "enforced by physics, not by policy" — there is no runtime check to forget, no per-route allowlist to maintain, no WAF rule that can be misconfigured. The browser does it.

The control extends the production / staging isolation logic that EDE Phase 3 §3 requires from "environment separation" to "PHI vs. non-PHI surface separation," using the same Atlas project + AWS account + DNS / CDN topology that already underpins prod / staging isolation.

Why this control exists ​

Performance marketing for an ACA marketplace platform requires conversion pixels, retargeting, audience-build tooling, and creative testing. Those tools assume a relatively permissive operating environment that is incompatible with HIPAA-grade and EDE Phase 3-grade controls on PHI surfaces. Forcing a single domain to host both would require per-route allowlists and CSP exceptions that drift and break silently. Splitting at the subdomain level makes the boundary impossible to forget.

Framework mappings ​

  • HIPAA Security Rule §164.308(a)(4) — Information Access Management. The control implements least-functional-access for third-party processors by scoping their reachable cookie + execution surface to the non-PHI subdomain.
  • HIPAA Security Rule §164.312(a)(1) — Access Control technical safeguard. The portal subdomain enforces authentication before any PHI-bearing page renders, and CSP enforces no third-party script execution on that subdomain.
  • CMS EDE Appendix A §3 — Environment separation. The control is the documented extension of the prod / staging isolation logic from environments to surfaces.
  • SOC 2 CC6.1 — Logical access. The subdomain CSP allowlist is the operational artifact mapping to logical access scoping for third-party processors.
  • SOC 2 CC6.6 / CC6.7 — Restriction of access to systems and information. The control restricts third-party processor access to apex-only.

2. Cookie + CSP scoping rules ​

Apex (askflorence.health) ​

  • All first-party cookies set by our application must be scoped Domain=askflorence.health (not .askflorence.health). The wildcard form would propagate to app.askflorence.health.
  • Third-party cookies (ad-tech, heatmap, A/B test) inherit the third party's defaults. Most ad-tech vendors set apex-scoped cookies by default. Reviewer confirms at intake.
  • CSP is permissive within an explicit allowlist of approved third-party domains, populated from the tool registry below.

Portal (app.askflorence.health) ​

  • Content-Security-Policy: script-src 'self'; img-src 'self' data:; connect-src 'self' <first-party-analytics-host>; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self' as the floor. <first-party-analytics-host> = our self-hosted OpenPanel + GlitchTip (ADR 0009). No third-party origins permitted in script-src, connect-src (except the first-party self-hosted analytics), frame-src, or form-action.
  • CSP report-uri enabled in production; any blocked-script violation generates a report to our backend. Reports are reviewed in the quarterly access review (see docs/infrastructure/access-reviews/).
  • The portal serves no inline scripts; 'unsafe-inline' is not in the policy.
  • No analytics SDKs, no heatmap SDKs, no error-tracking SDKs with un-BAA'd vendors. The first-party self-hosted stack (OpenPanel + GlitchTip) is the only analytics/error surface.

Compatibility with the cross-surface attribution pattern ​

Click IDs (fbclid, gclid, li_fat_id, ttclid) and UTM params captured on apex are persisted on the waitlist record and read again at enrollment-submit time inside the portal. The portal does NOT load a third-party pixel to read them; instead, our backend reads the click IDs server-side from the enrollment record and fires the conversion server-side to Meta CAPI, Google Enhanced Conversions, LinkedIn CAPI, and TikTok Events API with SHA-256 hashed PII. Hashing happens before bytes leave our infrastructure.

This pattern is the standard documented healthcare-and-finance approach for all four ad platforms and does not require the portal to relax its CSP.


3. Tool-approval SOP ​

Proposal template ​

Each tool a partner wants to wire onto apex is submitted as a single record:

Tool name:              <e.g., Meta Pixel + Conversions API>
Vendor:                 <vendor legal name>
Vendor website:         <link>
Surface scope proposed: apex | portal | both
Data flow summary:      <what events, what fields, where they go>
PII transmitted:        <yes / no, list of fields, hashed?>
Cookie domain scope:    <apex | .apex (wildcard, likely flag for review)>
Loads on portal:        <yes / no — if yes, flag for review; default no>
BAA available:          <yes / no / not applicable>
BAA signed if yes:      <date or N/A>
Proposed by:            <partner name, contact email>
Purpose:                <one-line business reason>

Review checklist (compliance reviewer side) ​

  1. Is the surface scope apex-only? If proposed both or portal, default is denial unless the vendor has a signed BAA and the data flow has no PHI.
  2. Does the cookie scope respect the apex boundary? Wildcard scope (.askflorence.health) is flagged; resolve with vendor to a scoped variant before approval.
  3. Does the data flow include PHI? If yes, deny unless BAA is signed AND surface is portal-only AND the vendor is on the data-classification minimum-vendor list.
  4. Does the tool load on portal? If yes, deny unless first-party self-hosted (OpenPanel + GlitchTip).
  5. For session-replay / heatmap tools: is input recording disabled by default? If recording is enabled, require input-masking configuration that excludes the calculator income field. Document the configuration screenshot or settings export in the registry row.
  6. Is the vendor on the existing vendor register? If not, add a row to the vendor register at the same time as the analytics registry row, with appropriate subprocessor classification.
  7. Is there an Article 28 GDPR DPA available if the vendor receives EU traffic? If we ever market in EU, this becomes mandatory. Today we only market in the US; flag for forward awareness only.

Approval / denial language ​

  • Approved: add a row to the registry below with approval date + reviewer initials. Reply to partner: Approved. Wire as described. Registry row: <link>. Re-review in 12 months unless scope changes.
  • Approved with condition: add the row with the condition explicitly noted (e.g., "Approved with condition: input masking on for input[type='number'] on /"). Reply with the exact condition copy/pasted so the partner can confirm before going live.
  • Denied: reply with the specific reason from the checklist, the change required, and an offer to re-review on resubmission. Do not file a registry row for denied tools; track in the partner's correspondence only.

Turnaround target ​

24-48 hours for a tool submission. We do not batch; each tool is reviewed independently and returned independently. The clock starts when the proposal record is complete (all fields filled).

Re-review cadence ​

  • Annual: every registry row gets a touchpoint review on its anniversary date. Confirm vendor, scope, BAA status, configuration unchanged.
  • On scope change: if a partner wants to expand a tool from PageView-only to Lead+Purchase tracking, or from apex-only to wherever, re-run the full review.
  • On vendor M&A or material policy change: trigger an off-cycle review if the vendor is acquired, changes data residency, or materially changes its data-processing terms.

4. Living tool registry ​

The registry is populated as partners propose tools. It is the source of truth for what is authorized to run on apex.

ToolVendorSurfaceProposed byData flowPII transmittedCookie scopeBAAApproval dateReviewerLast reviewedNotes
(empty)(empty)(empty)(empty)(empty)(empty)(empty)(empty)(empty)(empty)(empty)Registry will populate as Creative AdBundance submits the first tool list. Empty is correct at 2026-05-11.

When the first tools land, replace the empty placeholder row with real entries. Keep entries even after a tool is retired (move to a "Retired" sub-section with retirement date) for the audit trail.


5. Tripwires + detection ​

What the control is designed to prevent, and how we know if any of it slipped:

TripwireHow it happensDetection
Third-party script renders on app.askflorence.healthEngineer pastes an <script> into a layout file; PR review misses itCSP violation report to backend report-uri; periodic audit script grep'ing built portal HTML for non-'self' script origins
Cookie scoped Domain=.askflorence.health (wildcard) by mistakeVendor SDK default differs from documented behavior; engineer adds wrong scopeQuarterly cookie inventory audit; first-party cookie check in browser-test suite
Session-replay tool records calculator income inputVendor default has recording on; intake didn't catch itSpot-check session-replay recordings during quarterly access review; vendor settings export attached to registry row
Tool added to apex without registry reviewPartner wires a tool ahead of review; engineer ships itPR template asks "new third-party script?" with link to registry; CI check fails build if <script src= references a domain not in the allowlist (future enhancement)
PHI accidentally hashed and sent to ad-tech endpointBackend conversion-forwarding code receives a PHI field by mistake; sends it hashed but it shouldn't be sent at allCode review on backend conversion forwarder; allowlist of fields permitted in the hashed-PII payload (email, phone — that's it)

6. Reference patterns in the repo ​

These already exist and are referenced by the control:

  • instrumentation-client.ts + src/lib/posthog-server.ts — hostname-based opt-out pattern; the same pattern will short-circuit any first-party analytics capture on the portal subdomain.
  • src/app/api/waitlist/route.ts (consent sub-document pattern, ~line 460-469 as of 2026-05-11) — the per-record consent capture pattern that extends to enrollment-time consent capture in the portal.
  • src/lib/analytics.ts (server-side event spine) — the tool-portable callsite where the OpenPanel ingest plugs in when ENG-347 lands. (The legacy next.config.ts /ingest/* PostHog reverse-proxy was removed with the PostHog rip — #75 sub-A, PRs #184/#186.)

7. Cross-references ​

TopicWhere it lives
Privacy policy + Terms of Service (consumer-facing)/privacy, /terms (v2026.04, published)
Partner-facing version of this control (Creative AdBundance)docs/briefs/creative-adbundance-analytics-brief.md
EDE Phase 3 control mapping (§3 prod/staging + this control as the surface-level extension)docs/security-compliance/ede-control-mapping.md
Vendor / Subprocessor register (where each approved tool also lands a row)docs/security-compliance/vendor-register.md
Privacy Impact Assessment (current PHI-adjacent flows)docs/security-compliance/privacy-impact-assessment.md
Data classification taxonomydocs/infrastructure/data-classification.md
Member portal compliance design (auth, audit, consent capture inside the portal)docs/agent-platform/compliance.md
ENG-187 — Member portal concept and requirements (where the subdomain + CSP + click-ID propagation + server-side CAPI work is scoped)Linear

8. Open items ​

  • First tool registry entries — will populate when Creative AdBundance returns its proposed Stage 1 tool list (target mid-June 2026).
  • Cookie consent UI — not yet shipped. Inventory of currently-set cookies + a consent banner that gates third-party pixel loading is a prerequisite for any tool that drops third-party cookies on apex. New GitHub issue to be filed once CA tool list confirms the need.
  • Portal subdomain provisioning — app.askflorence.health DNS + ACM cert + ALB/CloudFront routing + CSP report-uri are part of ENG-187 scope, not a standalone task.
  • Click-ID capture + server-side CAPI pipeline — also part of ENG-187 scope. Spawns its own issue only if engineering design says it warrants independent tracking.
  • CI check on script-src allowlist — future enhancement. PR template question is the current control; automated CI grep is the next step.
Pager
Previous pageAccess Control Policy
Next pageVendor / Subprocessor Register

AskFlorence Internal Documentation. Not for public distribution.

AskFlorence

Internal Documentation

Access restricted. Not for public distribution.