22 KiB
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
- Scope match — token's scope vs entry's scopes. No match → vault says nothing. Full stop.
- L2 Credential decryption — vault decrypts credential fields server-side using L2, serves them to authorized agents.
- 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.
-- 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
idis 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:
- Valid bearer token
admin = 1on the agent row- 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:
- User taps device → WebAuthn returns PRF (and signature)
- P0 = first 4 bytes of PRF (used as lookup key)
- Server returns
wrapped_L3for that P0 - Client unwraps:
L3 = decrypt(wrapped_L3, PRF) - 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):
- Device 1 (already authenticated, has L3 in memory)
- Device 2 creates credential (tap) → gets PRF2
- Device 1:
wrapped_L3_2 = encrypt(L3, PRF2) - Store:
P0_2 → wrapped_L3_2 - 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.
Price for Life Guarantee
Core commitment: The price a customer pays at signup is their price forever, as long as the subscription remains active. We have never raised prices on existing customers. We never will. We may raise prices for new customers — but never for existing, active subscribers.
Mechanics:
- Locked by tier + currency at moment of first successful charge
- Annual renewals charge the same amount, same currency, forever
- Currency exchange fluctuations absorbed by us (not passed to customer) — both directions
- We bear forex risk: if EUR weakens, we lose margin; if EUR strengthens, you don't pay more
- Applies to all supported currencies: USD, EUR, GBP, CHF, and future additions
Upgrade path:
- Upgrade to higher tier → pay then-current rate for new tier → that price locks for life
- Downgrade → pay then-current rate for lower tier → lock applies to new rate
- Side-grade (e.g., Team 10 → Team 25) → new tier's current rate locks
The catch (intentional):
- Cancel → forfeit lock forever
- Re-subscribe later → pay then-current published rate
- This creates mutual incentive: we keep you happy, you keep subscribing
Competitive positioning (for marketing only — not legal docs):
- 1Password raised prices ~25% on existing customers (2023-2024)
- Bitwarden raised prices ~20% on existing customers (2024)
- LastPass... well, LastPass had other issues
- We raise prices only for new customers — existing subscribers are protected forever
- Note: Competitor references belong in marketing materials only, never in Terms or legal documents
Economics: We architected costs to decline over time (infrastructure efficiency, scale). Customer lifetime value rises as cost-to-serve falls. Price increases are a choice, not a necessity. We choose never.
Cancellation, Auto-Renewal & Payment Failure Policy
Auto-renewal is default:
- Protects against accidental vault deletion from expired cards
- Annual plans: 14-day "regret period" after auto-renewal (full refund, no questions)
- Monthly plans: cancel before next charge
- Can be disabled anytime; vault stays active until period ends
User-initiated cancellation:
- Takes effect at the start of next billing period (not immediate)
- When effective: vaults deleted instantly and permanently from active systems
- 7-day warning email before deletion — final chance to export
- No grace period, no trash bin, no reversal
- 14-day regret period (Section 6) does NOT apply to cancellations — only auto-renewals
Failed payment & 14-day retry window:
- Day 0: Payment fails, email sent, vault active
- Days 1-14: Automatic retries by Paddle; update payment method anytime
- Day 15: Enter cancellation status; 7-day warning sent
- Day 22: Vaults deleted per Section 10
Compliance backups:
- Retained for maximum 30 days after deletion
- Exist solely for legal/regulatory compliance
- NOT available for restoration — this is a legal firewall
- After 30 days: permanently destroyed
Reactivation is new:
- Deleted vaults cannot be restored, even within 30-day backup window
- Start fresh with empty vault
- 14-day regret period does not apply to post-deletion reactivation
Self-hosted exception: Community Edition users manage their own data. This policy applies only to hosted service.
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 | People | Vaults | Agents | Annual | Trial |
|---|---|---|---|---|---|
| Personal | 1 | 1 | 5 | $12/yr | 7 days |
| Family | ~6 | 1 | 15 | $24/yr | 7 days |
| Pro | 1 | 1 | 50 | $49/yr | 7 days |
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 | 10 | 11 (10+1) | 100 | $249/yr | — | $24.90 |
| Team 25 | 25 | 26 (25+1) | 250 | $499/yr | — | $19.96 |
| Team 100 | 100 | 101 (100+1) | 1,000 | $1,499/yr | $149/mo | $14.99 |
| Team 250 | 250 | 251 (250+1) | 2,500 | $2,999/yr | $299/mo | $11.99 |
| Team 500 | 500 | 501 (500+1) | 5,000 | $4,999/yr | $499/mo | $9.99 |
Vault count = employees + 1 (company vault). Agents scale with seats — 10 per person on Team plans.
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.