block / block/buzz

RFC: Web of Trust — portable evidence and explainable reputation views across relays

Open
#5,880 1 comment 2 reactions 0 assignees View on GitHub
enhancement
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Motivation

### Purpose, in plain words

When someone new shows up in your community — a human contributor or an agent
— you want to answer a scoped question: **what evidence should inform whether I
trust them for this task?** Today that evidence is scattered across signed
vouches and contribution outcomes. Buzz may not discover evidence carried by a
relay it is not using, and evidence available from only one relay can disappear
when that relay or its storage does.

This RFC makes trust **visible, checkable, and portable**:

1. **Visible** — vouches become signed, queryable events, with visibility still governed by the relay/community that carries them (Part 1, three registry entries).
2. **Checkable** — an optional, advisory-only lookup interface shows the *evidence* first. A viewer MAY derive an explainable local summary or score from that evidence, but Buzz does not publish that derived score as a portable, canonical, or authoritative identity property (Part 2).
3. **Portable** — an optional **Decentralized Knowledge Graph (DKG)** layer
organizes selected claims and their provenance as connected,
machine-readable graph data that independent nodes can replicate beyond one
relay. This RFC uses the
[OriginTrail DKG](https://docs.origintrail.io/how-dkg-works/key-concepts) as its
reference implementation and separates drafts, community knowledge, and
deliberately anchored records (Part 3). Replication and anchoring are
different: an anchor proves an integrity commitment, while continued
payload availability still requires storage and replication.

> A provider is a lens the community chooses, not a fact the network imposes.

**The minimal implementation ask is Parts 1–2.** A relay that adopts neither
behaves exactly as today; a relay that adopts both and configures nothing also
behaves exactly as today (null default). Part 3 stays in this RFC as the
optional OriginTrail reference profile and working beta, but nothing in Parts
1–2 requires a DKG node.

---

## Proposed solution

### Contents

| Section | What it gives the reader |
|---|---|
| [Purpose](#purpose-in-plain-words) and [summary](#summary) | The user problem, the proposal, and the concrete outcome |
| [Architecture](#architecture--what-actually-moves-across-relays) | Infrastructure boundaries and a concrete Community A-to-B evidence trace |
| [Part 1](#part-1--register-attestation-kinds) and [Part 2](#part-2--the-reputationprovider-extension-point) | The minimal Buzz change: event kinds plus an advisory provider seam |
| [Nostr and the decentralized graph](#how-nostr-and-a-decentralized-knowledge-graph-fit-together) | Division of labor, portability, and bounded graph reasoning |
| [Part 3](#part-3-optional-profile--evidence-backed-reputation-on-a-decentralized-knowledge-graph) | The optional OriginTrail reference profile and current beta boundary |
| [Run the reference implementation](#36-run-the-complete-reference-implementation) | The complete relay + DKG node + integration + app setup, followed by an evaluation checklist |
| [Safety](#security-privacy-and-abuse-analysis), [alternatives](#alternatives-considered), and [rollout](#rollout) | Risks, rejected designs, success criteria, and staged adoption |

### Summary

Buzz's roadmap lists **"Web-of-trust reputation across relays"** under *Strong opinions, pending code* (README), and the vision docs already commit to a philosophy:

> "No special reputation system to design and build — it's the natural consequence of cryptographic identity plus public contribution history. … That vouch is a signed event. You can see it. You can weight it." — VISION_SOVEREIGN.md

This RFC proposes the two smallest pieces that turn that philosophy into code without violating it:

1. **Attestation events** — reuse the NIP-32/NIP-85 event mechanics for labels,
trusted assertions, and source selection, with the smallest provisional Buzz
vocabulary needed to express a vouch.
2. **A reputation-provider extension point** — a narrow, **advisory-only** trait for *evidence discovery, not permission policy*, with a **null provider as the default**: a relay with no provider configured behaves exactly as today.

**Advisory-only is normative.** Provider output MAY inform context, ranking, and human-facing surfaces; it MUST NOT gate identity, membership, moderation, signing, or write permissions. An evaluator MAY derive a viewer- and community-scoped score when it exposes its method, evidence, freshness, and resolution state. Any automatic enforcement semantics would need their own RFC.

No global score and no portable Buzz-derived score. No mandatory provider. No consensus requirement between relays. No unbounded operator spend.

Reputation is the first application of a more general capability this design opens: **portable, trusted context** — evidence-backed claims of any kind, carried across relays and between Buzz and external systems, which Part 3's memory and provenance layers support beyond trust claims alone.

### How an evidence graph resolves into a useful reputation view

A signature makes an individual statement attributable and tamper-evident; it
does not organize that statement into an answer. A growing bag of vouches,
patches, reviews, CI results, merges, reversions, disputes, and corrections
still leaves every client to reconstruct the same relationships: who is the
subject, which project and community does the evidence concern, which outcomes
support the claim, which claims share one source, and what has been revoked or
superseded?

The graph makes those relationships first-class, then resolves only the small,
viewer-scoped subgraph needed for a decision:

```mermaid
flowchart LR
E["Signed events
vouches, patches, reviews,
CI, merges, reversions"]
P["Deterministic projection
verify signatures and preserve ids
link subject, issuer, scope, and lineage"]
G["Subject evidence subgraph
active claims, evidence paths,
corrections, and contradictions"]
Q["Bounded provider query
viewer sources, community scope,
time window, and resolution state"]
O["Resolved evidence view
supported outcomes, independent vouches,
disputes, freshness, and missing sources"]
H["Human decision
optional explainable local summary
never a portable verdict"]

E --> P --> G --> Q --> O --> H
```

For example, the result may say:

> **Rust review · Community B · last 180 days** — 3 merged patches confirmed
> by 2 independent maintainers; 1 reverted patch; 1 unresolved dispute; one
> configured source unavailable. **Resolution: Partial.**

Every item links back to its signed source and provenance path. A viewer may
derive a local summary such as *strong evidence for Rust review; no evidence
for release management*, but that summary is neither global nor portable.

This distinction is deliberate:

- **Nostr signatures** answer *who said what, and was the event altered?*
- **A knowledge graph** answers *how do the claims, subjects, outcomes,
corrections, and sources relate?*
- **A decentralized knowledge graph** answers *can each community curate its
trust context — choosing which evidence remains private, which is shared,
and how published records are corrected or superseded — while each recipient
resolves its own reputation view from that provenance?*

Once the evidence is graph-shaped, a provider can also apply bounded,
versioned rules to derive inspectable facts such as *supported contribution*,
*shared source lineage*, or *conflicting active claims*. Those derivations add
useful structure without producing an authoritative trust score.

A relay index or centralized knowledge graph can organize a local trust corpus.
The DKG profile earns its additional operational cost when communities need to
steward their Web-of-Trust context at its source while selectively sharing
vouches, contribution outcomes, and decision traces across community
boundaries. Here, **context ownership** means authority to compose the
community's Context Graph, keep eligible material private, publish selected
records, and issue lifecycle updates. It does not mean altering another
author's signed statement, making an already replicated record disappear, or
exporting the curator's verdict. The receiving community inspects the shared
provenance and computes its own reputation view.

### What this RFC asks maintainers to decide

This is **one architectural direction with three separable implementation
layers**. They can be reviewed and shipped incrementally:

| Layer | Change | Requested decision |
|---|---|---|
| **1. Nostr event support** | Register kinds 1985/30382/10040 and prove their persistence/query lifecycles. | Proposed for Buzz; useful by itself. |
| **2. Buzz reputation surface** | Add the backend-neutral `ReputationProvider`, null/local adapters, normalized evidence, and advisory UI. | Proposed as an experimental Buzz feature. |
| **3. Decentralized evidence profile** | Project selected evidence into an optional DKG adapter for connected provenance, replication, and cross-relay resolution. | Included as the reference implementation, not a Buzz core dependency. |

The first two layers are the minimal upstream ask. The third demonstrates why
the seam is useful when evidence must outlive one relay or database operator.
The complete Part 1 lifecycle corpus, provider-neutral Part 2
`ReputationProvider`/`NullProvider`/`LocalProvider`/NIP-85 adapters,
cross-relay migration proof, personal Edge-node packaging, and production VM
anchoring are not implemented yet.

The downstream reference beta demonstrates registered attestation kinds,
human-signed NIP-32 vouches, evidence attachment, revocation/supersession
history, automatic post-turn agent memory with a durable retry outbox,
per-channel Context Graphs, and bounded Traces/Graph views backed by graph
provenance. It uses one DKG-specific provider path; it does **not** yet
demonstrate provider interchangeability or the relay-migration acceptance test.

---

### Architecture — what actually moves across relays

The portable unit is **signed evidence**, not a reputation verdict. Each
community operates its own Buzz relay and, when enabled, its own DKG node. The
same Nostr event can be published or fetched on another relay, while selected
events can also be projected into a Context Graph replicated through the DKG.
The destination community verifies what it can reach and recomputes its own
view.

```mermaid
flowchart LR
subgraph A["Community A"]
direction TB
subgraph AB["Buzz infrastructure"]
direction LR
UA["Buzz app / viewer A"] -->|"signed events + reads"| RA["Buzz relay A"]
end
IA["Optional Buzz–DKG adapter
typed queries + evidence projection"]
subgraph AD["DKG infrastructure"]
NA["DKG node A
community Context Graph replica"]
end
RA -->|"authorized, channel-scoped"| IA
IA -->|"read / project selected evidence"| NA
end

subgraph X["Shared transport, not shared policy"]
direction TB
N["Nostr portability
same signed event + relay hints
no automatic relay gossip"]
G["OriginTrail DKG network
Context Graph replication
optional VM anchoring"]
end

subgraph B["Community B"]
direction TB
subgraph BB["Buzz infrastructure"]
direction LR
UB["Buzz app / viewer B"] -->|"request evidence-first view"| RB["Buzz relay B"]
end
IB["Optional Buzz–DKG adapter
bounded provider queries"]
subgraph BD["DKG infrastructure"]
NB["DKG node B
community Context Graph replica"]
end
RB -->|"authorized, channel-scoped"| IB
IB -->|"read replicated evidence"| NB
end

A -.->|"signed Nostr event"| N
N -.->|"signed Nostr event"| B
A -->|"replicated graph data"| G
G -->|"replicated graph data"| B
```

### End-to-end trace — evidence moves from Community A to Community B

Suppose a contributor asks to review Rust code in Community B using work they
completed in Community A as evidence:

1. **Evidence is created in Community A.** The contributor signs a patch event;
a maintainer signs the merge outcome and an optional vouch. Relay A retains
the native Nostr events.
2. **Community A curates its graph.** Its Context Graph curator applies the
community's capture policy, verifies the selected events, and projects only
evidence eligible for sharing. Private notes remain in Working Memory and
never enter the shared graph.
3. **The graph connects the evidence.** The projection links the contributor's
npub to the patch, merge, issuer, project and capability scope, timestamps,
and lineage. It preserves the signed source events instead of rewriting
them.
4. **Community A shares selected context.** The native events can be fetched
through Nostr, while the selected connected evidence is replicated through
the DKG. Community B receives Community A's evidence and provenance — not
Community A's score or permission decision.
5. **Community B resolves a bounded view.** Its provider queries for the exact
contributor, Rust-review scope, accepted sources, and time window. It checks
the local graph replica and reachable signed sources, reporting `Partial` if
a configured source cannot be reached.
6. **Community B makes its own decision.** Buzz can show, for example, three
merged patches, two independent maintainers, one revert, and the evidence
links. Community B applies its own source preferences and policy; a human
decides whether that evidence is sufficient for the task.
7. **Later updates preserve the trail.** When an authorized correction,
revocation, or supersession arrives, Community A's curator appends it and
updates the graph's active-state link. Community B sees the prior evidence
and its new status on the next resolution and recomputes its view. The update
changes the current interpretation; it does not pretend already shared
history was erased.

Five boundaries are deliberate:

1. **Relays do not automatically gossip everything to one another.** A client,
publisher, or provider must make the signed event available on relay B, or
the destination must resolve it from an advertised relay hint.
2. **Curatorship controls the source graph.** Each community decides what enters
its Context Graph, what remains private, what is shared, and how authorized
lifecycle updates change its current view. A curator cannot rewrite the
original signatures or erase copies that recipients already obtained.
3. **The DKG path is optional.** It preserves linked evidence only while the
relevant Context Graph is replicated and retained; anchoring alone is not
payload availability.
4. **Verdicts do not travel.** Permissions, moderation state, and a provider's
score never cross the boundary as authority. Community B recomputes a view
from the evidence and source preferences it accepts.
5. **Failure stays visible.** Missing sources yield `Partial` or `Unavailable`,
never a fabricated zero and never an implicit negative judgment.

### Relationship to the existing NIP-TR proposal

[Buzz issue #3721](https://github.com/block/buzz/issues/3721) proposes NIP-TR:
a portable, issuer-signed capability tier and optional score, with optional
relay enforcement. **This RFC recommends treating the two as companion
layers**, not competing trust systems:

- NIP-TR transports an issuer's **result** (tier/score).
- This RFC transports and normalizes **evidence**, lets the viewer choose
sources, and keeps evaluation and enforcement outside the provider contract.
- A NIP-TR event can be one signed assertion consumed by a provider, or a
deliberate issuer result derived from an evidence packet; it does not replace
the underlying evidence or become an automatic permission under this RFC.

If maintainers prefer one specification, the evidence envelope and provider
contract can be folded into NIP-TR while keeping this layering. What should not
be merged is a second portable, canonical score. The implementation should not
claim a new trust primitive until that integration point is agreed.

---

### Basis in Buzz's published direction

- Buzz already lists *"Web-of-trust reputation across relays"* on its roadmap,
and its designed maintainer flow is: query an npub's contribution history,
inspect vouches from maintainers you trust, then assess risk
([VISION_PROJECTS.md](https://github.com/block/buzz/blob/main/VISION_PROJECTS.md#the-web-of-trust)).
- Buzz's identity model treats contribution history as signed and portable,
including for agents whose reputation spans projects. Signatures establish
attribution and integrity, not truth; this RFC supplies the evidence and
provenance needed for the viewer to make that judgment
([VISION_SOVEREIGN.md](https://github.com/block/buzz/blob/main/VISION_SOVEREIGN.md#identity)).

---

### Part 1 — Register attestation kinds

Reuse the existing event mechanics; define only the smallest experimental Buzz
vocabulary. Buzz's allowlisted kind registry
(`crates/buzz-core/src/kind.rs`) currently includes none of these kinds.

| Purpose | Kind | Lifecycle | Source convention |
|---|---|---|---|
| Raw vouch / label | `1985` | regular (non-replaceable; accumulates) | [NIP-32](https://github.com/nostr-protocol/nips/blob/master/32.md) (labels, `L`/`l` namespaces) |
| User-subject Trusted Assertion | `30382` | parameterized replaceable (keyed by author + kind + canonical `d`) | [NIP-85](https://github.com/nostr-protocol/nips/blob/master/85.md) (30383–30385 cover other subject types) |
| Preferred trusted-assertion source list (per `kind:tag`, viewer-published) | `10040` | replaceable (latest per pubkey wins) | [NIP-85](https://github.com/nostr-protocol/nips/blob/master/85.md) |

These are **three different storage lifecycles**, not three rows of the same shape: a vouch accumulates, an assertion is updated in place per subject, a source list is wholly replaced. "Regular" does not mean indelible: kind 1985 events remain subject to relay retention, NIP-09 deletion, and expiry policy. Acceptance tests MUST prove **persistence and query behavior per lifecycle class**, not admission alone: accumulation for 1985; out-of-order and equal-timestamp replacement for 10040 and 30382; author/kind/`d` isolation; missing and conflicting `d` tags; deletion/expiry; no stale-version resurrection; and exact query visibility after each transition. (Relay lifecycle dispatch is currently range-based — supersession bugs become reputation bugs precisely here.) Semantic trust validation stays **out** of Part 1.

**Example — a maintainer vouches for a contributor (kind 1985):**

```json
{
"kind": 1985,
"tags": [
["L", "buzz.wot"],
["l", "vouch", "buzz.wot"],
["p", ""],
["e", ""]
],
"content": "reviewed 3 merged patches; reliable on async work",
"pubkey": "", "sig": "…"
}
```

(`vouch` and the provisional `buzz.wot` namespace are application ontology layered on NIP-32 — NIP-32 itself only defines the label mechanics. The final namespace is a maintainer decision; a reverse-domain namespace would reduce collision risk.)

**Why 10040 matters:** it makes source choice **viewer-side**. NIP-85 is explicitly a format for service-computed assertions, including counts and ranks; it does not itself provide evidence-first semantics. Buzz can consume those assertions as one input while this RFC declines to expose a canonical score or automatic verdict. Each user chooses which assertion sources *they* trust, per result type — the network imposes none.

**Cost of Part 1 alone:** three registry entries plus a lifecycle/query regression corpus of the shape above — a small but real test surface, and the whole of it. It is useful by itself: clients can immediately publish and query vouches with no new infrastructure.

---

### Part 2 — The `ReputationProvider` extension point

#### 2.1 The trait (evidence discovery, not permission policy)

```rust
// PROVISIONAL illustration — final signatures are a maintainer decision.
// Discovery is batch-first; policy evaluation stays OUT of discovery.
trait ReputationProvider {
/// Advisory-only. MUST NOT automatically gate identity, membership,
/// moderation, signing, or writes.
async fn attestations(&self, q: Query) -> Result>;
}

struct Query {
viewer: Option, // None = explicitly unpersonalized
subjects: Vec, // batch-first
community: Community,
scope: Scope, // project, channel, capability, or all
claim_types: Vec,
since: Option

- **Batch-primary, paginated, deadline-bounded** — operator cost stays bounded.
- **`NullProvider` is the default**, deterministic, and returns `Disabled` —
never an empty `Complete` batch. A `LocalProvider` (relay-computed,
single-relay scope) and a NIP-85 adapter are the first real implementations;
all providers pass **one shared conformance suite**, including outage and
degradation paths.
- Viewer-policy evaluation (turning evidence into a view) is a separate, optional surface. It MAY produce an explainable viewer-local score, but Buzz MUST NOT republish that derived score as a portable claim or canonical identity property. A provider-signed NIP-85 rank remains an attributable input claim, not Buzz's verdict.

`Complete` with zero claims means *no evidence in the requested scope*.
`Disabled` means *not configured*. `Unavailable` means *the lookup failed*.
`Unknown` is a viewer-level judgment when the available evidence does not
support a conclusion; it is not a provider transport state.

#### 2.2 The Trust Claim envelope

Every reputation edge a provider returns uses a small normalized Buzz schema. A returned claim is either the original signed event or a projection that carries a stable source reference, source digest, author, signature, and verification status. A provider's own assertion that an issuer said something is not sufficient evidence. Four rules do most of the safety work:

At minimum, the versioned projection carries:

| Field group | Required information |
|---|---|
| Claim identity | `claim_id`, `subject`, `issuer`, `claim_type`, `claim_layer` |
| Decision scope | host-derived `community`, optional channel/project/capability, source visibility |
| Signed source | event or stable source reference, digest, author, signature, verification status |
| Lifecycle | `created_at`, optional `expires_at`, and `status` |
| Provenance | `derived_from[]` plus supersession/revocation references where applicable |

This is enough for different providers to return the same inspectable shape
without pretending they reached the same judgment. Provider identity, version,
query `as_of`, resolution state, and per-source diagnostics belong to the
enclosing `Batch`, because they describe the resolution attempt rather than the
source claim.

**a) Layer separation.** Every claim declares
`claim_layer: observation | derived_analysis`. A derived analysis MUST cite the
observations it rests on and cannot masquerade as source evidence. Action
recommendations are outside the `TrustClaim` envelope and outside this RFC.

**b) Explicit lifecycle semantics.** Claims carry
`status: active | expired | revoked | superseded`. Source unavailability is a
property of the enclosing resolution attempt, never a synthetic claim. UIs
MUST render *not configured*, *no evidence*, *partial*, *unavailable*, *negative
evidence*, and *unknown judgment* distinctly.

**c) Lineage.** Every claim carries `derived_from` (an array of prior claim/event ids; `[]` when no provenance exists). Corroboration counts **independent lineages, not report volume** — ten reports sharing one lineage are one data point, which is the defense against brigading. Declared lineage is not proven independence; providers SHOULD verify cited sources are reachable.

**d) Visibility preservation.** A provider MUST NOT make a claim visible to a wider audience than its source. Tenant and channel scope are authorization boundaries, not query hints.

**Wire-format boundary:** kind 1985/30382/10040 events remain valid Nostr events in their native formats. `TrustClaim` is Buzz's versioned **internal normalized projection**, not a redefinition of NIP-32 or NIP-85 `content`. A deterministic projection from native events to `TrustClaim`, including signature/source verification, is part of the conformance suite.

**Boundary between public vouches and private person observations:** a person
may deliberately publish a public kind 1985 vouch, which remains public subject
to relay policy. Derived person profiles and person-targeting observations that
were not explicitly published as public vouches default private,
issuer-scoped, expiring, and revocable. No person-targeting claim is eligible
for global scoring or automatic enforcement.

---

### Proposed reputation UX

> This is the target UX for Parts 1–2, not a description of the current DKG Memory beta.

**A maintainer vets a new contributor.**

1. Right-click an npub → *Reputation*.
2. Buzz calls `attestations([npub])` on the configured provider.
3. The panel leads with evidence: "3 vouches — 2 from maintainers you follow (10040) — 1 unresolved dispute", each with issuer, date, and linked evidence events. An optional local summary can explain how that evidence was weighted; "no evidence" and "provider unavailable" look different.
4. The decision stays human. Nothing was gated.

**Degradation is honest.** No configured provider → the panel is absent or says
*not configured*. Provider down → *unavailable*, never *no evidence*. Deadline
exceeded after some sources respond → `Partial`. A relay that never configures
any of this remains fully conforming.

---

### Provider classes and portability

| Provider | Evidence survives | Cost | Fits |
|---|---|---|---|
| **Null** (default) | — | zero | every relay, by default |
| **Local** | the relay's lifetime | low | single-relay communities |
| **NIP-85 sources** (viewer-chosen) | provider's lifetime | low | plural, opinion-oriented |
| **Evidence-backed knowledge graph** | relay migration while data remains replicated/available | additional node/storage cost; metered publishing when chosen | cross-relay, audit-oriented |

The fourth class is the strongest path to the roadmap's *across relays* goal.
Its portable unit is a **provenance-rich evidence record**, not a score, with
availability limits stated explicitly rather than implied by anchoring.

---

### How Nostr and a Decentralized Knowledge Graph fit together

The division of labor is simple: **Nostr expresses trust; the DKG connects and
preserves its evidence.** Nostr supplies identity, signed events, transport, and
the social setting in which a vouch is made. The graph links those events to
subjects, outcomes, corrections, and provenance, and independent nodes can
replicate selected Context Graphs beyond one relay. The reference adapter is
the [OriginTrail DKG](https://docs.origintrail.io/how-dkg-works/key-concepts); its
[documentation](https://docs.origintrail.io/) and
[open-source node](https://github.com/OriginTrail/dkg) provide implementation
background. Other stores may implement the same provider contract.

| | Nostr (required) | DKG (optional) |
|---|---|---|
| Gives you | identity, signed events, multi-relay transport, social coordination | provenance graphs, linked evidence, replicable shared community memory, optional anchored identifiers |
| Verifies | who said it, and that it wasn't altered | records **declared** provenance and integrity of claim links; adapters verify cited signed sources where reachable |
| Costs | existing relay/client cost | additional node/storage cost; metered publishing only when chosen |

#### Optional graph reasoning: useful, bounded, explainable

Connected evidence can support more than traversal and storage. A provider MAY
apply declarative rules over a bounded, subject-scoped packet to derive
inspectable facts. This non-normative Datalog-style example connects a signed
patch to its author, merge, and project:

```prolog
supported_contribution(Subject, Patch, Merge, Project) :-
authored_by(Patch, Subject),
merged_as(Patch, Merge),
in_project(Merge, Project),
signature_verified(Patch),
signature_verified(Merge).
```

Other appropriate rules can detect shared lineage, explicit contradictions, or
correction chains. This RFC does not standardize a reasoner. Any derived fact
MUST identify its rule-set version, input claim ids, scope, `as_of` time, and
resolution state through `derived_from`. Evaluation MUST be resource-bounded;
MUST NOT perform global closure or transitive trust propagation; and MUST NOT
turn missing data into negative evidence. Derived facts remain advisory.

The operating principle is **minimum sufficient verifiability**. Ordinary local
vouches remain Nostr-only. The optional graph path is justified when evidence
must survive relay churn, connect to other evidence, or be resolved outside its
originating conversation. Projection is always Nostr-first and preserves each
selected event's id, author, signature, and digest; §3.1 defines what may be
projected and how it is promoted.

---

### Part 3 (optional profile) — evidence-backed reputation on a Decentralized Knowledge Graph

Parts 1–2 stand alone. This part remains in the same RFC and describes the optional evidence-backed provider profile, with the DKG as a working reference adapter. Though framed here around reputation, the same layers carry **trusted context generally** — decision traces, memory, provenance for any claim — portable across relays and between Buzz and other systems.

#### 3.1 Three memory layers — durability is graduated, and that's the point

Every attestation projected into the Part 3 profile lives in one of three
layers, and **the layer is itself evidence about the record's publication and
durability state**:

| Layer | Scope | Cost | Meaning |
|---|---|---|---|
| **Working Memory** | local/private, on the issuer's own node | local storage only; no network publication or anchoring fee | a draft that remains local until deliberately shared |
| **Shared Working Memory** | community-visible, off-chain, subscription-scoped | low | the everyday layer: vouches, sightings, contribution records the community can query |
| **Verifiable Memory** | anchored on-chain, individually addressable | metered, **human-authorized** | integrity commitment and durable locator for selected records; payload availability still requires storage/replication |

This graduation avoids the false choice between anchoring everything (defamation risk and unbounded cost) and keeping everything relay-local. Promotion up the layers is **deliberate, consented, and costed**. Nothing is anchored by default, and an anchor MUST NOT be presented as a guarantee that the underlying payload will remain available forever.

**The capture boundary is narrow and deterministic.** The reference projection
may include deliberately public vouches and opted-in, completed signed outcomes
such as patches, reviews, CI results, maintainer approvals, merges, reversions,
and corrections. It MUST NOT infer reputation from casual chat, default
reactions, private channels or DMs, or unresolved accusations. Projection
records what happened and who attested to it; it does not infer character or
intent.

#### 3.2 Community-curated context — ownership at the source

Buzz already promises *"identity is portable even when the hosting isn't."*
This provider class aims to extend that promise to **context**. In this profile,
the community is the curator of its Context Graph. Curatorship is continuing
control over the graph at its source; it is not ownership of claims signed by
other authors and not a power to erase replicas already received elsewhere.
The target architecture is:

- **The curator controls composition and lifecycle.** It defines the capture
policy, projects eligible signed evidence, and maintains explicit correction,
revocation, and supersession links. Updates preserve the earlier signed
record and change which version the graph presents as active.
- **The curator controls publication.** Eligible material can remain in private
Working Memory, be promoted to community-visible Shared Working Memory, or be
deliberately anchored as Verifiable Memory. Material that must remain private
stays local unless encryption, capabilities, and server-side authorization
provide an explicit restricted-sharing path.
- **Subscription scopes discovery, not confidentiality.** Shared Working Memory
MUST be treated as non-confidential: once plaintext evidence has been
replicated, the curator can publish a correction or stop serving it but
cannot guarantee deletion from every recipient.
- Each user or community can resolve reputation through **their own node** (or
one they choose to trust). The current beta starts with one community-side
node next to the relay; optional personal Edge nodes are future work.
- Working/shared-memory claims survive relay migration **conditional on
continued replication and node availability**. Deliberately anchored
Verifiable Memory assets carry durable locators and commitments, while their
payloads still require storage. Within those bounds, a migrating community
recomputes its own view from the surviving evidence rather than importing
anyone's verdict — that recomputation is the target acceptance criterion,
not a capability already proven by the beta.

**Buzz scoping remains authoritative.** The relay `Host` selects the community. Channel-scoped events and memory use the NIP-29 `h` tag; an attestation without channel scope is community-global, never deployment-global. A provider MUST bind every lookup to the authenticated host-derived community, apply the relay's canonical channel visibility check, and never merge evidence across communities merely because the same npub appears in both.

![One agent's sub-graph of the live Web of Trust evidence graph: 76 entities and 33 relationships, entities colored by type, humanized labels, and the supports relations between claims](https://raw.githubusercontent.com/OriginTrail/buzz/main/docs/assets/screenshots/dkg-memory-contributor-graph.jpg)

*Shipped in the OriginTrail reference beta (v0.5.10-dkg-beta.5) — not part of the Part 1–2 ask.* One contributor sub-graph on the **live** Web of Trust channel: what this agent claimed and what each claim connects to — 76 entities · 33 relationships, with the evidence rail resolving a decision to its signed source. In the beta it resolves through the community provider; personal-node verification is a planned extension.

#### 3.3 Decision traces — evidence you can interrogate, not just read

A vouch that says "trustworthy" is a conclusion. This layer keeps the **trail**: every claim carries its issuer, timestamp, and `derived_from` lineage back to the concrete events it rests on — a merged patch, a review thread, a prior claim. Contribution history becomes an **auditable reasoning trail**:

- A maintainer can go beyond *"has someone vouched for this npub?"* to *"what exactly did they observe, when, and on what evidence?"* — and follow every link.
- For **agents**, this is the difference between plausible and accountable. Buzz's vision says an agent's *"reputation is on the line with every contribution."* With decision traces, an agent's claims are reviewable the way its patches are: you can reconstruct *why* it concluded what it concluded, claim by claim, and check each claim against its cited sources.
- Contradictions stay visible — two conflicting attestations coexist with their lineages, and the viewer weighs them, instead of a store silently keeping the last write.

![One agent's decision trail on the live Web of Trust channel: 33 decisions and 43 evidence rows on a time-ordered spine, the selected decision showing its evidence rail with layer, timestamp, supporting message, and the resolve-in-node-UI link](https://raw.githubusercontent.com/OriginTrail/buzz/main/docs/assets/screenshots/dkg-memory-contributor-traces.jpg)

*Shipped in the OriginTrail reference beta (v0.5.10-dkg-beta.5) — not part of the Part 1–2 ask.* A contributor's conclusions with their trails attached, from **live** channel data: 33 decisions · 43 evidence on a time-ordered spine, each ⊕ row a signed message the decision derives from, and a link that resolves the claim through the configured provider.

#### 3.4 Provenance as a first-class property

Every edge in the graph answers: *who asserted this, when, derived from what,
superseded by what?* Supersession keeps history addressable: a corrected claim
points to what it corrects rather than overwriting it. For reachable,
signature-verified sources, the resulting evidence path is tamper-evident: the
signatures prove event authorship and the graph preserves how those events were
composed.

#### 3.5 Reference implementation and Beta V1

The running beta deliberately starts with the easiest useful deployment for a Buzz community: **one DKG node beside the community relay**. The node may be Edge or Core. Members do not need to install a node to read community-visible memory; a personal Edge node is a later verification upgrade.

```mermaid
flowchart LR
A["Buzz app"] -->|"NIP-98 signed typed read"| R["Buzz relay"]
R -->|"membership and channel authorization"| G["Buzz-DKG query gateway"]
G -->|"allowlisted SWM and VM read"| N["DKG Edge or Core node"]
R -->|"NIP-29 channel events"| I["Buzz-DKG integration"]
I -->|"selected thread capture"| N
```

The public boundary is the Buzz relay, **not** the DKG HTTP API. The signed-in
app sends a NIP-98 request to the active community relay. The relay derives the
community from its host, verifies membership and channel visibility, and
forwards only typed reads to a protected same-host gateway. Clients cannot
choose a Context Graph id, submit SPARQL, select a DKG endpoint, obtain a DKG
credential, or read private Working Memory.

Section 3.6 pins the exact reference sources and states their volatile feature
status; the normative acceptance boundary remains in Conformance and Rollout
below.

#### 3.6 Run the complete reference implementation

A reproducible evaluation means running the complete stack, not only opening
the UI against infrastructure operated by somebody else. The evaluator sets up
all four components:

1. a DKG-aware **Buzz relay** from `OriginTrail/buzz`;
2. a DKG **Edge or Core node** (Edge is sufficient for this beta);
3. the **Buzz–DKG integration** beside that relay and node; and
4. the **Buzz DKG Beta desktop app** connected as a normal Buzz user.

Together these demonstrate the actual authorization and data path: the app
authenticates to Buzz, the relay derives community/channel scope, the
integration verifies and compiles signed memory proposals, and the DKG node
stores and answers queries against the channel's Context Graph. A hosted
community can be useful for a quick visual preview, but it is not a substitute
for this reproducibility test.

The running implementation covers the current OriginTrail reference subset.
Cross-relay replication, personal Edge-node verification, provider
interchangeability, and production VM anchoring remain explicit acceptance
targets rather than demonstrated capabilities.

Nothing in this setup modifies an installation of official `block/buzz`; the
beta app uses a separate application name, bundle identifier, data directory,
and updater channel.

#### Repositories and exact responsibility

| Repo | What it supplies |
|---|---|
| [`OriginTrail/buzz`](https://github.com/OriginTrail/buzz) | Canonical source for the DKG-aware relay, ACP post-turn memory runtime, CLI support, and desktop Memory UI. The packaged beta below is built from a pinned commit in this repository. |
| [`OriginTrail/buzz-dkg-integration`](https://github.com/OriginTrail/buzz-dkg-integration) | Community-side installer/source, authenticated query gateway, semantic-memory compiler, per-channel Context Graph lifecycle, bounded query policy, and DKG Edge/Core integration. |
| [`OriginTrail/buzz-dkg-beta`](https://github.com/OriginTrail/buzz-dkg-beta) | Cross-platform showcase packages and the signed Tauri update feed. It contains distribution machinery, not a second application source of truth. |

#### Complete self-hosted setup

This setup is intended for an evaluator with a disposable 64-bit Linux host
(`x86_64` or `aarch64`), a DNS name whose ports 80/443 reach the host, Docker
with Compose v2.24.4+, Git, `sudo`, OpenSSL, npm, and Node.js 22.13–22.x or
23.4+. Use testnet and disposable credentials for the first run.

**1. Install the app and create the relay-owner identity.** Download
[`v0.5.10-dkg-beta.5`](https://github.com/OriginTrail/buzz-dkg-beta/releases/tag/v0.5.10-dkg-beta.5)
for macOS (Apple Silicon or Intel), Windows x86-64, or Linux x86-64, and verify
it against `SHA256SUMS`. Update bundles carry mandatory Tauri signatures; the
macOS and Windows installers are not yet Apple/Microsoft signed, so the
operating system may require explicit first-launch approval. Launch **Buzz DKG
Beta**, create a Nostr identity, and copy its 64-character **public** hex key.
It will be the relay owner; keep its private key inside the app and never send
it to the server or integration.

**2. Build and start the DKG-aware Buzz relay.** The commit below is the exact
application source used by `v0.5.10-dkg-beta.5`.

```bash
git clone https://github.com/OriginTrail/buzz.git
cd buzz
git checkout ddd51ce59282461b2f025f1681f0aa9af6565d5f
docker build --target runtime -t origintrail/buzz:dkg-beta.5 .

cd deploy/compose
cp .env.example .env
```

Edit `.env` before starting:

- set `BUZZ_IMAGE=origintrail/buzz:dkg-beta.5`;
- replace `buzz.example.com` with the evaluator's DNS name in every URL field;
- set `RELAY_OWNER_PUBKEY` to the public key from step 1; and
- replace every remaining `CHANGE_ME` with a stable random value (use
`openssl rand -hex 32` for the 64-hex secrets and retain the file securely).

Then render the configuration and start it with Caddy-managed TLS:

```bash
BUZZ_COMPOSE_TLS=true ./run.sh config
BUZZ_COMPOSE_TLS=true ./run.sh start
curl -fsS https://YOUR_DOMAIN/_liveness
```

**3. Add the DKG node and integration from reviewed source.** The pinned
integration commit contains automatic post-turn capture, evidence-set
deduplication, ontology profiles, bounded semantic queries, load control, and
the 10,000-triple channel-graph operation used by the current showcase.

```bash
cd ../../..
git clone https://github.com/OriginTrail/buzz-dkg-integration.git
cd buzz-dkg-integration
git checkout c74d81790dd3ed5f63921d346d485dd10ddf2081
npm ci

sudo env BDI_MVP_NODE="$(command -v node)" ./buzz-dkg plan \
--relay wss://YOUR_DOMAIN \
--dkg-role edge \
--dkg-network testnet

sudo env BDI_MVP_NODE="$(command -v node)" ./buzz-dkg install \
--relay wss://YOUR_DOMAIN \
--dkg-role edge \
--dkg-network testnet

sudo env BDI_MVP_NODE="$(command -v node)" ./buzz-dkg status
sudo env BDI_MVP_NODE="$(command -v node)" ./buzz-dkg smoke
```

Review the displayed plan before accepting it. The installer preserves the
relay database, identity, public URL, and TLS configuration; installs or reuses
a DKG Edge/Core node; creates the **Web of Trust** seed channel and private
Context Graph; configures lazy private graphs for other channels; keeps VM
publication disabled; and exposes no public DKG port or credential.

The public one-line installer release currently predates the post-turn memory,
bounded-query, and full-graph commits above, so this reproducibility path pins
reviewed source instead of claiming that `releases/latest` reproduces the live
showcase. A new installer release should replace this source step before a
broader public beta.

**4. Connect the app.** In Buzz DKG Beta, connect to
`wss://YOUR_DOMAIN` with the owner identity and join **Web of Trust**. For
another tester, enroll their public key from the relay checkout:

```bash
cd ../buzz/deploy/compose
./run.sh add-member --role member
```

Operational checks remain available from the integration checkout by using the
same `sudo env BDI_MVP_NODE="$(command -v node)" ./buzz-dkg ` form with
`status`, `logs`, or `smoke`. `remove` stops the integration while retaining
Buzz history, DKG state, integration state, memberships, channels, and Context
Graphs.

**5. Exercise the complete loop.** Ask a managed agent a normal channel
question. After its visible response succeeds, the ACP runtime performs a
separate tool-free extraction, signs a semantic proposal bound to the
input/output event ids, writes it to a durable local outbox, and submits it
without posting another chat message. Open **◈ Memory**, select the agent,
switch between **Traces** and **Graph**, and follow a decision's evidence rail
back to its signed source event. Human-only discussion can use the compatibility
command `@dkg distill` in the seeded channel.

An ordinary Buzz relay that does not advertise the DKG capability continues to
work as an ordinary Buzz relay; the Memory entry point is capability-gated. It
does **not** fabricate a local graph or promise discovery mode on every relay.

#### Optional hosted preview

Reviewers who want to see the UI before operating the stack may request access
to the allowlisted OriginTrail test community through the
[`buzz-dkg-beta` tracker](https://github.com/OriginTrail/buzz-dkg-beta/issues/new)
and then connect the beta app to `wss://buzz-dkg-relay.origintrail.io`. This
previews live data and interaction design only; it does not validate installation,
operator isolation, relay authorization, or independent DKG operation.

#### What to evaluate

- **Evidence before verdicts:** every decision or vouch exposes issuer, scope,
time, memory layer, and signed source where reachable.
- **Honest resolution:** the UI distinguishes local-node verification,
community-provider resolution, unverified receipts, partial results, and
provider failure.
- **Bounded graph behavior:** counts distinguish graph totals from displayed
subsets; full-channel visualization is capped at 10,000 triples and reports
truncation instead of pretending the cap is the total.
- **Automatic but attributable capture:** successful managed-agent turns
produce signed proposals tied to exact source event ids; ordinary human
messages are not silently distilled.
- **Authorization:** the client never supplies a Context Graph id, SPARQL
endpoint, DKG token, or cross-channel scope. The relay derives community and
channel access from the authenticated request.

#### Current limitations, stated plainly

- **One community node in the hosted beta.** Cross-relay durability and the
two-provider migration/recomputation drill remain design targets, not
demonstrated claims.
- **One DKG-specific provider path.** The provider-neutral Part 2 trait,
`NullProvider`, `LocalProvider`, NIP-85 adapter, and shared conformance suite
are not shipped in the beta.
- **No packaged personal Edge-node flow yet.** Hosted evaluators resolve
through the community provider. Working Memory stays node-local.
- **VM is deliberately disabled.** The test community does not spend gas or
anchor person-targeting evidence on-chain.
- **Contributor views are attribution lenses.** They are derived from signed
authorship inside the channel graph, not separately replicated storage
partitions or confidentiality boundaries.
- **OS trust is still beta-grade.** Tauri update artifacts are signed, but
fresh macOS and Windows installers are not Apple/Microsoft signed.
- **Queries are intentionally constrained.** No client-selected graphs,
unrestricted SPARQL, global closure, or unbounded traversal is exposed
through the public relay boundary.

**An offer to the Buzz maintainers.** The OriginTrail core team is keen to
contribute this work upstream — **natively integrated, community-owned shared
Context Graphs advancing the Web of Trust** — under Buzz's review standards
and at whatever pace fits the roadmap. Parts 1–2 are deliberately separable,
provider-neutral, and zero-cost to non-adopters; Part 3 is an external running
reference, not a request to make DKG infrastructure mandatory. To challenge a
claim against the running system, comment here, open an issue on
[`OriginTrail/buzz-dkg-beta`](https://github.com/OriginTrail/buzz-dkg-beta/issues),
or compare this evidence-first proposal with the companion
[block/buzz#3721 (NIP-TR)](https://github.com/block/buzz/issues/3721).

---

### Security, privacy, and abuse analysis

| Threat | Required boundary or mitigation |
|---|---|
| Sybil vouches or brigading | Source choice stays viewer-side; corroboration counts independent lineages, not event volume; no vouch grants authority. |
| A provider invents or alters evidence | Return the original signed event or a stable reference plus digest, author, signature, and verification status. Provider identity/version and `as_of` are always visible. |
| A provider selectively omits inconvenient evidence | Return configured, consulted, and failed source diagnostics with the exact query scope and resolution state. Never claim global completeness; viewers may compare providers. |
| Stale, revoked, or superseded claims | Preserve append-only history and explicit status. Never silently resurrect an older replaceable event or count an expired/revoked claim as active. |
| Cross-community data leakage | Derive community from the authenticated relay host, enforce NIP-29 channel visibility, and never widen source visibility during projection. Same npub does not authorize a cross-community join. |
| Person-targeting abuse or durable defamation | Only deliberately public vouches are public by default. Other person-targeting observations remain private, issuer-scoped, expiring, revocable, and ineligible for automatic enforcement. |
| Provider outage presented as a bad reputation | Carry `ResolutionState` and render *not configured*, *no evidence*, *partial*, *unavailable*, *negative evidence*, and *unknown judgment* distinctly. |
| Query-cost or graph-traversal denial of service | Batch and paginate; require a hard deadline and result limit; use bounded typed operations. Never expose unrestricted client-selected SPARQL through the public relay boundary. |
| An anchor is mistaken for truth or availability | Describe anchoring only as an integrity commitment and locator. Verify signed sources separately, and report replication/availability independently. |
| A local score becomes a shadow permission system | Show method, scope, evidence window, reasons, and resolution state; prohibit automatic membership, moderation, signing, or write decisions under this RFC. |

The same npub is intentionally correlatable across relays; that is how portable
identity works. What is *not* automatic is importing private evidence,
community membership, or a prior community's policy judgment merely because
the key matches.

## Alternatives considered

| Alternative | Why this RFC does not choose it as the whole design |
|---|---|
| NIP-TR alone | It can carry a useful issuer result, but a tier/score does not by itself standardize inspectable evidence, resolution state, or visibility preservation. It can remain a compatible input. |
| NIP-85 alone | It provides plural, viewer-selected assertion sources and may carry ranks, but does not define Buzz's evidence envelope, provider degradation contract, or community authorization boundary. |
| Relay-local Nostr events only | This is sufficient for Part 1 and may be all many communities need. It does not prove long-lived availability or connected provenance after relay migration. |
| A mandatory DKG dependency | Rejected: it raises cost and operational coupling for every Buzz deployment. The DKG is one optional adapter behind the same provider contract. |
| A single global score or ingest gate | Rejected: it collapses contextual judgment into authority, creates a capture target, and conflicts with an advisory experiment. |

---

## Additional context

### Conformance

- Provider output MUST NOT automatically gate identity, membership, moderation, signing, or writes.
- `NullProvider` MUST be the default, deterministic, and return `Disabled`.
- Every claim MUST carry `claim_layer: observation | derived_analysis`, issuer,
lifecycle `status`, and `derived_from` (`[]` allowed). A derived analysis MUST
cite its inputs; action recommendations are outside the envelope.
- Every projected claim MUST retain the original signed event or a stable source reference, digest, author, signature, and verification status.
- Every batch MUST identify its provider/version, exact query scope, `as_of`,
resolution state, and configured/consulted/failed source diagnostics. No
provider may claim global completeness.
- Providers MUST preserve the source's visibility, host-derived community, and NIP-29 channel authorization boundary.
- Derived person profiles and person-targeting observations that were not deliberately published as public vouches MUST default private, expiring, and revocable. No person-targeting claim may feed global scoring or automatic enforcement.
- All providers MUST pass one shared conformance suite, including outage, staleness, and degradation paths.
- Any derived score MUST identify the viewer/community scope, methodology, evidence window, `as_of` time, and resolution state; it MUST NOT be republished as a canonical property of the subject.
- UIs MUST distinguish *not configured*, *no evidence*, *partial*,
*unavailable*, *negative evidence*, and *unknown judgment*.
- **Target portability acceptance criterion:** after a relay migration, users on the new relay can re-resolve the same signed attestations and recompute their own views — without importing any prior provider's verdict. The beta has not yet demonstrated this.

### Non-goals

No universal score and no portable Buzz-derived score. No canonical ranking. No mandatory backend. No new moderation powers. No claim that signed history equals truth — signatures give attribution and tamper-evidence; judgment stays with the viewer. No claim that an on-chain commitment alone guarantees off-chain payload availability.

### Rollout

1. **Part 1** — register kinds 1985 / 30382 / 10040 + acceptance tests (small PR, useful alone).
2. **Part 2** — `ReputationProvider` trait, `NullProvider`, `LocalProvider`, conformance suite (experimental, feature-flagged).
3. A NIP-85 source adapter honoring users' `10040` lists.
4. Evaluate the included Part 3 adapter behind the explicit feature flag, ship a desktop beta, publish a closed but publicly reachable test relay, and run the migration/availability acceptance test.

Before the experiment is considered ready for broader enablement, it must
demonstrate all of the following:

- With no provider configured, existing relay and client behavior is unchanged.
- `LocalProvider` and the reference DKG adapter pass the same bounded-query,
lifecycle, visibility, and degraded-source conformance cases.
- A two-community migration exercise re-resolves the same source event ids and
digests from replicated evidence, recomputes a fresh local view, and imports
no prior provider verdict.
- Revoked, superseded, conflicting, and duplicate-lineage claims produce the
expected evidence packet; an unreachable configured source produces
`Partial` or `Unavailable`, never a zero score.
- The beta reports p50/p95 query latency, storage growth, replication lag, and
any anchoring spend so maintainers can set explicit operating budgets before
enabling it outside the experiment.

### Recommended decisions for the experiment

1. Keep evidence discovery separate from viewer policy. Any standardized `view`
or enforcement surface requires a follow-up RFC.
2. Keep `TrustClaim` as a versioned Buzz-internal projection during the
experiment. Consider an interoperability specification only after two
independent providers demonstrate the need.
3. Surface reputation first in the Projects contributor panel, where the
decision has a concrete task and project scope.
4. Exclude restricted attestations from the MVP. Encryption/capabilities may
follow and do not block public vouches or opted-in public outcomes in Parts
1–2.
5. Replace provisional `buzz.wot` with a maintainer-approved reverse-domain
namespace before any interoperable release.

### Related issues and duplicate search

We searched the open Buzz issues and PRs on 2026-08-14 for *web of trust*,
*reputation*, *attestation*, *DKG*, and *knowledge receipt*. The closest issue is
[#3721 — NIP-TR portable trust attestations](https://github.com/block/buzz/issues/3721).
It overlaps with this RFC's portable attestation layer, but it does not define
the evidence-first provider contract, channel-scoped Context Graph projection,
or complete reference deployment proposed here. We would be happy to align the
provisional event vocabulary with that discussion rather than create competing
wire formats.

Related but complementary work includes
[#4529 — knowledge receipt event kinds](https://github.com/block/buzz/issues/4529),
which describes provider-neutral receipts for artifacts derived into an
external store, and
[#2754 — stable downstream extension points](https://github.com/block/buzz/issues/2754),
which asks for broader integration boundaries. None is a duplicate of this
end-to-end Web-of-Trust proposal and runnable DKG-backed reference profile.

### References

- [Buzz roadmap](https://github.com/block/buzz/blob/main/README.md) and [Web of Trust vision](https://github.com/block/buzz/blob/main/VISION_PROJECTS.md#the-web-of-trust)
- [NIP-32 — Labeling](https://github.com/nostr-protocol/nips/blob/master/32.md)
- [NIP-85 — Trusted Assertions](https://github.com/nostr-protocol/nips/blob/master/85.md)
- [Buzz RFC issue #3721 — NIP-TR](https://github.com/block/buzz/issues/3721)
- [OriginTrail DKG key concepts](https://docs.origintrail.io/how-dkg-works/key-concepts), [documentation](https://docs.origintrail.io/), and [DKG V10 node](https://github.com/OriginTrail/dkg)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.