OpenChainGraph Chain · Client-Side Conversions

Document Conversion Verification

Three-node workflow that makes a local file conversion verifiable. Convert a document in the browser, bind the conversion into a canonical receipt that ties the input digest to the converter identity, the parameters, and the output digest, then independently verify the receipt by recomputing its binding. Each stage produces a tamper-evident SHA-256 execution hash, and nothing leaves the browser.

Markdown / Tabular Conversion Receipt RFC 8785 binding 3 nodes W3C VC §13.11 v0.6.0
Workflow summary
Popular client-side converters prove privacy but attest nothing about how a file was transformed. This workflow supplies the missing layer. Stage 1 converts the document locally. Stage 2 binds the conversion edge into a receipt whose binding_sha256 is a SHA-256 over the JCS-canonical receipt. Stage 3 recomputes that binding and, when the files are supplied, re-hashes them to confirm they match. Nodes: ART-189 (or ART-190 on the tabular branch) then ART-191 then ART-192.
Branches. This workflow has two entry paths. The markdown branch starts at the Markdown converter (ART-189). The tabular branch swaps in the Tabular Data Converter (ART-190) for CSV, JSON, and Markdown-table conversion. Both branches share the same receipt builder and verifier for stages 2 and 3.
ART-189 Markdown Converter ART-190 Tabular (branch) ART-191 Receipt Builder ART-192 Receipt Verifier ★
★ terminal node · gold border = export · dashed = branch alternate
Stage 1: Local Conversion
1
convert_markdown_document · ART-189
Convert Markdown to injection-safe HTML and plain text over a hand-rolled CommonMark subset, and return SHA-256 digests of the input, HTML, and plain text over exact UTF-8 bytes. On the tabular branch, convert_tabular_data (ART-190) converts across CSV, JSON, and Markdown tables with RFC 4180 parsing.
→ Open tool · → Tabular branch
MCP tool: convert_markdown_document
{
  "tool": "convert_markdown_document",
  "arguments": {
    "markdown": "# Report\n\nSee **results** in the [appendix](https://example.org).",
    "options": { "heading_ids": true, "table_support": true }
  }
}
Stage 2: Bind the Conversion Receipt
2
build_conversion_receipt · ART-191
Bind the input digest, converter identity, parameters, and output digest into a canonical receipt. binding_sha256 is a SHA-256 over the JCS-canonical receipt with binding_sha256 removed. Checks cover hex validity, converter identity completeness, and the self-conversion case.
→ Open tool
MCP tool: build_conversion_receipt
{
  "tool": "build_conversion_receipt",
  "arguments": {
    "input_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "output_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
    "source_format": "markdown",
    "target_format": "html",
    "converter": { "name": "art-189-markdown-document-converter", "version": "1.0.0" },
    "parameters": { "heading_ids": true, "table_support": true }
  }
}
Stage 3: Verify the Receipt (terminal)
3
verify_conversion_receipt · ART-192
Recompute binding_sha256 over the JCS-canonical receipt and compare, then optionally compare digests re-hashed from the actual files. Returns a verdict of valid, binding_mismatch, digest_mismatch, or malformed. Final stage, exportable as Policy Mandate JSON or W3C VC.
→ Open tool
MCP tool: verify_conversion_receipt
{
  "tool": "verify_conversion_receipt",
  "arguments": {
    "receipt": { "...": "the receipt object returned by build_conversion_receipt" },
    "recomputed_input_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "recomputed_output_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
  }
}
Full Chain MCP Sequence

Run the three tools in order. The converter digests feed the receipt builder, and the receipt feeds the verifier, so the verdict is fully reproducible by re-hashing the files.

Full chain: 3 MCP calls
// Step 1: convert the document locally (Markdown branch)
const step1 = await mcp.call("convert_markdown_document", {
  markdown: "# Report\n\nSee **results** in the [appendix](https://example.org).",
  options: { heading_ids: true, table_support: true }
});

// Step 2: bind the conversion edge into a receipt
const step2 = await mcp.call("build_conversion_receipt", {
  input_sha256: step1.input_sha256,
  output_sha256: step1.html_sha256,
  source_format: "markdown",
  target_format: "html",
  converter: { name: "art-189-markdown-document-converter", version: "1.0.0" },
  parameters: { heading_ids: true, table_support: true }
});

// Step 3: verify the receipt (final stage)
const step3 = await mcp.call("verify_conversion_receipt", {
  receipt: step2.receipt,
  recomputed_input_sha256: step1.input_sha256,
  recomputed_output_sha256: step1.html_sha256
});

console.log("Verdict:", step3.verdict);          // "valid"
console.log("Binding:", step2.receipt.binding_sha256);
Chain Metadata
Chain slugdocument-conversion-verification
Nodesart-189 (or art-190) → art-191 → art-192
Branchesmarkdown · tabular
ClusterClient-Side Conversions
StandardsRFC 4180 · CommonMark / GFM · RFC 8785 (JCS)
Spec version0.6.0
Terminal exportPolicy Mandate JSON · W3C VC (§13.11)
Hash schemeSHA-256 over JCS-canonical {policy_parameters, output_payload}