AdaptivMapr

Your data

Schema-only: the header row and three clamped rows pass; the rest of the file stays

The cascade holds nothing between calls — but the product around it has an account, a wallet, an audit trail and your uploads. Here is what each of those is, which store it sits in, how long it survives, and exactly what happens when you press delete.

Schema-only: the header row and three clamped rows pass; the rest of the file staysheadersclamp≤3 rows · ≤80 chars

What we store

Eight categories, and nothing else.

The cascade itself is pure compute — it holds no state between calls. The deployed product around it does: an account, a wallet, an audit trail, your uploads for as long as you need to finish an import, and the records that keep the service working and safe.

Account email

Your email address is the identifier your account is built on (with your name and picture if you sign in with Google). It is held by Supabase Auth and written to the tenant record on first sign-in. There is no password to store — there is none. Accepting our policies or the BAA also records your IP address and browser, as evidence of the agreement.
Identityauth.users.id → tenants.id, populated by a handle_new_user trigger that also writes your tenant_members row. Dashboard reads then run on your own user JWT, so row-level security is the gate rather than application code.

Sign-in & sessions

Sign-in runs through Supabase Auth — Google OAuth, or a single-use email link / one-time code. Your session lives in short-lived cookies Supabase issues and refreshes.

Uploaded files & mappings

Files are parsed in memory and the parsed upload is stored in Cloudflare KV under a native expiry taken from your workspace retention setting, mirrored to Supabase for the same window. In schema-only mode only column headers and up to three sample values (≤80 characters each) are retained.

API keys

v1 keys are HMAC-signed and self-contained: verification needs no lookup, and we store only an identifier used for revocation. The full key string is shown once at creation and never persisted.
Why it mattersVerification is a signature check plus a revocation read — a leaked database row cannot mint a key, because the row never contained one.

Usage & audit trail

Request metadata (timestamp, endpoint, status, duration, billed units) and a hash-chained audit log of key creation, revocation, commits, settings changes and billing events. Each audit entry is kept for seven years while the workspace exists, and the whole log is erased with the workspace (see Erasure below). Server logs stay in Cloudflare Workers Logs for 7 days.

Billing data

Stripe holds your card details — we never see them. We store the Stripe customer id, your prepaid wallet balance, a ledger of charges and top-ups, and invoicing metadata; Stripe holds a billing address and VAT number if you supply them. Nothing is charged on a schedule unless you take the optional monthly plan.

Error reports & support

When a page errors, your browser sends a scrubbed report — error type, a 300-character message with emails, numbers and keys removed, the page path, stack frames — that lives only in Cloudflare logs. A support request travels as ordinary email to our mailbox and its text is not stored in our database; never put patient information in one.

Prompt-injection signals

When a detector flags text sent to an AI feature as a possible manipulation attempt, we keep the rules that fired and an excerpt of the matched text (at most 2,000 characters, which can include data next to the match) for 180 days, to study such attempts and train a model that detects them. It changes nothing about the run; incognito chats are never recorded.

We do not collect biometric data, precise geolocation, behavioural analytics, or advertising identifiers. See §2 of the Privacy Policy for the complete list.

  • Uploads in KV, on a TTL you set
  • RLS tenant isolation
  • HMAC self-contained API keys
  • Headers + ≤3 rows in schema-only
  • Hash-chained audit_logs

Where it lives

Every row has a store, a clock, and a reader.

“We don’t keep anything” is not a claim we make. This is the actual map: which system holds each thing, how long it survives there, and which identity is allowed to read it back.

WhatRetentionWho can read it
Parsed uploads (may contain PHI)Cloudflare KV (MAPR_KV), mirrored to Supabase0, 24, 168 or 720 h — 24 by default; an uncommitted upload’s record stays until the workspace goesService role, tenant-scoped
Account, wallet, workspace settingsSupabase PostgresUntil you delete the workspaceYour user JWT, under RLS
API keysHMAC-signed, self-containedUntil you revoke themNobody — we store no key
Audit trailSupabase audit_logs, hash-chained and append-only7 years · erased with the workspaceYou, and whoever you export it to
Billing recordsStripe + Supabase metadataStripe keeps invoices and payments; our ledger keeps amounts and dates with nothing linking them to youStripe holds the card
Edge request logsCloudflare7 days (logs) · about 3 months (analytics)Operations, metadata only
Prompt-injection signalsSupabase mcp_security_events180 days · erased with the workspaceAdaptivMapr operators; you, through the export
Retention figures are /legal/privacy §7 and /legal/security §8; the upload window is your own retention_hours setting, written straight into the KV expirationTtl. Uploads (PHI), connectors (secrets) and the v1 bearer API run service-role with explicit tenant_id scoping; the dashboard plane runs on your user JWT so RLS enforces isolation in the database rather than in application code.

Two modes

Schema-only sends a clamped sample, never the file.

Schema-only and full-data are two modes of the same cascade, not two tiers of a plan. Both draw the same small flat per-map fee; schema-only sends headers and at most three sample rows clamped to 80 characters a cell, full-data sends the rows. Neither turns the models off: columns the deterministic layers cannot settle go to our mapping ranker and the model layer in both — the mode decides how much a model sees.

Schema-only — data minimization

Only column headers and at most three sample rows, each clamped to 80 characters, ever leave your tenant, and the same clamp is re-applied at the model boundary. It is a mode, not a tier: most columns resolve before any model is consulted, and a DPA is usually unnecessary (one is provided on request).
EnforcedThe clamp is applied at the HTTP edge in every route that accepts sample rows, and re-applied defensively at the LLM boundary. One chokepoint, clampForSchemaOnly() in lib/parser.ts.

Full-data — in-region, under a BAA

Row-level AI cleanup goes to phi-cloud with X-PHI and X-Region set, so the gateway forces a PHI-eligible, in-region model. It costs 20% more on the whole map charge, and it is locked until your workspace accepts the BAA/NDA in the app.
GatedAn explicit PHI request without an acceptance returns 403 agreement_required with a pointer to Settings → Security & Data. There is no silent downgrade to the general catalogue.

PHI routing is off by default: an unconfigured workspace runs standard. Turning it on is an explicit opt-in in Settings → Security & Data, in the same place you accept the BAA/NDA. See how the wallet is charged and how one run resolves its routing.

Erasure

Two buttons, one implementation.

“Delete workspace” erases one workspace for all its members. “Delete account” erases every workspace you are alone in, leaves the ones you share, and deletes your sign-in. Both run one implementation. There used to be two, and one of them skipped the audit event, the KV purge and the cache clears, then reported success after a failed delete.

  1. 1Audit event first

    The erasure intent is written and awaited BEFORE anything is destroyed. If a later step fails, the workspace is still there and the attempt is on its record; if the erasure completes, it goes with the rest of the audit log.

  2. 2Outside stores first

    While the database still says what belongs to the workspace: every upload is purged from Cloudflare KV with its webhook secret, delivery record and dead-letter entries, the phi-cloud key is revoked, and the Stripe customer profile is deleted. If any of these fails, the erasure stops there and the workspace is left whole, so a retry finishes the job.

  3. 3One database transaction

    One function erases the whole database side at once: the workspace’s entire audit log, its rate-limit counters, the tenant row and everything hanging off it. The billing ledger is kept but stripped of the workspace link, and signed agreements are kept as evidence. Before it commits, it checks every table for anything still carrying the workspace id. If something is left, nothing is committed. It records one anonymous tombstone.

  4. 4Caches cleared

    Per-workspace KV entries (quota, admin email, entitlements) are deleted, and connectors, settings, agreement and key caches are invalidated, so a warm Worker isolate cannot bring a deleted row back.

  5. 5Notification email

    A destructive-action email is queued through the Worker’s waitUntil so it still lands after the response has flushed and the tenant row is gone.

  6. 6No false success

    Neither route reports success unless every step finished. A failed erasure returns an error, never “Account deleted.” Account deletion also stops before removing your sign-in, so you can sign in and try again.

bash
# Two buttons, one implementation (lib/workspaceErasure.ts).
# Both require a CSRF token AND a server-side confirmation string.

curl -X DELETE https://adaptivmapr.com/api/v1/me/workspace \
  -H "X-CSRF-Token: $CSRF" \
  -H "content-type: application/json" \
  -d '{"confirm":"delete-my-workspace-<workspace_id>"}'

# The account button erases every workspace that is yours alone, leaves the
# ones you share, then deletes your sign-in:
curl -X DELETE https://adaptivmapr.com/api/auth/account \
  -H "X-CSRF-Token: $CSRF" \
  -H "content-type: application/json" \
  -d '{"confirm":"delete my account"}'
→ complete · one transaction · residue-checked · anonymous tombstone

You do not need curl: the same cascade runs from Dashboard → Settings → Account, which asks you to type the confirmation phrase first. Erasure cannot be undone, so take a copy before you press it: Download your data sits on the same page (see Export & rights). Deleting a workspace erases everything in it, for every member: uploads and their stored copies, connectors and their secrets, API keys, chats and stored files, schemas, saved mappings and reshape programs, settings, and the workspace’s audit log. Its phi-cloud key is revoked and its Stripe customer profile is deleted, which also cancels any subscription. Deleting your account erases every workspace where you are the only member and removes you from workspaces you share with others — those stay with their members, including their audit log of what you did there, but your email is removed from their uploads and approvals. Then your sign-in is deleted. The audit log is erased with the workspace. What remains is one anonymous erasure record — a one-way hash of the workspace id, the time, and how many records were removed — so an erasure can be shown to have happened without keeping whose it was. Kept, for accounting and as evidence of what was agreed: the billing ledger (amounts, dates and Stripe references, no longer linked to the workspace or to you — Stripe keeps the invoices and payments), and signed BAA/DPA records and Terms/Privacy acceptances, which keep the signer’s name, email, IP address and browser and are deleted automatically after six years. If you cannot reach the dashboard, email dpo@adaptivmapr.com from the registered address with the subject Account deletion request. We action it within one month.

Export & rights

Portability, access, correction — self-serve, or on request.

You have the right to receive a copy of your personal data in a machine-readable format (GDPR Art. 20 / nFADP Art. 25), and to access, correct, restrict or object to our processing of it.

Self-serve

Sign in at /dashboard to review your API keys, usage, audit trail and workspace settings. Uploaded files stay reachable in Chat for as long as your workspace retention setting keeps them.

Structured export

Workspace owners and admins can download one JSON file — settings, members, saved schemas, learned layouts, signed agreements, the wallet ledger, the audit log, prompt-injection signals and remembered chats — with Download your data on Dashboard → Settings → Account. For anything that file does not cover, or if you cannot sign in, email dpo@adaptivmapr.com with the subject Data export request. We respond within one month.

The complete list of rights is in §8 of the Privacy Policy. AdaptivMapr is HIPAA-ready — we offer a BAA and hold a HIPAA security risk assessment on file — and SOC 2 Type II is in progress, with no attestation report yet. HIPAA is not a certification anyone can hold, so we do not claim one.

Ask us anything about your own data.

Our data protection officer answers directly. If you need the DPA, the subprocessor list, or a BAA before you can evaluate, ask and we will send it.
Your Data — AdaptivMapr