# vault1984

> *"If you want to keep a secret, you must also hide it from yourself."*  
> — George Orwell, 1984

**A password manager where a breached server gives attackers nothing.**

Not because we delete the data. Not because we encrypt it harder.  
Because the decryption key was never there to begin with.

Managed hosting or self-hosted. Open source. Three encryption layers.  
One binary. One SQLite file.

---

## Why the architecture matters

In 2022, attackers stole the entire vault database of a leading password manager. The encryption worked exactly as designed. The problem was structural: when you store encrypted data on a server that also holds the decryption capability, a breach gives attackers unlimited offline time to crack. Four years later, accounts are still being drained from that breach. The industry's response has been higher iteration counts — making the vault harder to crack. vault1984's response was to make it worthless to steal.

Everything in your vault is encrypted. What differs is who holds the key.

| Layer | Contains | Key held by |
|-------|----------|-------------|
| **Vault** | Titles, URLs, usernames | Server — by design. Knowing you have a Coinbase account isn't an attack. |
| **Credential** | Passwords, API keys, TOTP seeds, SSH keys | Your agents — delegated by you. The server never had it. |
| **Identity** | Card numbers, CVV, government IDs, seed phrases | You only — hardware authenticator required. Agents cannot reach it. |

**Threat model:**

| Scenario | Vault | Credential | Identity |
|----------|-------|------------|----------|
| Database stolen | Readable (with vault key) | Worthless ciphertext | Worthless ciphertext |
| Server compromised | Visible during request | Ciphertext — server cannot decrypt | Not present |
| Agent token compromised | Via MCP | Decryptable by that agent | Not present |
| Hardware key + PIN stolen | Everything | Everything | Everything |

### How storage works

The vault does not encrypt your credentials. You do.

Credential and Identity fields are encrypted by the browser or agent before they leave the client. The vault receives the encrypted blobs, wraps everything with Vault Encryption (VAULT_KEY) for storage, and returns it on read. The server handles pack/unpack — it never inspects what's inside Credential or Identity fields.

Each field carries a `layer` tag (`vault` / `credential` / `identity`) so the client knows what it can decrypt after unpack.

**Credential key derivation:** X25519 keypair derived via HKDF-SHA256 from your WebAuthn authenticator's PRF output. Public key stored on server. Private key derived client-side during browser session and baked into agent tokens at creation time — never stored on server. Agents unwrap it locally.

**Identity key derivation:** AES-256 symmetric key derived via HKDF-SHA256 from the same PRF output (independent branch). Browser-only. Never leaves the client. Not in tokens. Not in the database.

One root of trust: your hardware authenticator. One tap unlocks both Credential and Identity layers in the browser.

---

## Quick start

```bash
go build -o vault1984 ./cmd/vault1984/
./vault1984
# Open http://localhost:1984/app/
# Register a passkey → vault is ready
```

No config files, no environment variables, no database setup.

---

## MCP setup

Create a token in the web UI (Tokens page), then add to your MCP client config:

```json
{
  "mcpServers": {
    "vault1984": {
      "url": "http://localhost:1984/mcp",
      "headers": {
        "Authorization": "Bearer v1984_..."
      }
    }
  }
}
```

The token is a combined credential: MCP auth + the Credential private key (wrapped). The agent decrypts Credential-layer fields locally. The server never sees the key.

### Available tools

| Tool | Description |
|------|-------------|
| `get_credential` | Find and return a credential by query |
| `list_credentials` | List all accessible entries |
| `get_totp` | Get live TOTP code for 2FA |
| `search_vault` | Full-text search across entries |
| `check_expiring` | Find expiring credentials, cards, documents |
| `save_credential` | Write a new or updated credential (write-enabled tokens only) |

Identity-layer fields return `[Identity Encryption — hardware key required]` to agents. They are not accessible without a browser session and physical authenticator tap.

Tokens are read-only by default. Write access is granted explicitly when creating the token.

---

## Features

- **One binary** — Go, compiles to linux/mac/windows. FIPS mode available (`GOEXPERIMENT=boringcrypto`)
- **One file** — SQLite per vault. Portable, copy it anywhere
- **No master password** — WebAuthn only. Touch ID, Face ID, YubiKey, Titan Key, Windows Hello
- **Three-layer field encryption** — Vault / Credential / Identity, per-field, auto-detected on import
- **Client-side encryption** — browser and agents encrypt before sending. The vault stores what it receives.
- **AI agent integration** — MCP tools for reading and writing credentials, completing 2FA flows autonomously
- **Auto-detection** — imports auto-flag card numbers, CVV, government IDs, recovery codes as Identity layer across 15+ languages
- **Auto-lock** — 60s idle + 15s countdown. Session and key cleared on lock
- **TOTP generation** — agents can complete 2FA flows without user intervention
- **Browser extension** — Manifest V3, LLM field mapping, autofill on any site
- **No content scripts** — the extension injects nothing into pages
- **Native import** — Chrome, Firefox, Bitwarden, Proton Pass without LLM. Any format via LLM fallback
- **Smart dedup** — collision resolution by source modification date
- **Automatic backups** — weekly, 3-month retention, deterministic slot per vault ID
- **Audit log** — every access logged with actor (web / extension / MCP / agent name)
- **Multi-tenant** — hosted mode, token identifies the vault. The Elastic License 2.0 prohibits offering this as a managed service to third parties — vault1984.com is the only authorized hosted service.

---

## Config

All optional. Set via environment or `.env` file in the working directory.

```bash
PORT=1984                # default
DATA_DIR=.               # directory for vault DB files
MODE=self-hosted         # or "hosted" for multi-tenant
VAULT_KEY=...            # server-side encryption key for storage
FIREWORKS_API_KEY=...    # for LLM import of unknown formats
```

`VAULT_KEY` is the server's storage key — it wraps all data at rest, including Credential and Identity blobs. Losing it makes the database unreadable. It does not give access to Credential or Identity plaintext — those require the client-side keys derived from your hardware authenticator.

---

## Import

Encryption happens in the browser. The vault never sees plaintext Credential or Identity fields during import.

**Import flow:**
1. Browser downloads existing encrypted entries from the vault and decrypts them locally
2. Browser parses the import file — natively for known formats, or sends the file to the server for LLM parsing; server returns parsed plaintext to the browser without storing it
3. Browser matches against existing entries — URL, username, and decrypted values
4. Browser shows preview: new / update / skip
5. User confirms — browser encrypts all changes and sends a single batch to the vault

Native parsing (no LLM, no server) for:
- **Chrome** — `chrome://settings/passwords` → export CSV
- **Firefox** — `about:logins` → export CSV
- **Bitwarden** — Settings → Export → JSON
- **Proton Pass** — Settings → Export → JSON (zip or plain)

Any other format: drag and drop, LLM parses it server-side and returns structure to the browser.

Collision rule: newest modification date wins. Per entry, where timestamps are available.

Identity-layer auto-detection on import covers card numbers, CVV, government IDs (SSN, passport, driver's license, BSN, PESEL, etc.), recovery codes, and crypto wallets — in English, Dutch, German, French, Spanish, Portuguese, Italian, Chinese, Japanese, Korean, Russian, Arabic, Hindi, Turkish, Polish, Swedish, Thai, and Vietnamese.

---

## Backups

Automatic weekly backups with 3-month retention. Each vault's backup slot is deterministic — the first byte of the vault ID maps to an hour of the week, spreading backup load evenly across nodes.

Backups use SQLite `VACUUM INTO` for consistent, compacted snapshots stored in `{DATA_DIR}/backups/`.

From the web UI: view all backups, trigger immediate backup, restore (current DB saved as pre-restore backup first).

---

## Telemetry

Optional push telemetry for monitoring hosted nodes. Disabled by default.

```bash
./vault1984 \
  --telemetry-freq 60 \
  --telemetry-host https://your-monitoring-endpoint/telemetry \
  --telemetry-token <bearer-token>
```

Or via environment: `TELEMETRY_FREQ`, `TELEMETRY_HOST`, `TELEMETRY_TOKEN`.

Reports: hostname, uptime, OS/arch, CPU/memory/disk usage, vault count, total entries. No vault contents, no credentials, no user data.

---

## Testing

```bash
go test ./api/... -v
```

No setup required. Each test spins up an in-process server with a temp SQLite database.

---

## Managed hosting

Don't want to run the server? We host it.

Same cryptographic guarantees. We run the infrastructure. We cannot read your Credential or Identity fields — not policy, math. The plaintext was never sent to us.

→ [vault1984.com](https://vault1984.com)

---

## License

[Elastic License 2.0](LICENSE) — free to use, modify, and self-host. Cannot be offered as a managed service to third parties.
