Sealed RAG for regulated data
15 minRun contracts or PII through managed RAG with a key only you hold. Create a byok store, ingest a file, lock it when idle, and unlock to query, so a stolen database is ciphertext even to us. Sealed stores are text only today: non-text modalities are not supported in a sealed store.
- •
A Ringside API key exported as
FC_API_KEY - •
A file to ingest (this uses
contract.pdf) - •
Read the encrypted-RAG guide first if the managed vs byok choice is unfamiliar
When you need this
Normal managed RAG stores your document text and vectors as plaintext, because it has to read them to search. For a public handbook that is fine. For contracts, tax returns, case notes or anything regulated, it means whoever can read the database can read your documents. A sealed store encrypts the chunk text and vectors at rest under a key, and a byok sealed store uses a key only you hold, so while it is locked it is ciphertext even to Ringside.
This tutorial uses encryption: "byok" with a passphrase. If you only need at-rest encryption and are happy for us to operate the key, use encryption: "managed" instead and skip the lock/unlock steps. The conceptual differences are in the encrypted-RAG guide.
Sealed stores are text only today. Documents are extracted to text, chunked, embedded and sealed as text; non-text modalities are not supported in a sealed store. If you need those, use an unsealed store.
Create a byok store
Create the store with encryption: "byok" and a passphrase. We derive a key from the passphrase, store only a wrapped copy, and never keep the passphrase itself. The store is created unlocked for this session so you can ingest right away.
curl https://api.fightclub.pro/v1/vector_stores \
-H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "acme-contracts",
"embedding_model": "text-embedding-3-small",
"encryption": "byok",
"key": { "type": "passphrase", "passphrase": "correct-horse-battery-staple" }
}'
# => { "id": "vs_...", "encryption": "byok", "vector_sealing": "full" }Choose a strong passphrase and store it the way you would any other secret. There is no recovery: if it is lost, the store cannot be read, by you or by us. That is the point.
Ingest a file
Upload and attach exactly as you would for any store. The chunk text and embedding vectors are sealed under your key before they are written. Poll the file status until it reads completed.
FILE=$(curl -s https://api.fightclub.pro/v1/files \
-H "Authorization: Bearer $FC_API_KEY" \
-F purpose=attachments -F file=@contract.pdf | jq -r .id)
curl https://api.fightclub.pro/v1/vector_stores/vs_.../files \
-H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
-d "{\"file_id\":\"$FILE\"}"
# poll until "status":"completed"
curl https://api.fightclub.pro/v1/vector_stores/vs_.../files/$FILE \
-H "Authorization: Bearer $FC_API_KEY"Lock it when idle
A byok store can be locked. While locked there is no key in memory, so ingest and search fail closed: nothing readable comes out, and a database dump is pure ciphertext. Lock it whenever you are not actively using it.
curl -X POST https://api.fightclub.pro/v1/vector_stores/vs_.../lock \
-H "Authorization: Bearer $FC_API_KEY"
# => { "locked": true }Unlock, then query
To use the store again, present the passphrase to /unlock. That opens a time-limited session. While unlocked, file_search works exactly as on any store: it decrypts only the chunks it returns, in memory, and answers. The calling code is identical to a plaintext store.
# unlock (a wrong passphrase returns 401; the session has a rolling idle TTL)
curl -X POST https://api.fightclub.pro/v1/vector_stores/vs_.../unlock \
-H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
-d '{"key":{"passphrase":"correct-horse-battery-staple"}}'
# => { "unlocked": true, "expires_at": 1782300900 }
# then run file_search inside an Assistants run, as usual
curl https://api.fightclub.pro/v1/threads/$TH/runs \
-H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
-d '{"assistant_id":"asst_...",
"tools":[{"type":"file_search","file_search":{"vector_store_ids":["vs_..."]}}]}'If you query while the store is locked, you get an empty result, never ciphertext and never an error that leaks content. That fail-closed behaviour is the guarantee.