Privacy
Anvil sits in front of actions that move money, delete records, or send messages. To do that we necessarily see something about those actions. This page says exactly what — surface by surface — and nothing more than we can point to in the running code.
Everything below describes Anvil Cloud, the hosted service at anvilcontrol.ai. If you run Anvil self-hosted, the data stays in your own infrastructure and this page describes only the marketing site and the ghost intake, if you use them.
The short version
- We do not sell your data, we do not share it for advertising, and we do not use it to train models.
- The ghost intake keeps no copy of the log text you paste. The report derived from it is held briefly — up to 30 minutes in our job store, up to 12 hours in memory — so it can be rendered, downloaded, and emailed, then dropped.
- The hosted control plane keeps a decision record for each action you protect. That record is metadata about the call — action name, policy, mode, outcome, amount, timing — plus a fingerprint of the payload rather than the payload itself, with one documented exception: an enforce-mode block captures the call body, up to 128 KB, so you can retry it after review.
- Sign-in is Google OAuth. We keep your verified email address as your workspace identity, plus the account id, display name, and profile photo URL Google returns — for up to 30 days after your last visit.
- We are US-hosted. Our sub-processors are listed below, and we tell customers before that list changes.
- Retention periods for production decision records are still being set. We say so plainly below rather than publish a schedule the code does not implement.
Who we are and how to reach us
Anvil is operated by Henry Miller, an individual trading as Anvil, based in San Francisco, California. Privacy questions, access requests, deletion requests, and DPA requests all go to henry@anvilcontrol.ai, and a human reads that inbox every business day. There is no support queue between you and the person who wrote the service.
We have not incorporated an operating entity yet. When we do, we will name it here and on the Terms, and we will notify customers under a signed agreement. A registered mailing address will follow the entity — we would rather leave that blank than print an address that is really a home.
Our roles: when we are the controller, and when you are
We wear two hats, and which one applies depends on the data.
For your account, our request and security logs, the marketing site, and support correspondence, Anvil is the controller — we decide why that data exists and what happens to it, and the rights described below are exercised against us directly.
For customer data flowing through a guarded action — the amounts, action names, counterparties, approvals, and payloads inside your decision records — you are the controller and Anvil is your processor, acting on your instructions under the DPA. If one of your end users asks us about their data, we will not answer for you: we refer them to you and tell you it happened.
If you are unsure which hat applies to something, ask, and we will tell you.
What we collect, by surface
1. The ghost intake
The ghost intake at go.anvilcontrol.ai/ghost is deliberately anonymous — you can use it without an account. It is also the surface where you hand us the most sensitive material, so it gets the most specific disclosure. The wording below says the same thing as the disclosure rendered on the intake screen itself, and a test holds the retention numbers in the two places to the same value, so they cannot drift apart quietly.
- What we take: the log or config text you upload or paste — or, in connector mode, the read-scoped credentials you enter, used only to pull a bounded window of recent activity.
- Before analysis we run a pattern-based redaction pass over the content (keys, bearer tokens, cookies, emails, card- and SSN-shaped numbers). It is best-effort, not DLP — it will miss novel secret formats, so treat it as a safety net, not a guarantee.
- Where analysis runs: on Anvil's servers. External model calls are off unless the operator of the deployment has both enabled them and configured a provider key. When they are off, nothing you paste leaves our servers. When they are on, a redacted excerpt is sent to the configured provider for inference and the model's answer is cached on our servers to avoid repeat calls. The intake screen tells you which of those two states the deployment you are using is in, before you paste. Either way, your content is not used to train models.
- How long it lives: we do not keep your log or config text. It is parsed in memory and never written to a file or a database row. The report we derive from it is held briefly so the page can render it and you can download or email the PDF: the job events carrying that report live in Redis for up to 30 minutes, and the pending report plus its rendered PDF sit in the server's memory for up to 12 hours, keyed to your session. Both are dropped after that, and neither survives a restart. An intake session also holds request counters for that same 12 hours. A connector token is held in memory for the same window and is never sent back to the browser. Credentials you type are used for the pull and not stored.
If you ask us to email you a copy of your ghost report, that email — including your address and the report PDF — is sent through our email provider (see the sub-processor list).
2. Account and sign-in
Sign-in is Google OAuth with the scope openid email profile. From what Google returns we store your verified email address — which becomes your workspace identity — Google's account identifier for you, the email-verified flag, your display name, and the URL of your profile photo, with created and updated timestamps. Your session record holds a session id, your user id, email, name, photo URL, and first-seen and last-seen timestamps.
Both records live in Redis and expire 30 days after they were last written, so an account you stop using ages out on its own. We do not receive your Google password, and we do not read your mail, your files, or your contacts.
For each workspace we store the workspace name, the verified email, and a creation timestamp. A workspace email supplied during provisioning is a separate field from the address you signed in with, and only a Google-verified sign-in proves ownership of an address — we do not treat a self-declared email as an ownership claim.
3. API keys
An Anvil API key is stored as a hash plus a short non-secret prefix, a label you choose, and created / last-used / revoked timestamps. The key itself is not recoverable from our database; if you lose it, you rotate it.
4. Runtime decision records
When your code calls Anvil to guard an action, we record what we decided and why. Per call that means: an identifier and idempotency key, the action name, the policy and mode in effect, the outcome and status, the amount in cents where the action has one, the number of attempts, the reason and the specific rule that blocked it, timestamps, duration, a trace id, and a hash of the payload. Approval and override records additionally carry the operator's email, so a maker-checker decision is attributable to a person.
Sensitive-data (egress) checks record the classes of sensitive data found and the field names redacted — not the values.
Blocked calls. There is one place where we store the call body itself: when an enforce-mode rule blocks a call, Anvil captures the input body — up to 128 KB — so that an operator who reviews and overrides the block can retry the original request. That body is whatever your code was about to send, so it can contain personal data, payment references, or confidential business detail; it exists only to make an operator-reviewed retry possible. Records carry an explicit flag for whether the body was captured, so the interface never implies a retry it cannot perform. On every other path — ghost mode, allowed calls, dry runs — we hold the fingerprint, not the body.
Audit integrity. Audit records can be linked into a tamper-evident hash chain, which anvil verify checks. HMAC signing of that chain is off unless you set a signing key (ANVIL_AUDIT_SIGNING_KEY); with no key set, the chain is tamper-evident but not cryptographically attested, and we label it that way in the product rather than implying otherwise.
5. Product usage
Per guard call we record the workspace, the action name, the idempotency key, the outcome, and the duration, so we can show you your own usage and so we can tell whether the service is healthy. This is operational metadata, not content.
6. Ordinary web and email
The marketing pages, docs, pricing, and this page are static and carry no analytics scripts, no advertising pixels, and no third-party cookies. Our servers write standard request logs (IP address, user agent, path, status, timing) for security and debugging. Cookies we set are functional: a session cookie after sign-in, and short-lived cookies that carry a sign-in across our own origins.
If you subscribe to status-page notifications, we store your email address or webhook URL, a double-opt-in confirmation token, and the timestamps of confirmation and unsubscribe.
What we do not do
- We do not sell personal data or share it for cross-context behavioural advertising.
- We do not use your content, logs, policies, or decision records to train models — ours or anyone else's.
- We do not run behavioural advertising or analytics trackers on our public pages.
- We do not ask for, and you should not send us, raw payment-card authentication data or protected health information. Anvil is not a supported environment for either today.
Sub-processors
These are the third parties that can process customer data on our behalf. The first five rows are in active use today. The two AI rows are conditional: they process nothing unless a deployment has AI analysis enabled *and* a provider key configured, and on anvilcontrol.ai today it is off. We do not list aspirational vendors, and we do not pad the list to look bigger.
| Sub-processor | What it does for us | What it can see | Where |
|---|---|---|---|
| Railway | Hosts the application services, the Postgres database, and Redis | Everything stored by the service | United States |
| Cloudflare | CDN and static hosting for the anvilcontrol.ai apex | Request metadata for the marketing site | Global edge, US origin |
| GitHub (Microsoft) | Source hosting and the build pipeline, and storage of the daily database backup as a private build artifact | A full copy of the database, inside that backup artifact | United States |
| Resend | Transactional and alert email (ghost reports, status-page confirmations, alerts) | Recipient address and message content | United States |
OAuth sign-in only, scope openid email profile | Your Google account identity, at sign-in | United States | |
| Anthropic | AI-assisted analysis — only when the deployment has AI analysis enabled with an Anthropic key | A redacted excerpt of content submitted for analysis | United States |
| Google (Gemini) | AI-assisted analysis — only when the deployment has AI analysis enabled with a Gemini key | A redacted excerpt of content submitted for analysis | United States |
The two AI rows are conditional on purpose. On a deployment where AI analysis is not enabled, no content reaches either provider, and we will not claim otherwise to look more capable.
The GitHub row is there for a specific reason: our host does not provide native Postgres backups on our current plan, so the daily backup is taken by our own build pipeline and kept there. That means a full copy of the database exists in a second place, readable by repository collaborators. It is a deliberate trade for having a restorable backup at all, and it belongs on this list rather than in a footnote.
Customer-directed integrations are different. When you connect a system you own — Stripe, Datadog, CloudWatch, Splunk, Temporal, Airflow, Twilio, n8n, LangSmith, Langfuse, Helicone — Anvil pulls *from* that provider using credentials you supply. That is your integration under your agreement with that provider, not our sub-processing of your data, and Anvil holds the credential in memory for the pull window and never returns it to the browser.
Changes. We maintain this list as the current one. Customers under a signed agreement are notified before a new sub-processor starts processing their data, with the objection procedure set out in the DPA.
International transfers
Anvil Cloud is hosted in the United States, and our sub-processors above process in the United States. If you are outside the US, using the hosted service means your data is transferred to and processed in the US. We do not operate an EU or UK data residency option today, and during beta the service is aimed primarily at US customers.
Where a transfer mechanism such as the EU standard contractual clauses or the UK addendum is required, a signed DPA is the instrument that carries it. A public page cannot execute those clauses — see the note at the top of the DPA for exactly where we stand on producing one.
Sign-up abuse controls use counters keyed by hashed network identifiers, rather than email addresses or raw IP addresses. Redis attempt counters expire after two minutes. Expired workspace-creation counters are removed during later successful sign-up activity; inactive counters can remain until that cleanup runs.
Retention
We would rather publish what the code does than a schedule it does not implement.
| What | How long | Notes |
|---|---|---|
| Ghost intake log or config text | Not retained | Parsed in memory; never written to a file or a database row |
| Ghost intake report and its PDF | Up to 30 min (job store) / up to 12 h (memory) | Held so the report can be rendered, downloaded, and emailed. Dropped on restart |
| Ghost intake session counters | Up to 12 hours | In memory only |
| Connector credentials | The pull window, up to 12 hours | In memory only, never returned to the browser |
| AI inference cache | While AI analysis is enabled | Exists only on deployments with AI analysis on |
| Sign-in and session records | 30 days after last use | In Redis; expires on its own |
| Idempotency records | 24 hours by default | This is the duplicate-suppression window, tunable per call |
| Decision records, receipts, policies, usage events | Retained until deletion is requested | No automatic expiry is implemented today |
| Database backups | 14 days | A daily dump kept as a private build artifact at GitHub; 14 days is that artifact's retention |
| Request and security logs | Short operational window at our host | Not a customer-facing retention commitment |
Production retention and deletion periods for decision records are an open decision, not a settled one, and we are not going to invent one on a web page. Nothing in the code expires a decision record today; it is there until you ask us to remove it. If you need a contractual retention period, say so and we will agree it in a signed DPA. Backups, security logs, records under legal hold, and records we are required to keep may persist for a limited period after a deletion request — a deletion request reaches live systems first and ages out of the 14-day backup window after that.
Why we are allowed to process it
Where the GDPR or the UK GDPR applies to data for which we are the controller, these are our lawful bases:
| What we process | Basis |
|---|---|
| Your account, workspace, and the service itself | Performance of our contract with you |
| Request and security logs, abuse prevention, debugging | Our legitimate interest in keeping the service working and safe, balanced against your interests |
| Alert and status-page email you asked for | Your consent, withdrawable at any time |
| Records we are required to keep, and responses to lawful requests | Compliance with a legal obligation |
Where we are your processor rather than the controller, your instructions are the basis, and the DPA is the operative document.
Your choices and requests
Email henry@anvilcontrol.ai to access, correct, export, or delete your data, to object to or restrict a processing activity, or to withdraw consent. We confirm receipt within one business day and complete the request within 30 days. If something is genuinely going to take longer, we will tell you before the 30 days are up and say why, rather than going quiet.
- You may use an authorised agent. We will ask for written proof that you authorised them, and we may ask you to confirm it directly.
- We will not treat you differently for asking. Exercising any of these rights does not change your access, your pricing, or the service you get. There is nothing to retaliate with and we would not anyway.
- If we get it wrong, appeal it. Reply to our answer and say you are appealing; a second look is free and we will explain the outcome in writing.
- Deletion is a manual operation, on request. There is no self-serve "delete my account" button today. We do the deletion ourselves and tell you what was removed.
- Export of your decision records is available today through the
anvil auditcommand and the decision log in the dashboard — you do not need to ask us for it.
If you are in the EU, the UK, or Switzerland, you may also complain to your data protection supervisory authority, and if you are in California you may complain to the California Privacy Protection Agency or the Attorney General. We would rather you came to us first so we can fix it, but that is your right and not conditional on trying us.
Where a privacy law gives you rights beyond the above, those rights apply.
Security
Security has its own page. The security policy opens with what actually protects your data — encryption, tenant isolation, access control, credential storage, backups and the daily restore test — and then covers the vulnerability reporting channel, our response-time commitments, and what is in and out of scope. The contractual version of the same controls is section 5 of the DPA.
In short: transport encryption everywhere, encryption at rest at our host and at GitHub for the backup artifact, tenant isolation enforced at the query layer and regression-tested, API keys stored only as hashes, and one person with production access.
We hold no SOC 2, no ISO 27001, and no completed third-party penetration test. If one of those is a requirement for you, tell us and we will tell you honestly where we are rather than where we would like to be.
No system is completely secure, and for a customer under a signed agreement the security schedule in that agreement — not this page — defines what we have committed to.
Children
Anvil is a developer tool sold to businesses. It is not directed to children, and we do not knowingly collect personal information from anyone under 16.
Changes to this statement
This page is generated from a reviewed source document, so what you read here is what was reviewed. Every version carries a version number and an effective date at the top, and the "What changed" note at the foot of the page says what moved and when. Superseded versions stay in our public source history, so "we updated the privacy statement" is something you can check rather than take on trust.
For a material change affecting customers under a signed agreement, we notify them rather than relying on you re-reading a web page.