Your cards and bank accounts, synced between your devices, on a server only you control.
The self-hosted, zero-knowledge sync service and web vault for QuanCard.
Website · Getting started · Deployment · Threat model · Protocols
Important
QuanCard is a personal collection vault. It does not issue cards, move money, connect to banks or help anyone bypass KYC or regional restrictions. This is a development preview without an independent security audit. Read the threat model before you store real data.
QuanCard on iPhone keeps your cards and bank accounts on the device and can sync through iCloud. QuanCard Server is the third option: your own sync backend, plus a full web vault for any desktop browser. Running as published, it only ever holds ciphertext:
- iPhone ⇄ server ⇄ web. Pair your iPhone once with a QR code. Edits on either side appear on the other, encrypted end to end.
- Zero knowledge. The browser and the iPhone encrypt everything before upload. The server stores opaque, immutable revisions and does not see a card number, a key or your password. It also serves the web vault's code, so a compromised server could replace it; see the threat model.
- Yours to run. One Docker Compose file with automatic HTTPS, your domain, your backups. Open source under AGPL-3.0.
Note
What is open source here. This repository, the self-hosted sync server and the web vault, is open source. The QuanCard iPhone app is a commercial product and is not open source. The protocols it speaks are documented here, so you can audit how your data is encrypted and stored.
|
🔐 End-to-end encrypted 📱 Multi-device sync 🔗 One-scan pairing 🔀 Conflicts you can trust |
💳 A real desktop app 🙈 Private by default 👨👩👧 Family-ready 🛡️ Hardened |
You need a Linux host with Docker, a domain that points to it, and ports 80 and 443 open.
git clone https://github.com/zoolapp/quancard-server.git && cd quancard-server
./scripts/init-env.sh vault.example.com # writes .env and prints a one-time setup token
docker compose up -d --wait # Caddy obtains the HTTPS certificate- Open
https://vault.example.com, enter the setup token and create the owner account. - Create a vault. It starts with a sample card; Settings → Sample data loads the full catalogue.
- Settings → Pair iPhone, then scan the code in QuanCard: Settings → Sync → Self-hosted Sync.
To try it on your own machine, run ./scripts/init-env.sh localhost && docker compose -f compose.local.yaml up -d,
then open http://localhost:8080.
📖 Getting started walks through the first hour: pairing, members, two-step verification and backups. Deployment covers nginx, Traefik and Cloudflare Tunnel, upgrades, and every configuration option.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
All screenshots use synthetic test data or the built-in sample data (public test numbers that cannot make payments).
Browser / iPhone (trusted) Your server (untrusted for content)
────────────────────────── ───────────────────────────────────
password ─Argon2id─▶ authKey ───────────────────────────▶ Argon2id(authKey) verifier
└▶ KEK ─wraps─▶ Account Key ───────────▶ wrapped Account Key
└─wraps─▶ vault key ──▶ wrapped vault key
card / account ─AES-256-GCM(vault key)─▶ revision ───────▶ opaque, immutable revisions
iPhone ◀── pairing QR code (long-term vault key, not sent through the server) ── browser
- One protocol, every client. The web client speaks the iPhone's
quancard.envelope.v1and sync v1 formats and reproduces the iOS test vectors byte for byte (vectors/,packages/protocol, Apache-2.0). Future clients such as macOS discover server features fromGET /api/v1/status. - Photos are re-encoded in the browser (EXIF stripped, ≤ 1600 px, ≤ 1 MiB), encrypted, and stored inside the item's revision. They reach your server and your paired devices only.
- Sample data uses the same catalogue and item IDs as the iPhone app, so a sample loaded on one device is recognised, and can be removed, on the others.
Specifications: auth v1 · pairing v1 · sync v1 · HTTP API (OpenAPI) · passkey v1 (proposal).
A stolen database, backup or network capture reveals no card data. A weak password can still be guessed offline, so use a long passphrase. The server operator sees metadata: account names, how many revisions there are and when they were written. A malicious or compromised server could serve modified web code, which is the limit of every browser-based end-to-end encrypted app. Run the server yourself, keep it updated, and prefer the iPhone app on hosts you do not trust. Details and mitigations are in THREAT_MODEL.md. Report vulnerabilities privately as described in SECURITY.md.
| Area | Status |
|---|---|
| Server: accounts, 2FA, invites, sessions, audit, vault data plane, pairing, capability discovery | ✅ implemented, tested |
| Web vault: desktop shell, ⌘K, cards and accounts, photos, reveal, conflict centre, sample data, PWA | ✅ implemented, end-to-end and UI-gate tested |
| iPhone self-hosted sync: QR pairing, linked animation, identical-copy folding | ✅ implemented in the app (pending App Store release) |
| Docker image, HTTPS compose, backup and restore | ✅ verified |
| Passkeys (PRF unlock) | 📝 specified and reviewed, not implemented |
Encrypted .qvault import/export in the browser, macOS client, sync v2 (photo blobs) |
🗓 roadmap |
| Independent security audit | 🗓 planned |
corepack enable && pnpm install
pnpm -r build && pnpm -r test && pnpm lint
pnpm exec playwright test e2e/vault.spec.ts # end-to-end story
UI_ACCEPTANCE=1 pnpm exec playwright test e2e/ui-acceptance.spec.ts # UI gate (run separately)Layout: packages/protocol (Apache-2.0, isomorphic codecs) · apps/server (Fastify, node:sqlite) ·
apps/web (Preact, WebCrypto, hash-wasm) · e2e · deploy. See
CONTRIBUTING.md and CHANGELOG.md.
The server and the web client are licensed under AGPL-3.0-only. packages/protocol and
vectors/ are licensed under Apache-2.0, so other clients and
auditors can reuse them freely. The QuanCard name, the otter character and the app icon are brand
assets of ZOOL LLC (details). © 2026 ZOOL LLC.







