PageSourceSearch

https://phasoric.com/assets/ExchangeParticipantPage-BzyEWhmH.js

js phasoric.com collected 2026-10-02 01:41:18 UTC 26,442 bytes, 2 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/pdf-Z9pqnvJW.js","assets/react-vendor-BqQF_9sx.js","assets/rolldown-runtime-BNNRdYrd.js"])))=>i.map(i=>d[i]);
2import{o as le}from"./rolldown-runtime-BNNRdYrd.js";import{_ as de,b as pe,h as me,r as he,s as q}from"./react-vendor-BqQF_9sx.js";import{t as fe}from"./arrow-down-to-line-BDrDoikw.js";import{t as ue}from"./check-BqN3womb.js";import{t as ye}from"./circle-alert-O5VGs98L.js";import{t as xe}from"./circle-check-CAIOAVvh.js";import{t as we}from"./clock-DN7EZiEq.js";import{t as D}from"./copy-hpp0DL04.js";import{t as be}from"./lock-keyhole-2TZFXc4h.js";import{t as ge}from"./shield-alert-BMjaOk0D.js";import{t as ve}from"./shield-Du7n0Agy.js";import{t as ke}from"./upload-DnjwHCuu.js";import{Rt as je,Vt as Ne,Wt as Se}from"./index-D2055s_4.js";import{t as Ee}from"./useVisiblePolling-D3deGbXy.js";import{t as Ce}from"./client-BHTBpyJq.js";import{t as Pe}from"./SEO-B1lzIa6m.js";var I={name:"file-check",size:24,node:[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"m9 15 2 2 4-4",key:"1grp1n"}]]};I.node;var Ae=Se(I),g=le(pe(),1),A=new TextEncoder,V=new TextDecoder,Te=104857600;function K(){if(typeof globalThis<"u"&&globalThis.crypto?.subtle)return globalThis.crypto;throw new Error("Web Crypto API is not available in the current environment.")}async function B(e){const r=K(),i=typeof e=="string"?A.encode(e):e instanceof Uint8Array?e:new Uint8Array(e),t=await r.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(t),c=>c.toString(16).padStart(2,"0")).join("")}async function Be(e,r){if(!e||!/^[A-Za-z0-9_-]{32,256}$/.test(r||""))throw new Error("The participant invitation credential is invalid.");const i=K(),t=async w=>new Uint8Array(await i.subtle.digest("SHA-256",A.encode(`basalt-vault-exchange:${w}:v1:${e}:${r}`))),c=await t("participant-key"),l=BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),m=(BigInt(`0x${Array.from(c,w=>w.toString(16).padStart(2,"0")).join("")}`)%(l-1n)+1n).toString(16).padStart(64,"0"),d=Uint8Array.from(m.match(/.{2}/g),w=>Number.parseInt(w,16)),o=Uint8Array.from([48,65,2,1,0,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,4,39,48,37,2,1,1,4,32]),p=new Uint8Array(o.length+d.length);p.set(o),p.set(d,o.length);const f=await i.subtle.importKey("pkcs8",p,{name:"ECDH",namedCurve:"P-256"},!0,["deriveBits"]),u=await i.subtle.exportKey("jwk",f);return{token:L(await t("participant-token")),privateKey:u,publicKey:{kty:"EC",crv:"P-256",x:u.x,y:u.y,ext:!0,key_ops:[]}}}function Ke(e){return L(A.encode(JSON.stringify(e)))}function J(e){if(!e||typeof e!="string")throw new Error("Private key string is missing or invalid.");return JSON.parse(V.decode(W(e)))}function Y(e,r="bin"){return(String(e||"").replace(/[\\/:*?"<>|\u0000-\u001f\u007f]/g,"_").trim()||`document.${r}`).slice(0,180)}async function G(e,r,i,t){const c=K(),l=await c.subtle.importKey("jwk",r,{name:"ECDH",namedCurve:"P-256"},!1,["deriveBits"]),m=await c.subtle.importKey("jwk",i,{name:"ECDH",namedCurve:"P-256"},!1,[]),d=await c.subtle.deriveBits({name:"ECDH",public:m},l,256),o=await c.subtle.importKey("raw",d,"HKDF",!1,["deriveKey"]);return c.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:A.encode(e),info:A.encode("basalt-vault-exchange:v1")},o,{name:"AES-GCM",length:256},!1,t)}async function _e({exchangeId:e,privateKey:r,peerPublicKey:i,fileBytes:t,fileName:c="document.bin",mimeType:l="application/octet-stream",password:m="",maxFileBytes:d=26214400}){const o=K(),p=t instanceof Uint8Array?t:t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(await t.arrayBuffer());if(p.byteLength===0)throw new Error("The selected file is empty.");const f=Math.min(Number(d)||26214400,Te);if(p.byteLength>f)throw new Error(`The file exceeds this exchange's ${Math.round(f/1024/1024)} MB limit (${(p.byteLength/1024/1024).toFixed(1)} MB).`);const u=await B(p),w=Y(c),x=String(l||"application/octet-stream").slice(0,120),v=A.encode(JSON.stringify({version:1,fileName:w,mimeType:x,password:String(m||""),fileSize:p.byteLength,fileSha256:u}
2)),y=new Uint8Array(4+v.byteLength+p.byteLength);new DataView(y.buffer,y.byteOffset,y.byteLength).setUint32(0,v.byteLength,!1),y.set(v,4),y.set(p,4+v.byteLength);const k=await G(e,r,i,["encrypt"]),N=o.getRandomValues(new Uint8Array(12)),_=await o.subtle.encrypt({name:"AES-GCM",iv:N},k,y);return{cipher:_,iv:L(N),cipherSha256:await B(_),plainSha256:u,fileName:w,mimeType:x}}async function ze({exchangeId:e,privateKey:r,peerPublicKey:i,cipher:t,iv:c,expectedCipherSha256:l=null}){const m=t instanceof Uint8Array?t:t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset||0,t.byteLength),d=m.buffer.slice(m.byteOffset,m.byteOffset+m.byteLength);if(l){const k=await B(m);if(k!==l)throw new Error(`The sealed package does not match its recorded digest. Expected: ${l}, Actual: ${k}`)}const o=await G(e,r,i,["decrypt"]),p=await K().subtle.decrypt({name:"AES-GCM",iv:W(c)},o,d),f=new Uint8Array(p);if(f.byteLength<5)throw new Error("The sealed package payload is invalid.");const u=new DataView(f.buffer,f.byteOffset,f.byteLength).getUint32(0,!1);if(u<2||u>f.byteLength-4)throw new Error("The sealed package metadata is corrupted.");const w=V.decode(f.slice(4,4+u)),x=JSON.parse(w);if(x.version!==1)throw new Error(`Unsupported sealed package version: ${x.version}`);const v=f.slice(4+u);if(v.byteLength!==x.fileSize)throw new Error("The recovered file size does not match its sealed receipt.");const y=await B(v);if(y!==x.fileSha256)throw new Error("The recovered file digest does not match its sealed receipt.");return{fileName:Y(x.fileName),mimeType:x.mimeType||"application/octet-stream",password:x.password||"",fileBytes:v,fileSha256:y}}function L(e){let r="";for(let t=0;t<e.length;t+=32768)r+=String.fromCharCode(...e.subarray(t,t+32768));return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function W(e){const r=e.replace(/-/g,"+").replace(/_/g,"/"),i=r.padEnd(Math.ceil(r.length/4)*4,"="),t=atob(i),c=new Uint8Array(t.length);for(let l=0;l<t.length;l+=1)c[l]=t.charCodeAt(l);return c}var $e=104857600,Ue=Object.freeze({general:{preset:"general",maxFileBytes:26214400,allowedMimeTypes:[],allowedExtensions:[],requirePassword:!1,verifyProtectedPdf:!1,requireCommitConfirmation:!0},protected_pdf:{preset:"protected_pdf",maxFileBytes:26214400,allowedMimeTypes:["application/pdf"],allowedExtensions:["pdf"],requirePassword:!0,verifyProtectedPdf:!0,requireCommitConfirmation:!0}});function U(e={}){const r=e?.preset==="protected_pdf"?"protected_pdf":"general",i=Ue[r],t=Number(e?.maxFileBytes??i.maxFileBytes),c=Number.isSafeInteger(t)&&t>0?Math.min(t,$e):i.maxFileBytes,l=(m,d,o)=>Array.isArray(m)?[...new Set(m.map(p=>String(p||"").trim().toLowerCase()).filter(p=>o.test(p)))].slice(0,d):[];return{preset:r,maxFileBytes:c,allowedMimeTypes:l(e?.allowedMimeTypes??i.allowedMimeTypes,20,/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/),allowedExtensions:l(e?.allowedExtensions??i.allowedExtensions,20,/^[a-z0-9]{1,12}$/),requirePassword:e?.requirePassword==null?i.requirePassword:!!e.requirePassword,verifyProtectedPdf:e?.verifyProtectedPdf==null?i.verifyProtectedPdf:!!e.verifyProtectedPdf,requireCommitConfirmation:e?.requireCommitConfirmation==null?i.requireCommitConfirmation:!!e.requireCommitConfirmation}}var Le="/assets/pdf.worker.min-BmVo14Nb.mjs";async function Re(e,r,i){const t=U(i),c=String(e?.name||""),l=String(e?.type||"application/octet-stream").toLowerCase();if(!e||e.size<=0||e.size>t.maxFileBytes)throw new Error(`Choose a non-empty file no larger than ${Math.round(t.maxFileBytes/1024/1024)} MB.`);const m=c.includes(".")?c.split(".").pop().toLowerCase():"";if(t.allowedMimeTypes.length&&!t.allowedMimeTypes.includes(l))throw new Error("This file type is not allowed by the exchange policy.");if(t.allowedExtensions.length&&!t.allowedExtensions.includes(m))throw new Error("This filename extension is not allowed by the exchange policy.");if(t.requirePassword&&!String(r||""))throw new Error("This exchange requires the document password or access code.");const d={fileName:c,mimeType:l,fileSize:e.size,passwordProvided:!!r,pdfHeaderVerified:!1,pdfPasswordVerified:!1,commitConfirmed:!0};if(t.verifyProtectedPdf){const o=new Uint8Array(await e.arrayBuffer());if(d.pdfHeaderVerified=String.fromCharCode(...o.slice(0,5))==="%PDF-",!d.pdfHeaderVerified)throw new Error("The selected file is not an actual PDF document.");const{getDocument:p,GlobalWorkerOptions:f,PasswordResponses:u}=await de(async()=>{const{getDocument:y,GlobalWorkerOptions:k,PasswordResponses:N}=await import("./pdf-Z9pqnvJW.js");return{getDocument:y,GlobalWorkerOptions:k,PasswordResponses:N}},__vite__mapDeps([0,1,2]));
2typeof process<"u"&&process.versions?.node||(f.workerSrc=Le);const w=p({data:o.slice()});let x=!1;try{await w.promise}catch(y){if(x=y?.name==="PasswordException"||y?.code===u.NEED_PASSWORD||y?.code===u.INCORRECT_PASSWORD,!x)throw new Error("Phasoric could not verify this PDF's password protection. Re-save the PDF with a document-open password and try the new file.",{cause:y})}finally{await w.destroy()}if(!x)throw new Error("This PDF opens without a password. Re-save it with a password required to open the document, not only restrictions on editing or printing.");const v=p({data:o.slice(),password:String(r)});try{await(await v.promise).getPage(1),d.pdfPasswordVerified=!0}catch(y){throw new Error("The supplied password does not open this PDF.",{cause:y})}finally{await v.destroy()}}return d}var Oe="basalt_private_exchange_access:v2:",R=/^[A-Za-z0-9_-]{32,256}$/,O=/^[A-Za-z0-9_-]{80,2048}$/,X=/^[A-Za-z0-9_-]{32,256}$/;function Z(e){if(e)return e;try{return globalThis.localStorage}catch{return null}}function $(e){return`${Oe}${String(e||"")}`}function Q(e){return!!(R.test(e?.token||"")&&O.test(e?.rawKey||"")&&(!e.claim||X.test(e.claim)))}function Fe(e,r="",i){const t=Z(i);if(!t||!e)return null;try{const c=JSON.parse(t.getItem($(e))||"null");if(c?.version!==2||!Array.isArray(c.records))return null;const l=c.records.filter(d=>Q(d)&&(!d.expiresAt||new Date(d.expiresAt).getTime()>Date.now()));if(l.length!==c.records.length&&t.setItem($(e),JSON.stringify({version:2,records:l})),!l.length)return t.removeItem($(e)),null;const m=r?l.find(d=>d.claim===r):l.length===1?l[0]:null;return m?{token:m.token,rawKey:m.rawKey,expiresAt:m.expiresAt||null}:null}catch{return null}}function M(e,{claim:r="",token:i,rawKey:t,expiresAt:c=null},l){const m=Z(l);if(!m||!e||!R.test(i||"")||!O.test(t||"")||r&&!X.test(r))return!1;try{const d=$(e),o=JSON.parse(m.getItem(d)||"null"),p=o?.version===2&&Array.isArray(o.records)?o.records.filter(Q):[],f=p.findIndex(x=>x.token===i||r&&x.claim===r),u=f>=0?p[f]:null,w={claim:r||u?.claim||"",token:i,rawKey:t,expiresAt:c};return f>=0?p[f]=w:p.push(w),m.setItem(d,JSON.stringify({version:2,records:p.slice(-4)})),!0}catch{return!1}}function H({origin:e,pathname:r,token:i,rawKey:t}){return!R.test(i||"")||!O.test(t||"")?"":`${e}${r}#${new URLSearchParams({token:i,key:t}).toString()}`}var a=he();function qe(){try{const e=new URLSearchParams(window.location.hash.replace(/^#/,"")),r=e.get("key")||"";return{claim:e.get("claim")||"",token:e.get("token")||"",privateKey:r?J(r):null,rawKey:r}}catch{return{claim:"",token:"",privateKey:null,rawKey:""}}}function De(e){const r=qe();if(r.token&&r.privateKey)return r;const i=Fe(e,r.claim);if(!i)return r;try{return{claim:r.claim,token:i.token,privateKey:J(i.rawKey),rawKey:i.rawKey,restored:!0}}catch{return r}}function nt(){const{id:e}=me(),[r,i]=(0,g.useState)(()=>De(e)),[t,c]=(0,g.useState)(null),[l,m]=(0,g.useState)(!0),[d,o]=(0,g.useState)(""),[p,f]=(0,g.useState)(""),[u,w]=(0,g.useState)(null),[x,v]=(0,g.useState)(""),[y,k]=(0,g.useState)(!1),[N,_]=(0,g.useState)(null),[ee,F]=(0,g.useState)(!1),P=(0,g.useCallback)(async(s=r.token)=>{if(!s)return;const n=await fetch(`/api/vault-exchange/${e}/status`,{headers:{Authorization:`Bearer ${s}`}}),h=await n.json().catch(()=>({}));if(!n.ok)throw new Error(h.error||"Unable to check exchange status.");c(h)},[r.token,e]);(0,g.useEffect)(()=>{let s=!0;return(async()=>{try{o("");let n=r;if(r.claim&&!r.token){const h=await Be(e,r.claim),b=h.token,j=await B(b),E=await fetch(`/api/vault-exchange/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.claim}`,"Content-Type":"application/json"},body:JSON.stringify({tokenHash:j,publicKey:h.publicKey})}),T=await E.json().catch(()=>({}));if(!E.ok)throw new Error(T.error||"Unable to enroll in this exchange.");const S=Ke(h.privateKey);n={claim:r.claim,token:b,privateKey:h.privateKey,rawKey:S},M(e,{claim:r.claim,token:b,rawKey:S}),window.history.replaceState(null,"",`${window.location.pathname}#token=${b}&key=${S}`),s&&i(n)}else if(n.token&&n.privateKey&&n.rawKey){const h=H({origin:window.location.origin,pathname:window.location.pathname,token:n.token,rawKey:n.rawKey});h&&window.location.href!==h&&window.history.replaceState(null,"",h)}if(!n.token||!n.privateKey)throw new Error("This participant link is missing its enrollment or local cryptographic credential.");await P(n.token)}catch(n){s&&o(n.message)}finally{s&&m(!1)}})(),()=>{s=!1}},[]),(0,g.useEffect)(()=>{!r.token||!r.rawKey||M(e,{claim:r.claim,token:r.token,rawKey:r.rawKey,expiresAt:t?.expiresAt||null})},[r.claim,r.rawKey,r.token,t?.expiresAt,e]);const te=(0,g.useCallback)(()=>P().catch(s=>o(s.message)),[P]);Ee(te,!!(t&&!["released","expired","canceled","canceling","expiring"].includes(t.status)),6e3);const re=s=>{const n=s.target.files?.[0]||null,h=U(t?.policy);if(n&&n.size>h.maxFileBytes){w(null),o(`This exchange allows files up to ${Math.round(h.maxFileBytes/1024/1024)} MB.`);return}o(""),w(n)},ae=async s=>{if(s.preventDefault(),!u||!r.privateKey||!t?.peerPublicKey)return o("Select a file after both participants have enrolled.");
2if(!(t.policy?.requireCommitConfirmation&&!window.confirm("Commit this encrypted deposit? After finalization it cannot be replaced or withdrawn unilaterally."))){k(!0),o(""),f("Validating and encrypting entirely in this browser…");try{const n=await Re(u,x,t.policy),h=await u.arrayBuffer(),b=await _e({exchangeId:e,privateKey:r.privateKey,peerPublicKey:t.peerPublicKey,fileBytes:h,fileName:u.name,mimeType:u.type||"application/octet-stream",password:x,maxFileBytes:t.policy.maxFileBytes}),j={iv:b.iv,cipherSha256:b.cipherSha256,plainSha256:b.plainSha256,cipherSize:b.cipher.byteLength,evidence:n},E=new Blob([b.cipher],{type:"application/octet-stream"}),T=await Ce(`vault-exchanges/${e}/${t.slot}/package.bin`,E,{access:"private",handleUploadUrl:`/api/vault-exchange/${e}/upload`,headers:{Authorization:`Bearer ${r.token}`},clientPayload:JSON.stringify(j),multipart:E.size>20971520,contentType:"application/octet-stream"}),S=await fetch(`/api/vault-exchange/${e}/finalize`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify({blob:T,metadata:j})}),C=await S.json().catch(()=>({}));if(!S.ok)throw new Error(C.error||"Unable to finalize the encrypted deposit.");f(C.released?"Both immutable commitments are complete. Retrieval is now enabled.":"Your immutable commitment is complete; waiting for the other participant."),w(null),await P()}catch(n){o(n.message),f("")}finally{k(!1)}}},ie=async()=>{k(!0),o("");try{const s=await fetch(`/api/vault-exchange/${e}/retrieve`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`}}),n=await s.json().catch(()=>({}));if(!s.ok)throw new Error(n.error||"Unable to issue a retrieval capability.");const h=await fetch(n.downloadUrl,{cache:"no-store"});if(!h.ok)throw new Error("The short-lived private retrieval capability was rejected or expired.");const b=await h.arrayBuffer(),j=await ze({exchangeId:e,privateKey:r.privateKey,peerPublicKey:n.peerPublicKey,cipher:b,iv:n.iv,expectedCipherSha256:n.cipherSha256});if(j.fileSha256!==n.plainSha256)throw new Error("The recovered file digest differs from the committed receipt.");const E=await fetch(`/api/vault-exchange/${e}/confirm-decryption`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify({plainSha256:j.fileSha256})}),T=await E.json().catch(()=>({}));if(!E.ok)throw new Error(T.error||"The decryption receipt could not be confirmed.");_(j),f("Decryption and committed-digest verification succeeded in this browser.");const S=URL.createObjectURL(new Blob([j.fileBytes],{type:j.mimeType})),C=document.createElement("a");C.href=S,C.download=j.fileName,document.body.appendChild(C),C.click(),C.remove(),URL.revokeObjectURL(S),await P()}catch(s){o(s.message)}finally{k(!1)}},ne=async()=>{if(window.confirm("Request cancellation? After enrollment, both participants must request it before ciphertext is purged."))try{const s=await fetch(`/api/vault-exchange/${e}/request-cancellation`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`}}),n=await s.json().catch(()=>({}));if(!s.ok)throw new Error(n.error||"Unable to request cancellation.");f(n.mutual?"Both cancellation requests are recorded; storage purge is queued.":"Your cancellation request is recorded. The other participant must also authorize it."),await P()}catch(s){o(s.message)}},se=async()=>{try{const s=await fetch(`/api/vault-exchange/${e}/receipts`,{headers:{Authorization:`Bearer ${r.token}`}});if(!s.ok){const b=await s.json().catch(()=>({}));throw new Error(b.error||"Unable to export signed receipts.")}const n=URL.createObjectURL(await s.blob()),h=document.createElement("a");h.href=n,h.download=`exchange-${e}-receipts.json`,document.body.appendChild(h),h.click(),h.remove(),URL.revokeObjectURL(n)}catch(s){o(s.message)}},oe=async()=>{const s=H({origin:window.location.origin,pathname:window.location.pathname,token:r.token,rawKey:r.rawKey});if(!s)return o("This browser has no participant access link.");try{await navigator.clipboard.writeText(s),f("Participant access link copied. Keep it private; it contains this participant's decryption key.")}catch{o("Unable to copy the participant access link in this browser.")}};if(l)return(0,a.jsxs)("div",{className:"min-h-screen bg-[#070b11] text-basalt-100 flex items-center justify-center",children:[(0,a.jsx)(Ne,{className:"animate-spin text-cyan-400"})," ",(0,a.jsx)("span",{className:"ml-3 text-sm",children:"Establishing your independent participant identity…"})]});if(d&&!t)return(0,a.jsx)("div",{className:"min-h-screen bg-[#070b11] flex items-center justify-center p-4",children:(0,a.jsxs)("div",{className:"max-w-md rounded-3xl border border-red-500/30 bg-[#0c121c] p-8 text-center text-basalt-300",children:[(0,a.jsx)(ge,{className:"mx-auto text-red-400",size:36}),(0,a.jsx)("h1",{className:"mt-4 text-xl font-bold text-white",children:"Exchange unavailable"}),(0,a.jsx)("p",{className:"mt-2 text-xs",children:d}),(0,a.jsx)(q,{to:"/",className:"mt-5 inline-block text-cyan-300",children:"Visit Phasoric"})]})});const z=U(t?.policy),ce=t?.status==="released";return(0,a.jsxs)("div",{className:"min-h-screen bg-[#070b11] text-basalt-100 px-4 py-10",children:[(0,a.jsx)(Pe,{title:`${t?.title||"Private Exchange"}
2 · Phasoric`,description:"Independently enrolled, end-to-end encrypted simultaneous exchange."}),(0,a.jsxs)("div",{className:"mx-auto max-w-3xl space-y-6",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 text-xs font-bold uppercase tracking-[.18em] text-cyan-400",children:[(0,a.jsx)(je,{size:18})," Phasoric Private Exchange"]}),(0,a.jsxs)("div",{className:"text-[10px] text-basalt-500",children:["Expires ",new Date(t.expiresAt).toLocaleString()]})]}),(0,a.jsxs)("div",{className:"rounded-3xl border border-white/10 bg-[#0c121c] shadow-2xl",children:[(0,a.jsxs)("div",{className:"border-b border-white/[.06] p-7",children:[(0,a.jsxs)("div",{className:"text-[10px] font-bold uppercase text-cyan-300",children:["Participant ",t.slot,": ",t.ownName]}),(0,a.jsx)("h1",{className:"mt-1 text-2xl font-bold text-white",children:t.title}),(0,a.jsxs)("p",{className:"mt-2 text-xs text-basalt-400",children:["Your browser generated your identity and private key."," ",t.peerName," independently controls the other slot."]})]}),(0,a.jsxs)("div",{className:"p-7 space-y-6",children:[d&&(0,a.jsxs)("div",{className:"flex gap-2 rounded-xl border border-red-500/30 bg-red-500/10 p-3 text-xs text-red-200",children:[(0,a.jsx)(ye,{size:15}),d]}),p&&(0,a.jsxs)("div",{className:"flex gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-3 text-xs text-emerald-200",children:[(0,a.jsx)(xe,{size:15}),p]}),(0,a.jsx)("div",{className:"grid sm:grid-cols-2 gap-3",children:[["Your slot",t.ownCommitted,t.ownClaimed],[t.peerName,t.peerCommitted,t.peerClaimed]].map(([s,n,h])=>(0,a.jsx)("div",{className:"rounded-2xl border border-white/10 bg-black/30 p-4",children:(0,a.jsxs)("div",{className:"flex justify-between text-xs font-semibold",children:[(0,a.jsx)("span",{children:s}),n?(0,a.jsxs)("span",{className:"text-emerald-400",children:[(0,a.jsx)(ue,{size:12,className:"inline"})," Committed"]}):h?(0,a.jsxs)("span",{className:"text-amber-300",children:[(0,a.jsx)(we,{size:12,className:"inline"})," Enrolled"]}):(0,a.jsx)("span",{className:"text-basalt-500",children:"Awaiting enrollment"})]})},s))}),(0,a.jsx)("div",{className:"rounded-xl border border-cyan-500/20 bg-cyan-500/5 p-4 text-xs text-basalt-300",children:(0,a.jsxs)("div",{className:"flex flex-col justify-between gap-3 sm:flex-row sm:items-center",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("strong",{className:"text-white",children:"Your access is remembered in this browser"}),(0,a.jsx)("p",{className:"mt-1 text-[11px] leading-5 text-basalt-400",children:"You can reopen the original invitation from any supported browser until the exchange expires. Keep it private because it provides access to this participant slot."})]}),(0,a.jsxs)("button",{type:"button",onClick:oe,className:"shrink-0 rounded-lg border border-cyan-300/20 px-3 py-2 text-[11px] font-semibold text-cyan-200 hover:bg-cyan-300/10",children:[(0,a.jsx)(D,{size:12,className:"mr-1 inline"})," Copy access link"]})]})}),!t.ownCommitted&&(0,a.jsxs)("form",{onSubmit:ae,className:"space-y-4 border-t border-white/[.06] pt-5",children:[(0,a.jsxs)("div",{className:"rounded-xl border border-cyan-500/20 bg-cyan-500/5 p-3 text-[11px] text-basalt-300",children:["Policy:"," ",(0,a.jsx)("strong",{className:"text-white",children:z.preset==="protected_pdf"?"Password-protected PDF":"Document exchange"})," ","· max ",Math.round(z.maxFileBytes/1024/1024)," MB"]}),(0,a.jsxs)("label",{className:"relative block rounded-2xl border-2 border-dashed border-white/15 bg-black/30 p-6 text-center",children:[(0,a.jsx)("input",{type:"file",accept:z.preset==="protected_pdf"?".pdf,application/pdf":void 0,onChange:re,className:"absolute inset-0 h-full w-full cursor-pointer opacity-0"}),(0,a.jsx)(ke,{className:"mx-auto text-cyan-400"}),u?(0,a.jsxs)("div",{className:"mt-2 text-sm text-white",children:[u.name," ·"," ",(u.size/1024/1024).toFixed(2)," MB"]}):(0,a.jsx)("div",{className:"mt-2 text-xs text-basalt-300",children:"Choose one file to encrypt and commit"})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)("label",{className:"text-[10px] font-bold uppercase text-basalt-400",children:z.requirePassword?"Required document password":"Optional password or access code"}),(0,a.jsx)("input",{value:x,onChange:s=>v(s.target.value),className:"mt-1 w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white"})]}),!t.peerClaimed&&(0,a.jsx)("p",{className:"text-xs text-amber-300",children:"The other participant must enroll before encryption can use their public key."}),(0,a.jsx)("button",{disabled:y||!u||!t.peerClaimed,className:"w-full rounded-xl bg-cyan-400 px-5 py-3 text-xs font-bold text-black disabled:opacity-40",children:y?"Validating, encrypting, and uploading…":"Review & make immutable commitment"})]}),ce&&(0,a.jsxs)("div",{className:"rounded-2xl border border-emerald-500/40 bg-emerald-950/20 p-5",children:[(0,a.jsxs)("div",{className:"flex gap-3",children:[(0,a.jsx)(be,{className:"text-emerald-400"}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h2",{className:"font-bold text-white",children:"Atomic release complete"}),(0,a.jsx)("p",{className:"text-xs text-basalt-300",children:"Both commitments are recorded. A 60-second, object-scoped retrieval capability will be issued only when requested."})]})]}),(0,a.jsxs)("button",{onClick:ie,disabled:y,className:"mt-4 w-full rounded-xl bg-emerald-400 px-5 py-3 text-xs font-bold text-black disabled:opacity-40",children:[(0,a.jsx)(fe,{size:15,className:"inline mr-2"}),"Retrieve, verify, and decrypt"]}),N&&(0,a.jsxs)("div",{className:"mt-3 rounded-xl bg-black/40 p-3 text-xs",children:[(0,a.jsx)(Ae,{size:14,className:"inline text-emerald-400 mr-2"}),N.fileName,N.password&&(0,a.jsxs)("button",{onClick:()=>{navigator.clipboard.writeText(N.password),F(!0),setTimeout(()=>F(!1),2e3)},className:"ml-3 text-cyan-300",children:[(0,a.jsx)(D,{size:12,className:"inline"})," ",ee?"Copied password":"Copy password"]})]})]}),(0,a.jsxs)("div",{className:"flex justify-between gap-3",children:[(0,a.jsx)("button",{onClick:se,className:"text-[11px] text-cyan-300 hover:text-white",children:"Download signed re
2ceipt bundle"}),(0,a.jsx)("button",{onClick:ne,disabled:t.ownCancellationRequested,className:"text-[11px] text-basalt-400 hover:text-white disabled:opacity-50",children:t.ownCancellationRequested?"Your cancellation request is recorded":"Request mutual cancellation"})]}),(0,a.jsxs)("div",{className:"rounded-2xl border border-white/[.06] bg-black/20 p-4 text-[10px] text-basalt-400",children:[(0,a.jsxs)("div",{className:"font-bold text-cyan-300",children:[(0,a.jsx)(ve,{size:13,className:"inline mr-1"}),"Exchange protection"]}),(0,a.jsx)("p",{className:"mt-2 leading-relaxed",children:"Your document stays private until both participants complete their submissions. When the exchange is ready, each participant can access the other document and review the exchange history."}),(0,a.jsx)(q,{to:"/guides/private-exchange",target:"_blank",rel:"noopener noreferrer",className:"mt-3 inline-flex font-semibold text-cyan-300 hover:text-white",children:"Read the process, recovery, and security guide →"})]})]})]})]})]})}export{nt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.