Skip to content

open protocol for relational trust · validation-as-a-service on top

Trust is personal, cryptographic,
and contextual.

Quidnug is a decentralized protocol where every node decides who to trust from its own perspective. Keys are recoverable without central escrow. Every state change is signed and replay-safe. We operate the public network and offer domain validation as a paid service on top of it, but the whole protocol is Apache 2.0 and you can run it yourself.

25protocol QDPs
1QRP (reviews) shipping
17use case designs
19client libraries
Apache 2.0open source
  • ECDSA P-256 identities
  • M-of-N guardian recovery
  • Per-signer monotonic nonces
  • Proof-of-Trust consensus
  • ACME-style DNS validation

Why you would bother

Most systems pretend trust is a number. It is not.

Universal reputation scores, centralized certificate authorities, and "just email us to reset your key" are the compromises you live with when a system refuses to model trust honestly. Every one of them becomes the failure that puts the platform on the front page.

A single universal score is always wrong for someone.

A credit bureau says you are 712. A ride-share rates you 4.81. A social platform flags you "good standing". The number exists so the platform can delegate judgment; the moment judgment is contested (an error in the file, a vindictive rider, a shadow ban) the subject has no recourse, because the number is authoritative by fiat. Quidnug refuses to produce the number and forces each viewer to answer for themselves.

Central key escrow is a honeypot waiting to happen.

Every platform that holds a "reset my key" switch is one phishing email from a mass takeover. The 2016 DNC breach, the 2022 FTX signer extraction, the quiet cascade of SIM-swap hijacks every quarter: all are "the reset switch was too reachable" by another name. Guardian recovery makes recovery slow, public, and countersignable, which is what you want for anything valuable.

"Signed by whom?" is usually a dangling question.

Most "audit logs" are app-owned rows in a database that the app can edit. Most "signed artifacts" are code-signed by a CI key that rotates silently. When someone eventually asks "did this specific key actually authorize this event at this moment", the answer is usually a shrug. Quidnug makes "signed by whom" the only way state changes.

How trust works

Every trust statement has a subject, an object, a level, and a scope.

Instead of "Bob has a reputation", Quidnug captures "Alice trusts Bob at 0.9 for home contracting, signed on 2026-03-14". That statement is a cryptographic edge. Many such edges form a trust graph, and the protocol answers questions by walking it from the observer's perspective only.

trust = 0.8 trust = 0.9 Carol Alice Bob From Carol's view: trust(Bob) = 0.8 × 0.9 = 0.72 no universal score · multiple paths → take max · depth-bounded BFS

Direct trust is exactly what Alice signed. Transitive trust composes multiplicatively along a path (Carol trusts Alice at 0.8, Alice trusts Bob at 0.9, so Carol trusts Bob at 0.72). If multiple paths exist, Quidnug takes the maximum: one strong recommendation beats a crowd of weak ones. The default traversal depth is five hops.

What you don't get is a number that exists independent of any viewer. Ask a different observer, get a different answer. That is correct behavior. The platform refuses to launder disagreement into consensus.

Read the concepts page · API surface

How domains scope trust

Trust always carries its context on the label.

A trust edge is not valid "in general". It is valid in a specific domain, named with DNS-like dot-notation. A doctor attested by a state medical board is not automatically trusted to sign smart-contract oracle readings. An oracle trusted for ETH/USD is not automatically trusted to issue college diplomas. Cross-domain capture attacks simply do not compose.

gov medical-board.gov texas.medical-board.gov credentials.…medical-board.gov doctors.credentials.… Alice trusted at 0.95 services home.services contractors.home.services Alice trusted at 0.90 separate subtree mainnet ethereum.mainnet price-feeds.ethereum.mainnet oracles.price-feeds.… Alice NOT trusted here no cross-branch inheritance DOMAIN TREE · READ RIGHT-TO-LEFT

Domains can inherit along the parent/child axis when the app opts in (a trust edge at texas.medical-board.gov can be used to answer queries in credentials.texas.medical-board.gov). Inheritance never crosses siblings, and the protocol makes cross-subtree trust leakage impossible by construction.

Pick domain names that look like what they are. Align depth to the authority structure you actually have. Reserve a top-level segment for your organization so domain collisions across federated deployments cannot happen.

Domain semantics · QDP-0003: cross-domain nonce scoping

How consensus works

Different nodes can see different chains. This is a feature.

Quidnug does not produce one globally-agreed chain. It produces per-observer chains tied to each node's trust graph. Proof-of-Trust tiers every incoming block into one of four buckets based on how much the observer trusts the validator who signed it. If you trust a validator, you build on their blocks. If you don't, you don't. Nobody votes about it.

Validator D signs block #12,405 domain: credentials.state-med.gov gossip gossip OBSERVER · ALICE Trusts D at 0.92 via 2 signed edges in this domain TIER Trusted ≥ 0.70 threshold Block #12,405 applied to main chain. All 37 transactions effective. chain tip = #12,405 · no divergence OBSERVER · BOB Trusts D at 0.15 only via a weak 3-hop path TIER Untrusted < 0.20 threshold Block rejected from main chain. Only trust-edge data extracted. chain tip = #12,404 · D is skipped The protocol never asks Alice and Bob to agree. They don't, and that is correct behavior for this domain.

This fits the shape of real consortium problems. A medical consortium where different hospitals trust different CA roots should not agree on attestations signed by the "wrong" root. A cross-jurisdictional election where counties trust their own officials should not replicate precinct blocks from another county's official. A cross-merchant fraud signal network should let each merchant weight reporters differently.

What Quidnug is not: a BFT chain, a Nakamoto chain, or a high-TPS payment rail. There is no coordinator, no "voting", and no block reward. Throughput targets thousands per second per node with aggressive tuning, not millions. This is the price of honesty about disagreement.

Consensus details · Rogue-node security

How keys live and die

Losing a key shouldn't lose the business.

Real systems deal with lost laptops, stolen phones, forgotten passphrases, departing employees, and compromised signing services. Central escrow (the "email us to reset" approach) turns every recovery into a phishing vector and every customer support agent into a potential single point of failure. Quidnug replaces that with a cryptographic protocol: M guardians you chose in advance, a time-lock, and a veto window.

time-lock window · default 24h (configurable 1h…1y) t = 0 init landed veto possible throughout time-lock elapses commit 1 · INIT 3 of 5 guardians sign GuardianRecoveryInit names the new public key 2 · VETO (optional) Subject cancels GuardianRecoveryVeto still holds the current key? stop it. 3 · COMMIT Rotation applied GuardianRecoveryCommit new key is effective immediately STOLEN KEY Attacker can sign but cannot rotate: rotation requires a fresh anchor, which subject + guardians co-authorize. QUORUM CAPTURE M compromised guardians can start a recovery, but the subject vetoes within the time-lock if they still hold a key.

A rotation can be initiated by the subject alone (if they still have the current key) or by any M of their N guardians (if they don't). A time-lock, default 24 hours, opens a veto window: if the rotation was initiated maliciously, the real subject can cancel it. At the end of the window, a guardian commits and the subject's key is replaced.

The threat model is honest. A stolen key cannot rotate itself to lock the subject out, because rotation requires a fresh anchor that the subject or quorum authorizes. A compromised M of N quorum can rotate the subject's key; this is why you pick guardians carefully and keep a veto key. AnchorInvalidation shuts an epoch down immediately if you suspect compromise early.

Key lifecycle · QDP-0002 · QDP-0006

Transaction lifecycle

Every state change is signed, nonced, gossiped, tiered, anchored.

Applications don't mutate state by PUT-ing JSON at a REST endpoint. They build a typed transaction, sign it with their current epoch key, submit it, and watch it land. The node verifies the signature, checks the nonce ledger for replay, anchors it into a block, and gossips the block to peers. Each peer then tiers the block on its own terms.

CLIENT NODE (Go) PEERS 1. Build + sign canonical bytes · ECDSA P-256 nonce = highest + 1 2. Verify sig · nonce ledger · epoch rejects replay, wrong epoch 3. Anchor in block block engine seals sequence + Merkle root 4. Push QDP-0005 5a. Peer A tiers as Trusted trust(A → node, domain) ≥ threshold applies transactions to A's main chain 5b. Peer B tiers as Tentative trust mid-band holds separately · doesn't build on it WHAT THIS BUYS YOU Replay-safe by construction (nonce ledger). Tamper-evident (signature + Merkle anchor). Honest about disagreement (per-observer tiering). No global coordinator required; no universal reputation score produced.

Nonces are per-signer monotonic: your next nonce has to be strictly higher than any nonce the network has seen from you. That gives replay protection without a global counter and without coordination. If you submit a stale nonce, the node returns NONCE_REPLAY and nothing lands.

Seven core transaction types carry all protocol-level state: TRUST, IDENTITY, TITLE, EVENT, ANCHOR, GUARDIAN_*, and FORK_BLOCK. Applications compose workflows on top. Event streams give you append-only, monotonically sequenced per-subject logs for audit trails, supply chains, and state machines.

Transaction types · Event streams · QDP-0001

qrp-0001 · first app-level protocol

A real system on top: trust-weighted reviews.

QRP-0001 is the first Quidnug Review Proposal: a domain-level protocol for reviews, comments, helpfulness voting, flagging, and verified purchases, built entirely from the primitives above. Drop-in widgets for React, Vue, Astro, plain HTML, Shopify, and WordPress ship today.

qn-aurora · nano product grid
4.5 ↑ 0.4 vs crowd
qn-aurora · standard detail page
4.5 ↑ 0.4 · 23 sources
qn-constellation why this rating
CROWD 3+ HOPS 2 HOPS DIRECT YOU
qn-trace weight composition
positive mixed crowd direct transitive width = relative weight · color = rating · outline = direct vs transitive

All three primitives render the same underlying data at three information densities. Zero JS dependencies. Full Schema.org JSON-LD carried alongside for SEO.

Three rating-visualization primitives (qn-aurora, qn-constellation, qn-trace) render per-observer weighted ratings at three information densities. The rating value is one of many signals encoded; confidence, trust proximity, freshness, and the delta from the crowd average all carry through.

The trust-weight formula is a product of four factors (Topical trust, Helpfulness, Activity, Recency). Missing any factor sets the weight to zero for that review, so 500 sybil accounts with no trust path to you contribute exactly nothing to your effective rating.

Reviews page · QRP-0001 spec · Algorithm · One-line install

30-second demo

Stand up a node. Create two identities. Declare trust. Query it.

One binary, one HTTP API, one canonical-bytes signing format shared across every SDK. A signature produced in Python verifies byte-for-byte in Go, Rust, JavaScript, or on the reference node.

# 1. Create Alice's identity
curl -X POST http://localhost:8080/api/identities \
  -d '{"quidId":"alice","name":"Alice","creator":"alice"}'

# 2. Alice trusts Bob at 0.9 for "contractors.home"
curl -X POST http://localhost:8080/api/trust \
  -d '{"truster":"alice","trustee":"bob","trustLevel":0.9,
       "domain":"contractors.home"}'

# 3. Query trust from Alice's perspective
curl "http://localhost:8080/api/trust/alice/bob?domain=contractors.home"
# {"trustLevel":0.9,"trustPath":["alice","bob"],...}
from quidnug import Client, Quid

client = Client("http://localhost:8080")
alice  = Quid.generate("alice")
bob    = Quid.generate("bob")

client.register_identity(alice)
client.register_identity(bob)

client.grant_trust(alice, trustee=bob,
                   trust_level=0.9,
                   domain="contractors.home")

r = client.query_trust(observer="alice",
                       target="bob",
                       domain="contractors.home")
print(r.trust_level)      # 0.9
print(r.trust_path)       # ["alice", "bob"]
package main

import (
  "context"
  "github.com/quidnug/quidnug/pkg/client"
)

func main() {
  c := client.New("http://localhost:8080")
  ctx := context.Background()

  alice, _ := client.NewQuid("alice")
  bob,   _ := client.NewQuid("bob")
  c.RegisterIdentity(ctx, alice)
  c.RegisterIdentity(ctx, bob)

  c.GrantTrust(ctx, alice, bob, 0.9, "contractors.home")
  r, _ := c.QueryTrust(ctx, "alice", "bob", "contractors.home")
  _ = r
}
import { Client, Quid } from '@quidnug/client';

const client = new Client('http://localhost:8080');
const alice  = await Quid.generate('alice');
const bob    = await Quid.generate('bob');

await client.registerIdentity(alice);
await client.registerIdentity(bob);

await client.grantTrust(alice, {
  trustee: bob,
  trustLevel: 0.9,
  domain: 'contractors.home',
});

const r = await client.queryTrust({
  observer: 'alice', target: 'bob',
  domain: 'contractors.home',
});
console.log(r.trustLevel, r.trustPath);
use quidnug::{Client, Quid};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
  let client = Client::new("http://localhost:8080");
  let alice  = Quid::generate("alice")?;
  let bob    = Quid::generate("bob")?;

  client.register_identity(&alice).await?;
  client.register_identity(&bob).await?;

  client.grant_trust(&alice, &bob, 0.9,
                     "contractors.home").await?;

  let r = client.query_trust("alice", "bob",
                             "contractors.home").await?;
  println!("{} {:?}", r.trust_level, r.trust_path);
  Ok(())
}
Full protocol surface · /api/v1 + /api/v2 · OpenAPI 3.0 spec available

the service

Validation-as-a-service, built on the protocol above.

Running your own Quidnug node is free and fully supported. But if you want a third-party-signed attestation that your domain really belongs to you, continuously re-verified, visible to any Quidnug-speaking system, that is what we sell. Same shape as Let's Encrypt, for Quidnug domain identities.

1 CLAIM Submit quid + domain oracles.yourapp.com from the console or via API 2 CHALLENGE Token issued _quidnug-challenge. oracles.yourapp.com TTL 15m, scoped to quid 3 PUBLISH Add TXT record one-click via Cloudflare, Route 53, Google DNS, or manual paste 4 VERIFY Multi-resolver check Cloudflare, Google, Quad9, OpenDNS quorum-of-3 required 5 ATTEST Signed TRUST edge from quidnug root → your quid, domain-scoped in operators.network.… 6 RENEW Continuous re-check hourly to daily (tier-dependent) auto-revoke on drop ACME-style verification. Open-source tooling. Cryptographic output.

pricing

Priced by validation depth, not seats.

Start free on one domain with email verification. Upgrade to Pro when you need DNS ownership and a predictable recheck cadence. Upgrade to Business when your customers want a legal-entity-attested badge. Upgrade to Governance Partner when you want to co-operate the public network.

TIER 0 Free email verified 1 domain 24h recheck TIER 1 Pro DNS ownership per-domain pricing 1h recheck · SLA-lite TIER 2 Business legal entity attested KYB + DNS + SLA 15m recheck · API access TIER 3 Governance Partner cross-sign authority co-operate a seed node custom contract

DNS providers

Works with every DNS provider. Cloudflare, Route 53, and Google Cloud DNS ship day one.

One-click TXT record creation for the three big cloud DNS providers, scoped tokens that cannot touch your other records, and a manual-paste fallback that works with any registrar. Consumer registrars (Namecheap, GoDaddy, Porkbun) roll in over the first quarter.

Shipping day one

CF
Cloudflare
API token · zone-scoped
live
R53
AWS Route 53
IAM assume-role
live
GCP
Google Cloud DNS
OAuth · workload identity
live

Coming soon

NC
Namecheap
API key
planned
GD
GoDaddy
API key + secret
planned
PB
Porkbun
API key
planned
DO
DigitalOcean DNS
personal access token
planned
AZ
Azure DNS
service principal
planned
HE
Hurricane Electric
manual TXT
planned
TXT
Manual TXT paste
any registrar
always

Where it fits

17 detailed use cases across five industries.

Each use case is a full implementation plan: problem statement, architecture with sequence diagrams, concrete SDK code, and a threat model. Pick your domain, read the design, clone the examples.

Client libraries

Three layers. One byte-identical wire format.

Protocol SDKs at the base bind the full wire format in every major language. Reviews widgets sit on top, wrapping QRP-0001 as drop-in UI. Platform plugins wrap the widgets for Shopify and WordPress so non-engineers install from an app store. Signatures verify interchangeably across the whole stack.

PLATFORM PLUGINS one-click install into the CMS your customer already uses Shopify app WordPress plugin more planned REVIEWS WIDGETS · QRP-0001 drop-in rating + review UI; zero-dep aurora/constellation/trace primitives reviews-widget React Vue Astro Web components Angular (planned) PROTOCOL SDKs core bindings to the full protocol surface: trust, identity, events, anchors, guardians, gossip Go Python JS / TS Rust Java / Kotlin C# / .NET Swift Android (Kotlin) Browser extension (MV3) ISO 20022 bridge CLI every layer above is composed from the one below; signing is byte-identical across the entire stack

where this sits

Honest comparisons to every adjacent protocol.

Quidnug isn't positioned against public chains, DID + VC, Sigstore, PGP web-of-trust, or OAuth/OIDC. Each solves a different problem well. The comparisons below spell out exactly where each neighbor wins and where the "who trusts whom from my perspective" question makes Quidnug the right answer.

Relational trustGuardian recoveryDomain scopingNo universal scoreSelf-hostedNo on-chain cost
Quidnug yes yes yes yes yes yes
Public chain partial partial no no partial no
DID + VC no partial partial partial yes yes
Sigstore no no no yes partial yes
PGP WoT yes no no yes yes yes
OAuth / OIDC no partial no no no yes

Each cell is shorthand. Follow the per-comparison links for the actual argument, including where the other tool wins.

The public network

A small cooperative network you can peer with, or ignore.

We operate three seed nodes under quidnug.com. Any operator can bring up their own node and propose bilateral trust with the seeds: we'll tier your blocks, if you tier ours. The protocol enforces the rest.

NEW OPERATOR (Alice) QUIDNUG SEED 1. Signed peering request requester.quidId · domains[] · trustLevel · signature 2. Review verify sig · probe endpoint · policy 3. Seed publishes TRUST edges seed → Alice · in requested domains 4. Alice reciprocates Alice → seed · ≤ 72 hours 5. Peering active · blocks propagate both ways · either side can revoke with TRUST level 0 no secrets were exchanged · no private state crossed the wire

The public network is not a permissioned consortium and it is not a permissionless chain. It is a trust graph seeded by quidnug.com that grows by bilateral consent in specific domains under a reserved network.quidnug.com tree. No secrets are exchanged. No service-level agreement is offered. Either side can unilaterally revoke by publishing a trust edge at level zero.

Under the hood

One Go node, six subsystems, twenty-five design proposals.

The reference node is a single static Go binary. Six cooperating subsystems handle trust path discovery, nonce enforcement, guardian state, block tiering, gossip, and bootstrapping. Every protocol feature ships as a numbered Quidnug Design Proposal with rationale, compatibility analysis, and migration plan.

Client SDKs, Python · Go · JS/TS · Rust · Java · .NET · Swift · Android · React · CLI HTTP REST API · /api/v1 (core) · /api/v2 (guardians + gossip + bootstrap) QUIDNUG NODE (Go) Trust Engine BFS path discovery Nonce Ledger QDP-0001 · replay safety Guardian Registry QDP-0002 · M-of-N recovery Block Engine Proof-of-Trust tiered acceptance Push Gossip QDP-0005 · seconds-latency fanout Bootstrap · Forks QDP-0008 · 0009 · 0010 Peer QuidnugNode instances (P2P), HTTP+sig · gossip · probes · snapshot pull

Honest sizing

Quidnug is a sharp tool. Reach for it carefully.

Strong fit

  • "Who trusts whom?" is a first-class question in your data model (reputation, credentials, consortium fraud detection, cross-org approvals).
  • Keys must be recoverable without central escrow (institutional custody, high-value signing, long-lived credentials, federated identity).
  • State transitions need to be replay-safe and auditable without requiring global consensus (most internal/consortium systems).
  • Federated operators need coordinated protocol upgrades with on-chain activation (fork-block migration).

Weak fit

  • High-TPS payment rails. Auditability beats raw throughput here; target thousands per second, not millions.
  • Fully permissionless public chains with no initial trust seeding and no out-of-band bootstrap channel.
  • Products that need a single universal reputation score. The protocol deliberately refuses to produce one, and an aggregator built on top still has to cite its observer.
  • Single-tenant apps that don't have a "signed by whom" problem. Just use a database.

Validated domains. Open-source protocol. One subscription.

Join the waitlist to claim a domain on the free tier, or run the entire open-source stack yourself and never send us a dollar. Both paths are first-class; the protocol is not hostage to the service.