Deployment
ReceiptDB is a layer on the PostgreSQL you already operate, not a hosted service. A stateless API runs in your cloud, on Kubernetes with the Helm chart or on Docker, in front of PostgreSQL 16 or 17 with pgvector: self-managed, Amazon RDS, Cloud SQL or Azure Database for PostgreSQL. Records, vectors, the lineage graph and the audit log are ordinary tables, so your existing backups, monitoring and access controls apply.
What leaves your network
Nothing, unless a setting names a destination. Each outbound call is an integration you switch on, and receipt config check shows which are set:
- A model you choose, for answers, grounding checks or the model scanner. Search, explain, lineage, retraction and erasure never call a model, and a local model keeps it in your network.
- An embedding endpoint, when you configure a hosted embedder.
- Scanners you enable, such as Lakera Guard or your own HTTP classifier; never a source whose egress labels don't allow that destination.
- Connectors Enterprise reading the content sources you name.
- Your KMS Enterprise, to unwrap the master key at start.
- Your SIEM, webhooks and tracing: Splunk, OpenTelemetry or syslog; signed webhooks; OTLP spans.
- Your privacy and lineage platforms: OneTrust, Transcend, OpenLineage.
- Answer spans to Langfuse or Phoenix, when you name one.
Your frameworks' own settings are yours: Haystack sends usage statistics to its makers when a pipeline runs (the first run, then at most once a minute per pipeline), with ReceiptDB's document store in it or not, unless HAYSTACK_TELEMETRY_ENABLED=False is set before Haystack is imported. ReceiptDB doesn't change another library's setting.
Data protection
Labels that fail closed
Every record carries labels: trust, licence, readers, data subjects, personal data, egress and validity. Labels flow down the lineage graph, so a derived record is never more trusted, or less restricted, than its riskiest input. Content without labels is treated as untrusted and restricted, and permissions a connector can't map deny access.
Access that follows the data
Every search is access-checked. A summary or an answer is never readable by someone who couldn't read its sources, and revoking a group's access to a source revokes it on everything built from it, in one transaction.
Egress control
Label where content may be sent, such as "local only" or "Anthropic EU". Search enforces it for the model reading the results, and answers record where their sources went.
Erasure
Erasure reaches every chunk, vector, memory and answer derived from a person's data and either completes everywhere or changes nothing. What it keeps of a person, a document or its content is an unreadable fingerprint, keyed with a secret you hold outside the database, so a stolen copy can't confirm who was erased. The certificate can be checked against the database afterwards by an independent verifier.
Crypto-shredding Enterprise
Text about each person is encrypted with its own key, under a master key held in AWS KMS, Google Cloud KMS or Azure Key Vault. Erasing a person destroys their key, so their text can't be read back from the live database, nor from a restored backup when the key store lives on a separate instance; seal the vectors too, and so do their embeddings.
Suspect content
Scanners hold flagged sources and their derivatives out of retrieval until someone reviews them, and each scanner's verdict stays on the record. A personal-data detector flags what a writer never declared, built in or with Microsoft Presidio; it only tightens labels and never stores what it matched.
Identity and access
- Single sign-on and provisioning Enterprise: SSO over OIDC and SCIM from Okta or Entra ID. Users always search as themselves, and each tenant has its own directory.
- Groups from your authorization engine Enterprise: SpiceDB or OpenFGA.
- Permissions as fresh as the source Enterprise: connectors follow Google Drive and SharePoint as they change, so a revoked share is applied about a minute after the source reports it; the optional live check reads a document's permissions at the source again before it's returned, and leaves it out if the source can't answer.
- Scoped API keys and tenants Enterprise: keys scoped to what they may do, and tenants you can disable or remove.
Audit and integrity
- A receipt for every answer: question, asker, model, time and lineage to every source, exportable for a regulator. Your reviewers check any receipt themselves:
receipt verify-receiptre-hashes the answer against the database, down to every source it names, and names the reason when a record was erased or sealed, the answer isn't in the ledger, or a source was moved to another URI. - A tamper-evident log Enterprise: every lifecycle change in a hash-chained log, with signed exports and certificates. Signed checkpoints kept outside the database make a rewritten or truncated log detectable, even to someone with database access.
- Legal holds: hold a document or a person, and everything derived from them is kept through erasure and retention, out of search and answers, until release. Certificates list what was held back and why.
- Compliance reports Enterprise: EU AI Act and FINRA templates built from the same records. See a sample: EU AI Act · FINRA.
ReceiptDB gives you the evidence; how you use it determines compliance.
Supply chain
Every release image ships with a software bill of materials and SLSA build provenance, for your supply-chain review.
Every change is checked before it merges: Semgrep for the code and gitleaks for secrets, and every dependency change goes through pip-audit and Trivy, which scans each image and refuses a fixable high-severity flaw.
Operations
- Bounded under load: timeouts on every request, a separate ceiling for retractions and erasures, per-caller rate limits, a throttle on failed authentication, and an overloaded API tells clients when to retry.
- Keys rotated with zero downtime: the outgoing API key keeps working beside the new one for a window you set, up to a week, so every client moves over on its own schedule.
- Recovers on its own: after a database outage or failover, each API replica serves again within about a second of the database accepting connections; requests in the gap get a 503 with a time to retry.
- All or nothing, under faults: every retraction, supersession, quarantine, release, relabel and erasure applies whole or not at all, even with its connection cut before or after the commit, behind PgBouncer in either mode; once it reports success, it has applied.
- Behind your pooler: direct connections or PgBouncer in session or transaction mode, with tenants isolated through the pooler.
- Observable: structured JSON logs with a request ID on every line, Prometheus metrics, and OpenTelemetry traces down to each database statement.
- Upgrades: numbered migrations run once, across every tenant, with no locks on a restart, from any earlier release.
- Runbooks, drilled: fourteen runbooks, one per failure, each drilled against the real failure it describes; the alerts that raise them link straight to the page.
- Support without exposure: one command writes a support bundle of versions, settings, health and recent warnings, with no record content or secrets in it.
- A licence that never holds data hostage: after expiry there's a grace period; after that, only new Enterprise features stop. Reads, decryption, erasure and access to every tenant keep working.
Reporting a vulnerability
Write to hello@counterfoillabs.com (also in security.txt). Start your review with our threat model: every trust boundary, STRIDE over each, and the AI-specific threats, from prompt injection to a malicious tenant, with each control mapped to the code and tests that hold it; ask for it. We also answer security review questionnaires: ask for one.