The parts that touch personal data were built to be audited.
Veil processes the most sensitive material an organisation holds, on behalf of a request it is legally obliged to answer. This page is what a security review usually has to extract over three calls.
Data residency
Everything stays in the European Union.
There is no region setting to get wrong, because there is only one region. Each component below is pinned, not merely defaulted.
Database and authentication
Frankfurt
Row-level isolation per organisation
Object storage
Frankfurt
Private buckets, no public objects
Processing workers
Frankfurt
No public ingress beyond a health check
Web functions
Frankfurt
Pinned at the deployment level
Model inference
European provider
No case, document or account identifier goes with the content
Encryption and purge
A purge destroys the key, not just the rows.
The personal data densest in identifiers is encrypted under a key belonging to your case, and that key is itself wrapped by a key belonging to your organisation.
Encrypted before it is stored
AES-256-GCM, applied on our servers before the data reaches the database. The keys never reach the browser. Decryption happens on our servers in Frankfurt, in the component that processes documents and in the web application's server functions, and the only decrypted content the browser receives is the short excerpt around an entity that a reviewer opens on the review screen, after the server has checked they may see it. None of it reaches a log.
What stays readable, and why
Five things are not encrypted under the case key. The display name of each entity the system finds, which is the fullest spelling of that name, email address or identifier exactly as it appeared in your documents: the review screen shows it so that a reviewer can tell who is who across documents, and encrypting it under the case key is planned but not yet done. The normalised form of a name or identifier, which is what lets the system recognise two spellings as the same person: encrypting it would break that matching or leak the same information anyway, and it is a folded, lower-case form rather than the text as it appeared. The identifiers you declare for the data subject, which detection matches against. The external reference you can give a case to tie it to your own request tracker, which identifies a person if your tracker puts one in it. And the names of the files in a case and of any connected folder they came from. All five are held by our database provider, Supabase, in Frankfurt. Each is covered by every other control on this page, but we would rather say so than let you assume otherwise.
Crypto-shredding
When a case purges, the case key is destroyed along with the rows. Everything encrypted under that key is unreadable from that moment, wherever a copy of it survives, including in a backup. The five things above are deleted with the rows rather than shredded, so a backup taken before the purge still holds them for as long as that backup can be restored, which is seven days. The originals, the generated documents and the bundles are deleted outright.
Encryption in transit
TLS on every hop, including the internal call from the web tier to the component that processes documents, which is authenticated in its own right.
Retention
Cases expire on a clock you set.
Retention is a plan-capped setting, not a support ticket. A released case purges on schedule and leaves an accountability record with no personal data in it.
- Default retention after release
- 30 days
- Maximum retention
- Up to 90 days by plan
- Unreleased cases
- Purged at 180 days, with warnings first
- What the purge removes
- Objects, extractions, entity mentions, the case key
- What the purge leaves
- A tombstone: reference, dates, counts, quality summary
Access control
Nothing is listable, and nothing is long-lived.
Signed URLs only
Storage is never browsable and holds no public object. Each file is reached through a short-lived link to that one object, issued by a server route that re-checks membership and role at the moment of issue.
Row-level isolation
Every tenant table carries the organisation id and a row-level security policy. Cross-organisation reads are refused by the database, not by application code.
Roles and multi-factor
Owner, admin, member and viewer, with multi-factor authentication available on every plan.
Logging and audit
Logs carry counts. Never content.
No personal data in logs
Loggers accept identifiers, counts, enumerations and durations, and nothing else. The property is enforced automatically on every change rather than remembered by whoever writes the line.
Model calls logged as arithmetic
An inference call is recorded as counts and durations. The prompt, the completion and any recognised text are never written to a log.
Append-only audit trail
State transitions, entity decisions, bundle downloads, each opening of the unredacted excerpts a reviewer reads around an entity, and settings changes are appended through a single writer and cannot be edited afterwards. Each entry is deleted six years after it is made.
Product integrity
The check that clears a document is not the thing that redacted it.
Verification is independent
Every generated document is checked by a component built and run separately from the redaction itself, so a mistake in the redaction cannot pass its own check. The separation is enforced automatically in our build, not maintained by convention.
Nothing uncleared ships
A document the verification cannot clear is withheld from the bundle rather than released with a warning attached, and the case page flags it to whoever releases the case. Withholding one document does not cost you the rest of the bundle.
Hostile input parsing
Archive, email and office document parsers are treated as an attack surface: guards against malicious archives, per-job memory and time budgets, and fuzzing in continuous integration.
Constrained egress
The component that handles document content has no general outbound network access. It reaches an explicitly allowed set of destinations and nothing else, extended only by a connector your organisation chooses to enable.
Quality gated in CI
Every change that could affect detection quality is measured against a labelled corpus before it can ship. A change that finds fewer of the planted third parties, or that starts removing the data subject, does not merge.
If something goes wrong
The clock is in the contract, and it starts before you ask.
Everything above this section is about prevention. This is what we owe you when prevention has failed, and none of it is new here: each point restates a clause you already signed, linked underneath so you can read the binding version rather than our summary of it.
The clock is contractual
Clause 6.1 of the Data processing agreement commits us to notifying you without undue delay, and in any event within 48 hours, after becoming aware of a personal data breach affecting your personal data. It is a term of the agreement rather than a service target, and it runs whether or not you have asked. Clause A2.7 commits us to a written procedure behind it, which is where the moment awareness begins is defined and recorded, so the start of the clock is a fact in a record rather than somebody's recollection of a weekend.
A suspicion starts it, not a confirmation
Clause 6.4 is the trigger this product specifically has. If the independent verification finds a surface we had decided to redact in a bundle you have already released, we treat that as a suspected personal data breach and notify you under clause 6.1, rather than waiting until we know how far it went. The same finding before release is the ordinary path and not a breach: the document is withheld from the bundle, which is what the section above this one describes.
You decide, we supply
Notifying a supervisory authority or the affected data subjects is your decision as controller, and clause 6.3 leaves it there. Our job is what clause 6.2 sets out: the nature of the breach, the categories and approximate numbers of data subjects and records concerned, the likely consequences, and the measures taken or proposed, given to you in phases if phasing is the only way to get you the first part while you can still act on it.
How to reach us out of hours
One address, and it is the same one in every document we publish: security@pritect.ai. The Coordinated disclosure policy says what to put in a report and what we do with it. Clause 5.1 of the Acceptable use policy already routes a released bundle that still carries somebody else's personal data to that address as a priority one incident. And clause 4.4 of the Coordinated disclosure policy says plainly that where a report shows customer personal data has been exposed, the clock in the first point above runs on its own, independently of anything else happening with the report.
Sub-processors
Who else touches the data.
The complete list. The authoritative version, with the transfer position and the notice period for changes, is the sub-processor list in the trust centre.
Supabase
Database, authentication and object storage
Frankfurt, EU
Fly.io
Document processing workers
Frankfurt, EU
Vercel
Web application hosting. Its server functions decrypt the short excerpts a reviewer opens on the review screen
Frankfurt, EU
Mistral AI
Entity detection and optical character recognition
EU
Stripe
Billing. Never receives document content
EU
Resend
Account email: sign-in links, password resets, invitations and service notices. Never receives document content
EU West 1, EU
Analytics on the public pages only, after you accept the analytics category. Never receives document content, and nothing at all from behind sign-in
Global, including the United States, under Standard Contractual Clauses
Your next access request does not have to eat a week.
Open a case, declare the subject, drop the documents in. Veil redacts, raises what it is not sure of, and shows you its working.