BV-PRGA — fail-closed DLP frontier between BiVelio services and LLM providers
Reason this release was yanked:
mejora
Project description
bivelio-privacy-gateway (BV-PRGA)
PROPRIETARY AND CONFIDENTIAL — © 2026 BiVelio Inc. All Rights Reserved. This software is the exclusive intellectual property of BiVelio Inc. No license is granted. Copying, distribution, modification, or use without the prior written authorization of BiVelio Inc. is strictly prohibited. BiVelio reserves all patent rights. See LICENSE.
BV-PRGA (BiVelio Privacy Redaction & Gating Algorithm) is a fail-closed data-loss-prevention (DLP) frontier that sits between BiVelio's internal services (Brain, document ingestion, RAG, agents, automations) and any external LLM provider (OpenAI, Anthropic, …). No prompt, tool call, document chunk or embedding reaches a third-party model without passing through it.
It is built to the principle that privacy cannot depend on every developer remembering to call a library: the gateway is the only egress path, it inspects every text-bearing field of the request (including data buried inside tool-call arguments), and anything it cannot inspect is denied — never forwarded.
Why this exists
Off-the-shelf proxies inspect messages[].content and little else. Sensitive
data slips through the gaps: a DNI inside a tool call's JSON arguments, an API
key in tool_use.input, an IBAN in an embeddings request, a secret split across
streaming chunks, an image nobody redacted. BV-PRGA is designed to close those
gaps explicitly and to fail closed when it can't.
| Design rule | How BV-PRGA enforces it |
|---|---|
| No silent passthrough | Unknown endpoint → deny (no catch-all). New endpoint = new adapter + tests. |
| Cover every field | Recursive walk of content, tool-call arguments (parsed as JSON), tool_use.input, embeddings input, metadata, message names. |
| Low false positives | Every structured ID is checksum-gated (DNI mod-23, IBAN mod-97, Luhn, JWT header decode). |
| Secrets ≠ PII | Credentials are blocked and treated as compromised, never pseudonymised. |
| Fail closed | Detector error/timeout → block or route-local, never forward the original. |
| Reversible only inside the perimeter | Pseudonym tokens are per-tenant + per-session, TTL-bounded, restored only on the way back. |
| Auditable, not leaky | Audit events carry entity counts and decisions — never values, tokens or prompts. |
Benchmarks (reproduced from code)
Measured on the deterministic layer (structured identifiers + secrets) over
a seeded, labelled, multilingual corpus with hard negatives. Full methodology
and the honesty caveats (what is not measured) are in
docs/BENCHMARKS.md.
| Metric | Value |
|---|---|
| Micro precision / recall / F1 | 1.000 / 1.000 / 1.000 (4522 entities, 1000 docs) |
| Residual leak rate (values still present after sanitisation) | 0.0000 % |
| Pseudonymisation round-trip fidelity | 100 % (1163/1163) |
| Irreversible-redaction leaks | 0 |
| Throughput (single-thread, pure-Python core) | ~3.0 M chars/s (~6.9 k docs/s) |
Reproduce: make benchmark (JSON) or make benchmark-doc (regenerates the doc).
These are deterministic-layer numbers by design — checksum gating makes near perfect precision/recall achievable for IDs and secrets. Free-text PII (names/addresses) is delegated to the optional NLP layer and is not claimed at 100 %. We do not overclaim.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ BiVelio services │
│ Brain · document ingestion · RAG · agents · automations │
└──────────────────────────────┬──────────────────────────────┘
│ normalised internal contract
┌──────────────────────────────▼──────────────────────────────┐
│ BIVELIO PRIVACY GATEWAY (BV-PRGA) │
│ 1. endpoint + schema validator (unknown → deny) │
│ 2. protocol adapter (OpenAI Chat / Responses / Anthropic) │
│ 3. recursive field walk (tool args, tool_use.input, ...) │
│ 4. deterministic detectors (regex + checksum) │
│ 5. optional NLP/NER layer (Presidio, local models) │
│ 6. secret / credential detector │
│ 7. per-tenant confidential dictionaries │
│ 8. policy engine (block / redact / pseudonymize / local) │
│ 9. token vault (per tenant+session, TTL, encrypted) │
│ 10. value-free audit + synthetic canaries │
└──────────────┬────────────────┬────────────────┬────────────┘
FORWARD│ ROUTE_LOCAL│ DENY│
┌──────▼──────┐ ┌────────▼─────┐ ┌─────▼──────┐
│ LiteLLM │ │ local model │ │ 403 + audit│
│ (router) │ └──────────────┘ │ security │
└──────┬──────┘ │ event │
OpenAI / Anthropic / … └────────────┘
LiteLLM is used after BV-PRGA, purely as a provider router — never as the
privacy boundary. See docs/ARCHITECTURE.md.
The four detection layers
- Structured identifiers — regex gated on checksums: Spanish DNI/NIE/NIF/CIF, IBAN (ES/AD/FR…, ISO 7064 mod-97), credit cards (Luhn), phones (ES/AD), email, IPv4.
- Contextual PII (optional
[nlp]) — Presidio + local spaCy/GLiNER for names, addresses, locations in es/ca/fr/en. - Secrets & credentials — provider keys (OpenAI/Anthropic), AWS, GCP, GitHub, Slack, Stripe, JWT (header-validated), PEM private keys, bearer tokens, connection strings, basic-auth URLs.
- Tenant confidential — per-tenant dictionaries for codenames, unannounced clients, internal labels — the sensitive data no generic model knows about.
Field coverage matrix
| Endpoint | Inspected surfaces |
|---|---|
POST /v1/chat/completions |
messages[].content (string + vision blocks), messages[].name, tool_calls[].function.arguments (JSON, recursive), function_call.arguments, tools[] descriptions, user, metadata |
POST /v1/responses |
instructions, input[] (recursive: content blocks, function args, tool outputs), user, metadata, tools[] |
POST /v1/messages (Anthropic) |
system (string + blocks), text, thinking/redacted_thinking, tool_use.input (recursive), tool_result.content, tools[], metadata |
POST /v1/embeddings |
input (string or list), user |
| any other path | denied — add an adapter + tests to support it |
Image / audio / file blocks are reported as unsupported and denied under the fail-closed policy (they must be processed locally first).
Quickstart
The core has zero third-party dependencies. Extras are opt-in.
# core only (detection, redaction, policy, adapters, pipeline, benchmark, CLI)
pip install -e .
# with the HTTP server / NLP / YAML / crypto extras as needed
pip install -e '.[server]' # FastAPI proxy
pip install -e '.[nlp]' # Presidio contextual PII
pip install -e '.[dev]' # pytest + pyyaml (tests & benchmark)
CLI
# scan text (exit code 3 if the request would be blocked)
echo "DNI 12345678Z, IBAN ES9121000418450200051332, key sk-ant-api03-…" | bpg scan
bpg scan --json report.txt # machine-readable
bpg benchmark --markdown # reproduce the benchmark
bpg policy config/policy.example.yaml # show the effective policy
bpg serve --policy config/policy.example.yaml # run the gateway (needs [server])
Python API
from bivelio_privacy_gateway.gateway.pipeline import Sanitizer
from bivelio_privacy_gateway.policy.engine import Policy
sanitizer = Sanitizer(Policy.default())
outcome = sanitizer.sanitize_request(
"/v1/chat/completions",
{"model": "gpt-4o", "messages": [
{"role": "user", "content": "Mi DNI es 12345678Z y mail ana@bivelio.com"}]},
tenant="acme", session="conv-42", request_id="req-1",
)
outcome.decision # "forward" | "route_local" | "deny"
outcome.body # sanitised payload (safe to forward to LiteLLM)
outcome.audit.by_type # {"SPANISH_DNI": 1, "EMAIL": 1} -- counts, no values
# on the way back, restore reversible tokens inside the perimeter
reply = sanitizer.restore_response(provider_text, tenant="acme", session="conv-42")
Docker
docker compose up --build # gateway + LiteLLM router (see docker-compose.yml)
Network egress control (mandatory)
Application-level inspection is necessary but not sufficient. At the infrastructure layer:
- BiVelio services have no direct outbound internet access.
- Only the gateway may reach provider domains / the LiteLLM router.
- LiteLLM accepts traffic only from the gateway.
- Provider credentials live only in the gateway / router, never in Brain.
This makes it technically impossible for a new SDK, script or dependency to call
a provider directly and bypass BV-PRGA. See docs/THREAT_MODEL.md.
Policy
Policies are declarative (defaults in code, overridable via YAML). Example:
mode: fail_closed
unknown_endpoint: deny
unsupported_content: deny
actions:
ANTHROPIC_API_KEY: block
PRIVATE_KEY: block
CREDIT_CARD: redact
EMAIL: pseudonymize
INTERNAL_CONFIDENTIAL: route_local
detectors:
pii: { engine: presidio, enabled: false, languages: [es, ca, fr, en] }
tenant_dictionaries:
terms: { INTERNAL_CONFIDENTIAL: ["Proyecto Aurora"] }
storage:
token_vault: { ttl_seconds: 900 }
Full action table and rationale in docs/POLICY.md.
Project layout
src/bivelio_privacy_gateway/
├── detectors/ checksums, structured IDs, secrets, tenant dicts, engine, presidio
├── redaction/ token vault (scoped/TTL) + transformer (redact/pseudonymize/block)
├── policy/ declarative entity→action engine
├── adapters/ recursive walker + OpenAI/Anthropic/embeddings + registry
├── audit/ value-free events + synthetic canaries
├── gateway/ fail-closed pipeline + FastAPI app + streaming restorer
├── benchmark/ seeded corpus + runner + markdown report
└── cli.py bpg scan | benchmark | policy | serve
licensing/ BV-LIC: model, token codec, keys, verifier, enforcement, issuer
services/ CP-0 control plane (Hetzner side): common · licensing · metering
apps/web/ privacy.bivelio.com marketing site (Next.js → Vercel)
deploy/ control-plane Dockerfiles · compose · Keycloak realm notes
tests/ 74 tests across every layer (gateway + CP-0)
docs/ ARCHITECTURE · THREAT_MODEL · POLICY · BENCHMARKS · LICENSING ·
ROADMAP · COMMERCIALIZATION-PLAN · CONTROL-PLANE · DEPLOYMENT-TOPOLOGY
Development
make install # editable install with dev extras
make test # pytest (53 tests)
make benchmark # JSON benchmark
make lint # ruff (if installed)
Roadmap
- Presidio contextual-PII layer integrated (multilingual es/ca/fr/en) and
evaluated — oracle recall 0.99 / auto F1 0.94, combined residual leak
~3 %. See
docs/BENCHMARKS.md. Next: evaluate on a real internal corpus and tune thresholds/allowlists. - Output-side DLP (scan tool outputs / generated URLs before they reach tools).
- Clustered, encrypted vault backend.
- NeMo Guardrails integration inside Brain/RAG (retrieval + execution + output rails).
- Batch/Files/Vector-store adapters (currently denied).
Commercial model — BV-LIC
BV-PRGA is monetised as a self-hosted product: the gateway runs on the customer's infrastructure (their data never leaves their perimeter), and a signed BV-LIC license key unlocks paid capabilities. Key properties:
- Offline-verifiable Ed25519 licenses (work air-gapped); the customer embeds only BiVelio's public key.
- Fail-closed-safe enforcement: an expired/invalid/missing license degrades to Community (commercial features off) but never disables DLP protection.
- Privacy-safe metering: the value-free audit events (counts + decisions +
license_id/tier, never content) are exactly what BiVelio's control plane ingests for usage-based billing — no sensitive data reaches BiVelio.
bpg license verify "$BPG_LICENSE_TOKEN" --tenant acme # customer side
python scripts/bvlic_issue.py issue ... # BiVelio control plane
Data plane = customer infra. Control plane (licensing + metering + updates) =
BiVelio Hetzner (shared Keycloak / Hyperswitch / Qdrant / Postgres). Full design
in docs/COMMERCIALIZATION-PLAN.md and
docs/LICENSING.md.
License
Proprietary. © 2026 BiVelio Inc. All rights reserved. The BV-PRGA algorithm and
all related inventions are the property of BiVelio Inc., which reserves all
patent rights. See LICENSE and NOTICE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bivelio_privacy_gateway-0.1.1.tar.gz.
File metadata
- Download URL: bivelio_privacy_gateway-0.1.1.tar.gz
- Upload date:
- Size: 136.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4b28e6d8fa420df35914f2637e7c0fbf7a39f9e4f3a8b09f7e3fcfda92aa7f0
|
|
| MD5 |
b5bce26b1b982d87c55a715ca84f8354
|
|
| BLAKE2b-256 |
3c834a9eb059afcfd730d813a49fac097564ecdf5514ff70f366a7fca85f548c
|
Provenance
The following attestation bundles were made for bivelio_privacy_gateway-0.1.1.tar.gz:
Publisher:
publish.yml on BiVelio/bivelio-privacy-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bivelio_privacy_gateway-0.1.1.tar.gz -
Subject digest:
f4b28e6d8fa420df35914f2637e7c0fbf7a39f9e4f3a8b09f7e3fcfda92aa7f0 - Sigstore transparency entry: 2212786482
- Sigstore integration time:
-
Permalink:
BiVelio/bivelio-privacy-gateway@e5423895926d7993ef27705344b6772244499c98 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/BiVelio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e5423895926d7993ef27705344b6772244499c98 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bivelio_privacy_gateway-0.1.1-py3-none-any.whl.
File metadata
- Download URL: bivelio_privacy_gateway-0.1.1-py3-none-any.whl
- Upload date:
- Size: 121.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0b39352e047e7749093f3c390d4c41a1495fc8543e27205dfcca46e77876294
|
|
| MD5 |
de5f3bdd9354678bce23ca215fbdd277
|
|
| BLAKE2b-256 |
1d02e77e83ca749ad3c02f712a41bc35bb0cf1d01d8096909fb0b416ba6f21dd
|
Provenance
The following attestation bundles were made for bivelio_privacy_gateway-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on BiVelio/bivelio-privacy-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bivelio_privacy_gateway-0.1.1-py3-none-any.whl -
Subject digest:
b0b39352e047e7749093f3c390d4c41a1495fc8543e27205dfcca46e77876294 - Sigstore transparency entry: 2212786586
- Sigstore integration time:
-
Permalink:
BiVelio/bivelio-privacy-gateway@e5423895926d7993ef27705344b6772244499c98 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/BiVelio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e5423895926d7993ef27705344b6772244499c98 -
Trigger Event:
push
-
Statement type: