# The Cannot List

**Mirror's moat is not what it can see. It is what it is built to be structurally incapable of doing —
and every one of those refusals is enforced by a test you can run.**

Most compliance products are a list of features. This is a list of *inabilities*. Each one below is a
liability the rail is designed never to hold — a customer's value, a filing decision, a risk score, a
cut of the trade, a ranking of members — because holding any of them is what got the pooled AML utilities
killed by privacy counsel, or would put the operator in the tipping-off and settlement path.

The point of this page is the last column. A refusal that lives only in a mission statement is a promise.
A refusal that fails a build when someone tries to remove it is a **specification**. A competitor that
adds a risk score does not merely disagree with our ethics; it fails this standard, and an examiner
trained on it can ask them to run the same test. Everything here is checkable from source with
`node kernel/test.js` (currently ~6,720 assertions across ~106 files); the individual guards are named so
you can find and run them yourself, and the sha256 of every test file the runner executes is published at
[/conformance-suite.json](/conformance-suite.json) — so you can confirm you ran the whole suite, not a
subset chosen to pass.

---

## What the operator cannot hold

| It cannot… | Because | Enforced by |
|---|---|---|
| **hold a raw value, unit, band, corridor table, or salt** | the wire rejects any of those keys at any nesting depth, on every route, before dispatch (`400 raw_leaked`) | `server/designed-inability.test.js`, and the `RAW_KEYS` deep scan in `server/core.js` |
| **hold a suspicious-activity filing or a filing decision** | filing-adjacent keys — `sar`, `str`, `goaml_ref`, `filing_decision`, and their morphology — are refused at any depth (`400 sar_wall`), because tipping-off is a criminal offence the rail must be incapable of committing | `conformance/sar-wall.test.js` runs an 81-item adversarial corpus (including Cyrillic-homoglyph and zero-width-joiner smuggles) through the real operator; all refused |
| **read a value even under subpoena or breach** | its inbox is opaque digests. There is no plaintext to seize, and no operator route anywhere accepts, escrows, or recovers a shared secret | the whole protocol (`SPEC.md` §5, §11); `server/designed-inability.test.js` pins the four routes an integrator might expect to leak |

## What the verdict cannot become

| It cannot… | Because | Enforced by |
|---|---|---|
| **emit a risk score, probability, rating, or likelihood** | a track record reports counts with their denominator, never a number about a person; the builder throws on any planted scoring key | `mirror-certificate.assertNoScore` (throws), pinned in `kernel/mirror-certificate.test.js` |
| **produce a fourth verdict** | reconciliation returns exactly `reconciled`, `divergent`, or `undetermined`; ambiguity fails closed to `undetermined`, never to a clear | `kernel/mirror-kernel.test.js` and the conformance vectors |
| **rank one member against another** | a member's own certificate is counts-only and names no counterparty; a per-counterparty or ranking field is refused | `mirror-evenhand.assertCountsOnly` and `mirror-rerisk.assertNoRanking` (both throw) |
| **leak through its own by-products** | the public registry strips anything trade-shaped, and cover traffic must be structurally uniform or it is refused | `mirror-public.assertNoLeak` and `mirror-cadence.assertNoCoverLeak` |
| **become a filing decision, a recommendation, or a score — even in its richest evidence output** | the evidence taxonomy folds the signed verdicts a party already holds into a structured *fact pattern* (what kind of mismatch, how large structurally, which bytes to cite) so a bank's own investigators reason over a sharper exhibit — but it names no action, combines nothing into a number, and holds no raw value; a filing/suspicion/recommendation key or a scoring key is refused before the record is emitted | `mirror-taxonomy.assertNoDecision` and the shared `assertNoScore` (both throw), pinned in `kernel/mirror-taxonomy.test.js` |

## What the business cannot do

| It cannot… | Because | Enforced by |
|---|---|---|
| **charge a fee on the size or volume of a trade** | metering the flow would pay a member to submit less, and give a regulator cause to argue the rail profits from looking the other way; a `bps`, `per_trade`, `take_rate` or `ad_valorem` field is a hard failure, not a computed line | `mirror-billing.assertNoVolumeFee` (throws), pinned in `server/vectors.test.js` (`billing_volume_fee_refused`) |
| **invent a price** | corridor edges are supplied by the parties and cited to a source; the kernel bands against them and authors none. A decision table is built only from a *ratified* table, never a caller-supplied one | the reconcile signature takes edges as input; `mirror-provenance` binds the table's cited source into the verdict |
| **move, hold, freeze, or settle money** | it carries no account, card, or routing field, and the ISO 20022 evidence block refuses any settlement or release instruction — it attaches proof, it never triggers a payment | `kernel/mirror-iso20022.js` `carriesSettlement` refusal; there is no settlement route anywhere in `server/core.js` |

## And the verifier refuses a record that carries one

Every refusal above is enforced at the **door** — the wire rejects a forbidden field on the way in. But a
signed verdict is meant to be checked **offline**, by an examiner who never talks to the operator, and a
naive check verifies only the ES256 signature. So a record a rogue or mis-patched operator signed *with* a
`risk_score` or a `sar_decision` in it would verify as "an authentic Mirror verdict" — and the whole legal
posture would rest on trusting the operator not to have added one.

That is closed. A **conformant verifier refuses a record carrying a forbidden field even when the signature
is valid**: a filing decision, a risk score, a volume fee, a settlement instruction, or a leaked corridor
secret. The signature proves the bytes are unaltered; the scan proves they are the *kind* of record Mirror
is allowed to emit, and both must hold. So "this rail cannot hold a filing decision" stops being a promise
about the operator and becomes a property the examiner checks on the record in their hand — with no network
and no trust. It runs wherever a verdict is verified through the shared kernels: the downloadable examiner
pack, which re-verifies every signature in your browser, and the console's in-browser check. The one
vocabulary is parity-pinned to the door's, so the verifier can never
be less strict than the wall (`kernel/mirror-forbidden.js`, enforced in `kernel/mirror-sign.js`
`verifyRecord`; pinned by `kernel/mirror-forbidden.test.js` and `server/forbidden-parity.test.js`). It is
scoped honestly: it forbids what a verdict must never hold, and deliberately still admits a signed
*provenance* record that quotes a ratified table — because the operator holds ratified edges by design and
is blind only to the per-shipment salt and value.

## And it cannot quietly stop being any of these

The refusals are not honour-system. `conformance/falsify.js` is a seeded fuzzer that fires poisoned and
clean payloads at the real operator and **publishes the first defect its own run finds** — it caught a
real depth-limited scan that let a raw value nine levels deep through, now fixed and pinned. `server/schema-linter.js`
is a build-time guard over the signed record shapes. If a future change removes a guard above, a test
goes red before it ships; nothing here can decay into a promise without the suite noticing.

---

*This is the specification of Mirror's designed inability. Read alongside the
[boundary register](/boundary-register.md) (what it cannot **detect**, and the honest upgrade path), the
[threat model](/threat-model.md), and the [protocol spec](/mirror-protocol-spec.md). Every claim here is
a test; run the suite and hold us to it. See also the [typology map](/typologies.md) — what Mirror
detects, and what still hides from it.*
