|
export: token-served age snapshot of dialogue for an n-gram consumer
Navi had no way to hand its history to another machine. A database dump was the obvious idea and the wrong one: prod's 597 MB is mostly things that must never leave (Fernet-encrypted MCP keys, user rows, attachments), and the dialogue an n-gram table wants is 14 MB of it. So the export is a fixed, versioned SELECT — role, content, session, seq, ts — over both message tables. Default corpus is user+assistant only: tool output is 52 MB of scraped web text and command logs, and system messages are near-duplicate boilerplate; either would dominate the counts. A rolling window takes whole sessions, newest first, up to 150 MB, so the snapshot stays bounded as history grows. The snapshot is age-encrypted to a recipient whose private half never reaches this server, so Navi cannot decrypt what it exports. The plaintext gzip is deterministic, and its digest becomes content_id: an unchanged corpus keeps the ciphertext and its ETag, so a consumer that polls every few minutes downloads nothing until something actually changed. Endpoints sit behind a bearer token (machine credential, not user auth): /export/v1/manifest describes, /export/v1/messages streams and answers 304 on a matching If-None-Match. /health carries an informational freshness object that never moves the aggregate status. scripts/navi_export.py is the consumer side: keygen, then pull — manifest first, download, checksum, decrypt, gzip-verify, atomic rename; exit 3 when nothing changed. |
|---|
|
|
| .gitignore |
|---|
| deploy/env.template |
|---|
| docs/api.md |
|---|
| docs/config.md |
|---|
| docs/export.md 0 → 100644 |
|---|
| docs/index.md |
|---|
| navi/api/routes/export.py 0 → 100644 |
|---|
| navi/api/routes/health.py |
|---|
| navi/config.py |
|---|
| navi/export/__init__.py 0 → 100644 |
|---|
| navi/export/builder.py 0 → 100644 |
|---|
| navi/export/loop.py 0 → 100644 |
|---|
| navi/main.py |
|---|
| pyproject.toml |
|---|
| scripts/navi_export.py 0 → 100755 |
|---|
| tests/unit/api/test_export.py 0 → 100644 |
|---|
| tests/unit/export/test_builder.py 0 → 100644 |
|---|
| tests/unit/export/test_cli.py 0 → 100644 |
|---|
| uv.lock |
|---|