@semics-tech/emdash-esign 1.0.0-rc.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +3 -2
- package/dist/manifest.json +3 -2
- package/dist/plugin.mjs +14 -14
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/** @type {import("emdash").PluginDescriptor} */
|
|
8
8
|
const descriptor = Object.freeze({
|
|
9
9
|
"id": "semics-esign",
|
|
10
|
-
"version": "1.0.0-rc.
|
|
10
|
+
"version": "1.0.0-rc.2",
|
|
11
11
|
"format": "standard",
|
|
12
12
|
"entrypoint": "@semics-tech/emdash-esign/sandbox",
|
|
13
13
|
"capabilities": [
|
|
@@ -235,7 +235,8 @@ const descriptor = Object.freeze({
|
|
|
235
235
|
"envelopes/list",
|
|
236
236
|
"envelopes/resend",
|
|
237
237
|
"envelopes/void",
|
|
238
|
-
"outbox/status"
|
|
238
|
+
"outbox/status",
|
|
239
|
+
"integrations/pair"
|
|
239
240
|
],
|
|
240
241
|
"adminPages": [
|
|
241
242
|
{
|
package/dist/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "semics-esign",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.2",
|
|
4
4
|
"declaredAccess": {
|
|
5
5
|
"media": {
|
|
6
6
|
"read": {},
|
|
@@ -242,7 +242,8 @@
|
|
|
242
242
|
"envelopes/list",
|
|
243
243
|
"envelopes/resend",
|
|
244
244
|
"envelopes/void",
|
|
245
|
-
"outbox/status"
|
|
245
|
+
"outbox/status",
|
|
246
|
+
"integrations/pair"
|
|
246
247
|
],
|
|
247
248
|
"admin": {
|
|
248
249
|
"settingsSchema": {
|
package/dist/plugin.mjs
CHANGED
|
@@ -2,11 +2,11 @@ function e(e){for(let t of Object.keys(e))e[t]===void 0&&delete e[t];return e}fu
|
|
|
2
2
|
`)}async function pe(e,t){return x(new Uint8Array(await crypto.subtle.sign(`HMAC`,e,ae.encode(t))))}async function me(e){let{secret:t,purpose:n,params:r,now:i,ttlMs:a=9e5}=e,o=await de(t);if(n.length===0)throw Error(`Link purpose must not be empty.`);if(!Number.isFinite(i))throw Error(`Link now must be a finite epoch time in milliseconds.`);if(!(a>=ie&&a<=re))throw Error(`Link ttl must be between ${ie} and ${re} ms.`);let s=Object.entries(r);if(s.some(([e])=>oe.has(e)))throw Error(`Link params must not use the reserved names exp or sig.`);let c=String(Math.floor((i+a)/1e3)),l=new URLSearchParams(s);return l.set(`exp`,c),l.set(`sig`,await pe(o,fe(n,c,s))),l}async function he(e){let{secret:t,purpose:n,query:r,now:i}=e,a=await de(t),o=new Set,s=[],c,l;for(let[e,t]of r){if(o.has(e))return T(`TOKEN_INVALID`);o.add(e),e===`exp`?c=t:e===`sig`?l=t:s.push([e,t])}return c===void 0||l===void 0||!se.test(c)||!le(await pe(a,fe(n,c,s)),l)?T(`TOKEN_INVALID`):i>=Number(c)*1e3?T(`TOKEN_EXPIRED`):w(Object.fromEntries(s))}const ge=Object.freeze({intent:`esign-intent/1`,receipt:`esign-receipt/1`,lookup:`esign-lookup/1`,catalog:`esign-catalog/1`}),_e=Object.freeze({intent:8192,receipt:2048,lookup:1024,catalog:1024}),ve=/^[A-Za-z0-9_-]{4,64}$/,ye=/^[A-Za-z0-9_-]*$/,be=new TextEncoder;function xe(e){if(!ye.test(e)||e.length%4==1)return;let t=atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),n=Uint8Array.from(t,e=>e.charCodeAt(0));return x(n)===e?n:void 0}async function Se(e){if(e.length!==32)throw Error(`Client secret must be 32 bytes.`);return C(e)}async function Ce(e,t,n){let r=await crypto.subtle.sign(`HMAC`,await Se(e),be.encode(`${t}.${n}`));return x(new Uint8Array(r))}const we=/^[A-Za-z0-9_-]{1,64}$/,Te=/^[A-Za-z0-9._:-]{1,128}$/,Ee=/^[0-9a-f]{64}$/,De=/^[A-Za-z0-9_-]{16,64}$/,Oe=/^[A-Za-z0-9_]{1,64}$/,ke=/[\uD800-\uDFFF]/u,Ae=/[\u0000-\u001F\u007F]/,je=/[\u0000- \u007F]/;function Me(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ne(e){let t=0;for(let n of e)t++;return t}function Pe(e,t,n){if(typeof e!=`string`||ke.test(e))return!1;let r=Ne(e);return r>=t&&r<=n}function k(e,t){return typeof e==`string`&&t.test(e)}function Fe(e){return Number.isSafeInteger(e)&&e>=0}function Ie(e){return Pe(e,1,200)&&!Ae.test(e)}function Le(e){if(!Pe(e,1,254)||je.test(e))return!1;let t=e.split(`@`);return t.length===2&&t[0]!==``&&t[1]!==``}function Re(e){if(!Me(e))return!1;let t=Object.entries(e);return t.length<=32&&t.every(([e,t])=>Oe.test(e)&&Pe(t,0,500))}function ze(e){return Me(e)&&Ie(e.name)}function Be(e){let t=e.as===`guardian`;return Fe(e.iat)&&Fe(e.exp)&&e.exp>e.iat&&k(e.nonce,De)&&k(e.tpl,we)&&(e.tplVersion===void 0||Number.isSafeInteger(e.tplVersion)&&e.tplVersion>=1)&&k(e.ref,Te)&&Me(e.signer)&&Ie(e.signer.name)&&Le(e.signer.email)&&(e.as===void 0||e.as===`self`||t||e.as===`buyer`)&&(t?ze(e.participant):!Object.hasOwn(e,`participant`))&&(e.delivery===void 0||e.delivery===`inline`||e.delivery===`email`)&&Re(e.prefill)&&Pe(e.returnUrl,1,2048)}const Ve=new Set([`completed`,`declined`,`voided`,`expired`]);function He(e){let t=e.status===`completed`;return k(e.envelopeId,we)&&k(e.ref,Te)&&Ve.has(e.status)&&k(e.docSha256,Ee)&&(t?e.pdfSha256===null||k(e.pdfSha256,Ee):e.pdfSha256===null)&&(t?k(e.finalHash,Ee):e.finalHash===null)&&Fe(e.at)}const Ue={intent:Be,receipt:He,lookup:e=>Fe(e.ts)&&k(e.ref,Te),catalog:e=>Fe(e.ts)};function We(e,t){return!Me(t)||t.v!==1||t.typ!==e||!k(t.cid,ve)||!Ue[e](t)?T(`PAYLOAD_INVALID`):e===`intent`&&t.exp-t.iat>1800?T(`TOKEN_LIFETIME_EXCEEDED`):w(t)}const Ge=new Set([`localhost`,`127.0.0.1`,`[::1]`]);function Ke(e){try{return new URL(e)}catch{return}}function qe(e){return e.username!==``||e.password!==``}function Je(e){let t=Ke(e);if(!(t===void 0||qe(t)||t.search!==``||e.includes(`#`)))return t.protocol===`https:`||t.protocol===`http:`&&Ge.has(t.hostname)?t:void 0}function Ye(e,t){return t.endsWith(`/`)?e.startsWith(t):e===t||e.startsWith(`${t}/`)}function Xe(e,t){let n=Ke(e);return n===void 0||n.protocol!==`https:`&&n.protocol!==`http:`||qe(n)||e.includes(`#`)?!1:t.some(e=>{let t=Je(e);return t!==void 0&&t.origin===n.origin&&Ye(n.pathname,t.pathname)})}async function Ze(e,t){let{token:n}=t;if(typeof n!=`string`)return T(`TOKEN_MALFORMED`);if(n.length>_e[e])return T(`TOKEN_TOO_LARGE`);let r=n.split(`.`);if(r.length!==2)return T(`TOKEN_MALFORMED`);let[i,a]=r,o=xe(i);if(o===void 0||o.length===0||a.length!==43||xe(a)===void 0)return T(`TOKEN_MALFORMED`);let s=Qe(o);if(s===void 0||!k(s.cid,ve))return T(`TOKEN_MALFORMED`);let c=await t.getClient(s.cid);return c===void 0?T(`CLIENT_UNKNOWN`):c.revoked?T(`CLIENT_REVOKED`):le(await Ce(c.secret,ge[e],i),a)?w({payload:s,client:c}):T(`TOKEN_INVALID`)}function Qe(e){if(!(e[0]===239&&e[1]===187&&e[2]===191))try{let t=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(e));return Me(t)?t:void 0}catch{return}}function $e(e,t){return e===`intent`?t.iat:e===`receipt`?t.at:t.ts}function et(e,t){if(e===`intent`)return t.exp+60;if(e!==`receipt`)return t.ts+300+60}async function tt(e,t){let n=await Ze(e,t);if(!n.ok)return n;let r=We(e,n.value.payload);if(!r.ok)return r;let i=Math.floor(t.now/1e3);if($e(e,r.value)>i+60)return T(`TOKEN_NOT_YET_VALID`);let a=et(e,r.value);return a!==void 0&&i>a?T(`TOKEN_EXPIRED`):w({payload:r.value,client:n.value.client})}async function nt(e){let t=await tt(`intent`,e);if(!t.ok)return t;let{payload:n,client:r}=t.value,i=r.returnUrlAllowlist?.length?r.returnUrlAllowlist:e.siteOrigin===void 0?[]:[`${e.siteOrigin}/`];return Xe(n.returnUrl,i)?await e.consumeNonce(n.cid,n.nonce,n.exp+60)?w(n):T(`TOKEN_REPLAYED`):T(`RETURN_URL_NOT_ALLOWED`)}async function rt(e,t){let n=await tt(e,t);return n.ok?w(n.value.payload):n}function it(e){return rt(`lookup`,e)}function at(e){return rt(`catalog`,e)}async function ot(e,t,n){let r=We(e,t);if(!r.ok)throw Error(`Cannot sign ${e} token: ${r.error}.`);let i=x(be.encode(JSON.stringify(t))),a=`${i}.${await Ce(n,ge[e],i)}`;if(a.length>_e[e])throw Error(`Cannot sign ${e} token: TOKEN_TOO_LARGE.`);return a}const A=(e=Date.now())=>new Date(e).toISOString();function st(e){let t=e.kind;return{to:e.to,subject:e.subject,...typeof t==`string`?{kind:t}:{}}}async function ct(e,t,n,r){let i=r();return await e.put(i,{message:t,status:`pending`,attempts:0,nextAttemptAt:n,createdAt:n}),i}function lt(e){return Math.min(6e4*2**(e-1),36e5)}async function ut(e){let t={sent:0,failed:0,gaveUp:0,remainingHint:!1};if(!e.email)return t;let n=Math.max(1,e.maxPerTick??6),{items:r}=await e.storage.query({status:`pending`,nextAttemptAtLte:e.now,limit:n+1});if(r.length===0)return t;let i=[],a=0,o=0,s=0;for(let{id:t,data:c}of r.slice(0,n)){let n=c.attempts+1;try{await e.email.send(c.message),a++;let r=st(c.message);i.push({id:t,data:{...c,message:r,status:`sent`,attempts:n,sentAt:e.now}})}catch(r){let a=(r instanceof Error?r.message:String(r)).replace(/\S*:\/\/\S*|[\w-]{20,}/g,`…`).slice(0,300);n>=5?(s++,i.push({id:t,data:{...c,message:st(c.message),status:`failed`,attempts:n,lastError:a}})):(o++,i.push({id:t,data:{...c,attempts:n,lastError:a,nextAttemptAt:e.now+lt(n)}}))}}return await e.storage.putMany(i),{sent:a,failed:o,gaveUp:s,remainingHint:r.length>n}}async function dt(e){let[t,n]=await Promise.all([e.storage.query({status:`pending`,limit:100}),e.storage.query({status:`failed`,limit:100})]);return{state:e.email?`ok`:`no_transport`,pending:t.items.length,failed:n.items.length}}const ft=new TextEncoder;function pt(e){if(!ve.test(e))throw Error(`Client id must match the esign-intent/1 clientId grammar.`)}function mt(e,t){if(pt(e),t.length!==32)throw Error(`Client secret must be 32 bytes.`);return`esign1.${e}.${x(t)}`}async function ht(e,t){if(e.length<32)throw Error(`Master key must be at least 32 bytes.`);pt(t);let n=await C(e);return new Uint8Array(await crypto.subtle.sign(`HMAC`,n,ft.encode(`esign-client/1.`+t)))}function gt(e=b){let t=e(16);if(t.length!==16)throw Error(`Random source must return 16 bytes.`);let n=`cl_`;for(let e of t)n+=`abcdefghijklmnopqrstuvwxyz234567`[e&31];return n}const _t=[{font:`regular`,resource:`F1`,baseFont:`Helvetica`},{font:`bold`,resource:`F2`,baseFont:`Helvetica-Bold`},{font:`italic`,resource:`F3`,baseFont:`Helvetica-Oblique`}];function vt(e){let t=new Uint16Array(256);for(let n=0;n<224;n++)t[32+n]=Number.parseInt(e.slice(2*n,2*n+2),36);return t}const yt=vt(`7q7q9vfgfgopij5b9999atg87q997q7qfgfgfgfgfgfgfgfgfgfg7q7qg8g8g8fgs7ijijk2k2ijgzlmk27qdwijfgn5k2lmijlmk2ijgzk2ijq8ijijgz7q7q7qd1fg99fgfgdwfgfg7qfgfg6666dw66n5fgfgfgfg99dw7qfgdwk2dwdwdw9a789ag800fg0066fg99rsfgfg99rsij99rs00gz0000666699999qfgrs99rsdw99q800dwij7q99fgfgfgfg78fg99khaafgg899kh99b4g8999999fgex7q9999a5fgn6n6n6gzijijijijijijrsk2ijijijij7q7q7q7qk2k2lmlmlmlmlmg8lmk2k2k2k2ijijgzfgfgfgfgfgfgopdwfgfgfgfg7q7q7q7qfgfgfgfgfgfgfgg8gzfgfgfgfgdwfgdw`),bt={regular:yt,bold:vt(`7q99d6fgfgopk26m9999atg87q997q7qfgfgfgfgfgfgfgfgfgfg9999g8g8g8gzr3k2k2k2k2ijgzlmk27qfgk2gzn5k2lmijlmk2ijgzk2ijq8ijijgz997q99g8fg99fggzfggzfg99gzgz7q7qfg7qopgzgzgzgzatfg99gzfglmfgfgdwat7satg800fg007qfgdwrsfgfg99rsij99rs00gz00007q7qdwdw9qfgrs99rsfg99q800dwij7q99fgfgfgfg7sfg99khaafgg899kh99b4g8999999gzfg7q9999a5fgn6n6n6gzk2k2k2k2k2k2rsk2ijijijij7q7q7q7qk2k2lmlmlmlmlmg8lmk2k2k2k2ijijgzfgfgfgfgfgfgopfgfgfgfgfg7q7q7q7qgzgzgzgzgzgzgzg8gzgzgzgzgzfggzfg`),italic:yt},xt=new Map([8364,0,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,0,381,0,0,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,0,382,376].flatMap((e,t)=>e?[[e,128+t]]:[])),St=/^[\x20-\x7e\xa0-\xff]*$/;function Ct(e){return e>=32&&e<=126||e>=160&&e<=255?e:e===9||e===10||e===13?32:xt.get(e)??63}function wt(e){if(St.test(e))return e;let t=``;for(let n of e)t+=String.fromCharCode(Ct(n.codePointAt(0)));return t}function Tt(e){return bt[e]}function Et(e,t){let n=bt[t],r=0;for(let t=0;t<e.length;t++)r+=n[e.charCodeAt(t)];return r}const Dt=1e7;function j(e){if(!Number.isFinite(e))return`0`;let t=Math.round(Math.min(Dt,Math.max(-Dt,e))*100)/100;return t===0?`0`:String(t)}function Ot(e){return`(${e.replace(/[\\()]/g,`\\$&`)})`}function kt(e){if(/^[\x20-\x7e]*$/.test(e))return Ot(e);let t=`FEFF`;for(let n=0;n<e.length;n++)t+=e.charCodeAt(n).toString(16).toUpperCase().padStart(4,`0`);return`<${t}>`}function At(e){let t=e.getTime();if(!Number.isFinite(t))return;let n=new Date(t).toISOString();return`D:${n.slice(0,4)}${n.slice(5,7)}${n.slice(8,10)}${n.slice(11,13)}${n.slice(14,16)}${n.slice(17,19)}Z`}function jt(e){return`<< /Length ${e.length} >>\nstream\n${e}\nendstream`}function Mt(e,t,n){let r=[`%PDF-1.7
|
|
3
3
|
%âãÏÓ
|
|
4
4
|
`],i=r[0].length,a=`xref\n0 ${e.length+1}\n0000000000 65535 f \n`;e.forEach((e,t)=>{let n=`${t+1} 0 obj\n${e}\nendobj\n`;a+=`${String(i).padStart(10,`0`)} 00000 n \n`,r.push(n),i+=n.length});let o=n===void 0?``:` /Info ${n} 0 R`;r.push(`${a}trailer\n<< /Size ${e.length+1} /Root ${t} 0 R${o} >>\nstartxref\n${i}\n%%EOF\n`);let s=r.join(``),c=new Uint8Array(s.length);for(let e=0;e<s.length;e++)c[e]=s.charCodeAt(e);return c}function Nt(e){let t,n;return Array.isArray(e)?[t,n]=e:typeof e==`object`&&e&&({x:t,y:n}=e),typeof t==`number`&&typeof n==`number`&&Number.isFinite(t)&&Number.isFinite(n)?[t,n]:void 0}function Pt(e){let t=e?.strokes;if(!Array.isArray(t))return[];let n=[],r=2e4;for(let e of t){if(!Array.isArray(e)||r<=0)continue;let t=[];for(let n of e){let e=Nt(n);e&&r>0&&(t.push(e),r--)}t.length>0&&n.push(t)}return n}function Ft(e,t){let n=Pt(e);if(n.length===0)return``;let r=e,i=typeof r.w==`number`&&Number.isFinite(r.w)&&r.w>0?r.w:0,a=typeof r.h==`number`&&Number.isFinite(r.h)&&r.h>0?r.h:0;if(i===0||a===0){for(let e of n)for(let[t,n]of e)i=Math.max(i,t),a=Math.max(a,n);i=Math.max(i,1),a=Math.max(a,1)}let o=Math.min(t.width/i,t.height/a),s=(t.height-a*o)/2,c=e=>j(t.x+Math.min(i,Math.max(0,e))*o),l=e=>j(t.top-s-Math.min(a,Math.max(0,e))*o),u=[`q 0.05 0.1 0.45 RG 1.2 w 1 J 1 j`];for(let e of n){let[t]=e;u.push(`${c(t[0])} ${l(t[1])} m`),e.length===1&&u.push(`${c(t[0])} ${l(t[1])} l`);for(let t=1;t<e.length;t++){let[n,r]=e[t];u.push(`${c(n)} ${l(r)} l`)}u.push(`S`)}return u.push(`Q`),u.join(`
|
|
5
|
-
`)}const It=wt(` `);function M(e,t,n,r){let i=n*1e3+1e-6,a=Tt(r),o=Et(It,r),s=[],c=[];for(let n of e.split(/\r\n|\r|\n/)){let e=/[\ud800-\udfff]/.test(n)?Array.from(n):void 0,r=(t,r)=>e?e.slice(t,r).join(``):n.slice(t,r),l=wt(n),u=0,d=0,f=()=>{let e=c.length/2,n=c[0]??0,i=c[c.length-1]??0,a=e>0&&i-n===d+e-1,o,f;if(a)o=r(n,i),f=l.slice(n,i);else{let e=[],t=[];for(let n=0;n<c.length;n+=2)e.push(r(c[n],c[n+1])),t.push(l.slice(c[n],c[n+1]));o=e.join(` `),f=t.join(It)}s.push({text:o,bytes:f,width:u*t/1e3}),c.length=0,u=0,d=0},p=s.length;for(let e=0;e<l.length;){if(l.charCodeAt(e)===32){e++;continue}let n=e,r=l.indexOf(` `,n),s=r===-1?l.length:r;e=s;let p=0;for(let e=n;e<s;e++)p+=a[l.charCodeAt(e)];if(c.length>0&&(u+o+p)*t<=i){c.push(n,s),u+=o+p,d+=s-n;continue}if(c.length>0&&f(),p*t<=i){c.push(n,s),u=p,d=s-n;continue}for(;n<s;){let e=n,r=0;for(;e<s;){let o=a[l.charCodeAt(e)];if(e>n&&(r+o)*t>i)break;r+=o,e++}c.length=0,c.push(n,e),u=r,d=e-n,e<s&&f(),n=e}}(c.length>0||s.length===p)&&f()}return s}const Lt={width:595.28,height:841.89},Rt=1.3,zt={1:18,2:13,3:11},Bt=Object.fromEntries(_t.map(e=>[e.font,e.resource])),N=(e,t)=>typeof e==`number`&&Number.isFinite(e)&&e>0?e:t,Vt=(e,t)=>typeof e==`number`&&Number.isFinite(e)&&e>=0?e:t,
|
|
6
|
-
`))}function
|
|
5
|
+
`)}const It=wt(` `);function M(e,t,n,r){let i=n*1e3+1e-6,a=Tt(r),o=Et(It,r),s=[],c=[];for(let n of e.split(/\r\n|\r|\n/)){let e=/[\ud800-\udfff]/.test(n)?Array.from(n):void 0,r=(t,r)=>e?e.slice(t,r).join(``):n.slice(t,r),l=wt(n),u=0,d=0,f=()=>{let e=c.length/2,n=c[0]??0,i=c[c.length-1]??0,a=e>0&&i-n===d+e-1,o,f;if(a)o=r(n,i),f=l.slice(n,i);else{let e=[],t=[];for(let n=0;n<c.length;n+=2)e.push(r(c[n],c[n+1])),t.push(l.slice(c[n],c[n+1]));o=e.join(` `),f=t.join(It)}s.push({text:o,bytes:f,width:u*t/1e3}),c.length=0,u=0,d=0},p=s.length;for(let e=0;e<l.length;){if(l.charCodeAt(e)===32){e++;continue}let n=e,r=l.indexOf(` `,n),s=r===-1?l.length:r;e=s;let p=0;for(let e=n;e<s;e++)p+=a[l.charCodeAt(e)];if(c.length>0&&(u+o+p)*t<=i){c.push(n,s),u+=o+p,d+=s-n;continue}if(c.length>0&&f(),p*t<=i){c.push(n,s),u=p,d=s-n;continue}for(;n<s;){let e=n,r=0;for(;e<s;){let o=a[l.charCodeAt(e)];if(e>n&&(r+o)*t>i)break;r+=o,e++}c.length=0,c.push(n,e),u=r,d=e-n,e<s&&f(),n=e}}(c.length>0||s.length===p)&&f()}return s}const Lt={width:595.28,height:841.89},Rt=1.3,zt={1:18,2:13,3:11},Bt=Object.fromEntries(_t.map(e=>[e.font,e.resource])),N=(e,t)=>typeof e==`number`&&Number.isFinite(e)&&e>0?e:t,Vt=(e,t)=>typeof e==`number`&&Number.isFinite(e)&&e>=0?e:t,Ht=e=>typeof e==`string`?e:e==null?``:String(e),Ut=e=>e===`bold`||e===`italic`?e:`regular`;function Wt(e){let t=Math.round(N(e?.width,Lt.width)*100)/100,n=Math.round(N(e?.height,Lt.height)*100)/100,r=e?.margin,i=e=>Vt(typeof r==`number`?r:typeof r==`object`&&r?r[e]:void 0,56),a={top:i(`top`),right:i(`right`),bottom:i(`bottom`),left:i(`left`)};if(t-a.left-a.right<72||n-a.top-a.bottom<72){let e=Math.max(0,Math.min((t-72)/2,(n-72)/2,56));a={top:e,right:e,bottom:e,left:e}}return{width:t,height:n,margin:a}}var Gt=class{pages=[];ops=[];y;left;right;bottom;constructor(e){this.g=e,this.left=e.margin.left,this.right=e.width-e.margin.right,this.bottom=e.height-e.margin.bottom,this.y=e.margin.top,this.pages.push(this.ops)}get contentWidth(){return this.right-this.left}get atTop(){return this.y<=this.g.margin.top}newPage(){this.ops=[],this.pages.push(this.ops),this.y=this.g.margin.top}ensure(e){this.y+e>this.bottom+1e-6&&!this.atTop&&this.newPage()}pdfY(e){return j(this.g.height-e)}text(e,t,n,r,i){i.length!==0&&this.ops.push(`BT /${Bt[r]} ${j(n)} Tf ${j(e)} ${this.pdfY(t+n)} Td ${Ot(i)} Tj ET`)}alignX(e,t,n=this.left,r=this.contentWidth){return t===`center`?n+(r-e.width)/2:t===`right`?n+r-e.width:n}paragraph(e,t,n,r,i){let a=t*Rt;for(let i of M(e,t,this.contentWidth,n))this.ensure(a),this.text(this.alignX(i,r),this.y,t,n,i.bytes),this.y+=a;this.y+=i}heading(e,t){let n=zt[t],r=M(e,n,this.contentWidth,`bold`),i=this.atTop?0:n*.6;this.ensure(i+r.length*n*Rt+n*.4+20*Rt),this.atTop||(this.y+=i),this.paragraph(e,n,`bold`,`left`,n*.4)}spacer(e){this.y+=e,this.y>this.bottom&&this.newPage()}rule(){this.ensure(12);let e=this.pdfY(this.y+6);this.ops.push(`0.75 w 0.6 G ${j(this.left)} ${e} m ${j(this.right)} ${e} l S 0 G`),this.y+=12}pageBreak(){this.atTop||this.newPage()}table(e,t,n){if(e.length===0)return;let r=e.map(e=>N(e.width,1)),i=r.reduce((e,t)=>e+t,0),a=[],o=r.map(e=>this.contentWidth*e/i);o.reduce((e,t)=>(a.push(e),e+t),this.left);let s=n*Rt,c=(e,t)=>o.map((r,i)=>M(Ht(e[i]),n,r-8,t)),l=c(e.map(e=>e.header),`bold`),u=e=>Math.max(1,...e.map(e=>e.length)),d=u(l)*s+8,f=(e,t,r,i,c)=>{let l=r*s+8,u=this.pdfY(this.y+l);c&&this.ops.push(`0.92 g ${j(this.left)} ${u} ${j(this.contentWidth)} ${j(l)} re f 0 g`),this.ops.push(`0.5 w 0.7 G`);for(let e=0;e<o.length;e++)this.ops.push(`${j(a[e])} ${u} ${j(o[e])} ${j(l)} re S`);this.ops.push(`0 G`),e.forEach((e,o)=>{for(let c=0;c<r;c++){let r=e[t+c];r&&this.text(a[o]+4,this.y+4+c*s,n,i,r.bytes)}}),this.y+=l},p=()=>f(l,0,u(l),`bold`,!0);this.ensure(d+s+8),p();let m=!0;for(let e of t){let t=c(Array.isArray(e)?e:[],`regular`),n=u(t),r=0;for(;r<n;){let e=Math.floor((this.bottom-this.y-8+1e-6)/s),i=n-r;if(e>=i){f(t,r,i,`regular`,!1),m=!1;break}if(m){let i=Math.max(1,e);if(f(t,r,i,`regular`,!1),r+=i,r>=n)break}this.newPage(),p(),m=!0}}this.y+=10*.5}signature(e){let t=Math.min(N(e.width,220),this.contentWidth),n=N(e.height,70),r=M(Ht(e.label),9,this.contentWidth,`regular`).filter(e=>e.bytes),i=(Array.isArray(e.caption)?e.caption:[]).flatMap(e=>M(Ht(e),9,this.contentWidth,`regular`)).filter(e=>e.bytes),a=9*Rt;this.ensure(r.length*a+n+4+i.length*a);for(let e of r)this.text(this.left,this.y,9,`regular`,e.bytes),this.y+=a;let o=this.y,s=M(Ht(e.typedName),20,t,`italic`)[0];s?.bytes&&this.text(this.left+4,o+n-28,20,`italic`,s.bytes);let c=Ft(e.strokes,{x:this.left,top:this.g.height-o,width:t,height:n});c&&this.ops.push(c),this.y=o+n+2;let l=this.pdfY(this.y);this.ops.push(`0.5 w 0.4 G ${j(this.left)} ${l} m ${j(this.left+t)} ${l} l S 0 G`),this.y+=2;for(let e of i)this.text(this.left,this.y,9,`regular`,e.bytes),this.y+=a;this.y+=12}block(e){switch(e.type){case`heading`:this.heading(Ht(e.text),e.level===2||e.level===3?e.level:1);break;case`paragraph`:{let t=N(e.size,10),n=e.align===`center`||e.align===`right`?e.align:`left`;this.paragraph(Ht(e.text),t,Ut(e.font),n,t*.5);break}case`spacer`:this.spacer(Vt(e.height,0));break;case`rule`:this.rule();break;case`pageBreak`:this.pageBreak();break;case`table`:this.table(Array.isArray(e.columns)?e.columns:[],Array.isArray(e.rows)?e.rows:[],N(e.size,9));break;case`signature`:this.signature(e);break}}footer(e){if(!e)return;let t=Ht(e.text),n=this.pages.length;this.pages.forEach((r,i)=>{let a=[t,e.pageNumbers?`Page ${i+1} of ${n}`:``].filter(Boolean);if(a.length===0)return;let[o]=M(a.join(` · `),8,this.contentWidth,`regular`),s=this.alignX(o,`center`),c=this.g.margin.bottom/2;r.push(`BT /F1 8 Tf ${j(s)} ${j(c)} Td ${Ot(o.bytes)} Tj ET`)})}};function Kt(e,t,n){let r=new Gt(e);for(let e of Array.isArray(t)?t:[])e&&typeof e==`object`&&r.block(e);return r.footer(n),r.pages.map(e=>e.join(`
|
|
6
|
+
`))}function qt(e){let t=[],n=(e,n)=>{typeof n==`string`&&n!==``&&t.push(`/${e} ${kt(n)}`)};if(n(`Title`,e?.title),n(`Author`,e?.author),n(`Subject`,e?.subject),n(`Keywords`,e?.keywords),n(`Creator`,e?.creator),n(`Producer`,`semics pdf`),e?.creationDate instanceof Date){let n=At(e.creationDate);n&&t.push(`/CreationDate (${n})`)}return`<< ${t.join(` `)} >>`}function Jt(e){let t=Wt(e.page),n=Kt(t,e.blocks,e.footer),r=[`<< /Type /Catalog /Pages 2 0 R >>`,``,qt(e.info)],i=_t.map(e=>(r.push(`<< /Type /Font /Subtype /Type1 /BaseFont /${e.baseFont} /Encoding /WinAnsiEncoding >>`),`/${e.resource} ${r.length} 0 R`)).join(` `),a=`[0 0 ${j(t.width)} ${j(t.height)}]`,o=[];for(let e of n){r.push(jt(e));let t=r.length;r.push(`<< /Type /Page /Parent 2 0 R /MediaBox ${a} /Resources << /Font << ${i} >> >> /Contents ${t} 0 R >>`),o.push(`${r.length} 0 R`)}return r[1]=`<< /Type /Pages /Kids [${o.join(` `)}] /Count ${o.length} >>`,Mt(r,1,3)}async function Yt(e,t){let n=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(`${t}:${e}`));return S(new Uint8Array(n).slice(0,16))}async function Xt(e,t,n,r){let i=Math.floor(n/(r.windowSeconds*1e3)),a=`rl:${r.scope}:${await Yt(t,r.salt)}:${i}`,o=Number.parseInt(await e.get(a)??`0`,10),s=Number.isFinite(o)&&o>0?o:0;return s>=r.limit?T(`RATE_LIMITED`):(await e.set(a,`${s+1}:${(i+1)*r.windowSeconds}`,{ttlSeconds:r.windowSeconds*2}),w({remaining:r.limit-s-1}))}async function Zt(e,t,n){let r=(await e.list(`rl:`)).filter(({value:e})=>!(Number(String(e).split(`:`)[1])*1e3>t)).map(({key:e})=>e);for(let t of r.slice(0,n))await e.delete(t);return{calls:1+Math.min(n,r.length),more:r.length>n}}const Qt=`cron:scheduled:v11`,$t=`ensure-schedules`;async function en(e,t){try{if(await e.kv.get(Qt))return;await e.cron?.schedule($t,{schedule:new Date(t).toISOString()})}catch{}}async function tn(e,t){let n=e.cron;if(!n)return!1;for(let e of t)await n.schedule(e.name,{schedule:e.schedule});return!0}async function nn(e,t,n){await tn(e,t)&&await e.kv.set(Qt,{at:new Date(n).toISOString()})}async function rn(e,t,n,r){return e.name===$t?(await nn(t,n,r),!0):!1}function an(e){return typeof e==`object`&&!!e&&e.type===`page_load`}function on(e,t=()=>!0,n=Date.now){let r=e.handler,i=async(e,i)=>(t(e?.input)&&await en(i,n()),r(e,i));return{...e,handler:i}}var sn=class extends Error{code=`TEMPLATE_MISSING_FIELD`;constructor(e){super(`Template field "${e}" has no value`),this.field=e,this.name=`TemplateError`}};const cn=/\{\{\s*([A-Za-z_][A-Za-z0-9_.]*)\s*\}\}/g,ln={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`};function un(e){return e.replace(/\s*[\r\n]+\s*/g,` `).replace(/[\\&<>"'#[\]()*_`~|{}+!-]/g,e=>ln[e]??`\\${e}`)}function dn(e){return[...new Set([...e.matchAll(cn)].map(e=>e[1]))]}function fn(e,t){return e.replace(cn,(e,n)=>{let r=Object.hasOwn(t,n)?t[n]:void 0;if(r===void 0)throw new sn(n);return un(String(r))})}function pn(e){return`${e.replace(/^/,``).replace(/\r\n?/g,`
|
|
7
7
|
`).normalize(`NFC`).split(`
|
|
8
8
|
`).map(e=>e.replace(/[ \t]+$/,``)).join(`
|
|
9
|
-
`).replace(/\n+$/,``)}\n`}async function
|
|
9
|
+
`).replace(/\n+$/,``)}\n`}async function P(e){let t=typeof e==`string`?new TextEncoder().encode(e):new Uint8Array(e);return S(await crypto.subtle.digest(`SHA-256`,t))}const mn={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},hn=e=>e.replace(/[&<>"']/g,e=>mn[e]),gn=e=>e.replace(/\s*[\r\n]+\s*/g,` `),_n=/\{\{(\w+)\}\}/g;function vn(e,t,n){return e.replace(_n,(e,r)=>n(t[r]??``))}const yn=`January February March April May June July August September October November December`.split(` `);function bn(e){let t=new Date(e);return`${t.getUTCDate()} ${yn[t.getUTCMonth()]} ${t.getUTCFullYear()}`}function xn(e,t,n){let r=Object.fromEntries(Object.entries(n).map(([e,t])=>[e,gn(t)]));return{to:e,subject:vn(t.subject,r,e=>e),text:vn(t.text,r,e=>e),html:vn(t.html,r,hn)}}function Sn(e){let t=e.expiresAt?`This request expires on ${bn(e.expiresAt)}.`:``;return xn(e.to,{subject:`{{sender}} asks you to sign: {{title}}`,text:`Hello {{name}},
|
|
10
10
|
|
|
11
11
|
{{sender}} has asked you to review and sign "{{title}}" electronically.{{expiry}}
|
|
12
12
|
|
|
@@ -17,22 +17,22 @@ This link is personal to you. Please do not forward it.
|
|
|
17
17
|
`,html:`<p>Hello {{name}},</p>
|
|
18
18
|
<p>{{sender}} has asked you to review and sign "{{title}}" electronically.{{expiry}}</p>
|
|
19
19
|
<p><a href="{{link}}">Review and sign the document</a></p>
|
|
20
|
-
<p>This link is personal to you. Please do not forward it.</p>`},{name:e.signerName,title:e.title,sender:e.sender,link:e.link,expiry:t?` ${t}`:``})}function
|
|
20
|
+
<p>This link is personal to you. Please do not forward it.</p>`},{name:e.signerName,title:e.title,sender:e.sender,link:e.link,expiry:t?` ${t}`:``})}function Cn(e){return xn(e.to,{subject:`Signed: {{title}}`,text:`Hello {{name}},
|
|
21
21
|
|
|
22
22
|
Thank you. "{{title}}" for {{sender}} is now signed.
|
|
23
23
|
Get your signed copy here (the page issues a fresh download link each time):
|
|
24
24
|
{{link}}
|
|
25
25
|
`,html:`<p>Hello {{name}},</p>
|
|
26
26
|
<p>Thank you. "{{title}}" for {{sender}} is now signed.</p>
|
|
27
|
-
<p><a href="{{link}}">Get your signed copy</a> (the page issues a fresh download link each time).</p>`},{name:e.signerName,title:e.title,sender:e.sender,link:e.link})}const
|
|
27
|
+
<p><a href="{{link}}">Get your signed copy</a> (the page issues a fresh download link each time).</p>`},{name:e.signerName,title:e.title,sender:e.sender,link:e.link})}const wn=`outbox-drain`;function Tn(e){let t=e.storage.outbox;return{put:(e,n)=>t.put(e,n),putMany:e=>t.putMany([...e]),query:({status:e,nextAttemptAtLte:n,limit:r})=>t.query({where:{status:e,...n===void 0?{}:{nextAttemptAt:{lte:n}}},orderBy:{nextAttemptAt:`asc`},limit:r})}}function En(e){try{let{origin:t}=new URL(e.site.url);return t===`null`?``:t}catch{return``}}const Dn=(e,t)=>typeof t==`string`&&t.trim()!==``?t.trim():e.site.name,On=`The site URL is not set, so signing invitations and signed-copy emails are not queued (their links would not work). Set the site URL in EmDash's settings, then use Resend invitation.`;async function kn(e,t){let{signerId:n,envelope:r,token:i,now:a}=t,o=En(e);if(!o)return null;let s=Sn({to:r.signer.email,signerName:r.signer.name,title:r.title,sender:Dn(e,t.senderSetting),link:`${o}/sign/${i}`,expiresAt:r.expiresAt});return ct(Tn(e),s,a,()=>`invite-${n}`)}async function An(e,t){let n=En(e);if(!n)return null;let r={to:t.envelope.signer.email,signerName:t.envelope.signer.name,title:t.envelope.title,sender:Dn(e,t.senderSetting),link:`${n}/signed/${t.token}`};return ct(Tn(e),Cn(r),t.now,()=>`complete-${t.envelopeId}`)}async function jn(e,t,n=Date.now()){if(e.name!==wn)return!1;let r=await ut({storage:Tn(t),email:t.email,now:n});return r.gaveUp>0&&t.log.error(`emails given up after repeated failures`,{count:r.gaveUp}),!0}async function Mn(e){return dt({storage:Tn(e),email:e.email,now:Date.now()})}const Nn=`0`.repeat(64);function Pn(e=b){return S(e(32))}function Fn(e,t){return P(e+t)}function In(e,t){return`${e}:a${String(t).padStart(6,`0`)}`}const Ln=e=>Object.keys(e).sort().map(t=>[t,e[t]]);function Rn(e){let t=JSON.stringify([1,e.envelopeId,e.seq,e.type,e.at,e.actor,Ln(e.data),Ln(e.commitments)]);return P(e.prevHash+t)}async function zn(e,t,n,r){let i=Object.entries(n.personal??{}).filter(e=>typeof e[1]==`string`),a={};for(let[e,t]of i)a[e]=await Fn(r,t);let o={envelopeId:e,seq:t?t.seq+1:0,type:n.type,at:n.at,actor:n.actor,data:{...n.data},commitments:a,prevHash:t?t.hash:Nn};return{...o,personal:i.length>0?Object.fromEntries(i):null,hash:await Rn(o)}}function Bn(e,t,n){return Vn(e,null,t,n)}async function Vn(e,t,n,r){let i=[],a=t;for(let t of n){let n=await zn(e,a,t,r);i.push({id:In(e,n.seq),data:n}),a=n}return i}async function Hn(e,t,n,r){let i=r.attempts??2;for(let a=0;a<i;a++){let{items:i}=await e.query({where:{envelopeId:t},orderBy:{seq:`desc`},limit:1}),a=await zn(t,i[0]?.data??null,n,r.salt);if((await e.compareAndSet(In(t,a.seq),null,a)).applied)return w(a)}return T(`CONFLICT`)}async function Un(e,t){let{items:n}=await e.query({where:{envelopeId:t},orderBy:{seq:`desc`},limit:1});return n[0]?.data??null}async function Wn(e,t){let[n,...r]=t;return n?(await e.compareAndSet(n.id,null,n.data)).applied?(r.length>0&&await e.putMany(r),!0):!1:!0}async function Gn(e,t){for(let[n,r]of Object.entries(e.personal??{}))if(e.commitments[n]!==await Fn(t,r))return!1;return!0}async function Kn(e,t,n={}){let r=Nn;for(let[i,a]of t.entries()){let t=e=>T({seq:i,reason:e});if(a.envelopeId!==e)return t(`ENVELOPE`);if(a.seq!==i)return t(`SEQ`);if(await Rn(a)!==a.hash)return t(`HASH`);if(a.prevHash!==r)return t(`PREV_HASH`);if(n.salt!==void 0&&!await Gn(a,n.salt))return t(`COMMITMENT`);r=a.hash}return n.head!==void 0&&n.head!==r?T({seq:t.length,reason:`HEAD`}):w({head:r,length:t.length})}function qn(e){return{...e,personal:null}}function Jn(e,t){return P(`esign-final/1\n${e}\n${t}`)}const Yn=[`draft`,`sent`,`in_progress`,`completed`,`declined`,`voided`,`expired`],Xn=[`declined`,`voided`,`expired`],Zn=Object.freeze({draft:[`sent`,`voided`],sent:[`in_progress`,`completed`,...Xn],in_progress:[`completed`,...Xn],completed:[],declined:[],voided:[],expired:[]});function Qn(e){return typeof e==`string`&&Yn.includes(e)}function $n(e,t){return Qn(e)&&Qn(t)&&Zn[e].includes(t)}function er(e){return Zn[e].length===0}async function F(e,t,n,r,i={}){if(!$n(n,r))return T(`ILLEGAL_TRANSITION`);let a=await e.updateIf(t,{where:{status:n},set:{...i,status:r}});return a.applied?w(a.data):T(`CONFLICT`)}const I=(e,t)=>`${e}:v${t}`;function tr(e){if(typeof e!=`object`||!e||Array.isArray(e))return T([{path:``,code:`INVALID_INPUT`}]);let{name:t,body:n,description:r,integrations:i}=e,a=[],o=typeof t==`string`?t.trim():``;return(o.length===0||o.length>200)&&a.push({path:`name`,code:`INVALID_NAME`}),(typeof n!=`string`||n.trim().length===0||n.length>1e5)&&a.push({path:`body`,code:`INVALID_BODY`}),r!==void 0&&(typeof r!=`string`||r.length>1e3)&&a.push({path:`description`,code:`INVALID_DESCRIPTION`}),i!==void 0&&typeof i!=`boolean`&&a.push({path:`integrations`,code:`INVALID_INTEGRATIONS`}),a.length>0?T(a):w({name:o,body:n,...typeof r==`string`&&r!==``?{description:r}:{},...typeof i==`boolean`?{integrations:i}:{}})}function nr(e,t){return{...e,status:`version`,templateId:t}}function rr(e,t){let n=tr(e);if(!n.ok)return n;let r={name:n.value.name,...n.value.description===void 0?{}:{description:n.value.description},kind:`text`,status:`active`,public:!1,integrations:n.value.integrations??!1,version:1,body:n.value.body,fields:dn(n.value.body),createdAt:t.now,updatedAt:t.now};return w({head:r,versions:[{id:I(t.id,1),data:nr(r,t.id)}]})}function ir(e,t,n){if(e.status===`archived`)return T([{path:``,code:`TEMPLATE_ARCHIVED`}]);let r=tr(t);if(!r.ok)return r;let{description:i,...a}=e,o={...a,...r.value.description===void 0?{}:{description:r.value.description},name:r.value.name,body:r.value.body,fields:dn(r.value.body),integrations:r.value.integrations??e.integrations===!0,version:e.version+1,updatedAt:n.now};return w({head:o,version:{id:I(n.id,o.version),data:nr(o,n.id)}})}function ar(e,t){return e.status===`archived`?e:{...e,status:`archived`,updatedAt:t}}function or(e){return e?.status===`active`&&e.integrations===!0}function sr(e){return e.status===`active`?w(e):T(`TEMPLATE_NOT_FOUND`)}const cr=/[\u0000-\u001F\u007F]/,lr=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,ur=/^[A-Za-z0-9_]{1,64}$/,dr=(e,t)=>`${e}:s${t}`,fr=e=>typeof e==`object`&&!!e&&!Array.isArray(e),pr=e=>typeof e==`string`&&e.length>0&&e.length<=200&&!e.includes(`:`);function mr(e){let t=typeof e==`string`?e.trim():``;return t.length>0&&t.length<=200&&!cr.test(t)?t:null}function hr(e){let t=typeof e==`string`?e.trim().toLowerCase():``;return t.length<=254&&lr.test(t)?t:null}function gr(e){if(e===void 0)return{};if(!fr(e))return null;let t=Object.entries(e);if(t.length>32)return null;let n={};for(let[e,r]of t){if(!ur.test(e)||typeof r!=`string`||[...r].length>500)return null;n[e]=r}return n}function _r(e){if(e===void 0)return[];if(!Array.isArray(e)||e.length>16)return null;let t=[];for(let n of e){if(!fr(n)||typeof n.key!=`string`||!ur.test(n.key)||t.some(e=>e.key===n.key))return null;let e=typeof n.label==`string`?n.label.trim():``;if(e===``||[...e].length>100||cr.test(e)||n.required!==void 0&&typeof n.required!=`boolean`)return null;t.push({key:n.key,label:e,...n.required?{required:!0}:{}})}return t}function vr(e){if(!fr(e))return T([{path:``,code:`INVALID_INPUT`}]);let{templateId:t,templateVersion:n,title:r,signer:i,fields:a}=e,o=[];pr(t)||o.push({path:`templateId`,code:`INVALID_TEMPLATE_ID`}),n!==void 0&&!(Number.isSafeInteger(n)&&n>=1)&&o.push({path:`templateVersion`,code:`INVALID_VERSION`});let s=typeof r==`string`?r.trim():void 0;r!==void 0&&!(s&&s.length<=200&&!cr.test(s))&&o.push({path:`title`,code:`INVALID_TITLE`});let c=fr(i)?i:{},l=mr(c.name),u=hr(c.email);l===null&&o.push({path:`signer.name`,code:`INVALID_SIGNER_NAME`}),u===null&&o.push({path:`signer.email`,code:`INVALID_SIGNER_EMAIL`});let d=gr(a);d===null&&o.push({path:`fields`,code:`INVALID_FIELDS`});let f=_r(e.signerFields);return f===null&&o.push({path:`signerFields`,code:`INVALID_FIELDS`}),o.length>0?T(o):w({templateId:t,...n===void 0?{}:{templateVersion:n},...s===void 0?{}:{title:s},signer:{name:l,email:u,as:`self`},fieldValues:d,...f&&f.length>0?{signerFields:f}:{}})}function yr(e,t,n){let r=e?sr(e):T(`TEMPLATE_NOT_FOUND`);return!r.ok||n===void 0?r:t?.status===`version`&&t.version===n?w(t):T(`TEMPLATE_NOT_FOUND`)}function br(e){let{signer:t}=e;return{...e.fieldValues,"signer.name":t.name,"signer.email":t.email,...t.participant?{"participant.name":t.participant.name}:{}}}function xr(e,t){let n=br(e);return dn(t).filter(e=>!Object.hasOwn(n,e)).map(e=>({path:`fields.${e}`,code:`MISSING_FIELD`}))}function Sr(e,t,n){let{title:r,...i}=e,a={title:r??t.name,templateVersion:t.version,status:`draft`,routing:`parallel`,...i,signerEmail:i.signer.email.toLowerCase(),signerIds:[],docSha256:null,snapshot:null,expiresAt:null,sentAt:null,completedAt:null,finalHash:null,piiSalt:n.piiSalt,createdAt:n.now,updatedAt:n.now},o=xr(a,t.body);return o.length>0?T(o):w(a)}function Cr(e,t,n){return Sr({templateId:e.templateId,signer:e.signer,fieldValues:e.fieldValues,delivery:`email`,...e.title===void 0?{}:{title:e.title},...e.signerFields?{signerFields:e.signerFields}:{}},t,n)}function wr(e,t,n){let r={name:e.signer.name.trim(),email:e.signer.email.trim().toLowerCase(),as:e.as??`self`,...e.participant?{participant:{name:e.participant.name.trim()}}:{}};return Sr({templateId:e.tpl,signer:r,fieldValues:{...e.prefill},delivery:e.delivery??`inline`,clientId:e.cid,externalRef:e.ref,returnUrl:e.returnUrl},t,n)}function Tr(e){let t=0;for(let n=e.indexOf(`
|
|
28
28
|
`);n!==-1;n=e.indexOf(`
|
|
29
|
-
`,n+1))t++;return t}async function
|
|
30
|
-
`,"`",`*`,`_`,`[`,`!`,`<`]),
|
|
31
|
-
`){o(),i.push({type:`break`}),s++;continue}let l=n<6?this.markup(s,t,n):void 0;l?.inline?(o(),i.push(l.inline)):a+=l?l.text:e,s=l?l.end:s+1}return o(),i}markup(e,t,n){let r=this.src[e];if(r==="`")return this.codeSpan(e,t);if(r===`*`||r===`_`)return this.emphasis(e,t,n);if(r===`[`)return this.link(e,t,n,!1);if(r===`!`&&this.src[e+1]===`[`)return this.link(e+1,t,n,!0);if(r===`<`)return this.autolink(e,t)}next(e,t,n,r){let i=this.memo.get(e);if(i&&t>=i.from&&(i.at===-1||t<=i.at))return i.at;let a=n(t);for(;a!==-1&&!r(a);)a=n(a+1);return this.memo.set(e,{from:t,at:a}),a}escaped(e){let t=0;for(let n=e-1;n>=0&&this.src[n]===`\\`;n--)t++;return t%2==1}codeSpan(e,t){let{src:n}=this,r=1;for(;n[e+r]==="`";)r++;let i="`".repeat(r),a=this.next(`code${r}`,e+r,e=>n.indexOf(i,e),e=>n[e-1]!=="`"&&n[e+r]!=="`");return a===-1||a+r>t?{text:i,end:e+r}:{inline:{type:`code`,text:
|
|
32
|
-
`))});continue}if(
|
|
33
|
-
`)))});continue}let l=[i.trim()];for(r++;r<e.length&&!
|
|
34
|
-
`))})}return n}function
|
|
29
|
+
`,n+1))t++;return t}async function Er(e,t){let n;try{n=fn(t,br(e))}catch(e){if(e instanceof sn)return T([{path:`fields.${e.field}`,code:`MISSING_FIELD`}]);throw e}let r=pn(n);return r.length>131072||Tr(r)>1500?T([{path:`body`,code:`DOCUMENT_TOO_LARGE`}]):w({text:r,docSha256:await P(r)})}const Dr=e=>e>=55296&&e<=56319;function Or(e,t,n){let r=[];for(let e=0;e<t.length;){let n=Math.min(e+65536,t.length);n<t.length&&Dr(t.charCodeAt(n-1))&&n--,r.push(t.slice(e,n)),e=n}let i=`${e}:${n.slice(0,16)}`;return r.map((t,a)=>({id:`${i}:${a}`,data:{envelopeId:e,contentType:`text/markdown`,index:a,count:r.length,data:t,sha256:n}}))}function kr(e){let t=e[0];if(!t||e.length!==t.count)return null;let n=[...e].sort((e,t)=>e.index-t.index);return n.every((e,n)=>e.index===n&&e.count===t.count&&e.sha256===t.sha256)?n.map(e=>e.data).join(``):null}async function Ar(e,t,n,r){if(!$n(t.status,`sent`))return T(`ILLEGAL_TRANSITION`);if(n.version!==t.templateVersion)return T(`TEMPLATE_MISMATCH`);let i=await Er(t,n.body);if(!i.ok)return i;let{text:a,docSha256:o}=i.value,s=Or(e,a,o),c=dr(e,1),{signer:l}=t;return w({envelope:{...t,status:`sent`,docSha256:o,snapshot:{ids:s.map(e=>e.id),length:a.length},signerIds:[c],sentAt:r.now,expiresAt:A(Date.parse(r.now)+r.expiryDays*864e5),updatedAt:r.now},chunks:s,signer:{id:c,data:{envelopeId:e,order:1,role:`signer`,name:l.name,email:l.email,as:l.as,...l.participant?{participant:l.participant}:{},status:`pending`,tokenHash:r.tokenHash,createdAt:r.now}}})}const jr=[`declined`,`voided`,`expired`];function Mr(e){return e.find(e=>!jr.includes(e.data.status))}async function Nr(e,t,n){return`env_${(await P(`${e}\n${t}`)).slice(0,32)}_${n}`}function Pr(e,t,n){let{signer:r,clientId:i,externalRef:a}=e;return{type:`envelope.created`,at:e.createdAt,actor:t,data:{source:t===`admin`?`admin`:`intent`,templateId:e.templateId,templateVersion:e.templateVersion,title:e.title,delivery:e.delivery,as:r.as,...i===void 0?{}:{clientId:i},...a===void 0?{}:{externalRef:a},...n?{userId:n}:{}},personal:{name:r.name,email:r.email,...r.participant?{participant:r.participant.name}:{}}}}function Fr(e,t,n){return{type:`envelope.sent`,at:e.updatedAt,actor:t,data:{docSha256:e.docSha256,expiresAt:e.expiresAt,signerIds:e.signerIds.join(`,`),...n?{userId:n}:{}},personal:{email:e.signer.email}}}function Ir(e={}){let t=[];return new Headers(e.headers).forEach((e,n)=>t.push([n,e])),{__emdashPluginResponse:!0,status:e.status??200,headers:t,body:e.body??null}}const Lr={amp:`&`,lt:`<`,gt:`>`,quot:`"`,"#39":`'`},Rr=/^&(amp|lt|gt|quot|#39);/,zr=/[!-/:-@[-`{-~]/,Br=/[\p{L}\p{N}]/u,Vr=/[\s"'<>`\\\u0000-\u001F\u007F]/,Hr=/^(https?:\/\/|mailto:)/i,Ur=new Set([`\\`,`&`,`
|
|
30
|
+
`,"`",`*`,`_`,`[`,`!`,`<`]),Wr=/[\\&\n`*_[!<]/g;function Gr(e){if(!(e.length===0||Vr.test(e)||!Hr.test(e)))try{return new URL(e).href}catch{return}}function Kr(e){return e.replace(/\\([!-/:-@[-`{-~])|&(amp|lt|gt|quot|#39);/g,(e,t,n)=>t===void 0?Lr[n]:t)}function qr(e){let t=new Map,n={"]":[],")":[]},r={"[":`]`,"(":`)`},i=/[\\[\]()]/g;for(let a=i.exec(e);a;a=i.exec(e)){let e=a.index,o=a[0];if(o===`\\`)i.lastIndex=e+2;else if(o in r)n[r[o]]?.push(e);else{let r=n[o]?.pop();r!==void 0&&t.set(r,e)}}return t}var Jr=class{partner;memo=new Map;constructor(e){this.src=e,this.partner=qr(e)}parse(e,t,n){let{src:r}=this,i=[],a=``,o=()=>{a&&i.push({type:`text`,text:a}),a=``},s=e;for(;s<t;){let e=r[s];if(!Ur.has(e)){Wr.lastIndex=s;let e=Wr.exec(r),n=e&&e.index<t?e.index:t;a+=r.slice(s,n),s=n;continue}if(e===`\\`&&s+1<t&&zr.test(r[s+1])){a+=r[s+1],s+=2;continue}let c=e===`&`?Rr.exec(r.slice(s,Math.min(t,s+6))):null;if(c){a+=Lr[c[1]],s+=c[0].length;continue}if(e===`
|
|
31
|
+
`){o(),i.push({type:`break`}),s++;continue}let l=n<6?this.markup(s,t,n):void 0;l?.inline?(o(),i.push(l.inline)):a+=l?l.text:e,s=l?l.end:s+1}return o(),i}markup(e,t,n){let r=this.src[e];if(r==="`")return this.codeSpan(e,t);if(r===`*`||r===`_`)return this.emphasis(e,t,n);if(r===`[`)return this.link(e,t,n,!1);if(r===`!`&&this.src[e+1]===`[`)return this.link(e+1,t,n,!0);if(r===`<`)return this.autolink(e,t)}next(e,t,n,r){let i=this.memo.get(e);if(i&&t>=i.from&&(i.at===-1||t<=i.at))return i.at;let a=n(t);for(;a!==-1&&!r(a);)a=n(a+1);return this.memo.set(e,{from:t,at:a}),a}escaped(e){let t=0;for(let n=e-1;n>=0&&this.src[n]===`\\`;n--)t++;return t%2==1}codeSpan(e,t){let{src:n}=this,r=1;for(;n[e+r]==="`";)r++;let i="`".repeat(r),a=this.next(`code${r}`,e+r,e=>n.indexOf(i,e),e=>n[e-1]!=="`"&&n[e+r]!=="`");return a===-1||a+r>t?{text:i,end:e+r}:{inline:{type:`code`,text:Kr(n.slice(e+r,a))},end:a+r}}emphasis(e,t,n){let{src:r}=this,i=r[e],a=r[e+1]===i?i+i:i,o=e+a.length,s=e=>e>=0&&e<r.length&&Br.test(r[e]),c=e=>i===`_`&&s(e),l={text:a,end:o};if(c(e-1)||o>=t||/\s/.test(r[o]))return l;let u=this.next(a,o+1,e=>r.indexOf(a,e),e=>!this.escaped(e)&&!/\s/.test(r[e-1])&&!c(e+a.length));if(u===-1||u+a.length>t)return l;let d=this.parse(o,u,n+1);return{inline:{type:a.length===2?`strong`:`em`,children:d},end:u+a.length}}link(e,t,n,r){let{src:i}=this,a={text:r?`![`:`[`,end:e+1},o=this.partner.get(e);if(o===void 0||o>=t||i[o+1]!==`(`)return a;let s=this.partner.get(o+1);if(s===void 0||s>=t)return a;let c=s+1;if(r)return{text:Kr(i.slice(e+1,o)),end:c};let l=Gr(Kr(i.slice(o+2,s)));return l?{inline:{type:`link`,href:l,children:this.parse(e+1,o,n+1)},end:c}:{text:Kr(i.slice(e,c)),end:c}}autolink(e,t){let n=/^<([A-Za-z][A-Za-z0-9+.-]*:[^\s<>]*)>/.exec(this.src.slice(e,Math.min(t,e+2048))),r=n?Gr(n[1]):void 0;if(!(!n||!r))return{inline:{type:`link`,href:r,children:[{type:`text`,text:n[1]}]},end:e+n[0].length}}};function Yr(e){return new Jr(e).parse(0,e.length,0)}const Xr=/^ {0,3}(`{3,}|~{3,})/,Zr=/^ {0,3}(#{1,6})(?:[ \t]+(.*?))?(?:[ \t]+#+)?[ \t]*$/,Qr=/^ {0,3}([-*_])(?:[ \t]*\1){2,}[ \t]*$/,$r=/^ {0,3}> ?(.*)$/,ei=/^ {0,3}[-*+][ \t]+(.*)$/,ti=/^ {0,3}(\d{1,9})[.)][ \t]+(.*)$/,ni=e=>e.trim()===``,ri=e=>Xr.test(e)||Zr.test(e)||Qr.test(e)||$r.test(e)||ei.test(e)||ti.test(e);function ii(e,t){let n=[],r=0;for(;r<e.length;){let i=e[r];if(ni(i)){r++;continue}let a=Xr.exec(i);if(a){let t=a[1],i=RegExp(`^ {0,3}${t[0]}{${t.length},}[ \\t]*$`),o=[];for(r++;r<e.length&&!i.test(e[r]);)o.push(e[r]),r++;r++,n.push({type:`code`,text:Kr(o.join(`
|
|
32
|
+
`))});continue}if(Qr.test(i)){n.push({type:`rule`}),r++;continue}let o=Zr.exec(i);if(o){let e=Math.min(6,o[1].length+1);n.push({type:`heading`,level:e,children:Yr(o[2]??``)}),r++;continue}if($r.test(i)&&t<4){let i=[];for(;r<e.length&&$r.test(e[r]);)i.push($r.exec(e[r])[1]),r++;n.push({type:`quote`,children:ii(i,t+1)});continue}let s=ei.test(i),c=ti.exec(i);if(s||c){let t=s?ei:ti,i=[];for(;r<e.length;){let n=e[r],a=t.exec(n);if(a)i.push([s?a[1]:a[2]]);else if(!ni(n)&&/^ {2,}\S/.test(n)&&!ri(n.trimStart()))i.at(-1).push(n.trim());else break;r++}n.push({type:`list`,ordered:!s,...c&&c[1]!==`1`?{start:Number(c[1])}:{},items:i.map(e=>Yr(e.join(`
|
|
33
|
+
`)))});continue}let l=[i.trim()];for(r++;r<e.length&&!ni(e[r])&&!ri(e[r]);)l.push(e[r].trim()),r++;n.push({type:`paragraph`,children:Yr(l.join(`
|
|
34
|
+
`))})}return n}function ai(e){return ii(e.replace(/\r\n?/g,`
|
|
35
35
|
`).split(`
|
|
36
|
-
`),0)}const
|
|
37
|
-
`;case`link`:{let t=ci(e.children);return t===e.href?t:`${t} (${e.href})`}default:return ci(e.children)}}).join(``)}function li(e){let t=[],n=(e,r)=>{for(let i of e)switch(i.type){case`heading`:t.push({type:`heading`,text:ci(i.children),level:Math.min(i.level,3)});break;case`paragraph`:t.push({type:`paragraph`,text:ci(i.children),...r?{font:`italic`}:{}});break;case`list`:i.items.forEach((e,n)=>{let a=i.ordered?`${(i.start??1)+n}.`:`•`;t.push({type:`paragraph`,text:`${a} ${ci(e)}`,...r?{font:`italic`}:{}})});break;case`quote`:n(i.children,!0);break;case`code`:t.push({type:`paragraph`,text:i.text,size:9});break;case`rule`:t.push({type:`rule`});break}};return n(ii(e),!1),t}function ui(e){let t=e.signature,n=[e.name,`Signed ${si(e.signedAt)}`];return t?.kind===`drawn`&&t.strokes?{type:`signature`,label:`Signature`,strokes:{v:1,w:1,h:1,strokes:t.strokes},caption:t.typedName?[t.typedName,...n]:n}:{type:`signature`,label:`Signature`,typedName:t?.typedName??e.name,caption:n}}function di(e,t,n){let r=e.envelope.signerFields??[];if(r.length===0)return[];let i=t.fieldValues??{};return[{type:`spacer`,height:12},{type:`heading`,text:`Details entered by ${n?t.name:`the signer`}`,level:2},{type:`table`,columns:[{header:`Field`},{header:`Value`,width:2}],rows:r.map(e=>[e.label,i[e.key]??``])}]}function fi(e){let{envelope:t,signers:n,events:r,head:i,envelopeId:a}=e,o=n.length>1,s=[[`Envelope`,a],[`Document`,t.title],[`Document SHA-256`,t.docSha256??``],...n.flatMap((e,t)=>[[o?`Signer ${t+1}`:`Signer`,e.name],[`Signing as`,oi[e.as]??e.as],...e.participant?[[`Participant`,e.participant.name]]:[],[`Signature`,e.signature?.kind===`drawn`?`Drawn`:`Typed`],[`Signature SHA-256`,e.signature?.sha256??``],[`Consent version`,e.consentVersion??``],...e.consentSha256?[[`Consent wording SHA-256`,e.consentSha256]]:[],...e.otpVerifiedAt?[[`Identity check`,`Email one-time code verified`]]:[],[`Signed`,si(e.signedAt)]]),[`Completed`,si(t.completedAt)],[`Audit events`,String(r.length)]],c=r.map(e=>[String(e.seq+1),si(e.at),e.type,typeof e.data.signer==`number`?`signer ${e.data.signer}`:e.actor,e.personal?.ip??``,e.hash.slice(0,16)]);return{info:{title:t.title,subject:`Signed document and certificate of completion`,creator:`semics e-sign`,...t.completedAt?{creationDate:new Date(t.completedAt)}:{}},footer:{text:`Envelope ${a}`,pageNumbers:!0},blocks:[{type:`heading`,text:t.title,level:1},...li(e.snapshot),...n.flatMap(t=>[...di(e,t,o),{type:`spacer`,height:18},ui(t)]),{type:`pageBreak`},{type:`heading`,text:`Certificate of completion`,level:1},{type:`paragraph`,text:`This certificate records how the document above was signed. It was signed with a simple electronic signature: the signer consented to sign electronically, confirmed their intent to sign, and signed the exact text identified by the document SHA-256 below. Every step is recorded in a hash-chained audit trail; the final hash binds the document to the end of that trail. Anyone holding this PDF can check these values on the verify page.`},{type:`spacer`,height:8},{type:`table`,columns:[{header:`Field`},{header:`Value`,width:3}],rows:s},{type:`spacer`,height:8},{type:`heading`,text:`Audit trail`,level:2},{type:`table`,columns:[{header:`#`,width:.4},{header:`Time`,width:1.6},{header:`Event`,width:1.6},{header:`Actor`,width:.8},{header:`IP address`,width:1.2},{header:`Event hash (first 16)`,width:1.6}],rows:c,size:8},{type:`spacer`,height:8},{type:`paragraph`,text:`Audit chain head`,font:`bold`,size:9},{type:`paragraph`,text:i,size:9},{type:`paragraph`,text:`Final hash`,font:`bold`,size:9},{type:`paragraph`,text:t.finalHash??``,size:9}]}}async function pi(e){let t=qt(fi(e));return{bytes:t,sha256:await F(t)}}const R=new TextEncoder().encode(`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`);function mi(e){let t=new Uint8Array(Math.ceil(e.length/3)*4),n=e.length-e.length%3,r=0;for(let i=0;i<n;i+=3){let n=e[i]<<16|e[i+1]<<8|e[i+2];t[r++]=R[n>>18],t[r++]=R[n>>12&63],t[r++]=R[n>>6&63],t[r++]=R[n&63]}if(n<e.length){let i=n+1<e.length,a=e[n]<<16|(i?e[n+1]<<8:0);t[r++]=R[a>>18],t[r++]=R[a>>12&63],t[r++]=i?R[a>>6&63]:61,t[r++]=61}return new TextDecoder().decode(t)}function hi(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}catch{return null}}const gi=(e,t,n)=>`${e}:pdf:${t.slice(0,16)}:${n}`;function _i(e,t,n){let r=Math.max(1,Math.ceil(t.length/ai));return Array.from({length:r},(i,a)=>({id:gi(e,n,a),data:{envelopeId:e,kind:`signed-pdf`,contentType:`application/pdf`,index:a,count:r,bytes:t.length,sha256:n,data:mi(t.subarray(a*ai,(a+1)*ai))}}))}function vi(e){let t=e[0];if(!t||e.length!==t.count)return null;let n=[...e].sort((e,t)=>e.index-t.index),r=new Uint8Array(t.bytes),i=0;for(let[e,a]of n.entries()){if(a.index!==e||a.sha256!==t.sha256||a.bytes!==t.bytes)return null;let n=hi(a.data);if(!n||i+n.length>r.length)return null;r.set(n,i),i+=n.length}return i===r.length?r:null}const yi=`signed-pdf-`,bi=e=>`${yi}${e}`;function xi(e,t,n,r=0){return e?.schedule(bi(t),{schedule:A(n),data:{envelopeId:t,attempt:r}})}async function Si(e,t,n){let{envelopes:r,signers:i,snapshots:a,audit_events:o,artifacts:s}=B(e),c=await r.get(t);if(!c||c.status!==`completed`||c.pdfSha256||c.personalPurgedAt||c.signerIds.length===0||!c.snapshot||!c.docSha256)return`skipped`;let[l,u,d]=await Promise.all([i.getMany(c.signerIds),a.getMany(c.snapshot.ids),o.query({where:{envelopeId:t},orderBy:{seq:`asc`},limit:100})]),f=Or([...u.values()]),p=d.items.map(e=>e.data),m=await Gn(t,p),h=m.ok&&p.at(-1)?.type===`envelope.completed`&&await qn(c.docSha256,m.value.head)===c.finalHash,g=c.signerIds.map(e=>l.get(e));if(g.some(e=>e?.status!==`signed`)||f===null||!m.ok||!h){let r=n.attempt??0;return r+1>=5?(e.log.error(`signed PDF not generated: the envelope never settled`,{envelopeId:t}),`gave-up`):(await xi(e.cron,t,n.now+6e4,r+1),`retry`)}let{bytes:_,sha256:v}=await pi({envelopeId:t,envelope:c,signers:g,snapshot:f,events:p,head:m.value.head}),y=_i(t,_,v);return await s.putMany(y),(await r.updateIf(t,{where:{status:`completed`,pdfSha256:null},set:{pdfSha256:v,pdf:{ids:y.map(e=>e.id),bytes:_.length},updatedAt:A(n.now)}})).applied?(await Qi(e.cron,t,n.now),`stored`):`skipped`}async function Ci(e,t){if(!e.name.startsWith(yi))return!1;let n=e.data?.envelopeId,r=e.data?.attempt;return typeof n!=`string`||n.length===0||await Si(t,n,{now:Date.now(),attempt:typeof r==`number`&&Number.isSafeInteger(r)?r:0}),!0}const wi=`esign/download`,Ti=`esign:download-link-key`,Ei=/^[A-Za-z0-9_:.-]{1,200}$/,Di=RegExp(`^[0-9a-f]{64}$`);function Oi(e){return typeof e!=`string`||!Di.test(e)?null:Uint8Array.from(e.match(/../g),e=>Number.parseInt(e,16))}async function ki(e){let t=Oi(await e.get(Ti));if(t)return t;let n=crypto.getRandomValues(new Uint8Array(32));if((await e.compareAndSet(Ti,null,S(n))).applied)return n;let r=Oi(await e.get(Ti));if(!r)throw Error(`download link key unavailable`);return r}async function Ai(e,t,n){let r=await me({secret:await ki(e.kv),purpose:wi,params:{e:t},now:n,ttlMs:9e5}),i=A(Number(r.get(`exp`))*1e3);return{url:`/_emdash/api/plugins/${e.plugin.id}/public/download?${r}`,expiresAt:i}}function z(e){let{status:t,body:n}=D(e);return Fr({status:t,headers:{"content-type":`application/json; charset=utf-8`,"cache-control":`no-store`},body:{kind:`text`,value:JSON.stringify(n)}})}function ji(e){try{return e?.url?new URL(e.url).searchParams:null}catch{return null}}async function Mi(e,t){let n=ji(e.request);if(!n)return z(`TOKEN_INVALID`);if(n.has(`token`))return z(`TOKEN_IN_QUERY`);let r=Date.now(),i=await he({secret:await ki(t.kv),purpose:wi,query:n,now:r});if(!i.ok)return z(i.error);let a=i.value.e;if(typeof a!=`string`||!Ei.test(a))return z(`TOKEN_INVALID`);let{envelopes:o,artifacts:s}=B(t),c=await o.get(a);if(!c||c.status!==`completed`||c.recordsPurgedAt)return z(`ENVELOPE_NOT_FOUND`);if(!c.pdfSha256||!c.pdf)return await xi(t.cron,a,r),z(`SIGNED_PDF_PENDING`);let l=vi([...(await s.getMany(c.pdf.ids)).values()]);return!l||await F(l)!==c.pdfSha256?(t.log.error(`signed PDF chunks do not match pdfSha256`,{envelopeId:a}),z(`INTERNAL`)):Fr({status:200,headers:{"content-type":`application/pdf`,"content-disposition":`attachment; filename="signed-${a.replace(/[^A-Za-z0-9_-]/g,`_`)}.pdf"`,"cache-control":`private, no-store`,"x-content-type-options":`nosniff`,"referrer-policy":`no-referrer`},body:{kind:`bytes`,value:l}})}const Ni=(e,t)=>Mi(e,t),Pi=e=>typeof e.user?.id==`string`&&e.user.id.length>0?e.user.id:void 0,B=e=>e.storage,V=e=>typeof e==`object`&&e?e:{},H=e=>({...D(`BAD_REQUEST`).body,...e?{issues:e}:{}}),U=e=>D(e).body;function Fi(e){let t=V(e).id;return typeof t==`string`&&t.length>0&&t.length<=200?t:null}function Ii(e){return Number.isSafeInteger(e)&&e>=1&&e<=365?e:30}function Li(e){return e instanceof Error&&e.message.includes(`UNIQUE constraint failed`)}async function Ri(e,t,n){let r=e;for(let e=1;;e++)try{return{token:r,value:await n(await O(r))}}catch(n){if(!Li(n)||e>=3)throw n;r=ce(t)}}async function zi(e,t,n,r){let{token:i}=await Ri(n,r,n=>e.put(t.id,{...t.data,tokenHash:n}));return i}const Bi=(e,{piiSalt:t,...n})=>({id:e,...n}),Vi=(e,{snapshot:t,fieldValues:n,piiSalt:r,...i})=>({id:e,...i});async function Hi(e,t,n,r){if(!(await Vn(B(e).audit_events,t,r,{salt:n.piiSalt})).ok)throw Error(`audit chain contention`)}async function Ui(e,t){let n=_r(e.input);if(!n.ok)return H(n.error);let{templateId:r,templateVersion:i}=n.value,{templates:a,envelopes:o,audit_events:s}=B(t),c=await a.getMany(i===void 0?[r]:[r,L(r,i)]),l=vr(c.get(r),i===void 0?void 0:c.get(L(r,i)),i);if(!l.ok)return U(`TEMPLATE_NOT_FOUND`);let u=Nn(),d=Sr(n.value,l.value,{now:A(),piiSalt:u});if(!d.ok)return H(d.error);let f=crypto.randomUUID();return await o.put(f,d.value),await s.putMany(await zn(f,[Nr(d.value,`admin`,Pi(e))],u)),{ok:!0,envelope:Bi(f,d.value)}}async function Wi(e,t){let n=Fi(e.input);if(!n)return H();let{envelopes:r,templates:i,snapshots:a,signers:o}=B(t),s=await r.get(n);if(!s)return U(`ENVELOPE_NOT_FOUND`);if(!Qn(s.status,`sent`))return U(`ENVELOPE_CLOSED`);let{templateId:c,templateVersion:l}=s,[u,d]=await Promise.all([i.getMany([c,L(c,l)]),t.settings.list()]),f=Object.fromEntries(d.map(e=>[e.key,e.value])),p=vr(u.get(c),u.get(L(c,l)),l);if(!p.ok)return U(`TEMPLATE_NOT_FOUND`);let m=ce(),h=await kr(n,{...s,...await void 0},p.value,{now:A(),tokenHash:await O(m),expiryDays:Ii(f.expiryDays)});if(!h.ok)return Array.isArray(h.error)?H(h.error):U(`ENVELOPE_CLOSED`);await a.putMany(h.value.chunks);let g=await I(r,n,`draft`,`sent`,h.value.envelope);if(!g.ok)return U(`ENVELOPE_CLOSED`);let _=await zi(o,h.value.signer,m),v=await On(t,{signerId:h.value.signer.id,envelope:g.value,token:_,senderSetting:f.senderName,now:Date.now()});return await Hi(t,n,g.value,Pr(g.value,`admin`,Pi(e))),{ok:!0,envelope:Bi(n,g.value),...v?{}:{invitation:`SITE_URL_MISSING`}}}async function Gi(e,t){let n=Fi(e.input);if(!n)return H();let{envelopes:r,snapshots:i,signers:a}=B(t),o=await r.get(n);if(!o)return U(`ENVELOPE_NOT_FOUND`);let[s,c]=await Promise.all([o.snapshot?i.getMany(o.snapshot.ids):Promise.resolve(new Map),o.signerIds.length>0?a.getMany(o.signerIds):Promise.resolve(new Map)]),l=o.pdfSha256?await Ai(t,n,Date.now()):null;return{ok:!0,envelope:Bi(n,o),download:l,snapshot:o.snapshot?Or([...s.values()]):null,signers:[...c].map(([e,t])=>({id:e,order:t.order,name:t.name,email:t.email,status:t.status}))}}async function Ki(e,t){let n=Fi(e.input);if(!n)return H();let{envelopes:r,signers:i,outbox:a,audit_events:o}=B(t),s=await r.get(n);if(!s)return U(`ENVELOPE_NOT_FOUND`);let c=s.signerIds[0];if(s.status!==`sent`||c===void 0)return U(`ENVELOPE_CLOSED`);if(!Tn(t))return{ok:!1,error:{code:`SITE_URL_MISSING`,message:Dn}};let l=Fn(n,0),u=Fn(n,1),[d,f,p]=await Promise.all([t.settings.get(`senderName`),a.get(`invite-${c}`),o.getMany([l,u])]);if(f&&f.status!==`failed`)return{ok:!1,error:{code:`INVITATION_QUEUED`,message:`The invitation is already queued or sent.`}};let m=await Ri(ce(),void 0,e=>i.updateIf(c,{where:{status:`pending`},set:{tokenHash:e}}));if(!m.value.applied)return U(`ENVELOPE_CLOSED`);await On(t,{signerId:c,envelope:s,token:m.token,senderSetting:d,now:Date.now()});let h=!1;p.has(u)||(h=await Un(o,await Bn(n,p.get(l)??null,[Pr(s,`admin`,Pi(e))],s.piiSalt)));let{name:g,email:_,status:v}=m.value.data;return{ok:!0,envelope:Bi(n,s),signers:[{id:c,order:m.value.data.order,name:g,email:_,status:v}],repaired:h}}async function qi(e,t){let n=Fi(e.input);if(!n)return H();let r=await B(t).envelopes.get(n);if(!r)return U(`ENVELOPE_NOT_FOUND`);let i=A(),a=await I(B(t).envelopes,n,r.status,`voided`,{closedAt:i,updatedAt:i});return a.ok?(await Hi(t,n,a.value,{type:`envelope.voided`,at:i,actor:`admin`,...Pi(e)?{data:{userId:Pi(e)}}:{}}),{ok:!0,envelope:Bi(n,a.value)}):U(`ENVELOPE_CLOSED`)}async function Ji(e,t){let{status:n,cursor:r}=V(e.input);if(n!==void 0&&!Zn(n)||r!==void 0&&!(typeof r==`string`&&r.length>0&&r.length<=500))return H();let i=await B(t).envelopes.query({...n===void 0?{}:{where:{status:n}},orderBy:{createdAt:`desc`},limit:100,...r===void 0?{}:{cursor:r}});return{ok:!0,envelopes:i.items.map(e=>Vi(e.id,e.data)),...i.hasMore&&i.cursor?{nextCursor:i.cursor}:{}}}const Yi={"envelopes/create":{handler:Ui},"envelopes/send":{handler:Wi},"envelopes/get":{handler:Gi},"envelopes/list":{handler:Ji},"envelopes/resend":{handler:Ki},"envelopes/void":{handler:qi},"outbox/status":{handler:(async(e,t)=>({ok:!0,...await jn(t)}))}},Xi=`completion-email-`,Zi=e=>`${Xi}${e}`;function Qi(e,t,n){return e?.schedule(Zi(t),{schedule:A(n),data:{envelopeId:t}})}async function $i(e,t,n){let[r,i,a]=await Promise.all([B(e).envelopes.get(t),e.settings.get(`senderName`),B(e).outbox.get(`complete-${t}`)]);if(!r||r.status!==`completed`||!r.pdfSha256||a)return!1;let o=r.signerIds[0];if(o===void 0||!Tn(e))return!1;let s=await Ri(ce(),void 0,t=>B(e).signers.updateIf(o,{where:{status:`signed`},set:{copyTokenHash:t}}));return s.value.applied?(await kn(e,{envelopeId:t,envelope:r,token:s.token,senderSetting:i,now:n}),!0):!1}async function ea(e,t){if(!e.name.startsWith(Xi))return!1;let n=e.data?.envelopeId;return typeof n==`string`&&n.length>0&&await $i(t,n,Date.now()),!0}const ta=`expire`,na=`expire-more`;async function ra(e,t){if(e.name!==ta&&e.name!==na)return!1;let{envelopes:n}=B(t),r=A(),i=await n.query({where:{status:{in:[`sent`,`in_progress`]},expiresAt:{lt:r}},orderBy:{expiresAt:`asc`},limit:2});for(let{id:e,data:a}of i.items){let i=await I(n,e,a.status,`expired`,{closedAt:r,updatedAt:r});i.ok&&await Hi(t,e,i.value,{type:`envelope.expired`,at:r,actor:`system`})}return i.hasMore&&await t.cron?.schedule(na,{schedule:A(Date.now()+6e4)}),!0}function ia(e){if(typeof e!=`string`)return null;let t=new TextEncoder().encode(e.trim());return t.length>=32?t:null}const aa=`intent-finish-`,oa=e=>`${aa}${e}`;function sa(e,t,n){return e?.schedule(oa(t),{schedule:A(n),data:{envelopeId:t}})}async function ca(e,t){let n=await C(e),r=await crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(`esign-invite/1.${t}`));return x(new Uint8Array(r))}async function la(e,t,n){let{envelopes:r,templates:i,snapshots:a,signers:o,audit_events:s}=B(e),c=await r.get(t);if(!c||c.status!==`draft`||c.delivery!==`email`||!c.clientId)return`skipped`;let l=L(c.templateId,c.templateVersion),[u,d]=await Promise.all([i.getMany([c.templateId,l]),e.settings.list()]),f=Object.fromEntries(d.map(e=>[e.key,e.value])),p=vr(u.get(c.templateId),u.get(l),c.templateVersion);if(!p.ok)return`skipped`;let m=ia(f.integrationMasterKey);if(!m)return`skipped`;let h=await ca(m,t),g=await kr(t,c,p.value,{now:A(n),tokenHash:await O(h),expiryDays:Ii(f.expiryDays)});if(!g.ok)return`skipped`;await a.putMany(g.value.chunks);let _=await zi(o,g.value.signer,h);await On(e,{signerId:g.value.signer.id,envelope:g.value.envelope,token:_,senderSetting:f.senderName,now:n});let v=[Nr(c,`integration`),Pr(g.value.envelope,`integration`)];return await s.putMany(await zn(t,v,c.piiSalt)),(await I(r,t,`draft`,`sent`,g.value.envelope)).ok?`sent`:`skipped`}async function ua(e,t){if(!e.name.startsWith(aa))return!1;let n=e.data?.envelopeId;return typeof n==`string`&&n.length>0&&await la(t,n,Date.now()),!0}const da=`nonce-sweep`,fa=`nonce-sweep-more`;async function pa(e){let{nonces:t,cron:n,now:r,page:i=100,pages:a=3}=e,o=A(r),s=0,c=!1;for(let e=0;e<a;e++){let e=await t.query({where:{expiresAt:{lt:o}},orderBy:{expiresAt:`asc`},limit:i});if(e.items.length===0||(s+=await t.deleteMany(e.items.map(e=>e.id)),c=e.hasMore===!0,!c))break}return c&&await n?.schedule(fa,{schedule:A(r+6e4)}),{deleted:s,more:c}}async function ma(e,t){if(e.name!==da&&e.name!==fa)return!1;let n=t.storage.nonces;return await pa({nonces:n,cron:t.cron,now:Date.now()}),!0}const ha=`retention`,ga=`retention-more`,_a=`cron:retention`,va=e=>e.status===`sent`||e.status===`in_progress`,ya=e=>va(e)?null:Date.parse(e.completedAt??e.closedAt??e.updatedAt),ba=(e,t,n,r)=>{let i=e.find(e=>e.key===t)?.value;return typeof i==`number`&&Number.isFinite(i)?Math.min(r,Math.max(1,Math.round(i))):n};function xa(e,t){let n=new Date(t);n.setUTCMonth(n.getUTCMonth()-ba(e,`retentionPersonalDataMonths`,12,120));let r=new Date(t);return r.setUTCFullYear(r.getUTCFullYear()-ba(e,`retentionSignedRecordsYears`,7,50)),{p:Math.max(n.getTime(),r.getTime()),r:r.getTime()}}function Sa(e,t){let{name:n,email:r,ip:i,ua:a,signature:o,fieldValues:s,declineReason:c,copyTokenHash:l,participant:u,...d}=t;return{...d,name:``,email:``,tokenHash:`purged:${e}`,...o?{signature:{kind:o.kind,sha256:o.sha256}}:{}}}function Ca(e,t){let{piiSalt:n,returnUrl:r,signerEmail:i,...a}=e;return{...a,signer:{name:``,email:``,as:e.signer.as},fieldValues:{},personalPurgedAt:t}}async function wa(e,t,n){let r=new Set(t.filter(e=>e.data.status===`draft`).map(e=>e.id)),i=await e.audit_events.query({where:{envelopeId:{in:t.map(e=>e.id)}},limit:100,...n?{cursor:n}:{}}),a=i.items.filter(e=>!r.has(e.data.envelopeId)&&e.data.personal!==null),o=i.items.filter(e=>r.has(e.data.envelopeId)).map(e=>e.id);return a.length>0&&await e.audit_events.putMany(a.map(e=>({id:e.id,data:Kn(e.data)}))),o.length>0&&await e.audit_events.deleteMany(o),i.hasMore?i.cursor:void 0}async function Ta(e,t,n){let r=A(n),i=t.filter(e=>e.data.status!==`draft`),a=i.flatMap(e=>e.data.signerIds),o=a.length>0?await e.signers.getMany(a):new Map,s=a.flatMap(e=>{let t=o.get(e);return t?[{id:e,data:Sa(e,t)}]:[]});s.length>0&&await e.signers.putMany(s),i.length>0&&await e.envelopes.putMany(i.map(e=>({id:e.id,data:Ca(e.data,r)})));let c=t.filter(e=>e.data.status===`draft`).map(e=>e.id);c.length>0&&await e.envelopes.deleteMany(c)}async function Ea(e,t){let n=B(e),r={...await e.kv.get(_a)},i=!1;if(!r.phase||r.phase===`rl`)(await Xt(e.kv,t,3)).more?r.phase=`rl`:Object.assign(r,xa(await e.settings.list(`retention`),t),{phase:`personal`});else if(r.phase===`outbox`){let e=await n.outbox.query({where:{status:{in:[`sent`,`failed`]},nextAttemptAt:{lt:r.p}},limit:100});e.items.length>0&&await n.outbox.deleteMany(e.items.map(e=>e.id)),i=!e.hasMore}else{let e=r.phase===`personal`,i=e?r.p:r.r,a=await n.envelopes.query({where:{createdAt:{gte:(e?r.pf:r.rf)??``,lt:A(i)}},limit:10,...r.cursor?{cursor:r.cursor}:{}}),o=t=>e?t.personalPurgedAt:t.recordsPurgedAt,s=a.items.filter(({data:e})=>!o(e)&&(ya(e)??i)<i),c=s.length===0;if(!r.step&&s.length>0){if(e)r.acursor=await wa(n,s,r.acursor);else{let e=await n.audit_events.query({where:{envelopeId:{in:s.map(e=>e.id)}},limit:100});if(e.items.length>0&&await n.audit_events.deleteMany(e.items.map(e=>e.id)),e.hasMore)r.acursor=`more`;else{delete r.acursor;let e=s.flatMap(e=>e.data.pdf?.ids??[]),t=s.flatMap(e=>e.data.snapshot?.ids??[]);e.length>0&&await n.artifacts.deleteMany(e),t.length>0&&await n.snapshots.deleteMany(t)}}r.acursor||(r.step=1)}else if(s.length>0){if(e)await Ta(n,s,t);else{let e=s.flatMap(e=>e.data.signerIds);e.length>0&&await n.signers.deleteMany(e);let r=A(t);await n.envelopes.putMany(s.map(({id:e,data:t})=>({id:e,data:{...t,title:``,signerIds:[],snapshot:null,pdf:null,pdfSha256:null,recordsPurgedAt:r}})))}c=!0}if(c){delete r.step;for(let{data:e}of a.items)!o(e)&&!s.some(t=>t.data===e)&&(!r.keep||e.createdAt<r.keep)&&(r.keep=e.createdAt);a.hasMore&&a.cursor?r.cursor=a.cursor:(r[e?`pf`:`rf`]=r.keep??A(i),delete r.cursor,delete r.keep,r.phase=e?`records`:`outbox`)}}return i&&delete r.phase,await e.kv.set(_a,r),i||await e.cron?.schedule(ga,{schedule:A(t)}),i}async function Da(e,t,n=Date.now()){return e.name!==ha&&e.name!==ga?!1:(await Ea(t,n),!0)}const Oa=e=>va(e)||e.status===`completed`&&!e.pdfSha256;async function ka(e,t){let n=B(e),r;if(t.includes(`@`)){let e=t.toLowerCase(),[i,a]=await Promise.all([n.signers.query({where:{email:e},limit:10}),n.envelopes.query({where:{signerEmail:e},limit:10})]),o=new Map(a.items.map(e=>[e.id,e.data])),s=[...new Set(i.items.map(e=>e.data.envelopeId))].filter(e=>!o.has(e));if(s.length>0)for(let[e,t]of await n.envelopes.getMany(s))o.set(e,t);r=[...o].slice(0,10).map(([e,t])=>({id:e,data:t}))}else{let e=await n.envelopes.get(t);r=e?[{id:t,data:e}]:[]}return{due:r.filter(e=>!Oa(e.data)&&!e.data.personalPurgedAt),open:r.filter(e=>Oa(e.data)).length}}async function Aa(e,t,n){let r=B(e),i=await wa(r,t.due);if(i&&=await wa(r,t.due,i),i)throw Error(`audit trail too long for one request`);await Ta(r,t.due,n),await r.outbox.deleteMany(t.due.flatMap(e=>[`complete-${e.id}`,...e.data.signerIds.map(e=>`invite-${e}`)]))}const ja=new Set([`localhost`,`127.0.0.1`,`[::1]`]);function Ma(e=b){return x(e(32))}const Na=e=>ia(e)===null;function Pa(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(e===``)continue;let r;try{r=new URL(e)}catch{return{ok:!1,entry:e}}if(!(r.protocol===`https:`||r.protocol===`http:`&&ja.has(r.hostname))||r.username||r.password||e.includes(`#`)||e.includes(`?`))return{ok:!1,entry:e};t.push(r.href)}return t.length>10?{ok:!1,entry:`too many entries`}:{ok:!0,entries:t}}async function Fa(e,t,n){let r=ia(t.masterKey);if(!r)return{ok:!1,code:`MASTER_KEY_MISSING`};let i=t.name.trim();if(i===``||i.length>100)return{ok:!1,code:`NAME_REQUIRED`};let a=gt(n.random),o={name:i,clientId:a,createdAt:n.now,lastUsedAt:null,revokedAt:null,returnUrlAllowlist:t.returnUrlAllowlist};return await e.put(a,o),{ok:!0,client:o,pairing:mt(a,await ht(r,a))}}async function Ia(e,t,n){return(await e.updateIf(t,{where:{revokedAt:null},set:{revokedAt:n}})).applied}async function La(e){return(await e.query({orderBy:{createdAt:`desc`},limit:100})).items.map(e=>e.data)}function Ra(e){let t=(e??``).split(`,`).filter(e=>e.trim()!==``).length;return t===0?{state:`missing`,canSaveSecrets:!1,keyCount:0,banner:{tone:`error`,message:`EMDASH_ENCRYPTION_KEY is not set, so secret settings (the integration master key and the Turnstile secret) cannot be saved. Set it in the site environment and restart.`}}:{state:`ready`,canSaveSecrets:!0,keyCount:t,banner:null}}function za(e){let t=`PLUGIN_SETTING_ENCRYPTION_KEY_MISSING`,n=e=>e.includes(t)||e.includes(`PluginSettingEncryptionError`);return typeof e==`string`?n(e):e instanceof Error?n(e.message)||e.name===`PluginSettingEncryptionError`:typeof e==`object`&&e?e.code===t:!1}const Ba=e=>e.storage.templates,W=e=>({...D(`BAD_REQUEST`).body,...e?{issues:e}:{}}),Va=()=>D(`TEMPLATE_NOT_FOUND`).body;function Ha(e){let t=V(e).id;return typeof t==`string`&&t.length>0&&t.length<=200&&!t.includes(`:`)?t:null}const Ua=(e,t)=>({id:e,...t}),Wa=(e,{body:t,...n})=>({id:e,...n});async function Ga(e,t){let n=await Ba(e).get(t);return n&&n.status!==`version`?n:null}const Ka={"templates/create":{handler:(async(e,t)=>{let n=crypto.randomUUID(),r=nr(e.input,{id:n,now:A()});if(!r.ok)return W(r.error);let{head:i,versions:a}=r.value;return await Ba(t).putMany([{id:n,data:i},...a]),{ok:!0,template:Ua(n,i)}})},"templates/update":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=await Ga(t,n);if(!r)return Va();let i=rr(r,e.input,{id:n,now:A()});return i.ok?(await Ba(t).putMany([{id:n,data:i.value.head},i.value.version]),{ok:!0,template:Ua(n,i.value.head)}):W(i.error)})},"templates/get":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=V(e.input).version;if(r!==void 0&&!(Number.isSafeInteger(r)&&r>=1))return W();let i=r,a=await Ba(t).getMany(i===void 0?[n]:[n,L(n,i)]),o=a.get(n);if(!o||o.status===`version`)return Va();let s=i===void 0?o:a.get(L(n,i));if(!s)return Va();let c=Array.from({length:o.version},(e,t)=>t+1);return{ok:!0,template:Ua(n,{...s,status:o.status}),versions:c}})},"templates/list":{handler:(async(e,t)=>{let n=V(e.input).status??`active`;if(n!==`active`&&n!==`archived`)return W();let{items:r}=await Ba(t).query({where:{status:n},limit:200});return{ok:!0,templates:r.map(e=>Wa(e.id,e.data)).sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:0)}})},"templates/archive":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=await Ga(t,n);if(!r)return Va();if(r.status===`archived`)return{ok:!0,template:Ua(n,r)};let i=ir(r,A());return await Ba(t).putMany([{id:n,data:i}]),{ok:!0,template:Ua(n,i)}})}},qa=(e,t)=>({severity:`error`,title:e,...t?{message:t}:{}}),Ja=e=>B(e.ctx).clients;async function Ya(e){return(await e.ctx.settings.list()).find(e=>e.key===`integrationMasterKey`)?.value}const Xa=e=>typeof e==`string`&&e.trim()!==``;function Za(e,r,o=[]){let s=ia(e)!==null,c=typeof e==`object`&&!!e,l=Ra(null).banner;return K([t(`Integrations`),...u([c&&l&&{severity:`error`,title:`Encryption key missing`,message:l.message},!s&&!c&&{severity:`warning`,title:Xa(e)?`Integration master key is too short`:`Integration master key not set`,message:`Clients are paired with secrets derived from the master key. Generate one here, or save one of at least 32 characters in Settings.`}]),...o,...s||c||Xa(e)?[]:[d([f(`integrations.generate-key`,`Generate master key`,{style:`primary`})])],t(`Clients`),a({columns:[i(`name`,`Name`),i(`clientId`,`Client id`),i(`created`,`Created`,`relative_time`),i(`status`,`Status`,`badge`),i(`revoke`,``,`element`)],rows:r.map(e=>({name:e.name,clientId:e.clientId,created:e.createdAt,status:e.revokedAt?`Revoked`:`Active`,...e.revokedAt?{}:{revoke:f(`client.revoke`,`Revoke`,{style:`danger`,value:e.clientId,confirm:{title:`Revoke this client?`,text:`Its intents and receipts are refused from now on. This cannot be undone; create a new client to pair again.`,confirm:`Revoke client`,deny:`Keep`,style:`danger`}})}})),pageActionId:`clients.page`,emptyText:`No clients yet.`}),t(`Add a client`),n(`The pairing string is shown once, right after you create the client, and cannot be shown again. Paste it into the other plugin's settings. Return URLs: one per line, https (http only for localhost); leave blank to allow this site only.`),y({fields:[m(`name`,`Name`,{initialValue:``}),m(`returnUrlAllowlist`,`Allowed return URLs`,{multiline:!0,initialValue:``})],submit:{label:`Create client`,actionId:`client.create`}})])}async function G(e,t,n=[]){return Za(t,await La(Ja(e)),n)}async function Qa(e){let[t,n]=await Promise.all([Ya(e),La(Ja(e))]);return Za(t,n)}async function $a(e){let t=await Ya(e);if(Xa(t))return G(e,t,u([qa(`Key already set`,`Changing it would re-pair every client.`)]));let n=Ma();try{await e.ctx.settings.set(`integrationMasterKey`,n)}catch(n){if(!za(n))throw n;return G(e,t,u([qa(`Encryption key missing`,Ra(null).banner?.message)]))}return G(e,n,u([{severity:`info`,title:`Master key generated`}]))}async function eo(e,t){let n=await Ya(e),r=(e,t)=>typeof e==`string`?e.slice(0,t):``,i=Pa(r(t.returnUrlAllowlist,2e3));if(!i.ok)return G(e,n,u([qa(`Not created`,`Return URL not allowed: ${i.entry.slice(0,200)}`)]));let a=await Fa(Ja(e),{name:r(t.name,200),returnUrlAllowlist:i.entries,masterKey:n},{now:A(e.now)});return a.ok?G(e,n,[...u([{severity:`warning`,title:`Copy the pairing string now`,message:`It is shown only this once and cannot be recovered. Treat it like a password.`}]),o({code:a.pairing})]):G(e,n,u([qa(`Not created`,a.code===`MASTER_KEY_MISSING`?`Set the integration master key first (at least 32 characters), or generate one.`:`Give the client a name of up to 100 characters.`)]))}async function to(e,t){let n=await Ia(Ja(e),t,A(e.now));return G(e,await Ya(e),u([n?{severity:`info`,title:`Client revoked`}:qa(`Not revoked`,`Unknown or already revoked.`)]))}const K=e=>({blocks:e}),q=(e,t=200)=>typeof e==`string`?e.trim().slice(0,t):``,J=(e,t,n)=>t.handler({input:n,user:e.user??null},e.ctx),no=e=>Yi[e],ro=e=>Ka[e],io={INVALID_NAME:`Give the template a name of up to 200 characters.`,INVALID_BODY:`The template text is required (up to 100,000 characters).`,INVALID_DESCRIPTION:`The description is too long (up to 1,000 characters).`,TEMPLATE_ARCHIVED:`This template is archived.`,INVALID_INTEGRATIONS:`Choose whether integrations may use the template.`,INVALID_TITLE:`The title is too long or has control characters.`,INVALID_SIGNER_NAME:`Enter the signer's name.`,INVALID_SIGNER_EMAIL:`Enter a valid email address for the signer.`,INVALID_FIELDS:`A field value is too long or not text.`,MISSING_FIELD:`A template field has no value.`,DOCUMENT_TOO_LARGE:`The document is too long to sign (up to 131,072 characters and 1,500 lines).`};function Y(e,t=`The change was refused.`){let n=Array.isArray(e.issues)?e.issues:[];return n.length>0?n.map(e=>io[e.code??``]??`${e.path??`input`} (${e.code??`invalid`})`).join(` `):e.error?.message??t}const ao=(e,t,n)=>({severity:e,title:t,...n?{message:n}:{}}),X=(e,t)=>ao(`error`,e,t),oo=(e,t)=>ao(`warning`,e,t),so=(e,t)=>f(e,t,{style:`secondary`}),Z=(e,t)=>ao(`info`,e,t),co=()=>so(`envelopes.back`,`Back to envelopes`),lo=()=>so(`templates.back`,`Back to templates`),uo=e=>f(`envelope.open`,`Open envelope`,{value:e}),fo={"envelope.created":`Envelope created`,"envelope.sent":`Envelope sent`,"signer.viewed":`Signer opened the document`,"signer.consented":`Signer gave consent`,"signer.signed":`Signer signed`,"signer.declined":`Signer declined`,"envelope.completed":`Envelope completed`,"envelope.declined":`Envelope declined`,"envelope.voided":`Envelope voided`,"envelope.expired":`Envelope expired`},po=e=>!Tn(e.ctx)&&oo(`Set the site URL`,Dn);async function mo(e){let t=await jn(e.ctx);return[po(e),t.state===`no_transport`&&oo(`No email transport`,`No email provider is configured, so signing invitations stay queued and are not delivered. Install an email provider plugin.`),t.failed>0&&oo(`${t.failed} email${t.failed===1?``:`s`} could not be delivered`,`Open the envelope and use Resend invitation if a signer never received theirs.`)]}async function ho(e,r,o=[],s){let c=Zn(r)?r:``,[l,d]=await Promise.all([J(e,no(`envelopes/list`),{...c?{status:c}:{},...s?{cursor:s}:{}}),mo(e)]),p=typeof l.nextCursor==`string`?l.nextCursor:void 0,h=(l.envelopes??[]).map(e=>{let t=e.signer;return{title:e.title,signer:t?`${t.name??``} <${t.email??``}>`:``,status:e.status,created:e.createdAt,open:f(`envelope.open`,`Open`,{value:e.id})}});return K([t(`Envelopes`),...u(d),...o,y({fields:[g(`status`,`Status`,[{label:`Any status`,value:``},...Jn.map(e=>({label:e.replaceAll(`_`,` `),value:e}))],{initialValue:c})],submit:{label:`Filter`,actionId:`envelopes.filter`}}),n(`Newest first, 100 a page. Create an envelope from a template on the Templates page.`),a({columns:[i(`title`,`Title`),i(`signer`,`Signer`),i(`status`,`Status`,`badge`),i(`created`,`Created`,`relative_time`),i(`open`,``,`element`)],rows:h,pageActionId:`envelopes.page:${c}`,...p?{nextCursor:p}:{},emptyText:`No envelopes match.`}),t(go),y({fields:[m(`subject`,`Signer email or envelope id`)],submit:{label:`Find`,actionId:`retention.preview`}})])}const go=`Delete personal data`;async function _o(e,n,r){let i=await ka(e.ctx,n),a=i.due.length;return r&&a>0&&await Aa(e.ctx,i,e.now),K([t(go),...u([{severity:r?`info`:`warning`,title:r&&a>0?`Personal data deleted`:a+i.open>0?`${a} envelope(s) to delete, ${i.open} kept for now`:`No envelopes found`,message:`Signed records stay for their own period; open envelopes and pending PDFs are skipped.`}]),d([...!r&&a>0?[f(`retention.erase`,go,{style:`danger`,value:n,confirm:{title:`${go}?`,text:`This cannot be undone.`,confirm:`Delete`,deny:`Keep`,style:`danger`}})]:[],co()])])}async function vo(e,t){if(!t)return`missing`;let n=await B(e.ctx).outbox.get(`invite-${t}`);return n?n.status===`failed`?`failed`:`queued`:`missing`}async function Q(e,o,s={}){let{envelopes:c,signers:l,audit_events:m}=B(e.ctx),h=s.envelope??await c.get(o);if(!h)return K([t(`Envelope`),...u([X(`Envelope not found`,`It may have been removed.`)]),d([co()])]);let g=h.status===`sent`||h.status===`in_progress`,[_,v,y]=await Promise.all([m.query({where:{envelopeId:o},orderBy:{seq:`asc`},limit:200}),s.signers?Promise.resolve(s.signers):h.signerIds.length>0?l.getMany(h.signerIds).then(e=>[...e].map(([e,t])=>({id:e,name:t.name,email:t.email,status:t.status}))):Promise.resolve([]),s.invite??(h.status===`sent`?vo(e,h.signerIds[0]):Promise.resolve(`n/a`))]),b=v[0],x=h.status===`sent`&&(y===`missing`||y===`failed`),S=null;if(h.status===`completed`&&!h.recordsPurgedAt)if(h.pdfSha256){let t=await Ai(e.ctx,o,e.now);S=d([p(`Download signed PDF`,{kind:`external`,url:`${e.origin}${t.url}`},{appearance:`primary`})])}else S=n(`The signed PDF is still being prepared. Reload in a minute.`);let C=[h.status===`draft`&&f(`envelope.send`,`Send for signature`,{style:`primary`,value:o}),x&&f(`envelope.resend`,`Resend invitation`,{style:`primary`,value:o}),(h.status===`draft`||g)&&f(`envelope.void`,`Void`,{style:`danger`,value:o,confirm:{title:`Void this envelope?`,text:`The signer will no longer be able to sign it. This cannot be undone.`,confirm:`Void envelope`,deny:`Keep`,style:`danger`}}),co()].filter(e=>e!==!1);return K([t(h.title),...u([x&&{severity:`warning`,title:`The invitation was not delivered`,message:y===`failed`?`The email gave up after repeated failures. Resend invitation queues a fresh email with a new signing link.`:`The invitation was never queued. Resend invitation queues it with a new signing link.`},x&&po(e)]),...s.extra??[],...h.personalPurgedAt?[n(`Personal data deleted ${h.personalPurgedAt}${h.recordsPurgedAt?`; signed records deleted`:``} (retention).`)]:[],r([{label:`Status`,value:h.status.replaceAll(`_`,` `)},{label:`Template`,value:`${h.templateId} v${h.templateVersion}`},{label:`Signer`,value:b?`${b.name} <${b.email}>`:h.signer.email},{label:`Signer status`,value:b?.status??`not sent yet`},{label:`Delivery`,value:h.delivery},{label:`Created`,value:h.createdAt},{label:`Sent`,value:h.sentAt??`Not sent`},{label:`Expires`,value:h.expiresAt??`Not set`},{label:`Completed`,value:h.completedAt??`Not completed`},{label:`Document SHA-256`,value:h.docSha256??`Set when sent`},{label:`Final hash`,value:h.finalHash??`Set when completed`}]),...S?[S]:[],d(C),t(`Audit timeline`),a({columns:[i(`seq`,`#`,`number`),i(`event`,`Event`),i(`at`,`When`,`text`),i(`actor`,`By`)],rows:_.items.map(({data:e})=>({seq:e.seq,event:fo[e.type]??e.type,at:e.at,actor:e.actor})),pageActionId:`audit.page:${o}`,emptyText:`No events yet.`})])}async function yo(e,n){let r;try{r=await J(e,no(`envelopes/send`),{id:n})}catch{return K([t(`Envelope`),...u([X(`The envelope was sent but the invitation could not be queued`,`Open the envelope and use Resend invitation.`)]),d([uo(n)])])}if(r.ok!==!0)return K([t(`Envelope`),...u([X(`Not sent`,Y(r))]),d([uo(n),co()])]);let i=r.invitation===`SITE_URL_MISSING`;return K([t(`Envelope`),...u([i?{severity:`warning`,title:`Envelope sent, but no invitation was queued`,message:Dn}:Z(`Envelope sent`,`The signer's invitation is queued.`)]),d([uo(n),co()])])}async function bo(e,t){let n=await J(e,no(`envelopes/void`),{id:t});if(n.ok!==!0){let r=n.error?.code===`ENVELOPE_CLOSED`;return Q(e,t,{extra:u([X(r?`This envelope cannot be voided`:`Not voided`,r?`It is already completed, declined, voided or expired.`:Y(n))])})}return Q(e,t,{envelope:n.envelope,invite:`n/a`,extra:u([Z(`Voided`,`The signer can no longer sign this envelope.`)])})}async function xo(e,t){let n=await J(e,no(`envelopes/resend`),{id:t});return n.ok===!0?Q(e,t,{envelope:n.envelope,invite:`queued`,signers:n.signers,extra:u([Z(`Invitation queued`,`A new email with a new signing link is on its way.`)])}):Q(e,t,{extra:u([n.error?.code===`INVITATION_QUEUED`?Z(`Already queued`,`The invitation is queued or was sent.`):X(`Not resent`,Y(n,`Only an envelope that is sent and unsigned can be resent.`))])})}const So=/^(signer|participant)\./;async function Co(e,r,i=[]){let a=await J(e,ro(`templates/get`),{id:r}),o=a.template;return a.ok!==!0||!o?K([t(`New envelope`),...u([X(`Template not found`)]),...i]):K([t(`New envelope: ${o.name}`),...i,n(`Creates a draft you can check before sending it for signature. Signer fields: one per line as key: Label, ending in * when required.`),y({fields:[m(`title`,`Title`,{initialValue:o.name}),m(`signerName`,`Signer name`),m(`signerEmail`,`Signer email`),...o.fields.filter(e=>!So.test(e)).map(e=>m(`field:${e}`,e)),m(`signerFields`,`Fields the signer fills in (optional)`,{multiline:!0,placeholder:`phone: Phone number *`})],submit:{label:`Create draft`,actionId:`envelope.create`},blockId:`envelope-new:${r}`}),d([lo()])])}function wo(e){return typeof e==`string`?e.slice(0,4e3).split(`
|
|
38
|
-
`).map(e=>e.trim()).filter(e=>e!==``).map(e=>{let t=e.indexOf(`:`),n=(t===-1?e:e.slice(0,t)).trim(),r=t===-1?``:e.slice(t+1).trim(),i=r.endsWith(`*`);return i&&(r=r.slice(0,-1).trim()),{key:n,label:r,...i?{required:!0}:{}}}):[]}async function To(e,t,n){let r=t?.startsWith(`envelope-new:`)?t.slice(13):``;if(!r)return K(u([X(`Choose a template first`)]));let i={};for(let[e,t]of Object.entries(n))e.startsWith(`field:`)&&(i[e.slice(6)]=typeof t==`string`?t:``);let a=q(n.title),o=wo(n.signerFields),s=await J(e,no(`envelopes/create`),{templateId:r,...a?{title:a}:{},signer:{name:q(n.signerName),email:q(n.signerEmail)},fields:i,...o.length>0?{signerFields:o}:{}});if(s.ok!==!0)return Co(e,r,u([X(`Not saved`,Y(s))]));let c=s.envelope.id;return Q(e,c,{extra:u([Z(`Draft created`,`Check the details, then send it.`)])})}async function Eo(e,r=[]){let o=((await J(e,ro(`templates/list`),{})).templates??[]).map(e=>({name:e.name,version:e.version,fields:(e.fields??[]).join(`, `),integrations:e.integrations===!0?`Yes`:`No`,updated:e.updatedAt,edit:f(`template.edit`,`Edit`,{value:e.id}),use:f(`envelope.new`,`New envelope`,{style:`primary`,value:e.id})}));return K([t(`Templates`),...r,a({columns:[i(`name`,`Name`),i(`version`,`Version`,`number`),i(`fields`,`Fields`),i(`integrations`,`Integrations`),i(`updated`,`Updated`,`relative_time`),i(`edit`,``,`element`),i(`use`,``,`element`)],rows:o,pageActionId:`templates.page`,emptyText:`No templates yet. Add one below.`}),t(`New template`),n(`Write the document in Markdown. Use {{field}} for values filled in per envelope, and {{signer.name}} for the signer.`),y({fields:[m(`name`,`Name`),m(`description`,`Description (optional)`),m(`body`,`Template text`,{multiline:!0}),Do(!1)],submit:{label:`Create template`,actionId:`template.create`}})])}function Do(e){return _(`integrations`,`Available to integrations`,{description:`Paired sites (such as Events) may send this template for signing.`,initialValue:e})}function Oo(e){let t=Object.fromEntries(un(e).map(e=>[e,`«${e}»`]));try{return dn(e,t)}catch{return e}}function ko(e,r,i=[]){let a=String(r.body??``),s=un(a);return K([t(`Edit template: ${String(r.name??``)}`),...i,n(`Version ${String(r.version??1)}. Saving writes a new version; sent envelopes keep the text they were sent with.`),y({fields:[m(`name`,`Name`,{initialValue:String(r.name??``)}),m(`description`,`Description (optional)`,{initialValue:String(r.description??``)}),m(`body`,`Template text`,{initialValue:a,multiline:!0}),Do(r.integrations===!0)],submit:{label:`Save new version`,actionId:`template.save`},blockId:`template:${e}`}),t(`Preview`),n(s.length>0?`Fields: ${s.join(`, `)}. Placeholders show as «name».`:`This template has no fields.`),o({code:Oo(a)}),d([f(`envelope.new`,`New envelope from this template`,{style:`primary`,value:e}),f(`template.archive`,`Archive`,{style:`danger`,value:e,confirm:{title:`Archive this template?`,text:`It can no longer be used for new envelopes. Sent envelopes are not affected.`,confirm:`Archive`,deny:`Keep`,style:`danger`}}),lo()])])}async function Ao(e,t,n=[]){let r=await J(e,ro(`templates/get`),{id:t});return r.ok!==!0||!r.template?Eo(e,u([X(`Template not found`)])):ko(t,r.template,n)}async function jo(e,t){let n=await J(e,ro(`templates/create`),{name:q(t.name),body:typeof t.body==`string`?t.body:``,...q(t.description,1e3)?{description:q(t.description,1e3)}:{},integrations:t.integrations===!0});return n.ok===!0?Eo(e,u([Z(`Template created`)])):Eo(e,u([X(`Not saved`,Y(n))]))}async function Mo(e,t,n){let r=t?.startsWith(`template:`)?t.slice(9):``;if(!r)return K(u([X(`Choose a template first`)]));let i={name:q(n.name),body:typeof n.body==`string`?n.body:``,description:q(n.description,1e3),integrations:n.integrations===!0},a=await J(e,ro(`templates/update`),{id:r,...i});return a.ok===!0?ko(r,a.template,u([Z(`Saved`)])):ko(r,{...i,version:`?`},u([X(`Not saved`,Y(a))]))}async function No(e,t){let n=await J(e,ro(`templates/archive`),{id:t});return Eo(e,u([n.ok===!0?Z(`Template archived`):X(`Not archived`,Y(n))]))}const Po=[{key:`senderName`,label:`Sender name`,kind:`text`},{key:`expiryDays`,label:`Envelope expiry (days)`,kind:`number`,min:1,max:365},{key:`consentVersion`,label:`Consent version`,kind:`text`},{key:`consentWording`,label:`Consent wording`,kind:`long`},{key:`retentionPersonalDataMonths`,label:`Keep personal data (months)`,kind:`number`,min:1,max:120},{key:`retentionSignedRecordsYears`,label:`Keep signed records (years)`,kind:`number`,min:1,max:50},{key:`turnstileSiteKey`,label:`Turnstile site key`,kind:`text`}],Fo=[{key:`turnstileSecretKey`,label:`Turnstile secret key`},{key:`integrationMasterKey`,label:`Integration master key`}],Io=e=>typeof e==`string`&&e!==``?`readable`:typeof e==`object`&&e?`unreadable`:`unset`;function Lo(e,r,i=[]){let a=Fo.some(e=>r[e.key]===`unreadable`),o=Ra(null).banner;return K([t(`Settings`),...u([a&&o&&{severity:`error`,title:`Encryption key missing`,message:o.message},r.integrationMasterKey===`unset`&&oo(`Integration master key not set`,`Other plugins cannot create envelopes through the integration protocol until it is saved.`)]),...i,y({fields:[...Po.map(t=>t.kind===`number`?h(t.key,t.label,{min:t.min,max:t.max,...typeof e[t.key]==`number`?{initialValue:e[t.key]}:{}}):m(t.key,t.label,{multiline:t.kind===`long`,initialValue:typeof e[t.key]==`string`?e[t.key]:``})),...Fo.map(e=>v(e.key,`${e.label} (leave blank to keep)`,{hasValue:r[e.key]===`readable`}))],submit:{label:`Save settings`,actionId:`settings.save`}}),n(`Reminder and one-time-code settings (Pro) are in the plugin's own settings panel.`)])}async function Ro(e){let t=await e.ctx.settings.list(),n=Object.fromEntries(t.map(e=>[e.key,e.value]));return{values:n,secrets:Object.fromEntries(Fo.map(e=>[e.key,Io(n[e.key])]))}}async function zo(e){let{values:t,secrets:n}=await Ro(e);return Lo(t,n)}async function Bo(e,t){let{values:n,secrets:r}=await Ro(e),i=[],a=[];for(let e of Po){let r=t[e.key];if(r==null||r===``)continue;let o;if(e.kind===`number`){if(o=Number(r),!Number.isInteger(o)||o<(e.min??0)||o>(e.max??2**53-1)){a.push(`${e.label} must be a whole number from ${e.min} to ${e.max}.`);continue}}else o=q(r,e.kind===`long`?2e3:200);o!==n[e.key]&&i.push([e.key,o])}let o=Fo.filter(e=>q(t[e.key],500)!==``);if(o.some(e=>e.key===`integrationMasterKey`&&Na(q(t[e.key],500)))&&a.push(`The integration master key must be at least 32 characters, or use Generate on the Integrations page.`),a.length>0)return Lo(n,r,u([X(`Not saved`,a.join(` `))]));if(i.length+o.length>6)return Lo(n,r,u([X(`Too many changes at once`,`Save at most 6 settings at a time.`)]));if(i.length+o.length===0)return Lo(n,r,u([Z(`Nothing to save`)]));let s={...n},c={...r};try{for(let n of o)await e.ctx.settings.set(n.key,q(t[n.key],500)),c[n.key]=`readable`;for(let[t,n]of i)await e.ctx.settings.set(t,n),s[t]=n}catch(e){if(!za(e))throw e;let t=Ra(null).banner;return Lo(n,r,u([{severity:`error`,title:`Encryption key missing`,message:t?.message}]))}return Lo(s,c,u([Z(`Saved`)]))}const Vo=e=>q(e,200);async function Ho(e,t){if(t.type===`page_load`)switch(t.page){case`/envelopes`:return ho(e,``);case`/templates`:return Eo(e);case`/settings`:return zo(e);case`/integrations`:return Qa(e);default:return K(u([X(`Page not found`)]))}if(t.type===`form_submit`){let n=t.values;switch(t.action_id){case`envelopes.filter`:return ho(e,q(n.status));case`envelope.create`:return To(e,t.block_id,n);case`template.create`:return jo(e,n);case`template.save`:return Mo(e,t.block_id,n);case`settings.save`:return Bo(e,n);case`client.create`:return eo(e,n);case`retention.preview`:return _o(e,q(n.subject),!1)}}else{let n=Vo(t.value);if(t.action_id.startsWith(`envelopes.page:`))return ho(e,t.action_id.slice(15),[],q(t.value,500)||void 0);if(t.action_id.startsWith(`audit.page:`))return Q(e,Vo(t.action_id.slice(11)));switch(t.action_id){case`envelopes.back`:case`envelopes.page`:return ho(e,``);case`envelope.open`:return Q(e,n);case`envelope.send`:return yo(e,n);case`envelope.void`:return bo(e,n);case`envelope.resend`:return xo(e,n);case`retention.erase`:return _o(e,n,!0);case`envelope.new`:return Co(e,n);case`integrations.generate-key`:return $a(e);case`client.revoke`:return to(e,n);case`clients.page`:return Qa(e);case`templates.back`:case`templates.page`:return Eo(e);case`template.edit`:return Ao(e,n);case`template.archive`:return No(e,n)}}return K(u([X(`Unknown action`)]))}const Uo={admin:{handler:(async(e,t)=>{let n=`http://localhost`;try{n=new URL(e.request?.url??``).origin}catch{}return Ho({ctx:t,origin:n,now:Date.now(),user:e.user??null},e.input)})}},Wo=[`completed`,`declined`,`voided`,`expired`],Go=e=>{if(!e)return;let t=Date.parse(e);return Number.isNaN(t)?void 0:Math.floor(t/1e3)};function Ko(e,t){let{status:n,clientId:r,externalRef:i}=t;if(!Wo.includes(n)||!r||!i||t.docSha256===null)return;let a=n===`completed`,o=a?Go(t.completedAt):Go(t.closedAt)??Go(t.updatedAt);if(o===void 0)return;let s={v:1,typ:`receipt`,cid:r,envelopeId:e,ref:i,status:n,docSha256:t.docSha256,pdfSha256:a?t.pdfSha256??null:null,finalHash:a?t.finalHash:null,at:o};return We(`receipt`,s).ok?s:void 0}async function qo(e,t,n){let r=Ko(e,t);return r?ot(`receipt`,r,n):void 0}function Jo(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):void 0}function Yo(e){let t={};return{settings:()=>t,async getClient(n){let[r,i]=await Promise.all([e.settings.list(),B(e).clients.get(n)]);t=Object.fromEntries(r.map(e=>[e.key,e.value]));let a=ia(t.integrationMasterKey);if(!(!a||!i))return{secret:await ht(a,n),revoked:i.revokedAt!==void 0&&i.revokedAt!==null,returnUrlAllowlist:Jo(i.returnUrlAllowlist)}}}}async function Xo(e,t,n){let r=ia(n);if(!(!r||!t.clientId))return qo(e,t,await ht(r,t.clientId))}async function Zo(e,t,n=Date.now()){let r=await at({token:V(e).request,now:n,getClient:Yo(t).getClient});if(!r.ok)return U(r.error);let i=[],a;for(let e=0;e<3;e++){let e=await B(t).templates.query({where:{status:`active`},limit:200,...a===void 0?{}:{cursor:a}});if(i.push(...e.items),!e.hasMore||!e.cursor)break;a=e.cursor}return{ok:!0,templates:i.filter(e=>ar(e.data)).map(e=>({id:e.id,name:e.data.name,version:e.data.version})).sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:e.id<t.id?-1:1)}}const Qo=(e,t)=>Zo(e.input,t),$o=/^[0-9a-f]{64}$/,es=/[\u0000-\u001F\u007F]/,ts=e=>Array.isArray(e)&&e.length===2&&e.every(e=>typeof e==`number`&&Number.isFinite(e)&&e>=0&&e<=1);function ns(e){let t=e=>T({path:`signature.strokes`,code:e});return!Array.isArray(e)||e.length===0||e.length>64?t(`INVALID_SIGNATURE`):JSON.stringify(e).length>32768?t(`STROKES_TOO_LARGE`):e.every(e=>Array.isArray(e)&&e.length>0&&e.every(ts))?w(e):t(`INVALID_SIGNATURE`)}function rs(e){let t=T({path:`signature`,code:`INVALID_SIGNATURE`});if(!dr(e)||e.kind!==`typed`&&e.kind!==`drawn`)return t;let n=e.typedName===void 0?void 0:pr(e.typedName);if(n===null)return t;if(e.kind===`typed`)return n===void 0?t:w({kind:`typed`,typedName:n});let r=ns(e.strokes);return r.ok?w({kind:`drawn`,...n===void 0?{}:{typedName:n},strokes:r.value}):r}function is(e){if(!dr(e))return T([{path:``,code:`INVALID_INPUT`}]);let t=[];e.consent!==!0&&t.push({path:`consent`,code:`CONSENT_REQUIRED`}),e.intent!==!0&&t.push({path:`intent`,code:`INTENT_REQUIRED`});let n=typeof e.docSha256==`string`&&$o.test(e.docSha256)?e.docSha256:null;n===null&&t.push({path:`docSha256`,code:`INVALID_DOC_HASH`});let r=typeof e.consentSha256==`string`&&$o.test(e.consentSha256)?e.consentSha256:null;r===null&&t.push({path:`consentSha256`,code:`INVALID_CONSENT_HASH`});let i=rs(e.signature);i.ok||t.push(i.error);let a=hr(e.fieldValues);return a===null&&t.push({path:`fieldValues`,code:`INVALID_FIELDS`}),t.length>0||n===null||r===null||!i.ok||a===null?T(t):w({docSha256:n,consentSha256:r,signature:i.value,fieldValues:a})}function as(e){if(e===void 0)return;let t=typeof e==`string`?e.trim():``;return t.length===0||[...t].length>500||es.test(t)?null:t}async function os(e,t,n){let r=Object.keys(n.fieldValues).sort().map(e=>[e,n.fieldValues[e]]),i=await F(n.salt+JSON.stringify([e,t.kind,t.typedName??null,t.strokes??null,r]));return{...t,sha256:i}}const ss=e=>({...e.ip===void 0?{}:{ip:e.ip},...e.ua===void 0?{}:{ua:e.ua}}),cs=e=>e===void 0?{}:{signer:e};function ls(e,t,n,r){return{type:`signer.viewed`,at:e,actor:`signer`,data:{docSha256:t,...cs(r)},personal:ss(n)}}function us(e){let{at:t,docSha256:n,signature:r}=e;return[{type:`signer.consented`,at:t,actor:`signer`,data:{docSha256:n,consentVersion:e.consentVersion,consentSha256:e.consentSha256,intent:!0},personal:ss(e.who)},{type:`signer.signed`,at:t,actor:`signer`,data:{docSha256:n,kind:r.kind,signatureSha256:r.sha256},personal:{name:r.typedName??e.signerName,...ss(e.who)}},{type:`envelope.completed`,at:t,actor:`system`,data:{docSha256:n}}]}function ds(e){let{at:t,docSha256:n,hasReason:r}=e;return[{type:`signer.declined`,at:t,actor:`signer`,data:{docSha256:n,hasReason:r,...cs(e.order)},personal:ss(e.who)},{type:`envelope.declined`,at:t,actor:`system`,data:{docSha256:n}}]}const fs=[`sent`,`in_progress`];function ps(e){let t=V(e).token;return typeof t==`string`&&t.length>0&&t.length<=200?t:null}const ms=e=>({...e.requestMeta?.ip?{ip:e.requestMeta.ip}:{},...e.requestMeta?.userAgent?{ua:e.requestMeta.userAgent}:{}});function hs(e){try{return e!==void 0&&new URL(e.url).searchParams.has(`token`)}catch{return!1}}function gs(e,t){let n=new Map,r,i={get:t=>{let r=n.get(t);return r||(r=e.kv.get(t),n.set(t,r)),r},set:async(e,t)=>{r={key:e,value:t}}},a=Date.now(),o=()=>Yt(i,t.requestMeta?.ip??`unknown`,a,{scope:`ceremony`,limit:20,windowSeconds:600,salt:`esign-ceremony/1`});return{async blocked(){return!(await o()).ok},async fail(){let t=await o();return t.ok&&r&&await e.kv.set(r.key,r.value),U(t.ok?`SIGNING_TOKEN_INVALID`:`RATE_LIMITED`)}}}async function _s(e,t){let{items:n}=await B(e).signers.query({where:{tokenHash:await O(t)},limit:1}),r=n[0];return r&&await ue(t,r.data.tokenHash)?r:null}async function vs(e,t){let{items:n}=await B(e).signers.query({where:{copyTokenHash:await O(t)},limit:1}),r=n[0];return r?.data.copyTokenHash&&await ue(t,r.data.copyTokenHash)?r:null}const ys=e=>!!(e.returnUrl&&e.clientId),bs=(e,t)=>ys(t)?e.settings.get(`integrationMasterKey`):Promise.resolve(void 0);async function xs(e,t,n){if(!t.returnUrl)return{};let r=await Xo(e,t,n);return{returnUrl:t.returnUrl,...r?{receipt:r}:{}}}const Ss=(e,t)=>e.find(e=>e.key===t)?.value;async function Cs(e,t){let n=await(t?e.settings.list():e.settings.list(`consent`)),r=(e,t)=>{let r=Ss(n,e);return typeof r==`string`&&r.length>0?r:t},i=r(`consentWording`,`I agree to use electronic records and an electronic signature for this document.`);return{version:r(`consentVersion`,`1`),wording:i,sha256:await F(i),masterKey:Ss(n,`integrationMasterKey`)}}const ws=(e,t)=>e.expiresAt!==null&&e.expiresAt<=t,Ts=(e,t)=>e.signerIds.length>1?t.order:void 0;async function Es(e,t,n,r,i){let a=B(e).audit_events,o=i;for(let e=0;e<2;e++){if(o??=await Bn(t,await Hn(a,t),r,n),await Un(a,o))return o;o=void 0}throw Error(`audit chain contention`)}async function Ds(e,t){if(hs(e.request))return U(`TOKEN_IN_QUERY`);let n=gs(t,e),r=ps(e.input);if(r===null)return n.fail();if(await n.blocked())return U(`RATE_LIMITED`);let i=V(e.input).open===!0,{envelopes:a,snapshots:o}=B(t),s=await _s(t,r),c=s?null:await vs(t,r),l=s??c;if(!l)return n.fail();let u=await a.get(l.data.envelopeId);if(!u)return U(`ENVELOPE_NOT_FOUND`);if(c&&u.status!==`completed`)return n.fail();if(!fs.includes(u.status)||l.data.status!==`pending`){let e={ok:!0,state:`closed`,status:u.status,title:u.title,...c?{}:await xs(l.data.envelopeId,u,await bs(t,u))};return u.status!==`completed`||l.data.status!==`signed`?e:u.pdfSha256?{...e,pdf:`ready`,download:await Ai(t,l.data.envelopeId,Date.now())}:{...e,pdf:`pending`}}let d=A();if(ws(u,d))return U(`SIGNING_TOKEN_EXPIRED`);let f=u.document,[p,m]=await Promise.all([u.snapshot?o.getMany(u.snapshot.ids):Promise.resolve(new Map),Cs(t,!1)]),h=f&&!u.snapshot?``:Or([...p.values()]);if(h===null)return U(`INTERNAL`);let g=u.status,_=Ts(u,l.data);if(i){let n=!1;if(u.status===`sent`&&(n=(await I(a,l.data.envelopeId,`sent`,`in_progress`,{updatedAt:d})).ok,n&&(g=`in_progress`)),_!==void 0&&(n=(await B(t).signers.updateIf(l.id,{where:{viewedAt:null},set:{viewedAt:d}})).applied),n){let n=ls(d,u.docSha256??``,ms(e),_);if(!(await Vn(B(t).audit_events,l.data.envelopeId,n,{salt:u.piiSalt})).ok)throw Error(`audit chain contention`)}}let{participant:v}=l.data;return{ok:!0,state:`ready`,envelope:{id:l.data.envelopeId,title:u.title,status:g,docSha256:u.docSha256,expiresAt:u.expiresAt},signer:{name:l.data.name,as:l.data.as,...v?{participant:v.name}:{}},snapshot:h,...f?{document:{kind:f.kind,name:f.name,bytes:f.bytes,pages:f.pages}}:{},...u.otp?{otp:l.data.otpVerifiedAt?`verified`:`required`}:{},...u.signerFields?.length?{fields:u.signerFields}:{},consent:{version:m.version,wording:m.wording,sha256:m.sha256}}}async function Os(e,t,n){if(hs(e.request))return U(`TOKEN_IN_QUERY`);let r=gs(t,e),i=ps(e.input);if(i===null)return r.fail();let a=is(e.input);if(!a.ok)return H(a.error);let{envelopes:o,signers:s,audit_events:c}=B(t),l=await _s(t,i);if(!l||l.data.status!==`pending`)return r.fail();let u=l.data.envelopeId,d=await o.get(u);if(!d)return U(`ENVELOPE_NOT_FOUND`);if(d.status===`sent`)return U(`SESSION_REQUIRED`);if(d.status!==`in_progress`||d.document&&!n)return U(`ENVELOPE_CLOSED`);let f=A();if(ws(d,f))return U(`SIGNING_TOKEN_EXPIRED`);if(d.otp&&!l.data.otpVerifiedAt)return U(`OTP_REQUIRED`);if(d.docSha256===null||a.value.docSha256!==d.docSha256)return H([{path:`docSha256`,code:`DOC_CHANGED`}]);let p=await Cs(t,ys(d));if(a.value.consentSha256!==p.sha256)return H([{path:`consentSha256`,code:`CONSENT_CHANGED`}]);let m=d.signerFields??[],h=a.value.fieldValues,g=[...Object.keys(h).filter(e=>!m.some(t=>t.key===e)).map(e=>({path:`fieldValues.${e}`,code:`INVALID_FIELDS`})),...m.filter(e=>e.required&&(h[e.key]??``).trim()===``).map(e=>({path:`fieldValues.${e.key}`,code:`INVALID_FIELDS`}))];if(g.length>0)return H(g);let _=await os(d.docSha256,a.value.signature,{fieldValues:h,salt:d.piiSalt}),v=ms(e),y={status:`signed`,signature:_,consentAt:f,consentVersion:p.version,consentSha256:p.sha256,signedAt:f,fieldValues:h,...v};if(d.signerIds.length>1)return n?n(t,{envelopeId:u,envelope:d,signer:l,set:y,now:f}):U(`ENVELOPE_CLOSED`);let b=us({at:f,docSha256:d.docSha256,consentVersion:p.version,consentSha256:p.sha256,signature:_,signerName:l.data.name,who:v}),x=await Bn(u,await Hn(c,u),b,d.piiSalt),S=await qn(d.docSha256,x.at(-1)?.data.hash??``),C=await I(o,u,d.status,`completed`,{completedAt:f,finalHash:S,updatedAt:f});if(!C.ok)return U(`ENVELOPE_CLOSED`);if(await s.updateIf(l.id,{where:{status:`pending`},set:y}),!await Un(c,x))throw Error(`audit chain contention`);return await xi(t.cron,u,Date.parse(f)),{ok:!0,status:`completed`,completedAt:f,...await xs(u,C.value,p.masterKey)}}async function ks(e,t){if(hs(e.request))return U(`TOKEN_IN_QUERY`);let n=gs(t,e),r=ps(e.input);if(r===null)return n.fail();let i=as(V(e.input).reason);if(i===null)return H([{path:`reason`,code:`INVALID_INPUT`}]);let{envelopes:a,signers:o}=B(t),s=await _s(t,r);if(!s||s.data.status!==`pending`)return n.fail();let c=s.data.envelopeId,l=await a.get(c);if(!l)return U(`ENVELOPE_NOT_FOUND`);if(!Qn(l.status,`declined`))return U(`ENVELOPE_CLOSED`);let u=A();if(ws(l,u))return U(`SIGNING_TOKEN_EXPIRED`);let d=await I(a,c,l.status,`declined`,{closedAt:u,updatedAt:u});if(!d.ok)return U(`ENVELOPE_CLOSED`);let f=ms(e);return await o.updateIf(s.id,{where:{status:`pending`},set:{status:`declined`,declinedAt:u,...i===void 0?{}:{declineReason:i},...f}}),await Es(t,c,l.piiSalt,ds({at:u,docSha256:l.docSha256,hasReason:i!==void 0,who:f,order:Ts(l,s.data)})),{ok:!0,status:`declined`,...await xs(c,d.value,await bs(t,d.value))}}const As=e=>(t,n)=>e(t,n),js=(e=>({"public/session":As(Ds),"public/submit":As((t,n)=>Os(t,n,e)),"public/decline":As(ks)}))();function Ms(e){try{return new URL(e.site.url).origin}catch{return}}async function Ns(e,t,n={}){let r=(n.now??Date.now)(),i=A(r),{envelopes:a,signers:o,snapshots:s,templates:c,nonces:l}=B(t),u=Yo(t),d=await nt({token:V(e).intent,now:r,getClient:u.getClient,consumeNonce:async(e,t,n)=>{let r=`${e}.${t}`;try{let t={nonce:r,cid:e,expiresAt:A(n*1e3)};return(await l.compareAndSet(r,null,t)).applied}catch(e){if(Li(e))return!1;throw e}},siteOrigin:Ms(t)});if(!d.ok)return U(d.error);let f=d.value,p=u.settings();if(f.replace===!0)return Is(t,f,i);let m=f.tplVersion===void 0?void 0:L(f.tpl,f.tplVersion),h=await c.getMany(m===void 0?[f.tpl]:[f.tpl,m]),g=h.get(f.tpl);if(!ar(g))return U(`TEMPLATE_NOT_FOUND`);let _=vr(g,m===void 0?void 0:h.get(m),f.tplVersion);if(!_.ok)return U(`TEMPLATE_NOT_FOUND`);let v=Nn(n.random),y=Cr(f,_.value,{now:i,piiSalt:v});if(!y.ok)return H(y.error);let b={delivery:y.value.delivery,signer:y.value.signer},x=f.resend===!0?(e,n,i)=>On(t,{signerId:e,envelope:n,token:i,senderSetting:p.senderName,now:r}):void 0,S=ce(n.random),C=await O(S),w=async e=>{let t=await Mr(f.cid,f.ref,e);return{id:t,sent:await kr(t,y.value,_.value,{now:i,tokenHash:C,expiryDays:Ii(p.expiryDays)})}},T=await w(1);if(!T.sent.ok)return Array.isArray(T.sent.error)?H(T.sent.error):U(`INTERNAL`);let ee=await a.compareAndSet(T.id,null,T.sent.value.envelope);if(!ee.applied){let e=await a.query({where:{clientId:f.cid,externalRef:f.ref},limit:100}),i=jr(e.items);if(i)return i.data.status===`draft`&&await sa(t.cron,i.id,r),Fs(o,i.id,i.data,b,n.random,x);let s=Math.max(e.items.length,1)+1;if(y.value.delivery===`email`){let e=await Mr(f.cid,f.ref,s);if(!(await a.compareAndSet(e,null,y.value)).applied){let t=await a.get(e);return t?Fs(o,e,t,b,n.random):U(`INTERNAL`)}return await sa(t.cron,e,r),$(e,y.value,void 0)}if(T=await w(s),!T.sent.ok)return Array.isArray(T.sent.error)?H(T.sent.error):U(`INTERNAL`);if(ee=await a.compareAndSet(T.id,null,T.sent.value.envelope),!ee.applied){let e=await a.get(T.id);return e?Fs(o,T.id,e,b,n.random):U(`INTERNAL`)}}let{id:te,sent:E}=T;if(!E.ok)return U(`INTERNAL`);await s.putMany(E.value.chunks);let ne=await zi(o,E.value.signer,S,n.random);E.value.envelope.delivery===`email`&&await On(t,{signerId:E.value.signer.id,envelope:E.value.envelope,token:ne,senderSetting:p.senderName,now:r});let D=[Nr(y.value,`integration`),Pr(E.value.envelope,`integration`)];return await B(t).audit_events.putMany(await zn(te,D,v)),$(te,E.value.envelope,ne)}function $(e,t,n,r=t.delivery===`inline`){return{ok:!0,envelopeId:e,status:t.status,...n!==void 0&&r?{signingToken:n}:{}}}function Ps(e,t){let n=e.signer;return n.email===t.email&&n.as===t.as&&(n.participant?.name??null)===(t.participant?.name??null)}async function Fs(e,t,n,r,i,a){let o=n.signerIds[0],s=(n.status===`sent`||n.status===`in_progress`)&&Ps(n,r.signer),c=r.delivery===`inline`&&s,l=a!==void 0&&r.delivery===`email`&&n.delivery===`email`&&s;if(!c&&!l||o===void 0)return $(t,n,void 0);let u=await Ri(ce(i),i,t=>e.updateIf(o,{where:{status:`pending`},set:{tokenHash:t}}));if(!u.value.applied)return $(t,n,void 0);if(c||!a)return $(t,n,u.token,!0);let d=await a(o,n,u.token);return{...$(t,n,void 0),...d?{resent:!0}:{}}}async function Is(e,t,n){let{envelopes:r}=B(e),i=jr((await r.query({where:{clientId:t.cid,externalRef:t.ref},limit:100})).items);if(!i)return{ok:!0,status:`none`};let a=i.data.signer;if(a.name===t.signer.name.trim()&&a.email===t.signer.email.trim().toLowerCase()&&a.as===(t.as??`self`)&&(a.participant?.name??null)===(t.participant?.name.trim()??null)||i.data.status===`completed`)return $(i.id,i.data,void 0);let o=await I(r,i.id,i.data.status,`voided`,{closedAt:n,updatedAt:n});return o.ok?(await Hi(e,i.id,o.value,{type:`envelope.voided`,at:n,actor:`integration`}),$(i.id,o.value,void 0)):U(`ENVELOPE_CLOSED`)}const Ls=(e,t)=>Ns(e.input,t),Rs=64*1024,zs=[{name:`public/envelopes/from-intent`,methods:[`POST`],body:`json`,maxBytes:16*1024},{name:`public/session`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/otp/send`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/otp/verify`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/submit`,methods:[`POST`],body:`json`,maxBytes:256*1024},{name:`public/decline`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/download`,methods:[`GET`],body:`none`,response:`raw`},{name:`public/verify`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/receipts/lookup`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/templates/catalog`,methods:[`POST`],body:`json`,maxBytes:Rs},{name:`public/self-serve/start`,methods:[`POST`],body:`json`,maxBytes:Rs}];async function Bs(){return D({code:`NOT_FOUND`}).body}function Vs(e={}){let t={};for(let n of zs)t[n.name]={public:!0,methods:[...n.methods],request:n.maxBytes===void 0?{body:n.body}:{body:n.body,maxBytes:n.maxBytes},...n.response?{response:n.response}:{},handler:e[n.name]??Bs};return t}const Hs=e=>Number(/_(\d+)$/.exec(e)?.[1]??0);function Us(e){let t;for(let n of e)(!t||Hs(n.id)>Hs(t.id)||Hs(n.id)===Hs(t.id)&&n.data.createdAt>t.data.createdAt)&&(t=n);return t}async function Ws(e,t,n=Date.now()){let r=Yo(t),i=await it({token:V(e).request,now:n,getClient:r.getClient});if(!i.ok)return U(i.error);let{cid:a,ref:o}=i.value,s=Us((await B(t).envelopes.query({where:{clientId:a,externalRef:o},limit:100})).items.filter(e=>e.data.clientId===a&&e.data.externalRef===o));if(!s)return{ok:!0,state:`none`,receipt:null};if(!$n(s.data.status))return{ok:!0,state:`pending`,receipt:null};let c=await Xo(s.id,s.data,r.settings().integrationMasterKey);return c?{ok:!0,state:`terminal`,receipt:c}:U(`INTERNAL`)}const Gs=(e,t)=>Ws(e.input,t),Ks=/^[0-9a-f]{64}$/,qs=async(e,t)=>{let n=V(e.input).sha256,r=typeof n==`string`?n.toLowerCase():``;if(!Ks.test(r))return H([{path:`sha256`,code:`invalid`}]);if(!(await Yt({get:e=>t.kv.get(e),set:(e,n)=>t.kv.set(e,n)},e.requestMeta?.ip??`unknown`,Date.now(),{scope:`esign-verify`,limit:20,windowSeconds:600,salt:`esign-verify/1`})).ok)return U(`RATE_LIMITED`);let{envelopes:i,audit_events:a}=B(t),o=(await i.query({where:{pdfSha256:r},limit:1})).items[0];if(!o||o.data.status!==`completed`)return{ok:!0,matched:!1};let s=o.data,{items:c}=await a.query({where:{envelopeId:o.id},orderBy:{seq:`asc`},limit:101}),l=null;if(c.length<=100){let e=c.map(e=>e.data),t=await Gn(o.id,e);l=t.ok&&s.docSha256!==null&&e.at(-1)?.type===`envelope.completed`&&await qn(s.docSha256,t.value.head)===s.finalHash}return{ok:!0,matched:!0,status:s.status,completedAt:s.completedAt,finalHash:s.finalHash,chainVerified:l}},Js=[{name:Cn,schedule:`* * * * *`},{name:da,schedule:`0 * * * *`},{name:ha,schedule:`23 3 * * *`},{name:ta,schedule:`17 * * * *`}],Ys=Vs({"public/envelopes/from-intent":Ls,"public/download":Ni,"public/verify":qs,"public/receipts/lookup":Gs,"public/templates/catalog":Qo,...js}),Xs={hooks:{"plugin:activate":async(e,t)=>{await en(t,Js)},cron:async(e,t)=>{await nn(e,t,Js,Date.now())||await An(e,t)||await ea(e,t)||await ua(e,t)||await ma(e,t)||await Da(e,t)||await ra(e,t)||await Ci(e,t)}},routes:{...Ys,...Uo,...Ka,...Yi,admin:an(Uo.admin,rn),"templates/create":an(Ka[`templates/create`]),"public/verify":an(Ys[`public/verify`])}};export{Xs as default};
|
|
36
|
+
`),0)}const oi=262144/4*3,si={self:`Self`,guardian:`Parent or guardian`,buyer:`Buyer`},ci=e=>e?`${e.slice(0,10)} ${e.slice(11,19)} UTC`:``;function li(e){return e.map(e=>{switch(e.type){case`text`:case`code`:return e.text;case`break`:return`
|
|
37
|
+
`;case`link`:{let t=li(e.children);return t===e.href?t:`${t} (${e.href})`}default:return li(e.children)}}).join(``)}function ui(e){let t=[],n=(e,r)=>{for(let i of e)switch(i.type){case`heading`:t.push({type:`heading`,text:li(i.children),level:Math.min(i.level,3)});break;case`paragraph`:t.push({type:`paragraph`,text:li(i.children),...r?{font:`italic`}:{}});break;case`list`:i.items.forEach((e,n)=>{let a=i.ordered?`${(i.start??1)+n}.`:`•`;t.push({type:`paragraph`,text:`${a} ${li(e)}`,...r?{font:`italic`}:{}})});break;case`quote`:n(i.children,!0);break;case`code`:t.push({type:`paragraph`,text:i.text,size:9});break;case`rule`:t.push({type:`rule`});break}};return n(ai(e),!1),t}function di(e){let t=e.signature,n=[e.name,`Signed ${ci(e.signedAt)}`];return t?.kind===`drawn`&&t.strokes?{type:`signature`,label:`Signature`,strokes:{v:1,w:1,h:1,strokes:t.strokes},caption:t.typedName?[t.typedName,...n]:n}:{type:`signature`,label:`Signature`,typedName:t?.typedName??e.name,caption:n}}function fi(e,t,n){let r=e.envelope.signerFields??[];if(r.length===0)return[];let i=t.fieldValues??{};return[{type:`spacer`,height:12},{type:`heading`,text:`Details entered by ${n?t.name:`the signer`}`,level:2},{type:`table`,columns:[{header:`Field`},{header:`Value`,width:2}],rows:r.map(e=>[e.label,i[e.key]??``])}]}function pi(e){let{envelope:t,signers:n,events:r,head:i,envelopeId:a}=e,o=n.length>1,s=[[`Envelope`,a],[`Document`,t.title],[`Document SHA-256`,t.docSha256??``],...n.flatMap((e,t)=>[[o?`Signer ${t+1}`:`Signer`,e.name],[`Signing as`,si[e.as]??e.as],...e.participant?[[`Participant`,e.participant.name]]:[],[`Signature`,e.signature?.kind===`drawn`?`Drawn`:`Typed`],[`Signature SHA-256`,e.signature?.sha256??``],[`Consent version`,e.consentVersion??``],...e.consentSha256?[[`Consent wording SHA-256`,e.consentSha256]]:[],...e.otpVerifiedAt?[[`Identity check`,`Email one-time code verified`]]:[],[`Signed`,ci(e.signedAt)]]),[`Completed`,ci(t.completedAt)],[`Audit events`,String(r.length)]],c=r.map(e=>[String(e.seq+1),ci(e.at),e.type,typeof e.data.signer==`number`?`signer ${e.data.signer}`:e.actor,e.personal?.ip??``,e.hash.slice(0,16)]);return{info:{title:t.title,subject:`Signed document and certificate of completion`,creator:`semics e-sign`,...t.completedAt?{creationDate:new Date(t.completedAt)}:{}},footer:{text:`Envelope ${a}`,pageNumbers:!0},blocks:[{type:`heading`,text:t.title,level:1},...ui(e.snapshot),...n.flatMap(t=>[...fi(e,t,o),{type:`spacer`,height:18},di(t)]),{type:`pageBreak`},{type:`heading`,text:`Certificate of completion`,level:1},{type:`paragraph`,text:`This certificate records how the document above was signed. It was signed with a simple electronic signature: the signer consented to sign electronically, confirmed their intent to sign, and signed the exact text identified by the document SHA-256 below. Every step is recorded in a hash-chained audit trail; the final hash binds the document to the end of that trail. Anyone holding this PDF can check these values on the verify page.`},{type:`spacer`,height:8},{type:`table`,columns:[{header:`Field`},{header:`Value`,width:3}],rows:s},{type:`spacer`,height:8},{type:`heading`,text:`Audit trail`,level:2},{type:`table`,columns:[{header:`#`,width:.4},{header:`Time`,width:1.6},{header:`Event`,width:1.6},{header:`Actor`,width:.8},{header:`IP address`,width:1.2},{header:`Event hash (first 16)`,width:1.6}],rows:c,size:8},{type:`spacer`,height:8},{type:`paragraph`,text:`Audit chain head`,font:`bold`,size:9},{type:`paragraph`,text:i,size:9},{type:`paragraph`,text:`Final hash`,font:`bold`,size:9},{type:`paragraph`,text:t.finalHash??``,size:9}]}}async function mi(e){let t=Jt(pi(e));return{bytes:t,sha256:await P(t)}}const L=new TextEncoder().encode(`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`);function hi(e){let t=new Uint8Array(Math.ceil(e.length/3)*4),n=e.length-e.length%3,r=0;for(let i=0;i<n;i+=3){let n=e[i]<<16|e[i+1]<<8|e[i+2];t[r++]=L[n>>18],t[r++]=L[n>>12&63],t[r++]=L[n>>6&63],t[r++]=L[n&63]}if(n<e.length){let i=n+1<e.length,a=e[n]<<16|(i?e[n+1]<<8:0);t[r++]=L[a>>18],t[r++]=L[a>>12&63],t[r++]=i?L[a>>6&63]:61,t[r++]=61}return new TextDecoder().decode(t)}function gi(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}catch{return null}}const _i=(e,t,n)=>`${e}:pdf:${t.slice(0,16)}:${n}`;function vi(e,t,n){let r=Math.max(1,Math.ceil(t.length/oi));return Array.from({length:r},(i,a)=>({id:_i(e,n,a),data:{envelopeId:e,kind:`signed-pdf`,contentType:`application/pdf`,index:a,count:r,bytes:t.length,sha256:n,data:hi(t.subarray(a*oi,(a+1)*oi))}}))}function yi(e){let t=e[0];if(!t||e.length!==t.count)return null;let n=[...e].sort((e,t)=>e.index-t.index),r=new Uint8Array(t.bytes),i=0;for(let[e,a]of n.entries()){if(a.index!==e||a.sha256!==t.sha256||a.bytes!==t.bytes)return null;let n=gi(a.data);if(!n||i+n.length>r.length)return null;r.set(n,i),i+=n.length}return i===r.length?r:null}const bi=`signed-pdf-`,xi=e=>`${bi}${e}`;function Si(e,t,n,r=0){return e?.schedule(xi(t),{schedule:A(n),data:{envelopeId:t,attempt:r}})}async function Ci(e,t,n){let{envelopes:r,signers:i,snapshots:a,audit_events:o,artifacts:s}=z(e),c=await r.get(t);if(!c||c.status!==`completed`||c.pdfSha256||c.personalPurgedAt||c.signerIds.length===0||!c.snapshot||!c.docSha256)return`skipped`;let[l,u,d]=await Promise.all([i.getMany(c.signerIds),a.getMany(c.snapshot.ids),o.query({where:{envelopeId:t},orderBy:{seq:`asc`},limit:100})]),f=kr([...u.values()]),p=d.items.map(e=>e.data),m=await Kn(t,p),h=m.ok&&p.at(-1)?.type===`envelope.completed`&&await Jn(c.docSha256,m.value.head)===c.finalHash,g=c.signerIds.map(e=>l.get(e));if(g.some(e=>e?.status!==`signed`)||f===null||!m.ok||!h){let r=n.attempt??0;return r+1>=5?(e.log.error(`signed PDF not generated: the envelope never settled`,{envelopeId:t}),`gave-up`):(await Si(e.cron,t,n.now+6e4,r+1),`retry`)}let{bytes:_,sha256:v}=await mi({envelopeId:t,envelope:c,signers:g,snapshot:f,events:p,head:m.value.head}),y=vi(t,_,v);return await s.putMany(y),(await r.updateIf(t,{where:{status:`completed`,pdfSha256:null},set:{pdfSha256:v,pdf:{ids:y.map(e=>e.id),bytes:_.length},updatedAt:A(n.now)}})).applied?(await $i(e.cron,t,n.now),`stored`):`skipped`}async function wi(e,t){if(!e.name.startsWith(bi))return!1;let n=e.data?.envelopeId,r=e.data?.attempt;return typeof n!=`string`||n.length===0||await Ci(t,n,{now:Date.now(),attempt:typeof r==`number`&&Number.isSafeInteger(r)?r:0}),!0}const Ti=`esign/download`,Ei=`esign:download-link-key`,Di=/^[A-Za-z0-9_:.-]{1,200}$/,Oi=RegExp(`^[0-9a-f]{64}$`);function ki(e){return typeof e!=`string`||!Oi.test(e)?null:Uint8Array.from(e.match(/../g),e=>Number.parseInt(e,16))}async function Ai(e){let t=ki(await e.get(Ei));if(t)return t;let n=crypto.getRandomValues(new Uint8Array(32));if((await e.compareAndSet(Ei,null,S(n))).applied)return n;let r=ki(await e.get(Ei));if(!r)throw Error(`download link key unavailable`);return r}async function ji(e,t,n){let r=await me({secret:await Ai(e.kv),purpose:Ti,params:{e:t},now:n,ttlMs:9e5}),i=A(Number(r.get(`exp`))*1e3);return{url:`/_emdash/api/plugins/${e.plugin.id}/public/download?${r}`,expiresAt:i}}function R(e){let{status:t,body:n}=D(e);return Ir({status:t,headers:{"content-type":`application/json; charset=utf-8`,"cache-control":`no-store`},body:{kind:`text`,value:JSON.stringify(n)}})}function Mi(e){try{return e?.url?new URL(e.url).searchParams:null}catch{return null}}async function Ni(e,t){let n=Mi(e.request);if(!n)return R(`TOKEN_INVALID`);if(n.has(`token`))return R(`TOKEN_IN_QUERY`);let r=Date.now(),i=await he({secret:await Ai(t.kv),purpose:Ti,query:n,now:r});if(!i.ok)return R(i.error);let a=i.value.e;if(typeof a!=`string`||!Di.test(a))return R(`TOKEN_INVALID`);let{envelopes:o,artifacts:s}=z(t),c=await o.get(a);if(!c||c.status!==`completed`||c.recordsPurgedAt)return R(`ENVELOPE_NOT_FOUND`);if(!c.pdfSha256||!c.pdf)return await Si(t.cron,a,r),R(`SIGNED_PDF_PENDING`);let l=yi([...(await s.getMany(c.pdf.ids)).values()]);return!l||await P(l)!==c.pdfSha256?(t.log.error(`signed PDF chunks do not match pdfSha256`,{envelopeId:a}),R(`INTERNAL`)):Ir({status:200,headers:{"content-type":`application/pdf`,"content-disposition":`attachment; filename="signed-${a.replace(/[^A-Za-z0-9_-]/g,`_`)}.pdf"`,"cache-control":`private, no-store`,"x-content-type-options":`nosniff`,"referrer-policy":`no-referrer`},body:{kind:`bytes`,value:l}})}const Pi=(e,t)=>Ni(e,t),Fi=e=>typeof e.user?.id==`string`&&e.user.id.length>0?e.user.id:void 0,z=e=>e.storage,B=e=>typeof e==`object`&&e?e:{},V=e=>({...D(`BAD_REQUEST`).body,...e?{issues:e}:{}}),H=e=>D(e).body;function Ii(e){let t=B(e).id;return typeof t==`string`&&t.length>0&&t.length<=200?t:null}function Li(e){return Number.isSafeInteger(e)&&e>=1&&e<=365?e:30}function Ri(e){return e instanceof Error&&e.message.includes(`UNIQUE constraint failed`)}async function zi(e,t,n){let r=e;for(let e=1;;e++)try{return{token:r,value:await n(await O(r))}}catch(n){if(!Ri(n)||e>=3)throw n;r=ce(t)}}async function Bi(e,t,n,r){let{token:i}=await zi(n,r,n=>e.put(t.id,{...t.data,tokenHash:n}));return i}const Vi=(e,{piiSalt:t,...n})=>({id:e,...n}),Hi=(e,{snapshot:t,fieldValues:n,piiSalt:r,...i})=>({id:e,...i});async function Ui(e,t,n,r){if(!(await Hn(z(e).audit_events,t,r,{salt:n.piiSalt})).ok)throw Error(`audit chain contention`)}async function Wi(e,t){let n=vr(e.input);if(!n.ok)return V(n.error);let{templateId:r,templateVersion:i}=n.value,{templates:a,envelopes:o,audit_events:s}=z(t),c=await a.getMany(i===void 0?[r]:[r,I(r,i)]),l=yr(c.get(r),i===void 0?void 0:c.get(I(r,i)),i);if(!l.ok)return H(`TEMPLATE_NOT_FOUND`);let u=Pn(),d=Cr(n.value,l.value,{now:A(),piiSalt:u});if(!d.ok)return V(d.error);let f=crypto.randomUUID();return await o.put(f,d.value),await s.putMany(await Bn(f,[Pr(d.value,`admin`,Fi(e))],u)),{ok:!0,envelope:Vi(f,d.value)}}async function Gi(e,t){let n=Ii(e.input);if(!n)return V();let{envelopes:r,templates:i,snapshots:a,signers:o}=z(t),s=await r.get(n);if(!s)return H(`ENVELOPE_NOT_FOUND`);if(!$n(s.status,`sent`))return H(`ENVELOPE_CLOSED`);let{templateId:c,templateVersion:l}=s,[u,d]=await Promise.all([i.getMany([c,I(c,l)]),t.settings.list()]),f=Object.fromEntries(d.map(e=>[e.key,e.value])),p=yr(u.get(c),u.get(I(c,l)),l);if(!p.ok)return H(`TEMPLATE_NOT_FOUND`);let m=ce(),h=await Ar(n,{...s,...await void 0},p.value,{now:A(),tokenHash:await O(m),expiryDays:Li(f.expiryDays)});if(!h.ok)return Array.isArray(h.error)?V(h.error):H(`ENVELOPE_CLOSED`);await a.putMany(h.value.chunks);let g=await F(r,n,`draft`,`sent`,h.value.envelope);if(!g.ok)return H(`ENVELOPE_CLOSED`);let _=await Bi(o,h.value.signer,m),v=await kn(t,{signerId:h.value.signer.id,envelope:g.value,token:_,senderSetting:f.senderName,now:Date.now()});return await Ui(t,n,g.value,Fr(g.value,`admin`,Fi(e))),{ok:!0,envelope:Vi(n,g.value),...v?{}:{invitation:`SITE_URL_MISSING`}}}async function Ki(e,t){let n=Ii(e.input);if(!n)return V();let{envelopes:r,snapshots:i,signers:a}=z(t),o=await r.get(n);if(!o)return H(`ENVELOPE_NOT_FOUND`);let[s,c]=await Promise.all([o.snapshot?i.getMany(o.snapshot.ids):Promise.resolve(new Map),o.signerIds.length>0?a.getMany(o.signerIds):Promise.resolve(new Map)]),l=o.pdfSha256?await ji(t,n,Date.now()):null;return{ok:!0,envelope:Vi(n,o),download:l,snapshot:o.snapshot?kr([...s.values()]):null,signers:[...c].map(([e,t])=>({id:e,order:t.order,name:t.name,email:t.email,status:t.status}))}}async function qi(e,t){let n=Ii(e.input);if(!n)return V();let{envelopes:r,signers:i,outbox:a,audit_events:o}=z(t),s=await r.get(n);if(!s)return H(`ENVELOPE_NOT_FOUND`);let c=s.signerIds[0];if(s.status!==`sent`||c===void 0)return H(`ENVELOPE_CLOSED`);if(!En(t))return{ok:!1,error:{code:`SITE_URL_MISSING`,message:On}};let l=In(n,0),u=In(n,1),[d,f,p]=await Promise.all([t.settings.get(`senderName`),a.get(`invite-${c}`),o.getMany([l,u])]);if(f&&f.status!==`failed`)return{ok:!1,error:{code:`INVITATION_QUEUED`,message:`The invitation is already queued or sent.`}};let m=await zi(ce(),void 0,e=>i.updateIf(c,{where:{status:`pending`},set:{tokenHash:e}}));if(!m.value.applied)return H(`ENVELOPE_CLOSED`);await kn(t,{signerId:c,envelope:s,token:m.token,senderSetting:d,now:Date.now()});let h=!1;p.has(u)||(h=await Wn(o,await Vn(n,p.get(l)??null,[Fr(s,`admin`,Fi(e))],s.piiSalt)));let{name:g,email:_,status:v}=m.value.data;return{ok:!0,envelope:Vi(n,s),signers:[{id:c,order:m.value.data.order,name:g,email:_,status:v}],repaired:h}}async function Ji(e,t){let n=Ii(e.input);if(!n)return V();let r=await z(t).envelopes.get(n);if(!r)return H(`ENVELOPE_NOT_FOUND`);let i=A(),a=await F(z(t).envelopes,n,r.status,`voided`,{closedAt:i,updatedAt:i});return a.ok?(await Ui(t,n,a.value,{type:`envelope.voided`,at:i,actor:`admin`,...Fi(e)?{data:{userId:Fi(e)}}:{}}),{ok:!0,envelope:Vi(n,a.value)}):H(`ENVELOPE_CLOSED`)}async function Yi(e,t){let{status:n,cursor:r}=B(e.input);if(n!==void 0&&!Qn(n)||r!==void 0&&!(typeof r==`string`&&r.length>0&&r.length<=500))return V();let i=await z(t).envelopes.query({...n===void 0?{}:{where:{status:n}},orderBy:{createdAt:`desc`},limit:100,...r===void 0?{}:{cursor:r}});return{ok:!0,envelopes:i.items.map(e=>Hi(e.id,e.data)),...i.hasMore&&i.cursor?{nextCursor:i.cursor}:{}}}const Xi={"envelopes/create":{handler:Wi},"envelopes/send":{handler:Gi},"envelopes/get":{handler:Ki},"envelopes/list":{handler:Yi},"envelopes/resend":{handler:qi},"envelopes/void":{handler:Ji},"outbox/status":{handler:(async(e,t)=>({ok:!0,...await Mn(t)}))}},Zi=`completion-email-`,Qi=e=>`${Zi}${e}`;function $i(e,t,n){return e?.schedule(Qi(t),{schedule:A(n),data:{envelopeId:t}})}async function ea(e,t,n){let[r,i,a]=await Promise.all([z(e).envelopes.get(t),e.settings.get(`senderName`),z(e).outbox.get(`complete-${t}`)]);if(!r||r.status!==`completed`||!r.pdfSha256||a)return!1;let o=r.signerIds[0];if(o===void 0||!En(e))return!1;let s=await zi(ce(),void 0,t=>z(e).signers.updateIf(o,{where:{status:`signed`},set:{copyTokenHash:t}}));return s.value.applied?(await An(e,{envelopeId:t,envelope:r,token:s.token,senderSetting:i,now:n}),!0):!1}async function ta(e,t){if(!e.name.startsWith(Zi))return!1;let n=e.data?.envelopeId;return typeof n==`string`&&n.length>0&&await ea(t,n,Date.now()),!0}const na=`expire`,ra=`expire-more`;async function ia(e,t){if(e.name!==na&&e.name!==ra)return!1;let{envelopes:n}=z(t),r=A(),i=await n.query({where:{status:{in:[`sent`,`in_progress`]},expiresAt:{lt:r}},orderBy:{expiresAt:`asc`},limit:2});for(let{id:e,data:a}of i.items){let i=await F(n,e,a.status,`expired`,{closedAt:r,updatedAt:r});i.ok&&await Ui(t,e,i.value,{type:`envelope.expired`,at:r,actor:`system`})}return i.hasMore&&await t.cron?.schedule(ra,{schedule:A(Date.now()+6e4)}),!0}function U(e){if(typeof e!=`string`)return null;let t=new TextEncoder().encode(e.trim());return t.length>=32?t:null}const aa=`intent-finish-`,oa=e=>`${aa}${e}`;function sa(e,t,n){return e?.schedule(oa(t),{schedule:A(n),data:{envelopeId:t}})}async function ca(e,t){let n=await C(e),r=await crypto.subtle.sign(`HMAC`,n,new TextEncoder().encode(`esign-invite/1.${t}`));return x(new Uint8Array(r))}async function la(e,t,n){let{envelopes:r,templates:i,snapshots:a,signers:o,audit_events:s}=z(e),c=await r.get(t);if(!c||c.status!==`draft`||c.delivery!==`email`||!c.clientId)return`skipped`;let l=I(c.templateId,c.templateVersion),[u,d]=await Promise.all([i.getMany([c.templateId,l]),e.settings.list()]),f=Object.fromEntries(d.map(e=>[e.key,e.value])),p=yr(u.get(c.templateId),u.get(l),c.templateVersion);if(!p.ok)return`skipped`;let m=U(f.integrationMasterKey);if(!m)return`skipped`;let h=await ca(m,t),g=await Ar(t,c,p.value,{now:A(n),tokenHash:await O(h),expiryDays:Li(f.expiryDays)});if(!g.ok)return`skipped`;await a.putMany(g.value.chunks);let _=await Bi(o,g.value.signer,h);await kn(e,{signerId:g.value.signer.id,envelope:g.value.envelope,token:_,senderSetting:f.senderName,now:n});let v=[Pr(c,`integration`),Fr(g.value.envelope,`integration`)];return await s.putMany(await Bn(t,v,c.piiSalt)),(await F(r,t,`draft`,`sent`,g.value.envelope)).ok?`sent`:`skipped`}async function ua(e,t){if(!e.name.startsWith(aa))return!1;let n=e.data?.envelopeId;return typeof n==`string`&&n.length>0&&await la(t,n,Date.now()),!0}const da=`nonce-sweep`,fa=`nonce-sweep-more`;async function pa(e){let{nonces:t,cron:n,now:r,page:i=100,pages:a=3}=e,o=A(r),s=0,c=!1;for(let e=0;e<a;e++){let e=await t.query({where:{expiresAt:{lt:o}},orderBy:{expiresAt:`asc`},limit:i});if(e.items.length===0||(s+=await t.deleteMany(e.items.map(e=>e.id)),c=e.hasMore===!0,!c))break}return c&&await n?.schedule(fa,{schedule:A(r+6e4)}),{deleted:s,more:c}}async function ma(e,t){if(e.name!==da&&e.name!==fa)return!1;let n=t.storage.nonces;return await pa({nonces:n,cron:t.cron,now:Date.now()}),!0}const ha=`retention`,ga=`retention-more`,_a=`cron:retention`,va=e=>e.status===`sent`||e.status===`in_progress`,ya=e=>va(e)?null:Date.parse(e.completedAt??e.closedAt??e.updatedAt),ba=(e,t,n,r)=>{let i=e.find(e=>e.key===t)?.value;return typeof i==`number`&&Number.isFinite(i)?Math.min(r,Math.max(1,Math.round(i))):n};function xa(e,t){let n=new Date(t);n.setUTCMonth(n.getUTCMonth()-ba(e,`retentionPersonalDataMonths`,12,120));let r=new Date(t);return r.setUTCFullYear(r.getUTCFullYear()-ba(e,`retentionSignedRecordsYears`,7,50)),{p:Math.max(n.getTime(),r.getTime()),r:r.getTime()}}function Sa(e,t){let{name:n,email:r,ip:i,ua:a,signature:o,fieldValues:s,declineReason:c,copyTokenHash:l,participant:u,...d}=t;return{...d,name:``,email:``,tokenHash:`purged:${e}`,...o?{signature:{kind:o.kind,sha256:o.sha256}}:{}}}function Ca(e,t){let{piiSalt:n,returnUrl:r,signerEmail:i,...a}=e;return{...a,signer:{name:``,email:``,as:e.signer.as},fieldValues:{},personalPurgedAt:t}}async function wa(e,t,n){let r=new Set(t.filter(e=>e.data.status===`draft`).map(e=>e.id)),i=await e.audit_events.query({where:{envelopeId:{in:t.map(e=>e.id)}},limit:100,...n?{cursor:n}:{}}),a=i.items.filter(e=>!r.has(e.data.envelopeId)&&e.data.personal!==null),o=i.items.filter(e=>r.has(e.data.envelopeId)).map(e=>e.id);return a.length>0&&await e.audit_events.putMany(a.map(e=>({id:e.id,data:qn(e.data)}))),o.length>0&&await e.audit_events.deleteMany(o),i.hasMore?i.cursor:void 0}async function Ta(e,t,n){let r=A(n),i=t.filter(e=>e.data.status!==`draft`),a=i.flatMap(e=>e.data.signerIds),o=a.length>0?await e.signers.getMany(a):new Map,s=a.flatMap(e=>{let t=o.get(e);return t?[{id:e,data:Sa(e,t)}]:[]});s.length>0&&await e.signers.putMany(s),i.length>0&&await e.envelopes.putMany(i.map(e=>({id:e.id,data:Ca(e.data,r)})));let c=t.filter(e=>e.data.status===`draft`).map(e=>e.id);c.length>0&&await e.envelopes.deleteMany(c)}async function Ea(e,t){let n=z(e),r={...await e.kv.get(_a)},i=!1;if(!r.phase||r.phase===`rl`)(await Zt(e.kv,t,3)).more?r.phase=`rl`:Object.assign(r,xa(await e.settings.list(`retention`),t),{phase:`personal`});else if(r.phase===`outbox`){let e=await n.outbox.query({where:{status:{in:[`sent`,`failed`]},nextAttemptAt:{lt:r.p}},limit:100});e.items.length>0&&await n.outbox.deleteMany(e.items.map(e=>e.id)),i=!e.hasMore}else{let e=r.phase===`personal`,i=e?r.p:r.r,a=await n.envelopes.query({where:{createdAt:{gte:(e?r.pf:r.rf)??``,lt:A(i)}},limit:10,...r.cursor?{cursor:r.cursor}:{}}),o=t=>e?t.personalPurgedAt:t.recordsPurgedAt,s=a.items.filter(({data:e})=>!o(e)&&(ya(e)??i)<i),c=s.length===0;if(!r.step&&s.length>0){if(e)r.acursor=await wa(n,s,r.acursor);else{let e=await n.audit_events.query({where:{envelopeId:{in:s.map(e=>e.id)}},limit:100});if(e.items.length>0&&await n.audit_events.deleteMany(e.items.map(e=>e.id)),e.hasMore)r.acursor=`more`;else{delete r.acursor;let e=s.flatMap(e=>e.data.pdf?.ids??[]),t=s.flatMap(e=>e.data.snapshot?.ids??[]);e.length>0&&await n.artifacts.deleteMany(e),t.length>0&&await n.snapshots.deleteMany(t)}}r.acursor||(r.step=1)}else if(s.length>0){if(e)await Ta(n,s,t);else{let e=s.flatMap(e=>e.data.signerIds);e.length>0&&await n.signers.deleteMany(e);let r=A(t);await n.envelopes.putMany(s.map(({id:e,data:t})=>({id:e,data:{...t,title:``,signerIds:[],snapshot:null,pdf:null,pdfSha256:null,recordsPurgedAt:r}})))}c=!0}if(c){delete r.step;for(let{data:e}of a.items)!o(e)&&!s.some(t=>t.data===e)&&(!r.keep||e.createdAt<r.keep)&&(r.keep=e.createdAt);a.hasMore&&a.cursor?r.cursor=a.cursor:(r[e?`pf`:`rf`]=r.keep??A(i),delete r.cursor,delete r.keep,r.phase=e?`records`:`outbox`)}}return i&&delete r.phase,await e.kv.set(_a,r),i||await e.cron?.schedule(ga,{schedule:A(t)}),i}async function Da(e,t,n=Date.now()){return e.name!==ha&&e.name!==ga?!1:(await Ea(t,n),!0)}const Oa=e=>va(e)||e.status===`completed`&&!e.pdfSha256;async function ka(e,t){let n=z(e),r;if(t.includes(`@`)){let e=t.toLowerCase(),[i,a]=await Promise.all([n.signers.query({where:{email:e},limit:10}),n.envelopes.query({where:{signerEmail:e},limit:10})]),o=new Map(a.items.map(e=>[e.id,e.data])),s=[...new Set(i.items.map(e=>e.data.envelopeId))].filter(e=>!o.has(e));if(s.length>0)for(let[e,t]of await n.envelopes.getMany(s))o.set(e,t);r=[...o].slice(0,10).map(([e,t])=>({id:e,data:t}))}else{let e=await n.envelopes.get(t);r=e?[{id:t,data:e}]:[]}return{due:r.filter(e=>!Oa(e.data)&&!e.data.personalPurgedAt),open:r.filter(e=>Oa(e.data)).length}}async function Aa(e,t,n){let r=z(e),i=await wa(r,t.due);if(i&&=await wa(r,t.due,i),i)throw Error(`audit trail too long for one request`);await Ta(r,t.due,n),await r.outbox.deleteMany(t.due.flatMap(e=>[`complete-${e.id}`,...e.data.signerIds.map(e=>`invite-${e}`)]))}const ja=new Set([`localhost`,`127.0.0.1`,`[::1]`]);function Ma(e=b){return x(e(32))}const Na=e=>U(e)===null;function Pa(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(e===``)continue;let r;try{r=new URL(e)}catch{return{ok:!1,entry:e}}if(!(r.protocol===`https:`||r.protocol===`http:`&&ja.has(r.hostname))||r.username||r.password||e.includes(`#`)||e.includes(`?`))return{ok:!1,entry:e};t.push(r.href)}return t.length>10?{ok:!1,entry:`too many entries`}:{ok:!0,entries:t}}async function Fa(e,t,n){let r=U(t.masterKey);if(!r)return{ok:!1,code:`MASTER_KEY_MISSING`};let i=t.name.trim();if(i===``||i.length>100)return{ok:!1,code:`NAME_REQUIRED`};let a=gt(n.random),o={name:i,clientId:a,createdAt:n.now,lastUsedAt:null,revokedAt:null,returnUrlAllowlist:t.returnUrlAllowlist};return await e.put(a,o),{ok:!0,client:o,pairing:mt(a,await ht(r,a))}}async function Ia(e,t,n){return(await e.updateIf(t,{where:{revokedAt:null},set:{revokedAt:n}})).applied}async function La(e){return(await e.query({orderBy:{createdAt:`desc`},limit:100})).items.map(e=>e.data)}function Ra(e){let t=(e??``).split(`,`).filter(e=>e.trim()!==``).length;return t===0?{state:`missing`,canSaveSecrets:!1,keyCount:0,banner:{tone:`error`,message:`EMDASH_ENCRYPTION_KEY is not set, so secret settings (the integration master key and the Turnstile secret) cannot be saved. Set it in the site environment and restart.`}}:{state:`ready`,canSaveSecrets:!0,keyCount:t,banner:null}}function za(e){let t=`PLUGIN_SETTING_ENCRYPTION_KEY_MISSING`,n=e=>e.includes(t)||e.includes(`PluginSettingEncryptionError`);return typeof e==`string`?n(e):e instanceof Error?n(e.message)||e.name===`PluginSettingEncryptionError`:typeof e==`object`&&e?e.code===t:!1}const Ba=e=>e.storage.templates,W=e=>({...D(`BAD_REQUEST`).body,...e?{issues:e}:{}}),Va=()=>D(`TEMPLATE_NOT_FOUND`).body;function Ha(e){let t=B(e).id;return typeof t==`string`&&t.length>0&&t.length<=200&&!t.includes(`:`)?t:null}const Ua=(e,t)=>({id:e,...t}),Wa=(e,{body:t,...n})=>({id:e,...n});async function Ga(e,t){let n=await Ba(e).get(t);return n&&n.status!==`version`?n:null}const Ka={"templates/create":{handler:(async(e,t)=>{let n=crypto.randomUUID(),r=rr(e.input,{id:n,now:A()});if(!r.ok)return W(r.error);let{head:i,versions:a}=r.value;return await Ba(t).putMany([{id:n,data:i},...a]),{ok:!0,template:Ua(n,i)}})},"templates/update":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=await Ga(t,n);if(!r)return Va();let i=ir(r,e.input,{id:n,now:A()});return i.ok?(await Ba(t).putMany([{id:n,data:i.value.head},i.value.version]),{ok:!0,template:Ua(n,i.value.head)}):W(i.error)})},"templates/get":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=B(e.input).version;if(r!==void 0&&!(Number.isSafeInteger(r)&&r>=1))return W();let i=r,a=await Ba(t).getMany(i===void 0?[n]:[n,I(n,i)]),o=a.get(n);if(!o||o.status===`version`)return Va();let s=i===void 0?o:a.get(I(n,i));if(!s)return Va();let c=Array.from({length:o.version},(e,t)=>t+1);return{ok:!0,template:Ua(n,{...s,status:o.status}),versions:c}})},"templates/list":{handler:(async(e,t)=>{let n=B(e.input).status??`active`;if(n!==`active`&&n!==`archived`)return W();let{items:r}=await Ba(t).query({where:{status:n},limit:200});return{ok:!0,templates:r.map(e=>Wa(e.id,e.data)).sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:0)}})},"templates/archive":{handler:(async(e,t)=>{let n=Ha(e.input);if(!n)return W();let r=await Ga(t,n);if(!r)return Va();if(r.status===`archived`)return{ok:!0,template:Ua(n,r)};let i=ar(r,A());return await Ba(t).putMany([{id:n,data:i}]),{ok:!0,template:Ua(n,i)}})}},qa=(e,t)=>({severity:`error`,title:e,...t?{message:t}:{}}),Ja=e=>z(e.ctx).clients;async function Ya(e){return(await e.ctx.settings.list()).find(e=>e.key===`integrationMasterKey`)?.value}const Xa=e=>typeof e==`string`&&e.trim()!==``;function Za(e,r,o=[]){let s=U(e)!==null,c=typeof e==`object`&&!!e,l=Ra(null).banner;return K([t(`Integrations`),...u([c&&l&&{severity:`error`,title:`Encryption key missing`,message:l.message},!s&&!c&&{severity:`warning`,title:Xa(e)?`Integration master key is too short`:`Integration master key not set`,message:`Clients are paired with secrets derived from the master key. Generate one here, or save one of at least 32 characters in Settings.`}]),...o,...s||c||Xa(e)?[]:[d([f(`integrations.generate-key`,`Generate master key`,{style:`primary`})])],t(`Clients`),a({columns:[i(`name`,`Name`),i(`clientId`,`Client id`),i(`created`,`Created`,`relative_time`),i(`status`,`Status`,`badge`),i(`revoke`,``,`element`)],rows:r.map(e=>({name:e.name,clientId:e.clientId,created:e.createdAt,status:e.revokedAt?`Revoked`:`Active`,...e.revokedAt?{}:{revoke:f(`client.revoke`,`Revoke`,{style:`danger`,value:e.clientId,confirm:{title:`Revoke this client?`,text:`Its intents and receipts are refused from now on. This cannot be undone; create a new client to pair again.`,confirm:`Revoke client`,deny:`Keep`,style:`danger`}})}})),pageActionId:`clients.page`,emptyText:`No clients yet.`}),n(`Events on this site: with the Events suite installed, an administrator pairs it in one click at /_events/pair (the client appears here as "Events on this site"; no string to copy).`),t(`Add a client`),n(`The pairing string is shown once, right after you create the client, and cannot be shown again. Paste it into the other plugin's settings. Return URLs: one per line, https (http only for localhost); leave blank to allow this site only.`),y({fields:[m(`name`,`Name`,{initialValue:``}),m(`returnUrlAllowlist`,`Allowed return URLs`,{multiline:!0,initialValue:``})],submit:{label:`Create client`,actionId:`client.create`}})])}async function G(e,t,n=[]){return Za(t,await La(Ja(e)),n)}async function Qa(e){let[t,n]=await Promise.all([Ya(e),La(Ja(e))]);return Za(t,n)}async function $a(e){let t=await Ya(e);if(Xa(t))return G(e,t,u([qa(`Key already set`,`Changing it would re-pair every client.`)]));let n=Ma();try{await e.ctx.settings.set(`integrationMasterKey`,n)}catch(n){if(!za(n))throw n;return G(e,t,u([qa(`Encryption key missing`,Ra(null).banner?.message)]))}return G(e,n,u([{severity:`info`,title:`Master key generated`}]))}async function eo(e,t){let n=await Ya(e),r=(e,t)=>typeof e==`string`?e.slice(0,t):``,i=Pa(r(t.returnUrlAllowlist,2e3));if(!i.ok)return G(e,n,u([qa(`Not created`,`Return URL not allowed: ${i.entry.slice(0,200)}`)]));let a=await Fa(Ja(e),{name:r(t.name,200),returnUrlAllowlist:i.entries,masterKey:n},{now:A(e.now)});return a.ok?G(e,n,[...u([{severity:`warning`,title:`Copy the pairing string now`,message:`It is shown only this once and cannot be recovered. Treat it like a password.`}]),o({code:a.pairing})]):G(e,n,u([qa(`Not created`,a.code===`MASTER_KEY_MISSING`?`Set the integration master key first (at least 32 characters), or generate one.`:`Give the client a name of up to 100 characters.`)]))}async function to(e,t){let n=await Ia(Ja(e),t,A(e.now));return G(e,await Ya(e),u([n?{severity:`info`,title:`Client revoked`}:qa(`Not revoked`,`Unknown or already revoked.`)]))}const K=e=>({blocks:e}),q=(e,t=200)=>typeof e==`string`?e.trim().slice(0,t):``,J=(e,t,n)=>t.handler({input:n,user:e.user??null},e.ctx),no=e=>Xi[e],ro=e=>Ka[e],io={INVALID_NAME:`Give the template a name of up to 200 characters.`,INVALID_BODY:`The template text is required (up to 100,000 characters).`,INVALID_DESCRIPTION:`The description is too long (up to 1,000 characters).`,TEMPLATE_ARCHIVED:`This template is archived.`,INVALID_INTEGRATIONS:`Choose whether integrations may use the template.`,INVALID_TITLE:`The title is too long or has control characters.`,INVALID_SIGNER_NAME:`Enter the signer's name.`,INVALID_SIGNER_EMAIL:`Enter a valid email address for the signer.`,INVALID_FIELDS:`A field value is too long or not text.`,MISSING_FIELD:`A template field has no value.`,DOCUMENT_TOO_LARGE:`The document is too long to sign (up to 131,072 characters and 1,500 lines).`};function Y(e,t=`The change was refused.`){let n=Array.isArray(e.issues)?e.issues:[];return n.length>0?n.map(e=>io[e.code??``]??`${e.path??`input`} (${e.code??`invalid`})`).join(` `):e.error?.message??t}const ao=(e,t,n)=>({severity:e,title:t,...n?{message:n}:{}}),X=(e,t)=>ao(`error`,e,t),oo=(e,t)=>ao(`warning`,e,t),so=(e,t)=>f(e,t,{style:`secondary`}),Z=(e,t)=>ao(`info`,e,t),co=()=>so(`envelopes.back`,`Back to envelopes`),lo=()=>so(`templates.back`,`Back to templates`),uo=e=>f(`envelope.open`,`Open envelope`,{value:e}),fo={"envelope.created":`Envelope created`,"envelope.sent":`Envelope sent`,"signer.viewed":`Signer opened the document`,"signer.consented":`Signer gave consent`,"signer.signed":`Signer signed`,"signer.declined":`Signer declined`,"envelope.completed":`Envelope completed`,"envelope.declined":`Envelope declined`,"envelope.voided":`Envelope voided`,"envelope.expired":`Envelope expired`},po=e=>!En(e.ctx)&&oo(`Set the site URL`,On);async function mo(e){let t=await Mn(e.ctx);return[po(e),t.state===`no_transport`&&oo(`No email transport`,`No email provider is configured, so signing invitations stay queued and are not delivered. Install an email provider plugin.`),t.failed>0&&oo(`${t.failed} email${t.failed===1?``:`s`} could not be delivered`,`Open the envelope and use Resend invitation if a signer never received theirs.`)]}async function ho(e,r,o=[],s){let c=Qn(r)?r:``,[l,d]=await Promise.all([J(e,no(`envelopes/list`),{...c?{status:c}:{},...s?{cursor:s}:{}}),mo(e)]),p=typeof l.nextCursor==`string`?l.nextCursor:void 0,h=(l.envelopes??[]).map(e=>{let t=e.signer;return{title:e.title,signer:t?`${t.name??``} <${t.email??``}>`:``,status:e.status,created:e.createdAt,open:f(`envelope.open`,`Open`,{value:e.id})}});return K([t(`Envelopes`),...u(d),...o,y({fields:[g(`status`,`Status`,[{label:`Any status`,value:``},...Yn.map(e=>({label:e.replaceAll(`_`,` `),value:e}))],{initialValue:c})],submit:{label:`Filter`,actionId:`envelopes.filter`}}),n(`Newest first, 100 a page. Create an envelope from a template on the Templates page.`),a({columns:[i(`title`,`Title`),i(`signer`,`Signer`),i(`status`,`Status`,`badge`),i(`created`,`Created`,`relative_time`),i(`open`,``,`element`)],rows:h,pageActionId:`envelopes.page:${c}`,...p?{nextCursor:p}:{},emptyText:`No envelopes match.`}),t(go),y({fields:[m(`subject`,`Signer email or envelope id`)],submit:{label:`Find`,actionId:`retention.preview`}})])}const go=`Delete personal data`;async function _o(e,n,r){let i=await ka(e.ctx,n),a=i.due.length;return r&&a>0&&await Aa(e.ctx,i,e.now),K([t(go),...u([{severity:r?`info`:`warning`,title:r&&a>0?`Personal data deleted`:a+i.open>0?`${a} envelope(s) to delete, ${i.open} kept for now`:`No envelopes found`,message:`Signed records stay for their own period; open envelopes and pending PDFs are skipped.`}]),d([...!r&&a>0?[f(`retention.erase`,go,{style:`danger`,value:n,confirm:{title:`${go}?`,text:`This cannot be undone.`,confirm:`Delete`,deny:`Keep`,style:`danger`}})]:[],co()])])}async function vo(e,t){if(!t)return`missing`;let n=await z(e.ctx).outbox.get(`invite-${t}`);return n?n.status===`failed`?`failed`:`queued`:`missing`}async function Q(e,o,s={}){let{envelopes:c,signers:l,audit_events:m}=z(e.ctx),h=s.envelope??await c.get(o);if(!h)return K([t(`Envelope`),...u([X(`Envelope not found`,`It may have been removed.`)]),d([co()])]);let g=h.status===`sent`||h.status===`in_progress`,[_,v,y]=await Promise.all([m.query({where:{envelopeId:o},orderBy:{seq:`asc`},limit:200}),s.signers?Promise.resolve(s.signers):h.signerIds.length>0?l.getMany(h.signerIds).then(e=>[...e].map(([e,t])=>({id:e,name:t.name,email:t.email,status:t.status}))):Promise.resolve([]),s.invite??(h.status===`sent`?vo(e,h.signerIds[0]):Promise.resolve(`n/a`))]),b=v[0],x=h.status===`sent`&&(y===`missing`||y===`failed`),S=null;if(h.status===`completed`&&!h.recordsPurgedAt)if(h.pdfSha256){let t=await ji(e.ctx,o,e.now);S=d([p(`Download signed PDF`,{kind:`external`,url:`${e.origin}${t.url}`},{appearance:`primary`})])}else S=n(`The signed PDF is still being prepared. Reload in a minute.`);let C=[h.status===`draft`&&f(`envelope.send`,`Send for signature`,{style:`primary`,value:o}),x&&f(`envelope.resend`,`Resend invitation`,{style:`primary`,value:o}),(h.status===`draft`||g)&&f(`envelope.void`,`Void`,{style:`danger`,value:o,confirm:{title:`Void this envelope?`,text:`The signer will no longer be able to sign it. This cannot be undone.`,confirm:`Void envelope`,deny:`Keep`,style:`danger`}}),co()].filter(e=>e!==!1);return K([t(h.title),...u([x&&{severity:`warning`,title:`The invitation was not delivered`,message:y===`failed`?`The email gave up after repeated failures. Resend invitation queues a fresh email with a new signing link.`:`The invitation was never queued. Resend invitation queues it with a new signing link.`},x&&po(e)]),...s.extra??[],...h.personalPurgedAt?[n(`Personal data deleted ${h.personalPurgedAt}${h.recordsPurgedAt?`; signed records deleted`:``} (retention).`)]:[],r([{label:`Status`,value:h.status.replaceAll(`_`,` `)},{label:`Template`,value:`${h.templateId} v${h.templateVersion}`},{label:`Signer`,value:b?`${b.name} <${b.email}>`:h.signer.email},{label:`Signer status`,value:b?.status??`not sent yet`},{label:`Delivery`,value:h.delivery},{label:`Created`,value:h.createdAt},{label:`Sent`,value:h.sentAt??`Not sent`},{label:`Expires`,value:h.expiresAt??`Not set`},{label:`Completed`,value:h.completedAt??`Not completed`},{label:`Document SHA-256`,value:h.docSha256??`Set when sent`},{label:`Final hash`,value:h.finalHash??`Set when completed`}]),...S?[S]:[],d(C),t(`Audit timeline`),a({columns:[i(`seq`,`#`,`number`),i(`event`,`Event`),i(`at`,`When`,`text`),i(`actor`,`By`)],rows:_.items.map(({data:e})=>({seq:e.seq,event:fo[e.type]??e.type,at:e.at,actor:e.actor})),pageActionId:`audit.page:${o}`,emptyText:`No events yet.`})])}async function yo(e,n){let r;try{r=await J(e,no(`envelopes/send`),{id:n})}catch{return K([t(`Envelope`),...u([X(`The envelope was sent but the invitation could not be queued`,`Open the envelope and use Resend invitation.`)]),d([uo(n)])])}if(r.ok!==!0)return K([t(`Envelope`),...u([X(`Not sent`,Y(r))]),d([uo(n),co()])]);let i=r.invitation===`SITE_URL_MISSING`;return K([t(`Envelope`),...u([i?{severity:`warning`,title:`Envelope sent, but no invitation was queued`,message:On}:Z(`Envelope sent`,`The signer's invitation is queued.`)]),d([uo(n),co()])])}async function bo(e,t){let n=await J(e,no(`envelopes/void`),{id:t});if(n.ok!==!0){let r=n.error?.code===`ENVELOPE_CLOSED`;return Q(e,t,{extra:u([X(r?`This envelope cannot be voided`:`Not voided`,r?`It is already completed, declined, voided or expired.`:Y(n))])})}return Q(e,t,{envelope:n.envelope,invite:`n/a`,extra:u([Z(`Voided`,`The signer can no longer sign this envelope.`)])})}async function xo(e,t){let n=await J(e,no(`envelopes/resend`),{id:t});return n.ok===!0?Q(e,t,{envelope:n.envelope,invite:`queued`,signers:n.signers,extra:u([Z(`Invitation queued`,`A new email with a new signing link is on its way.`)])}):Q(e,t,{extra:u([n.error?.code===`INVITATION_QUEUED`?Z(`Already queued`,`The invitation is queued or was sent.`):X(`Not resent`,Y(n,`Only an envelope that is sent and unsigned can be resent.`))])})}const So=/^(signer|participant)\./;async function Co(e,r,i=[]){let a=await J(e,ro(`templates/get`),{id:r}),o=a.template;return a.ok!==!0||!o?K([t(`New envelope`),...u([X(`Template not found`)]),...i]):K([t(`New envelope: ${o.name}`),...i,n(`Creates a draft you can check before sending it for signature. Signer fields: one per line as key: Label, ending in * when required.`),y({fields:[m(`title`,`Title`,{initialValue:o.name}),m(`signerName`,`Signer name`),m(`signerEmail`,`Signer email`),...o.fields.filter(e=>!So.test(e)).map(e=>m(`field:${e}`,e)),m(`signerFields`,`Fields the signer fills in (optional)`,{multiline:!0,placeholder:`phone: Phone number *`})],submit:{label:`Create draft`,actionId:`envelope.create`},blockId:`envelope-new:${r}`}),d([lo()])])}function wo(e){return typeof e==`string`?e.slice(0,4e3).split(`
|
|
38
|
+
`).map(e=>e.trim()).filter(e=>e!==``).map(e=>{let t=e.indexOf(`:`),n=(t===-1?e:e.slice(0,t)).trim(),r=t===-1?``:e.slice(t+1).trim(),i=r.endsWith(`*`);return i&&(r=r.slice(0,-1).trim()),{key:n,label:r,...i?{required:!0}:{}}}):[]}async function To(e,t,n){let r=t?.startsWith(`envelope-new:`)?t.slice(13):``;if(!r)return K(u([X(`Choose a template first`)]));let i={};for(let[e,t]of Object.entries(n))e.startsWith(`field:`)&&(i[e.slice(6)]=typeof t==`string`?t:``);let a=q(n.title),o=wo(n.signerFields),s=await J(e,no(`envelopes/create`),{templateId:r,...a?{title:a}:{},signer:{name:q(n.signerName),email:q(n.signerEmail)},fields:i,...o.length>0?{signerFields:o}:{}});if(s.ok!==!0)return Co(e,r,u([X(`Not saved`,Y(s))]));let c=s.envelope.id;return Q(e,c,{extra:u([Z(`Draft created`,`Check the details, then send it.`)])})}async function Eo(e,r=[]){let o=((await J(e,ro(`templates/list`),{})).templates??[]).map(e=>({name:e.name,id:e.id,version:e.version,fields:(e.fields??[]).join(`, `),integrations:e.integrations===!0?`Yes`:`No`,updated:e.updatedAt,edit:f(`template.edit`,`Edit`,{value:e.id}),use:f(`envelope.new`,`New envelope`,{style:`primary`,value:e.id})}));return K([t(`Templates`),...r,a({columns:[i(`name`,`Name`),i(`id`,`ID`),i(`version`,`Version`,`number`),i(`fields`,`Fields`),i(`integrations`,`Integrations`),i(`updated`,`Updated`,`relative_time`),i(`edit`,``,`element`),i(`use`,``,`element`)],rows:o,pageActionId:`templates.page`,emptyText:`No templates yet. Add one below.`}),t(`New template`),n(`Write the document in Markdown. Use {{field}} for values filled in per envelope, and {{signer.name}} for the signer.`),y({fields:[m(`name`,`Name`),m(`description`,`Description (optional)`),m(`body`,`Template text`,{multiline:!0}),Do(!1)],submit:{label:`Create template`,actionId:`template.create`}})])}function Do(e){return _(`integrations`,`Available to integrations`,{description:`Paired sites (such as Events) may send this template for signing.`,initialValue:e})}function Oo(e){let t=Object.fromEntries(dn(e).map(e=>[e,`«${e}»`]));try{return fn(e,t)}catch{return e}}function ko(e,r,i=[]){let a=String(r.body??``),s=dn(a);return K([t(`Edit template: ${String(r.name??``)}`),...i,n(`Version ${String(r.version??1)}. Saving writes a new version; sent envelopes keep the text they were sent with.`),n(`Template id:`),o({code:e}),y({fields:[m(`name`,`Name`,{initialValue:String(r.name??``)}),m(`description`,`Description (optional)`,{initialValue:String(r.description??``)}),m(`body`,`Template text`,{initialValue:a,multiline:!0}),Do(r.integrations===!0)],submit:{label:`Save new version`,actionId:`template.save`},blockId:`template:${e}`}),t(`Preview`),n(s.length>0?`Fields: ${s.join(`, `)}. Placeholders show as «name».`:`This template has no fields.`),o({code:Oo(a)}),d([f(`envelope.new`,`New envelope from this template`,{style:`primary`,value:e}),f(`template.archive`,`Archive`,{style:`danger`,value:e,confirm:{title:`Archive this template?`,text:`It can no longer be used for new envelopes. Sent envelopes are not affected.`,confirm:`Archive`,deny:`Keep`,style:`danger`}}),lo()])])}async function Ao(e,t,n=[]){let r=await J(e,ro(`templates/get`),{id:t});return r.ok!==!0||!r.template?Eo(e,u([X(`Template not found`)])):ko(t,r.template,n)}async function jo(e,t){let n=await J(e,ro(`templates/create`),{name:q(t.name),body:typeof t.body==`string`?t.body:``,...q(t.description,1e3)?{description:q(t.description,1e3)}:{},integrations:t.integrations===!0});return n.ok===!0?Eo(e,u([Z(`Template created`)])):Eo(e,u([X(`Not saved`,Y(n))]))}async function Mo(e,t,n){let r=t?.startsWith(`template:`)?t.slice(9):``;if(!r)return K(u([X(`Choose a template first`)]));let i={name:q(n.name),body:typeof n.body==`string`?n.body:``,description:q(n.description,1e3),integrations:n.integrations===!0},a=await J(e,ro(`templates/update`),{id:r,...i});return a.ok===!0?ko(r,a.template,u([Z(`Saved`)])):ko(r,{...i,version:`?`},u([X(`Not saved`,Y(a))]))}async function No(e,t){let n=await J(e,ro(`templates/archive`),{id:t});return Eo(e,u([n.ok===!0?Z(`Template archived`):X(`Not archived`,Y(n))]))}const Po=[{key:`senderName`,label:`Sender name`,kind:`text`},{key:`expiryDays`,label:`Envelope expiry (days)`,kind:`number`,min:1,max:365},{key:`consentVersion`,label:`Consent version`,kind:`text`},{key:`consentWording`,label:`Consent wording`,kind:`long`},{key:`retentionPersonalDataMonths`,label:`Keep personal data (months)`,kind:`number`,min:1,max:120},{key:`retentionSignedRecordsYears`,label:`Keep signed records (years)`,kind:`number`,min:1,max:50},{key:`turnstileSiteKey`,label:`Turnstile site key`,kind:`text`}],Fo=[{key:`turnstileSecretKey`,label:`Turnstile secret key`},{key:`integrationMasterKey`,label:`Integration master key`}],Io=e=>typeof e==`string`&&e!==``?`readable`:typeof e==`object`&&e?`unreadable`:`unset`;function Lo(e,r,i=[]){let a=Fo.some(e=>r[e.key]===`unreadable`),o=Ra(null).banner;return K([t(`Settings`),...u([a&&o&&{severity:`error`,title:`Encryption key missing`,message:o.message},r.integrationMasterKey===`unset`&&oo(`Integration master key not set`,`Other plugins cannot create envelopes through the integration protocol until it is saved.`)]),...i,y({fields:[...Po.map(t=>t.kind===`number`?h(t.key,t.label,{min:t.min,max:t.max,...typeof e[t.key]==`number`?{initialValue:e[t.key]}:{}}):m(t.key,t.label,{multiline:t.kind===`long`,initialValue:typeof e[t.key]==`string`?e[t.key]:``})),...Fo.map(e=>v(e.key,`${e.label} (leave blank to keep)`,{hasValue:r[e.key]===`readable`}))],submit:{label:`Save settings`,actionId:`settings.save`}}),n(`Reminder and one-time-code settings (Pro) are in the plugin's own settings panel.`)])}async function Ro(e){let t=await e.ctx.settings.list(),n=Object.fromEntries(t.map(e=>[e.key,e.value]));return{values:n,secrets:Object.fromEntries(Fo.map(e=>[e.key,Io(n[e.key])]))}}async function zo(e){let{values:t,secrets:n}=await Ro(e);return Lo(t,n)}async function Bo(e,t){let{values:n,secrets:r}=await Ro(e),i=[],a=[];for(let e of Po){let r=t[e.key];if(r==null||r===``)continue;let o;if(e.kind===`number`){if(o=Number(r),!Number.isInteger(o)||o<(e.min??0)||o>(e.max??2**53-1)){a.push(`${e.label} must be a whole number from ${e.min} to ${e.max}.`);continue}}else o=q(r,e.kind===`long`?2e3:200);o!==n[e.key]&&i.push([e.key,o])}let o=Fo.filter(e=>q(t[e.key],500)!==``);if(o.some(e=>e.key===`integrationMasterKey`&&Na(q(t[e.key],500)))&&a.push(`The integration master key must be at least 32 characters, or use Generate on the Integrations page.`),a.length>0)return Lo(n,r,u([X(`Not saved`,a.join(` `))]));if(i.length+o.length>6)return Lo(n,r,u([X(`Too many changes at once`,`Save at most 6 settings at a time.`)]));if(i.length+o.length===0)return Lo(n,r,u([Z(`Nothing to save`)]));let s={...n},c={...r};try{for(let n of o)await e.ctx.settings.set(n.key,q(t[n.key],500)),c[n.key]=`readable`;for(let[t,n]of i)await e.ctx.settings.set(t,n),s[t]=n}catch(e){if(!za(e))throw e;let t=Ra(null).banner;return Lo(n,r,u([{severity:`error`,title:`Encryption key missing`,message:t?.message}]))}return Lo(s,c,u([Z(`Saved`)]))}const Vo=e=>q(e,200);async function Ho(e,t){if(t.type===`page_load`)switch(t.page){case`/envelopes`:return ho(e,``);case`/templates`:return Eo(e);case`/settings`:return zo(e);case`/integrations`:return Qa(e);default:return K(u([X(`Page not found`)]))}if(t.type===`form_submit`){let n=t.values;switch(t.action_id){case`envelopes.filter`:return ho(e,q(n.status));case`envelope.create`:return To(e,t.block_id,n);case`template.create`:return jo(e,n);case`template.save`:return Mo(e,t.block_id,n);case`settings.save`:return Bo(e,n);case`client.create`:return eo(e,n);case`retention.preview`:return _o(e,q(n.subject),!1)}}else{let n=Vo(t.value);if(t.action_id.startsWith(`envelopes.page:`))return ho(e,t.action_id.slice(15),[],q(t.value,500)||void 0);if(t.action_id.startsWith(`audit.page:`))return Q(e,Vo(t.action_id.slice(11)));switch(t.action_id){case`envelopes.back`:case`envelopes.page`:return ho(e,``);case`envelope.open`:return Q(e,n);case`envelope.send`:return yo(e,n);case`envelope.void`:return bo(e,n);case`envelope.resend`:return xo(e,n);case`retention.erase`:return _o(e,n,!0);case`envelope.new`:return Co(e,n);case`integrations.generate-key`:return $a(e);case`client.revoke`:return to(e,n);case`clients.page`:return Qa(e);case`templates.back`:case`templates.page`:return Eo(e);case`template.edit`:return Ao(e,n);case`template.archive`:return No(e,n)}}return K(u([X(`Unknown action`)]))}const Uo={admin:{handler:(async(e,t)=>{let n=`http://localhost`;try{n=new URL(e.request?.url??``).origin}catch{}return Ho({ctx:t,origin:n,now:Date.now(),user:e.user??null},e.input)})}},Wo=[`completed`,`declined`,`voided`,`expired`],Go=e=>{if(!e)return;let t=Date.parse(e);return Number.isNaN(t)?void 0:Math.floor(t/1e3)};function Ko(e,t){let{status:n,clientId:r,externalRef:i}=t;if(!Wo.includes(n)||!r||!i||t.docSha256===null)return;let a=n===`completed`,o=a?Go(t.completedAt):Go(t.closedAt)??Go(t.updatedAt);if(o===void 0)return;let s={v:1,typ:`receipt`,cid:r,envelopeId:e,ref:i,status:n,docSha256:t.docSha256,pdfSha256:a?t.pdfSha256??null:null,finalHash:a?t.finalHash:null,at:o};return We(`receipt`,s).ok?s:void 0}async function qo(e,t,n){let r=Ko(e,t);return r?ot(`receipt`,r,n):void 0}function Jo(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):void 0}function Yo(e){let t={};return{settings:()=>t,async getClient(n){let[r,i]=await Promise.all([e.settings.list(),z(e).clients.get(n)]);t=Object.fromEntries(r.map(e=>[e.key,e.value]));let a=U(t.integrationMasterKey);if(!(!a||!i))return{secret:await ht(a,n),revoked:i.revokedAt!==void 0&&i.revokedAt!==null,returnUrlAllowlist:Jo(i.returnUrlAllowlist)}}}}async function Xo(e,t,n){let r=U(n);if(!(!r||!t.clientId))return qo(e,t,await ht(r,t.clientId))}async function Zo(e,t,n=Date.now()){let r=await at({token:B(e).request,now:n,getClient:Yo(t).getClient});if(!r.ok)return H(r.error);let i=[],a;for(let e=0;e<3;e++){let e=await z(t).templates.query({where:{status:`active`},limit:200,...a===void 0?{}:{cursor:a}});if(i.push(...e.items),!e.hasMore||!e.cursor)break;a=e.cursor}return{ok:!0,templates:i.filter(e=>or(e.data)).map(e=>({id:e.id,name:e.data.name,version:e.data.version})).sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:e.id<t.id?-1:1)}}const Qo=(e,t)=>Zo(e.input,t),$o=/^[0-9a-f]{64}$/,es=/[\u0000-\u001F\u007F]/,ts=e=>Array.isArray(e)&&e.length===2&&e.every(e=>typeof e==`number`&&Number.isFinite(e)&&e>=0&&e<=1);function ns(e){let t=e=>T({path:`signature.strokes`,code:e});return!Array.isArray(e)||e.length===0||e.length>64?t(`INVALID_SIGNATURE`):JSON.stringify(e).length>32768?t(`STROKES_TOO_LARGE`):e.every(e=>Array.isArray(e)&&e.length>0&&e.every(ts))?w(e):t(`INVALID_SIGNATURE`)}function rs(e){let t=T({path:`signature`,code:`INVALID_SIGNATURE`});if(!fr(e)||e.kind!==`typed`&&e.kind!==`drawn`)return t;let n=e.typedName===void 0?void 0:mr(e.typedName);if(n===null)return t;if(e.kind===`typed`)return n===void 0?t:w({kind:`typed`,typedName:n});let r=ns(e.strokes);return r.ok?w({kind:`drawn`,...n===void 0?{}:{typedName:n},strokes:r.value}):r}function is(e){if(!fr(e))return T([{path:``,code:`INVALID_INPUT`}]);let t=[];e.consent!==!0&&t.push({path:`consent`,code:`CONSENT_REQUIRED`}),e.intent!==!0&&t.push({path:`intent`,code:`INTENT_REQUIRED`});let n=typeof e.docSha256==`string`&&$o.test(e.docSha256)?e.docSha256:null;n===null&&t.push({path:`docSha256`,code:`INVALID_DOC_HASH`});let r=typeof e.consentSha256==`string`&&$o.test(e.consentSha256)?e.consentSha256:null;r===null&&t.push({path:`consentSha256`,code:`INVALID_CONSENT_HASH`});let i=rs(e.signature);i.ok||t.push(i.error);let a=gr(e.fieldValues);return a===null&&t.push({path:`fieldValues`,code:`INVALID_FIELDS`}),t.length>0||n===null||r===null||!i.ok||a===null?T(t):w({docSha256:n,consentSha256:r,signature:i.value,fieldValues:a})}function as(e){if(e===void 0)return;let t=typeof e==`string`?e.trim():``;return t.length===0||[...t].length>500||es.test(t)?null:t}async function os(e,t,n){let r=Object.keys(n.fieldValues).sort().map(e=>[e,n.fieldValues[e]]),i=await P(n.salt+JSON.stringify([e,t.kind,t.typedName??null,t.strokes??null,r]));return{...t,sha256:i}}const ss=e=>({...e.ip===void 0?{}:{ip:e.ip},...e.ua===void 0?{}:{ua:e.ua}}),cs=e=>e===void 0?{}:{signer:e};function ls(e,t,n,r){return{type:`signer.viewed`,at:e,actor:`signer`,data:{docSha256:t,...cs(r)},personal:ss(n)}}function us(e){let{at:t,docSha256:n,signature:r}=e;return[{type:`signer.consented`,at:t,actor:`signer`,data:{docSha256:n,consentVersion:e.consentVersion,consentSha256:e.consentSha256,intent:!0},personal:ss(e.who)},{type:`signer.signed`,at:t,actor:`signer`,data:{docSha256:n,kind:r.kind,signatureSha256:r.sha256},personal:{name:r.typedName??e.signerName,...ss(e.who)}},{type:`envelope.completed`,at:t,actor:`system`,data:{docSha256:n}}]}function ds(e){let{at:t,docSha256:n,hasReason:r}=e;return[{type:`signer.declined`,at:t,actor:`signer`,data:{docSha256:n,hasReason:r,...cs(e.order)},personal:ss(e.who)},{type:`envelope.declined`,at:t,actor:`system`,data:{docSha256:n}}]}const fs=[`sent`,`in_progress`];function ps(e){let t=B(e).token;return typeof t==`string`&&t.length>0&&t.length<=200?t:null}const ms=e=>({...e.requestMeta?.ip?{ip:e.requestMeta.ip}:{},...e.requestMeta?.userAgent?{ua:e.requestMeta.userAgent}:{}});function hs(e){try{return e!==void 0&&new URL(e.url).searchParams.has(`token`)}catch{return!1}}function gs(e,t){let n=new Map,r,i={get:t=>{let r=n.get(t);return r||(r=e.kv.get(t),n.set(t,r)),r},set:async(e,t)=>{r={key:e,value:t}}},a=Date.now(),o=()=>Xt(i,t.requestMeta?.ip??`unknown`,a,{scope:`ceremony`,limit:20,windowSeconds:600,salt:`esign-ceremony/1`});return{async blocked(){return!(await o()).ok},async fail(){let t=await o();return t.ok&&r&&await e.kv.set(r.key,r.value),H(t.ok?`SIGNING_TOKEN_INVALID`:`RATE_LIMITED`)}}}async function _s(e,t){let{items:n}=await z(e).signers.query({where:{tokenHash:await O(t)},limit:1}),r=n[0];return r&&await ue(t,r.data.tokenHash)?r:null}async function vs(e,t){let{items:n}=await z(e).signers.query({where:{copyTokenHash:await O(t)},limit:1}),r=n[0];return r?.data.copyTokenHash&&await ue(t,r.data.copyTokenHash)?r:null}const ys=e=>!!(e.returnUrl&&e.clientId),bs=(e,t)=>ys(t)?e.settings.get(`integrationMasterKey`):Promise.resolve(void 0);async function xs(e,t,n){if(!t.returnUrl)return{};let r=await Xo(e,t,n);return{returnUrl:t.returnUrl,...r?{receipt:r}:{}}}const Ss=(e,t)=>e.find(e=>e.key===t)?.value;async function Cs(e,t){let n=await(t?e.settings.list():e.settings.list(`consent`)),r=(e,t)=>{let r=Ss(n,e);return typeof r==`string`&&r.length>0?r:t},i=r(`consentWording`,`I agree to use electronic records and an electronic signature for this document.`);return{version:r(`consentVersion`,`1`),wording:i,sha256:await P(i),masterKey:Ss(n,`integrationMasterKey`)}}const ws=(e,t)=>e.expiresAt!==null&&e.expiresAt<=t,Ts=(e,t)=>e.signerIds.length>1?t.order:void 0;async function Es(e,t,n,r,i){let a=z(e).audit_events,o=i;for(let e=0;e<2;e++){if(o??=await Vn(t,await Un(a,t),r,n),await Wn(a,o))return o;o=void 0}throw Error(`audit chain contention`)}async function Ds(e,t){if(hs(e.request))return H(`TOKEN_IN_QUERY`);let n=gs(t,e),r=ps(e.input);if(r===null)return n.fail();if(await n.blocked())return H(`RATE_LIMITED`);let i=B(e.input).open===!0,{envelopes:a,snapshots:o}=z(t),s=await _s(t,r),c=s?null:await vs(t,r),l=s??c;if(!l)return n.fail();let u=await a.get(l.data.envelopeId);if(!u)return H(`ENVELOPE_NOT_FOUND`);if(c&&u.status!==`completed`)return n.fail();if(!fs.includes(u.status)||l.data.status!==`pending`){let e={ok:!0,state:`closed`,status:u.status,title:u.title,...c?{}:await xs(l.data.envelopeId,u,await bs(t,u))};return u.status!==`completed`||l.data.status!==`signed`?e:u.pdfSha256?{...e,pdf:`ready`,download:await ji(t,l.data.envelopeId,Date.now())}:{...e,pdf:`pending`}}let d=A();if(ws(u,d))return H(`SIGNING_TOKEN_EXPIRED`);let f=u.document,[p,m]=await Promise.all([u.snapshot?o.getMany(u.snapshot.ids):Promise.resolve(new Map),Cs(t,!1)]),h=f&&!u.snapshot?``:kr([...p.values()]);if(h===null)return H(`INTERNAL`);let g=u.status,_=Ts(u,l.data);if(i){let n=!1;if(u.status===`sent`&&(n=(await F(a,l.data.envelopeId,`sent`,`in_progress`,{updatedAt:d})).ok,n&&(g=`in_progress`)),_!==void 0&&(n=(await z(t).signers.updateIf(l.id,{where:{viewedAt:null},set:{viewedAt:d}})).applied),n){let n=ls(d,u.docSha256??``,ms(e),_);if(!(await Hn(z(t).audit_events,l.data.envelopeId,n,{salt:u.piiSalt})).ok)throw Error(`audit chain contention`)}}let{participant:v}=l.data;return{ok:!0,state:`ready`,envelope:{id:l.data.envelopeId,title:u.title,status:g,docSha256:u.docSha256,expiresAt:u.expiresAt},signer:{name:l.data.name,as:l.data.as,...v?{participant:v.name}:{}},snapshot:h,...f?{document:{kind:f.kind,name:f.name,bytes:f.bytes,pages:f.pages}}:{},...u.otp?{otp:l.data.otpVerifiedAt?`verified`:`required`}:{},...u.signerFields?.length?{fields:u.signerFields}:{},consent:{version:m.version,wording:m.wording,sha256:m.sha256}}}async function Os(e,t,n){if(hs(e.request))return H(`TOKEN_IN_QUERY`);let r=gs(t,e),i=ps(e.input);if(i===null)return r.fail();let a=is(e.input);if(!a.ok)return V(a.error);let{envelopes:o,signers:s,audit_events:c}=z(t),l=await _s(t,i);if(!l||l.data.status!==`pending`)return r.fail();let u=l.data.envelopeId,d=await o.get(u);if(!d)return H(`ENVELOPE_NOT_FOUND`);if(d.status===`sent`)return H(`SESSION_REQUIRED`);if(d.status!==`in_progress`||d.document&&!n)return H(`ENVELOPE_CLOSED`);let f=A();if(ws(d,f))return H(`SIGNING_TOKEN_EXPIRED`);if(d.otp&&!l.data.otpVerifiedAt)return H(`OTP_REQUIRED`);if(d.docSha256===null||a.value.docSha256!==d.docSha256)return V([{path:`docSha256`,code:`DOC_CHANGED`}]);let p=await Cs(t,ys(d));if(a.value.consentSha256!==p.sha256)return V([{path:`consentSha256`,code:`CONSENT_CHANGED`}]);let m=d.signerFields??[],h=a.value.fieldValues,g=[...Object.keys(h).filter(e=>!m.some(t=>t.key===e)).map(e=>({path:`fieldValues.${e}`,code:`INVALID_FIELDS`})),...m.filter(e=>e.required&&(h[e.key]??``).trim()===``).map(e=>({path:`fieldValues.${e.key}`,code:`INVALID_FIELDS`}))];if(g.length>0)return V(g);let _=await os(d.docSha256,a.value.signature,{fieldValues:h,salt:d.piiSalt}),v=ms(e),y={status:`signed`,signature:_,consentAt:f,consentVersion:p.version,consentSha256:p.sha256,signedAt:f,fieldValues:h,...v};if(d.signerIds.length>1)return n?n(t,{envelopeId:u,envelope:d,signer:l,set:y,now:f}):H(`ENVELOPE_CLOSED`);let b=us({at:f,docSha256:d.docSha256,consentVersion:p.version,consentSha256:p.sha256,signature:_,signerName:l.data.name,who:v}),x=await Vn(u,await Un(c,u),b,d.piiSalt),S=await Jn(d.docSha256,x.at(-1)?.data.hash??``),C=await F(o,u,d.status,`completed`,{completedAt:f,finalHash:S,updatedAt:f});if(!C.ok)return H(`ENVELOPE_CLOSED`);if(await s.updateIf(l.id,{where:{status:`pending`},set:y}),!await Wn(c,x))throw Error(`audit chain contention`);return await Si(t.cron,u,Date.parse(f)),{ok:!0,status:`completed`,completedAt:f,...await xs(u,C.value,p.masterKey)}}async function ks(e,t){if(hs(e.request))return H(`TOKEN_IN_QUERY`);let n=gs(t,e),r=ps(e.input);if(r===null)return n.fail();let i=as(B(e.input).reason);if(i===null)return V([{path:`reason`,code:`INVALID_INPUT`}]);let{envelopes:a,signers:o}=z(t),s=await _s(t,r);if(!s||s.data.status!==`pending`)return n.fail();let c=s.data.envelopeId,l=await a.get(c);if(!l)return H(`ENVELOPE_NOT_FOUND`);if(!$n(l.status,`declined`))return H(`ENVELOPE_CLOSED`);let u=A();if(ws(l,u))return H(`SIGNING_TOKEN_EXPIRED`);let d=await F(a,c,l.status,`declined`,{closedAt:u,updatedAt:u});if(!d.ok)return H(`ENVELOPE_CLOSED`);let f=ms(e);return await o.updateIf(s.id,{where:{status:`pending`},set:{status:`declined`,declinedAt:u,...i===void 0?{}:{declineReason:i},...f}}),await Es(t,c,l.piiSalt,ds({at:u,docSha256:l.docSha256,hasReason:i!==void 0,who:f,order:Ts(l,s.data)})),{ok:!0,status:`declined`,...await xs(c,d.value,await bs(t,d.value))}}const As=e=>(t,n)=>e(t,n),js=(e=>({"public/session":As(Ds),"public/submit":As((t,n)=>Os(t,n,e)),"public/decline":As(ks)}))();function Ms(e){try{return new URL(e.site.url).origin}catch{return}}async function Ns(e,t,n={}){let r=(n.now??Date.now)(),i=A(r),{envelopes:a,signers:o,snapshots:s,templates:c,nonces:l}=z(t),u=Yo(t),d=await nt({token:B(e).intent,now:r,getClient:u.getClient,consumeNonce:async(e,t,n)=>{let r=`${e}.${t}`;try{let t={nonce:r,cid:e,expiresAt:A(n*1e3)};return(await l.compareAndSet(r,null,t)).applied}catch(e){if(Ri(e))return!1;throw e}},siteOrigin:Ms(t)});if(!d.ok)return H(d.error);let f=d.value,p=u.settings();if(f.replace===!0)return Is(t,f,i);let m=f.tplVersion===void 0?void 0:I(f.tpl,f.tplVersion),h=await c.getMany(m===void 0?[f.tpl]:[f.tpl,m]),g=h.get(f.tpl);if(!or(g))return H(`TEMPLATE_NOT_FOUND`);let _=yr(g,m===void 0?void 0:h.get(m),f.tplVersion);if(!_.ok)return H(`TEMPLATE_NOT_FOUND`);let v=Pn(n.random),y=wr(f,_.value,{now:i,piiSalt:v});if(!y.ok)return V(y.error);let b={delivery:y.value.delivery,signer:y.value.signer},x=f.resend===!0?(e,n,i)=>kn(t,{signerId:e,envelope:n,token:i,senderSetting:p.senderName,now:r}):void 0,S=ce(n.random),C=await O(S),w=async e=>{let t=await Nr(f.cid,f.ref,e);return{id:t,sent:await Ar(t,y.value,_.value,{now:i,tokenHash:C,expiryDays:Li(p.expiryDays)})}},T=await w(1);if(!T.sent.ok)return Array.isArray(T.sent.error)?V(T.sent.error):H(`INTERNAL`);let ee=await a.compareAndSet(T.id,null,T.sent.value.envelope);if(!ee.applied){let e=await a.query({where:{clientId:f.cid,externalRef:f.ref},limit:100}),i=Mr(e.items);if(i)return i.data.status===`draft`&&await sa(t.cron,i.id,r),Fs(o,i.id,i.data,b,n.random,x);let s=Math.max(e.items.length,1)+1;if(y.value.delivery===`email`){let e=await Nr(f.cid,f.ref,s);if(!(await a.compareAndSet(e,null,y.value)).applied){let t=await a.get(e);return t?Fs(o,e,t,b,n.random):H(`INTERNAL`)}return await sa(t.cron,e,r),$(e,y.value,void 0)}if(T=await w(s),!T.sent.ok)return Array.isArray(T.sent.error)?V(T.sent.error):H(`INTERNAL`);if(ee=await a.compareAndSet(T.id,null,T.sent.value.envelope),!ee.applied){let e=await a.get(T.id);return e?Fs(o,T.id,e,b,n.random):H(`INTERNAL`)}}let{id:te,sent:E}=T;if(!E.ok)return H(`INTERNAL`);await s.putMany(E.value.chunks);let ne=await Bi(o,E.value.signer,S,n.random);E.value.envelope.delivery===`email`&&await kn(t,{signerId:E.value.signer.id,envelope:E.value.envelope,token:ne,senderSetting:p.senderName,now:r});let D=[Pr(y.value,`integration`),Fr(E.value.envelope,`integration`)];return await z(t).audit_events.putMany(await Bn(te,D,v)),$(te,E.value.envelope,ne)}function $(e,t,n,r=t.delivery===`inline`){return{ok:!0,envelopeId:e,status:t.status,...n!==void 0&&r?{signingToken:n}:{}}}function Ps(e,t){let n=e.signer;return n.email===t.email&&n.as===t.as&&(n.participant?.name??null)===(t.participant?.name??null)}async function Fs(e,t,n,r,i,a){let o=n.signerIds[0],s=(n.status===`sent`||n.status===`in_progress`)&&Ps(n,r.signer),c=r.delivery===`inline`&&s,l=a!==void 0&&r.delivery===`email`&&n.delivery===`email`&&s;if(!c&&!l||o===void 0)return $(t,n,void 0);let u=await zi(ce(i),i,t=>e.updateIf(o,{where:{status:`pending`},set:{tokenHash:t}}));if(!u.value.applied)return $(t,n,void 0);if(c||!a)return $(t,n,u.token,!0);let d=await a(o,n,u.token);return{...$(t,n,void 0),...d?{resent:!0}:{}}}async function Is(e,t,n){let{envelopes:r}=z(e),i=Mr((await r.query({where:{clientId:t.cid,externalRef:t.ref},limit:100})).items);if(!i)return{ok:!0,status:`none`};let a=i.data.signer;if(a.name===t.signer.name.trim()&&a.email===t.signer.email.trim().toLowerCase()&&a.as===(t.as??`self`)&&(a.participant?.name??null)===(t.participant?.name.trim()??null)||i.data.status===`completed`)return $(i.id,i.data,void 0);let o=await F(r,i.id,i.data.status,`voided`,{closedAt:n,updatedAt:n});return o.ok?(await Ui(e,i.id,o.value,{type:`envelope.voided`,at:n,actor:`integration`}),$(i.id,o.value,void 0)):H(`ENVELOPE_CLOSED`)}const Ls=(e,t)=>Ns(e.input,t),Rs=`integrations:site-client`,zs=[`origin`,`sec-fetch-mode`,`sec-fetch-site`,`sec-fetch-dest`],Bs={ADMIN_REQUIRED:`Only an administrator can pair plugins.`,SERVER_ONLY:`Pairing runs on the server only.`,BAD_REQUEST:`The request was not valid.`,MASTER_KEY_INVALID:`The integration master key is unreadable or shorter than 32 characters.`,ENCRYPTION_KEY_MISSING:`EMDASH_ENCRYPTION_KEY is not set, so the master key cannot be saved.`},Vs=e=>({ok:!1,error:{code:e,message:Bs[e]}});function Hs(e,t){if(e)return typeof e.get==`function`?e.get(t)??void 0:e[t]}const Us=e=>e!=null&&e!==``,Ws={"integrations/pair":{handler:(async(e,t)=>{let n=e.user?.role;if(typeof n!=`number`||n<50)return Vs(`ADMIN_REQUIRED`);if(zs.some(t=>Hs(e.request?.headers,t)!==void 0))return Vs(`SERVER_ONLY`);let r=B(e.input),i=r.action;if(i!==`status`&&i!==`pair`&&i!==`unpair`)return Vs(`BAD_REQUEST`);let a=r.clientId;if(a!==void 0&&(typeof a!=`string`||!ve.test(a)))return Vs(`BAD_REQUEST`);let o=z(t).clients,[s,c]=await Promise.all([t.settings.list(),t.kv.get(Rs)]),l=typeof c==`string`?c:null,u=typeof a==`string`?a:l,[d,f]=await Promise.all([u?o.get(u):null,l&&l!==u&&i!==`status`?o.get(l):null]),p=d!==null&&!d.revokedAt,m=f!==null&&!f.revokedAt,h=A();if(i===`status`)return d&&u?{ok:!0,client:p?`active`:`revoked`,clientId:u}:{ok:!0,client:`none`};if(i===`unpair`)return m&&l&&await Ia(o,l,h),{ok:!0,revoked:p&&u?await Ia(o,u,h):!1};let g=s.find(e=>e.key===`integrationMasterKey`)?.value;if(!Us(g)){g=Ma();try{await t.settings.set(`integrationMasterKey`,g)}catch(e){if(za(e))return Vs(`ENCRYPTION_KEY_MISSING`);throw e}}let _=U(g);if(!_)return Vs(`MASTER_KEY_INVALID`);let v=p&&u?u:m?l:null;if(v)return v!==l&&(await t.kv.set(Rs,v),m&&l&&await Ia(o,l,h)),{ok:!0,created:!1,clientId:v,pairing:mt(v,await ht(_,v))};let y=await Fa(o,{name:`Events on this site`,returnUrlAllowlist:[],masterKey:g},{now:h});return y.ok?(await t.kv.set(Rs,y.client.clientId),{ok:!0,created:!0,clientId:y.client.clientId,pairing:y.pairing}):Vs(`MASTER_KEY_INVALID`)})}},Gs=64*1024,Ks=[{name:`public/envelopes/from-intent`,methods:[`POST`],body:`json`,maxBytes:16*1024},{name:`public/session`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/otp/send`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/otp/verify`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/submit`,methods:[`POST`],body:`json`,maxBytes:256*1024},{name:`public/decline`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/download`,methods:[`GET`],body:`none`,response:`raw`},{name:`public/verify`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/receipts/lookup`,methods:[`POST`],body:`json`,maxBytes:8*1024},{name:`public/templates/catalog`,methods:[`POST`],body:`json`,maxBytes:Gs},{name:`public/self-serve/start`,methods:[`POST`],body:`json`,maxBytes:Gs}];async function qs(){return D({code:`NOT_FOUND`}).body}function Js(e={}){let t={};for(let n of Ks)t[n.name]={public:!0,methods:[...n.methods],request:n.maxBytes===void 0?{body:n.body}:{body:n.body,maxBytes:n.maxBytes},...n.response?{response:n.response}:{},handler:e[n.name]??qs};return t}const Ys=e=>Number(/_(\d+)$/.exec(e)?.[1]??0);function Xs(e){let t;for(let n of e)(!t||Ys(n.id)>Ys(t.id)||Ys(n.id)===Ys(t.id)&&n.data.createdAt>t.data.createdAt)&&(t=n);return t}async function Zs(e,t,n=Date.now()){let r=Yo(t),i=await it({token:B(e).request,now:n,getClient:r.getClient});if(!i.ok)return H(i.error);let{cid:a,ref:o}=i.value,s=Xs((await z(t).envelopes.query({where:{clientId:a,externalRef:o},limit:100})).items.filter(e=>e.data.clientId===a&&e.data.externalRef===o));if(!s)return{ok:!0,state:`none`,receipt:null};if(!er(s.data.status))return{ok:!0,state:`pending`,receipt:null};let c=await Xo(s.id,s.data,r.settings().integrationMasterKey);return c?{ok:!0,state:`terminal`,receipt:c}:H(`INTERNAL`)}const Qs=(e,t)=>Zs(e.input,t),$s=/^[0-9a-f]{64}$/,ec=async(e,t)=>{let n=B(e.input).sha256,r=typeof n==`string`?n.toLowerCase():``;if(!$s.test(r))return V([{path:`sha256`,code:`invalid`}]);if(!(await Xt({get:e=>t.kv.get(e),set:(e,n)=>t.kv.set(e,n)},e.requestMeta?.ip??`unknown`,Date.now(),{scope:`esign-verify`,limit:20,windowSeconds:600,salt:`esign-verify/1`})).ok)return H(`RATE_LIMITED`);let{envelopes:i,audit_events:a}=z(t),o=(await i.query({where:{pdfSha256:r},limit:1})).items[0];if(!o||o.data.status!==`completed`)return{ok:!0,matched:!1};let s=o.data,{items:c}=await a.query({where:{envelopeId:o.id},orderBy:{seq:`asc`},limit:101}),l=null;if(c.length<=100){let e=c.map(e=>e.data),t=await Kn(o.id,e);l=t.ok&&s.docSha256!==null&&e.at(-1)?.type===`envelope.completed`&&await Jn(s.docSha256,t.value.head)===s.finalHash}return{ok:!0,matched:!0,status:s.status,completedAt:s.completedAt,finalHash:s.finalHash,chainVerified:l}},tc=[{name:wn,schedule:`* * * * *`},{name:da,schedule:`0 * * * *`},{name:ha,schedule:`23 3 * * *`},{name:na,schedule:`17 * * * *`}],nc=Js({"public/envelopes/from-intent":Ls,"public/download":Pi,"public/verify":ec,"public/receipts/lookup":Qs,"public/templates/catalog":Qo,...js}),rc={hooks:{"plugin:activate":async(e,t)=>{await tn(t,tc)},cron:async(e,t)=>{await rn(e,t,tc,Date.now())||await jn(e,t)||await ta(e,t)||await ua(e,t)||await ma(e,t)||await Da(e,t)||await ia(e,t)||await wi(e,t)}},routes:{...nc,...Uo,...Ka,...Xi,...Ws,admin:on(Uo.admin,an),"templates/create":on(Ka[`templates/create`]),"public/verify":on(nc[`public/verify`])}};export{rc as default};
|