@receiz/mcp-server
Version:
MCP server for agents building and verifying Receiz proof-native applications through the canonical Receiz SDK rails.
403 lines • 34.8 kB
JavaScript
import { createHash, randomBytes } from "node:crypto";
import { createReceizDeviceMaterialHost } from "./deviceMaterialHost.js";
import { deviceRuntimeOwner } from "./deviceOwner.js";
import { mkdtemp, open, realpath } from "node:fs/promises";
import { basename, join, relative, sep } from "node:path";
export const RECEIZ_SEALED_OUTPUT_URI = "ui://receiz/sealed-output-v22.html";
// ChatGPT file delivery mechanics only. These origins never admit proof or
// authorize custody; the canonical artifact and the complete byte check do.
export const RECEIZ_CHATGPT_FILE_ORIGINS = Object.freeze([
"https://oaisdmntprcentralus.blob.core.windows.net",
"https://oaisdmntprcacentral.blob.core.windows.net",
"https://oaisdmntprnortheu.blob.core.windows.net",
"https://oaisdmntprsoutheastus3.blob.core.windows.net",
"https://files.oaiusercontent.com",
"https://chatgpt.com",
]);
export const RECEIZ_PROOF_DELIVERY_ORIGINS = Object.freeze([...RECEIZ_CHATGPT_FILE_ORIGINS, "https://receiz.com"]);
export const RECEIZ_SEALED_OUTPUT_RESOURCE = Object.freeze({ uri: RECEIZ_SEALED_OUTPUT_URI,
name: "Receiz sealed proof delivery", description: "Component-only exact sealed artifact download after canonical device verification.",
mimeType: "text/html;profile=mcp-app" });
export const RECEIZ_SEALED_CHUNK_SIZE = 256 * 1024;
const transfers = new WeakMap();
export function registerReceizSealedOutput(runtime, reference, sha256, exactSnapshot) {
if (!/^receiz:file:[a-f0-9]{64}:.+$/.test(reference) || !/^[a-f0-9]{64}$/.test(sha256)
|| reference.slice(12, 76) !== sha256)
throw Error("sealed_output_reference_invalid");
const token = randomBytes(32).toString("base64url");
let held = transfers.get(runtime);
if (!held) {
held = new Map();
transfers.set(runtime, held);
}
for (const [key, value] of held)
if (value.expiresAt <= Date.now())
held.delete(key);
while (held.size >= 4)
held.delete(held.keys().next().value);
if (exactSnapshot && createHash("sha256").update(exactSnapshot.exactBytes).digest("hex") !== sha256)
throw Error("sealed_output_source_changed");
held.set(token, { reference, sha256, expiresAt: Date.now() + 30 * 60_000,
...(exactSnapshot ? { held: { ...exactSnapshot, exactBytes: exactSnapshot.exactBytes.slice() } } : {}) });
return token;
}
/** Exact-byte persistence beneath prior canonical admission. This composes the
* same private workspace write and digest locator used by offline sealing;
* it does not seal, parse, transform, or admit the supplied artifact. */
export async function persistReceizSealedOutput(workspacePath, input) {
const workspace = await realpath(workspacePath);
const filename = basename(input.filename);
if (!input.exactBytes.length || !filename || filename === "." || filename === "..")
throw Error("sealed_output_source_invalid");
const directory = await mkdtemp(join(workspace, ".receiz-sealed-"));
const outputPath = join(directory, filename);
const output = await open(outputPath, "wx", 0o600);
try {
await output.writeFile(input.exactBytes);
await output.sync();
}
finally {
await output.close();
}
const artifactSha256 = createHash("sha256").update(input.exactBytes).digest("hex");
return { artifactReference: `receiz:file:${artifactSha256}:${relative(workspace, outputPath).split(sep).join("/")}`,
artifactSha256, suggestedFilename: filename, mimeType: input.mimeType, byteLength: input.exactBytes.length,
mcpAuthority: false, strongerTruth: "sealed-receiz-proof-object" };
}
/** Device-custodied exact bytes. The reference is a locator, never authority. */
export async function readReceizSealedOutputChunk(input, workspace, runtime) {
if (!input || typeof input !== "object" || Array.isArray(input))
throw Error("sealed_output_arguments_invalid");
const args = input;
const byToken = typeof args.transferToken === "string";
if (Object.keys(args).some(key => !["transferToken", "artifactReference", "artifactSha256", "offset"].includes(key))
|| !Number.isSafeInteger(args.offset) || Number(args.offset) < 0
|| (byToken ? Object.keys(args).some(key => ["artifactReference", "artifactSha256"].includes(key))
: "transferToken" in args || typeof args.artifactReference !== "string" || typeof args.artifactSha256 !== "string"
|| !/^receiz:file:[a-f0-9]{64}:.+$/.test(args.artifactReference)
|| !/^[a-f0-9]{64}$/.test(args.artifactSha256)
|| args.artifactReference.slice(12, 76) !== args.artifactSha256))
throw Error("sealed_output_arguments_invalid");
const held = transfers.get(runtime);
// Reuse the held exact snapshot when present. After restart, a reference may
// reopen only through genuine owner admission and the existing canonical
// workspace verifier. Neither a digest nor identityAdmitted grants custody.
let transfer = byToken ? held?.get(args.transferToken)
: [...(held?.values() ?? [])].reverse().find(value => value.reference === args.artifactReference
&& value.sha256 === args.artifactSha256 && value.expiresAt > Date.now());
if (!transfer && !byToken) {
try {
deviceRuntimeOwner(runtime);
}
catch {
throw Error("sealed_output_transfer_unavailable");
}
const reference = args.artifactReference, sha256 = args.artifactSha256;
const opened = await createReceizDeviceMaterialHost(workspace).resolveProofReference(reference);
const token = registerReceizSealedOutput(runtime, reference, sha256);
transfer = transfers.get(runtime).get(token);
transfer.held = { exactBytes: opened.exactBytes.slice(), filename: opened.filename, mimeType: opened.mimeType };
}
if (!transfer || transfer.expiresAt <= Date.now())
throw Error("sealed_output_transfer_unavailable");
// First chunk admits an exact same-process snapshot. Later chunks use those
// same verified bytes, never a changing file or model-supplied projection.
if (!transfer.held) {
const opened = await createReceizDeviceMaterialHost(workspace).resolveProofReference(transfer.reference);
if (createHash("sha256").update(opened.exactBytes).digest("hex") !== transfer.sha256)
throw Error("sealed_output_source_changed");
transfer.held = { exactBytes: opened.exactBytes.slice(), filename: opened.filename, mimeType: opened.mimeType };
}
const source = transfer.held;
const bytes = source.exactBytes;
const offset = Number(args.offset);
if (offset >= bytes.length)
throw Error("sealed_output_offset_invalid");
const chunk = bytes.subarray(offset, Math.min(offset + RECEIZ_SEALED_CHUNK_SIZE, bytes.length));
const sha256 = createHash("sha256").update(bytes).digest("hex");
if (sha256 !== transfer.sha256)
throw Error("sealed_output_source_changed");
return {
public: { offset, nextOffset: offset + chunk.length, byteLength: bytes.length, artifactSha256: sha256,
filename: source.filename, mimeType: source.mimeType, mcpAuthority: false },
private: { bytesBase64: Buffer.from(chunk).toString("base64") },
};
}
// A component-only transport: exact bytes are never placed in model-visible
// content or structuredContent. ChatGPT's file library is optional; local
// download remains available when the host does not provide uploadFile.
export const RECEIZ_SEALED_OUTPUT_HTML = `<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>
*{box-sizing:border-box}body{font:14px/1.45 system-ui,-apple-system,"Segoe UI",sans-serif;margin:0;padding:8px;background:transparent;color:#152238}
.proof{position:relative;overflow:hidden;width:100%;max-width:600px;border:1px solid #e6e1d5;border-radius:20px;background:linear-gradient(150deg,#fff 0%,#fff 58%,#faf8f2 100%);box-shadow:0 16px 40px rgba(16,30,50,.09),0 1px 3px rgba(16,30,50,.04)}
.proof:before{content:"";display:block;height:3px;background:linear-gradient(90deg,#a98546,#e8d9ac 38%,#f8f2df 74%,#a98546)}
.inner{padding:21px 23px 19px}.head{display:flex;gap:13px;align-items:center}.mark{display:grid;place-items:center;width:42px;height:42px;flex:none;border:1px solid #e3dac7;border-radius:12px;background:#fff;box-shadow:0 3px 9px rgba(22,34,53,.06);color:#152238;font:700 25px/1 Georgia,serif}
.eyebrow{margin:0 0 3px;color:#8f7141;font-size:10px;font-weight:750;letter-spacing:.16em;text-transform:uppercase}.title{margin:0;color:#152238;font:600 21px/1.1 Georgia,"Times New Roman",serif;letter-spacing:-.025em}.rule{height:1px;margin:18px 0;background:linear-gradient(90deg,#ded8c9,#eeeae1 80%,transparent)}
.state{display:flex;align-items:flex-start;gap:10px;min-height:41px}.dot{width:8px;height:8px;flex:none;margin-top:6px;border-radius:50%;background:#af8a4d;box-shadow:0 0 0 4px #f8f0df}.state p{margin:0;color:#344355;font-size:13px}button{display:inline-flex;justify-content:center;align-items:center;width:100%;min-height:42px;margin:17px 0 0;padding:10px 15px;border:1px solid #132239;border-radius:10px;background:#14243b;color:#fff;font:650 13px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;letter-spacing:.015em;cursor:pointer;box-shadow:0 6px 14px rgba(20,36,59,.16)}button:hover:not(:disabled){background:#263e5c}button:focus-visible,a:focus-visible{outline:2px solid #a98546;outline-offset:3px}button:disabled{opacity:.58;cursor:default;box-shadow:none}
.facts{display:grid;grid-template-columns:1fr auto;gap:7px 12px;margin-top:19px;padding:13px 14px;border:1px solid #eee8dc;border-radius:11px;background:#fcfbf8}.label{color:#7c766b;font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase}.value{color:#26374c;font-size:11px;font-weight:650;text-align:right}.hash{grid-column:1/-1;color:#3b4b5d;font:10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere}.foot{display:flex;align-items:flex-start;gap:7px;margin:14px 0 0;color:#6e7780;font-size:11px;line-height:1.45}.foot:before{content:"◆";color:#ad8a50;font-size:9px;margin-top:2px}#link{margin:0}#link a{display:inline-block;margin-top:12px;color:#173b66;font-weight:650;text-decoration:underline;text-underline-offset:3px}
@media(max-width:440px){.inner{padding:17px}.title{font-size:19px}.facts{grid-template-columns:1fr auto}}
</style></head><body><article class="proof" aria-label="Receiz sealed proof object"><div class="inner"><header class="head"><div class="mark" aria-hidden="true">R</div><div><p class="eyebrow">Receiz · private custody</p><h2 class="title">Sealed proof object</h2></div></header><div class="rule"></div><div class="state"><span class="dot" aria-hidden="true"></span><p id="status" aria-live="polite">Waiting for the proof result from your device.</p></div><div class="facts"><span class="label">Integrity</span><span class="value">Canonical proof</span><span class="label">Sealed bytes</span><span class="value" id="size">—</span><span class="label">Artifact SHA-256</span><span class="hash" id="digest">Awaiting verified artifact</span></div><button id="save" disabled>Save sealed proof ↓</button><p id="link"></p><p class="foot">The sealed file is the proof object. This panel only verifies delivery of its exact bytes.</p></div></article><script>
(function(){
const platformOrigins=${JSON.stringify(RECEIZ_CHATGPT_FILE_ORIGINS)};
const status=document.getElementById('status'),button=document.getElementById('save'),link=document.getElementById('link'),digest=document.getElementById('digest'),size=document.getElementById('size');
status.dataset.resourceVersion='22';
let output=null,hostCapabilities=null,bridgeReady=false,busy=false,failed=false,saveStarted=false,uploadInvoked=false,saved=null,originalFile=null,downloadTarget=null,downloadClaims=null,nextId=1;
const pending=new Map();
function envelopes(value){
const values=[value,value?.result,value?.mcp_tool_result,value?.mcp_tool_result?.result,
value?.call_tool_result,value?.call_tool_result?.result];
return values.filter(item=>item&&typeof item==='object');
}
function accept(result){
if(busy||saveStarted)return;
const frames=envelopes(result);
const raw=frames.map(item=>item.structuredContent||item).find(item=>item?.artifactReference&&/^[a-f0-9]{64}$/.test(item?.artifactSha256||''));
if(raw&&output&&['artifactSha256','artifactReference','suggestedFilename','byteLength','mimeType'].some(key=>raw[key]!==undefined&&output[key]!==undefined&&raw[key]!==output[key]))return;
if(raw&&!output){output={...raw};
digest.textContent=raw.artifactSha256;size.textContent=Number.isSafeInteger(raw.byteLength)?raw.byteLength.toLocaleString()+' bytes':'—';}
if(failed)return;
const held=window.openai?.widgetState?.privateContent?.receizSealedSave;
if(output&&held&&held.artifactSha256===output.artifactSha256&&held.byteLength===output.byteLength&&held.filename===output.suggestedFilename){
saved=held;
if(held.phase==='accepted'&&held.fileId){button.disabled=!(typeof window.openai?.callTool==='function'||bridgeReady);button.textContent='Download sealed proof ↓';
status.textContent='Verified proof object ready to download.';return;}
if(!held.fileId&&held.phase!=='retrieval-requested'){saveStarted=true;button.disabled=false;button.textContent='Download sealed proof ↓';status.textContent='Your original proof remains available. ChatGPT save is unconfirmed.';return;}
}
if(output&&(typeof window.openai?.callTool==='function'||bridgeReady)){status.textContent=saved?.fileId?'Your original proof is ready to download.':'Verified proof ready on your connected owner runtime.';button.textContent='Download sealed proof ↓';button.disabled=false;}
else if(output){status.textContent='Proof verified; this host did not provide the private file handoff.';
status.dataset.handoffShape=frames.map(item=>['_meta','structuredContent','result','mcp_tool_result','call_tool_result'].filter(key=>key in item).join(',')).join('|');
status.dataset.handoffMeta=frames.map(item=>Object.keys(item._meta||{}).join(',')).join('|');
status.dataset.handoffTransfer=frames.map(item=>Object.keys(item._meta?.['receiz/sealedTransfer']||{}).join(',')).join('|');}
}
function discover(){
const legacy=window.openai;
if(!legacy)return;
const result=legacy.toolResponseMetadata?.mcp_tool_result;
if(result){accept({...result,structuredContent:result.structuredContent||legacy.toolOutput});return;}
if(legacy.toolOutput)accept({structuredContent:legacy.toolOutput,_meta:legacy.toolResponseMetadata?._meta});
}
function request(method,params){
const id=nextId++;
return new Promise((resolve,reject)=>{
const timeout=setTimeout(()=>{pending.delete(id);reject(Error('Host did not answer '+method));},15000);
pending.set(id,{resolve,reject,timeout});
window.parent.postMessage({jsonrpc:'2.0',id,method,params},'*');
});
}
window.addEventListener('message',event=>{
if(event.source!==window.parent)return;
const message=event.data;
if(!message||message.jsonrpc!=='2.0')return;
if(message.id!==undefined&&pending.has(message.id)){
const wait=pending.get(message.id);pending.delete(message.id);clearTimeout(wait.timeout);
if(message.error)wait.reject(Error(message.error.message||'Host request failed'));
else wait.resolve(message.result);
}
if(message.method==='ui/notifications/tool-result')accept(message.params);
},{passive:true});
window.addEventListener('openai:set_globals',discover);discover();
if(typeof window.parent?.postMessage==='function')request('ui/initialize',{protocolVersion:'2026-01-26',appInfo:{name:'Receiz sealed proof delivery',version:'11.0.0'},appCapabilities:{}})
.then(result=>{hostCapabilities=result?.hostCapabilities||{};bridgeReady=true;
status.dataset.hostCapabilities=Object.keys(hostCapabilities).join(',');
if(output)accept({structuredContent:output});
window.parent.postMessage({jsonrpc:'2.0',method:'ui/notifications/initialized'},'*');})
.catch(()=>{if(!window.openai&&!output)status.textContent='This host did not connect the proof handoff.';});
const decode=value=>{const binary=atob(value),bytes=new Uint8Array(binary.length);for(let i=0;i<binary.length;i++)bytes[i]=binary.charCodeAt(i);return bytes;};
const hex=bytes=>Array.from(bytes,v=>v.toString(16).padStart(2,'0')).join('');
function checkedUrl(value,origins){const url=new URL(value);status.dataset.handoffOrigin=url.origin;if(url.protocol!=='https:'||url.username||url.password||url.hash||!origins.includes(url.origin))throw Error('Exact file delivery origin unavailable');return url;}
function showDownloadFallback(){
if(!downloadTarget)return;
const panel=document.createElement('div');panel.setAttribute('role','group');panel.setAttribute('aria-label','Receiz file download');
panel.style.cssText='margin-top:14px;padding:13px 14px;border:1px solid #e6e1d5;border-radius:11px;background:#fcfbf8';
const name=document.createElement('div');name.textContent=downloadClaims.source.suggestedFilename;name.style.cssText='font-size:12px;font-weight:650;overflow-wrap:anywhere';
const open=document.createElement('a');open.href=downloadTarget.url.href;open.target='_blank';open.rel='noopener noreferrer';open.download=downloadClaims.source.suggestedFilename;open.textContent='Download file ↗';
open.onclick=event=>{if(typeof window.openai?.openExternal==='function'||bridgeReady&&hostCapabilities?.openLinks){event.preventDefault();
if(downloadTarget.expiresAt<=Date.now())return button.onclick();
return openOriginalDownload().catch(error=>{status.dataset.handoffError=error?.message||'Download unavailable';status.textContent='Open or copy the Receiz file link to save your proof.';});}};
panel.append(name,open);link.replaceChildren(panel);status.dataset.downloadHandoff='link';
}
async function openOriginalDownload(){
const url=downloadTarget?.url;
if(!url)throw Error('Receiz original file delivery unavailable');
if(typeof window.openai?.openExternal==='function')await window.openai.openExternal({href:url.href,redirectUrl:false});
else if(bridgeReady&&hostCapabilities?.openLinks)await request('ui/open-link',{url:url.href});
else throw Error('Host file opener unavailable');
// An opener acknowledgment cannot establish a completed filesystem save.
// Keep one exact-original HTTPS link available for a fresh user gesture.
showDownloadFallback();
status.dataset.downloadState='requested';
status.textContent='Your original proof is ready to save.';
}
async function prepareOriginalDownload(source,attemptIds){
const args={prepareDownload:true,attemptIds,artifactSha256:source.artifactSha256,byteLength:source.byteLength};
const result=window.openai?.callTool?await window.openai.callTool('receiz_offline_artifact_chunk',args):await request('tools/call',{name:'receiz_offline_artifact_chunk',arguments:args});
const frames=envelopes(result);
if(frames.some(item=>item.isError))throw Error('Receiz original file delivery unavailable');
const item=frames.map(frame=>frame.structuredContent).find(item=>item?.artifactSha256);
const delivery=frames.map(frame=>frame._meta?.['receiz/sealedDownload']).find(Boolean);
if(!item||item.artifactSha256!==source.artifactSha256||item.byteLength!==source.byteLength||item.filename!==source.suggestedFilename
||!delivery||!Number.isSafeInteger(delivery.expiresAt))throw Error('Original file delivery identity changed');
const url=checkedUrl(delivery.downloadUrl,['https://receiz.com']);
if(url.pathname!=='/download/proof/'+encodeURIComponent(source.suggestedFilename)||url.searchParams.size!==1
||!url.searchParams.get('ticket'))throw Error('Original file delivery identity changed');
downloadClaims={source,attemptIds};downloadTarget={url,expiresAt:delivery.expiresAt};
}
function offerDownload(){} // Platform URLs are inspected, never exposed as download links.
function originalDownload(exact,filename){originalFile={bytes:exact,filename};}
async function exactDownload(url,expected){
const response=await fetch(url.href,{credentials:'omit',redirect:'error',cache:'no-store'});
if(!response.ok||(response.url&&new URL(response.url).href!==url.href))throw Error('Exact file retrieval unavailable');
const parts=[];let length=0;
if(response.body){const reader=response.body.getReader();try{for(;;){const item=await reader.read();if(item.done)break;
length+=item.value.length;if(length>expected.byteLength){await reader.cancel();throw Error('Proof bytes changed during delivery');}parts.push(item.value);
}}finally{reader.releaseLock();}}
else parts.push(new Uint8Array(await response.arrayBuffer()));
const exact=new Uint8Array(parts.reduce((sum,part)=>sum+part.length,0));let offset=0;for(const part of parts){exact.set(part,offset);offset+=part.length;}
if(exact.length!==expected.byteLength||hex(new Uint8Array(await crypto.subtle.digest('SHA-256',exact)))!==expected.artifactSha256)throw Error('Proof bytes changed during delivery');
return exact;
}
async function rememberSave(value){
saved=value;
if(typeof window.openai?.setWidgetState==='function'){
const previous=window.openai.widgetState||{};
await window.openai.setWidgetState({modelContent:previous.modelContent||{},privateContent:{...(previous.privateContent||{}),receizSealedSave:value},imageIds:previous.imageIds||[]});
}
}
async function nativeOriginalDownload(exact,filename){
let binary='';for(let i=0;i<exact.length;i+=32768)binary+=String.fromCharCode(...exact.subarray(i,i+32768));
await request('ui/download-file',{contents:[{type:'resource',resource:{uri:'file:///'+encodeURIComponent(filename),mimeType:'application/octet-stream',blob:btoa(binary)}}]});
status.dataset.downloadState='requested';status.dataset.handoffStage='download-requested';
status.textContent='Sealed proof download requested. Save the file when your device asks.';
}
async function boundedFileHandoff(promise){
let timer;try{return await Promise.race([promise,new Promise((_,reject)=>{timer=setTimeout(()=>reject(Error('ChatGPT file handoff timed out')),10000);})]);}
finally{clearTimeout(timer);}
}
async function chatgptFile(exact,source){
if(!window.openai?.getFileDownloadUrl||!window.openai?.setWidgetState||(!saved?.fileId&&!window.openai?.uploadFile))return false;
const base={artifactSha256:source.artifactSha256,byteLength:source.byteLength,filename:source.suggestedFilename,
...(source.deliveryArtifactSha256?{deliveryArtifactSha256:source.deliveryArtifactSha256,deliveryByteLength:exact.length,deliveryFilename:source.deliveryFilename}: {})};
let fileId=saved?.fileId;
if(!fileId){
await rememberSave({...base,phase:'upload-requested'});
// Frozen trailer delivery law: opaque MIME is an integrity boundary.
// A filename never authorizes interpretive upload or download MIME.
const file=new File([exact],source.deliveryFilename||source.suggestedFilename,{type:source.deliveryMimeType||source.mimeType});
// One user-selected save request. An exception is an unknown outcome, never
// permission for a second upload or a library:false automatic retry.
uploadInvoked=true;
const uploaded=await boundedFileHandoff(window.openai.uploadFile(file,{library:true}));
if(typeof uploaded?.fileId!=='string'||!uploaded.fileId)throw Error('ChatGPT file acceptance unconfirmed');
fileId=uploaded.fileId;await rememberSave({...base,fileId,phase:'uploaded'});
}
status.dataset.handoffStage='checking-chatgpt-file';
const target=await boundedFileHandoff(window.openai.getFileDownloadUrl({fileId}));
const url=checkedUrl(target?.downloadUrl,platformOrigins);
await boundedFileHandoff(exactDownload(url,{artifactSha256:source.deliveryArtifactSha256||base.artifactSha256,byteLength:exact.length}));
status.dataset.deliveryArtifactSha256=source.deliveryArtifactSha256||base.artifactSha256;status.dataset.deliveryByteLength=String(exact.length);
await rememberSave({...base,fileId,phase:'accepted'});
offerDownload(url,source.deliveryFilename||source.suggestedFilename,source.deliveryArtifactSha256?'Download sealed proof carrier':'Download exact sealed proof');status.dataset.handoffStage='chatgpt-exact-file-accepted';
status.textContent=source.deliveryArtifactSha256?'ChatGPT accepted the verified proof carrier. Original seal and source are preserved. Library availability depends on your account.':'ChatGPT accepted the exact sealed file. Library availability depends on your account.';return true;
}
async function proofCarrier(source,attemptIds){
const parts=[];let offset=0,length=null,metadata=null;
while(length===null||offset<length){
const args={prepareCarrier:true,attemptIds,artifactSha256:source.artifactSha256,byteLength:source.byteLength,offset};
const result=window.openai?.callTool?await window.openai.callTool('receiz_offline_artifact_chunk',args):await request('tools/call',{name:'receiz_offline_artifact_chunk',arguments:args});
const frames=envelopes(result);
if(frames.some(item=>item.isError))throw Error('Verified proof carrier unavailable');
const item=frames.map(frame=>frame.structuredContent).find(item=>item?.sourceArtifactSha256);
const meta=frames.map(frame=>frame._meta?.['receiz/sealedChunk']).find(Boolean);
if(!item||item.sourceArtifactSha256!==source.artifactSha256||item.originalFilename!==source.suggestedFilename
||item.originalByteLength!==source.byteLength||item.originalRestorable!==true||item.signedProofUnchanged!==true
||item.mimeType!=='application/json'||typeof item.filename!=='string'||item.filename!==source.suggestedFilename+'.receizbundle.json'
||!/^[a-f0-9]{64}$/.test(item.artifactSha256)||item.offset!==offset||!Number.isSafeInteger(item.byteLength)
||item.byteLength<1||item.byteLength>67108864||!Number.isSafeInteger(item.nextOffset)||item.nextOffset<=offset||item.nextOffset>item.byteLength
||(metadata&&['artifactSha256','filename','mimeType','byteLength'].some(key=>item[key]!==metadata[key])))throw Error('Proof carrier identity changed');
const bytes=decode(meta?.bytesBase64||item.bytesBase64||'');
if(bytes.length!==item.nextOffset-offset)throw Error('Incomplete proof carrier');
parts.push(bytes);metadata=item;offset=item.nextOffset;length=item.byteLength;
}
const bytes=new Uint8Array(offset);let cursor=0;for(const part of parts){bytes.set(part,cursor);cursor+=part.length;}
if(hex(new Uint8Array(await crypto.subtle.digest('SHA-256',bytes)))!==metadata.artifactSha256)throw Error('Proof carrier bytes changed');
return {bytes,deliveryArtifactSha256:metadata.artifactSha256,deliveryFilename:metadata.filename,deliveryMimeType:metadata.mimeType};
}
button.onclick=async()=>{
if(busy||!output||(typeof window.openai?.callTool!=='function'&&!bridgeReady))return;
if(downloadTarget){busy=true;button.disabled=true;try{if(downloadTarget.expiresAt<=Date.now()){await prepareOriginalDownload(downloadClaims.source,downloadClaims.attemptIds);showDownloadFallback();status.dataset.downloadState='ready';status.textContent='Your original proof is ready to save.';}else await openOriginalDownload();}catch(error){status.dataset.handoffError=error?.message||'Download unavailable';showDownloadFallback();status.textContent='Your proof is ready. Open the Receiz download link below to save the file.';}finally{busy=false;button.disabled=false;}return;}
const downloadOnly=saveStarted||!!(saved&&!saved.fileId&&saved.phase!=='retrieval-requested');
failed=false;busy=true;saveStarted=true;uploadInvoked=false;button.disabled=true;const source={...output};
status.textContent='Retrieving exact sealed bytes…';status.dataset.handoffStage='requesting-exact-file';
try{
if(!saved?.fileId&&!downloadOnly)await rememberSave({artifactSha256:source.artifactSha256,byteLength:source.byteLength,filename:source.suggestedFilename,phase:'retrieval-requested'});
const parts=[],attemptIds=[];let offset=0,expectedLength=null,verifiedFilename=null,verifiedMime=null;
while(expectedLength===null||offset<expectedLength){
const argumentsForChunk={artifactReference:source.artifactReference,artifactSha256:source.artifactSha256,offset};
const result=window.openai?.callTool
?await window.openai.callTool('receiz_offline_artifact_chunk',argumentsForChunk)
:await request('tools/call',{name:'receiz_offline_artifact_chunk',arguments:argumentsForChunk});
const frames=envelopes(result);
status.dataset.handoffStage='chunk-returned';
if(frames.some(item=>item.isError))throw Error('Device retrieval failed');
const publicPart=frames.map(item=>item.structuredContent).find(item=>item?.artifactSha256);
const meta=frames.map(item=>item._meta?.['receiz/sealedChunk']).find(Boolean);
const chunkBase64=meta?.bytesBase64||publicPart?.bytesBase64;
if(!chunkBase64)throw Error('Component-only file transport unavailable');
if(!publicPart||publicPart.offset!==offset||publicPart.artifactSha256!==source.artifactSha256)throw Error('Proof source changed');
if(typeof publicPart.filename!=='string'||publicPart.filename!==source.suggestedFilename
||typeof publicPart.mimeType!=='string'||!publicPart.mimeType
||(source.mimeType!==undefined&&publicPart.mimeType!==source.mimeType
&&publicPart.mimeType!=='application/octet-stream')
||(verifiedFilename!==null&&(publicPart.filename!==verifiedFilename||publicPart.mimeType!==verifiedMime)))throw Error('Exact file identity unavailable');
verifiedFilename=publicPart.filename;verifiedMime=publicPart.mimeType;
if(typeof publicPart.receizTransportAttemptId==='string'&&/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/.test(publicPart.receizTransportAttemptId))attemptIds.push(publicPart.receizTransportAttemptId);
if(!Number.isSafeInteger(publicPart.nextOffset)||publicPart.nextOffset<=offset||!Number.isSafeInteger(publicPart.byteLength)
||publicPart.byteLength<1||publicPart.byteLength>524288000||publicPart.nextOffset>publicPart.byteLength||(expectedLength!==null&&publicPart.byteLength!==expectedLength)
||(source.byteLength!==undefined&&publicPart.byteLength!==source.byteLength))throw Error('Incomplete proof transfer');
const bytes=decode(chunkBase64);if(bytes.length!==publicPart.nextOffset-offset)throw Error('Incomplete proof transfer');
parts.push(bytes);offset=publicPart.nextOffset;expectedLength=publicPart.byteLength;
}
const exact=new Uint8Array(offset);let cursor=0;for(const part of parts){exact.set(part,cursor);cursor+=part.length;}
const digest=hex(new Uint8Array(await crypto.subtle.digest('SHA-256',exact)));
if(digest!==source.artifactSha256)throw Error('Proof bytes changed');
status.dataset.handoffStage='digest-matched';
const filename=verifiedFilename;
if(typeof filename!=='string'||!filename||filename.length>255||filename.includes('/')||filename.includes(String.fromCharCode(92))
||Array.from(filename).some(character=>character.charCodeAt(0)<32||character.charCodeAt(0)===127)
||!source.artifactReference.startsWith('receiz:file:'+source.artifactSha256+':')
||source.artifactReference.slice(12+64+1).split(String.fromCharCode(92)).join('/').split('/').pop()!==filename)throw Error('Exact file identity unavailable');
const file=new File([exact],filename,{type:verifiedMime});
originalDownload(exact,filename);
status.dataset.chatgptFileApis=['uploadFile','getFileDownloadUrl','openExternal'].filter(name=>typeof window.openai?.[name]==='function').join(',');
const canonicalSource={...source,byteLength:exact.length,suggestedFilename:file.name,mimeType:file.type};
const hosted=attemptIds.length===parts.length;
if(hosted){await prepareOriginalDownload(canonicalSource,attemptIds);
if(hostCapabilities?.downloadFile)await nativeOriginalDownload(exact,filename);
else{showDownloadFallback();status.dataset.downloadState='ready';status.textContent='Your original proof is ready to save.';}}
if(!downloadOnly){
if(exact.length<=33554432&&(saved?.fileId||window.openai?.uploadFile)&&window.openai?.getFileDownloadUrl&&window.openai?.setWidgetState&&hosted){
status.dataset.handoffStage='verifying-proof-carrier';
const carrier=await proofCarrier(canonicalSource,attemptIds);
await chatgptFile(carrier.bytes,{...canonicalSource,...carrier});
}else await chatgptFile(exact,canonicalSource);
}
if(downloadTarget){status.textContent=status.dataset.downloadHandoff==='link'?'Your original proof is ready to save.':'Sealed proof download requested. Save the file when your device asks.';busy=false;button.disabled=false;button.textContent='Download sealed proof ↓';return;}
if(hostCapabilities?.downloadFile){
await nativeOriginalDownload(exact,filename);busy=false;return;
}
// A local host may download held bytes directly. Never present a frame-local
// blob URL as an external link or send it to ChatGPT's native opener.
const anchor=document.createElement('a');anchor.href=URL.createObjectURL(new Blob([originalFile.bytes],{type:'application/octet-stream'}));anchor.download=originalFile.filename;
if(typeof anchor.click!=='function')throw Error('Host file download unavailable');anchor.click();
status.dataset.handoffStage='browser-download-requested';busy=false;status.textContent='Sealed proof download requested. Check your downloads.';
}catch(error){busy=false;const unknownUpload=uploadInvoked&&!saved?.fileId;failed=unknownUpload;saveStarted=unknownUpload;status.dataset.handoffError=error?.message||'File handoff failed';
if(downloadTarget){button.disabled=false;button.textContent='Download sealed proof ↓';
if(status.dataset.downloadState==='requested')status.textContent=status.dataset.downloadHandoff==='link'?'Your original proof is ready to save.':'Sealed proof download requested. Save the file when your device asks.';
else{showDownloadFallback();status.dataset.downloadState='ready';status.textContent='Your original proof is ready to save.';}
}else if(unknownUpload){status.textContent='ChatGPT save is unconfirmed. Download only; do not repeat the save.';button.disabled=false;button.textContent='Download sealed proof ↓';saveStarted=true;}
else{button.disabled=false;button.textContent='Download sealed proof ↓';status.textContent='File delivery is unconfirmed. Tap Download to retrieve the same proof again.';
if(!saved?.fileId&&!downloadOnly)try{await rememberSave({artifactSha256:source.artifactSha256,byteLength:source.byteLength,filename:source.suggestedFilename,phase:'retrieval-requested'});}catch{}}
}
};
})();
</script></body></html>`;
//# sourceMappingURL=sealedArtifactOutput.js.map