# The Trust Grade

Every ChainRender app carries a **trust grade** — a single letter (A / B / C) that tells a user, *before they
interact*, exactly how trustless the app is. It is computed on-chain, and the SDK computes an identical grade
locally (they are drift-locked), so you can see your app's grade as you build it.

## What the grades mean

| Grade | Word | Meaning |
|---|---|---|
| **A** | Trustless | Fully on-chain, no external dependencies. Everything you see is computed from chain state. |
| **B** | Pinned | Depends on an immutable, content-pinned external asset (e.g. an IPFS hash). Verifiable, but off-chain. |
| **C** | Live | Depends on something that can change — a live off-chain fetch, a mutable pointer, or an unproven asset. |

The grade is the **worst link**: one Grade-C part sets the headline, because a chain is only as trustless as its
weakest dependency. But the grade is never just a letter — it comes with an **itemized breakdown** naming *every*
deviation, so the user (and you) can see exactly *why* a grade was assigned.

## Why a grade instead of a checkmark

A binary "safe / unsafe" badge would be dishonest — trust is a spectrum, not a boolean. An app that renders a
chart from live on-chain data (Grade A) and an app that embeds an image from a random web server (Grade C) are
*both* "functional," but they are not equally trustworthy, and pretending otherwise would violate ChainRender's
core discipline: **marketing must never exceed what the code enforces.**

The grade makes the trust cost *legible*. A user who wants maximum assurance uses only Grade-A apps. A user who
accepts a pinned dependency uses Grade-B. Nobody is surprised, because the grade — and its reasons — are visible
up front.

## How it's computed (the reasoning)

The grade derives from the app's **capability envelope** — the union of everything the app can do and everything
it depends on. The enforcer walks the composition and, for each part, classifies its dependencies along several
axes (is data on-chain or fetched? is an asset immutable, attested, or mutable? does an action stay within the
declared envelope?). Each axis has an honest floor:

- **On-chain computation** → contributes nothing negative (Grade A).
- **A fail-closed enhancement** (e.g. a GPU effect that degrades to an on-chain poster, or a fetch that falls back
  to complete on-chain data) → *stays* Grade A, because the trustless floor is intact even if the enhancement fails.
- **A pinned/attested dependency** (a raw-CIDv1 IPFS asset, pointer anchored on-chain, client-verified,
  fail-closed) → Grade B. See the guide *[Grade B — a Pinned-IPFS Dependency](../guides/pinned-ipfs-dependency.md)*
  for how to declare it (`grade(app, { pinnedDep })`).
- **A live fetch or mutable pointer that the output actually depends on** → Grade C.

Crucially, the enforcer is **conservative and fails closed**: anything it cannot analyze is treated as unsafe
(refused or downgraded), never optimistically passed. An unknown vocabulary token is refused, not rendered.

## The relationship to safety-by-construction

The grade *describes* trust; the **enforcer** *enforces* safety. They're related but distinct:

- Some things are **refused outright** — an arbitrary-code escape hatch, an action that moves value while the app
  never declared it can, a `{to, selector}` not in the declared call set. These don't get a bad grade; they're
  *rejected at registration*. See **[The Capability Enforcer](./enforcer.md)**.
- Everything that *passes* gets an honest grade reflecting its real dependencies.

So a registered ChainRender app is always *safe* (it can't smuggle a hidden transaction), and its *grade* tells
you how *trustless* it is on top of that baseline safety.

## Using the grade as a developer

```ts
import { grade } from "@chainrender/client";

const g = grade(myApp);
console.log(g.letter);      // "A"
console.log(g.word);        // "Trustless"
console.log(g.breakdown);   // itemized deviations, if any
```

Watch the grade as you build. If adding a feature drops you from A to C, the breakdown tells you exactly which
dependency did it — and you can decide whether that trade-off is worth it, *before* your users ever see it.



## Resolvers and the grade (an important distinction)

Not all resolvers are equal for the grade:
- A **client-side resolver** — a JS function that fetches with viem/ethers in the browser (e.g. `getBalance`,
  `getBlock`) — is an off-chain fetch. It grades **C (Live)**. Routing data through a resolver function does not make
  it on-chain.
- An **on-chain resolver contract** — a resolver *address* referenced by a Slot — reads and renders the value
  on-chain during the `eth_call`. It grades **A (Trustless)**.

So a Slot bound to an on-chain resolver contract is Grade A; a Slot filled by a client-side JS resolver is Grade C.
The grade tells the truth either way — an app using client-side resolvers is not "fully on-chain," and the grade
correctly reflects that.

## Related

- **[The Capability Enforcer](./enforcer.md)** — what gets refused vs. graded.
- **[Content Addressing](./content-addressing.md)** — the immutability the grade builds on.
- **[Resolvers & Data Binding](./resolvers.md)** — how live data affects the grade.
