# Messaging & Note-Privacy Capabilities

ChainRender renders on-chain messages and private-payment discovery **honestly**, and declares the sends — it never
becomes a messaging protocol, an inbox, a relay, or an indexer, and it never custodies a key. Everything here is graded
by the same rule as the rest of the system: a re-computable `view` is Grade **A**; an event-log feed or a client-side
render is **≤ C** and labelled; a send is a **declared action**. (Full strategy: doc 157.)

## The one rule that decides the grade

| Where the work happens | Example | Treatment |
|---|---|---|
| Re-computable `eth_call` view | ERC-1271 validity, ERC-6538 lookup, shielded-pool invariants | **Grade A** |
| On-chain data via `eth_getLogs` / indexer | ERC-3722 Poster feed, ERC-5564 announcement scan | **≤ C, labelled** |
| Client-side / RPC crypto (never on-chain) | EIP-712 signing, ERC-5630 encrypt, stealth derivation | **declared / local** |
| A state change | ERC-5564 `announce`, ERC-3722 `post` | **declared action** |

An event-log feed is **not** Grade A: logs are verifiable but read via `eth_getLogs`, not a `view` a component can
re-run — so Poster feeds and stealth scans render at ≤ C with a labelled off-chain edge (the same posture as EFP
follower counts).

## Public messaging

- **ERC-1271 signature validity** (`sig-1271`, Grade A) — "is this message hash validly signed by contract account X?"
  A pure `view` against the account's own logic. Validity only — the *meaning* of the message is rendered client-side
  (see `msg-712`), never asserted here.
- **Render what you sign** (`msg-712`, client-side, ≤ C) — an honest render of the **EIP-712 / EIP-191 message you are
  about to sign**: every field named and typed, and **fail-closed on anything opaque** ("this field is raw bytes we
  can't interpret — do not sign blind"), with an A-hint only when the message is fully typed *and* bound to a
  `verifyingContract`. Anti-phishing infrastructure, framed as "marketing ≤ code" — it never says "safe to sign."
- **ERC-3722 Poster feed** (`poster-feed`, ≤ C) — public posts. Content lives only in `NewPost` event logs (no state),
  so it's an indexer read, labelled off-chain. Declaring a `post()` is a user action.

## Private messaging & payments

- **ERC-6538 stealth discovery** (`stealth-meta`, Grade A) — "is this address reachable via stealth payments, and what
  is its published stealth meta-address?" This *discovery read* is the only on-chain (Grade A) part of a private
  payment. The ERC-5564 `announce` send is a **declared action**; scanning announcements (`stealth-scan`, ≤ C) is an
  off-chain log read; deriving which announcements are yours uses your **viewing key, client-side**. ChainRender never
  holds a key or derives your address server-side.
- **ERC-5630 encryption** is client/RPC-side by construction (`eth_getEncryptionPublicKey` / ECIES) — rendered + declared,
  never a chain read, never custodied.

## Shielded pools / note privacy (Aztec / zk.money-style)

Render the **privacy boundary** honestly — the publicly-provable invariants, revealing nothing about ownership:

- `shielded-root` (Grade A) — the pool's current Merkle root.
- `shielded-set` (Grade A) — the **anonymity-set size**, i.e. *how private the pool actually is right now*. A small set
  is **weak** privacy — the card grades it WEAK / moderate / healthy and **says so**, instead of hiding a thin set.
- `shielded-nullifier` (Grade A) — is a nullifier spent (double-spend / already-claimed) **without** revealing identity.

The decrypted balance is a **client-side, viewing-key-gated enhancement** (≤ C, local) that **fails closed** to this
public floor. Shield / unshield / transfer are **declared actions** whose privacy leaks are **labelled, never hidden**:
*deposit reveals the amount + your L1 address; the internal transfer is private; withdrawing to a reused address re-links
you — use a fresh one.* This reuses the same commitment+nullifier DNA already shipped (Groth16 credentials + the
ownerless `NullifierRegistry`).

## Honest boundaries

- No key custody. Never a messaging protocol, inbox, relay, or indexer.
- No plaintext private content on-chain. Off-chain delivery (hubs, CCIP-Read, ciphertext stores) is ≤ C and labelled.
- A rendered signable message is a render, not an endorsement — it states what the message *is* and where it's opaque.
- A weak anonymity set is rendered as weak. Marketing ≤ code.

## For developers

Kinds are discoverable via `RESOLVER_KINDS` / `vocabulary()`; encode args with the helpers in `@chainrender/client`
(`chainc/messaging.ts`): `encodeSig1271Args`, `encodeStealthMetaArgs`, `encodeShieldedArgs`, plus the client-side
`renderTyped712`, `decodePrivacyLeaks`, and `posterFeedFilter`. On-chain resolvers:
`Sig1271Resolver`, `StealthMetaResolver`, `ShieldedPoolViewResolver` (caller-supplied addresses; fail-closed; ownerless).

## Related
- **[Reputation Capabilities](./reputation-capabilities.md)** · **[Privacy & Credentials](./privacy.md)** ·
  **[The Floor](./the-floor.md)**
