Skip to content
SaidFirst

Trust & security

Everything on this page is either verifiable in the product or disclosed as a gap. We would rather tell you what we don't have than be caught claiming what we do.

Security controls, with evidence

  • Tenant isolation is enforced in one central authorisation layer

    Every server component and action that touches organisation data resolves access through requireOrg()/requireClient(); portal surfaces bind the session to the host's organisation. No query trusts an id from a URL.

  • Passwords are bcrypt-hashed; reset tokens are hashed, single-use, 60-minute

    No plaintext password or reset token is ever stored; the reset flow answers identically whether or not an account exists (no enumeration oracle).

  • API, portal-setup and access tokens are stored as SHA-256 hashes

    A database leak does not hand out working credentials. The one documented exception: outbound-webhook signing secrets are stored raw because HMAC signing requires them — mitigated by display-once UI and self-serve secret rolling.

  • Outbound webhooks are HMAC-SHA256 signed

    Stripe-style t=…,v1=… signatures with a published verification snippet; delivery never follows redirects and endpoint URLs are validated against private address ranges.

  • Billing webhooks are signature-verified and idempotent

    Stripe events are verified with the endpoint secret and deduplicated in a ledger table, so a replayed event cannot double-apply.

  • Two-factor authentication is available and self-serve

    Any agency user can enrol a TOTP second factor from their own security settings, with single-use recovery codes. The implementation is RFC 4226/6238 on the platform's own crypto with no third-party dependency, tested against the RFCs' published vectors; enrolled secrets are AES-256-GCM encrypted, and an accepted code's time step is recorded so no code works twice.

  • Personal data is kept out of operational records entirely

    Rate-limit counters are keyed by a one-way HMAC, so no email address or IP is written to them. Credentials inside notification emails (password-reset and portal-invite links) are redacted before any delivery record is stored. Both are 'never stored' rather than 'deleted later'.

  • Abuse is rate-limited at the database, not in memory

    Signup, password reset, portal login, the read API (120 req/min), public audits, invites, imports and sweeps all pass through persistent fixed-window rate limits.

  • Open-redirect protection on every post-login destination

    All next/callback URLs pass through a same-origin validator before navigation.

  • Client portals are a separate, weaker principal

    Portal viewers authenticate against a host-scoped session with its own audience claim — an agency session never works on a portal host, or vice versa.

  • TLS in transit; encryption at rest

    Transport security and at-rest encryption are platform features of Vercel and Neon respectively (provider-managed keys).

  • Accessibility and security regressions block deploys

    CI runs typecheck, lint, the unit suite, a keyless end-to-end suite, a sweep load-test harness, and an axe WCAG 2.1 A/AA scan of the core customer- and client-facing surfaces on every push.

The questionnaire answers

Multi-factor authentication
Yes — native TOTP, self-serve from each user's security settings, with single-use recovery codes. Scoped precisely rather than generously: it applies to the email-and-password route. A Google or Microsoft sign-in is not additionally challenged by us, so the factor there is whichever your identity provider enforces; and client-portal viewers, a deliberately weaker principal, are out of scope. What is not built is org-wide enforcement — an owner can enable MFA for themselves but cannot yet require it of teammates.
Backups & recovery
Point-in-time restore is a platform feature of our database provider on paid tiers. Verifying the production tier and its restore window is a standing launch-runbook step — ask and we'll show you the current state rather than assert one here.
Breach notification
Without undue delay, within 72 hours of awareness — committed in the DPA, not just here.
Sub-processor changes
14 days' advance email notice, a dated change log on the register, and an objection right in the DPA.
Data residency
United States, single region, stated plainly. An EU-hosted deployment can be provisioned on request for customers who need it contractually — we don't claim “EU residency” until it is the default.
Known imperfections we disclose
Two-factor authentication cannot be mandated org-wide yet, only enabled per user (above). Deleting an entire account is handled by our team on request rather than self-serve — the data is removed within 30 days, and we would rather say so than imply a button that does not exist. Everything else on this page is a control we can demonstrate.

How long we keep things

Operational records are deleted on a schedule enforced by our scheduled jobs. These numbers are rendered from the same constants the deletion runs on, so this table cannot drift from the behaviour.

RecordKept forWhy
Rate-limit counters24 hoursAbuse counters, keyed by a one-way HMAC so no email address or IP is ever written. Deleted a day after the window they serve closes.
Sent-email records7 daysDelivery records for alerts and notifications, with any credential in the message redacted before it is stored.
Password-reset tokens30 daysStored only as a hash and single-use. Rows are deleted once used or expired; a live token is never purged early.
Portal-access tokens30 daysSame treatment as password-reset tokens, for client-portal invitations.
Webhook delivery records30 daysDelivery status for outbound integrations, kept for troubleshooting.

Visibility history — sweeps, engine answers and scores — is kept for the life of the account, because the trend is the product. It is deleted with the workspace, or with the account on request.

Your data stays yours

Full-history CSV export is self-serve on every plan — including the day you decide to leave. Deleting a client workspace permanently removes its data (typed-name confirmation, immediate cascade); cost-accounting entries, captured audit leads and past notification records survive without the workspace link, as the privacy policy states. We sell exclusively through agencies: we will never sell direct to brands, and we will never contact your clients or your leads. If SaidFirst ever winds down, customers get 90 days' notice and their full export.

SOC 2

SaidFirst is not SOC 2 certified, and we will not pretend otherwise. We are a small team; the controls on this page — code-enforced tenant isolation, hashed credentials and tokens, least-data design, and a CI gate that blocks deploys on security and accessibility regressions — are real and verifiable in our behaviour today. We will engage an auditor for SOC 2 Type I when revenue supports doing it properly, and we will say so here when a date exists. Until then: we sign our DPA, we answer security questionnaires, and every claim above is one we can demonstrate.

Deeper diligence? privacy@saidfirst.ai — also see the measurement methodology.