Skip to content

File rebuild (round-trip)

CloakAPI can round-trip a whole document, not just text. You attach a file (see File attachments — file extraction and tokenisation happen client-side via the browser extension, desktop app, or local proxy), let a model work on the tokenised content, and once the response comes back you turn it into a real file — a .docx, .xlsx, .html, and other formats.

The reconstruction step is client-side, like tokenisation. It runs wherever you already hold the alias map — the desktop app, or the open @cloakapi/reconstruction engine running in your own environment. The gateway is a blind relay: it never receives the detokenised text, the alias map, or the rebuilt file. There is no server-side reconstruct endpoint.

How it works (client-side)

Your device / environment (holds the alias map)
│ 1. The model's tokenised response comes back through the gateway
│ (blind relay — sees only tokens, never plaintext)
│ 2. You detokenise the response locally, using the alias map you
│ already hold for the conversation
│ 3. The reconstruction engine (@cloakapi/reconstruction, bundled in
│ the desktop app) rebuilds a real file — locally
Real output file (.docx / .xlsx / .html / …), written on your device

The plaintext and the rebuilt file never leave the machine that holds the alias map. Nothing about the reconstruction touches CloakAPI’s servers.

Where reconstruction runs

  • Desktop app. md, txt, html, docx, and xlsx are rebuilt entirely locally in native Rust (CommonMark via pulldown-cmark, .docx via docx-rs, .xlsx via rust_xlsxwriter — all MIT/Apache). No network call, no data leaves the device. At the max privacy tier — where detokenisation itself happens only on-device — the desktop app rebuilds the file locally too, so the gateway never sees plaintext.
  • Your own environment (builders). The reconstruction engine is the open @cloakapi/reconstruction package. Run it wherever you hold the alias map — your own server, a CLI, or a background job. It supports the full format matrix below. Because you hold the map and run the engine, the plaintext stays inside your trust boundary; CloakAPI’s gateway is never in the loop for the rebuild.

Browser SDK — trivial-format rebuild with no dependency

For a web app, the published SDK ships a dependency-free helper that rebuilds the trivial text formats (txt / md / html / csv / json) directly in the browser — you detokenise the reply locally first (holding your own alias map), then turn it into a downloadable file. The gateway never sees the plaintext or the file:

import { rebuildTextFile, isRebuildableFormat } from "@cloakapi/sdk/browser";
const detokenised = engine.detokenise(reply, map); // client-side, your map
const { blob, filename } = rebuildTextFile(detokenised, "md", "summary.md");
// trigger a download of `blob` (e.g. via an object URL)

Heavier output formats (docx / xlsx / pdf) throw from rebuildTextFile on purpose — it will not route your plaintext through a server to generate them. Use the full @cloakapi/reconstruction engine (matrix below) or the desktop app’s native Rust rebuild for those.

Supported formats

The reconstruction engine validates the target format against a fixed allowlist, matching the “implemented” formats in the package’s format matrix (packages/reconstruction/docs/matrix.md):

FormatMIME typeRound-trip fidelity
txttext/plainGREEN — trivial
mdtext/markdownGREEN — pass-through
htmltext/htmlGREEN
docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentYELLOW — style skeleton, new paragraphs get default style
pdfapplication/pdfYELLOW — textual fidelity, no original glyph layout
xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetGREEN — values only, formulas write-only
csvtext/csvGREEN
pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentationYELLOW — structured JSON or auto-split by headings
epubapplication/epub+zipYELLOW
latexapplication/x-latexGREEN — raw .tex, run pdflatex yourself
svgimage/svg+xmlYELLOW — text-to-SVG, no original vector layout
srtapplication/x-subripGREEN
vtttext/vttGREEN
jsonapplication/jsonGREEN — RFC 8785 canonical
yamltext/yamlGREEN
xmlapplication/xmlGREEN

Not yet supported: png/jpg image output, rtf, odt/ods/odp, mmd (Mermaid), mp3, mp4, zip. See packages/reconstruction/docs/matrix.md for the full deferred-formats rationale.

The alias map

Reconstruction takes the detokenised text plus the alias map you already hold for the conversation:

{
"response_text": "Dear Henry James, your invoice for Acme Corp is attached.",
"alias_map": {
"conversationId": "conv_9f1c2b7a",
"hmacPrefix": "a1b2",
"entries": [
{ "placeholder": "[TOKEN_PERSON_1]", "original": "Henry James" },
{ "placeholder": "[TOKEN_ORG_1]", "original": "Acme Corp" }
]
},
"target_format": "docx",
"input_mime": "application/pdf",
"fidelity": "structural"
}
FieldTypeNotes
response_textstringThe (already detokenised) text to rebuild.
alias_map.conversationIdstringMax 256 chars.
alias_map.hmacPrefixstringMax 16 chars — the request-scoped HMAC prefix salt the tokeniser stamped on every placeholder it emitted for this conversation.
alias_map.entries[]arrayEach entry: { placeholder, original }, both strings, max 512 chars each.
target_formatstringOne of the supported formats above.
input_mimestringOriginal file’s MIME type, e.g. application/pdf. Defaults to text/plain.
fidelitystringtextual | structural | layout | typographic. Defaults to structural.

Only placeholders whose prefix matches alias_map.hmacPrefix are honoured — tokens from a different conversation, or text that merely looks like a placeholder, are rejected by design (packages/reconstruction/src/alias-resolver.ts).

Rebuild receipt claim

The engine records the rebuild as attestation metadata — target format, requested and achieved fidelity, input/output MIME, input/output hashes, and an unresolved-token count. Any value greater than zero for unresolved tokens means some placeholders in response_text could not be resolved against alias_map (the file is still produced; those spans are left as literal placeholder text). The expected shape, folded onto the OpenReceipt envelope alongside the file-attachment attestation:

{
"claims": {
"file_rebuilt": {
"target_format": "docx",
"fidelity_requested": "structural",
"fidelity_achieved": "structural",
"input_mime": "application/pdf",
"output_mime": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"input_hash": "sha256:...",
"output_hash": "sha256:...",
"unresolved_tokens": 0,
"partial": false
}
}
}

Zero-payload invariant

Because reconstruction is client-side, no request or response body, alias-map entry, or rebuilt file ever reaches CloakAPI’s servers — there is nothing on the gateway to leak. In the desktop app the rebuilt bytes are written straight to disk via the native save dialog, never round-tripped over the network.

Portal and desktop apps

Desktop app — a download button in the chat composer lets you pick an output format; the app rebuilds the file locally (native Rust for md/txt/html/ docx/xlsx) and saves it via the native file dialog. At the max tier detokenisation and rebuild both stay on-device.

Browser portal — a download button on the response bubble, next to the receipt strip, rebuilds the file from the alias map held in the browser session for that conversation, using the in-browser reconstruction engine.

  • File attachments — the ingest half of the round-trip
  • Receipts — receipt envelope format and verification
  • Privacy model — tokenisation tiers, including why max never reaches the gateway with plaintext