> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletwall.org/llms.txt
> Use this file to discover all available pages before exploring further.

# PQ Evidence, Testnet Rehearsal & ZK/SP1 Status

> How WalletWall surfaces read-only post-quantum verifier evidence, proof artifact status, testnet rehearsal status, and ZK/SP1 research status as separate, sober gates — aligned with Wallet-Wall/walletwall-vault@0.8.5 (baseline @0.8.1).

export const resolveProofGateMatrix = input => {
  const REHEARSAL = {
    not_configured: 'not_configured',
    rehearsal_metadata_missing: 'rehearsal_metadata_missing',
    unsupported_schema: 'unsupported_schema',
    unavailable: 'unavailable',
    rehearsal_ready: 'rehearsal_ready'
  };
  const PQ_STATE = {
    observed: 'observed',
    not_observed: 'not_observed'
  };
  const ARTIFACT = {
    not_configured: 'not_configured',
    available: 'available'
  };
  const PROOF_BLOCK = {
    gated: 'gated',
    unavailable: 'unavailable',
    not_generated: 'not_generated'
  };
  const FORBIDDEN_CHAINS = [1, 8453, 137, 10, 42161, 56, 43114];
  const ALLOWED_TESTNETS = [31337, 11155111, 84532];
  const RED_LINES = ['Quantum-secure or quantum-proof', 'Production quantum protection', 'ZK-verified wallet', 'Live SP1 proof (proving is gated in this app)', 'On-chain ML-DSA verification (no implementation exists)', 'Mainnet-ready or production-ready', 'Custody, fund protection, or guaranteed security', 'Yield, interest, or returns'];
  const CLAIMS = {
    pq_evidence: 'Read-only, hash-only PQ verifier evidence was observed',
    artifact_available: 'Static proof-artifact metadata is available for display',
    artifact_reproducible: 'A reproducible proof-artifact example is available',
    rehearsal_ready: 'Sepolia testnet rehearsal metadata is documented and metadata-safe',
    research_status: 'Research and testnet status only'
  };
  const rehearsalGate = cfg => {
    if (cfg.metadataConfigured === false) {
      return {
        state: REHEARSAL.not_configured,
        reasons: ['No rehearsal metadata is configured.']
      };
    }
    const reasons = [];
    if (FORBIDDEN_CHAINS.includes(cfg.chainId)) {
      reasons.push(`chainId ${cfg.chainId} is a mainnet chain ID.`);
    } else if (!ALLOWED_TESTNETS.includes(cfg.chainId)) {
      reasons.push(`chainId ${cfg.chainId} is not an allowed testnet/local chain ID.`);
    }
    if (cfg.tokenMode !== 'mock') reasons.push(`tokenMode "${cfg.tokenMode}" is not 'mock'.`);
    if (cfg.safetyGatesAllTrue === false) reasons.push('At least one required appGate is not true.');
    return reasons.length > 0 ? {
      state: REHEARSAL.unavailable,
      reasons
    } : {
      state: REHEARSAL.rehearsal_ready,
      reasons: []
    };
  };
  const pqEvidenceObserved = input?.pqEvidenceObserved === true;
  const artifactAvailable = input?.artifactAvailable === true;
  const artifactReproducible = input?.artifactReproducible === true;
  const chainId = input?.chainId ?? 11155111;
  const tokenMode = input?.tokenMode ?? 'mock';
  const safetyGatesAllTrue = input?.safetyGatesAllTrue !== false;
  const metadataConfigured = input?.metadataConfigured !== false;
  const sp1ProvingRequested = input?.sp1ProvingRequested === true;
  const onChainMldsaRequested = input?.onChainMldsaRequested === true;
  const productionAuditCompleted = input?.productionAuditCompleted === true;
  const mainnetDeploymentRequested = input?.mainnetDeploymentRequested === true;
  const rehearsal = rehearsalGate({
    chainId,
    tokenMode,
    safetyGatesAllTrue,
    metadataConfigured
  });
  const gates = Object.freeze({
    pqEvidence: pqEvidenceObserved ? PQ_STATE.observed : PQ_STATE.not_observed,
    proofArtifact: artifactAvailable ? ARTIFACT.available : ARTIFACT.not_configured,
    proofArtifactReproducible: artifactAvailable && artifactReproducible,
    rehearsal: rehearsal.state,
    proofBlockStatus: PROOF_BLOCK.gated,
    onChainMldsaVerification: 'absent',
    mainnetDeployment: 'blocked',
    productionAudit: productionAuditCompleted ? 'completed' : 'absent'
  });
  const supported = [CLAIMS.research_status];
  if (gates.pqEvidence === PQ_STATE.observed) {
    supported.push(CLAIMS.pq_evidence);
  }
  if (gates.proofArtifact === ARTIFACT.available) {
    supported.push(CLAIMS.artifact_available);
  }
  if (gates.proofArtifactReproducible) {
    supported.push(CLAIMS.artifact_reproducible);
  }
  if (gates.rehearsal === REHEARSAL.rehearsal_ready) {
    supported.push(CLAIMS.rehearsal_ready);
  }
  const unsupported = [];
  if (gates.pqEvidence !== PQ_STATE.observed) {
    unsupported.push('PQ verifier evidence observed');
  }
  if (gates.proofArtifact !== ARTIFACT.available) {
    unsupported.push('Proof-artifact metadata available for display');
  }
  if (!gates.proofArtifactReproducible) {
    unsupported.push('Reproducible proof-artifact example available');
  }
  if (gates.rehearsal !== REHEARSAL.rehearsal_ready) {
    unsupported.push('Testnet rehearsal metadata ready');
  }
  for (const claim of RED_LINES) unsupported.push(claim);
  const failClosedNotices = [];
  if (sp1ProvingRequested) {
    failClosedNotices.push('SP1 proving was requested, but this app pins proofBlockStatus to "gated". No proof is generated by or for this surface, so no live-proof claim is unlocked.');
  }
  if (onChainMldsaRequested) {
    failClosedNotices.push('On-chain ML-DSA verification was requested, but no implementation exists — the public reference records feasibility only. The gate stays "absent".');
  }
  if (mainnetDeploymentRequested) {
    failClosedNotices.push('Mainnet deployment was requested, but it is hard-blocked. Mainnet chain IDs can never resolve to a ready state.');
  }
  if (FORBIDDEN_CHAINS.includes(chainId)) {
    failClosedNotices.push(`chainId ${chainId} is a mainnet chain ID — the rehearsal gate fails closed to "unavailable" and is never shown as ready.`);
  }
  if (tokenMode !== 'mock') {
    failClosedNotices.push('A non-mock token mode fails closed. Only mock assets with no monetary value are ever in scope.');
  }
  if (productionAuditCompleted) {
    failClosedNotices.push('A completed audit is its own separate gate. It does not imply mainnet readiness, production protection, or any of the red-line claims below.');
  }
  return Object.freeze({
    gates,
    rehearsalReasons: rehearsal.reasons,
    supported: Object.freeze(supported),
    unsupported: Object.freeze(unsupported),
    failClosedNotices: Object.freeze(failClosedNotices)
  });
};

export const ProofGateMatrix = ({idPrefix = 'pgm'}) => {
  const GATE_ROWS = [['pqEvidence', 'PQ evidence'], ['proofArtifact', 'Proof artifact status'], ['proofArtifactReproducible', 'Proof artifact reproducible'], ['rehearsal', 'Testnet rehearsal'], ['proofBlockStatus', 'SP1 proving'], ['onChainMldsaVerification', 'On-chain ML-DSA verification'], ['productionAudit', 'Production audit'], ['mainnetDeployment', 'Mainnet deployment']];
  const STYLES = `
.ww-pgm{--ww-pgm-bg:#FAFAF0;--ww-pgm-panel:#FFF7E8;--ww-pgm-ink:#2B2118;--ww-pgm-muted:#59646A;--ww-pgm-line:#B87333;--ww-pgm-line-soft:#D9C7B3;--ww-pgm-accent:#B84923;--ww-pgm-ok:#526246;--ww-pgm-warn:#8A5A1F;--ww-pgm-risk:#8F2F1D;}
@media (prefers-color-scheme:dark){.ww-pgm{--ww-pgm-bg:#1B1512;--ww-pgm-panel:#241C17;--ww-pgm-ink:#F2E9DF;--ww-pgm-muted:#A7B0B5;--ww-pgm-line:#8A5A1F;--ww-pgm-line-soft:#4A3B30;--ww-pgm-accent:#D9714B;--ww-pgm-ok:#9AAB89;--ww-pgm-warn:#D6A85A;--ww-pgm-risk:#E0836B;}}
.light .ww-pgm,:root.light .ww-pgm{--ww-pgm-bg:#FAFAF0;--ww-pgm-panel:#FFF7E8;--ww-pgm-ink:#2B2118;--ww-pgm-muted:#59646A;--ww-pgm-line:#B87333;--ww-pgm-line-soft:#D9C7B3;--ww-pgm-accent:#B84923;--ww-pgm-ok:#526246;--ww-pgm-warn:#8A5A1F;--ww-pgm-risk:#8F2F1D;}
.dark .ww-pgm,:root.dark .ww-pgm{--ww-pgm-bg:#1B1512;--ww-pgm-panel:#241C17;--ww-pgm-ink:#F2E9DF;--ww-pgm-muted:#A7B0B5;--ww-pgm-line:#8A5A1F;--ww-pgm-line-soft:#4A3B30;--ww-pgm-accent:#D9714B;--ww-pgm-ok:#9AAB89;--ww-pgm-warn:#D6A85A;--ww-pgm-risk:#E0836B;}
.ww-pgm{background:var(--ww-pgm-bg);color:var(--ww-pgm-ink);border:2px solid var(--ww-pgm-line);border-radius:4px;padding:1rem;font-size:0.875rem;line-height:1.5;}
.ww-pgm *{box-sizing:border-box;}
.ww-pgm-h{font-weight:600;font-size:0.75rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--ww-pgm-muted);margin:0 0 0.5rem;}
.ww-pgm fieldset{border:1px solid var(--ww-pgm-line-soft);border-radius:3px;padding:0.6rem 0.75rem 0.75rem;margin:0 0 0.75rem;}
.ww-pgm legend{font-weight:600;font-size:0.8125rem;padding:0 0.35rem;color:var(--ww-pgm-accent);}
.ww-pgm-checks{display:grid;grid-template-columns:1fr;gap:0.4rem;}
@media (min-width:40rem){.ww-pgm-checks{grid-template-columns:1fr 1fr;}}
.ww-pgm-check{display:flex;align-items:flex-start;gap:0.45rem;}
.ww-pgm-check input{margin-top:0.25rem;flex:none;}
.ww-pgm-check input:focus-visible{outline:2px solid var(--ww-pgm-accent);outline-offset:2px;}
.ww-pgm-field{display:flex;flex-direction:column;gap:0.25rem;}
.ww-pgm-field label{font-weight:600;}
.ww-pgm-field select{width:100%;padding:0.4rem 0.5rem;border:1px solid var(--ww-pgm-line-soft);border-radius:3px;background:var(--ww-pgm-panel);color:var(--ww-pgm-ink);font:inherit;}
.ww-pgm-field select:focus-visible{outline:2px solid var(--ww-pgm-accent);outline-offset:2px;}
.ww-pgm-scroll{overflow-x:auto;}
.ww-pgm-table{width:100%;border-collapse:collapse;font-size:0.8125rem;}
.ww-pgm-table caption{text-align:left;font-weight:600;color:var(--ww-pgm-muted);padding-bottom:0.35rem;}
.ww-pgm-table th,.ww-pgm-table td{border-bottom:1px solid var(--ww-pgm-line-soft);padding:0.35rem 0.4rem;text-align:left;}
.ww-pgm-code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.8125rem;background:var(--ww-pgm-bg);border:1px solid var(--ww-pgm-line-soft);border-radius:2px;padding:0.05rem 0.3rem;}
.ww-pgm-cols{display:grid;grid-template-columns:1fr;gap:0.75rem;margin-top:1rem;}
@media (min-width:48rem){.ww-pgm-cols{grid-template-columns:1fr 1fr;}}
.ww-pgm-col{border:1px solid var(--ww-pgm-line-soft);border-radius:3px;background:var(--ww-pgm-panel);padding:0.75rem;}
.ww-pgm-col[data-tone="ok"]{border-left:4px solid var(--ww-pgm-ok);}
.ww-pgm-col[data-tone="no"]{border-left:4px solid var(--ww-pgm-risk);}
.ww-pgm-col h4{margin:0 0 0.4rem;font-size:0.875rem;}
.ww-pgm-list{margin:0;padding-left:1.1rem;}
.ww-pgm-list li{margin:0.2rem 0;}
.ww-pgm-list[data-tone="no"] li{color:var(--ww-pgm-risk);}
.ww-pgm-notice{margin-top:0.75rem;border:1px solid var(--ww-pgm-warn);border-left:4px solid var(--ww-pgm-warn);border-radius:3px;padding:0.6rem;color:var(--ww-pgm-warn);}
.ww-pgm-notice ul{margin:0.3rem 0 0;padding-left:1.1rem;}
.ww-pgm-note{margin-top:0.75rem;padding-top:0.6rem;border-top:1px dashed var(--ww-pgm-line-soft);color:var(--ww-pgm-muted);font-size:0.8125rem;}
.ww-pgm-reset{margin-top:0.75rem;padding:0.35rem 0.7rem;border:1px solid var(--ww-pgm-line);border-radius:3px;background:transparent;color:var(--ww-pgm-ink);font:inherit;font-size:0.8125rem;cursor:pointer;}
.ww-pgm-reset:focus-visible{outline:2px solid var(--ww-pgm-accent);outline-offset:2px;}
`;
  const [pqEvidenceObserved, setPqEvidenceObserved] = useState(true);
  const [artifactAvailable, setArtifactAvailable] = useState(true);
  const [artifactReproducible, setArtifactReproducible] = useState(true);
  const [metadataConfigured, setMetadataConfigured] = useState(true);
  const [chainId, setChainId] = useState(11155111);
  const [tokenMode, setTokenMode] = useState('mock');
  const [safetyGatesAllTrue, setSafetyGatesAllTrue] = useState(true);
  const [sp1ProvingRequested, setSp1ProvingRequested] = useState(false);
  const [onChainMldsaRequested, setOnChainMldsaRequested] = useState(false);
  const [productionAuditCompleted, setProductionAuditCompleted] = useState(false);
  const [mainnetDeploymentRequested, setMainnetDeploymentRequested] = useState(false);
  const result = useMemo(() => resolveProofGateMatrix({
    pqEvidenceObserved,
    artifactAvailable,
    artifactReproducible,
    metadataConfigured,
    chainId,
    tokenMode,
    safetyGatesAllTrue,
    sp1ProvingRequested,
    onChainMldsaRequested,
    productionAuditCompleted,
    mainnetDeploymentRequested
  }), [pqEvidenceObserved, artifactAvailable, artifactReproducible, metadataConfigured, chainId, tokenMode, safetyGatesAllTrue, sp1ProvingRequested, onChainMldsaRequested, productionAuditCompleted, mainnetDeploymentRequested]);
  const reset = () => {
    setPqEvidenceObserved(true);
    setArtifactAvailable(true);
    setArtifactReproducible(true);
    setMetadataConfigured(true);
    setChainId(11155111);
    setTokenMode('mock');
    setSafetyGatesAllTrue(true);
    setSp1ProvingRequested(false);
    setOnChainMldsaRequested(false);
    setProductionAuditCompleted(false);
    setMainnetDeploymentRequested(false);
  };
  const evidenceChecks = [{
    name: 'pq',
    label: 'Read-only PQ verifier evidence observed',
    checked: pqEvidenceObserved,
    onChange: setPqEvidenceObserved
  }, {
    name: 'artifact',
    label: 'Proof artifact example available',
    checked: artifactAvailable,
    onChange: setArtifactAvailable
  }, {
    name: 'repro',
    label: 'Proof artifact reproducible',
    checked: artifactReproducible,
    onChange: setArtifactReproducible
  }, {
    name: 'audit',
    label: 'Production audit completed',
    checked: productionAuditCompleted,
    onChange: setProductionAuditCompleted
  }];
  const rehearsalChecks = [{
    name: 'meta',
    label: 'Rehearsal metadata configured',
    checked: metadataConfigured,
    onChange: setMetadataConfigured
  }, {
    name: 'gates',
    label: 'All required safety gates true',
    checked: safetyGatesAllTrue,
    onChange: setSafetyGatesAllTrue
  }];
  const pinnedChecks = [{
    name: 'sp1',
    label: 'Request SP1 proving active',
    checked: sp1ProvingRequested,
    onChange: setSp1ProvingRequested
  }, {
    name: 'mldsa',
    label: 'Request on-chain ML-DSA verification',
    checked: onChainMldsaRequested,
    onChange: setOnChainMldsaRequested
  }, {
    name: 'mainnet',
    label: 'Request mainnet deployment allowed',
    checked: mainnetDeploymentRequested,
    onChange: setMainnetDeploymentRequested
  }];
  return <div className="ww-pgm not-prose">
      <style>{STYLES}</style>

      <p className="ww-pgm-h">Proof gate matrix — educational claim boundaries, not a verifier</p>

      <fieldset>
        <legend>Evidence and artifact gates</legend>
        <div className="ww-pgm-checks">
          {evidenceChecks.map(check => <span className="ww-pgm-check" key={check.name}>
              <input id={`${idPrefix}-${check.name}`} type="checkbox" checked={check.checked} onChange={e => check.onChange(e.target.checked)} />
              <label htmlFor={`${idPrefix}-${check.name}`}>{check.label}</label>
            </span>)}
        </div>
      </fieldset>

      <fieldset>
        <legend>Testnet rehearsal gate</legend>
        <div className="ww-pgm-checks">
          {rehearsalChecks.map(check => <span className="ww-pgm-check" key={check.name}>
              <input id={`${idPrefix}-${check.name}`} type="checkbox" checked={check.checked} onChange={e => check.onChange(e.target.checked)} />
              <label htmlFor={`${idPrefix}-${check.name}`}>{check.label}</label>
            </span>)}
          <div className="ww-pgm-field">
            <label htmlFor={`${idPrefix}-chain`}>Chain</label>
            <select id={`${idPrefix}-chain`} value={chainId} onChange={e => setChainId(Number.parseInt(e.target.value, 10))}>
              <option value={11155111}>Sepolia testnet (11155111)</option>
              <option value={31337}>Local dev chain (31337)</option>
              <option value={1}>Ethereum mainnet (1) — must fail closed</option>
            </select>
          </div>
          <div className="ww-pgm-field">
            <label htmlFor={`${idPrefix}-token`}>Token mode</label>
            <select id={`${idPrefix}-token`} value={tokenMode} onChange={e => setTokenMode(e.target.value)}>
              <option value="mock">Mock assets only</option>
              <option value="real">Non-mock — must fail closed</option>
            </select>
          </div>
        </div>
      </fieldset>

      <fieldset>
        <legend>Hard-pinned gates — select one to watch it fail closed</legend>
        <div className="ww-pgm-checks">
          {pinnedChecks.map(check => <span className="ww-pgm-check" key={check.name}>
              <input id={`${idPrefix}-${check.name}`} type="checkbox" checked={check.checked} onChange={e => check.onChange(e.target.checked)} />
              <label htmlFor={`${idPrefix}-${check.name}`}>{check.label}</label>
            </span>)}
        </div>
      </fieldset>

      <div aria-live="polite">
        <div className="ww-pgm-scroll">
          <table className="ww-pgm-table">
            <caption>Resolved gate states — each derived from its own inputs only</caption>
            <thead>
              <tr>
                <th scope="col">Gate</th>
                <th scope="col">State</th>
              </tr>
            </thead>
            <tbody>
              {GATE_ROWS.map(([key, label]) => <tr key={key}>
                  <th scope="row">{label}</th>
                  <td>
                    <code className="ww-pgm-code">{String(result.gates[key])}</code>
                  </td>
                </tr>)}
            </tbody>
          </table>
        </div>

        {result.rehearsalReasons.length > 0 && <p className="ww-pgm-note">
            Rehearsal gate reasons: {result.rehearsalReasons.join(' ')}
          </p>}

        {result.failClosedNotices.length > 0 && <div className="ww-pgm-notice">
            <strong>Failed closed</strong>
            <ul>
              {result.failClosedNotices.map(notice => <li key={notice}>{notice}</li>)}
            </ul>
          </div>}

        <div className="ww-pgm-cols">
          <div className="ww-pgm-col" data-tone="ok">
            <h4>Claims supported by the selected state</h4>
            <ul className="ww-pgm-list">
              {result.supported.map(claim => <li key={claim}>{claim}</li>)}
            </ul>
          </div>
          <div className="ww-pgm-col" data-tone="no">
            <h4>Claims not supported by the selected state</h4>
            <ul className="ww-pgm-list" data-tone="no">
              {result.unsupported.map(claim => <li key={claim}>{claim}</li>)}
            </ul>
          </div>
        </div>
      </div>

      <p className="ww-pgm-note">
        Educational claim-boundary explorer only. No cryptography runs, no prover or contract is
        called, no repository is fetched, and no wallet is connected. The right-hand column is
        permanent: no combination of these controls can ever move a red-line claim into the
        supported column.
      </p>

      <button type="button" className="ww-pgm-reset" onClick={reset}>
        Reset to the documented testnet scenario
      </button>
    </div>;
};

# PQ Evidence, Testnet Rehearsal & ZK/SP1 Status

<Warning>
  Everything on this page is **read-only research and testnet status**. It is not custody, not a wallet transaction, not signing, not a mainnet deposit, not yield, and not production quantum protection. PQ evidence, proof artifact status, and testnet rehearsal are **separate gates** — none implies the others.
</Warning>

This page documents the post-quantum (PQ) verifier-evidence, proof artifact status, testnet-rehearsal, and ZK/SP1 status surfaces that the [Stablecoin Vault](/features/vault) renders. It aligns the app's public-facing language with the reference repo **[`Wallet-Wall/walletwall-vault`](https://github.com/Wallet-Wall/walletwall-vault)**. The evidence surfaces described here are pinned to the **`walletwall-vault@0.8.5`** baseline (SHA `6462c10`; initial baseline `@0.8.1`); the public repo's `main` has since advanced past this tag, so treat the specific version references below as an as-of snapshot rather than the repo's latest release.

The app consumes only **local, read-only shapes** derived from that repo. It does not fetch the repo at runtime and does not import its contracts, ABIs, verifier code, prover code, or deployment artifacts. See [Vault Boundaries & Disclosures](/vault/boundaries) for the full custody / testnet / quantum-resistance statement.

***

## Three separate gates

WalletWall keeps three independent questions separate and never collapses them into a single "ready / protected / secured" claim:

| Gate                      | Question it answers                                                    | What a positive state means                                                                                                                                                                        |
| ------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **PQ Evidence**           | *Was read-only verifier evidence observed?*                            | A hash-only verifier result is available to display. It is **not** custody, mainnet support, a ZK proof, or on-chain ML-DSA verification.                                                          |
| **Proof Artifact Status** | *Is a reproducible proof artifact example available for display?*      | A static, read-only metadata record derived from the public repo example (PR #65). It is **not** a live proof, **not** SP1-proven in this app, **not** on-chain verification, and **not** custody. |
| **Testnet Rehearsal**     | *Is a testnet simulator / operator path documented and metadata-safe?* | Documented Sepolia/testnet simulator metadata, mock assets only. It is **not** PQ evidence, **not** proof artifact status, and **not** production protection.                                      |

The flagship page may show all three together, but each is labelled as its own gate, and any may be unavailable without affecting the others.

### Try it — proof gate matrix

Toggle the gates below to see exactly which claims each state does and does not support.
The point of the exercise is what *cannot* happen: no combination moves a red-line claim
into the supported column, and requesting SP1 proving, on-chain ML-DSA verification, a
mainnet chain, or a non-mock token fails closed rather than unlocking anything.

This is a claim-boundary explainer, not a verifier or a deployment-status checker. It runs
no cryptography, calls no prover or contract, and fetches nothing.

<ProofGateMatrix idPrefix="pq-gates" />

***

## PQ Evidence (read-only, hash-only)

The Stablecoin Vault renders a **read-only** Post-Quantum Verifier Evidence card. It displays the deterministic, **hash-only** result shape produced by the open ML-DSA-65 verifier in the reference repo (schema id `walletwall.pq-verifier.v1`).

<AccordionGroup>
  <Accordion title="PQ Evidence — technical detail">
    * **Hash-only by design.** The card shows keccak256 hashes of the message, public key, and signature — never raw key, signature, message, or secret material. The adapter **fails closed**: any payload carrying raw material renders the placeholder instead.
    * **Display only.** No verification runs in the app. A `verified: true` result is evidence that the open verifier accepted a test vector — it is not a claim of custody, mainnet support, a ZK proof, or on-chain verification.
    * **Sample vs live.** The flagship page shows a clearly-marked **sample** result; live PQ evidence is *not* observed there.
    * **Reference:** verifier boundary guards and evidence artifact/schema correspond to public repo PRs #60 and #61 (baseline `walletwall-vault@0.8.1`).
  </Accordion>
</AccordionGroup>

<Note>
  The PQ evidence card never reaches a signer, provider, ABI, or network call. It is a self-contained, read-only presentation of an evidence shape.
</Note>

***

## Proof Artifact Status (read-only)

The Stablecoin Vault renders a **read-only** Proof Artifact Status card. It displays metadata derived from the reproducible proof-artifact example published in public repo PR #65 (`walletwall-vault@0.8.5`).

<AccordionGroup>
  <Accordion title="Proof Artifact Status — technical detail">
    * **Static, app-local fixture.** The card shows a demo fixture based on the example shape from the public repo. It is **not** fetched at runtime — no network request is made.
    * **Generated outside the app.** The proof artifact example was produced by the public vault repo reference tooling. This app does not run SP1, does not invoke a prover, and does not call any hosted verifier service.
    * **Proof block is gated.** The `proofBlockStatus` is `gated` — SP1 proving is not active in this app. No proof has been generated by or for this surface.
    * **Hash display only.** The card shows truncated keccak256 hashes for context only (evidence hash, output hash). No raw proving key, private key, witness, or mnemonic is ever displayed. The adapter **fails closed**: any artifact carrying forbidden raw-material fields renders the placeholder.
    * **Schema `walletwall.proof-artifact.v1`.** Only this schema version is understood; others render as unsupported.
    * **Not on-chain verification.** Displaying a proof artifact status is not on-chain ML-DSA verification and is not a production protection guarantee.
    * **Reference:** reproducible proof-artifact example from public repo PR #65 (`walletwall-vault@0.8.5`).
  </Accordion>
</AccordionGroup>

<Note>
  The proof artifact card never reaches a signer, prover, hosted-verifier endpoint, or contract. It is a self-contained, read-only presentation of a static example artifact.
</Note>

***

## Testnet Rehearsal status

The rehearsal status model answers whether a Sepolia/testnet simulator and operator path are documented and the metadata is safe to surface. It mirrors the app-consumable status example published in public repo PR #58 as a **static, app-local fixture** — nothing is fetched at runtime.

The model is deterministic and **fails closed**. It surfaces one of:

| State                        | Meaning                                                                                  |
| ---------------------------- | ---------------------------------------------------------------------------------------- |
| `not_configured`             | No rehearsal metadata configured — read-only readiness only                              |
| `rehearsal_metadata_missing` | Metadata present but required fields absent                                              |
| `unsupported_schema`         | Metadata schema version not understood                                                   |
| `unavailable`                | Malformed, non-testnet/forbidden chain, or a disabled safety gate — never shown as ready |
| `rehearsal_ready`            | Documented Sepolia/testnet metadata, mock token, all safety gates true                   |

A mainnet chain ID, a non-mock token mode, or any disabled safety gate forces `unavailable`. Mainnet chain IDs can never resolve to a ready state.

***

## ZK / SP1 status — disclosure only

The reference repo includes an **SP1 smoke lane** and a **ZK/PQ status matrix** (public repo PRs #62 and #63). In the app these are **research / disclosure status only**:

* The SP1 smoke lane is a **research signal**, not production proving.
* **No on-chain verification** runs in the app.
* There is **no ZK proof** behind any user-facing readiness state, and none is implied.
* This is **not production quantum protection**.

A reproducible proof-artifact example was published in public PR #65 (`walletwall-vault@0.8.5`). The app displays this as read-only Proof Artifact Status (see above). The artifact is **not** a live SP1 proof and **not** on-chain verification.

See the [ZK proof-artifact roadmap](/vault/zk-proof-artifact-roadmap) for the staged, non-production next steps.

***

## Safety boundaries

This surface inherits the full vault boundary statement: **no custody**, **no wallet transaction**, **no signing**, **no contract writes**, **no mainnet deposits**, **no yield**, and **not production quantum protection**. In full, no WalletWall surface here involves:

* custody of funds or private-key handling,
* wallet transactions, signing, or contract writes,
* mainnet deposits or withdrawals,
* yield, interest, or returns,
* production quantum protection.

The complete statement — custody, financial, testnet, quantum-resistance, mainnet gates, and the app/vault repo boundary — lives in [Vault Boundaries & Disclosures](/vault/boundaries).

***

## Approved framing

| Use                                              | Do not use                                 |
| ------------------------------------------------ | ------------------------------------------ |
| Read-only PQ verifier evidence                   | Quantum-proof / quantum-secure             |
| Hash-only result shape                           | Funds are protected / secured              |
| Proof artifact status — read-only                | Live SP1 proof / on-chain verification     |
| Generated outside the app                        | Proof artifact guarantees protection       |
| SP1 proving is gated                             | SP1 proves your wallet                     |
| Testnet rehearsal metadata                       | Mainnet-ready / production-ready           |
| Separate PQ, proof artifact, and rehearsal gates | A single "vault is ready" claim            |
| SP1 smoke is research status                     | On-chain ML-DSA verification (none exists) |
| Not production quantum protection                | Quantum-proof / quantum-safe claim         |

***

## Related

<CardGroup cols={2}>
  <Card title="Vault Boundaries & Disclosures" icon="shield" href="/vault/boundaries">
    Full custody, testnet, and quantum-resistance boundary statement.
  </Card>

  <Card title="Stablecoin Vault & Vault Simulator" icon="vault" href="/features/vault">
    The flagship readiness journey and the Sepolia rehearsal detail route.
  </Card>

  <Card title="ZK proof-artifact roadmap" icon="route" href="/vault/zk-proof-artifact-roadmap">
    Staged, non-production next steps for the ZK/SP1 proof-artifact lane.
  </Card>

  <Card title="walletwall-vault@0.8.5" icon="github" href="https://github.com/Wallet-Wall/walletwall-vault">
    The public reference repo that owns contracts, the verifier, and deployment records (current: @0.8.5).
  </Card>
</CardGroup>
