diff --git a/CLAUDE.md b/CLAUDE.md
index e501846..c457c08 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -538,6 +538,45 @@ Migrations are sequentially versioned and **immutable once committed**. Correct
mistake with a new file, never by editing one that has landed — the runner's
checksum diverges and it refuses to start.
+## The distribution table reports flows and does not judge them
+
+`/:chain/network` carries a table of who won the blocks and what became of the
+rewards. It exists because a concern was raised that a pool might not be paying
+out, and it is built so that it can never be the thing making that accusation.
+
+**Direction is a fact in the payload.** `Wormhole::NativeTransferred` and
+`Balances::Transfer` both carry `from`, `to` and `amount`, so inflow and outflow
+are counted from what the chain recorded rather than inferred from an account
+appearing near an event.
+
+**A nonce cannot answer this, and reaching for one is the obvious mistake.**
+Wormhole transfers dispatch *unsigned* — `verify_private_batch` and
+`verify_public_batch` have no signer — so an address here can move a fortune
+with `nonce: 0`. Reading a zero nonce as "has never sent anything" is wrong on
+this chain.
+
+**What the numbers cannot settle**, and what the page therefore says out loud:
+an operator may hold several addresses; may settle off-chain; or may be a solo
+miner keeping what it earned, which is the ordinary case. Measured on mainnet,
+several large accounts send nothing at all, and the accounts distributing to
+hundreds of recipients have never mined a block — so payout wallets here are
+funded from somewhere other than mining addresses. There is also no such thing
+as a "pool" on this chain: the word appears only inside a name an operator
+reports over telemetry, which is why `MinerFlow` carries the `AttributionSource`
+and the table calls the name column its weakest. A site that flagged entities as
+delinquent on the strength of a name they chose themselves is one bad match away
+from libelling someone.
+
+What earns the table its place is **comparison**. One miner's recipient count
+says almost nothing; beside its neighbours' it says a great deal. The reader
+draws the conclusion; the site lays out the evidence and names its limits.
+
+**Two columns are not measured the same way.** `holds` is chain state, true now;
+`mined`, `sent on` and `recipients` are over the indexed range. On a chain read
+from genesis they agree; on one still being indexed backwards a miner appears to
+hold far more than it ever mined. The note under the table says so, because the
+discrepancy looks exactly like the thing the table is for.
+
## The network page mixes two kinds of certainty, and says which
`/:chain/network` puts chain state and this observer's index on one page, and
diff --git a/web/src/api/rest.ts b/web/src/api/rest.ts
index ab9cac4..c23ccdd 100644
--- a/web/src/api/rest.ts
+++ b/web/src/api/rest.ts
@@ -20,6 +20,7 @@ import type { GenesisDetail } from './generated/GenesisDetail'
import type { ReversibleState } from './generated/ReversibleState'
import type { RecentBlock } from './generated/RecentBlock'
import type { MinerDetail } from './generated/MinerDetail'
+import type { Distribution } from './generated/Distribution'
import type { NetworkSummary } from './generated/NetworkSummary'
import type { NodeIndex } from './generated/NodeIndex'
import type { NodeInfo } from './generated/NodeInfo'
@@ -256,3 +257,12 @@ export async function fetchNode(
export async function fetchNetwork(chain: string, signal?: AbortSignal): Promise {error} Following the rewards…
+ Every figure here is something the chain recorded: direction comes from each transfer
+ event's own
+ The names are the weakest column and come from telemetry, not the chain — an operator
+ chooses what its node calls itself, so a name containing “pool” is a claim rather than a
+ fact. Two of these columns are not measured the same way: holds is
+ read from chain state and is true right now, while mined, sent on and{' '}
+ recipients are counted over the indexed range above. On a chain read from genesis
+ those agree; on one still being indexed backwards they do not, and a miner can appear to
+ hold far more than it ever mined simply because the earlier half has not been read yet.{' '}
+ Where the rewards went
+
+ {fmtHeight(data.window_blocks)}-block window · amounts in {symbol} ·{' '}
+ {data.indexed_from !== null && data.indexed_to !== null
+ ? `blocks ${fmtHeight(data.indexed_from)}–${fmtHeight(data.indexed_to)}`
+ : 'nothing indexed yet'}
+
+
+
+
+
+
+
+ {data.miners.map((m) => {
+ const recipients = m.flows?.recipients ?? null
+ return (
+
+ Miner
+
+ Share
+ Mined
+ Holds
+ Sent on
+ Recipients
+
+
+ )
+ })}
+
+
+
+ {fmtShare(m.share)}
+ {amount(m.mined)}
+ {amount(m.balance)}
+ {amount(m.flows?.sent)}
+ {recipients === null ? '—' : fmtHeight(recipients)}
+ from and to, and what a miner mined is what the
+ chain paid it.{' '}
+
+ What the figures mean is a separate question, and this table does not answer it.
+ {' '}
+ An operator may hold several addresses, may settle off-chain, or may be a solo miner keeping
+ what it earned — which is the ordinary case and not remarkable. A zero in{' '}
+ recipients is not an accusation; it is a starting point for one.
+ Sent on also counts only transfers out of the address the chain pays:
+ an operator distributing from a different wallet shows nothing here.
+