Architecture · Technical deep dive

How Haven is built.

Haven is a desktop agent that finds the sensitive things you forgot you had — passwords in old emails, tax returns shared with the whole internet, ID scans in forgotten folders — and fixes them with one reversible click. It was designed backwards from a single constraint: your content must never leave your device to be protected. This page is the full technical picture — every machine, every model, every byte that crosses a wire.

On this page
Haven at a glance

A privacy product where the architecture is the promise.

Haven is a native desktop application — a Rust workspace wrapped in a Tauri shell with a React dashboard — that connects to your email, cloud storage, and local files, scans them on your own machine, and walks you through cleaning up what it finds. Detection runs in three escalating tiers, two of which never touch the network. The few bytes that do leave are bounded, logged on-device before they're sent, and verifiable by anyone with a packet sniffer.

28
Rust crates in the agent workspace
46
Tier 1 detectors · regex + checksums
18
Tier 2 ML classes · on-device ONNX
31B
Tier 3 model params · Haven's own GPU
7
Source types scanned
3
Signed delivery channels · Ed25519
≤2%
Of items ever need the cloud tier
30d
Undo window on every action
System map

Five surfaces, one trust boundary.

The whole product is five deployable surfaces. One of them — the desktop agent — holds all user content. The other four are deliberately designed so they couldn't hold it: a static marketing site, a static artifact CDN, a counters-only backoffice, and two GPU services that process bounded payloads in memory and forget them.

Marketing site havenprotect.app static · nginx · zero user data no connection to the agent — ever Signed artifact CDN models · rules · updates .havenprotect.app — nginx static signed manifests + model bytes Tier 3 inference inference.havenprotect.app vLLM · Gemma 4 · 31B · FP8 zero retention · in-memory only ≤1,500-char excerpt ⇄ verdict Image safety image.havenprotect.app ShieldGemma 2 · Haven-owned GPU in-memory · images never written image check (on by default) · scored in memory, then gone Backoffice backoffice.havenprotect.app Node · Express · SQLite aggregate counters — never content daily aggregate counters feedback · scrubbed errors trust boundary — all content lives inside Haven desktop agent Tauri 2 · Rust · React 19 scanning · ML · encrypted store — all local Windows MSI · macOS DMG
Animated wires show the only traffic that exists. The marketing site has no wire at all — it cannot see users.
  • Desktop agent — the product. Everything sensitive happens here: scanning, classification, the encrypted findings store, remediation, undo.
  • Signed artifact CDN — three static nginx channels that only ever send: detection rules, ML model bytes, and update manifests, each Ed25519-signed before it leaves CI.
  • Tier 3 inference — Haven-controlled GPU running an open-weights model behind an OpenAI-compatible API. Receives bounded excerpts, returns verdicts, retains nothing.
  • Image safety — a second, Haven-owned GPU for the explicit-photo detector (on by default; turn it off per connector), built specifically so users' intimate photos are never processed by a third party.
  • Backoffice — the operations plane. Accepts aggregate telemetry counters, tester feedback, and scrubbed error reports; serves the team an OTP-gated dashboard.
Technology stack

Boring where it should be, sharp where it counts.

The agent is systems software — Rust end to end, with ML inference embedded in-process. The supporting services are deliberately minimal: static file serving, one small Node app, and two GPU boxes running open-weights models Haven controls outright.

Agent core — Rust workspace, 28 crates
Rs
Rust 2021
28-crate workspace · AGPL-3.0
Ta
Tauri 2
native shell · tray · notifications
To
Tokio
async runtime
Sq
SQLite + SQLCipher
encrypted local store · key in OS keychain
Ox
ONNX Runtime
in-process ML · ort + HF tokenizers
Ed
ed25519-dalek
signature verification, compiled-in keys
Agent UI
Re
React 19
dashboard · drawer · Ask Haven
TS
TypeScript 5.8
strict
Vi
Vite 7 + Tailwind 4
build & styling
Inference
vL
vLLM
Gemma 4 · 31B · FP8 · Tier 3
SG
ShieldGemma 2
4B · image safety · FastAPI
Ca
Caddy + HAProxy
TLS · admission control · systemd
Delivery & operations
GH
GitHub Actions
self-hosted runners · sign-in-CI
Ng
nginx
static CDN · reverse proxies · LE certs
No
Node 20 + Express
backoffice · better-sqlite3 WAL
Detection pipeline

Three tiers. Two never touch the network.

Every message, file, and attachment flows through an escalating pipeline. Tier 1 is deterministic pattern matching. Tier 2 is a transformer running inside the app process. Only when both of those are genuinely uncertain — a low single-digit percentage of items — does a bounded excerpt cross the trust boundary to Tier 3 for a second opinion.

everything you connect mail · drive · files · chats TIER 1 Deterministic 46 detectors · regex + Luhn & ABA checksums microseconds per item on-device TIER 2 DistilBERT · ONNX 17 sensitive classes 512-token window runs in the app process on-device TRUST BOUNDARY TIER 3 Gemma 4 · 31B · FP8 in: ≤1,500-char excerpt out: confirmed · refuted · insufficient (no change) ~220-token response cap Haven GPU · zero retention the overwhelming majority resolves here, on your machine ≤2% — ambiguous items only
Watch the dots: green resolves at Tier 1, gold at Tier 2. Only the rare orange dot crosses the boundary — as a bounded excerpt, never a whole document.
Tier 1 · deterministic

46 detectors, zero guesswork

  • API keys & tokens — 35+ provider formats: AWS, GitHub, Stripe, OpenAI, Slack, Google, and more
  • Financial — card numbers (Luhn-validated), ABA routing numbers, bank accounts
  • Identity — SSNs, plaintext passwords, JWTs
  • Tax documents — W-2, 1099, K-1, 1040
  • Account takeover — rogue forwarding rules, suspicious mail filters
  • Sharing posture — public links, domain-wide and stale external shares
Tier 2 · on-device ML

Context, not just patterns

A fine-tuned DistilBERT runs inside the app via ONNX Runtime and reads what regex can't — classifying content into 17 sensitive categories:

tax documentmedical recordcredential contextlegal strategyprivate financialgovernment IDimmigrationemploymentinsuranceestatefinancial statementbackground checkreal estatedomestic relationsminor's databiometricintimate content · on by defaultbenign
Tier 3 · second opinion

Bounded, logged, forgotten

  • Only Tier-2-flagged ambiguity ever reaches it — a ≤1,500-character excerpt, never the document
  • Verdicts only: confirmed elevates, refuted drops the finding, insufficient changes nothing
  • Nothing persisted server-side: no request logs, no caches, no cross-call state
  • Never used to train anything, by anyone
  • Every call appears in the on-device Network Activity log — excerpt hash, destination, size, latency
Why this shape? Recall comes from Tier 1 (cheap, exhaustive), precision from Tier 2 (context-aware, still private), and the hard cases get a frontier-quality answer from Tier 3 without ever giving up the document. Each tier also improves independently: rules ship weekly, the classifier ships monthly, and the Tier 3 model upgrades server-side with zero client changes.
The trust boundary

What leaves the device — exactly, and nothing else.

Most privacy products ask you to trust a policy. Haven's claim is structural: there is exactly one code path that can reach the network, it only accepts a fixed list of payload shapes, and it writes every outbound request to an on-device log before the bytes leave. A continuous CI lint fails the build if any other crate so much as links an HTTP client.

Never leaves your device yours
  • Raw message bodies & files

    The full body or file is never uploaded — only a bounded, redacted excerpt of a flagged item ever crosses (see right).

  • OAuth tokens

    Held in the OS keychain; sent only to the provider that issued them.

  • The values of your findings

    Haven records that a password exists — not the password.

  • The encrypted findings store

    SQLCipher database, key in your OS keychain.

  • Ask Haven questions

    Parsed by an on-device grammar. No ML, no network.

  • Your inferred context profile

    Computed locally to rank findings; stays local.

Crosses the wire — bounded & logged accounted for
  • Aggregate telemetry counters

    Daily rollups from a fixed slug vocabulary — free-form strings are unrepresentable in the schema.

  • Signed-manifest checks

    "Is there a new rules pack / model / update?" — version metadata only.

  • Tier 3 excerpts

    ≤1,500 characters of a flagged item, one round-trip, discarded after the verdict.

  • Explicit-photo image checks

    On by default (off per connector). Image attachments to Haven's own GPU, scored in memory, never written to disk.

  • Scrubbed crash reports

    Panic events pass a scrubber that strips paths, locals, and anything matching Tier 1 patterns.

  • Tester feedback

    What you typed in the feedback box — after the same scrubber.

One chokepoint, enforced by the compiler and CI

scanner · tiers 1–3 connectors · OAuth telemetry aggregator updates · rules · models feedback · error reports haven-egress the single network chokepoint closed payload allowlist one destination per payload logged on-device before send Google · Microsoft APIs (your mail) *.havenprotect.app services signed-artifact CDN crash ingest (scrubbed) …and nothing else. unknown host = no code path CI lint: HTTP anywhere else fails the build
The allowlist is an enum, not a config file — adding a destination requires a code change, a review, and a release users can diff.
Verify it yourself. Inside the app, the Logging page shows every outbound request — payload type, destination, size, and timing — written before the request fires. A security researcher with a proxy can confirm the page tells the truth without any cooperation from Haven. That's the standard we hold ourselves to: architecture, not a promise.
Infrastructure

Where it all actually runs.

Five pieces of hardware, each with one job. The interesting choice: both GPU services run open-weights models on machines Haven controls — no third-party AI API ever sees user content, and the explicit-photo detector got its own dedicated box precisely because that content deserves the strongest possible custody.

Your computer
the only place your content exists
The agent installs from a signed MSI (Windows) or DMG (macOS) and does all scanning, classification, and storage locally.
Tauri 2 shell · Rust workspace
SQLCipher store · ONNX in-process
Windows shipping · macOS in flight
Tier 3 inference GPU
inference.havenprotect.app
Dedicated bare-metal GPU host (US) running vLLM. Admission control in front, TLS termination at the edge, nothing written behind it.
Gemma 4 · 31B · FP8
vLLM · HAProxy · Caddy
zero-retention configuration
Image-safety GPU
image.havenprotect.app
Haven-owned box for the explicit-photo detector (on by default; off per connector). Built so users' most intimate content is scored in memory on our hardware — never a third-party API. Images are never written to disk, never logged.
RTX 6000 Ada · 48 GB
ShieldGemma 2 · 4B · FastAPI
bearer-gated · in-memory only
Static artifact CDN
models · rules · updates .havenprotect.app
Three nginx doc-roots serving signed envelopes: detection rules, ML model bytes, and update manifests. No compute, no state, nothing to breach.
nginx static · Let's Encrypt
no-cache manifests
previous versions kept for rollback
Backoffice VM
backoffice.havenprotect.app
The operations plane: telemetry aggregates, feedback inbox, alpha invites, release artifact intake. Behind nginx with strict CSP and per-endpoint rate limits.
Node 20 · Express
better-sqlite3 · WAL
OTP-gated dashboard
Signed delivery & auto-updates

Everything that changes the agent is signed.

Detection rules, ML models, and the application itself all ship through independent channels — and the agent refuses anything whose Ed25519 signature doesn't verify against keys compiled into the binary. A compromised CDN can't hurt users: a bad signature means the agent silently keeps what it has.

GitHub Actions self-hosted runners build · validate · sign release key rules-signing key updates.havenprotect.app update manifest + installer bytes staged rollout percentage per release rules + models .havenprotect.app rules pack · weekly cadence Tier 2 ONNX bundle · ~267 MB each file pinned by SHA-256 manifest + .sig envelope + .sig agent verifies pubkey baked into binary then installs on restart agent verifies fail-closed: a bad sig = keep the prior pack
Two independent keys: compromising the release pipeline doesn't grant control of detection rules, and vice versa.
  • App updates — the agent checks a signed manifest, downloads only when the SHA-256 matches, and respects a staged rollout percentage so a bad release reaches 5% of the fleet, not 100%.
  • Rules packs — new detectors ship weekly without an app release. The pack carries its own minimum-agent-version gate, so old agents never load rules they can't run.
  • Model bundles — Tier 2 classifier upgrades arrive the same way: signed manifest, per-file hashes, atomic activation, prior version kept for rollback.
  • Everything is opt-out-able — update checking is a user preference, and the Network Activity log shows every check the agent makes.
Connectors & local store

Seven kinds of sources, one encrypted store.

Each connector is its own Rust crate speaking the provider's native protocol — OAuth 2.0 with PKCE for the cloud sources, direct database reads for iMessage, plain file I/O for local folders. Tokens live in the OS keychain. Sync is incremental, so after the first deep scan Haven only reads what's new.

G
Gmail
OAuth + PKCE · History API sync
D
Google Drive
sharing-permission metadata only
O
Outlook & M365
OAuth + PKCE · incl. mail rules
1
OneDrive
sharing-posture audit
P
Proton Mail / IMAP
via Proton Bridge · any IMAP host
i
iMessage
macOS · local chat.db read
T
This device
PDF · DOCX · XLSX · text extraction

The local store

Everything Haven learns lands in a single SQLCipher-encrypted SQLite database on the user's disk. The 32-byte key is generated on first launch and held in the OS keychain — Haven's servers couldn't read the store even with a copy of the file.

  • Findings & verdicts — what was found, where, and every action taken, with the 30-day undo trail.
  • The Network Activity log — the on-device record of every byte that ever left, kept in the same transaction as the send itself.
  • Signed artifacts — the active rules pack, model manifests, and update manifests, stored as the exact signed bytes that were verified.
  • Schema discipline — 29 additive migrations and counting; upgrades never rewrite or expose prior data.
Ask Haven — the natural-language search shipped in 0.3.97 — is a deliberate showcase of the architecture: questions are parsed by an on-device grammar in the haven-query crate and run against finding metadata. No ML, no generation, no network round-trip. The question never leaves the machine, and the answer is honest about what the index can't know.
Backoffice & operations

An ops plane that can't see your data.

The backoffice exists so a small team can run an alpha fleet: watch aggregate health, read tester feedback, issue invites, and stage releases. Its most important property is what it doesn't receive — the telemetry schema is a fixed vocabulary of counter slugs, so message content is not just unsent, it's unrepresentable.

Agent fleet ~25 alpha testers Release CI signed MSI / DMG Haven team browser bearer keys upload key email OTP backoffice.havenprotect.app POST /v1/telemetry/aggregate POST /v1/feedback/submit POST /v1/client-errors/submit POST /v1/release/upload POST /v1/license/validate · heartbeat rate-limited · size-capped · Helmet CSP SQLite · WAL aggregates · feedback · invites OTP dashboard fleet intel · invites · kill-switch
Three caller types, three separate auth schemes — agents and the team never share a credential path.

What the team can actually do

  • Fleet dashboard — daily aggregate charts: scans run, findings by severity band, remediation counts, version adoption. Counters, not content.
  • Alpha lifecycle — invite by email, issue license keys and download tokens, and remotely pause a license (the kill-switch): a paused agent's writes are refused fleet-wide.
  • Release intake — CI uploads each signed installer; the backoffice keeps the latest plus recent versions per OS for the download links and the update channel.
  • Feedback inbox — every in-app "send feedback" lands here, already scrubbed on the client before it was sent.
The closing argument. Every box on this page was placed to make one sentence true: Haven can grow — new detectors weekly, new models monthly, new surfaces over time — without ever widening what leaves the user's machine. The egress allowlist is the contract; everything else is implementation.