DeDi Node

A self-hostable server for the DeDi standard, with an append-only Merkle log underneath: signed checkpoints, inclusion and consistency proofs, and other nodes witnessing that the log was never rewritten. It is a Merkle log, not a blockchain. New here? Start with the overview, then the quickstart.

All documentation

Served by this node, from the copy embedded in the binary it is running — so these are the documents for this build, not for whatever is on a branch somewhere.

Start here

What this is, how to run one, and why it is not a blockchain.

OverviewDeDi Node is a self-hostable, open-source server for the Decentralized Directory protocol, with an append-only Merkle log underneath so anyone can check that what it serves was published…
QuickstartFrom nothing to a signed, provable record in about five minutes. You need Docker, curl and jq. No Go toolchain and no source checkout: everything runs from the published image…
Why DeDi Node existsI built this because I was running a real Beckn network in production, and the single most important component in it — the registry, the thing every party trusts to answer "who is this…
ArchitectureWhat each part of the node proves, and what it does not. The short version: the log makes history checkable, witnesses make it checked, replication keeps it up, and none of those three is a…

Running a node

Getting one up, configuring it, and choosing what it does.

ConfigurationEvery environment variable dedid serve reads, and every CLI subcommand. The node has no config file: one binary, configured by its environment, so the same image is every role. Unset means…
APIEvery route the node serves, what it accepts, and what it answers. The eight /dedi/lookup|query|versions routes are the DeDi standard's read API (api/openapi.yaml); everything else is this…
One-click deployDeploying gives you a Postgres with a volume and a DeDi node pulling flywheelai/dedi-node, on a public domain, signing a checkpoint every 30 seconds. It asks you nothing — the database…
Deployment modesdedid ships as one binary with three trust planes. Two of them are feature flags: set the env vars and the plane turns on, unset them and it does not exist. There are no separate builds,…
Replication and high availabilityRaft is a crash-fault protocol. A cluster keeps the directory available when a replica dies. It does not make the directory trustworthy: three replicas run by one operator follow that…
Crawler and mirrorThe DeDi standard has two roles: a publisher signs files and hosts them, and a server crawls publishers and answers the read API for what it found. This node is a publisher by default (file…

Operating it

The console, and every write it can make.

The operator consoleThe write plane's user interface, at /admin. Five tabs. Most of what they do is a signed entry in the node's log; Domains only reads.
Onboarding a participantAdmitting an identity to a registry: the Participants section's Onboard a participant disclosure in the console, and the signed write behind it. This is the operation that decides who the…
Key rotationReplacing the key a participant signs with, without removing the participant, and the reasoning about time that makes a rotation safe rather than an outage.
RevocationWithdrawing a binding: the console's Revoke a participant panel, which opens against the participant selected in the Participants table, what "revoked" means to everyone downstream, and how…
Child nodes and namespace delegationA node can now stand in three different relations to another node, and the whole design rests on not confusing them.
Push notificationRevocation used to travel only as fast as caches expired. Measured end to end against two live beckn-onix v1.8.0 adapters, with the participant record declaring ttl: 20:
Discovery: who serves a domainAnswering "who serves domain X" rather than only "what key does this known subscriber use". The console's Who serves section, and the ?domain= filter behind it.
Governance (v0)How identities get into — and out of — a dedid registry. Status: v0, deliberate minimum. The signed write plane carries out these decisions; it does not make them.

Proving it

The parts that make a claim checkable by someone who does not trust you.

WitnessingOne node checking, on a schedule, that another node's log has only ever been appended to — and recording what it found in its own log, where the target cannot reach it. This is the part…
File publicationThis node implements the producer half of the DeDi standard's file publication model (publishing-dedi-files.md): it signs and serves a DeDi file per registry, plus a signed manifest, so a…

Against the standard

Where this node and the specification agree, and where they do not.

Conformance against the DeDi standardNot to be confused with the dedi.global platform's own OpenAPI document (73 paths), which describes a hosted implementation, not the standard. It matters because ONIX was built against it,…
Open gaps against the DeDi standardMeasured against the LFDT standard at commit 52e120d. Every claim here was checked by running code or reading the spec text, never inferred from our own docs — the entries marked proven…
Built-in reference registry schemasThe DeDi standard ships five reference registry schemas, read-only in the spec submodule at docs/spec/lfdt/schemas/:

Use cases

Deployments that depend on it, and what they check.

Use case: a Beckn networkBeckn is the first thing this node was built for. Every signed Beckn message is checked by the receiving ONIX adapter against the sender's key in a DeDi registry, so the registry is the…
Use case: CRESTCREST issues verifiable credentials for work: who did what, under which terms, on whose authority. A credential is only as good as the facts behind it, so CREST publishes those facts to a…

History

The original plan, superseded where the other pages say so.

DeDi Node — Design DocumentHistory. This is the original plan, written in July 2026 before most of the node existed. It is kept because its reasoning still explains the code, but it describes intentions, not the node…

Beckn message validated against this registry

sequenceDiagram
    autonumber
    participant BAP as ONIX · BAP
    participant BPP as ONIX · BPP
    participant D as dedid
    BAP->>BPP: select (signed)
    BPP->>D: GET /lookup/bap.example.com/subscribers.beckn.one/{keyId}
    D-->>BPP: signing_public_key (+ inclusion proof)
    BPP->>BPP: verify signature ✓
    BPP-->>BAP: on_select (signed)
    BAP->>D: lookup BPP key → verify ACK ✓
    Note over D: bad/absent key → 401 reject

ONIX's registry URL is a locked constant pointing at fabric.nfh.global, so an adapter needs a small patch to use this node; see the Beckn use case.

Decentralised trust: one node witnesses another

sequenceDiagram
    autonumber
    participant A as Node A · primary
    participant B as Node B · witness
    B->>A: GET /log/checkpoint (signed)
    B->>A: GET /log/proof/consistency?old&new
    B->>B: verify append-only (RFC 6962)
    B->>B: record verdict in own log
    Note over B: forged history → alarm

Test cases

#TestResult
1Published dedi-conformance suite v0.0.1 against the public node22/22: core, versioning, publication, beckn
2In-process conformance module against the pinned openapi.yaml5 tests, 21 subtests pass
3ONIX dediregistry client (v1.8.0) over the wire6/6 pass
4Live two-adapter Beckn network resolving keys against this noderunning; see use case
5Inclusion proof checked in the browser (WebCrypto)/verify
6Witness verifies a target is append-onlyverdicts at /dedi/witness
7Witness detects a forked history, and a rewrite at the same sizealarm (unit tests)

Results measured 3 October 2026 on build sha-69bffe0; how to rerun them is in conformance.

API

The read routes, relative to this node. Plain GET, no auth. Every route, its parameters and its errors: API.

EndpointReturns
/dedi/lookup/{namespace}/{registry}/{record}the current version of a record
/dedi/lookup/{namespace}/{registry}registry metadata and schema
/dedi/lookup/{namespace}namespace metadata
/dedi/query/{namespace}[/{registry}]a filtered, paginated listing; ?domain= for who serves a domain
/dedi/versions/{namespace}[/{registry}[/{record}]]full version history
/dedi/log/checkpointsigned tree head (C2SP checkpoint)
/dedi/log/proof/consistency?old=&new=append-only proof between two tree sizes
/dedi/log/historycheckpoints and writes over time
/dedi/witness[/{origin}]what this node has verified about other logs
/dedi/delegations/{namespace}child namespaces delegated, and their witness verdicts
/dedi/networkpeers, reachability, witness health, cluster state
/dedi/statsrequests served, by status class, plus uptime
/.well-known/dedi.index.jsonsigned DeDi manifest; files under /dedi-files/
/healthz, /metricsliveness for probes; Prometheus metrics

Lookup modifiers: ?proof=inclusion attaches a Merkle inclusion proof and the signed checkpoint it verifies against; ?version_id= pins an exact version; ?as_on= resolves the record as of a date (YYYY-MM-DD, the close of that day in UTC) or an RFC 3339 timestamp. Unknown or repeated parameters are a 400, never silently ignored. Example against the public node (on your own node, use your host and a record you published):

curl -s "https://dedi.beckn.try-dough.com/dedi/lookup/bpp.example.com/subscribers.beckn.one/76EU7ofwRCF1aobQkShARrf1PAUsNpHqWUJoynPu9w45YFKmzqaPmy?proof=inclusion"

/dedi/network reports whether configured peers answered. That is an observation, deliberately weaker than witnessing: reachability says a node replied, while a witness verdict is evidence that a log has not been rewritten. Raft replicas of one node share its key and prove nothing about each other; see replication. Witness verdicts are published at /dedi/witness; the _witness namespace that stores them is hidden from the directory browser and the standard's read routes.

Getting registered

Onboarding is operator-gated: there is no self-service registration, by design — who exists on a network is a governed decision, and every onboarding or revocation is an auditable entry in the transparency log. To register a participant on the networks served by the reference nodes, email contact@theflywheel.in with your subscriber id, type (BAP, BPP, BG or CDS), namespace, and Ed25519 signing public key. Details: governance.

Run your own node

One container and one Postgres. Needs Docker; no source checkout and no Go toolchain.

docker network create dedi-net
docker run -d --name dedi-pg --network dedi-net \
  -e POSTGRES_USER=dedi -e POSTGRES_PASSWORD=dedi -e POSTGRES_DB=dedi postgres:16-alpine
until docker exec dedi-pg pg_isready -h 127.0.0.1 -U dedi -q; do sleep 1; done
docker run -d --name dedi-node --network dedi-net -p 8080:8080 \
  -e DATABASE_URL='postgres://dedi:dedi@dedi-pg:5432/dedi?sslmode=disable' \
  -e DEDI_ORIGIN=localhost/log flywheelai/dedi-node:latest
until curl -sf localhost:8080/healthz >/dev/null; do sleep 1; done
curl -s localhost:8080/dedi/log/checkpoint   # your own signed tree head

The node mints its identity key on first start and prints the public verifier key in its log. Opening the write plane and making a first signed write: quickstart. Every setting: configuration. Witnessing, anchoring and replication: deployment modes.

Protocol & references