Compliance
This page narrates Escalate's data-handling posture for customers evaluating it pre-DPA. The legal-contract version of these claims lives at /legal/privacy and /legal/dpa; this page exists to give you a plain- English read on what Escalate stores, what it does with that data, and what guarantees back each claim.
Three tiers of claim — each backed by a different defense mechanism:
- Tier A — Code-defended. Enforced by source-code invariants with structural CI gates. If a future PR weakens the claim, the build fails.
- Tier B — Contractually defended. Enforced by the DPA + LLM- provider sub-processor agreements. Read the DPA for the binding language.
- Tier C — Process-defended. Enforced by an internal agent-coordination review rule (no code gate). If a future PR introduced a violating code path, founder review is the only catch. Available to customers via DPA + an annual security questionnaire on request.
§1 What Escalate stores + how
Tier A — Per-workspace data isolation
Every row in Escalate's Postgres has a workspace_id column and a
Row-Level Security policy that restricts reads + writes to rows
matching the requesting workspace's ID. Cross-workspace reads are
structurally impossible.
Defense: A boot-time schema assertion at
packages/shared/src/db/schema-assertions-runner.ts verifies the
RLS policies exist + are enabled on every table before the worker
or bot processes accept traffic. Boot fails fast if any policy is
missing or relaxed.
Cross-link: /legal/privacy restates this in contract-grade language.
Data inventory (narrative)
What Escalate stores per workspace:
- Slack message metadata + content for channels the bot created (deal channels only — no DMs, no arbitrary channels).
- CRM deal records (Salesforce Opportunity / HubSpot Deal — id, name, amount, stage, last-update timestamp).
- Role mappings (which workspace user is Legal / Security / Compliance / AE).
- Threshold configuration (per-role business-day silences).
- Audit chain (every alert, every action you took, every classification verdict).
What Escalate does NOT store:
- DMs. Escalate's bot scope does NOT include
groups:historyor arbitrary-channel read; only channels it auto-created. - CRM contact PII outside deal-record fields. Names, phone numbers, custom contact fields are not pulled.
- OAuth refresh tokens in plaintext. Stored encrypted (Supabase Vault).
§2 The LLM firewall
Escalate uses LLMs (Llama 3.3 70B as the V1 default; Anthropic Claude available) to classify sub-thread messages — is this a substantive ask, a routing question, a completed task? The classifier verdict drives what to track; it never drives how the audit chain transitions.
Tier A — Deterministic code owns state transitions
Per Persistent Decision #6 (load-bearing, can't be re-opened without explicit founder direction):
- LLMs classify. The classifier returns a structured verdict
(e.g.,
{kind: 'substantive_ask'}or{kind: 'routing_question'}). - Deterministic code owns state. The silence-tracker reads the
verdict + advances state machines (
threshold_state,alert_state) via plain TypeScript — no LLM in the write path.
Defense: The single-writer registry lint at
tools/ci/single-writer-registry.sh enforces that every state-
machine mutator in the codebase has exactly one declared writer
file (plus an optional orchestrator). If a future PR added an LLM-
driven write to one of these state machines, the lint hard-fails
merge. The registry is at
packages/shared/tests/state-writers-registry.ts.
Tier A — No cross-customer fine-tuning
Escalate's LLM access is mediated by the ChatProvider interface
at packages/worker/src/classifier/providers/. This interface is
the boundary at which provider-specific quirks (OpenAI-
compatible vs. Anthropic SDK) get isolated from the rest of the
classifier.
Equally important: this interface is also the only call site
for outbound LLM traffic. Any code path that would feed customer
data into a fine-tune endpoint would have to add a new method to
this interface or a new file under providers/ — both visible at
PR-review time.
Defense: Architecture invariants (arch:check gate) block any
import of @anthropic-ai/sdk or openai from outside
packages/worker/src/classifier/providers/. The boundary is
structural.
§3 No-training-on-customer-data
Tier B — Contractual claim
Escalate's LLM sub-processor agreements (currently Groq + Anthropic; extensible via the ChatProvider interface) prohibit training on inference inputs.
Defense: This is a contractual guarantee with each LLM provider, NOT a code-side claim. The defense lives in the master service agreements with each provider and is restated in /legal/dpa §"LLM sub-processors."
If you need a copy of the underlying provider agreements for your own compliance review, request via the DPA process.
§4 No founder-side customer impersonation
Tier C — Process-defended
Escalate does NOT have a "log in as customer" support feature. The founder cannot impersonate a customer user to debug an issue.
Defense: Process-defended via the agent-coordination rule. The
codebase has no /admin/login-as endpoint, no "set session as user
X" path, no super-user session token. Debugging is done via:
- Sentry (error reports with PII-scrubbed payloads).
- Supabase admin reads (DB-level inspection by the founder, NOT via session-impersonation).
- Customer screenshare (Calendly walkthrough).
- Audit-export of the customer's own audit chain (run by the
founder via
/escalate audit-export workspace).
Important caveat: This is a process defense, not a structural one. There is no CI gate today that would block a future PR from adding an admin-login-as endpoint. The defense is:
- The agent-coordination rule (founder reviews before any PR that would add such a path).
- The persistent-decision protection on PD #6 (load-bearing — not re-openable without explicit founder direction).
If a customer audit asks for a structural defense (a CI lint that
blocks any setSessionForUser-shaped code path), Escalate would
add it. Until then, the Tier C posture is honest about its
limitations.
§5 Auditing posture
Append-only audit chain (Tier A)
Every event Escalate writes to the events table is append-only.
The schema enforces this:
- No
UPDATEorDELETEpermitted on events rows (RLS + role GRANTs at the database level). - Each row has a
created_attimestamp + monotonic ordering. - Hash-chain integrity (M7 PR D) provides per-row tamper-evidence.
Defense: The boot-time assertion verifies the RLS posture on
events; a CI lint at tools/ci/event-direct-insert-guard.sh
prevents direct writes that would bypass the single-writer
discipline.
Audit-export (Tier A — feature surface)
You can export the full audit chain at any time via
/escalate audit-export workspace (founder-only). The export
includes:
- Every alert fired + the action taken.
- Every classifier verdict for sub-thread messages.
- Every CRM stage transition that fired the trigger.
- Every role-assignment + threshold change.
The export is signed (HMAC) so downstream consumers can verify integrity. See Slash commands for the export format options.
Cross-link: /legal/dpa §"Customer data export" restates this in contract-grade language.
Common questions
Where does my data physically live?
Supabase Postgres in AWS us-east-2. Single-region V1; multi-
region at $500K ARR per the V1 architectural plan.
Do I have a data-deletion process?
Yes — cancellation flows through the Customer Portal trigger a 30-day read-only grace period followed by scheduled deletion. See /legal/privacy §"Deletion."
Can I bring my own LLM key?
Today: no. Escalate manages LLM access centrally via the ChatProvider interface; per-customer routing is V1.5. If you have a compliance requirement that needs your own provider, ping the founder.
Do you have a SOC 2 report?
V1: no — Escalate is pre-SOC 2 as a deliberate trade-off (founder- solo + 10-DP target makes the audit cost unjustifiable today). SOC 2 Type II is a Year-2 milestone tied to first 25-customer ARR milestone. The DPA covers the substantive controls without the certification.
Next steps
- Read the binding legal version: /legal/privacy
- Export your audit chain:
/escalate audit-export workspace. - Lifecycle context: What Escalate does.