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

SOC 2 Controls Mapping ​

Evidence register for SOC 2 Type II Trust Services Criteria. Each row links a TSC criterion to the concrete implementation and the evidence artifact that proves it. Appended to every session that implements a relevant control; never rewritten retroactively.

Scope: CC (Common Criteria). Availability (A), Confidentiality (C), and Privacy (P) rows will be added if customers or the auditor request those categories.

CC6 — Logical and Physical Access Controls ​

CriterionImplementationEvidenceLast updated
CC6.1 — logical access controls restricting unauthorized accessSix narrow-scoped MongoDB users, one per service purpose. Each bound to a custom role with collection-level privileges. Prod app-write still exists and is documented as the exit criterion to remove.ADR 0003, runbook, Atlas custom-role JSON exported on demand.2026-04-17
CC6.3 — access is removed when no longer requiredTemporary admin tmp_restore_admin created for mongorestore, deleted same session. Pattern: every break-glass credential has a teardown step in its runbook.Session log 2026-04-17 "Temporary user created and deleted same session".2026-04-17
CC6.6 — restrictions on logical access from outside boundariesStaging Atlas project is fully isolated from prod project. No shared allowlist, no shared users, no shared roles. Staging allowlist is a single laptop IP; no 0.0.0.0/0.ADR 0001, Atlas access-list export.2026-04-17

| CC6.6 (additional row) — restrictions on logical access from outside boundaries (cross-cluster reference reads) | Prod cluster reads non-PHI public CMS reference data from staging cluster via AWS PrivateLink (vpce-0c81aea11e29bb928 in prod VPC vpc-09201679b87261b6d, targeting Atlas endpoint service com.amazonaws.vpce.us-east-1.vpce-svc-0d8138ea0f6542afa). Traffic stays on AWS backbone — no public internet path, no IP allowlist drift. Identity-bound at AWS account level (PrivateLink) + Atlas Mongo authentication (app_read_staging user, read-only on askflorence database). Service approved by Atlas with connectionStatus=AVAILABLE. | ADR — pivot CMS-API-direct + cross-cluster (section "Cross-cluster reference reads via AWS PrivateLink"); Terraform infra/envs/prod/atlas-staging-privatelink.tf (named af-prod-to-staging-reference-pl); Atlas privateEndpoints describe output. | 2026-05-08 | | CC6.7 — transmission encryption | All MongoDB Atlas connections use TLS 1.2+ (Atlas-enforced floor). PrivateLink traffic is doubly protected: AWS-backbone-only path AT THE NETWORK LAYER + TLS at the application layer. No plaintext channel exists between prod ECS and either Atlas cluster. | Atlas connection-string SRV resolves to TLS-only endpoints; AWS PrivateLink eliminates public-network exposure. | 2026-05-08 |

CC7 — System Operations ​

CriterionImplementationEvidenceLast updated
CC7.2 — the entity detects events indicating a failure of controlsagent_audit_log enforced append-only at the database permission layer. No app-tier credential can mutate the log; tamper attempts produce not allowed to do action [update/remove] errors, which are themselves logged by Atlas.ADR 0002, role JSON for role_writer_agents and role_admin_agents.2026-04-17
CC7.2 (additional row) — detection of unauthorized cross-cluster data-flow scopeStatic CI guard at scripts/audit/staging-collections-guard.ts runs on every PR via .github/workflows/staging-collections-guard.yml. Scans every getReferenceDb() call site in src/ + scripts/ and verifies the accessed collection is on STAGING_ALLOWED_COLLECTIONS (the cross-cluster data-classification allow-list in src/lib/db.ts). Fails the build if a developer (human or AI) introduces a cross-cluster read against a non-public collection. Catches three patterns: string-literal accesses, dynamic-name accesses (where static analysis can't verify the runtime collection name), and the inline (await getReferenceDb()).collection("…") form. Verified 2026-05-08 against synthetic violations of all three patterns — all caught with correct file:line + reason classification. Phase 2 live nightly drift check shipped 2026-05-09 (next row).Workflow first-push run (success, 42s); scripts/audit/staging-collections-guard.ts; src/lib/db.ts STAGING_ALLOWED_COLLECTIONS; ADR 0004; #100 / ENG-239.2026-05-08
CC7.2 (additional row) — detection of runtime privilege drift on cross-cluster readerLive nightly CI check at scripts/audit/staging-cluster-drift.ts runs at 08:00 UTC daily via .github/workflows/staging-cluster-drift.yml (cron + manual dispatch). Audits the actual Atlas state of app_read_staging (the user prod authenticates as when reading formularies_staging + providers_staging over PrivateLink): verifies (1) user has exactly one role, (2) role is role_reader_reference@admin, (3) role grants FIND action only, (4) on exactly askflorence.formularies_staging + askflorence.providers_staging and nothing else, (5) no inheritedRoles. Catches the runtime-drift cases the static guard cannot — someone elevating privileges via Atlas Admin UI by hand, an out-of-band script changing the role, an extra role attached to the user. On failure: opens a P1 GitHub issue (labels compliance + priority-1) with the violation report and rollback snippets. Verified 2026-05-09 against three synthetic violations: (a) extra collection grant, (b) wider action (INSERT instead of FIND), (c) extra role on user — all three caught with correct violation category + detail line. Pre-tightening role (read@askflorence) replaced with custom role_reader_reference in lock-step; verified prod cross-cluster reads still healthy after the swap (drug_tier=PreferredBrand and network_tier=Preferred smoke responses byte-identical to baseline).scripts/audit/staging-cluster-drift.ts; .github/workflows/staging-cluster-drift.yml; src/lib/db.ts STAGING_REFERENCE_READ_COLLECTIONS; docs/runbooks/atlas-user-provisioning.md Step H; ADR 0004; #100 / ENG-239.2026-05-09

CC8 — Change Management ​

CriterionImplementationEvidenceLast updated
CC8.1 — change management for controls protecting non-prod-isolation invariantsThe cross-cluster Atlas PrivateLink architecture (ADR 0004) requires the staging cluster stay non-PHI for the segmentation argument to hold. Any PR that introduces a getReferenceDb() call against a collection not on the data-classification allow-list is rejected at build time before merge — preventing silent SOC 2 CC6.6 segmentation breach. The allow-list (STAGING_ALLOWED_COLLECTIONS in src/lib/db.ts) is reviewed quarterly per the cadence in docs/security-compliance/vendor-register.md. The allow-list is intentionally duplicated between the source-of-truth file (src/lib/db.ts) and the enforcement script (scripts/audit/staging-collections-guard.ts) — defense-in-depth so a developer can't make the script "self-approve" by importing the source list.scripts/audit/staging-collections-guard.ts; src/lib/db.ts lines around STAGING_ALLOWED_COLLECTIONS; .github/workflows/staging-collections-guard.yml; ADR 0004.2026-05-08
CC8.1 (additional row) — change management for cross-cluster reader role privilegesThe cross-cluster reader app_read_staging was tightened from built-in read@askflorence to custom role_reader_reference@admin granting FIND action on exactly askflorence.formularies_staging + askflorence.providers_staging (the only collections the prod app actually reads via getReferenceDb()). Principle of least privilege; matches the STAGING_REFERENCE_READ_COLLECTIONS constant in src/lib/db.ts. The constants are duplicated between the source-of-truth file and the enforcement script (scripts/audit/staging-cluster-drift.ts) — same defense-in-depth pattern as Phase 1. Any out-of-band change to the user's role (Atlas Admin UI, ad-hoc atlas CLI invocation, role escalation script) is detected the next morning by the live nightly drift check (CC7.2 row above). Reviewed quarterly alongside STAGING_ALLOWED_COLLECTIONS.scripts/audit/staging-cluster-drift.ts EXPECTED_READ_COLLECTIONS_SCRIPT_COPY; src/lib/db.ts STAGING_REFERENCE_READ_COLLECTIONS; .github/workflows/staging-cluster-drift.yml; docs/runbooks/atlas-user-provisioning.md Step B + Step H; ADR 0004.2026-05-09

CC1 — Control Environment ​

CriterionImplementationEvidenceLast updated
CC1.1 — commitment to integrity and ethical valuesFounder + cofounders operate under documented Code of Conduct (acknowledgment captured at onboarding); engineering rules in CLAUDE.md Security rules section govern day-to-day behavior (no secrets in repo, no PHI in chat, etc.).CLAUDE.md Security rules section; Onboard Team Member runbook.2026-05-11
CC1.4 — commitment to attract, develop, retain competent individualsOnboarding runbook enforces BAA-awareness brief + HIPAA workforce-awareness brief before any PHI access; quarterly access reviews verify continued competence + appropriate access scope.Onboard Team Member runbook; Access reviews.2026-05-11

CC2 — Communication and Information ​

CriterionImplementationEvidenceLast updated
CC2.3 — communicates with external parties about its objectives, system, processesPrivacy notice (pending publish per #55) communicates data practices to consumers + agents; vendor BAA-inventory communicates subprocessor scope; quarterly access review records communicate operating cadence internally.Privacy Impact Assessment; Vendor / Subprocessor Register; Access reviews.2026-05-11

CC3 — Risk Assessment ​

CriterionImplementationEvidenceLast updated
CC3.1, CC3.2 — identifies + analyzes risks; assesses fraud riskAnnual risk register at risk-assessment.md; first version 2026-05-11 with 16 identified risks scored Likelihood × Impact; mitigations tracked per row with owner + follow-up.Risk Assessment.2026-05-11
CC3.3 — considers potential for fraudRisk R-006 (legacy app-write whole-DB credential) and R-012 (HubSpot gdpr-delete pattern) explicitly address insider + scripted-action fraud paths; mitigations in flight.Risk Assessment R-006, R-012.2026-05-11

Updates to CC6 — Additional rows ​

CriterionImplementationEvidenceLast updated
CC6.2 — user registration + provisioningOnboarding runbook enforces identity-domain provisioning across AWS SSO, Atlas, GitHub, Google Workspace, HubSpot with MFA-enrollment-before-access; ADR 0003 narrow-scoped users enforce least privilege per role; Phase 5 agent onboarding (magic link + TOTP per NIST 800-63B AAL2) is designed in agent platform compliance.Onboard runbook; Access Control Policy; ADR 0003; Agent platform compliance.2026-05-11
CC6.8 — protection against malwareAWS GuardDuty enabled org-wide (account-level threat detection); GuardDuty malware-protection plan covers agent-survey-uploads S3 bucket; GitHub secret scanning + Dependabot active on the main repo; macOS endpoint protection (built-in XProtect + FileVault) on founder + ops devices.GuardDuty configuration at infra/envs/log-archive/; docs/infrastructure/guardduty-setup.md; GitHub org settings.2026-05-11

CC7 — Additional rows ​

CriterionImplementationEvidenceLast updated
CC7.1 — detection + monitoring of system anomaliesAWS GuardDuty (account threat detection, malware protection); AWS Security Hub (cross-service findings: CIS, FSBP, NIST 800-53 standards); CloudTrail org-trail (all AWS API events, 7-year retention in log-archive S3); Atlas database audit logs (DB-layer auth + admin actions); staging-cluster-drift workflow (nightly 08:00 UTC drift check on cross-cluster reader role, opens P1 issue on drift); staging-collections-guard workflow (per-PR static guard); validate-secrets workflow (per-PR secret-format check).GuardDuty config; Security Hub config; CloudTrail org-trail in log-archive account; .github/workflows/staging-cluster-drift.yml, .github/workflows/staging-collections-guard.yml, .github/workflows/validate-secrets.yml.2026-05-11
CC7.3 — incident responseFormal Incident Response Plan defines roles (IC = Taha, Comms = Ian, Compliance Liaison = Asad), severity classification (SEV-0/1/2/3), 5-step lifecycle (Detect → Contain → Assess → Notify → Remediate), regulatory notification timelines (HIPAA Breach Notification Rule 60-day clock from discovery); operational playbook in security-incident-response runbook; 5 worked-example incidents from 2026 documented.Incident Response Plan; Security Incident Response runbook; session-log entries for 2026-04-10, 2026-04-30, 2026-05-06, 2026-05-09 incidents.2026-05-11
CC7.4 — incident communication + disclosureIRP defines notification recipients (affected individuals, HHS OCR, media for >500-affected breaches, state AGs, CMS EDE program contact, vendor BAA partners, investors, internal team) with timelines per HIPAA Breach Notification Rule. Comms Lead (Ian) owns external messaging; Compliance Liaison (Asad) owns regulatory clock.Incident Response Plan, Step 4 — Notify.2026-05-11

CC9 — Risk Mitigation ​

CriterionImplementationEvidenceLast updated
CC9.2 — vendor management; third-party riskVendor register catalogs every subprocessor with BAA / DPA / FedRAMP status; Tier 1/2/3 segmentation by data exposure; quarterly review for status drift; annual full BAA-PDF audit at audit prep; new-vendor adoption gated on BAA-signed-before-data-flows; PostHog removal in flight per #75 (currently on free tier without HIPAA BAA).Vendor / Subprocessor Register; #57 (BAA chase); #75 (PostHog removal).2026-05-11

How to add a row ​

Each session that lands a control-relevant change MUST append a row here, including a link to the ADR / runbook / session log that is the evidence. Rows are additive; if a control is superseded, leave the old row and add a new one with a later Last updated date.

Pager
Previous pageOverview (auditor entry point)
Next pageHIPAA Control Mapping

AskFlorence Internal Documentation. Not for public distribution.

AskFlorence

Internal Documentation

Access restricted. Not for public distribution.