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

Data Models ​

Status: Schemas locked. Collections created in Phase 2 (survey responses) and Phase 5 (everything else).


Collections overview ​

CollectionPhasePurposeWritten byRead by
agent_survey_responses211-screen research survey resultsapp_writer_surveyapp_writer_agents, app_admin_agents
agents5Agent accounts and profileapp_writer_agentsapp_writer_agents, app_admin_agents
agencies5Agency orgs (agent team parents)app_writer_agentsapp_writer_agents, app_admin_agents
agent_sessions5Auth tokens (magic links + sessions)app_writer_agentsapp_writer_agents
admins5Admin / super-admin role registryapp_admin_agentsapp_admin_agents
super_admins5Super-admin credentials (pwd hash, TOTP)app_admin_agentsapp_admin_agents
agent_audit_log5Append-only audit trailapp_writer_agents, app_admin_agentsaudit_reader
agent_nipr_records5NIPR PDB validation resultsapp_writer_agentsapp_writer_agents, app_admin_agents
agent_id_verifications5KYC vendor resultsapp_writer_agentsapp_writer_agents, app_admin_agents
agent_unsubscribes2CAN-SPAM opt-out records (pre-Phase-5 only)app_writer_surveyapp_writer_agents

agent_survey_responses (Phase 2) ​

Ships first. Forward-compatible with Phase 5 agent accounts — no breaking changes needed when accounts arrive, just a backfill script to link responses to their eventual agentId.

ts
{
  _id: ObjectId,
  submittedAt: Date,

  // Identity (no account yet when Phase 2 ships)
  email: string,          // normalized lowercase, indexed
  fullName: string,
  companyName: string,

  // OPTIONAL — backfilled by Phase 5 migration script
  // (scripts/db/backfill-agent-survey-ids.js) when an agent creates
  // an account and email matches
  agentId?: ObjectId,

  // Survey payload — structured blob, schema will evolve
  responses: {
    oepVolume, sepVolume,
    leadSources: string[], leadCost, conversionRate,
    selfEmployedPct, medicaidRejectedPct,
    topClientReasons: string[], ageRange,
    enrollmentTools: string[], enrollmentTime,
    timeSavingsRating, biggestFriction,
    consentDocs: string[], docStorage, clawbackExperience,
    retentionRate, proactiveRenewal, autoRenewalHarm,
    hardestPart, wishlist,
    featureRatings: {
      prequalLeads, brandedPage, memberPortal,
      renewalAlerts, dashboard, aiAssistant
    },
    pmpmRange, carriersWorkedWith: string[],
    adjacentInterests: string[],
    idealPartnership, partnershipModelPref,
    willingToHelp, canRefer, otherNotes
  },

  // Consent — see compliance doc
  consent: ConsentSubdocument,

  // Metadata
  schemaVersion: "v1",
  ip?: string,
  userAgent?: string,
  referrer?: string
}

Indexes: email, submittedAt, agentId. Retention: indefinite (research data).


agents (Phase 5) ​

Core agent account record. NPN is the immutable primary identifier.

ts
{
  _id: ObjectId,
  npn: string,                // unique index, immutable
  email: string,               // unique index, lowercase, mutable via flow
  fullName: string,
  phone: string,
  agencyId?: ObjectId,         // null for solo agents

  licensedStates: string[],    // two-letter codes
  status: "pending_review"     // just signed up
        | "id_verification_required"  // NIPR passed, need ID verify
        | "active"             // cleared, can receive leads
        | "rejected"
        | "suspended",
  partnershipModel?: "full-service" | "submit-ready",

  orgSize: "solo" | "2-5" | "6-15" | "16-50" | "50+",
  currentAcaMembers: "0-50" | "51-200" | "201-500" | "501-1000" | "1001-5000" | "5000+",
  referralSource: string,

  emailVerified: boolean,
  totpSetupCompletedAt?: Date,  // required for Tier 2 access

  createdAt: Date,
  updatedAt: Date,
  activatedAt?: Date,
  notes?: string,              // internal ops notes

  // Consent carried forward from waitlist / onboarding
  consent: ConsentSubdocument
}

Indexes: npn (unique), email (unique), status, licensedStates, agencyId, createdAt. Retention: indefinite while active. After rejection/suspension, follow HIPAA retention (6-10 years) then hard delete.


agencies (Phase 5) ​

ts
{
  _id: ObjectId,
  name: string,
  primaryAgentId: ObjectId,    // agency creator / owner
  teamSize: string,             // carried forward from onboarding
  createdAt: Date
}

Agency members are all agents docs with agencyId pointing here. Agency owner has additional permissions within the agency scope (invite, remove team members — Phase 6+ feature, not in MVP).


agent_sessions (Phase 5) ​

Auth tokens. TTL-indexed in MongoDB so old tokens auto-expire.

ts
{
  _id: ObjectId,
  agentId: ObjectId,
  token: string,               // opaque random 32-byte hex, indexed
  type: "magic_link" | "session",
  expiresAt: Date,             // 15min for magic_link, 8hr for session
  usedAt?: Date,               // magic links are single-use
  createdAt: Date,
  userAgent?: string,
  ip?: string
}

Indexes: token (unique), agentId, expiresAt (TTL — auto-cleans expired entries). Retention: auto-expires per the expiresAt TTL. Audit trail of auth events lives in agent_audit_log separately.


admins (Phase 5) ​

Role registry for platform admins.

ts
{
  _id: ObjectId,
  email: string,               // unique, lowercase
  role: "super_admin" | "admin" | "support",
  addedBy?: ObjectId,          // super_admin who granted (null for seed)
  addedAt: Date,
  revokedAt?: Date,            // soft-revoke, preserves audit trail
  lastLoginAt?: Date,
  totpSetupCompletedAt?: Date  // required before any access
}

Indexes: email (unique), role. Write access: only app_admin_agents MongoDB user. Retention: indefinite; soft-revoked rows never hard-deleted.


super_admins (Phase 5) ​

Separate collection for super-admin credentials. Separated from admins so compromise of the regular admin collection doesn't immediately grant super-admin access.

ts
{
  _id: ObjectId,
  email: string,               // unique
  passwordHash: string,         // argon2id
  totpSecret: string,          // AES-encrypted at app layer
  recoveryCodes: string[],      // hashed, single-use
  allowedIps: string[],         // CIDR ranges for IP allowlist
  lastLoginAt?: Date,
  lastLoginIp?: string,
  createdAt: Date
}

Written by: app_admin_agents only, and only via the super-admin management flow (or break-glass scripts). Seeded by: scripts/admin/seed-super-admin.js (one-time bootstrap).


agent_audit_log (Phase 5) ​

Append-only. The source of truth for every auth event, admin action, and data change. Required for SOC 2 / HIPAA / EDE.

ts
{
  _id: ObjectId,
  actorType: "agent" | "admin" | "super_admin" | "system",
  actorId?: ObjectId,
  actorEmail?: string,

  action: string,              // e.g. "login_succeeded", "status_changed", "admin_role_granted"
  resourceType?: string,       // "agent" | "admin" | "super_admin" | "session"
  resourceId?: ObjectId,

  changes?: {
    before: any,
    after: any
  },

  ip?: string,
  userAgent?: string,
  outcome: "success" | "failure",
  timestamp: Date
}

Indexes: timestamp, actorId, action, resourceId. Retention: 6 years minimum (HIPAA § 164.316), 10 years preferred for EDE margin. Write access: app_writer_agents and app_admin_agents (append only; app layer enforces no update/delete). Read access: audit_reader (readonly MongoDB user used by the compliance-export script).

See Auth Architecture for the full list of events logged.


agent_nipr_records (Phase 5) ​

NIPR PDB Detail Report responses for audit trail.

ts
{
  _id: ObjectId,
  agentId: ObjectId,
  checkedAt: Date,
  npnValid: boolean,
  licenseStates: string[],
  niprResponseId: string,
  rawResponse: any,            // full API response for audit
  cost: number                  // e.g. 1.30
}

Indexes: agentId, checkedAt. Retention: 10 years (EDE audit margin).


agent_id_verifications (Phase 5) ​

KYC vendor results.

ts
{
  _id: ObjectId,
  agentId: ObjectId,
  vendor: "persona" | "stripe_identity" | "plaid" | "veriff",
  vendorRecordId: string,       // vendor's ID for this verification
  status: "pending" | "passed" | "failed" | "manual_review",
  verifiedAt?: Date,
  rawResponse: any              // full vendor response for audit
}

Indexes: agentId, status, verifiedAt. Retention: 10 years (EDE audit margin).


agent_unsubscribes (Phase 2-only) ​

Minimal unsubscribe log for the period before agent_audit_log exists. Phase 5 migration copies these into the audit log.

ts
{
  _id: ObjectId,
  email: string,
  unsubscribedAt: Date,
  optInTypes: string[],         // e.g. ["marketingEmail"]
  ip: string,
  userAgent: string
}

Indexes: email, unsubscribedAt.


The consent sub-document ​

Used by agent_survey_responses, waitlist entries with interest: "agent", future agents records, and anywhere else we capture an email with intent to communicate.

ts
consent: {
  versions: {
    privacyPolicy: "v2026.04",        // version in effect when consent given
    termsOfService: "v2026.04",
    consentStatement: "<exact text shown to user>"
  },
  optIns: {
    platformContact: boolean,          // "contact me about becoming an agent"
    marketingEmail: boolean,           // "product updates and research"
    marketingSms?: boolean             // future-reserved
  },
  capturedAt: Date,
  ip: string,
  userAgent: string,
  referrer?: string,
  pageUrl: string,
  method: "checkbox" | "implicit" | "verbal_recorded"
}

This structure is designed to satisfy HubSpot / Salesforce import requirements and GDPR / CCPA consent proof by construction. See Compliance Model.


Cross-phase migration: survey backfill ​

When Phase 5 ships and agents create real accounts, run once:

scripts/db/backfill-agent-survey-ids.js

For every agent_survey_responses row where agentId is absent, find a matching agent by email, set agentId, preserve submittedAt. Idempotent — safe to re-run.


Related ​

  • Overview — phase roadmap
  • Auth Architecture — how agent_sessions, agent_audit_log, and TOTP tie together
  • MongoDB Permissioning — which DB user can touch which collection
  • Compliance Model — retention rationale and regulatory mapping
Pager
Previous pageCompliance Model
Next pageOverview

AskFlorence Internal Documentation. Not for public distribution.

AskFlorence

Internal Documentation

Access restricted. Not for public distribution.