/* global React, HashBadge, AttestationStatePill, ReasonCodeChip, MerkleProofTree, TimelineAxis */
/* =========================================================
END-TO-END FLOW: Dispute → replay → CE 3.0 export
5 discrete steps shown as a horizontal flow strip.
========================================================= */
function DisputeFlow() {
const [step, setStep] = React.useState(0);
const steps = [
{ id: "inbox", name: "01 · Inbox", sub: "dispute arrives" },
{ id: "open", name: "02 · Decision", sub: "opens attestation" },
{ id: "replay", name: "03 · Replay", sub: "re-verify proof" },
{ id: "assemble",name: "04 · Assemble", sub: "select evidence" },
{ id: "export", name: "05 · Export", sub: "CE 3.0 signed pack" },
];
return (
{/* stepper */}
{steps.map((s, i) => (
))}
{step === 0 && setStep(1)} />}
{step === 1 && setStep(2)} />}
{step === 2 && setStep(3)} />}
{step === 3 && setStep(4)} />}
{step === 4 && setStep(0)} />}
);
}
function StepInbox({ onNext }) {
const disputes = [
{ id: "DSP-2026-04-22-0014", arn: "74711036112401947281", reason: "10.4 · Fraud — card-absent", amt: "€1,240.00", merchant: "ACME-EU", deadline: "14d", att: "ATT-7F4A2C90", priority: "high" },
{ id: "DSP-2026-04-22-0013", arn: "74711036112401923004", reason: "13.1 · Merchandise/services not received", amt: "€82.40", merchant: "ACME-EU", deadline: "21d", att: "ATT-7F4A2C91", priority: "low" },
{ id: "DSP-2026-04-22-0012", arn: "74711036112401888120", reason: "10.4 · Fraud — card-absent", amt: "€500.00", merchant: "ACME-EU", deadline: "8d", att: "ATT-7F4A2C8D", priority: "high" },
];
return (
step 01 — inbox
3 disputes awaiting analyst
Each row links to a signed attestation emitted by the kernel at auth-time. Open one to begin.
webhook · dispute.created · 14:31:02 UTC
| dispute id |
ARN |
reason |
amount |
attestation |
deadline |
|
{disputes.map((d, i) => (
| {d.id} |
{d.arn} |
{d.reason}
{d.priority === "high" && priority}
|
{d.amt} |
|
{d.deadline} |
|
))}
);
}
function StepDecision({ onNext }) {
return (
step 02 — open attestation
ATT-7F4A2C90 · DECLINE · €1,240.00
The kernel signed this decision at auth-time. Every field below was committed to Merkle root .
} />
DECLINE} />
} />
} />
v4.2.1 } />
signer identityEIP-712
} />
● HSM · nCipher} />
} />
);
}
function InfoCell({ k, v, mono }) {
return (
);
}
function SignerRow({ k, v, mono }) {
return (
{k}
{v}
);
}
function StepReplay({ onNext }) {
const [verifying, setVerifying] = React.useState(false);
const [done, setDone] = React.useState(false);
const run = () => {
setVerifying(true); setDone(false);
setTimeout(() => { setVerifying(false); setDone(true); }, 1400);
};
return (
step 03 — replay & re-verify proof
Deterministic replay · model input → output verified
Re-executes the signed model against the committed feature vector hash. Output must match the original attestation byte-for-byte.
{/* replay console */}
{done && ● match · committed root matches recomputed root}
);
}
function Line({ t, ok, working, sub }) {
return (
{ok ? "✓" : working ? "⋯" : "·"}
{t}
{sub && {sub}}
);
}
function StepAssemble({ onNext }) {
const [sel, setSel] = React.useState({
sig: true, merkle: true, reason: true, model: true, features: true, sca: true, device: false, policy: false,
});
const toggle = k => setSel(s => ({ ...s, [k]: !s[k] }));
const items = [
{ id: "sig", name: "EIP-712 signature", req: true, bytes: "256 B", artifact: "0x4a7b8c…3921" },
{ id: "merkle", name: "Merkle inclusion proof", req: true, bytes: "480 B", artifact: "depth 5 · 5 siblings" },
{ id: "reason", name: "Reason code manifest (F14, F22)", req: true, bytes: "128 B", artifact: "schema v2.1" },
{ id: "model", name: "Model version + weights hash", req: true, bytes: "96 B", artifact: "v4.2.1 · 0x0c2d…48" },
{ id: "features", name: "Feature vector hash", req: true, bytes: "64 B", artifact: "0x9c3f1a…b6" },
{ id: "sca", name: "SCA / 3DS attestation link", req: false, bytes: "1.1 KB", artifact: "3DS-9A41C2E7 · ECI 05" },
{ id: "device", name: "Device fingerprint capsule", req: false, bytes: "2.4 KB", artifact: "reputation hash" },
{ id: "policy", name: "Ruleset version attestation", req: false, bytes: "320 B", artifact: "ruleset v18" },
];
const total = items.filter(i => sel[i.id]).reduce((n, i) => n + parseFloat(i.bytes), 0);
return (
step 04 — assemble evidence pack
Visa CE 3.0 · Compelling Evidence bundle
Required artifacts are pre-selected and locked. Optional ones strengthen the case; the exporter signs the final bundle as a single Merkle leaf.
| artifact | size | detail | required |
{items.map(i => (
!i.req && toggle(i.id)}>
|
{i.name} |
{i.bytes} |
{i.artifact} |
{i.req ? "required" : "optional"} |
))}
pack previewCE 3.0 · JSON + PDF
artifacts
{items.filter(i => sel[i.id]).length}/{items.length}
bundle size
{total.toFixed(1)} KB
{"{"}
"scheme": "visa",
"ce_version": "3.0",
"attestation": "ATT-7F4A2C90",
"root": "0xa1b2c3…2345",
"signer": "0x7a1c9e…d031",
"artifacts": [
{items.filter(i => sel[i.id]).map(i => (
"{i.id}",
))}
]
{"}"}
);
}
function Check({ on, locked }) {
return (
{on && }
);
}
function StepExport({ onNext }) {
return (
step 05 — export
Signed evidence pack ready for submission
}/>
}/>
}/>
2026-04-22 14:34:11.228 UTC}/>
2026-05-06 (14d)}/>
Dispute lifecycle end-to-end · 43 seconds analyst time · no raw PAN touched · fully reproducible by counterparty
);
}
function KV({ k, v }) {
return (
{k}
{v}
);
}
function ExportButton({ label, sub, primary }) {
return (
);
}
function OutKind({ name, schema, ready }) {
return (
{name}
{ready && ready}
{schema}
);
}
Object.assign(window, { DisputeFlow });