0. What the server can and cannot see — read this before renting anything
The product’s promise is zero-knowledge custody (ADR-0014, ADR-0019): the server stores what it needs to coordinate and cannot read a profile. That was re-measured, not re-read, on 2026-09-04 by querying the database and listing the bucket after a full two-device round trip [MEASURED]:
| where | in the clear | sealed / hashed (server cannot read) |
|---|---|---|
accounts |
email · totp_enabled flag · created-at · a 16-byte auth salt (non-secret by design) |
password_hash is an Argon2id hash of a client-derived verifier, never the passphrase (ADR-0019 C1) · totp_seed_enc 60 bytes, AEAD under VFLIN_TOTP_KEY |
devices |
device id (the daemon’s UUID) · device name · last-seen | refresh_token_hash (43 chars; the token itself is never stored) |
profiles_meta |
profile id · blob key · content hash · ciphertext size · version vector (device ids → counters) · fence (S5: the sync-lease fence of the last accepted push, a monotonic counter — coordination metadata, derived from no plaintext) · state · updated-at |
— |
account_keyrings |
a JSON envelope: version, the KDF parameters (mCost/tCost/pCost), saltKek, the device-key registry (device id → 32-byte public signing key), accountPub |
wrappedMkPassword, wrappedMkRecovery, wrappedAccountPriv (AEAD nonce + ciphertext) · the MK-MAC |
bucket vflin-blobs |
per blob a cleartext manifest (VFB1 + JSON): profile id · device id · version vector · coreVersion · plaintext payloadSize · inner content hash — documented in PROFILE_STORAGE_SYNC.md §“manifest (cleartext, integrity-protected)” |
wrappedDek · sealedRecord (name / fingerprint / proxy) · the payload — AEAD, opaque bytes |
audit_log, orgs, shares, subscriptions |
empty after the flow: the daemon never ships action-log entries (log.append is unreachable from it), no team was created, no plan bought |
— |
password_resets (S4) |
which account a reset is for, its expiry, whether it was used — and a hash of the mailed token (token_hash), never the token; a row with a NULL account is a decoy an unknown email leaves so reset-init does the same work on both branches |
the reset token itself (mailed once, 30-min, single-use) |
billing_events (S4) |
the account an event was for, its plan/status, the provider’s order reference, when it arrived — a payment-history read for the cabinet’s invoices | — |
So an operator with root on the VPS learns: who has an account, how many devices and profiles they have, how large each profile is, which Chromium version last opened it, and when it changed. They learn no passphrase, no profile content, no cookies, no fingerprint, no proxy. Say exactly this to users; do not say “the server stores nothing”.