@certrev/cert-block 1.0.3 → 1.1.1

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +25 -6
  3. package/dist/builder/cert-chrome-data.d.ts +26 -1
  4. package/dist/builder/cert-chrome-data.d.ts.map +1 -1
  5. package/dist/builder/cert-chrome-data.js +1 -0
  6. package/dist/builder/cert-chrome-data.js.map +1 -1
  7. package/dist/builder/cert-review-card.d.ts +35 -2
  8. package/dist/builder/cert-review-card.d.ts.map +1 -1
  9. package/dist/builder/cert-review-card.js +112 -2
  10. package/dist/builder/cert-review-card.js.map +1 -1
  11. package/dist/builder/delivery-runtime.d.ts +23 -0
  12. package/dist/builder/delivery-runtime.d.ts.map +1 -0
  13. package/dist/builder/delivery-runtime.js +38 -0
  14. package/dist/builder/delivery-runtime.js.map +1 -0
  15. package/dist/builder/envelope-face.d.ts +63 -0
  16. package/dist/builder/envelope-face.d.ts.map +1 -0
  17. package/dist/builder/envelope-face.js +151 -0
  18. package/dist/builder/envelope-face.js.map +1 -0
  19. package/dist/builder/index.d.ts +15 -3
  20. package/dist/builder/index.d.ts.map +1 -1
  21. package/dist/builder/index.js +14 -2
  22. package/dist/builder/index.js.map +1 -1
  23. package/dist/builder/issuer-key.d.ts +12 -0
  24. package/dist/builder/issuer-key.d.ts.map +1 -0
  25. package/dist/builder/issuer-key.js +14 -0
  26. package/dist/builder/issuer-key.js.map +1 -0
  27. package/dist/components/memo-toggle.d.ts +42 -0
  28. package/dist/components/memo-toggle.d.ts.map +1 -0
  29. package/dist/components/memo-toggle.js +60 -0
  30. package/dist/components/memo-toggle.js.map +1 -0
  31. package/dist/components/render-cert-block.d.ts +9 -0
  32. package/dist/components/render-cert-block.d.ts.map +1 -1
  33. package/dist/components/render-cert-block.js +83 -25
  34. package/dist/components/render-cert-block.js.map +1 -1
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +3 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/modal/certrev-cert-modal.d.ts +34 -1
  40. package/dist/modal/certrev-cert-modal.d.ts.map +1 -1
  41. package/dist/modal/certrev-cert-modal.js +40 -2
  42. package/dist/modal/certrev-cert-modal.js.map +1 -1
  43. package/dist/modal/certrev-cert.entry.d.ts.map +1 -1
  44. package/dist/modal/certrev-cert.entry.js +2 -4
  45. package/dist/modal/certrev-cert.entry.js.map +1 -1
  46. package/dist/modal/certrev-cert.js +4 -4
  47. package/dist/modal/deprecated.d.ts +15 -0
  48. package/dist/modal/deprecated.d.ts.map +1 -0
  49. package/dist/modal/deprecated.js +22 -0
  50. package/dist/modal/deprecated.js.map +1 -0
  51. package/dist/modal/ftc-disclosure.d.ts +7 -3
  52. package/dist/modal/ftc-disclosure.d.ts.map +1 -1
  53. package/dist/modal/ftc-disclosure.js +7 -3
  54. package/dist/modal/ftc-disclosure.js.map +1 -1
  55. package/dist/modal/index.d.ts +4 -3
  56. package/dist/modal/index.d.ts.map +1 -1
  57. package/dist/modal/index.js +4 -3
  58. package/dist/modal/index.js.map +1 -1
  59. package/dist/modal/interactions.d.ts +20 -4
  60. package/dist/modal/interactions.d.ts.map +1 -1
  61. package/dist/modal/interactions.js +34 -7
  62. package/dist/modal/interactions.js.map +1 -1
  63. package/dist/verify/get-verified-delivery.d.ts +91 -0
  64. package/dist/verify/get-verified-delivery.d.ts.map +1 -0
  65. package/dist/verify/get-verified-delivery.js +157 -0
  66. package/dist/verify/get-verified-delivery.js.map +1 -0
  67. package/package.json +5 -1
  68. package/src/builder/cert-chrome-data.ts +27 -0
  69. package/src/builder/cert-review-card.tsx +143 -3
  70. package/src/builder/delivery-runtime.ts +54 -0
  71. package/src/builder/envelope-face.ts +173 -0
  72. package/src/builder/index.tsx +23 -1
  73. package/src/builder/issuer-key.ts +13 -0
  74. package/src/components/memo-toggle.ts +63 -0
  75. package/src/components/render-cert-block.ts +124 -28
  76. package/src/index.ts +28 -0
  77. package/src/modal/certrev-cert-modal.ts +45 -2
  78. package/src/modal/certrev-cert.entry.ts +2 -4
  79. package/src/modal/deprecated.ts +25 -0
  80. package/src/modal/ftc-disclosure.ts +7 -3
  81. package/src/modal/index.ts +4 -3
  82. package/src/modal/interactions.ts +37 -7
  83. package/src/verify/get-verified-delivery.ts +211 -0
  84. package/dist/modal/ftc-guard.d.ts +0 -85
  85. package/dist/modal/ftc-guard.d.ts.map +0 -1
  86. package/dist/modal/ftc-guard.js +0 -150
  87. package/dist/modal/ftc-guard.js.map +0 -1
  88. package/src/modal/ftc-guard.ts +0 -174
@@ -1,5 +1,5 @@
1
1
  /* biome-ignore-all format: generated cert-badge bundle, see @certrev/cert-block src/modal/ */ /* biome-ignore-all lint: generated cert-badge bundle, see @certrev/cert-block src/modal/ */
2
- "use strict";(()=>{var H="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",$e=(()=>{let e=new Int8Array(128).fill(-1);for(let t=0;t<H.length;t++)e[H.charCodeAt(t)]=t;return e[45]=62,e[95]=63,e})();function g(e){let t=[];for(let a=0;a<e.length;a++){let c=e.charCodeAt(a),d=c<128?$e[c]:-1;d>=0&&t.push(d)}let r=Math.floor(t.length*6/8),n=new Uint8Array(r),o=0,i=0,s=0;for(let a=0;a<t.length;a++)o=o<<6|t[a],i+=6,i>=8&&(i-=8,n[s++]=o>>i&255);return n}function C(e){return g(e)}function p(e,t=new Set){if(typeof e=="number"&&isNaN(e))throw new Error("NaN is not allowed");if(typeof e=="number"&&!isFinite(e))throw new Error("Infinity is not allowed");if(e===null||typeof e!="object")return JSON.stringify(e);if(typeof e.toJSON=="function"){if(t.has(e))throw new Error("Circular reference detected");t.add(e);let n=p(e.toJSON(),t);return t.delete(e),n}if(t.has(e))throw new Error("Circular reference detected");t.add(e);let r;if(Array.isArray(e))r=`[${e.map(o=>p(o===void 0||typeof o=="symbol"?null:o,t)).join(",")}]`;else{let n=[];for(let o of Object.keys(e).sort())e[o]===void 0||typeof e[o]=="symbol"||n.push(`${p(o)}:${p(e[o],t)}`);r=`{${n.join(",")}}`}return t.delete(e),r}var Oe=typeof p=="function"?p:p.default;function K(e){let t=Oe(e);if(typeof t!="string")throw new Error("canonicalize: value is not JSON-serializable");return t}function T(e){return new TextEncoder().encode(K(e))}function b(e,t="$"){if(typeof e=="number"){if(!Number.isInteger(e)||!Number.isSafeInteger(e))throw new Error(`canonicalPayloadBytes: number at ${t} (${e}) is not a safe integer. Signed-payload numbers must be safe integers so PHP/Go/Java verifiers reproduce identical canonical bytes`);return}if(Array.isArray(e)){e.forEach((r,n)=>b(r,`${t}[${n}]`));return}if(e&&typeof e=="object")for(let[r,n]of Object.entries(e))b(n,`${t}.${r}`)}function R(e){return b(e),T(e)}function k(e){return b(e),T(e)}var E="ed25519";var m={name:"Ed25519"};function Pe(e){return e.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,"")}async function q(e){switch(e.format){case"pem":return crypto.subtle.importKey("spki",g(Pe(e.pem)),m,!1,["verify"]);case"spki-base64":return crypto.subtle.importKey("spki",g(e.base64),m,!1,["verify"]);case"spki-der":return crypto.subtle.importKey("spki",e.bytes,m,!1,["verify"]);case"raw":{if(e.bytes.length!==32)throw new Error(`ed25519 raw public key must be 32 bytes, got ${e.bytes.length}`);return crypto.subtle.importKey("raw",e.bytes,m,!1,["verify"])}}}function ze(e){if("format"in e)return!1;let t=e;return typeof t.type=="string"&&typeof t.algorithm=="object"&&Array.isArray(t.usages)}async function G(e){return ze(e)?e:q(e)}async function j(e,t,r){let n=R(e),o=C(t);try{return await crypto.subtle.verify(m,r,o,n)}catch{return!1}}async function Ve(e,t){let{payload:r,signature:n}=e??{};if(!r||!n||r.contractVersion!==1)return{ok:!1,reason:"unsupported_contract_version"};if(n.alg!==E)return{ok:!1,reason:"unsupported_alg"};let o=await t(n.kid);if(!o)return{ok:!1,reason:"unknown_key"};let i;try{i=await G(o)}catch{return{ok:!1,reason:"unknown_key"}}return await j(r,n.sig,i)?{ok:!0,key:i}:{ok:!1,reason:"invalid_signature"}}function J(e,t){let r=t.now??new Date;if(e.subject.platform!==t.platform)return{decision:"suppress",reason:"platform_mismatch"};if(e.subject.externalId!==t.externalId)return{decision:"suppress",reason:"subject_mismatch"};if(e.lifecycle.revokedAt!==null)return{decision:"suppress",reason:"revoked"};if(r.getTime()>=Date.parse(e.lifecycle.expiresAt))return{decision:"suppress",reason:"expired"};let n=e.subject.contentDigest,o=t.liveContentHash;return n!==null&&o!=null&&n!==o?{decision:"suppress",reason:"content_drift"}:{decision:"render",payload:e}}async function W(e,t,r){let n;try{n=await Ve(e,t)}catch{return{decision:"suppress",reason:"unknown_key"}}return n.ok?J(e.payload,r):{decision:"suppress",reason:n.reason}}function v(e){return e?.kind==="tombstone"}async function He(e,t){let{signature:r}=e??{};if(!e?.subject||!r||e.contractVersion!==1)return{ok:!1,reason:"unsupported_contract_version"};if(r.alg!==E)return{ok:!1,reason:"unsupported_alg"};let n=await t(r.kid);if(!n)return{ok:!1,reason:"unknown_key"};let o;try{o=await G(n)}catch{return{ok:!1,reason:"unknown_key"}}let{signature:i,...s}=e,a=C(r.sig),c=!1;try{c=await crypto.subtle.verify(m,o,a,k(s))}catch{c=!1}return c?{ok:!0,key:o}:{ok:!1,reason:"invalid_signature"}}async function Z(e,t,r){let n;try{n=await He(e,t)}catch{return{decision:"suppress",reason:"unknown_key"}}return n.ok?e.subject.platform!==r.platform?{decision:"suppress",reason:"platform_mismatch"}:e.subject.externalId!==r.externalId?{decision:"suppress",reason:"subject_mismatch"}:{decision:"suppress",reason:"revoked"}:{decision:"suppress",reason:n.reason}}async function I(e,t,r){return v(e)?Z(e,t,r):W(e,t,r)}var Y=`
2
+ "use strict";(()=>{var H="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Be=(()=>{let e=new Int8Array(128).fill(-1);for(let t=0;t<H.length;t++)e[H.charCodeAt(t)]=t;return e[45]=62,e[95]=63,e})();function g(e){let t=[];for(let i=0;i<e.length;i++){let c=e.charCodeAt(i),d=c<128?Be[c]:-1;d>=0&&t.push(d)}let r=Math.floor(t.length*6/8),n=new Uint8Array(r),o=0,a=0,s=0;for(let i=0;i<t.length;i++)o=o<<6|t[i],a+=6,a>=8&&(a-=8,n[s++]=o>>a&255);return n}function C(e){return g(e)}function p(e,t=new Set){if(typeof e=="number"&&isNaN(e))throw new Error("NaN is not allowed");if(typeof e=="number"&&!isFinite(e))throw new Error("Infinity is not allowed");if(e===null||typeof e!="object")return JSON.stringify(e);if(typeof e.toJSON=="function"){if(t.has(e))throw new Error("Circular reference detected");t.add(e);let n=p(e.toJSON(),t);return t.delete(e),n}if(t.has(e))throw new Error("Circular reference detected");t.add(e);let r;if(Array.isArray(e))r=`[${e.map(o=>p(o===void 0||typeof o=="symbol"?null:o,t)).join(",")}]`;else{let n=[];for(let o of Object.keys(e).sort())e[o]===void 0||typeof e[o]=="symbol"||n.push(`${p(o)}:${p(e[o],t)}`);r=`{${n.join(",")}}`}return t.delete(e),r}var Ie=typeof p=="function"?p:p.default;function K(e){let t=Ie(e);if(typeof t!="string")throw new Error("canonicalize: value is not JSON-serializable");return t}function F(e){return new TextEncoder().encode(K(e))}function b(e,t="$"){if(typeof e=="number"){if(!Number.isInteger(e)||!Number.isSafeInteger(e))throw new Error(`canonicalPayloadBytes: number at ${t} (${e}) is not a safe integer. Signed-payload numbers must be safe integers so PHP/Go/Java verifiers reproduce identical canonical bytes`);return}if(Array.isArray(e)){e.forEach((r,n)=>b(r,`${t}[${n}]`));return}if(e&&typeof e=="object")for(let[r,n]of Object.entries(e))b(n,`${t}.${r}`)}function T(e){return b(e),F(e)}function R(e){return b(e),F(e)}var U="ed25519";var m={name:"Ed25519"};function Oe(e){return e.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,"")}async function q(e){switch(e.format){case"pem":return crypto.subtle.importKey("spki",g(Oe(e.pem)),m,!1,["verify"]);case"spki-base64":return crypto.subtle.importKey("spki",g(e.base64),m,!1,["verify"]);case"spki-der":return crypto.subtle.importKey("spki",e.bytes,m,!1,["verify"]);case"raw":{if(e.bytes.length!==32)throw new Error(`ed25519 raw public key must be 32 bytes, got ${e.bytes.length}`);return crypto.subtle.importKey("raw",e.bytes,m,!1,["verify"])}}}function Ne(e){if("format"in e)return!1;let t=e;return typeof t.type=="string"&&typeof t.algorithm=="object"&&Array.isArray(t.usages)}async function j(e){return Ne(e)?e:q(e)}async function G(e,t,r){let n=T(e),o=C(t);try{return await crypto.subtle.verify(m,r,o,n)}catch{return!1}}async function Pe(e,t){let{payload:r,signature:n}=e??{};if(!r||!n||r.contractVersion!==1)return{ok:!1,reason:"unsupported_contract_version"};if(n.alg!==U)return{ok:!1,reason:"unsupported_alg"};let o=await t(n.kid);if(!o)return{ok:!1,reason:"unknown_key"};let a;try{a=await j(o)}catch{return{ok:!1,reason:"unknown_key"}}return await G(r,n.sig,a)?{ok:!0,key:a}:{ok:!1,reason:"invalid_signature"}}function J(e,t){let r=t.now??new Date;if(e.subject.platform!==t.platform)return{decision:"suppress",reason:"platform_mismatch"};if(e.subject.externalId!==t.externalId)return{decision:"suppress",reason:"subject_mismatch"};if(e.lifecycle.revokedAt!==null)return{decision:"suppress",reason:"revoked"};if(r.getTime()>=Date.parse(e.lifecycle.expiresAt))return{decision:"suppress",reason:"expired"};let n=e.subject.contentDigest,o=t.liveContentHash;return n!==null&&o!=null&&n!==o?{decision:"suppress",reason:"content_drift"}:{decision:"render",payload:e}}async function Z(e,t,r){let n;try{n=await Pe(e,t)}catch{return{decision:"suppress",reason:"unknown_key"}}return n.ok?J(e.payload,r):{decision:"suppress",reason:n.reason}}function v(e){return e?.kind==="tombstone"}async function ze(e,t){let{signature:r}=e??{};if(!e?.subject||!r||e.contractVersion!==1)return{ok:!1,reason:"unsupported_contract_version"};if(r.alg!==U)return{ok:!1,reason:"unsupported_alg"};let n=await t(r.kid);if(!n)return{ok:!1,reason:"unknown_key"};let o;try{o=await j(n)}catch{return{ok:!1,reason:"unknown_key"}}let{signature:a,...s}=e,i=C(r.sig),c=!1;try{c=await crypto.subtle.verify(m,o,i,R(s))}catch{c=!1}return c?{ok:!0,key:o}:{ok:!1,reason:"invalid_signature"}}async function W(e,t,r){let n;try{n=await ze(e,t)}catch{return{decision:"suppress",reason:"unknown_key"}}return n.ok?e.subject.platform!==r.platform?{decision:"suppress",reason:"platform_mismatch"}:e.subject.externalId!==r.externalId?{decision:"suppress",reason:"subject_mismatch"}:{decision:"suppress",reason:"revoked"}:{decision:"suppress",reason:n.reason}}async function L(e,t,r){return v(e)?W(e,t,r):Z(e,t,r)}var Y=`
3
3
  @font-face {
4
4
  font-family: "DM Sans";
5
5
  font-style: normal;
@@ -119,7 +119,7 @@
119
119
  unicode-range:
120
120
  U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
121
121
  }
122
- `,X="https://assets.certrev.com";function f(e){return typeof e=="string"?e:typeof e=="number"&&Number.isFinite(e)?String(e):""}function l(e){return f(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var Ke=["assets.certrev.com","staging-assets.certrev.com"];function qe(e){return`width=${e},height=${e},fit=cover,format=auto,onerror=redirect`}function Ge(e,t){let r=(e??"").trim();if(!/^https:\/\//i.test(r))return r;let n;try{n=new URL(r)}catch{return r}if(!Ke.includes(n.hostname)||n.pathname.startsWith("/cdn-cgi/image/"))return r;let o=n.pathname.replace(/^\//,"");return`${n.origin}/cdn-cgi/image/${qe(t)}/${o}`}function Q(e,t){return Ge(e,t)}var U="Independent editorial review of this article\u2019s text and sources. Not a product endorsement, nor medical advice.";var ee=U;function M(e){if(!e||typeof e!="string"&&!(e instanceof Date))return null;let t=e instanceof Date?e:new Date(e);return Number.isNaN(t.getTime())?null:t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric",timeZone:"UTC"})}var B=["M67.59 221.77L138.77 292.95C145.8 299.98 145.8 311.44 138.77 318.47L123.02 334.22C116 341.25 104.54 341.25 97.5 334.22L26.32 263.04C19.29 256.01 19.29 244.55 26.32 237.52L42.07 221.77C49.1 214.74 60.56 214.74 67.59 221.77Z","M96.79 335.08L81.12 319.42C73.8 312.1 73.8 300.23 81.12 292.92L315.88 58.16C323.2 50.85 335.06 50.85 342.38 58.16L358.04 73.83C365.36 81.14 365.36 93.01 358.04 100.33L123.29 335.08C115.97 342.4 104.1 342.4 96.79 335.08Z","M203.5 335.14L187.83 319.48C180.52 312.16 180.52 300.29 187.83 292.98L315.88 164.93C323.2 157.62 335.06 157.62 342.38 164.93L358.04 180.6C365.36 187.92 365.36 199.78 358.04 207.1L230 335.14C222.68 342.46 210.82 342.46 203.5 335.14Z","M310.21 335.2L294.54 319.54C287.23 312.22 287.23 300.36 294.54 293.04L315.88 271.71C323.2 264.39 335.06 264.39 342.38 271.71L358.04 287.37C365.36 294.69 365.36 306.55 358.04 313.87L336.71 335.2C329.39 342.52 317.53 342.52 310.21 335.2Z"];function te(e,t){let r=B.map(n=>`<path fill="${t}" d="${n}"/>`).join("");return`<svg width="${e}" height="${e}" viewBox="0 0 375 375" aria-hidden="true" style="display:block;flex-shrink:0">${r}</svg>`}function re(e=8){return`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`}function ne(e="crm"){let t=`crm-stamp-arc-${e}`,r=B.map(n=>`<path fill="#0a1b3f" d="${n}"/>`).join("");return`<span class="crm-stamp"><svg viewBox="0 0 128 128" width="74" height="74" role="img" aria-label="CertREV verified stamp" style="display:block"><defs><path id="${t}" d="M64 18 A46 46 0 1 1 64 110 A46 46 0 1 1 64 18"/></defs><circle cx="64" cy="64" r="58" fill="none" stroke="#0a1b3f" stroke-width="1.3"/><circle cx="64" cy="64" r="51.5" fill="none" stroke="#0a1b3f" stroke-width="0.7" stroke-opacity="0.4"/><text font-family="'JetBrains Mono',ui-monospace,monospace" font-size="7.8" font-weight="600" letter-spacing="1.3" fill="#0a1b3f"><textPath href="#${t}" startOffset="1%">CERTREV VERIFIED \xB7 CERTIFIED \xB7 </textPath></text><svg x="49" y="50" width="30" height="28" viewBox="0 0 375 375" preserveAspectRatio="xMidYMid meet">${r}</svg></svg></span>`}var $=`
122
+ `,X="https://assets.certrev.com";function f(e){return typeof e=="string"?e:typeof e=="number"&&Number.isFinite(e)?String(e):""}function l(e){return f(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var Ve=["assets.certrev.com","staging-assets.certrev.com"];function He(e){return`width=${e},height=${e},fit=cover,format=auto,onerror=redirect`}function Ke(e,t){let r=(e??"").trim();if(!/^https:\/\//i.test(r))return r;let n;try{n=new URL(r)}catch{return r}if(!Ve.includes(n.hostname)||n.pathname.startsWith("/cdn-cgi/image/"))return r;let o=n.pathname.replace(/^\//,"");return`${n.origin}/cdn-cgi/image/${He(t)}/${o}`}function Q(e,t){return Ke(e,t)}var ee="Independent editorial review of this article\u2019s text and sources. Not a product endorsement, nor medical advice.";var te=ee;function M(e){if(!e||typeof e!="string"&&!(e instanceof Date))return null;let t=e instanceof Date?e:new Date(e);return Number.isNaN(t.getTime())?null:t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric",timeZone:"UTC"})}var B=["M67.59 221.77L138.77 292.95C145.8 299.98 145.8 311.44 138.77 318.47L123.02 334.22C116 341.25 104.54 341.25 97.5 334.22L26.32 263.04C19.29 256.01 19.29 244.55 26.32 237.52L42.07 221.77C49.1 214.74 60.56 214.74 67.59 221.77Z","M96.79 335.08L81.12 319.42C73.8 312.1 73.8 300.23 81.12 292.92L315.88 58.16C323.2 50.85 335.06 50.85 342.38 58.16L358.04 73.83C365.36 81.14 365.36 93.01 358.04 100.33L123.29 335.08C115.97 342.4 104.1 342.4 96.79 335.08Z","M203.5 335.14L187.83 319.48C180.52 312.16 180.52 300.29 187.83 292.98L315.88 164.93C323.2 157.62 335.06 157.62 342.38 164.93L358.04 180.6C365.36 187.92 365.36 199.78 358.04 207.1L230 335.14C222.68 342.46 210.82 342.46 203.5 335.14Z","M310.21 335.2L294.54 319.54C287.23 312.22 287.23 300.36 294.54 293.04L315.88 271.71C323.2 264.39 335.06 264.39 342.38 271.71L358.04 287.37C365.36 294.69 365.36 306.55 358.04 313.87L336.71 335.2C329.39 342.52 317.53 342.52 310.21 335.2Z"];function re(e,t){let r=B.map(n=>`<path fill="${t}" d="${n}"/>`).join("");return`<svg width="${e}" height="${e}" viewBox="0 0 375 375" aria-hidden="true" style="display:block;flex-shrink:0">${r}</svg>`}function ne(e=8){return`<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`}function oe(e="crm"){let t=`crm-stamp-arc-${e}`,r=B.map(n=>`<path fill="#0a1b3f" d="${n}"/>`).join("");return`<span class="crm-stamp"><svg viewBox="0 0 128 128" width="74" height="74" role="img" aria-label="CertREV verified stamp" style="display:block"><defs><path id="${t}" d="M64 18 A46 46 0 1 1 64 110 A46 46 0 1 1 64 18"/></defs><circle cx="64" cy="64" r="58" fill="none" stroke="#0a1b3f" stroke-width="1.3"/><circle cx="64" cy="64" r="51.5" fill="none" stroke="#0a1b3f" stroke-width="0.7" stroke-opacity="0.4"/><text font-family="'JetBrains Mono',ui-monospace,monospace" font-size="7.8" font-weight="600" letter-spacing="1.3" fill="#0a1b3f"><textPath href="#${t}" startOffset="1%">CERTREV VERIFIED \xB7 CERTIFIED \xB7 </textPath></text><svg x="49" y="50" width="30" height="28" viewBox="0 0 375 375" preserveAspectRatio="xMidYMid meet">${r}</svg></svg></span>`}var I=`
123
123
  :host {
124
124
  --cr-navy: #0a1b3f;
125
125
  --cr-lime: #d4e157;
@@ -552,6 +552,6 @@
552
552
  padding: 18px 18px 20px;
553
553
  }
554
554
  }
555
- `;var oe="nofollow sponsored noopener noreferrer",je=/^(dr|prof|professor|mr|mrs|ms|mx|rev|sir|dame)\.?\s+/i;function ie(e){let t=f(e).replace(je,"").trim(),r=t.indexOf(",");return(r===-1?t:t.slice(0,r)).trim()}function Je(e){let t=ie(e).split(/\s+/).filter(Boolean);return t.length===0?"":t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[t.length-1][0]).toUpperCase()}function We(e){return ie(e)}function Ze(e){return f(e).replace(/^https?:\/\//i,"").replace(/\/$/,"")}function ae(e){let t=f(e).trim();return t&&/^https?:\/\//i.test(t)?t:"#"}function Ye(e){return(f(e?.cardLabel)||f(e?.fullName)||f(e?.abbreviation)).trim()}function se(e){let t=[],r=Array.isArray(e?.credentials)?e.credentials:[];for(let n of r){let o=Ye(n);o&&!t.includes(o)&&t.push(o)}return t}function Xe(e,t){return t?.showBio===!1?"":(f(e?.background)||f(e?.bio)).trim()}function ce(e,t,r,n){let o=f(e?.photoUrl).trim();if(n&&/^https?:\/\//i.test(o)){let i=r.includes("--64")?64:56,s=Q(o,i===64?128:112);return`<img class="crm-avatar ${r}" src="${l(s)}" alt="" width="${i}" height="${i}" decoding="async">`}return`<span class="crm-avatar ${r}">${l(Je(t))}</span>`}var le='<button type="button" class="crm-close" data-certrev-modal-close aria-label="Close">&times;</button>';function fe(e){return`<div class="crm-head">${te(16,"#ffffff")}<span class="crm-head__eyebrow">${l(e)}</span><span class="crm-head__wordmark">CertREV</span></div>`}function de(e){return`<span class="${e}">${re(8)}Certified</span>`}function pe(e){let t=f(e?.compensationCue).trim();return`<div class="crm-disclosure">${t?`<span class="crm-disclosure__cue">${l(t)}</span> `:""}${l(ee)}</div>`}function ue(e){let t=e.expert??null,r=f(t?.displayName).trim();if(!r)return null;let n=e.display?.showExpertPhoto!==!1,o=se(t).join(" \xB7 "),i=M(e.certifiedAt)??"",s=f(e.displayCertId).trim(),a=f(e.articleTitle).trim(),c=f(e.verifyUrl).trim(),d=We(r),h=a?`<div class="crm-certifies"><div class="crm-certifies__eyebrow">Certifies the article</div><div class="crm-certifies__title">${l(a)}</div></div>`:"",x=s?`<div class="crm-meta__col"><div class="crm-meta__label">Certificate ID</div><div class="crm-meta__value crm-meta__value--mono">${l(s)}</div></div>`:"",Be=c?`<div class="crm-sig__url">${l(Ze(c))}</div>`:"";return`${le}${fe("Certificate of Expert Review")}<div class="crm-body--cert"><div class="crm-expert-row">${ce(t,r,"crm-avatar--56",n)}<div class="crm-expert-row__info"><div class="crm-expert-row__eyebrow">Reviewing Expert</div><div class="crm-expert-row__name">${l(r)}</div>${o?`<div class="crm-expert-row__creds">${l(o)}</div>`:""}</div></div>${h}<div class="crm-meta"><div class="crm-meta__col"><div class="crm-meta__label">Issued</div><div class="crm-meta__value">${l(i)}</div></div>${x}<div class="crm-meta__col"><div class="crm-meta__label">Status</div><div class="crm-meta__status">${de("crm-chip")}</div></div></div><div class="crm-sig"><div><div class="crm-sig__name">${l(d)}</div><div class="crm-sig__rule"></div>${Be}</div>${ne("cert")}</div>${pe(t)}<div class="crm-actions"><a class="crm-cta" href="${l(ae(c))}" target="_blank" rel="${oe}">View full certificate</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`}function me(e){let t=e.expert??null,r=f(t?.displayName).trim();if(!r)return null;let n=e.display?.showExpertPhoto!==!1,o=se(t),i=Xe(t,e.display),s=M(e.certifiedAt),a=o.length?`<div class="crm-chips">${o.map(h=>`<span class="crm-chips__chip">${l(h)}</span>`).join("")}</div>`:"",c=i?`<p class="crm-bio">${l(i)}</p>`:"",d=s?`Independently reviewed \xB7 Certified ${l(s)}`:"Independently reviewed";return`${le}${fe("Verified reviewer")}<div class="crm-body--expert"><div class="crm-id">${ce(t,r,"crm-avatar--64",n)}<div class="crm-id__info"><div class="crm-id__name">${l(r)}</div></div></div>${a}${c}<div class="crm-trust">${de("crm-trust__chip")}<span class="crm-trust__text">${d}</span></div>${pe(t)}<div class="crm-actions"><a class="crm-cta" href="${l(ae(t?.profileUrl))}" target="_blank" rel="${oe}">View full profile on CertREV</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`}var A="certrev-cert-modal",w=null;function Qe(){return typeof CSSStyleSheet<"u"&&"replaceSync"in CSSStyleSheet.prototype&&"adoptedStyleSheets"in Document.prototype}function et(){return Qe()?(w||(w=new CSSStyleSheet,w.replaceSync($)),w):null}var ye=!1;function tt(e){if(ye||(ye=!0,e.querySelector("style[data-certrev-modal-fonts]")))return;if(!e.querySelector("link[data-certrev-modal-preconnect]")){let r=e.createElement("link");r.rel="preconnect",r.href=X,r.crossOrigin="",r.setAttribute("data-certrev-modal-preconnect",""),e.head.appendChild(r)}let t=e.createElement("style");t.textContent=Y,t.setAttribute("data-certrev-modal-fonts",""),e.head.appendChild(t)}var O=class extends HTMLElement{constructor(){super();this.rendered=!1;this.content=null;this.fetchInFlight=null;this.root=this.attachShadow({mode:"open"});let r=et();if(r)this.root.adoptedStyleSheets=[r];else{let n=document.createElement("style");n.textContent=$,this.root.appendChild(n)}this.root.addEventListener("click",n=>this.onShadowClick(n))}open(r){return this.getAttribute("data-fonts")!=="host"&&tt(document),this.ensureRendered()?(this.show(r),!0):this.hasFetchSource()?(this.fetchThenShow(r),!0):!1}ensureRendered(){if(this.rendered)return this.content!=null;let r=this.readSyncContent();return r?(this.content=r,this.renderDialogs(r),this.rendered=!0,!0):!1}readSyncContent(){let r=this.getAttribute("data-envelope");if(r)return ge(r);let n=this.querySelector("script[data-certrev-envelope]");return n?.textContent?ge(n.textContent):null}hasFetchSource(){return!!(this.getAttribute("data-delivery-api")&&this.getAttribute("data-platform")&&this.getAttribute("data-external-id"))}async fetchThenShow(r){if(!this.fetchInFlight){let n=(this.getAttribute("data-delivery-api")||"").replace(/\/$/,""),o=this.getAttribute("data-platform")||"",i=this.getAttribute("data-external-id")||"";this.fetchInFlight=(async()=>{try{let s=await fetch(`${n}/api/cert/v1/delivery/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{cache:"no-store",credentials:"omit"});if(!s.ok)return;let a=await s.json();if(rt(a)){this.markSuppressed();return}let c=v(a)?void 0:a.payload?.content;c&&(this.content=c,this.renderDialogs(c),this.rendered=!0)}catch{}})()}await this.fetchInFlight,this.rendered&&this.show(r)}renderDialogs(r){let n=ue(r),o=me(r),i=document.createElement("div");i.innerHTML=`${n?`<dialog id="cert" class="crm-dialog crm-dialog--cert" aria-label="CertREV certificate">${n}</dialog>`:""}${o?`<dialog id="expert" class="crm-dialog crm-dialog--expert" aria-label="Verified reviewer profile">${o}</dialog>`:""}`;for(let s of Array.from(i.childNodes))this.root.appendChild(s)}show(r){let n=this.root.getElementById(r);n&&typeof n.showModal=="function"&&!n.open&&n.showModal()}markSuppressed(){this.setAttribute("data-certrev-suppressed","");for(let r of Array.from(document.querySelectorAll("[data-certrev-modal-open]")))r.setAttribute("hidden",""),r.setAttribute("aria-hidden","true")}onShadowClick(r){let n=r.target;if(!n)return;if(n instanceof HTMLDialogElement&&n.classList.contains("crm-dialog")){n.close();return}let o=n.closest("[data-certrev-modal-close]");o&&(r.preventDefault(),o.closest("dialog")?.close())}};function ge(e){try{let t=JSON.parse(e);return t&&typeof t=="object"?t:null}catch{return null}}function rt(e){if(!e)return!1;if(v(e))return!0;let t=e.payload?.lifecycle;return t?!!(t.revokedAt!=null||t.expiresAt&&Date.now()>=new Date(t.expiresAt).getTime()):!1}function nt(){typeof customElements>"u"||customElements.get(A)||customElements.define(A,O)}nt();var ot="[data-ftc-line]",xe=".certrev-memo",ve=".certrev-memo-wrap",it="data-certrev-ftc-neutralized",at="nofollow sponsored noopener noreferrer",he=new WeakSet;function st(e){let t=e.ownerDocument.defaultView;if(!t)return!0;let r=t.getComputedStyle(e);if(r.display==="none"||r.visibility==="hidden"||Number.parseFloat(r.opacity||"1")===0)return!1;let n=e.getBoundingClientRect();return n.width>0&&n.height>0}function ct(e){let t=e.querySelector(ot);return!t||(t.textContent||"").trim()!==U?!1:st(t)}function lt(e){let r=e.ownerDocument.createElement("div");r.setAttribute(it,""),r.style.cssText="font-family:system-ui,-apple-system,sans-serif;font-size:12px;color:#555;padding:12px;line-height:1.4",r.innerHTML=`This CertREV verification cannot be displayed because its required disclosure was not shown. <a href="https://certrev.com" style="color:#555" target="_blank" rel="${at}">Learn more</a>.`,e.replaceWith(r)}function ft(e){let t=Array.from(e.querySelectorAll(xe));if(!t.length)return"unguarded";let r="intact";for(let n of t)ct(n)||(r="tampered",lt(n));return r}function Ce(e){if(he.has(e))return;he.add(e);let t=()=>{ft(e)},r=()=>{t();let n=e.defaultView?.MutationObserver;if(!n)return;let o=Array.from(e.querySelectorAll(ve)),i=Array.from(e.querySelectorAll(xe)).filter(s=>!s.closest(ve));for(let s of[...o,...i])new n(t).observe(s,{childList:!0,subtree:!0,characterData:!0,attributes:!0})};e.readyState==="loading"?e.addEventListener("DOMContentLoaded",r,{once:!0}):r()}var be="data-certrev-acc",_="data-certrev-modal-open",N="data-certrev-initials";var dt=["avatar","certrev-memo__avatar"],Ee=new WeakSet;function Ue(e){let t=e.classList.toggle("open");e.setAttribute("aria-expanded",t?"true":"false")}function we(e){return e==="expert"?"expert":"cert"}function Ae(e,t){let r=e.querySelector(A);return r&&typeof r.open=="function"?r.open(t):!1}function _e(e){return e&&e.closest?e:null}function Se(e){let t=e.getAttribute(N);if(t==null)return;let r=dt.find(o=>e.classList.contains(o));if(!r)return;let n=e.ownerDocument.createElement("span");n.className=`${r} ${r}--initials`,n.setAttribute("aria-hidden","true"),n.textContent=t,e.replaceWith(n)}function pt(e){for(let t of Array.from(e.querySelectorAll(`img[${N}]`)))t.complete&&t.naturalWidth===0&&Se(t)}function ut(e){Ee.has(e)||(Ee.add(e),e.addEventListener("click",t=>{let r=_e(t.target);if(!r)return;let n=r.closest(`[${_}]`);if(n){Ae(e,we(n.getAttribute(_)))&&t.preventDefault();return}let o=r.closest(`[${be}]`);o&&!r.closest("a, button")&&Ue(o)}),e.addEventListener("error",t=>{let r=t.target;r&&r.tagName==="IMG"&&r.hasAttribute(N)&&Se(r)},!0),pt(e),e.addEventListener("keydown",t=>{if(t.key!=="Enter"&&t.key!==" "&&t.key!=="Spacebar")return;let r=_e(t.target);if(!r||r.closest("a, button"))return;let n=r.closest(`[${_}]`);if(n&&Ae(e,we(n.getAttribute(_)))){t.preventDefault();return}let o=r.closest(`[${be}]`);o&&(t.preventDefault(),Ue(o))}))}function De(e){let t=()=>ut(e);e.readyState==="loading"?e.addEventListener("DOMContentLoaded",t,{once:!0}):t()}var mt=[{selector:"main article",tier:"article"},{selector:"article",tier:"article"},{selector:"main",tier:"main"},{selector:".article-template__content",tier:"theme-class"},{selector:'[id^="ArticleContent"]',tier:"theme-class"},{selector:".rte",tier:"theme-class"}],y=[{selector:".article-template__content",tier:"theme-class"},{selector:'[id^="ArticleContent"]',tier:"theme-class"},{selector:".rte",tier:"theme-class"},{selector:"main article",tier:"article"},{selector:"article",tier:"article"},{selector:"main",tier:"main"}],P=y.map(e=>e.selector).join(", "),yt='header, [role="banner"], [class*="announcement"], footer, [role="contentinfo"], nav, [role="navigation"], cart-drawer, .cart-drawer, .drawer, .mini-cart, .modal, [role="dialog"]',u="data-certrev-placement",Te="data-certrev-anchor",gt='script[type="application/ld+json"][data-certrev-graph]',vt=".certrev-card-wrap",Re=".certrev-memo-wrap",ht=".certrev-pill-wrap",ke=384,xt=24,S="#references";function D(e){for(let t=e;t;t=t.parentElement){if(t.hasAttribute("hidden")||t.getAttribute("aria-hidden")==="true")return!1;let r=getComputedStyle(t);if(r.display==="none"||r.visibility==="hidden")return!1}return!0}function z(e){return e.closest(yt)!==null}function Fe(e,t){for(let{selector:r,tier:n}of t)if(e.matches(r))return n;return"article"}function F(e,t,r){for(let{selector:n,tier:o}of r)for(let i of Array.from(e.querySelectorAll(n)))if(i!==t&&!i.contains(t)&&!t.contains(i)&&D(i)&&!z(i))return{el:i,tier:o};return null}function V(e,t){let r=t.getAttribute(u);if(r)return{anchored:r!=="body-fallback",tier:r};let n=t.getAttribute(Te);if(n==="rail"){let a=e.querySelector(S)?.closest(P)??F(e,t,y)?.el??null,c=e.defaultView;if(a&&c&&D(a)&&!z(a)){let d=a.getBoundingClientRect();if(c.innerWidth-d.right>=ke)return t.style.setProperty("--certrev-rail-left",`${Math.round(d.right+xt)}px`),t.setAttribute(u,"rail"),{anchored:!0,tier:"rail"};a.insertAdjacentElement("afterbegin",t);let x=Fe(a,y);return t.setAttribute(u,x),{anchored:!0,tier:x}}return t.setAttribute(u,"body-fallback"),{anchored:!1,tier:"body-fallback"}}let o=n==="bottom"?"bottom":"top",i="body-fallback";if(o==="top"){let a=e.querySelector(S)?.closest(P)??null;if(a&&a!==t&&!a.contains(t)&&!t.contains(a)&&D(a)&&!z(a))a.insertAdjacentElement("afterbegin",t),i=Fe(a,y);else{let c=F(e,t,y);c&&(c.el.insertAdjacentElement("afterbegin",t),i=c.tier)}}else{let s=e.querySelector(S);if(s&&s!==t&&!t.contains(s)&&!s.contains(t)&&D(s))s.insertAdjacentElement("beforebegin",t),i="references";else{let a=F(e,t,mt);a&&(a.el.insertAdjacentElement("afterend",t),i=a.tier)}}return t.setAttribute(u,i),{anchored:i!=="body-fallback",tier:i}}function Ct(e){let t=e.querySelector(gt),r=!1;t&&t.parentNode!==e.head&&(e.head.appendChild(t),r=!0);let n=e.querySelector(vt),o=e.querySelector(Re);return e.querySelector(ht)?.setAttribute(u,"pill-fixed"),{graph:r,card:n?V(e,n):null,memo:o?V(e,o):null}}function bt(e){let t=e.defaultView;if(!t)return;let r=e.querySelector(`${Re}[${Te}="rail"]`);if(!r||r.getAttribute(u)!=="rail")return;let n,o=()=>{n&&clearTimeout(n),n=setTimeout(()=>{if(r.getAttribute(u)!=="rail"){t.removeEventListener("resize",o);return}let s=e.querySelector(S)?.closest(P)??F(e,r,y)?.el??null;(s?t.innerWidth-s.getBoundingClientRect().right:0)<ke&&(r.style.removeProperty("--certrev-rail-left"),r.removeAttribute(u),V(e,r),t.removeEventListener("resize",o))},150)};t.addEventListener("resize",o)}function Le(e){let t=()=>{Ct(e),bt(e)};e.readyState==="loading"?e.addEventListener("DOMContentLoaded",t,{once:!0}):t()}async function Et(e,t){let r=e.querySelector(".certrev-badge");if(!r)return;let n=e.getAttribute("data-delivery-api"),o=e.getAttribute("data-external-id"),i=e.getAttribute("data-platform")??"shopify";if(!n||!o)return;let s;try{s=await t.verify({baseUrl:n,platform:i,externalId:o})}catch{return}s.decision!=="render"&&(r.setAttribute("hidden",""),r.setAttribute("data-certrev-suppressed",s.reason))}function Ie(e,t){let r=()=>{for(let n of Array.from(e.querySelectorAll("certrev-badge[revalidate]")))Et(n,t)};e.readyState==="loading"?e.addEventListener("DOMContentLoaded",r,{once:!0}):r()}function Me(e,t=fetch){return async r=>{let o=`${r.baseUrl.replace(/\/+$/,"")}/api/cert/v1/delivery/${encodeURIComponent(r.platform)}/${encodeURIComponent(r.externalId)}`,i=await t(o,{headers:{accept:"application/json"}});if(!i.ok)throw new Error(`cert delivery ${i.status}`);let s=await i.json();return I(s,e,{platform:r.platform,externalId:r.externalId,liveContentHash:null,now:new Date})}}var Ut="cert-issuer-1",wt=`-----BEGIN PUBLIC KEY-----
555
+ `;var ae="nofollow sponsored noopener noreferrer",qe=/^(dr|prof|professor|mr|mrs|ms|mx|rev|sir|dame)\.?\s+/i;function ie(e){let t=f(e).replace(qe,"").trim(),r=t.indexOf(",");return(r===-1?t:t.slice(0,r)).trim()}function je(e){let t=ie(e).split(/\s+/).filter(Boolean);return t.length===0?"":t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[t.length-1][0]).toUpperCase()}function Ge(e){return ie(e)}function Je(e){return f(e).replace(/^https?:\/\//i,"").replace(/\/$/,"")}function se(e){let t=f(e).trim();return t&&/^https?:\/\//i.test(t)?t:"#"}function Ze(e){return(f(e?.cardLabel)||f(e?.fullName)||f(e?.abbreviation)).trim()}function ce(e){let t=[],r=Array.isArray(e?.credentials)?e.credentials:[];for(let n of r){let o=Ze(n);o&&!t.includes(o)&&t.push(o)}return t}function We(e,t){return t?.showBio===!1?"":(f(e?.background)||f(e?.bio)).trim()}function le(e,t,r,n){let o=f(e?.photoUrl).trim();if(n&&/^https?:\/\//i.test(o)){let a=r.includes("--64")?64:56,s=Q(o,a===64?128:112);return`<img class="crm-avatar ${r}" src="${l(s)}" alt="" width="${a}" height="${a}" decoding="async">`}return`<span class="crm-avatar ${r}">${l(je(t))}</span>`}var fe='<button type="button" class="crm-close" data-certrev-modal-close aria-label="Close">&times;</button>';function de(e){return`<div class="crm-head">${re(16,"#ffffff")}<span class="crm-head__eyebrow">${l(e)}</span><span class="crm-head__wordmark">CertREV</span></div>`}function pe(e){return`<span class="${e}">${ne(8)}Certified</span>`}function ue(e){let t=f(e?.compensationCue).trim();return`<div class="crm-disclosure">${t?`<span class="crm-disclosure__cue">${l(t)}</span> `:""}${l(te)}</div>`}function me(e){let t=e.expert??null,r=f(t?.displayName).trim();if(!r)return null;let n=e.display?.showExpertPhoto!==!1,o=ce(t).join(" \xB7 "),a=M(e.certifiedAt)??"",s=f(e.displayCertId).trim(),i=f(e.articleTitle).trim(),c=f(e.verifyUrl).trim(),d=Ge(r),h=i?`<div class="crm-certifies"><div class="crm-certifies__eyebrow">Certifies the article</div><div class="crm-certifies__title">${l(i)}</div></div>`:"",x=s?`<div class="crm-meta__col"><div class="crm-meta__label">Certificate ID</div><div class="crm-meta__value crm-meta__value--mono">${l(s)}</div></div>`:"",Me=c?`<div class="crm-sig__url">${l(Je(c))}</div>`:"";return`${fe}${de("Certificate of Expert Review")}<div class="crm-body--cert"><div class="crm-expert-row">${le(t,r,"crm-avatar--56",n)}<div class="crm-expert-row__info"><div class="crm-expert-row__eyebrow">Reviewing Expert</div><div class="crm-expert-row__name">${l(r)}</div>${o?`<div class="crm-expert-row__creds">${l(o)}</div>`:""}</div></div>${h}<div class="crm-meta"><div class="crm-meta__col"><div class="crm-meta__label">Issued</div><div class="crm-meta__value">${l(a)}</div></div>${x}<div class="crm-meta__col"><div class="crm-meta__label">Status</div><div class="crm-meta__status">${pe("crm-chip")}</div></div></div><div class="crm-sig"><div><div class="crm-sig__name">${l(d)}</div><div class="crm-sig__rule"></div>${Me}</div>${oe("cert")}</div>${ue(t)}<div class="crm-actions"><a class="crm-cta" href="${l(se(c))}" target="_blank" rel="${ae}">View full certificate</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`}function ye(e){let t=e.expert??null,r=f(t?.displayName).trim();if(!r)return null;let n=e.display?.showExpertPhoto!==!1,o=ce(t),a=We(t,e.display),s=M(e.certifiedAt),i=o.length?`<div class="crm-chips">${o.map(h=>`<span class="crm-chips__chip">${l(h)}</span>`).join("")}</div>`:"",c=a?`<p class="crm-bio">${l(a)}</p>`:"",d=s?`Independently reviewed \xB7 Certified ${l(s)}`:"Independently reviewed";return`${fe}${de("Verified reviewer")}<div class="crm-body--expert"><div class="crm-id">${le(t,r,"crm-avatar--64",n)}<div class="crm-id__info"><div class="crm-id__name">${l(r)}</div></div></div>${i}${c}<div class="crm-trust">${pe("crm-trust__chip")}<span class="crm-trust__text">${d}</span></div>${ue(t)}<div class="crm-actions"><a class="crm-cta" href="${l(se(t?.profileUrl))}" target="_blank" rel="${ae}">View full profile on CertREV</a><button type="button" class="crm-ghost" data-certrev-modal-close>Close</button></div></div>`}var w="certrev-cert-modal",ge="[data-certrev-cert]";function O(e){let t=e.closest(ge);for(let r=e;r;r=r.parentElement){let n=Array.from(r.querySelectorAll(w)).filter(o=>o.closest(ge)===t);if(n.length===1)return{modal:n[0],reason:null};if(n.length>1)return{modal:null,reason:"ambiguous",count:n.length};if(r===t)break}return{modal:null,reason:"none",count:0}}var E=null;function Ye(){return typeof CSSStyleSheet<"u"&&"replaceSync"in CSSStyleSheet.prototype&&"adoptedStyleSheets"in Document.prototype}function Xe(){return Ye()?(E||(E=new CSSStyleSheet,E.replaceSync(I)),E):null}var ve=!1;function Qe(e){if(ve||(ve=!0,e.querySelector("style[data-certrev-modal-fonts]")))return;if(!e.querySelector("link[data-certrev-modal-preconnect]")){let r=e.createElement("link");r.rel="preconnect",r.href=X,r.crossOrigin="",r.setAttribute("data-certrev-modal-preconnect",""),e.head.appendChild(r)}let t=e.createElement("style");t.textContent=Y,t.setAttribute("data-certrev-modal-fonts",""),e.head.appendChild(t)}var $=class extends HTMLElement{constructor(){super();this.rendered=!1;this.content=null;this.fetchInFlight=null;this.root=this.attachShadow({mode:"open"});let r=Xe();if(r)this.root.adoptedStyleSheets=[r];else{let n=document.createElement("style");n.textContent=I,this.root.appendChild(n)}this.root.addEventListener("click",n=>this.onShadowClick(n))}open(r){return this.getAttribute("data-fonts")!=="host"&&Qe(document),this.ensureRendered()?(this.show(r),!0):this.hasFetchSource()?(this.fetchThenShow(r),!0):!1}ensureRendered(){if(this.rendered)return this.content!=null;let r=this.readSyncContent();return r?(this.content=r,this.renderDialogs(r),this.rendered=!0,!0):!1}readSyncContent(){let r=this.getAttribute("data-envelope");if(r)return he(r);let n=this.querySelector("script[data-certrev-envelope]");return n?.textContent?he(n.textContent):null}hasFetchSource(){return!!(this.getAttribute("data-delivery-api")&&this.getAttribute("data-platform")&&this.getAttribute("data-external-id"))}async fetchThenShow(r){if(!this.fetchInFlight){let n=(this.getAttribute("data-delivery-api")||"").replace(/\/$/,""),o=this.getAttribute("data-platform")||"",a=this.getAttribute("data-external-id")||"";this.fetchInFlight=(async()=>{try{let s=await fetch(`${n}/api/cert/v1/delivery/${encodeURIComponent(o)}/${encodeURIComponent(a)}`,{cache:"no-store",credentials:"omit"});if(!s.ok)return;let i=await s.json();if(et(i)){this.markSuppressed();return}let c=v(i)?void 0:i.payload?.content;c&&(this.content=c,this.renderDialogs(c),this.rendered=!0)}catch{}})()}await this.fetchInFlight,this.rendered&&this.show(r)}renderDialogs(r){let n=me(r),o=ye(r),a=document.createElement("div");a.innerHTML=`${n?`<dialog id="cert" class="crm-dialog crm-dialog--cert" aria-label="CertREV certificate">${n}</dialog>`:""}${o?`<dialog id="expert" class="crm-dialog crm-dialog--expert" aria-label="Verified reviewer profile">${o}</dialog>`:""}`;for(let s of Array.from(a.childNodes))this.root.appendChild(s)}show(r){let n=this.root.getElementById(r);n&&typeof n.showModal=="function"&&!n.open&&n.showModal()}markSuppressed(){this.setAttribute("data-certrev-suppressed","");for(let r of Array.from(this.ownerDocument.querySelectorAll("[data-certrev-modal-open]")))O(r).modal===this&&(r.setAttribute("hidden",""),r.setAttribute("aria-hidden","true"))}onShadowClick(r){let n=r.target;if(!n)return;if(n instanceof HTMLDialogElement&&n.classList.contains("crm-dialog")){n.close();return}let o=n.closest("[data-certrev-modal-close]");o&&(r.preventDefault(),o.closest("dialog")?.close())}};function he(e){try{let t=JSON.parse(e);return t&&typeof t=="object"?t:null}catch{return null}}function et(e){if(!e)return!1;if(v(e))return!0;let t=e.payload?.lifecycle;return t?!!(t.revokedAt!=null||t.expiresAt&&Date.now()>=new Date(t.expiresAt).getTime()):!1}function tt(){typeof customElements>"u"||customElements.get(w)||customElements.define(w,$)}tt();var xe="data-certrev-acc",A="data-certrev-modal-open",N="data-certrev-initials";var rt="data-certrev-modal-unresolved",nt="certrev:modal-unresolved",ot=["avatar","certrev-memo__avatar"],Ce=new WeakSet;function be(e){let t=e.classList.toggle("open");e.setAttribute("aria-expanded",t?"true":"false")}function Ue(e){return e==="expert"?"expert":"cert"}function Ee(e,t){let r=O(e);if(r.modal){let n=r.modal;return typeof n.open=="function"?n.open(t):!1}return r.reason==="ambiguous"&&(e.setAttribute(rt,r.reason),e.dispatchEvent(new CustomEvent(nt,{bubbles:!0,detail:{reason:r.reason,modals:r.count}}))),!1}function we(e){return e&&e.closest?e:null}function Ae(e){let t=e.getAttribute(N);if(t==null)return;let r=ot.find(o=>e.classList.contains(o));if(!r)return;let n=e.ownerDocument.createElement("span");n.className=`${r} ${r}--initials`,n.setAttribute("aria-hidden","true"),n.textContent=t,e.replaceWith(n)}function at(e){for(let t of Array.from(e.querySelectorAll(`img[${N}]`)))t.complete&&t.naturalWidth===0&&Ae(t)}function it(e){Ce.has(e)||(Ce.add(e),e.addEventListener("click",t=>{let r=we(t.target);if(!r)return;let n=r.closest(`[${A}]`);if(n){Ee(n,Ue(n.getAttribute(A)))&&t.preventDefault();return}let o=r.closest(`[${xe}]`);o&&!r.closest("a, button")&&be(o)}),e.addEventListener("error",t=>{let r=t.target;r&&r.tagName==="IMG"&&r.hasAttribute(N)&&Ae(r)},!0),at(e),e.addEventListener("keydown",t=>{if(t.key!=="Enter"&&t.key!==" "&&t.key!=="Spacebar")return;let r=we(t.target);if(!r||r.closest("a, button"))return;let n=r.closest(`[${A}]`);if(n&&Ee(n,Ue(n.getAttribute(A)))){t.preventDefault();return}let o=r.closest(`[${xe}]`);o&&(t.preventDefault(),be(o))}))}function _e(e){let t=()=>it(e);e.readyState==="loading"?e.addEventListener("DOMContentLoaded",t,{once:!0}):t()}var st=[{selector:"main article",tier:"article"},{selector:"article",tier:"article"},{selector:"main",tier:"main"},{selector:".article-template__content",tier:"theme-class"},{selector:'[id^="ArticleContent"]',tier:"theme-class"},{selector:".rte",tier:"theme-class"}],y=[{selector:".article-template__content",tier:"theme-class"},{selector:'[id^="ArticleContent"]',tier:"theme-class"},{selector:".rte",tier:"theme-class"},{selector:"main article",tier:"article"},{selector:"article",tier:"article"},{selector:"main",tier:"main"}],P=y.map(e=>e.selector).join(", "),ct='header, [role="banner"], [class*="announcement"], footer, [role="contentinfo"], nav, [role="navigation"], cart-drawer, .cart-drawer, .drawer, .mini-cart, .modal, [role="dialog"]',u="data-certrev-placement",De="data-certrev-anchor",lt='script[type="application/ld+json"][data-certrev-graph]',ft=".certrev-card-wrap",Fe=".certrev-memo-wrap",dt=".certrev-pill-wrap",Te=384,pt=24,_="#references";function S(e){for(let t=e;t;t=t.parentElement){if(t.hasAttribute("hidden")||t.getAttribute("aria-hidden")==="true")return!1;let r=getComputedStyle(t);if(r.display==="none"||r.visibility==="hidden")return!1}return!0}function z(e){return e.closest(ct)!==null}function Se(e,t){for(let{selector:r,tier:n}of t)if(e.matches(r))return n;return"article"}function D(e,t,r){for(let{selector:n,tier:o}of r)for(let a of Array.from(e.querySelectorAll(n)))if(a!==t&&!a.contains(t)&&!t.contains(a)&&S(a)&&!z(a))return{el:a,tier:o};return null}function V(e,t){let r=t.getAttribute(u);if(r)return{anchored:r!=="body-fallback",tier:r};let n=t.getAttribute(De);if(n==="rail"){let i=e.querySelector(_)?.closest(P)??D(e,t,y)?.el??null,c=e.defaultView;if(i&&c&&S(i)&&!z(i)){let d=i.getBoundingClientRect();if(c.innerWidth-d.right>=Te)return t.style.setProperty("--certrev-rail-left",`${Math.round(d.right+pt)}px`),t.setAttribute(u,"rail"),{anchored:!0,tier:"rail"};i.insertAdjacentElement("afterbegin",t);let x=Se(i,y);return t.setAttribute(u,x),{anchored:!0,tier:x}}return t.setAttribute(u,"body-fallback"),{anchored:!1,tier:"body-fallback"}}let o=n==="bottom"?"bottom":"top",a="body-fallback";if(o==="top"){let i=e.querySelector(_)?.closest(P)??null;if(i&&i!==t&&!i.contains(t)&&!t.contains(i)&&S(i)&&!z(i))i.insertAdjacentElement("afterbegin",t),a=Se(i,y);else{let c=D(e,t,y);c&&(c.el.insertAdjacentElement("afterbegin",t),a=c.tier)}}else{let s=e.querySelector(_);if(s&&s!==t&&!t.contains(s)&&!s.contains(t)&&S(s))s.insertAdjacentElement("beforebegin",t),a="references";else{let i=D(e,t,st);i&&(i.el.insertAdjacentElement("afterend",t),a=i.tier)}}return t.setAttribute(u,a),{anchored:a!=="body-fallback",tier:a}}function ut(e){let t=e.querySelector(lt),r=!1;t&&t.parentNode!==e.head&&(e.head.appendChild(t),r=!0);let n=e.querySelector(ft),o=e.querySelector(Fe);return e.querySelector(dt)?.setAttribute(u,"pill-fixed"),{graph:r,card:n?V(e,n):null,memo:o?V(e,o):null}}function mt(e){let t=e.defaultView;if(!t)return;let r=e.querySelector(`${Fe}[${De}="rail"]`);if(!r||r.getAttribute(u)!=="rail")return;let n,o=()=>{n&&clearTimeout(n),n=setTimeout(()=>{if(r.getAttribute(u)!=="rail"){t.removeEventListener("resize",o);return}let s=e.querySelector(_)?.closest(P)??D(e,r,y)?.el??null;(s?t.innerWidth-s.getBoundingClientRect().right:0)<Te&&(r.style.removeProperty("--certrev-rail-left"),r.removeAttribute(u),V(e,r),t.removeEventListener("resize",o))},150)};t.addEventListener("resize",o)}function Re(e){let t=()=>{ut(e),mt(e)};e.readyState==="loading"?e.addEventListener("DOMContentLoaded",t,{once:!0}):t()}async function yt(e,t){let r=e.querySelector(".certrev-badge");if(!r)return;let n=e.getAttribute("data-delivery-api"),o=e.getAttribute("data-external-id"),a=e.getAttribute("data-platform")??"shopify";if(!n||!o)return;let s;try{s=await t.verify({baseUrl:n,platform:a,externalId:o})}catch{return}s.decision!=="render"&&(r.setAttribute("hidden",""),r.setAttribute("data-certrev-suppressed",s.reason))}function ke(e,t){let r=()=>{for(let n of Array.from(e.querySelectorAll("certrev-badge[revalidate]")))yt(n,t)};e.readyState==="loading"?e.addEventListener("DOMContentLoaded",r,{once:!0}):r()}function Le(e,t=fetch){return async r=>{let o=`${r.baseUrl.replace(/\/+$/,"")}/api/cert/v1/delivery/${encodeURIComponent(r.platform)}/${encodeURIComponent(r.externalId)}`,a=await t(o,{headers:{accept:"application/json"}});if(!a.ok)throw new Error(`cert delivery ${a.status}`);let s=await a.json();return L(s,e,{platform:r.platform,externalId:r.externalId,liveContentHash:null,now:new Date})}}var gt="cert-issuer-1",vt=`-----BEGIN PUBLIC KEY-----
556
556
  MCowBQYDK2VwAyEAMWN956IOPjpAq900dL428VzA28TO/pVXnq3brwqUmwM=
557
- -----END PUBLIC KEY-----`,At=e=>e===Ut?{format:"pem",pem:wt}:null;typeof document<"u"&&(Le(document),De(document),Ce(document),Ie(document,{verify:Me(At)}));})();
557
+ -----END PUBLIC KEY-----`,ht=e=>e===gt?{format:"pem",pem:vt}:null;typeof document<"u"&&(Re(document),_e(document),ke(document,{verify:Le(ht)}));})();
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Public names kept only so a patch release never breaks a compiling integration (the semver
3
+ * contract at the head of CHANGELOG.md). Each one does nothing it used to do; removal is for 2.0.
4
+ */
5
+ /** Dispatched on the document, once per document, on the first call of a removed API, so a caller
6
+ * that still relies on it can see that it does nothing. `detail: { api, removedIn }`. */
7
+ export declare const DEPRECATED_API_EVENT = "certrev:deprecated-api";
8
+ /**
9
+ * @deprecated Removed in 1.1.1: the runtime FTC disclosure guard is gone. This installs nothing,
10
+ * checks nothing and never hides or replaces a face; whether a face shows its disclosure is settled
11
+ * where the face is configured. The first call per document dispatches {@link DEPRECATED_API_EVENT}.
12
+ * Will be deleted in 2.0.
13
+ */
14
+ export declare function installFtcGuard(doc: Document): void;
15
+ //# sourceMappingURL=deprecated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deprecated.d.ts","sourceRoot":"","sources":["../../src/modal/deprecated.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;0FAC0F;AAC1F,eAAO,MAAM,oBAAoB,2BAA2B,CAAA;AAK5D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAMnD"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Public names kept only so a patch release never breaks a compiling integration (the semver
3
+ * contract at the head of CHANGELOG.md). Each one does nothing it used to do; removal is for 2.0.
4
+ */
5
+ /** Dispatched on the document, once per document, on the first call of a removed API, so a caller
6
+ * that still relies on it can see that it does nothing. `detail: { api, removedIn }`. */
7
+ export const DEPRECATED_API_EVENT = 'certrev:deprecated-api';
8
+ /** Documents that have already been told, so repeated calls dispatch once. */
9
+ const announcedDocs = new WeakSet();
10
+ /**
11
+ * @deprecated Removed in 1.1.1: the runtime FTC disclosure guard is gone. This installs nothing,
12
+ * checks nothing and never hides or replaces a face; whether a face shows its disclosure is settled
13
+ * where the face is configured. The first call per document dispatches {@link DEPRECATED_API_EVENT}.
14
+ * Will be deleted in 2.0.
15
+ */
16
+ export function installFtcGuard(doc) {
17
+ if (announcedDocs.has(doc))
18
+ return;
19
+ announcedDocs.add(doc);
20
+ doc.dispatchEvent(new CustomEvent(DEPRECATED_API_EVENT, { detail: { api: 'installFtcGuard', removedIn: '1.1.1' } }));
21
+ }
22
+ //# sourceMappingURL=deprecated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deprecated.js","sourceRoot":"","sources":["../../src/modal/deprecated.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;0FAC0F;AAC1F,MAAM,CAAC,MAAM,oBAAoB,GAAG,wBAAwB,CAAA;AAE5D,8EAA8E;AAC9E,MAAM,aAAa,GAAG,IAAI,OAAO,EAAY,CAAA;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAa;IAC5C,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAM;IAClC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACtB,GAAG,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,iBAAiB,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CACjG,CAAA;AACF,CAAC"}
@@ -4,9 +4,13 @@
4
4
  * module. Legally load-bearing: the curly apostrophe (U+2019) in "article’s"
5
5
  * is byte-exact; a reword is a contract divergence.
6
6
  *
7
- * Kept as its OWN module (imported by both ftc-guard + display-strings, exactly as in portal) so
8
- * the browser bundle emits the same `var` structure as the deployed certrev-cert.js — do not merge
9
- * it into display-strings.ts (that consolidation drops one `var` and breaks byte-parity).
7
+ * Kept as its OWN module (imported by display-strings, exactly as in portal) so the browser bundle
8
+ * emits the same `var` structure as the deployed certrev-cert.js — do not merge it into
9
+ * display-strings.ts (that consolidation drops one `var` and breaks byte-parity).
10
+ *
11
+ * It is the text the faces RENDER, nothing more. Since 1.1.1 nothing in this package checks at
12
+ * runtime that it is present or visible (the `ftc-guard` kill switch is gone): whether a face shows
13
+ * its disclosure is settled where the face is configured, not by hiding or replacing it in the page.
10
14
  */
11
15
  export declare const FTC_DISCLOSURE_LINE: "Independent editorial review of this article\u2019s text and sources. Not a product endorsement, nor medical advice.";
12
16
  //# sourceMappingURL=ftc-disclosure.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ftc-disclosure.d.ts","sourceRoot":"","sources":["../../src/modal/ftc-disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,mBAAmB,EAC/B,sHAA0H,CAAC"}
1
+ {"version":3,"file":"ftc-disclosure.d.ts","sourceRoot":"","sources":["../../src/modal/ftc-disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,mBAAmB,EAC/B,sHAA0H,CAAC"}
@@ -4,9 +4,13 @@
4
4
  * module. Legally load-bearing: the curly apostrophe (U+2019) in "article’s"
5
5
  * is byte-exact; a reword is a contract divergence.
6
6
  *
7
- * Kept as its OWN module (imported by both ftc-guard + display-strings, exactly as in portal) so
8
- * the browser bundle emits the same `var` structure as the deployed certrev-cert.js — do not merge
9
- * it into display-strings.ts (that consolidation drops one `var` and breaks byte-parity).
7
+ * Kept as its OWN module (imported by display-strings, exactly as in portal) so the browser bundle
8
+ * emits the same `var` structure as the deployed certrev-cert.js — do not merge it into
9
+ * display-strings.ts (that consolidation drops one `var` and breaks byte-parity).
10
+ *
11
+ * It is the text the faces RENDER, nothing more. Since 1.1.1 nothing in this package checks at
12
+ * runtime that it is present or visible (the `ftc-guard` kill switch is gone): whether a face shows
13
+ * its disclosure is settled where the face is configured, not by hiding or replacing it in the page.
10
14
  */
11
15
  export const FTC_DISCLOSURE_LINE = "Independent editorial review of this article’s text and sources. Not a product endorsement, nor medical advice.";
12
16
  //# sourceMappingURL=ftc-disclosure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ftc-disclosure.js","sourceRoot":"","sources":["../../src/modal/ftc-disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,iHAA0H,CAAC"}
1
+ {"version":3,"file":"ftc-disclosure.js","sourceRoot":"","sources":["../../src/modal/ftc-disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,iHAA0H,CAAC"}
@@ -6,13 +6,14 @@
6
6
  * storefront (`<script src=".../dist/modal/certrev-cert.js">`) instead of vendoring a copy.
7
7
  *
8
8
  * Importing this module as ESM has the SAME side effect as loading the IIFE: it registers the
9
- * `<certrev-cert-modal>` element and (in a browser) runs placement + interactions + FTC guard +
10
- * badge revalidation. Bundler users: `import '@certrev/cert-block/modal'`.
9
+ * `<certrev-cert-modal>` element and (in a browser) runs placement + interactions + badge
10
+ * revalidation (no FTC guard since 1.1.1). Bundler users: `import '@certrev/cert-block/modal'`.
11
11
  */
12
12
  import "./certrev-cert.entry.js";
13
13
  export { CERT_ISSUER_KID, CERT_ISSUER_PUBLIC_KEY_PEM, } from "./certrev-cert.entry.js";
14
14
  export { CERT_MODAL_TAG } from "./certrev-cert-modal.js";
15
- export { installFtcGuard } from "./ftc-guard.js";
15
+ /** @deprecated Since 1.1.1 a no-op (the runtime FTC guard was removed); deleted in 2.0. */
16
+ export { installFtcGuard } from "./deprecated.js";
16
17
  export { initCertInteractionsOnReady } from "./interactions.js";
17
18
  export { initCertPlacement } from "./placement.js";
18
19
  export { initBadgeRevalidation, type RevalidateDeps, revalidateBadge, } from "./revalidate.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,yBAAyB,CAAC;AAKjC,OAAO,EACN,eAAe,EACf,0BAA0B,GAC1B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EACN,qBAAqB,EACrB,KAAK,cAAc,EACnB,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,yBAAyB,CAAC;AAKjC,OAAO,EACN,eAAe,EACf,0BAA0B,GAC1B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,2FAA2F;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EACN,qBAAqB,EACrB,KAAK,cAAc,EACnB,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -6,8 +6,8 @@
6
6
  * storefront (`<script src=".../dist/modal/certrev-cert.js">`) instead of vendoring a copy.
7
7
  *
8
8
  * Importing this module as ESM has the SAME side effect as loading the IIFE: it registers the
9
- * `<certrev-cert-modal>` element and (in a browser) runs placement + interactions + FTC guard +
10
- * badge revalidation. Bundler users: `import '@certrev/cert-block/modal'`.
9
+ * `<certrev-cert-modal>` element and (in a browser) runs placement + interactions + badge
10
+ * revalidation (no FTC guard since 1.1.1). Bundler users: `import '@certrev/cert-block/modal'`.
11
11
  */
12
12
  // Side-effect: register the element + (in a browser) kick off the DOM passes.
13
13
  import "./certrev-cert.entry.js";
@@ -17,7 +17,8 @@ import "./certrev-cert.entry.js";
17
17
  export { CERT_ISSUER_KID, CERT_ISSUER_PUBLIC_KEY_PEM, } from "./certrev-cert.entry.js";
18
18
  // Composable entry points for advanced consumers (the IIFE wires these itself).
19
19
  export { CERT_MODAL_TAG } from "./certrev-cert-modal.js";
20
- export { installFtcGuard } from "./ftc-guard.js";
20
+ /** @deprecated Since 1.1.1 a no-op (the runtime FTC guard was removed); deleted in 2.0. */
21
+ export { installFtcGuard } from "./deprecated.js";
21
22
  export { initCertInteractionsOnReady } from "./interactions.js";
22
23
  export { initCertPlacement } from "./placement.js";
23
24
  export { initBadgeRevalidation, revalidateBadge, } from "./revalidate.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,8EAA8E;AAC9E,OAAO,yBAAyB,CAAC;AAEjC,+FAA+F;AAC/F,iGAAiG;AACjG,0FAA0F;AAC1F,OAAO,EACN,eAAe,EACf,0BAA0B,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EACN,qBAAqB,EAErB,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,8EAA8E;AAC9E,OAAO,yBAAyB,CAAC;AAEjC,+FAA+F;AAC/F,iGAAiG;AACjG,0FAA0F;AAC1F,OAAO,EACN,eAAe,EACf,0BAA0B,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,2FAA2F;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EACN,qBAAqB,EAErB,eAAe,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -8,8 +8,8 @@
8
8
  * (revealing the row's `.acc-bio` in place; the name caret rotates via CSS) and mirrors the
9
9
  * state on `aria-expanded`. A click on a link inside the row (e.g. the "Compensated expert"
10
10
  * cue) is NOT a toggle. Keyboard: Enter/Space on the role=button row.
11
- * • In-page modals: a `[data-certrev-modal-open]` control opens the unified
12
- * `<certrev-cert-modal>` element via its `.open('cert'|'expert')` method. Bare /
11
+ * • In-page modals: a `[data-certrev-modal-open]` control opens its OWN face's
12
+ * `<certrev-cert-modal>` element (`ownCertModal`) via its `.open('cert'|'expert')` method. Bare /
13
13
  * `"cert"` opens the certificate dialog; `"expert"` opens the reviewer dialog. With no JS / no
14
14
  * element / no envelope a link control falls back to its href (the certificate or the CertREV
15
15
  * profile page). The element owns its OWN close plumbing (× / Close / backdrop / Esc) inside its
@@ -21,6 +21,12 @@ export declare const ACC_ATTR = "data-certrev-acc";
21
21
  export declare const MODAL_OPEN_ATTR = "data-certrev-modal-open";
22
22
  export declare const INITIALS_ATTR = "data-certrev-initials";
23
23
  export declare const CARD_SELECTOR = ".certrev-card";
24
+ /** Stamped on a control that could not tell which modal is its own (value: the reason), beside the
25
+ * bubbling {@link MODAL_UNRESOLVED_EVENT}, so the miss is inspectable rather than a silent link. */
26
+ export declare const MODAL_UNRESOLVED_ATTR = "data-certrev-modal-unresolved";
27
+ /** Dispatched on a control whose face has no modal of its own but sits between other faces'
28
+ * (`ownCertModal` → `ambiguous`). `detail: { reason: 'ambiguous', modals }`. */
29
+ export declare const MODAL_UNRESOLVED_EVENT = "certrev:modal-unresolved";
24
30
  /** The dialog a `data-certrev-modal-open` control targets. */
25
31
  export type ModalKind = 'cert' | 'expert';
26
32
  /** Toggle a contributor row's accordion bio open/closed (the `.open` class drives the CSS reveal +
@@ -29,11 +35,21 @@ export declare function toggleAccordion(row: Element): void;
29
35
  /** Resolve a `data-certrev-modal-open` value to the dialog it opens. `"expert"` opens the reviewer
30
36
  * modal; anything else (the bare attribute, or `"cert"`) opens the certificate modal. */
31
37
  export declare function modalTargetKind(value: string | null): ModalKind;
32
- /** Open a cert dialog via the `<certrev-cert-modal>` element. Returns false (so the caller lets an
33
- * href fall back) when the element is absent or declines (no envelope + no fetch source). */
38
+ /** Open a cert dialog via the document's FIRST `<certrev-cert-modal>` element: a page-level helper
39
+ * for a page with one face. Controls go through `openOwnModal`, which finds their own face's element.
40
+ * Returns false (so the caller lets an href fall back) when the element is absent or declines (no
41
+ * envelope + no fetch source). */
34
42
  export declare function openModal(doc: Document, kind: ModalKind): boolean;
35
43
  /** Open the page's certificate modal (backward-compatible wrapper over openModal). */
36
44
  export declare function openCertModal(doc: Document): boolean;
45
+ /**
46
+ * Open a dialog of `control`'s OWN face's `<certrev-cert-modal>` (see `ownCertModal`), which is what
47
+ * the delegated click / key handlers do. Returns false (so a link control follows its own href) when
48
+ * the face has no modal, the element declines, or the control cannot tell which modal is its own; in
49
+ * that last case it is stamped `data-certrev-modal-unresolved="ambiguous"` and receives
50
+ * `certrev:modal-unresolved`, and another face's certificate is never opened in its place.
51
+ */
52
+ export declare function openOwnModal(control: Element, kind: ModalKind): boolean;
37
53
  /**
38
54
  * Replace a broken avatar `<img>` with its initials placeholder — the SAME markup the Liquid emits
39
55
  * when no photo URL is present. The SSR can't know a present URL will 404 (the canary's expert photo
@@ -1 +1 @@
1
- {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/modal/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,eAAO,MAAM,QAAQ,qBAAqB,CAAA;AAC1C,eAAO,MAAM,eAAe,4BAA4B,CAAA;AACxD,eAAO,MAAM,aAAa,0BAA0B,CAAA;AACpD,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAE5C,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAczC;6DAC6D;AAC7D,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAGlD;AAED;0FAC0F;AAC1F,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE/D;AAED;8FAC8F;AAC9F,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAIjE;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAEpD;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAU5D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAItD;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAyDxD;AAED,qDAAqD;AACrD,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAI/D"}
1
+ {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/modal/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,eAAO,MAAM,QAAQ,qBAAqB,CAAA;AAC1C,eAAO,MAAM,eAAe,4BAA4B,CAAA;AACxD,eAAO,MAAM,aAAa,0BAA0B,CAAA;AACpD,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAC5C;qGACqG;AACrG,eAAO,MAAM,qBAAqB,kCAAkC,CAAA;AACpE;iFACiF;AACjF,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAEhE,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAczC;6DAC6D;AAC7D,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAGlD;AAED;0FAC0F;AAC1F,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE/D;AAED;;;mCAGmC;AACnC,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAIjE;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAavE;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAU5D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAItD;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAyDxD;AAED,qDAAqD;AACrD,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAI/D"}
@@ -8,8 +8,8 @@
8
8
  * (revealing the row's `.acc-bio` in place; the name caret rotates via CSS) and mirrors the
9
9
  * state on `aria-expanded`. A click on a link inside the row (e.g. the "Compensated expert"
10
10
  * cue) is NOT a toggle. Keyboard: Enter/Space on the role=button row.
11
- * • In-page modals: a `[data-certrev-modal-open]` control opens the unified
12
- * `<certrev-cert-modal>` element via its `.open('cert'|'expert')` method. Bare /
11
+ * • In-page modals: a `[data-certrev-modal-open]` control opens its OWN face's
12
+ * `<certrev-cert-modal>` element (`ownCertModal`) via its `.open('cert'|'expert')` method. Bare /
13
13
  * `"cert"` opens the certificate dialog; `"expert"` opens the reviewer dialog. With no JS / no
14
14
  * element / no envelope a link control falls back to its href (the certificate or the CertREV
15
15
  * profile page). The element owns its OWN close plumbing (× / Close / backdrop / Esc) inside its
@@ -17,11 +17,17 @@
17
17
  *
18
18
  * No crypto, no network — pure DOM. Idempotent install (guarded so a double-load can't double-bind).
19
19
  */
20
- import { CERT_MODAL_TAG } from './certrev-cert-modal.js';
20
+ import { CERT_MODAL_TAG, ownCertModal } from './certrev-cert-modal.js';
21
21
  export const ACC_ATTR = 'data-certrev-acc';
22
22
  export const MODAL_OPEN_ATTR = 'data-certrev-modal-open';
23
23
  export const INITIALS_ATTR = 'data-certrev-initials';
24
24
  export const CARD_SELECTOR = '.certrev-card';
25
+ /** Stamped on a control that could not tell which modal is its own (value: the reason), beside the
26
+ * bubbling {@link MODAL_UNRESOLVED_EVENT}, so the miss is inspectable rather than a silent link. */
27
+ export const MODAL_UNRESOLVED_ATTR = 'data-certrev-modal-unresolved';
28
+ /** Dispatched on a control whose face has no modal of its own but sits between other faces'
29
+ * (`ownCertModal` → `ambiguous`). `detail: { reason: 'ambiguous', modals }`. */
30
+ export const MODAL_UNRESOLVED_EVENT = 'certrev:modal-unresolved';
25
31
  /** Avatar base classes whose `--initials` variant is the SSR no-photo fallback (kept in lockstep
26
32
  * with certrev-badge.liquid / certrev-memo.liquid). A broken <img> is swapped to `{base} {base}--initials`. */
27
33
  const AVATAR_BASE_CLASSES = ['avatar', 'certrev-memo__avatar'];
@@ -38,8 +44,10 @@ export function toggleAccordion(row) {
38
44
  export function modalTargetKind(value) {
39
45
  return value === 'expert' ? 'expert' : 'cert';
40
46
  }
41
- /** Open a cert dialog via the `<certrev-cert-modal>` element. Returns false (so the caller lets an
42
- * href fall back) when the element is absent or declines (no envelope + no fetch source). */
47
+ /** Open a cert dialog via the document's FIRST `<certrev-cert-modal>` element: a page-level helper
48
+ * for a page with one face. Controls go through `openOwnModal`, which finds their own face's element.
49
+ * Returns false (so the caller lets an href fall back) when the element is absent or declines (no
50
+ * envelope + no fetch source). */
43
51
  export function openModal(doc, kind) {
44
52
  const el = doc.querySelector(CERT_MODAL_TAG);
45
53
  if (el && typeof el.open === 'function')
@@ -50,6 +58,25 @@ export function openModal(doc, kind) {
50
58
  export function openCertModal(doc) {
51
59
  return openModal(doc, 'cert');
52
60
  }
61
+ /**
62
+ * Open a dialog of `control`'s OWN face's `<certrev-cert-modal>` (see `ownCertModal`), which is what
63
+ * the delegated click / key handlers do. Returns false (so a link control follows its own href) when
64
+ * the face has no modal, the element declines, or the control cannot tell which modal is its own; in
65
+ * that last case it is stamped `data-certrev-modal-unresolved="ambiguous"` and receives
66
+ * `certrev:modal-unresolved`, and another face's certificate is never opened in its place.
67
+ */
68
+ export function openOwnModal(control, kind) {
69
+ const own = ownCertModal(control);
70
+ if (own.modal) {
71
+ const el = own.modal;
72
+ return typeof el.open === 'function' ? el.open(kind) : false;
73
+ }
74
+ if (own.reason === 'ambiguous') {
75
+ control.setAttribute(MODAL_UNRESOLVED_ATTR, own.reason);
76
+ control.dispatchEvent(new CustomEvent(MODAL_UNRESOLVED_EVENT, { bubbles: true, detail: { reason: own.reason, modals: own.count } }));
77
+ }
78
+ return false;
79
+ }
53
80
  function asElement(target) {
54
81
  return target && target.closest ? target : null;
55
82
  }
@@ -95,7 +122,7 @@ export function initCertInteractions(doc) {
95
122
  // (Close is owned by the <certrev-cert-modal> element inside its shadow root.)
96
123
  const opener = el.closest(`[${MODAL_OPEN_ATTR}]`);
97
124
  if (opener) {
98
- if (openModal(doc, modalTargetKind(opener.getAttribute(MODAL_OPEN_ATTR))))
125
+ if (openOwnModal(opener, modalTargetKind(opener.getAttribute(MODAL_OPEN_ATTR))))
99
126
  e.preventDefault();
100
127
  return;
101
128
  }
@@ -124,7 +151,7 @@ export function initCertInteractions(doc) {
124
151
  return;
125
152
  const opener = el.closest(`[${MODAL_OPEN_ATTR}]`);
126
153
  if (opener) {
127
- if (openModal(doc, modalTargetKind(opener.getAttribute(MODAL_OPEN_ATTR)))) {
154
+ if (openOwnModal(opener, modalTargetKind(opener.getAttribute(MODAL_OPEN_ATTR)))) {
128
155
  e.preventDefault();
129
156
  return;
130
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"interactions.js","sourceRoot":"","sources":["../../src/modal/interactions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interactions.js","sourceRoot":"","sources":["../../src/modal/interactions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * ─────────────────────────────────────────────────────────────────────────────
3
+ * getVerifiedDelivery — the envelope PLUS the brand's render def, from the Delivery API
4
+ * ─────────────────────────────────────────────────────────────────────────────
5
+ *
6
+ * 1.1.0. The Delivery API answers a Builder placement with the signed artifact and, beside it,
7
+ * the brand's resolved render-def projection as a top-level `renderDef` sibling (the same shape a
8
+ * Shopify store carries in its `render_def` metafield). The envelope's signature covers `payload`
9
+ * only, so the sibling rides the response without touching the signed bytes, and a tombstone
10
+ * carries none. `getVerifiedEnvelope` keeps discarding it; this reads it.
11
+ *
12
+ * The same fetch, deadline, kernel and fail-closed rules as `getVerifiedEnvelope` (every sourcing
13
+ * failure reports the reason it actually is; nothing throws into the render path). Two things are
14
+ * different, and both are the point:
15
+ *
16
+ * 1. WHAT IS CACHED is the cryptographically verified PAYLOAD, not the verdict. The lifecycle
17
+ * policy (revoked, expired) and the subject match are re-run by `renderVerdict` on EVERY call,
18
+ * with the caller's clock. So a payload that was valid when fetched and expires while cached
19
+ * stops rendering at its `expiresAt`, not at the next refetch; and a refetch after the TTL
20
+ * picks up a tombstone (revocation) or a changed def with no write on the brand's side.
21
+ * 2. The CACHE KEY is the Delivery URL plus the rendering placement, so a staging and a
22
+ * production origin never share an entry, and neither do two placements.
23
+ *
24
+ * `peekVerifiedDelivery` is the synchronous read of the same cache: a React component suspends on
25
+ * `getVerifiedDelivery` once, then reads the settled value without a second promise (which is what
26
+ * keeps a streaming SSR render from suspending forever on a fresh promise every retry).
27
+ */
28
+ import type { CertChromeRenderDef } from '../builder/cert-chrome-data.js';
29
+ import type { CertPayload, CertSuppressReason, CertVerdict, RenderContext, ResolvePublicKeyByKid } from '../contract/kernel.js';
30
+ import { TtlCache } from './cache.js';
31
+ /** What one Delivery read settles to, as cached: a verified payload + its def, or the reason not. */
32
+ export type CachedDelivery = {
33
+ readonly kind: 'verified';
34
+ readonly payload: CertPayload;
35
+ readonly renderDef: CertChromeRenderDef | null;
36
+ } | {
37
+ readonly kind: 'suppressed';
38
+ readonly reason: CertSuppressReason;
39
+ };
40
+ /** The answer for one render: the verdict AT THIS RENDER'S CLOCK, and the def to paint it with. */
41
+ export interface VerifiedDelivery {
42
+ readonly verdict: CertVerdict;
43
+ /** The brand's render def, or null (no def resolved, a malformed one, or a suppress verdict). */
44
+ readonly renderDef: CertChromeRenderDef | null;
45
+ }
46
+ export interface GetVerifiedDeliveryOptions {
47
+ /** Base URL of the CertREV app that serves the Delivery API, e.g. 'https://portal.certrev.com'. */
48
+ readonly baseUrl: string;
49
+ readonly platform: string;
50
+ readonly externalId: string;
51
+ /** kid → public-key resolver. Required: no verify without keys. */
52
+ readonly resolveKid: ResolvePublicKeyByKid;
53
+ /** Render context: the platform + externalId this edge IS, and the render's clock (`now`). */
54
+ readonly context: RenderContext;
55
+ readonly fetchImpl?: typeof fetch;
56
+ /** Cache override. Defaults to the module-level shared delivery cache. */
57
+ readonly cache?: TtlCache<CachedDelivery>;
58
+ /** TTL in ms for a VERIFIED read (default: the cache's positive TTL, 60_000 on the shared one). */
59
+ readonly ttlMs?: number;
60
+ /** Deadline in ms for the fetch (default `DEFAULT_FETCH_TIMEOUT_MS`, 3s). */
61
+ readonly timeoutMs?: number;
62
+ }
63
+ /** Shared per-process cache: 60s for a verified read, 5s for a suppressed one. */
64
+ declare const sharedDeliveryCache: TtlCache<CachedDelivery>;
65
+ export declare function deliveryUrl(baseUrl: string, platform: string, externalId: string): string;
66
+ /** Cache key: the URL (origin included) × the placement rendering it. No clock: the TTL bounds time. */
67
+ export declare function deliveryCacheKey(opts: Pick<GetVerifiedDeliveryOptions, 'baseUrl' | 'platform' | 'externalId' | 'context'>): string;
68
+ /**
69
+ * The def sibling, shape-checked. Anything that is not the metafield shape is null, which paints
70
+ * the preset default (the same thing an absent def paints): a def is presentation, never a claim,
71
+ * so a malformed one degrades the styling and nothing else. The TOKEN VALUES are not judged here;
72
+ * `resolveBlockTheme` re-validates each at paint time and drops what is not a safe value.
73
+ */
74
+ export declare function parseRenderDef(value: unknown): CertChromeRenderDef | null;
75
+ /** Apply the render-time policy to a cached read: lifecycle + subject at THIS render's clock. */
76
+ export declare function settleDelivery(cached: CachedDelivery, context: RenderContext): VerifiedDelivery;
77
+ /**
78
+ * Fetch (if needed), verify, cache, and settle one Delivery read for one placement. FAIL-CLOSED:
79
+ * the verdict is `render` only when the artifact verified against `resolveKid` AND, at
80
+ * `context.now`, the payload is unrevoked, unexpired and for this placement.
81
+ */
82
+ export declare function getVerifiedDelivery(opts: GetVerifiedDeliveryOptions): Promise<VerifiedDelivery>;
83
+ /**
84
+ * The synchronous read: the settled answer when a fresh read is cached, else `undefined` (the
85
+ * caller then awaits `getVerifiedDelivery`). Never fetches.
86
+ */
87
+ export declare function peekVerifiedDelivery(opts: Pick<GetVerifiedDeliveryOptions, 'baseUrl' | 'platform' | 'externalId' | 'context' | 'cache'>): VerifiedDelivery | undefined;
88
+ /** Drop every cached read for one placement (e.g. from a revocation webhook). */
89
+ export declare function invalidateDelivery(opts: Pick<GetVerifiedDeliveryOptions, 'baseUrl' | 'platform' | 'externalId' | 'context'>, cache?: TtlCache<CachedDelivery>): void;
90
+ export { sharedDeliveryCache };
91
+ //# sourceMappingURL=get-verified-delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-verified-delivery.d.ts","sourceRoot":"","sources":["../../src/verify/get-verified-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,KAAK,EAEX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,qGAAqG;AACrG,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,GAC5G;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAEvE,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,iGAAiG;IACjG,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAC9C;AAED,MAAM,WAAW,0BAA0B;IAC1C,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAA;IACzC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,kFAAkF;AAClF,QAAA,MAAM,mBAAmB,0BAAwE,CAAA;AAMjG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED,wGAAwG;AACxG,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,GACvF,MAAM,CAER;AAKD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CA4BzE;AAyCD,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,gBAAgB,CAI/F;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASrG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC,GACjG,gBAAgB,GAAG,SAAS,CAG9B;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,EACzF,KAAK,GAAE,QAAQ,CAAC,cAAc,CAAuB,GACnD,IAAI,CAEN;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}