Skip to content

Data protection

Detection modes, the 60-detector library, entity detection and its selectable models, security scanning, the model notice, and retention.

Data protection runs on every request before dispatch. The default mode is tokenize: every detected value is swapped for a stable typed token like «EMAIL_1». Detected values reach the provider only as tokens, and the response is restored to the real values on its way back to you, streamed or not. The token map lives in memory for the life of the request and is never persisted. Pseudonymization is one way: it protects what you send out. In Sluis Workspace, public web search results and the model's own output from earlier in the same turn are not newly tokenized; a value the conversation already tokenized stays replaced by its token, and the audit log records when this applied.

# tokenize mode (the default): what you send
curl https://api.sluis.ai/v1/chat/completions \
  -H "Authorization: Bearer $SLUIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "sluis/auto", "messages": [{ "role": "user",
        "content": "Mail j.devries@acme.nl that IBAN NL91ABNA0417164300 is active." }] }'

Other modes: mask rewrites detected values irreversibly, block refuses the request with 422, and allow_log passes it through while flagging the audit row.

Data protection: configure scanning and pseudonymization.
Data protection: configure scanning and pseudonymization.English interface · illustrative demo data. Open the image for full size.

60 built-in detectors ship out of the box: 28 for personal data, from the US Social Security number to a national-ID pack that checksum-validates 12 EU countries, and 32 for secrets and credentials. Each one can be toggled per organisation, and custom terms (plain or regex) cover anything specific to your business:

Personal data · 28EmailPhone numberIBANCredit cardIPv4 addressIPv6 addressMAC addressUS Social Security numberDutch BSNPortuguese NIFGerman Steuer-IDPolish PESELBelgian rijksregisternummerFrench NIR (INSEE)Spanish DNI/NIEItalian codice fiscaleSwedish personnummerDanish CPR numberFinnish henkilötunnusUK National Insurance numberEU VAT numberBIC/SWIFT codeDutch license plateDutch addressPassport numberDate of birthGPS coordinatesVehicle identification number
Secrets & credentials · 32API key (generic)AWS access keyAWS secret access keyPrivate key (PEM)GitHub tokenGitLab tokenSlack tokenSlack webhook URLDiscord webhook URLGoogle API keyGoogle OAuth refresh tokenStripe keyMollie API keyAnthropic API keyOpenAI API keySluis keyHugging Face tokennpm tokenSendGrid keyTwilio keyShopify tokenVault tokenDatabricks tokenDocker Hub tokenTelegram bot tokenJSON Web TokenCredentials in URL.env file dumpAzure storage key / SASPassword assignmentConfidentiality markerHigh-entropy token (generic)

Entity detection

Persons, organizations and locations are hard to catch by pattern alone. Sluis combines context heuristics, email correlation, a tenant name directory, shipped dictionaries and optional NER. The NER model runs as a network-internal sidecar: text stays inside the deployment perimeter. These layers also inspect extracted document and OCR text when document protection is enabled. With NER on, one request may name up to 100,000 distinct entities; past that ceiling the scan counts as incomplete. A name the model detects once is replaced wherever it recurs in the request, as the same whole word with the same casing and the same token, including messages where the model did not report it. Lone generic words and short acronyms only cover the place the model reported.

The name dictionary is the deterministic counterpart to NER: given names and surnames compiled from government open data into a compiled dictionary that ships inside the gateway. It matches full names and honorific-anchored names with no added latency and nothing leaving your perimeter. Names that are also ordinary words are only matched with name-shaped context around them, so rare names remain the job of the directory or NER.

NER model options

Choose Basic, Expanded or Deep in Data protection. Basic uses built-in detectors and six deterministic name layers without a model call; it is the default for new organisations. Expanded adds Swift (spaCy); Deep adds GLiNER2-PII instead. Both model profiles require complete inspection and block model failures or incomplete scans. Deep costs more processing time, not a guarantee of higher recall. Custom allows individual tuning. Existing policies, exclusions, directories and workload overrides remain unchanged; unknown-word detection stays off in all three profiles. A workload cannot enable NER when the organisation has it off. AI name recognition is billed once per customer request it inspects: €0.005 with Swift (Expanded), €0.01 with GLiNER2 (Deep); Basic is included. Follow-up calls Sluis makes within that request are not billed again, and an incomplete inspection costs nothing. Each charge is a linked audit receipt that counts toward your budgets.

Deep adds substantial latency before your chosen model starts generating a response. Swift and GLiNER2 scan time depends on input length, message count and hardware. The deadline covers the total NER scan across all messages, attachments and windows in one request, not each window: 30 seconds for up to 320,000 characters, plus 30 seconds per further 320,000 characters, at most 10 minutes. It is a maximum, not typical latency. Optional hosted LLM inspection adds a separate wait before response generation, depending on input length, provider load and retries; it is outside this NER deadline.

Name detection: configure person-name detection and the NER model.
Name detection: configure person-name detection and the NER model.English interface · illustrative demo data. Open the image for full size.
ModelCoverageMeasured accuracyLatency
swift · spaCy xx_ent_wiki_smmultilingual, basicall-entity F1 0.58 · person F1 0.72 · recall ~0.533.5 ms p50 (CPU, 919 chars, 30 runs)
deep · GLiNER2-PII (mDeBERTa-v3, Apache-2.0)7 trained languages (EN, FR, ES, DE, IT, PT, NL) + multilingual backbone transferall-entity F1 0.61 · person F1 0.76 · recall ~0.70521.5 ms p50 (CPU, 919 chars, 30 runs)

Measured 2026-08-12 on an internal benchmark: WikiANN test sentences in six languages (NL, EN, DE, FR, ES, IT; 150 per language), scored as micro-F1 over (label, text) pairs at text level with the production false-positive filter applied, on an Apple-silicon dev machine at FP32. WikiANN is Wikipedia-domain, silver-standard data and spaCy's home turf, so read the numbers as relative guidance between the tiers, not absolute field accuracy.

Security scanning

Opt-in prompt-injection and jailbreak detection at the gate, scanned before dispatch. Three modes: off | log | block. off skips the scan. log records findings without blocking traffic. block refuses detected attacks and fails closed when Prompt Guard is unavailable or classification fails or is incomplete. No automatic model fallback.

Security always uses Llama Prompt Guard 2 86M (sluis/prompt-guard-2-86m), inside Sluis without external transfer of scan text. EUR 0.01 per completed logical scan, once regardless of windows or verdict, including sampled-safe results; no token surcharge. Off, preflight refusals and technical failures are not charged. Overlapping windows of at most 512 model tokens preserve segment boundaries, within the configured total scan budget of 4096 to 65536 tokens. The fixed detection threshold is 0.8. Scanning follows data protection, which can retain personal data when off or logging-only. Scans add latency and have bounded deadlines. Long inputs use selected excerpts; a safe result covers only inspected text, not the full input. Audit records inspected and total bytes. Built with Llama. Meta Llama 3.1 Community License.

Each scan has a separate, linked billable audit entry: security.scan. Charges can still apply when the parent request is blocked or served from cache. Workload overrides can change the scan mode. Separately, optional Nemotron privacy inspection uses Nebul under your residency policy and is token-priced.

Separately, opt-in key-behaviour anomaly detection runs as a background job with zero request latency: per-key baselines from robust statistics with hour-of-week seasonality, plus a multivariate isolation-forest layer. Alerts are explainable, never a bare score, and land in the Console's Security view, optionally by email.

Security: configure prompt-injection scanning.
Security: configure prompt-injection scanning.English interface · illustrative demo data. Open the image for full size.

Model notice

When tokenization rewrote a request, Sluis injects a leading system message telling the model the «…» tokens are opaque placeholders it must keep intact; that is what keeps the restore reliable. On by default; customise or disable it per organisation.

Retention & audit fidelity

Content retention (request and response bodies for the audit log) is on by default and encrypted at rest; audit fidelity chooses whether retained content stores the tokens or the original values. Retained content is kept until you erase it, unless you set a retention period in days in the Console's Data protection view. A daily purge applies the current period to content already stored, so shortening it also removes older content. Content from Sluis Workspace chats is deleted after the shorter of that period and the Workspace period for personal values in chats (7 days by default). The audit metadata ledger is kept and never altered. Turn retention off for a metadata-only ledger; that also disables the response cache.

Retention: choose whether request content is stored.
Retention: choose whether request content is stored.English interface · illustrative demo data. Open the image for full size.

Document anonymization

Send a docx, pdf, image, or text file to POST /v1/documents/anonymize and the same document comes back with PII and secrets replaced by merge tags like «PERSON_NAME_1» in text, and blurred out of images and PDF pages. Processing is local to the gateway, OCR included; the operation is sealed in the audit chain and metered per page/image. The token mapping is returned only when you ask for it and never stored. Redacted PDFs keep an invisible searchable text layer built from the anonymized text. For large documents, enqueue an async job and collect the result later via a time-limited signed URL. On scans, lines the OCR cannot read reliably, such as signatures and illegible handwriting, and ink outside every recognised text line, such as initials and stamps, are destroyed rather than guessed at. They read «UNREADABLE» in the text layer, and the response reports the UNREADABLE_REDACTED category.

The same protection works in transit: with the dlp_documents policy on, files uploaded through /v1/files and inline OCR documents are anonymized before they leave toward a provider, refused under block, and scanned under allow_log.

Playground Documents: upload a document for anonymization.
Playground Documents: upload a document for anonymization.English interface · illustrative demo data. Open the image for full size.
# enqueue a large document (202 + job id; Idempotency-Key honoured)
curl https://api.sluis.ai/v1/documents/anonymize/jobs \
  -H "Authorization: Bearer $SLUIS_KEY" \
  -F file=@archive.pdf

# poll until succeeded; the signed download_url then needs no API key
curl https://api.sluis.ai/v1/documents/anonymize/jobs/9c31… \
  -H "Authorization: Bearer $SLUIS_KEY"

Embeddings

Pseudonymized tokens are stable within one request, not across requests, so embeddings of tokenized text may not match between calls. The dlp_embeddings policy setting controls whether the scan covers /v1/embeddings: it is on by default, and setting it to off sends embedding inputs to the provider unscanned. Every exempted call is recorded in the audit trail.

Per-request removal terms

Any JSON request on the data plane — chat completions, completions, embeddings, responses, and the native Anthropic ingresses — may carry a top-level sluis extension. Its remove list names the terms the gateway must remove from the prompt before dispatch: a bare string, or an object with a text and a kind out of person | organization | location | term. At most 128 entries, each non-empty after trimming and at most 256 characters; matching is word-boundary and case-insensitive. The extension itself is a gateway construct and is always stripped before dispatch: it never reaches a provider, the cache, or retained content.

# name the terms the gateway must remove — the top-level "sluis" object never leaves the gateway
curl https://api.sluis.ai/v1/chat/completions \
  -H "Authorization: Bearer $SLUIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "mistral/mistral-large-latest",
        "messages": [{ "role": "user",
          "content": "Bas Alderding did a good job, send an email explaining how happy you are with that" }],
        "sluis": { "remove": [{ "text": "Bas Alderding", "kind": "person" }, "Project Nightingale"] } }'

# provider receives  → "«PERSON_NAME_1» did a good job, send an email explaining how happy you are with that"
# you receive back   → "Dear Bas Alderding, I am delighted with your work on Project Nightingale…"
# audit note         → dlp:tokenize:person_name(request)|dlp:tokenize:term(request)

Every match becomes a reversible token — «PERSON_NAME_1» — that joins the normal pseudonymization pass: under tokenize, the default, the original values are restored in the response, streaming included; under mask the term is replaced by [REDACTED:<kind>]; under block the request is refused with 422. The instruction is always honoured, even when the key sets dlp: off, the organisation runs in allow_log, or /v1/embeddings is exempted: it can only strengthen protection, never weaken it, which is why it is allowed per request where the retired x-sluis-dlp header was not. The listed term never reaches the provider.

A malformed directive is never silently ignored: an unknown kind, an entry over the limits, or an unknown field inside the extension is refused with 422. What actually ran is disclosed on the sealed audit row, where caller-supplied terms carry the request layer — dlp:tokenize:person_name(request) — distinct from the (ner) and (directory) layers, so the trail shows where each removal came from. The same list is accepted as a remove option on /v1/documents/anonymize and its async jobs.

Workload option overrides

Overrides belong to the workload and apply to all its credentials. An owner or admin configures option_overrides in Console → Workloads or with POST /admin/workloads when creating a workload. Unset options inherit organisation policy. To edit an existing workload, PATCH /admin/workloads/{workload_id} requires its complete mutable settings, including name, status, limits and budget; it replaces them rather than merging individual fields.

Workload policy overrides: choose deviations from the organisation defaults.
Workload policy overrides: choose deviations from the organisation defaults.English interface · illustrative demo data. Open the image for full size.
# create a workload with governed overrides; keys inherit its settings
curl -X POST https://api.sluis.ai/admin/workloads \
  -H "Authorization: Bearer $SLUIS_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "document-review", "option_overrides": {
        "dlp": { "mode": "off" },
        "ner_model": "deep",
        "security": { "prompt_injection": { "mode": "block" } } } }'
# sparse: absent fields inherit org policy; every deviation is sealed in the audit trail

The x-sluis-dlp request header has been removed. Requests carrying it receive 400; configure the workload instead. Effective overrides are recorded in the sealed audit trail.