Security at NomisFile
Last updated: May 2026
Sensitivity tiers
NomisFile classifies data into three sensitivity tiers. The tier determines where the data is stored and what controls apply.
| Tier | Examples | Storage |
|---|---|---|
| LOW | Calendar dates, license metadata, member names, filing status | NomisFile (encrypted at rest) |
| MEDIUM | Policies, procedures, generic findings text, meeting agendas | NomisFile (encrypted at rest, field-level encryption on body fields) |
| HIGH | Exam reports, first day letters, bond financial documents, sensitive meeting minutes | Customer-controlled storage. NomisFile holds metadata + URL only. The file stays in your Google Drive, SharePoint, OneDrive, Dropbox, or S3. |
What NomisFile holds
- Compliance calendar (filing deadlines, status, cadence)
- License metadata (jurisdiction, license type, NMLS ID)
- Obligation templates (cited to statute)
- Filing status and workflow state
- Anonymized findings summary and remediation status
- Policy text and procedure documents (medium-sensitivity)
- Generated documents (org charts, flow of funds diagrams)
- Audit log of every user action
What NomisFile does not hold
- Exam reports and examiner correspondence
- Audit reports from independent reviewers
- Bond financial documents and surety agreements
- First day letters and regulator-issued documents
- Sensitive meeting minutes marked as high-sensitivity
These documents remain in your existing cloud storage (Google Drive, SharePoint, OneDrive, Dropbox, Box, or S3). NomisFile stores only the metadata and a link to the file.
Implemented controls
All data encrypted in transit (TLS 1.2+) and at rest. Sensitive credential fields use pgcrypto symmetric encryption (pgp_sym_encrypt/decrypt). Database backups stored on encrypted volumes.
Every tenant-scoped table enforces row-level security keyed off authenticated user identity and organization membership. The application role is subject to RLS; data cannot cross tenant boundaries even in the event of application-layer bugs.
Every action is logged with user attribution, timestamp, and affected resource. External document access events are tracked (who opened what, when). Customer-visible recent-access page available.
Centralized upload service with filename sanitization, path containment, UUID-prefixed filenames, atomic writes, SHA-256 integrity hashing, and MIME/extension allowlisting.
External document reference URLs are validated against private/reserved IP ranges, loopback addresses, and non-HTTP protocols before storage. NomisFile never fetches or downloads content from external URLs.
Role hierarchy (owner > admin > editor > contributor > viewer) enforced at both application and database layers.
Application served via Cloudflare Tunnel with DDoS protection and TLS termination. Direct origin access is not exposed.
Sub-processors
Last reconciled against running production configuration: May 2026.
| Provider | Service | Data processed | Jurisdiction |
|---|---|---|---|
| Resend | Transactional email delivery | Recipient email address; subject + body of operator-facing alerts, verification + magic-link emails. Sensitive document content never appears in alert bodies. | US |
| Sentry | Error reporting + performance traces | Exception stack traces with PII scrubbed before send (send_default_pii=False, local-variable capture off, request body / cookies / query strings stripped, sensitive headers filtered, in-path tokens removed). |
US |
| Cloudflare — edge | DNS, email routing, DDoS protection, TLS termination, Cloudflare Tunnel | Request metadata (IP, headers, path) at the edge; no application payloads stored. | US |
| Cloudflare R2 | Encrypted backup object storage | GPG-symmetric-encrypted (AES-256) backup archives only — Postgres dump + documents volume snapshot. R2 never holds live application data; the GPG passphrase is held outside R2. | US |
| PostgreSQL host | Application database | All application data (encrypted at rest). Currently self-hosted via the postgres:16 container alongside the application; managed-provider migration is planned. |
US |
Stripe is not listed: the billing integration is not yet
in production. It will be added here when it ships. The
sub-processor list is reconciled against
app/config.py and the running compose stack
on every published change.
Compliance posture
SOC 2 Type II attestation is planned when our customer base supports the audit cycle. A security questionnaire is available on request — contact [email protected].
Incident response
Customers are notified within 72 hours of any confirmed security incident affecting their data, per industry best practice. Incident notifications include: scope of affected data, timeline of the incident, remediation steps taken, and recommended actions for affected customers.
Report a vulnerability
If you discover a security issue, please email [email protected]. All reports are taken seriously and will receive a response within one business day.