Menu
AkurAI-Build
publicLatest change 1c2159692a31765cd66ed709791ba11468054873 - Initial commit: bunfork v0.1.0 source tree by Olafur Bui
{% extends "docs.html" %}
{% block title %}SQLite and vectors · Bunfork docs{% endblock %}
{% block description %}Use Bunfork's SQLCipher-encrypted SQLite database, exact migrations, tenant/model-scoped vector CLI, and authenticated vector API.{% endblock %}
{% block breadcrumb %}SQLite & vectors{% endblock %}
{% block docs_title %}SQLite & vectors{% endblock %}
{% block docs_summary %}Bunfork keeps one narrow data model: encrypted vector records, exact embedded migrations, and bounded exhaustive cosine search.{% endblock %}
{% block docs_content %}
<section class="doc-section" aria-labelledby="encrypted-sqlite">
<h2 id="encrypted-sqlite">Encrypted SQLite</h2>
<p>The bundled SQLCipher build encrypts the database at rest. Bunfork validates the application ID, user version, complete migration ledger, exact table/index SQL, and absence of unexpected schema objects.</p>
<pre><code>./target/release/bunfork keygen
./target/release/bunfork migrate</code></pre>
<p>The key must decode to 32 random bytes represented by 64 hexadecimal characters. Keep the key outside the page and public directories and outside the deployment release.</p>
</section>
<section class="doc-section" aria-labelledby="vector-cli">
<h2 id="vector-cli">Vector CLI</h2>
<p>Global <code>--tenant</code> and <code>--model</code> values define the record scope. Put reads content from a UTF-8 file; embeddings are comma-separated finite <code>f32</code> values.</p>
<pre><code>./target/release/bunfork \
--tenant acme --model notes \
vector put note-1 \
--content-file note.txt \
--embedding 1,0,0
./target/release/bunfork \
--tenant acme --model notes \
vector search --embedding 0.9,0.1,0 --limit 5
./target/release/bunfork \
--tenant acme --model notes \
vector delete note-1</code></pre>
<p>Search returns deterministic JSON matches ordered by cosine similarity. It considers only records with the query's dimension in the selected tenant/model scope.</p>
</section>
<section class="doc-section" aria-labelledby="vector-api">
<h2 id="vector-api">Authenticated HTTP API</h2>
<p>Vector endpoints require <code>Authorization: Bearer <API_TOKEN></code>. For browser requests carrying an <code>Origin</code> header, the origin must match the configured public origin (or the request host when no public origin is configured).</p>
<pre><code>curl --request PUT http://localhost:3100/api/vectors/note-1 \
--header "Authorization: Bearer $API_TOKEN" \
--header "Content-Type: application/json" \
--data '{"id":"note-1","content":"hello","embedding":[1,0,0]}'
curl --request POST http://localhost:3100/api/vectors/search \
--header "Authorization: Bearer $API_TOKEN" \
--header "Content-Type: application/json" \
--data '{"embedding":[1,0,0],"limit":5}'
curl --request DELETE http://localhost:3100/api/vectors/note-1 \
--header "Authorization: Bearer $API_TOKEN"</code></pre>
<aside class="doc-note"><strong>ID consistency:</strong> on PUT, the path ID and JSON <code>id</code> must be identical.</aside>
</section>
<section class="doc-section" aria-labelledby="hard-limits">
<h2 id="hard-limits">Hard limits</h2>
<div class="table-wrap">
<table>
<thead><tr><th>Input</th><th>Limit</th></tr></thead>
<tbody>
<tr><td>Embedding dimensions</td><td>1–4,096</td></tr>
<tr><td>Search candidates</td><td>At most 10,000</td></tr>
<tr><td>Search work</td><td>At most 10,000,000 multiply-adds</td></tr>
<tr><td>Results</td><td>1–25</td></tr>
<tr><td>Record content</td><td>64 KiB</td></tr>
<tr><td>JSON request body</td><td>1 MiB</td></tr>
</tbody>
</table>
</div>
<p>A single in-process gate permits one HTTP vector search at a time; concurrent searches receive <code>429</code>. Invalid IDs, dimensions, norms, limits, or budgets are client errors rather than server errors.</p>
</section>
<aside class="doc-callout" aria-labelledby="vector-boundary">
<h2 id="vector-boundary">Deliberately exhaustive</h2>
<p>Bunfork does not load SQLite extensions and does not claim ANN or full-text search. The bounded exhaustive scan is suitable for a small encrypted corpus. Move search to a dedicated system when that ceiling is measurable.</p>
</aside>
<nav class="docs-pagination" aria-label="Documentation pagination">
<a href="/docs/cli"><small>Previous</small><span aria-hidden="true">←</span> CLI & operations</a>
<a href="/docs/deployment"><small>Next</small>Deploy & recover <span aria-hidden="true">→</span></a>
</nav>
{% endblock %}