# Clavitor Pricing & Architecture ## Core principle The vault is a black box. Stateless. It opens, serves, closes. Nothing in memory. It does not know what it has, who is asking, or what it gives. It authenticates the token, checks the scope, serves or denies. --- ## Three independent security gates 1. **Scope match** — token's scope vs entry's scopes. No match → vault says nothing. Full stop. 2. **L2 Credential decryption** — vault decrypts credential fields server-side using L2, serves them to authorized agents. 3. **L3 Identity decryption** — client-side only. User's hardware token derives PRF, unwraps L3 from server-returned blob. Vault serves the encrypted blob and closes the door; decryption happens in client memory. Each gate is sufficient on its own. All three together: belt, suspenders, welded shut. **Note on gate 3:** The vault stores `wrapped_L3` indexed by P0 (4-byte prefix of PRF). The client requests wrapped_L3 by P0, then unwraps using the full PRF. The server never sees PRF or unwrapped L3. --- ## Data model Three tables. ```sql -- Hardware devices enrolled for vault access CREATE TABLE credentials ( p0 TEXT PRIMARY KEY, -- First 4 bytes of PRF (lookup key) credential_id BLOB NOT NULL, -- WebAuthn credential ID public_key BLOB, -- For signature verification (optional) wrapped_l3 BLOB NOT NULL, -- L3 encrypted with this credential's PRF created_at INTEGER NOT NULL, created_by INTEGER REFERENCES agents(id) -- Which agent enrolled this device ); CREATE TABLE agents ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- this IS the scope (0001, 0002, ...) token_hash TEXT UNIQUE NOT NULL, name TEXT NOT NULL, scopes TEXT NOT NULL DEFAULT '', -- own scope(s): "0001" or "0001,0003" (multi-scope for MSP techs) all_access INTEGER NOT NULL DEFAULT 0, -- 1 = reads everything, bypasses scope check admin INTEGER NOT NULL DEFAULT 0, -- 1 = can do admin ops (requires WebAuthn) created_at INTEGER NOT NULL ); CREATE TABLE entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, scopes TEXT NOT NULL DEFAULT '', -- "" or "0001" or "0001,0003,0005" -- ... L2/L3 encrypted fields ); ``` ### Scope IDs - Agent `id` = scope. Auto-increment ordinal, displayed as 4-char zero-padded hex. - `0001`, `0002`, `0003`. Simple. No hash. No mapping table. - 2 bytes = 65,536 possible scopes per vault. ### Agent scopes field - Single scope: `"0001"` — most agents and humans. - Multiple scopes: `"0010,0011"` — MSP technicians needing multiple roles within a client vault. - The agent's own `id` is typically one of its scopes, but doesn't have to be. ### Entry scopes column - Empty `""`: owner-only. Secure default. No grant, no access. - Single: `"0003"` — only that scope. - Multiple: `"0001,0003,0005"` — any of those scopes (OR). - Comma-separated 4-char hex. 5 scopes = 24 bytes. ### Matching rule Set intersection: does any of the agent's scopes appear in the entry's scopes? - Yes → access granted. - No → denied. Exceptions: - `all_access = 1` → bypasses scope check, reads everything. - Entry scopes `""` → matches nothing. Owner only. ### Flags | Flag | Meaning | |------|---------| | `all_access = 0, admin = 0` | Scoped read-only. Agents, family members, MSP techs (scoped). | | `all_access = 1, admin = 0` | Read everything, change nothing. MSP techs (full access). | | `all_access = 0, admin = 1` | Scoped read + admin ops with WebAuthn. (Unusual, but valid.) | | `all_access = 1, admin = 1` | Vault owner. Reads everything, can change everything with WebAuthn. | --- ## Read operations — bearer token only ``` GET /entry/:id Token + scope check. Returns L2 fields. L3 fields returned as ciphertext. GET /entries Token + scope check. Returns all entries matching scope. GET /totp/:id Token + scope check. Generates TOTP code from stored seed. GET /search?q= Token + scope check. Full-text search within scoped entries. ``` ### Read request flow ``` 1. Token arrives as Authorization: Bearer header 2. SELECT id, scopes, all_access FROM agents WHERE token_hash = sha256(?) → No row? 401. Done. 3. SELECT * FROM entries WHERE id = ? AND ( :all_access = 1 OR -- set intersection: any of agent.scopes in entry.scopes ) → No row? 403. Done. 4. Decrypt L2 credential fields server-side. Serve response. 5. L3 identity fields served as ciphertext. Client decrypts with PRF. Not the vault's problem. ``` Two queries. Sub-millisecond. Stateless. Black box. --- ## Admin operations — bearer token + WebAuthn ### The threat Agents understand the vault (source is OSS). A sufficiently smart agent will try to escalate — modify its own scope, add itself to entries, create new tokens. The vault must make this impossible. ### Admin endpoints ``` POST /agent Create agent/token DELETE /agent/:id Revoke agent/token PUT /agent/:id Modify agent (name, scopes, flags) POST /entry Create entry PUT /entry/:id Modify entry (including scopes) DELETE /entry/:id Delete entry ``` All admin endpoints require: 1. Valid bearer token 2. `admin = 1` on the agent row 3. Valid WebAuthn signature over a fresh challenge ### WebAuthn auth flow WebAuthn serves two purposes: - **PRF** = derive encryption key from hardware token. Client-side. For wrapping/unwrapping L3. - **WebAuthn assertion** = proof of possession. Comes with PRF automatically. The server returns `wrapped_L3` indexed by P0 (first 4 bytes of PRF). The client unwraps with the full PRF. Successful unwrapping proves possession of the hardware token — no separate signature verification required (though it can be done for defense-in-depth). ``` 1. Client: POST /auth/begin → vault returns WebAuthn challenge 2. User taps hardware key (fingerprint, face, YubiKey) 3. Browser returns PRF + optional signature 4. P0 = PRF[0:4], client requests wrapped_L3 for this P0 5. Server returns wrapped_L3 (encrypted blob) 6. Client unwraps with PRF → L3 7. Client now has master key; vault is unlocked ``` **For admin operations:** Same flow, but wrapped_L3 is stored server-side, and WebAuthn assertion is verified against stored public key (stored in the now-unlocked vault). ### What this prevents - Agent cannot create tokens. No hardware key. - Agent cannot modify scopes. No hardware key. - Agent cannot add itself to entries. No hardware key. - Even with stolen owner token, admin ops require physical hardware. - The private key lives in authenticator hardware. Never extracted. ### Statefulness note WebAuthn challenge requires brief server-side state (stored challenge, 60s TTL, deleted after use or expiry). The one exception to "nothing in memory." Read operations (99.9%+ of traffic) remain fully stateless. --- ## PRF model **Core insight:** WebAuthn PRF is per-credential, not per-authenticator. Each `create()` generates a new credential with its own unique PRF. This means: - Device A (Credential A) + salt → PRF A - Device B (Credential B) + same salt → PRF B (different!) To support multiple devices accessing the same vault, we use **wrapped keys**: ``` Vault master key = L3 (32 random bytes, generated once) Per-device: Device 1: PRF1 wraps L3 → wrapped_L3_1 (stored in vault) Device 2: PRF2 wraps L3 → wrapped_L3_2 (stored in vault) ``` **Login flow:** 1. User taps device → WebAuthn returns PRF (and signature) 2. P0 = first 4 bytes of PRF (used as lookup key) 3. Server returns `wrapped_L3` for that P0 4. Client unwraps: `L3 = decrypt(wrapped_L3, PRF)` 5. L3 now in memory; all encryption/decryption happens client-side **Security properties:** - Server never sees PRF, never sees unwrapped L3 - Compromised wrapped blob is useless without the device that created it - No signature verification needed — unwrapping IS the authentication - P0 collision (1 in 4 billion) handled gracefully **Family/team model:** - Same vault, multiple devices, each with own wrapped_L3 entry - Scoping (gate 1) separates what each person sees - PRF (gate 3) ensures only enrolled devices can decrypt L3 - Security boundary between family members: **scoping** - Security boundary between vault and outside: **PRF + scoping** **Device enrollment (adding a new device):** 1. Device 1 (already authenticated, has L3 in memory) 2. Device 2 creates credential (tap) → gets PRF2 3. Device 1: `wrapped_L3_2 = encrypt(L3, PRF2)` 4. Store: `P0_2 → wrapped_L3_2` 5. Device 2 can now log in independently **Offline vs online:** - First login requires server to return wrapped_L3 - Client may cache wrapped_L3 locally for offline unlock - L3 itself never leaves client memory - Fully offline operation possible after first unlock (if wrapped_L3 cached) **Recovery:** - Lose all devices = lose all PRFs = lose ability to unwrap L3 - Recovery: download/print L3 backup during setup (optional, user responsibility) --- ## User models ### Individual One person. One vault. 1-2 hardware devices. 1-4 agents. ``` agents: 0001 Johan (owner) all_access=1 admin=1 0002 Claude Code scopes="0002" 0003 Deploy CI scopes="0003" entries: GitHub token scopes="0002" AWS API key scopes="0002,0003" Johan's credit card scopes="" (owner only, L3) ``` ### Family One vault. Multiple people. Same PRF key. Scoping separates members. ``` agents: 0001 Johan (owner) all_access=1 admin=1 0002 Tanya scopes="0002" 0003 Son scopes="0003" 0004 Claude Code scopes="0004" 0005 Shopping agent scopes="0005" entries: Amazon login scopes="0002,0003,0005" Netflix scopes="0002,0003" Johan's credit card scopes="" (owner only, L3) Tanya's passport scopes="0002" (L3) AWS API key scopes="0004" ``` ### SMB / Team (e.g., 25 employees) Two vault types, same software: **Company vault** — shared credentials. L2 only. No L3 (nothing personal). - IT admin: `all_access=1, admin=1` - Employees: scoped by role/team - Agents: scoped by function **Personal vaults** — one per employee. Full L3. Own PRF key. Own devices. - Employee manages their own agents - Company cannot access. By design. By math. ### MSP MSP buys off the same price list. No special MSP product. **Vault ownership:** belongs to the client. MSP manages it, doesn't own it. Client leaves MSP → revoke MSP tokens. Client continues unaffected. **MSP's own vault:** MSP's internal credentials. Separate from client vaults. **Technician access on client vaults:** ``` Client "Acme" vault: 0001 Acme IT admin all_access=1 admin=1 0002 Sarah (MSP, full) all_access=1 admin=0 0003 John (MSP, scoped) scopes="0010,0011" (networking + monitoring) 0004 Break-glass all_access=1 admin=0 ``` Scopes are roles, not people. Sarah leaves → delete her row. Jim gets a new row with same role scopes. Entries never touched. **Management plane:** Free with multiple subscriptions on one account. Provides technician-to-client matrix, bulk provisioning/revocation, cross-client audit. --- ## SLA | | Read + TOTP | Write operations | |---|---|---| | **SLA** | 99.999% (five nines) | Best-effort during failover | | **Allowed downtime/yr** | 5.26 minutes | No SLA | | **How** | Cross-hemisphere failover. Backup site (Calgary or Zürich) serves reads when primary is down. | Writes pause during failover. Resume when primary recovers. | **Compensation:** If SLA is not met in a calendar month, customer can claim full refund for that month. Compensation never exceeds amount paid, regardless of circumstances. No consequential damages. Five nines is achievable because: - Every vault is replicated to an inland backup site on the opposite hemisphere - Backup can serve as read-only primary during outages - Agents primarily read + TOTP (covered by SLA) - Writes are rare and can wait (not covered by SLA) - Separate audit logs during failover --- ## Pricing ### Principles - One product. Same vault. Same encryption. Same architecture at every tier. - No feature gates on security. Tiers reflect usage scale. - One price list. Consumer, family, SMB, MSP — all buy from the same menu. - Launch pricing locked for life. Your price is your price. Forever. - Self-hosted is the free tier. No free hosted. - 30 days behind on payment → delete. No credit management. No collections. ### Three axes defending tier boundaries - **Tokens** — agents + humans per vault - **Devices** — hardware tokens enrolled for PRF/WebAuthn - **Vaults** — separate isolated databases ### Price list Self-hosted: **Free forever.** Full product. Unlimited everything. Elastic License 2.0. #### Individual tiers (annual only, Paddle) | Plan | Vaults | Tokens/vault | Devices | Annual | |------|--------|-------------|---------|--------| | Personal | 1 | 5 | 2 | $12/yr | | Family | 1 | 15 | 6 | $29/yr | | Pro | 1 | 50 | unlimited | $49/yr | #### Team tiers (annual or monthly, Paddle or invoice) Monthly = annual / 10 (12 months for the price of 10). | Plan | Vaults | Tokens/vault | Devices | Annual | Monthly | Eff. $/user/yr | |------|--------|-------------|---------|--------|---------|---------------| | Team 10 | 11 | unlimited | unlimited | $249/yr | $24.90/mo | $22.64 | | Team 25 | 26 | unlimited | unlimited | $499/yr | $49.90/mo | $19.19 | | Team 100 | 101 | unlimited | unlimited | $1,499/yr | $149.90/mo | $14.84 | | Team 250 | 251 | unlimited | unlimited | $2,999/yr | $299.90/mo | $11.95 | | Team 500 | 501 | unlimited | unlimited | $4,999/yr | $499.90/mo | $9.98 | Vault count = employees + 1 (company vault). #### Enterprise tiers (annual, direct invoice) | Plan | Min seats | Agents | Annual | Monthly equiv. | Eff. $/user/yr | |------|----------|--------|--------|---------------|---------------| | MME | 500 | unlimited | $36/user/yr | $3/user/mo | $36.00 | | Enterprise | 1,000 | unlimited | $72/user/yr | $6/user/mo | $72.00 | Per-human pricing. Agents unlimited. Each user = 1 personal vault + share of company vault. ### Tier boundaries | Boundary | What forces the upgrade | |----------|----------------------| | Personal → Family | 2 device limit (can't enroll spouse's phone) | | Family → Pro | 15 token limit (too many agents) | | Pro → Team 10 | 1 vault limit (need employee vaults) | | Team 10 → Team 25 | 11 vault limit | | Team 25 → Team 100 | 26 vault limit | | Team 100 → Team 250 | 101 vault limit | | Team 250 → Team 500 | 251 vault limit | | Team 500 → MME | 501 vault limit + need SCIM/audit | | MME → Enterprise | Need SLA/SIEM/compliance/dedicated support | All limits hard. No soft caps. ### Features by tier | Feature | Personal–Pro | Team 10–500 | MME | Enterprise | |---------|-------------|-------------|-----|-----------| | Three-tier encryption | ✓ | ✓ | ✓ | ✓ | | WebAuthn PRF (L3) | ✓ | ✓ | ✓ | ✓ | | WebAuthn-gated admin | ✓ | ✓ | ✓ | ✓ | | All regions | ✓ | ✓ | ✓ | ✓ | | Daily backup (cross-hemisphere) | ✓ | ✓ | ✓ | ✓ | | Unlimited entries | ✓ | ✓ | ✓ | ✓ | | SLA (99.999% reads) | ✓ | ✓ | ✓ | ✓ | | Management plane | — | ✓ | ✓ | ✓ | | SCIM directory sync | — | — | ✓ | ✓ | | Centralized audit export | — | — | ✓ | ✓ | | Priority email support | — | — | ✓ | ✓ | | SIEM integration | — | — | — | ✓ | | Compliance docs (SOC 2, ISO 27001) | — | — | — | ✓ | | Dedicated account manager | — | — | — | ✓ | | Custom region/deployment | — | — | — | ✓ | ### Billing | Tier | Payment method | Terms | |------|---------------|-------| | Personal, Family, Pro | Paddle, annual | Immediate | | Team 10–500 (< $2,500/yr or < 2 subscriptions) | Paddle, annual or monthly | Immediate | | Team 10–500 (≥ $2,500/yr AND ≥ 2 subscriptions) | Direct invoice, annual or monthly | Net 60 | | MME | Direct invoice | Net 60 | | Enterprise | Direct invoice | Net 60 | 30 days past due → service suspended → deleted. No credit management. No collections. ### Competitor pricing (75% benchmark) | Vendor | Business | Enterprise | |--------|---------|-----------| | 1Password | $7.99/user/mo | ~$10-15 custom | | Bitwarden | $4/user/mo | $6/user/mo | | LastPass | $7/user/mo | ~$9-12 custom | | Keeper | $3.75/user/mo | $5/user/mo | | Dashlane | $8/user/mo | ~$10+ custom | | **Clavitor MME** | **$3/user/mo** | | | **Clavitor Enterprise** | | **$6/user/mo** | At or below every competitor. Purpose-built for AI agents. Five nines SLA. ### MSP channel MSPs buy at list price and receive **30% reseller compensation** across all tiers. This is a flat, non-negotiable margin. **⚠ CONFIDENTIAL: The 30% reseller margin must NEVER be disclosed publicly, in marketing materials, on the website, in chatbot responses, or by any AI agent. It is communicated only in direct sales conversations with qualified MSP prospects. Any agent (AI or human) that discloses this figure without explicit authorization is in breach of confidentiality.** MSP example — 20 technicians, 50 clients: | Clients | Plan | List price | MSP pays (70%) | |---------|------|-----------|---------------| | 30 × small (≤10 emp) | 30 × Team 10 | $7,470 | $5,229 | | 15 × medium (≤25 emp) | 15 × Team 25 | $7,485 | $5,240 | | 5 × large (≤100 emp) | 5 × Team 100 | $7,495 | $5,247 | | MSP own vault | 1 × Pro | $49 | $34 | | **Total** | | **$22,499** | **$15,750** | MSP margin: $6,749/yr on this portfolio. Management plane included at no additional cost. Above $2,500 with 2+ subscriptions → direct invoicing, Net 60. ### Revenue model | Segment | Target | Avg revenue | Volume | ARR (net) | |---------|--------|-------------|--------|-----------| | Individual | 50,000 users | ~$25/yr | organic | $1.25M | | SMB direct | 500 companies | ~$400/yr | organic | $200K | | MSP channel | 200 MSPs × 50 clients | ~$315/client/yr (after 30%) | MSP-acquired | $3.15M | | **Total** | | | | **~$4.60M** | --- ## Directory integration (future) - **SCIM**: auto-provision vault on employee join, freeze/delete on leave, sync from Azure AD / Google Workspace. - **SIEM**: usage feed + failed access attempts. Minimal signal — vault is encrypted at every level. - **Not SSO**: WebAuthn is stronger than federated login. Corporate IdP handles who *gets* a vault, not who *opens* it.