1. Introduction
The Data Portability Protocol enables users to:- Collect personal data from various platforms
- Store data under their control
- Grant third-party applications access to specific data scopes
- Revoke access at any time
- Maintain auditable records of all data access
Design principles
2. Terminology
Protocol entities
Protocol objects
Cryptographic primitives
3. Protocol model
Architecture layers
Key distinction
- Desktop App: NOT a protocol participant. Does NOT register onchain. Controls the Personal Server.
- Personal Server: IS a protocol participant. MUST register onchain. Can act unattended.
4. Protocol components
4.1 Personal server
Purpose: Stores user data in plaintext, responds to authorized data requests, maintains access logs, operates unattended. Registration: MUST be registered onchain viaDataPortabilityServers. Uses EIP-712 signature-based operations.
Hosting options
Every live Personal Server form runs client-side, on the user’s own device. A user-controlled hosted form (bring your own compute) is a future option — see Personal Servers.
Implementation targets
The Personal Server does NOT require the user’s wallet private key — only the master-key signature for key derivation.
API
Data endpoints:
Grant endpoints:
Other endpoints:
Sync endpoints (internal):
Write flow (POST /v1/data/{scope})
- Look up
schemaIdfor scope via DP RPC - Validate request body against schema
- Generate
collectedAttimestamp (UTC) - Construct data file envelope
- Store locally:
~/.vana/data/{scope}/{collectedAt}.json - Return
201 Created - Async: encrypt → upload to storage backend → register in DataRegistry
Authentication (builder requests)
All builder-initiated requests MUST include:
Signing: JSON canonicalized (keys sorted) → UTF-8 → base64url (no padding). Signature is EIP-191 over ASCII bytes of base64url string.
Verification: Personal Server recovers signer, verifies registered builder, validates
aud/method/uri/timestamps, checks grant validity for data reads.
Access control
MCP server
Personal Server includes an MCP server for AI assistant integration. Resources:vana://files, vana://file/{scope}, vana://file/{scope}/metadata, vana://grants, vana://schemas, vana://schema/{schemaId}
Tools: list_files, get_file, search_files — all require EIP-191 signature verification.
Tunneling
Desktop-bundled servers use Vana-managed FRP (Fast Reverse Proxy) for internet accessibility:- FRP server:
proxy.server.vana.org - User URL:
https://{userId}.server.vana.org - Wildcard DNS with Let’s Encrypt TLS
- Tunnel starts on app open, terminates on close
Local data hierarchy
4.2 DP RPC
Endpoint:https://dp-rpc.vana.org
Purpose: Provides fast API access to protocol operations with eventual chain consistency. Operated as a single sequencer / bounded facilitator (not decentralised); trust is bounded by the user signatures it carries and by onchain verifiability.
Trust model:
DP RPC API
Server operations:
Grant operations:
File operations:
Schema operations:
Builder operations:
Utility:
Request format
Response format
ID computation
The DP RPC assigns deterministically computedbytes32 IDs:
4.3 Vana L1 (onchain contracts)
DataPortabilityServers
Address:0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c (Moksha Testnet)
Manages Personal Server registration and trust relationships.
DataPortabilityGrantees
Address:0x8325C0A0948483EdA023A1A2Fd895e62C5131234 (Moksha Testnet)
Manages builder registration.
DataPortabilityPermissions
Address:0xD54523048AdD05b4d734aFaE7C68324Ebb7373eF (Moksha Testnet)
Manages grant creation and revocation. Grants are scope-native (V2): a grant carries a list of scopes and an expiry, not an enumeration of file IDs.
fileIds, with a permissionFileIds accessor) remains deployed on mainnet during migration, but is legacy — new grants MUST use the scope-native model above.
DataRegistry
Address:0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C (Moksha Testnet)
Stores immutable file records.
schemaId. Omitting schemaId is invalid for protocol compliance.
4.4 Builder access (Direct flow)
Builders integrate via the Direct flow: a browser-based approval plus backend polling. There is no builder-facing deep link or session-relay hop.Steps
- Create request. The builder backend calls
createAccessRequest({ scopes, ... })and receives{ requestId, approvalUrl, appAddress }. - User approves. The user opens
approvalUrlin a browser tab, reviews the requested scopes, and signs the EIP-712 grant. The signed grant is submitted onchain via DP RPC. - Poll status. The builder backend polls
getAccessRequestStatus(requestId)untilstatusisapproved(ordenied/expired). On approval the response is{ status, personalServerUrl, grantId, scope }. - Read data. The builder reads the approved data from the user’s Personal Server at
personalServerUrl, paying the protocol fee from escrow (see §4.5).
Status values
Desktop-bundled Personal Servers are reached over a Vana-managed relay/tunnel for internet reachability (FRP,
https://{userId}.server.vana.org). This is infrastructure for Personal Server reachability only — it is distinct from, and not a substitute for, the deprecated builder session-relay flow.4.5 Fees & escrow
Protocol fees are collected through a per-account escrow contract. The Personal Server never holds funds — it only gates a read on the fee showing paid.Escrow
Each account maintains a deposited balance that the protocol settles against on fee-bearing operations.- Deposit — an account funds its escrow balance.
- Settle — the protocol moves funds from a payer to a payee against a referenced operation (
ref). - Withdraw — an account withdraws its unspent balance.
FeeRegistry
Fee amounts are held onchain in a FeeRegistry. Implementers MUST read the current amount onchain rather than hard-coding it. Two fee types exist:Paid read (X-PAYMENT challenge/retry)
A fee-bearing read uses a challenge/retry handshake:
- Builder issues the read; if the fee is unpaid, the Personal Server responds with an
X-PAYMENTchallenge. - The SDK settles the fee from escrow and retries the request with an
X-PAYMENTheader carrying the payment receipt. - The Personal Server verifies the fee is settled, then returns the data. The read is gated on the fee showing paid.
5. Data formats
5.1 Scope taxonomy
5.2 Data file format
JSON envelope (v1):5.3 Grant format (EIP-712)
5.4 Access log format
5.5 App manifest
W3C Web App Manifest with customvana block. Discoverable via <link rel="manifest"> at the builder’s appUrl.
Required vana fields: appUrl, privacyPolicyUrl, termsUrl, supportUrl, webhookUrl, signature.
Signature: EIP-191 by builder address over canonical JSON of vana block (keys sorted, signature excluded).
Verification: Desktop App MUST verify manifest origin, appUrl match, and signature recovery before rendering consent.
5.6 Data connector metadata
6. Protocol operations
6.1 User registration
- User opens Desktop App
- Redirect to Passport (identity provider)
- Authenticate (social/email)
- Wallet created or retrieved
- Setup complete
6.2 Data collection
- User clicks “Connect ” in Desktop App
- Embedded browser opens; user logs in
- Data Connector scrapes data (user’s IP, user’s browser session)
- Raw data sent to Personal Server via
POST /v1/data/{scope} - Personal Server stores locally, then async: encrypt → upload → register
6.3 Connect data flow (Direct flow)
- User clicks “Connect data” on builder’s web app
- Builder backend calls
createAccessRequest({ scopes, ... })→{ requestId, approvalUrl, appAddress } - User opens
approvalUrlin a browser tab, reviews scopes, verifies the app manifest - User approves; the EIP-712 grant is signed and submitted onchain via DP RPC
- Builder backend polls
getAccessRequestStatus(requestId)untilapproved→{ status, personalServerUrl, grantId, scope } - Builder reads approved data from the Personal Server at
personalServerUrl, paying thedata_accessfee from escrow (see §4.5)
6.4 Grant revocation
- User clicks “Revoke” in Desktop App
- Signs revocation
- Submit
DELETE /v1/grants/{grantId}to DP RPC - DP RPC marks revoked immediately; async chain sync
- Personal Server blocks future requests
- Builder receives
410 Grant revokedon next request
6.5 Data deletion
DataRegistry entries are immutable. Deletion is implemented as:- User requests deletion in Desktop App
- Personal Server deletes encrypted blob from storage backend
- Local decrypted copy removed
- Tombstone written via DP RPC
- Other Personal Servers treat tombstoned records as non-existent (
410or404)
7. Security
7.1 Encryption
- All user data MUST be encrypted with OpenPGP password-based encryption before writing to storage backends
- Password is
hex(scope_key)where scope key is derived per section 2 - Personal Servers serve decrypted data to authorized builders over TLS
- Vana MUST NOT have access to plaintext data
7.2 Authentication
- Onchain operations MUST be signed using EIP-712 typed data
- Builder requests to Personal Servers MUST include
Authorization: Web3Signed(EIP-191) - Nonces MUST prevent replay attacks for onchain operations
7.3 Authorization
Personal Server MUST verify before serving data:- Signature valid
- Grant not revoked
- Grant not expired
- Requested scope within granted scopes
- Authorization signer matches onchain grantee
7.4 Transport
- All HTTP endpoints MUST use TLS 1.3
- Personal Servers SHOULD implement certificate pinning
- DP RPC SHOULD implement rate limiting
7.5 Threat model
8. Error handling
Error code structure
Following SMTP convention, the protocol uses a 3-digit error code system:Error codes
Error response format
9. Extensibility
Adding data sources
- Define scope taxonomy (
{source}.{category}) - Create JSON Schema for data structure
- Register schema in
DataRefinerRegistry - Build a Data Connector (optional — not protocol)
Adding storage backends
Implement theStorageBackend interface:
Adding capabilities
Personal Servers declare capabilities in registration:10. Builder SDK
Published as@opendatalabs/vana-sdk on NPM. Builders use the Direct flow (§4.4): a server-side controller creates and polls access requests, and a React hook drives the browser approval.