Overview
AgentVault defines formal state machines for three core protocol flows: enrollment (device onboarding), 1:1 messaging (E2E encrypted owner-agent communication), and room lifecycle (multi-participant task rooms). These state machines govern all valid transitions and enforce security invariants at every step.The server never sees plaintext. All encryption and decryption happens client-side.
Protocol messages are opaque blobs to the server.
Enrollment
Invite Token States
Invite tokens are the entry point for device enrollment. Tokens are single-use, short-lived, and stored as BLAKE2b hashes (never raw).| Constraint | Value |
|---|---|
| Max uses | 1 (single-use) |
| Max TTL | 10 minutes |
| Storage | BLAKE2b hash only |
| Transition to CONSUMED | Immediate on successful device submission |
Device Lifecycle States
Devices progress through a lifecycle from pending enrollment to active participation, with administrative controls for suspension and revocation. State rules:| State | Capabilities |
|---|---|
| PENDING | Cannot communicate. Awaiting admin approval. |
| APPROVED | Eligible for key exchange. Cannot yet send messages. |
| ACTIVE | Full participation: messaging, room membership, key exchange. |
| SUSPENDED | Temporarily blocked. No communication. Reversible. |
| REVOKED | Permanently removed. All room memberships stripped. Triggers rekey. |
Enrollment Protocol Flow
The full enrollment sequence from invite creation through device activation: Failure cases return generic error messages to prevent information leakage:| Failure | Server Response |
|---|---|
| Token expired | 400 Bad Request (generic) |
| Token already consumed | 400 Bad Request (generic) |
| Invalid proof-of-possession | 400 Bad Request (generic) |
| Token revoked | 400 Bad Request (generic) |
1:1 Messaging
Session Establishment
Before two devices can exchange messages, they must establish a shared session using the X3DH (Extended Triple Diffie-Hellman) key agreement protocol.The owner must send the first message. The agent must not send until it has received
at least one message from the owner (the
activated flag). This ensures the Double Ratchet
is properly initialized from the X3DH shared secret.Message Send/Receive
Each message advances the Double Ratchet, deriving a unique message key for every message. Old keys are deleted after decryption (forward secrecy). Message fields uploaded to server:| Field | Type | Description |
|---|---|---|
conversation_id | UUID | Identifies the 1:1 conversation |
sender_device_id | UUID | Sending device identifier |
ciphertext | BYTEA | Encrypted message payload |
header_blob | BYTEA | Ratchet header (public DH key + counters) |
Replay Protection
- Each message includes a unique message number from the ratchet chain.
- The recipient rejects duplicate sequence numbers.
- A sliding window handles out-of-order delivery (skipped message keys are cached temporarily for later decryption).
Encryption Details
| Property | Value |
|---|---|
| Key agreement | X3DH (Extended Triple Diffie-Hellman) |
| Ratchet | Double Ratchet (Signal Protocol) |
| Symmetric cipher | XChaCha20-Poly1305 |
| Key size | 256-bit |
| Nonce size | 192-bit (eliminates nonce reuse risk) |
| Forward secrecy | Yes — old keys deleted after use |
| Signing | Ed25519 |
| Key exchange | X25519 |
Room Lifecycle
Each task room is a multi-participant group with its own encryption state. The current implementation uses Double Ratchet per-conversation within rooms. MLS (Messaging Layer Security) is planned for post-MVP.Room State Machine
Create Room
Add Initial Members
Admin adds initial members. Each member’s device receives the key material
needed to participate.
Add Member
Rules:- Only ACTIVE devices may receive room membership.
- Existing connected members are notified via WebSocket broadcast.
- The new member’s device subscribes to the room’s Redis pub/sub channels.
Remove Member / Device Revocation
Guarantees:- Forward secrecy preserved — removed devices cannot decrypt messages from the new epoch.
- WebSocket connections are closed immediately on revocation.
- All room memberships are stripped atomically.
Concurrency Handling
Simultaneous Admin Changes
When multiple admins issue conflicting changes (e.g., two membership changes at once), the server enforces ordering:- The first commit to reach the server is applied.
- Conflicting operations must rebase against the new state and retry.
Message During Rekey
If a device attempts to send during an epoch transition:- The send fails with an epoch mismatch error.
- The client fetches the latest group state.
- The client updates local encryption state.
- The client retries the send under the new epoch.
Error Recovery
Epoch Mismatch
Epoch Mismatch
- Fetch latest room state from server.
- Verify the commit chain integrity.
- Resynchronize local encryption state.
Corrupt State
Corrupt State
- Trigger full state resync from server.
- If verification fails, admin can perform a room reset (re-establishes all encryption state from scratch).
Ratchet Desync (1:1)
Ratchet Desync (1:1)
When the Double Ratchet falls out of sync between owner and agent:
- Delete the broken session from local storage.
- Clear the relevant key material.
- Re-establish via fresh X3DH key exchange.
- The
device_linkedevent triggers a new conversation.
Security Enforcement Rules
These invariants hold across all protocol state machines:Zero-Knowledge Server
Server never decrypts content. All protocol messages are opaque BYTEA blobs.
RLS Enforcement
PostgreSQL Row-Level Security enforces membership before read/write on all tables.
Mandatory Rekey
Device revocation triggers mandatory rekey of all affected rooms.
No Content in Push
Push notifications contain zero message content. Content is fetched client-side after notification.
Non-Goals
The protocol explicitly does not protect against:- Fully compromised operating systems (device-level compromise).
- Screenshot or screen recording prevention.
- Global traffic analysis or metadata obfuscation beyond what TLS provides.
Validation Checklist
For implementers verifying protocol compliance:Enrollment tokens are single-use and expire within 10 minutes
Device fingerprint is verified by admin before approval
All encryption state is validated client-side before use
No plaintext columns exist in the database
All tables have RLS policies enabled
Revocation automatically triggers rekey of all affected rooms
Owner sends first message in every 1:1 conversation
Old ratchet keys are deleted after decryption