Tenant-isolated
by design.
Privacy-by-architecture, not policy-by-PDF. Every Product you connect runs inside its own Cloudflare Durable Object. Cross-tenant access is architecturally impossible — not just disallowed.
Data flow
Webhooks and SDK events land in your tenant Durable Object. Aggregated counts and semantic shape — never raw payloads — flow through AI Gateway to LLM providers. The briefing email comes back to your inbox.
What we send to LLMs
We send aggregated counts, schema shape hints, and semantic annotations. We never send raw event bodies, customer emails, or conversation contents to shared model providers.
Vector embeddings are computed on our infrastructure (Cloudflare Vectorize) and stay there. Only the resulting cluster labels and counts flow into the briefing pipeline.
AI Gateway logs the requests for our own observability. Those logs are never shared with model providers and are not used for training. See §7.
What we store, and where
Six distinct stores, each sized to its access pattern. No shared tables, no shared namespaces. Every key, object, and row is prefixed by your Product's ID.
| Store | Purpose | Retention |
|---|---|---|
| Durable Object SQLite | Tenant state — settings, rollups, feedback clusters, semantics, briefings, watchlists, agent memory. | Lifetime of the account |
| Analytics Engine | Raw append-only product events at scale. Columnar OLAP; cheap at billions of rows. | 365 days |
| R2 | Large blobs — sales-call transcripts, email attachments, chat attachments. | 90 days unless referenced by an active rollup |
| Vectorize | Feedback + call + review embeddings. One namespace per Product for semantic dedup and search. | While their source exists |
| Workers KV | SDK key → Product mapping, hostname cache, feature flags. | Only while in use |
| Cloudflare Secrets Store | Platform secrets. Per-Product OAuth tokens are encrypted with AES-GCM before being written to the DO. | Only the values you authorize; rotated with you |
Full architectural rationale in the architecture page.
Retention
Custom retention windows are part of the Scale tier. Contact us if your compliance posture requires shorter or longer windows.
Deletion
One click from your settings. We call ProductDO.deleteTenant()
which drops the SQLite tables, schedules R2 blob deletion, removes
Vectorize entries, and revokes the OAuth tokens. Within 30 days, this
is irreversible — there is no undelete.
The delete path is the only path that touches tenant data at a structural level. There is no other function or endpoint that removes or exports tenant data. See the architecture page for the full invariant.
Sub-processors
7 vendors. Each row names the service, the data it can access, and whether it pledges not to train models on that data.
| Vendor | Purpose | Data accessed | Region | No training | Added | |
|---|---|---|---|---|---|---|
| Infrastructure | Cloudflare | Workers compute, Durable Objects, R2 object storage, Vectorize, Workers KV, D1, Analytics Engine, Email Routing, Secrets Store | all tenant data (encrypted at rest by default; per-tenant DO isolation) | global edge | — | 2026-04-25 |
| Sentry | error tracking and performance monitoring | error stack traces, request metadata; no payload bodies, no PII intentionally shipped (filtered at boundary) | us | — | 2026-04-25 | |
| AI providers | Cloudflare AI Gateway | rate limiting, caching, and observability for outbound LLM calls | AI request/response payloads — counts and shape hints, never raw tenant data | global edge | Yes | 2026-04-25 |
| Anthropic | Claude language models accessed through AI Gateway | aggregated counts, schema shape hints, semantic annotations — never raw events, customer emails, or conversation contents | us | Yes | 2026-04-25 | |
| OpenAI | embeddings + GPT models accessed through AI Gateway | aggregated counts, schema shape hints, semantic annotations — never raw events, customer emails, or conversation contents | us | Yes | 2026-04-25 | |
| Payments | Stripe | billing for the Herald subscription itself (your customers' Stripe accounts are not a sub-processor relationship — those are direct integrations) | your billing email, name, payment method | global | — | 2026-04-25 |
| Cloudflare Email Workers | transactional email delivery (briefings, magic links) | your email address, briefing subject lines and bodies | global edge | — | 2026-04-25 |
The full public list is at /legal/subprocessors;
this section is the same data inlined for the security overview. The
canonical source is apps/marketing/src/data/subprocessors.ts.
AI training pledge
Your data is not used to train models.
Cloudflare AI Gateway logs are stored for our own observability and are not shared with Anthropic or OpenAI for training.
Anthropic and OpenAI commercial APIs do not train on inputs by default. The OAuth integrations Herald uses sit on the commercial tier; we re-confirm this with each contract renewal.
Webhook verification
Every webhook (Stripe, Intercom, HubSpot, GitHub, and others) is HMAC-verified before its payload enters the queue. Failed verifications log to Sentry and return 401 — they never enter the tenant. Verification happens in middleware, before any handler logic runs.
SOC 2 status
Herald follows SOC 2 controls and is preparing for a Type 1 audit. We are not yet certified. We will publish the audit report here when it lands.
If your organization requires a current SOC 2 report before signing, contact us at security@withherald.co — we can walk through our controls directly.
Security contact
Found something? Email security@withherald.co.
A PGP key will be published at /.well-known/security.txt
(coming). We respond within one business day.
We ask that you give us reasonable time to investigate and address the issue before disclosing publicly. We do not pursue legal action against researchers who follow this process.
security@withherald.co
Questions about controls, SOC 2, or custom retention? We respond within one business day.
By submitting, you agree Herald can email you the briefing and occasional product updates. See our Privacy Policy and Terms. Unsubscribe any time.