Protocol Specification v0.1

Your data. Your keys.
Your rules.

Programmable infrastructure for decentralized communication. Identity, encryption, consent-based routing, and encrypted storage — without trusted servers.

👁Centralized E2EESovereignty Gap
identity:platform-controlled account
social graph:fully visible to server
metadata:who, when, where, how often
consent:platform decides
portability:no right to exit
ban =identity erased
vs
🔒Decentrl ProtocolEncryption-Blind
identity:self-sovereign DID + your keys
social graph:opaque to mediator
metadata:encrypted tags only
consent:bilateral crypto contracts
portability:switch mediators freely
you ownkeys, data, relationships

E2EE protects content. Decentrl protects everything else.

TypeScript
MIT License
6 RFCs
3 keys
Ed25519 + X25519 + AES-256
0
Plaintext on mediators
2x
Dual-delivery pattern
DID
W3C decentralized identity
MIT
Open source forever

The entire privacy stack.
One protocol.

Dual-Layer Encryption
Transit encryption (root secret from ephemeral X25519 DH) protects data in flight. Storage encryption (local AES-256 key) protects data at rest. Your mediator has neither key.
Communication Contracts
Bilateral cryptographic agreements with dual Ed25519 signatures. No data flows without mutual consent. One primitive handles user-to-user, user-to-mediator, and user-to-group relationships.
Declarative SDK
Define event schemas with Zod and state reducers. The SDK handles identity, contracts, encryption, routing, sync, and React hooks — all behind defineDecentrlApp().

Schema in, encrypted app out

Define events and reducers. Get identity, encryption, contracts, and sync for free.

app.ts
import { defineDecentrlApp } from '@decentrl/sdk'
import { z } from 'zod'

const app = defineDecentrlApp({
  events: {
    'chat.message': {
      schema: z.object({
        id: z.string().uuid(),
        chatId: z.string(),
        text: z.string(),
      }),
      tags: ['chat.$${chatId}'],
    },
  },
  state: {
    messages: {
      initial: [],
      reduce: {
        'chat.message': (s, d) =>
          s.some(m => m.id === d.id)
            ? s : [...s, d],
      },
    },
  },
})
chat.tsx
import { useDecentrl, useDecentrlState } 
  from '@decentrl/sdk-react'

function Chat({ chatId }) {
  const { publish } = useDecentrl()
  const messages = useDecentrlState(
    s => s.messages.filter(
      m => m.chatId === chatId
    )
  )

  return (
    <div>
      {messages.map(m => (
        <Message key={m.id} data={m} />
      )))}
      <Composer onSend={text =>
        publish('chat.message', {
          id: crypto.randomUUID(),
          chatId, text,
        })
      } />
    </div>
  )
}

Three steps to zero-knowledge

01

Generate Identity

Three keys generated on-device. Your DID embeds public keys and mediator endpoint — anyone can verify you and send you a contract request without a registry lookup.

generateIdentityKeys()
02

Establish Contract

Both parties exchange ephemeral X25519 keys and sign with Ed25519. A shared root secret is derived locally — no secret ever crosses the network.

client.contracts.request(did)
03

Communicate

Events are encrypted, signed, and dual-delivered — one copy to the recipient, one to your own mediator. Both parties keep complete records. The mediator sees nothing.

client.publish(type, data)

One install.
Zero compromises.

$npm install @decentrl/sdk zod