VITNAcontainment for rogue AI agents
Try the demoSign in
We never sell your data. Here is exactly what we store.

Privacy Policy

Last updated: October 6, 2026 · Applies to VITNA and all COSTRINITY products

[ TL;DR: the short version ]
  • ✓Cloud storage is the default. Your agents send events and checks to our API, and we store the events and a record of each check.
  • ✓With no credentials set, the MCP package creates a trial account. Versions before 0.5.1 send your machine's hostname as part of the agent name; 0.5.1 and later do not.
  • ✓From October 19, 2026, guard mode (0.5.1 and later) tells us that it is in use, and we note that once on your account. VITNA_GUARD_NO_ACTIVATION=1 turns it off.
  • ✓A check stores its verdict, not your raw input. Guard mode with a policy file is the exception: we store each call's tool name and target address, and for a held call up to 400 characters of its arguments, with detected secrets replaced.
  • ✓Rate limits are enforced server-side, so we do hold per-agent request counts.
  • ✓Security records, such as refused keys, sign-ins and guard sessions opened with a policy file, keep the IP address and user agent, and are kept indefinitely.
  • ✓We never sell your data or share it with third parties for their own purposes.
  • ✓Want zero cloud storage of events? VITNA Desktop keeps events, decisions and holds on your device. It still checks our server for updates, and contacts it to activate a licence key if you enter one.

1. Who We Are

VITNA is a product of COSTRINITY INC. ("COSTRINITY"). We build developer tools for AI agent operators. Our registered contact is hello@costrinity.xyz.

2a. Checker result emails (optional)

The two free checkers at /article-50 and /ai-act-december-2026 store nothing that identifies you by default. You can run either one start to finish and share the result link. When you finish a check, the page sends one anonymous count of which obligations or deadlines your answers triggered, and we store it with no email address, no IP address and no account attached. A click through to booking is counted the same way.

If you tick the box and submit your address at the result step, we store exactly this: your email address, which checker you ran, a short summary of the result you were shown, the obligation identifiers your answers triggered, the fact that you consented, the timestamp, and when each follow-up email went out. If you later book a call through our booking page with the same address, we also note when you booked, and the follow-up emails stop (section 2b). We do not store your individual answers, and we do not store an IP address against it.

We use it to send you that result, and two short follow-up emails over the following week. Then the sequence stops on its own. Every one of those emails carries a one-click unsubscribe link. Using it puts your address on a do-not-email list, which stops every checker email, including for a checker you have not run yet. We keep your address on that list so the block holds, and the page you land on offers an undo.

Retention: we keep the record until you ask us to delete it. Unsubscribing stops the emails but does not delete the record. To delete it at any time, write to hello@costrinity.xyz and we will remove it.

2b. Booking a call or starting an assessment

Booking a call through our booking page, which runs on Cal.com, creates an assessment engagement record. From the booking notice Cal.com sends us, we store the name and email address you entered there, the company name if you gave one, the booking's id and the call time, with the time you booked and, unless it belongs to a free email service, the domain of your email address. Starting an assessment with the form at /engage/start creates the same record from the company, name and email address you type. We use the address to send you the scope agreement and the intake questionnaire, and up to two reminders if the deposit is still unpaid after you accept the agreement. These emails go out from our Google Workspace mailbox, through Google's Gmail service. Cal.com handles the booking itself under its own privacy policy.

If you accept the scope agreement, we also store your company's legal name and address, the name and title you sign with, the exact text you accepted, the time, and your IP address and user agent, as evidence of who accepted it. Answers you submit in the intake questionnaire are stored with the engagement. Each payment for the engagement is requested with a PayPal invoice: we send PayPal the contact name, email address and company name on the engagement, and PayPal emails you the invoice under its own privacy policy. The scope agreement sets out how we handle the material of the engagement itself, and for how long. The engagement record is not deleted automatically.

2. What Data We Collect

Account data
Depending on how you sign in: your email address, a password stored only as a bcrypt hash, the numeric id and username of your GitHub account, or a passkey's credential id and public key. A passkey must verify you, with your fingerprint, your face or a PIN, when you add it and each time you sign in with it. That check happens on your device: from it we receive only a flag saying it was done, never your fingerprint, face or PIN. A sign-in code we email you is stored only as a hash. With GitHub we ask only for read access to your profile, and we do not read your email address from it. When you sign up with a password we also store your name if you give one, and a region and jurisdiction, so the right rules apply. Unless the sign-up request names them (our sign-up form does not), they are worked out from the country our host's network reports for your IP address, or failing that from your browser's language setting. We store the region and jurisdiction, not the country or the IP address. We never store plain-text passwords. A trial account created by the MCP package is described in section 3.
Billing data
Payments by PayPal or card go through PayPal. We never see or store your card details. Checkout in Indian rupees through Razorpay is switched off pending merchant onboarding, so nothing is sent to Razorpay today. We keep a record of each payment: the account email, the plan, the provider's order id (and for PayPal, the payer id), and when the plan ends. A VITNA Desktop licence key is stored with the email it was issued to and the time it was last activated.
SOL payments
You can also pay for a plan in SOL from your own wallet. The payment link we show you carries your owner id as the payment's memo, which is how the payment is matched to your account. The memo, the paying wallet's address, the amount and the transaction signature are public on the Solana chain. Helius, the service that watches our wallet for payments, sees them and reports the payment to us. We keep the transaction signature with the payment record, and the paying wallet's address when a payment could not be applied automatically. No payment alert is sent to any third-party chat. Our application's log lines for a SOL payment carry the paying wallet's address and, when the payment is matched to an account, the account's email address. Separately, when you ask the dashboard to verify a Solana transaction that one of your events names, we send that transaction's signature to Helius to look it up.
Agent events (cloud mode, the default)
In the default cloud mode your agents send events to our API and we store them. This is what you get from the REST API and the MCP package unless you choose local mode or point them at VITNA Desktop. See section 3 for exactly which fields are sent and stored.
Decision and evidence records
When your agent calls a compliance or safety check on a claimed account, we store a signed decision record so it can be exported later as a signed evidence package. Signed decision records are kept indefinitely (section 5). A trial account keeps no signed record: its checks appear as rows on the dashboard timeline, and a held call as a hold record.
Operational metadata
Rate limits, plan caps, and the global trial ceiling are enforced server-side, which means we do hold per-agent request counts and timestamps, and each agent's last-seen time. We are explicit about this because an earlier version of this policy incorrectly said we did not.

3. Exactly What Is Sent and Stored

This section lists what the API, the MCP package (@costrinity/vitna-compliance-mcp) and its guard mode send to us, and what we keep.

Trial setup (MCP package)
With no credentials set, the package's first call to our API creates a trial account. It sends an agent name and an email address. From version 0.5.1 the agent name is vitna-compliance-mcp, unless you set VITNA_AGENT_NAME. Versions before 0.5.1 send your computer's hostname as part of the agent name (vitna-compliance-mcp- followed by your machine's hostname); 0.5.1 and later do not. The email address is a random placeholder, unless you set VITNA_EMAIL. We store both on the account, with a hash and the first 12 characters of the API key we issue. The agent name, including any hostname an earlier version sent, stays on the account and shows on your dashboard until you delete the agent.
Sent with every request
The MCP package sends your API key in request headers and your owner id in the request address (URL). Because it is in the address, the owner id also appears in our host's request logs.
What is sent on a check
Whatever you pass to the tool. For vitna_preflight that is the proposed action text, an optional structured payload, and an optional short action-type label. For the compliance checks it is the fields that check needs, for example purpose and data categories. The identifier tools, such as aadhaar_mask or iban_validate, send the identifier itself; we check it and return the result without storing it.
Guard mode (default)
The guard sends each tool call to our preflight check before the wrapped server runs it. It sends the tool's name and every text value in its arguments, joined and cut at 8,000 characters, plus the full arguments as a structured payload. It sends nothing before the first tool call.
Guard mode with a policy file
With VITNA_GUARD_POLICY set, the guard opens a session as soon as it starts, before any tool call. It sends your policy, the package version, and a coverage list that names the wrapped server and any surfaces you declared unwrapped. The wrapped server is named by VITNA_GUARD_NAME if you set it. Otherwise, from version 0.5.1, it is named by the file name of its command, such as npx, and never by a folder path or one of its arguments. Versions before 0.5.1 name it by its npm package if it has one, otherwise by its command, which can be a file path on your machine; 0.5.1 and later do not send paths. For each tool call it sends the tool's name, the full arguments, the first argument value that is a web address, any metadata your MCP client attaches to the call, and whether the call touched bait. While a call is held, the guard asks for its status every two seconds.
Guard activation note
From October 19, 2026, when guard mode (MCP package 0.5.1 or later) first contacts us, we note on your account that guard mode is in use, which mode (default or with a policy file), and the client version. In default mode the guard adds this to its first checked call each time it starts; with a policy file, each session it opens says the guard opened it. The note has no tool name, arguments, IP address or hostname, and we keep only the first one, with the time we first saw it, until you delete the account. Set VITNA_GUARD_NO_ACTIVATION=1 to stop this; checks still work.
What a check stores
Less than what is sent. A preflight check, which includes every call in default guard mode, stores the action type label, the threat category and the pattern name that matched, the verdict and reason, timestamps, and your owner id. A check whose payload has parts our detectors do not read (see Ingested events) is not allowed, and its record names the category scan_limit and the pattern beyond scan limit. The raw action text and the raw payload are NOT stored. A compliance check stores its verdict and a short label, such as the purpose for a consent check; data principals are referenced by UUID only. On a claimed account this is a signed decision record. Every check made with an API key also adds a row to your dashboard timeline with the verdict and label, and updates the agent's last-seen time. A trial account keeps no signed record, and each check counts against its trial limits.
What a policy session stores
More than a preflight check. The session record stores your policy, the coverage list, the package version, and the IP address and user agent of the request that opened the session, and of the one that closed it. For each call we store the tool name and the web address it targeted, with the decision and reason. That address is cut at 120 characters, and replaced as a whole if our detectors find a secret or personal data in it. On a claimed account they go into a signed decision record, stored with any trace ids your MCP client attached, and a timeline row; on a trial account, into a timeline row only. A session used through the REST API can also send on_behalf_of, a name or email address for the person the agent acted for, and a role. On a claimed account we store them with the trace ids; on_behalf_of is cut at 128 characters and replaced as a whole if our detectors find personal data in it, but detection is heuristic, so a name can be stored as sent.
Holds
A held call stores a hold record, on trial and claimed accounts alike: the tool name and target, up to 400 characters of the call's arguments (with any context sent alongside them), the reason, the deadline, and later the outcome. Secrets and personal data that our detectors recognise are replaced in that excerpt, but detection is heuristic, so the excerpt can still contain personal data.
Alerts
When a call in a policy session is held or blocked, we send an alert to the alert webhook in your notification settings, if you set one, and also to the session's own webhook, if the agent opened the session with one. Only you, signed in to the dashboard, can set or read the alert webhook in your notification settings; an agent's API key can add a session webhook but cannot replace yours. Both kinds carry your owner id, the session id, the tool name, the reason and the threat categories. A hold alert also carries the deadline, a link to your dashboard and the hold's argument excerpt. Neither carries a link that can decide a hold. Whoever runs that webhook address receives them. Hold, bait and rate alert emails are switched off until our product email domain is live. Then a hold email goes only to an account email address that was verified, and carries the action, its argument excerpt and a link to decide it. Bait and rate alert emails go to the account's email address. A bait alert email names the session and the action. A rate alert email names the session and how many holds and blocks it reached within the alert's time window, not any one action.
What an agent's key can read
Asked with an agent's API key, a trial key included, the compliance documents we generate for you (the privacy notice, DPA template, records of processing, SCC Annex II, cross-border notice, DPIA and consent receipts) print a placeholder where your name and contact address go, and readiness reports say whether a grievance officer is set without naming the officer or giving their address. An agent's API key cannot read or regenerate your VITNA Desktop licence key, cannot read or set the email address or webhook an alert rule sends to, and cannot register an address for breach or grievance events or read the address of one you registered. A key can rotate its own agent's key, and only you, signed in, can rotate another agent's. When someone files a grievance with you, an agent's key sees that it was filed, with its status and times, but not its title or description, which hold that person's contact email and what they wrote. An agent's key also cannot weaken the oversight of any agent, its own included: only you, signed in, can change your detection settings, run an erasure, create an agent, delete an agent or its events, delete an alert rule, or raise or remove an agent's limits. A key can only tighten its own agent's limits, and it can act in a policy session only if its own agent opened it.
Ingested events
In cloud mode, the events you POST to the ingest API are stored as sent, including any payload you choose to include, except for what our detectors redact. You control what you put in an event. Before an event is stored, each secret our detectors recognize, and each personal identifier from the set for your account's jurisdiction (such as an Aadhaar or a Social Security number), is replaced with a marker that names what was found, such as [redacted: AWS access key id]. In the event's message only the matching text is replaced and the rest is kept, except that a private key in PEM form is replaced from its BEGIN line to its END line (or to the end of the message when there is no END line); in the payload the whole field is replaced. Text, lists and objects in the payload that lie more than 32 levels deep, after the first 1,000 items of a list, or after the first 10,000 pieces of text in the payload are not read by our detectors, so each is replaced as a whole with [redacted: beyond scan limit]. At most 1,000 such parts in one request, across all its payloads, are replaced where they are; a payload whose parts would go past that is replaced whole instead, with {"value": "[redacted: beyond scan limit]"}. The keys of the objects in the payload are read too, each as a piece of text before its value, and count toward those 10,000. Where a key holds a secret or such an identifier, the object it is in is replaced as a whole with a marker that names what was found, or, for a key at the top level of the payload, the whole payload is. A key after the first 10,000 pieces of text is not read, so it and the keys after it in its object, with their values, are replaced together by one entry, [redacted: beyond scan limit], whose value is how many entries it replaces; if the object already has a key of that name before them, that key's value is replaced by the count. Detection is heuristic and we do not guarantee it catches everything, so do not send material you do not want stored. With storage_mode=local, the API still receives each event, checks it and sends it back without storing it, and it updates the agent's last-seen time. An event that names a data principal (principal_ref) still creates that principal's record if there is none, and the record holds a hash of the reference, not the reference itself.
Wallet tracking (legacy)
A Solana wallet address added to an agent through the wallets API is stored with its label and a history of its balance. To read the balance, our server sends the address to Solana's public RPC service (api.mainnet-beta.solana.com) when it is added, and again each time the agent's dashboard page refreshes it, which is every 30 seconds while that page is open.
Security records
When an API key is refused or has expired, we record the IP address, the user agent, the route and the first 12 characters of the key. Sign-in attempts, sign-ins, account claims, refused requests and rate-limit hits are recorded with the IP address and user agent. Failed sign-ins carry a short hash of the email address, never the address itself. These rows go to the append-only security log, which is kept indefinitely (section 5).
Our host's logs
Our host, Vercel, keeps request logs and our application's log lines for a limited period set by Vercel. Request logs include the address of each request, so they include the owner id the MCP package puts there. Other addresses carry data too: the unsubscribe link in a checker email carries your email address, and a claim link carries the trial account's owner id. Refused keys, failed sign-ins, refused requests and rate-limit hits are also written as application log lines, with the IP address, the owner id when there is one, and for a refused key its first 12 characters.
What we never collect
We do not pipe agent activity into Google Analytics, Mixpanel, Sentry, or any third-party analytics service. We do not build behavioral profiles for advertising, training data, or resale. We do not want your private keys or seed phrases; if you log one, treat it as compromised and rotate it.

4. How We Use Your Data

We use account data to authenticate you, bill the plan you signed up for, reach you about security or material policy updates, send account emails (a welcome, a notice when you reach a plan limit, and a warning before events are purged, which you can unsubscribe from; your licence key after a purchase; and the email an alert rule you set on the dashboard sends when it fires, to the address on that rule), and answer support requests you start. We use agent event and decision data to operate the product for you: running the checks you call, enforcing plan and rate limits, producing your evidence exports, and debugging faults you report. We also count totals, such as active agents and events, for our public stats; those totals name no account. We do not use it to train models, we do not sell it, and we do not share it for advertising.

5. Storage, Retention, and Security

Account credentials and agent data live in a PostgreSQL database (Supabase), encrypted at rest and in transit. Event retention depends on your tier: Free keeps event payloads 7 days; Pro, Team and Enterprise keep them 90 days. A purge job runs once a day and deletes events older than those windows. Each run deletes at most 5,000 rows, so when more than that are past their window, it works through them over the following daily runs, and an event can outlast its window until a run reaches it. It deletes from the events table only, which holds your ingested events and your dashboard timeline.

Everything else is kept indefinitely and is not purged automatically: signed decision records, policy session records with the IP address and user agent that opened and closed them, hold records with their argument excerpts, trace ids, incident records, assessment engagement records (section 2b), wallet addresses with their balance history, and the append-only security log, including refused-key rows with their IP address, user agent and key prefix. Account records stay until you delete the account, and a trial account that is never claimed is not deleted automatically. The application role deliberately holds no delete privilege on the audit tables, so the service that writes the log cannot remove from it; a minimisation purge there is a manual database operation.

Longer or shorter event retention can be agreed per Master Services Agreement. Stating this plainly: no tier below Enterprise retains event payloads for six months, so if you have a six-month logging obligation, do not rely on our hosted retention alone. The way any tier satisfies it is to export the Ed25519-signed evidence package and keep it yourself. Once exported it is a self-contained artifact that does not depend on our retention or on our servers continuing to exist.

6. Local and Desktop Mode

Local mode is the alternative to cloud storage, and it is opt-in, not the default. VITNA Desktop writes events to a SQLite file in the app's data folder on your device, not to our database. Its guard is the MCP package pointed at the app, set up as the app's Guard mode screen shows: VITNA_BASE_URL set to http://127.0.0.1:5757, with the owner id, API key and policy file from that screen. Set up that way, the guard gets its decisions, holds and session bundles from the app on your machine and sends nothing to our servers. Those events, decisions and holds do not reach us, so there is no copy on our side to read, share or delete.

The app does contact our servers in two ways. About 10 seconds after launch, and every 6 hours after that, it checks for updates by fetching a release file from vitna.costrinity.xyz. That request carries no account, key or app version, only the name and version of the update library; like any web request, it reaches our host from your IP address. An update is downloaded from GitHub, and only when you click Update now. If you enter a licence key, the app sends the key to our licensing endpoint to activate it, and again at each launch to check it is still valid; we record when a key was last activated. Signing in to a cloud account is not available inside the app.

One honest limit remains: we cannot sign with VITNA's key what we never receive. The Desktop guard signs each session bundle with a key the app generates on your machine instead, and the bundle says so.

7. Data Sharing

We do not sell, rent, lease, or share your data with any third party for their own purposes, ever. We use a small set of sub-processors to run the service: our database (Supabase), hosting (Vercel) and transactional email (Resend) providers, each of which processes data only to deliver the service to you. If you sign in with GitHub, GitHub confirms your account to us under its own privacy policy. Payments by PayPal or card go through PayPal, under its own privacy policy. Checkout in Indian rupees through Razorpay is switched off pending merchant onboarding, so nothing is sent to Razorpay today; if it is switched on, a Razorpay order would carry your account email, your owner id, the plan and your jurisdiction. If you pay in SOL, Helius reports the payment to us, and no payment alert is sent to any third-party chat (section 2). If you book a call, Cal.com handles the booking under its own privacy policy (section 2b). Assessment engagement emails go out through our Google Workspace mailbox, and engagement invoices through PayPal (section 2b). Alerts go to the webhook addresses you or your agent configure, and whoever runs those addresses receives them. Our public stats show totals across all accounts and name none, and the public live feed shows only our own test accounts. The current sub-processor register is published at /api/compliance/sub-processors.

8. Your Rights

Export
From the dashboard you can download your agents and their most recent events as a JSON file. The dashboard download is JSON only: CSV comes from the events export endpoint, which gives one agent's events as JSON or CSV, and the evidence export endpoint gives signed evidence packages. In VITNA Desktop the export is a local read with no server roundtrip.
Delete
Delete individual agents and their events from the dashboard. Whole-account deletion is not yet a dashboard button: it runs through the account-deletion endpoint while signed in, or email hello@costrinity.xyz and we will delete it within 30 days. Deleting an account removes your events, agents, alerts, incidents, data principals, consent artifacts and sign-in methods. Rows in the append-only security and audit log are kept, with the owner id column that links them to your account cleared. They keep what they recorded, such as action labels, hold excerpts, IP addresses and user agents. That includes one record that still names the account: when a hold was decided on the dashboard, the record of its outcome says who decided it as owner:dashboard followed by your owner id, and that text stays. We keep these rows because a tamper-evident audit log we can silently rewrite would not be an audit log. The record of any VITNA Desktop licence key issued to you is also kept after deletion, with the email address it was issued to.
Correction
There is no self-serve change of an account's email address yet. A trial claimed by email is bound to the address used at claim time. A trial claimed with GitHub or a passkey keeps no email address on the account. To correct an address, email hello@costrinity.xyz and we will action it.
GDPR / CCPA / DPDP
If you are in the EU, California, or India you have the right to access, rectify, erase, and port your data. In cloud mode we hold the data, so contact us and we will action it. In local mode most of these rights are already exercised on your own device. Contact hello@costrinity.xyz.

9. COSTRINITY, All Products

This policy applies to all current and future COSTRINITY products including VITNA (compliance and safety evidence for AI agents), GRiiD (Solana trading primitives, archived), CRYpT (desktop file encryption, archived), and any products we release in the future. The core principle is the same across all of them: your data is yours, we do not sell it, and we do not share it with third parties for their own purposes.

10. Changes to This Policy

If we make material changes to this policy, we will post the change here with an updated date at least 14 days before it takes effect (we do not currently send change notifications by email). The updated date at the top of this page always reflects the last change.

October 6, 2026: section 3 now says that text, lists and objects in an event's payload that lie beyond what our detectors read are replaced as a whole before the event is stored, instead of being stored as sent, and that when more than 1,000 of them do in one request, the payload whose parts go past that is replaced whole. This keeps less of what you send, not more, though a marker can take more bytes than a short part it replaces. It also says that a preflight check whose payload has such parts is not allowed, and what its record then names. It also says that our detectors now read the keys of an event's payload as well as its values, so that a key holding a secret or a personal identifier is replaced, with the object it is in, before the event is stored, instead of being stored as sent.

October 5, 2026: section 3 now says what an agent's API key can read of your account, and what it cannot change. It describes restrictions on what a key can read and do, not a new use of your data. Sections 2, 7 and 8 are also corrected to describe practice already in place, not a new use of your data: paying in SOL, with what Helius sees; that checkout through Razorpay is switched off and nothing is sent to Razorpay; that the dashboard download is JSON, with CSV from the events export endpoint; and that licence records are kept when an account is deleted. Sections 2 and 7 also say that we no longer send SOL payment alerts to any third-party chat. Section 3 also says that a secret or personal identifier our detectors find in an event's message is now replaced before the event is stored, as it already was in the payload. We store less, not more.

October 3, 2026: corrected to describe what guard mode, VITNA Desktop, the API and booking a call already send and keep. It describes practice already in place, not a new use of your data. It also describes what changes with MCP package 0.5.1: it stops sending your hostname in the agent name and file paths in the coverage list, and it adds the guard activation note in section 3, which starts on October 19, 2026 and which you can turn off.

11. Contact

Questions, data requests, or concerns: hello@costrinity.xyz. We aim to respond promptly; statutory data-subject request deadlines are honoured under the applicable regime.

← Back to VITNACold email: how we got your addressTermsDocsDashboard