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 relays the tokenised response; reconstruction stays on the device that holds the alias map. 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 — tokenisation runs before egress)
│ 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 stay on the machine that holds the alias map. Reconstruction does not upload either to CloakAPI.

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, this rebuild path does not upload the file. At the max privacy tier — where detokenisation itself happens only on-device — the desktop app rebuilds the file locally too, so plaintext stays on the device.
  • 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 plaintext and the file stay on the device:

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
}
}
}

Rebuild stays on the device

Because reconstruction is client-side, the alias map and the rebuilt file do not reach CloakAPI’s servers. The gateway only relays the tokenised request and response, and when your client sends an idempotency key it keeps a tokenised copy of the response for 24 hours so a retry returns the same result. 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