@privateav/sdk 3.4.2 → 3.4.3

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/README.md CHANGED
@@ -144,7 +144,7 @@ app.get('/age-verified', async (req, res) => {
144
144
  `https://api.privateav.com/api/v1/sessions/${sessionId}`,
145
145
  {
146
146
  headers: {
147
- 'Authorization': `Bearer ${process.env.SAFEPASSAGE_SECRET_KEY}`
147
+ 'Authorization': `Bearer ${process.env.PRIVATEAV_SECRET_KEY}`
148
148
  }
149
149
  }
150
150
  );
@@ -214,7 +214,7 @@ function AgeGate() {
214
214
  const [verifying, setVerifying] = useState(false);
215
215
 
216
216
  const sp = new PrivateAV({
217
- apiKey: process.env.NEXT_PUBLIC_SAFEPASSAGE_KEY,
217
+ apiKey: process.env.NEXT_PUBLIC_PRIVATEAV_KEY,
218
218
  returnUrl: window.location.origin + '/verified'
219
219
  });
220
220
 
@@ -244,7 +244,7 @@ Full TypeScript support included:
244
244
  import { PrivateAV, PrivateAVConfig, VerificationResult } from '@privateav/sdk';
245
245
 
246
246
  const config: PrivateAVConfig = {
247
- apiKey: process.env.NEXT_PUBLIC_SAFEPASSAGE_KEY!,
247
+ apiKey: process.env.NEXT_PUBLIC_PRIVATEAV_KEY!,
248
248
  returnUrl: '/verified',
249
249
  mode: 'new-tab',
250
250
  onComplete: (result: VerificationResult) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@privateav/sdk",
3
- "version": "3.4.2",
3
+ "version": "3.4.3",
4
4
  "description": "PrivateAV SDK - Lightweight redirect-based age verification",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "license": "MIT",
29
29
  "repository": {
30
30
  "type": "git",
31
- "url": "https://github.com/privateav/sdk"
31
+ "url": "git+https://github.com/privateav/sdk.git"
32
32
  },
33
33
  "bugs": {
34
34
  "url": "https://github.com/privateav/sdk/issues"
package/privateav.min.js CHANGED
@@ -1,3 +1,3 @@
1
- /* PrivateAV SDK v3.4.2 */
1
+ /* PrivateAV SDK v3.4.3 */
2
2
  "use strict";var PrivateAVSDK=(()=>{var v=Object.defineProperty,rt=Object.defineProperties,it=Object.getOwnPropertyDescriptor,ot=Object.getOwnPropertyDescriptors,st=Object.getOwnPropertyNames,w=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,M=Object.prototype.propertyIsEnumerable;var R=(e,t,n)=>t in e?v(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,u=(e,t)=>{for(var n in t||(t={}))I.call(t,n)&&R(e,n,t[n]);if(w)for(var n of w(t))M.call(t,n)&&R(e,n,t[n]);return e},y=(e,t)=>rt(e,ot(t));var _=(e,t)=>{var n={};for(var r in e)I.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&w)for(var r of w(e))t.indexOf(r)<0&&M.call(e,r)&&(n[r]=e[r]);return n};var C=(e,t)=>()=>(e&&(t=e(e=0)),t);var K=(e,t)=>{for(var n in t)v(e,n,{get:t[n],enumerable:!0})},at=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of st(t))!I.call(e,i)&&i!==n&&v(e,i,{get:()=>t[i],enumerable:!(r=it(t,i))||r.enumerable});return e};var ct=e=>at(v({},"__esModule",{value:!0}),e);function lt(e,t){return t.includes(e)}function O(e,t,n=[],r="SDK"){var o;let{origin:i}=e;return lt(i,t)||n.length>0&&n.some(c=>{if(c.startsWith("*.")){let s=c.slice(2);return i.endsWith(`.${s}`)||i===`https://${s}`||i===`http://${s}`}return i===c})?!0:(console.warn(`${r} Security: Blocked PostMessage from untrusted origin: ${i}`,{trustedOrigins:t,allowedCustomOrigins:n,eventType:(o=e.data)==null?void 0:o.type}),!1)}function W(e,t,n,r){let{data:i}=e;return!i||typeof i!="object"?{isValid:!1,error:"Invalid message format"}:(r?[n,r]:[n]).includes(i.type)?!i.sessionId||i.sessionId!==t?{isValid:!1,error:"Session ID mismatch"}:!i.status||!["verified","failed"].includes(i.status)?{isValid:!1,error:"Invalid status value"}:{isValid:!0}:{isValid:!1,error:"Invalid message type"}}function B(e,t="SDK"){e==="production"&&window.location.protocol!=="https:"&&console.warn(`${t} Warning: HTTPS recommended for production environment`,{current:window.location.href})}function A(e,t,n="SDK"){try{let r=new URL(e);if(r.protocol!=="https:"&&!(r.hostname==="localhost"||r.hostname==="127.0.0.1"))return{isValid:!1,error:`HTTPS required for return URLs in ${t}`};let i=[/data:/i,/javascript:/i,/vbscript:/i,/file:/i,/ftp:/i];for(let o of i)if(o.test(e))return{isValid:!1,error:"Blocked suspicious URL scheme"};return{isValid:!0}}catch(r){return{isValid:!1,error:"Invalid URL format"}}}function d(e,t,n="SDK"){let r={timestamp:new Date().toISOString(),userAgent:typeof navigator!="undefined"?navigator.userAgent:"unknown",url:typeof window!="undefined"?window.location.href:"unknown"};console.warn(`${n} Security Event: ${e}`,u(u({},r),t))}var b,H,T=C(()=>{"use strict";b=class{constructor(){this.attempts=new Map;this.maxAttempts=5;this.timeWindow=6e4}isAllowed(t,n="SDK"){let r=Date.now(),o=(this.attempts.get(t)||[]).filter(a=>r-a<this.timeWindow);return o.length>=this.maxAttempts?(console.warn(`${n} Security: Rate limit exceeded for ${t}`),!1):(o.push(r),this.attempts.set(t,o),!0)}reset(t){this.attempts.delete(t)}},H=new b});var F={};K(F,{createSignedState:()=>pt,generateHMAC:()=>P,generateSecureToken:()=>j,parseSignedState:()=>ut,verifyHMAC:()=>q});async function P(e,t){let n=new TextEncoder,r=n.encode(t),i=n.encode(e),o=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",o,i);return Array.from(new Uint8Array(a)).map(c=>c.toString(16).padStart(2,"0")).join("")}async function q(e,t,n){try{let r=await P(e,n);return dt(t,r)}catch(r){return!1}}function dt(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r++)n|=e.charCodeAt(r)^t.charCodeAt(r);return n===0}function j(e=32){let t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,n=>n.toString(16).padStart(2,"0")).join("")}async function pt(e,t){let n=y(u({},e),{timestamp:Date.now(),nonce:j(16)}),r=JSON.stringify(n),i=await P(r,t);return btoa(JSON.stringify({data:n,signature:i}))}async function ut(e,t,n=J,r="SDK"){try{let o=atob(e),a=JSON.parse(o);if(!a.data||!a.signature)return console.warn(`${r}: Invalid signed state format`),null;let{data:c,signature:s}=a,l=JSON.stringify(c);if(!await q(l,s,t))return console.warn(`${r}: State signature verification failed`),null;if(c.timestamp){let h=Date.now()-c.timestamp;if(h>n)return console.warn(`${r}: State parameter expired`,{age:h,maxAge:n}),null}let i=c,{timestamp:g,nonce:f}=i;return _(i,["timestamp","nonce"])}catch(o){return console.warn(`${r}: Failed to parse signed state`,o),null}}var G=C(()=>{"use strict";x()});function Z(e,t){if(!e.apiKey)throw new Error("apiKey is required");if(e.apiKey.length>z)throw new Error(`apiKey exceeds maximum length of ${z} characters`);if(!gt.test(e.apiKey))throw new Error("Invalid apiKey format. Expected pk_xxx (public) or sk_xxx (private)");if(typeof window!="undefined"&&e.apiKey.startsWith("sk_"))throw new Error(`Secret keys (sk_) should never be used in browser code for security reasons. Secret keys expose your account to unauthorized access if used client-side. Please use your public key (pk_) instead. If you need to use features that require a secret key (like custom challenge age), create the session server-side and pass the sessionId to startVerificationWithSession(). See: ${t.docsUrl}/server-side-sessions`);if(!e.returnUrl)throw new Error("returnUrl is required");if(e.returnUrl.length>S)throw new Error(`returnUrl exceeds maximum length of ${S} characters`);let n=ft(),r=A(e.returnUrl,n,t.brandName);if(!r.isValid)throw new Error(`returnUrl validation failed: ${r.error}`);if(e.cancelUrl){if(e.cancelUrl.length>S)throw new Error(`cancelUrl exceeds maximum length of ${S} characters`);let i=A(e.cancelUrl,n,t.brandName);if(!i.isValid)throw new Error(`cancelUrl validation failed: ${i.error}`)}if(e.defaultChallengeAge!==void 0){if(e.defaultChallengeAge<X)throw new Error(`defaultChallengeAge must be at least ${X}`);if(e.defaultChallengeAge>Y)throw new Error(`defaultChallengeAge cannot exceed ${Y}`)}if(e.defaultVerificationMode&&!["L1","L2"].includes(e.defaultVerificationMode))throw new Error("defaultVerificationMode must be L1 or L2");if(e.mode&&!["redirect","new-tab"].includes(e.mode))throw new Error("mode must be redirect or new-tab")}function ft(){if(typeof window=="undefined")return"production";let e=window.location.hostname;return e.includes("staging")||e.includes("stage")?"staging":"production"}async function Q(e,t,n,r="SDK"){let{createSignedState:i}=await Promise.resolve().then(()=>(G(),F));return i(e,n)}var X,Y,S,z,J,gt,x=C(()=>{"use strict";T();X=25,Y=150,S=2048,z=128,J=6e5,gt=/^(pk_|sk_)[a-zA-Z0-9_]+$/});var wt={};K(wt,{PrivateAV:()=>m,VERSION:()=>nt,default:()=>mt});function N(){crypto.randomUUID||(crypto.randomUUID=function(){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("");return[t.slice(0,8),t.slice(8,12),t.slice(12,16),t.slice(16,20),t.slice(20,32)].join("-")})}function L(e="SDK"){let t=[];if(!window.crypto||!window.crypto.getRandomValues)throw new Error(`${e} requires Web Crypto API support`);if(!window.crypto.subtle)throw new Error(`${e} requires Web Crypto subtle API for HMAC operations`);crypto.randomUUID||t.push("crypto.randomUUID not supported, using polyfill"),window.URLSearchParams||t.push("URLSearchParams not supported, consider adding a polyfill for IE 11 support"),t.length>0&&console.warn(`${e} Browser Compatibility:`,t.join("; "))}x();function V(e,t){let n=t.verifyUiUrl;if(!n||!n.startsWith("https://"))throw new Error(`HTTPS required for ${e} environment`);return n}function ht(e,t){let n=t.apiUrl;if(!n||!n.startsWith("https://"))throw new Error(`HTTPS required for API URLs in ${e} environment`);return n}function tt(e,t,n="SDK"){let r=window.location.protocol==="https:";switch(e){case"production":r||console.warn(`${n} Warning: HTTPS recommended for production environment`);break;case"staging":r||console.warn(`${n} Warning: HTTPS strongly recommended in staging environment`);break}try{V(e,t),ht(e,t)}catch(i){let o=i instanceof Error?i.message:String(i);throw new Error(`Environment configuration validation failed: ${o}`)}}T();var U=class{constructor(t,n,r){this.popupWindow=null;this.messageListener=null;this.popupMonitorInterval=null;this.unloadListener=null;this.isVerificationInProgress=!1;this.currentSessionId=null;this.lastVerifyUrl=null;this.lastSessionToken=null;this.temporaryHandoffToken=null;this.brandUrls=n,this.brandConstants=r,Z(t,{brandName:this.brandConstants.name,docsUrl:this.brandConstants.docsUrl});let i=t.environment||this.detectEnvironment();i!=="staging"&&i!=="production"&&(console.warn(`${this.brandConstants.name} SDK: Unknown environment '${i}', defaulting to 'production'`),i="production"),this.config=y(u({},t),{environment:i,mode:t.mode||"redirect"}),tt(this.config.environment,this.getUrlConfig(),this.brandConstants.name),B(this.config.environment,this.brandConstants.name),d("SDK_INITIALIZED",{environment:this.config.environment,mode:this.config.mode,origin:window.location.origin,protocol:window.location.protocol,hostname:window.location.hostname},this.brandConstants.name),this.setupAutoCleanup()}async verify(t={}){var i,o,a,c,s,l;let n=this.isPublicKey(),r;if(n)r=await this.createInternalSession(t);else throw new Error("Private API keys (sk_) should use the direct API, not the SDK. The SDK is designed for browser-based public key usage only.");if(!r)throw new Error("Failed to obtain sessionId from server");if(this.isVerificationInProgress){let p=new Error(`Verification already in progress for session ${(i=this.currentSessionId)==null?void 0:i.substring(0,8)}...`);throw d("RACE_CONDITION_PREVENTED",{currentSession:((o=this.currentSessionId)==null?void 0:o.substring(0,8))+"...",attemptedSession:"new-session-attempt",origin:window.location.origin},this.brandConstants.name),(c=(a=this.config).onError)==null||c.call(a,p),p}this.isVerificationInProgress=!0,this.currentSessionId=r;try{let p=`${this.config.apiKey}:${window.location.origin}`;if(!H.isAllowed(p,this.brandConstants.name)){let f=new Error("Too many verification attempts. Please wait before trying again.");throw d("RATE_LIMIT_EXCEEDED",{apiKey:this.config.apiKey.substring(0,8)+"...",origin:window.location.origin,sessionId:r?r.substring(0,8)+"...":"undefined"},this.brandConstants.name),(l=(s=this.config).onError)==null||l.call(s,f),f}let g=await this.buildVerificationUrl(t,r);d("VERIFICATION_INITIATED",{environment:this.config.environment,mode:this.config.mode,sessionId:r?r.substring(0,8)+"...":"undefined",origin:window.location.origin},this.brandConstants.name),this.config.mode==="new-tab"?this.openNewTab(g,r):(this.unlockVerification(),this.redirect(g))}catch(p){throw this.unlockVerification(),p}}async buildVerificationUrl(t,n){let r=this.config.verifyUrl||V(this.config.environment,this.getUrlConfig()),i=t.challengeAge!==void 0,o=t.verificationMode!==void 0,a=i||o,c=await Q({merchantId:this.config.apiKey,sessionId:n,returnUrl:this.config.returnUrl,cancelUrl:this.config.cancelUrl,challengeAge:t.challengeAge||this.config.defaultChallengeAge,verificationMode:t.verificationMode||this.config.defaultVerificationMode,hasOverrides:a,externalUserId:t.externalUserId,timestamp:Date.now(),apiUrl:this.getPortalApiUrl(),engineUrl:this.getEngineUrl(),wsUrl:this.getWebSocketUrl(),environment:this.config.environment,features:{testMode:!1,warmupPeriodMs:500,qualityThreshold:.6},handoffToken:this.temporaryHandoffToken||void 0,sessionToken:this.lastSessionToken||void 0,verifyUrl:this.lastVerifyUrl||void 0},this.config.environment,this.getHmacSecret(),this.brandConstants.name);if(this.lastVerifyUrl)try{let l=new URL(this.lastVerifyUrl);return l.searchParams.set("state",c),l.searchParams.set("mode",this.config.mode),t.skipIntro&&l.searchParams.set("skip_intro","true"),t.autoReturn&&l.searchParams.set("auto_return","true"),l.toString()}catch(l){}let s=new URLSearchParams({state:c,sessionId:n,mode:this.config.mode});return t.skipIntro&&s.set("skip_intro","true"),t.autoReturn&&s.set("auto_return","true"),`${r}/?${s.toString()}`}redirect(t){window.location.href=t}openNewTab(t,n){var a,c;if(this.cleanup(),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null),this.popupWindow=window.open(t,this.brandConstants.popupName,"width=600,height=700"),!this.popupWindow){(c=(a=this.config).onError)==null||c.call(a,new Error("Failed to open verification window. Please check popup blocker settings."));return}let r=this.getTrustedOrigins(),i=this.brandConstants.messageType,o=this.brandConstants.legacyMessageType;this.messageListener=s=>{var g,f,E,h,D,$;if(!O(s,r,[],this.brandConstants.name)){d("POSTMESSAGE_ORIGIN_BLOCKED",{origin:s.origin,environment:this.config.environment,expectedOrigins:`${this.brandConstants.name} trusted origins for ${this.config.environment}`,messageType:(g=s.data)==null?void 0:g.type},this.brandConstants.name);return}let l=W(s,n,i,o);if(!l.isValid){d("POSTMESSAGE_VALIDATION_FAILED",{error:l.error,origin:s.origin,sessionId:n.substring(0,8)+"...",messageType:(f=s.data)==null?void 0:f.type},this.brandConstants.name);return}let p={sessionId:s.data.sessionId,status:s.data.status};d("VERIFICATION_COMPLETED",{status:p.status,sessionId:n.substring(0,8)+"...",origin:s.origin},this.brandConstants.name),this.cleanup(),this.unlockVerification(),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null),p.status==="verified"?(h=(E=this.config).onComplete)==null||h.call(E,p):($=(D=this.config).onError)==null||$.call(D,new Error(`Verification failed: ${p.status}`))},window.addEventListener("message",this.messageListener),this.popupMonitorInterval=setInterval(()=>{var s,l;this.popupWindow&&this.popupWindow.closed&&(d("POPUP_CLOSED_BY_USER",{sessionId:n.substring(0,8)+"...",environment:this.config.environment},this.brandConstants.name),this.cleanup(),this.unlockVerification(),(l=(s=this.config).onCancel)==null||l.call(s))},500)}setupAutoCleanup(){if(this.unloadListener=()=>{d("SDK_AUTO_CLEANUP",{environment:this.config.environment,trigger:"page_unload"},this.brandConstants.name),this.cleanup(),this.unlockVerification()},window.addEventListener("beforeunload",this.unloadListener),window.addEventListener("pagehide",this.unloadListener),window.history&&window.history.pushState){let t=window.history.pushState;window.history.pushState=(...n)=>(this.cleanup(),this.unlockVerification(),t.apply(window.history,n))}}detectEnvironment(){let t=window.location.hostname;return t.includes("staging")||t.includes("stage")?"staging":"production"}getEnvironment(){return this.config.environment}unlockVerification(){this.isVerificationInProgress=!1,this.currentSessionId=null,d("VERIFICATION_UNLOCKED",{environment:this.config.environment,origin:window.location.origin},this.brandConstants.name)}cleanup(){this.popupWindow&&!this.popupWindow.closed&&this.popupWindow.close(),this.popupWindow=null,this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null)}removeAutoCleanupListeners(){this.unloadListener&&(window.removeEventListener("beforeunload",this.unloadListener),window.removeEventListener("pagehide",this.unloadListener),this.unloadListener=null)}destroy(){d("SDK_DESTROYED",{environment:this.config.environment,origin:window.location.origin},this.brandConstants.name),this.cleanup(),this.unlockVerification(),this.removeAutoCleanupListeners()}getPortalApiUrl(){return this.config.apiUrl?this.config.apiUrl:this.getUrlConfig().apiUrl}getEngineUrl(){return this.getUrlConfig().engineUrl}getWebSocketUrl(){return this.getUrlConfig().wsUrl}isPublicKey(){return this.config.apiKey.startsWith("pk_")}async createInternalSession(t){var n,r;try{let i=this.getPortalApiUrl(),o=await fetch(`${i}/api/v1/sessions/create`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({merchantId:this.config.apiKey,returnUrl:this.config.returnUrl,cancelUrl:this.config.cancelUrl,challengeAge:t.challengeAge,verificationMode:t.verificationMode,merchantName:document.title||window.location.hostname,externalUserId:t.externalUserId})});if(!o.ok){let s=await o.json().catch(()=>({}));throw new Error(`Failed to create session: ${o.status} ${o.statusText}. ${s.message||""}`)}let a=await o.json(),c=a.sessionId;if(!c)throw new Error("Server did not return a sessionId");return a.verifyUrl&&(this.lastVerifyUrl=a.verifyUrl),a.sessionToken&&(this.lastSessionToken=a.sessionToken),a.handoffToken&&(this.temporaryHandoffToken=a.handoffToken),d("INTERNAL_SESSION_CREATED",{sessionId:c.substring(0,8)+"...",environment:this.config.environment,apiKeyType:"public"},this.brandConstants.name),c}catch(i){let o=i instanceof Error?i.message:String(i);throw d("INTERNAL_SESSION_FAILED",{error:o,environment:this.config.environment,apiKeyType:"public"},this.brandConstants.name),(r=(n=this.config).onError)==null||r.call(n,i),new Error(`Failed to create verification session: ${o}`)}}getUrlConfig(){return this.brandUrls[this.config.environment]||this.brandUrls.production}getTrustedOrigins(){return this.getUrlConfig().trustedOrigins}getHmacSecret(){return this.config.environment==="staging"?this.brandConstants.hmacSecretStaging:this.brandConstants.hmacSecretProd}};var et={production:{apiUrl:"https://api.privateav.com",verifyUiUrl:"https://verify.privateav.com",engineUrl:"https://engine.privateav.com",wsUrl:"wss://engine.privateav.com/api/websocket/stream",trustedOrigins:["https://verify.privateav.com","https://portal.privateav.com","https://api.privateav.com"]},staging:{apiUrl:"https://api.staging.privateav.com",verifyUiUrl:"https://verify.staging.privateav.com",engineUrl:"https://engine.staging.privateav.com",wsUrl:"wss://engine.staging.privateav.com/api/websocket/stream",trustedOrigins:["https://verify.staging.privateav.com","https://portal.staging.privateav.com","https://api.staging.privateav.com"]}},k={name:"PrivateAV",hmacSecretProd:"privateav-prod-hmac-2025",hmacSecretStaging:"privateav-stage-hmac-2025",messageType:"privateav:verification:complete",legacyMessageType:"privateav-verification",popupName:"privateav-verify",docsUrl:"https://docs.privateav.com"};var m=class extends U{constructor(t){super(t,et,k)}},nt="3.4.2";m.VERSION=nt;typeof window!="undefined"&&(N(),L(`${k.name} SDK`));var mt=m;return ct(wt);})();
3
3
  if(typeof PrivateAVSDK !== "undefined" && PrivateAVSDK.PrivateAV) { window.PrivateAV = PrivateAVSDK.PrivateAV; window.PrivateAV.VERSION = PrivateAVSDK.VERSION; }
package/sdk.min.js CHANGED
@@ -1,3 +1,3 @@
1
- /* PrivateAV SDK v3.4.2 */
1
+ /* PrivateAV SDK v3.4.3 */
2
2
  "use strict";var PrivateAVSDK=(()=>{var v=Object.defineProperty,rt=Object.defineProperties,it=Object.getOwnPropertyDescriptor,ot=Object.getOwnPropertyDescriptors,st=Object.getOwnPropertyNames,w=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,M=Object.prototype.propertyIsEnumerable;var R=(e,t,n)=>t in e?v(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,u=(e,t)=>{for(var n in t||(t={}))I.call(t,n)&&R(e,n,t[n]);if(w)for(var n of w(t))M.call(t,n)&&R(e,n,t[n]);return e},y=(e,t)=>rt(e,ot(t));var _=(e,t)=>{var n={};for(var r in e)I.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&w)for(var r of w(e))t.indexOf(r)<0&&M.call(e,r)&&(n[r]=e[r]);return n};var C=(e,t)=>()=>(e&&(t=e(e=0)),t);var K=(e,t)=>{for(var n in t)v(e,n,{get:t[n],enumerable:!0})},at=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of st(t))!I.call(e,i)&&i!==n&&v(e,i,{get:()=>t[i],enumerable:!(r=it(t,i))||r.enumerable});return e};var ct=e=>at(v({},"__esModule",{value:!0}),e);function lt(e,t){return t.includes(e)}function O(e,t,n=[],r="SDK"){var o;let{origin:i}=e;return lt(i,t)||n.length>0&&n.some(c=>{if(c.startsWith("*.")){let s=c.slice(2);return i.endsWith(`.${s}`)||i===`https://${s}`||i===`http://${s}`}return i===c})?!0:(console.warn(`${r} Security: Blocked PostMessage from untrusted origin: ${i}`,{trustedOrigins:t,allowedCustomOrigins:n,eventType:(o=e.data)==null?void 0:o.type}),!1)}function W(e,t,n,r){let{data:i}=e;return!i||typeof i!="object"?{isValid:!1,error:"Invalid message format"}:(r?[n,r]:[n]).includes(i.type)?!i.sessionId||i.sessionId!==t?{isValid:!1,error:"Session ID mismatch"}:!i.status||!["verified","failed"].includes(i.status)?{isValid:!1,error:"Invalid status value"}:{isValid:!0}:{isValid:!1,error:"Invalid message type"}}function B(e,t="SDK"){e==="production"&&window.location.protocol!=="https:"&&console.warn(`${t} Warning: HTTPS recommended for production environment`,{current:window.location.href})}function A(e,t,n="SDK"){try{let r=new URL(e);if(r.protocol!=="https:"&&!(r.hostname==="localhost"||r.hostname==="127.0.0.1"))return{isValid:!1,error:`HTTPS required for return URLs in ${t}`};let i=[/data:/i,/javascript:/i,/vbscript:/i,/file:/i,/ftp:/i];for(let o of i)if(o.test(e))return{isValid:!1,error:"Blocked suspicious URL scheme"};return{isValid:!0}}catch(r){return{isValid:!1,error:"Invalid URL format"}}}function d(e,t,n="SDK"){let r={timestamp:new Date().toISOString(),userAgent:typeof navigator!="undefined"?navigator.userAgent:"unknown",url:typeof window!="undefined"?window.location.href:"unknown"};console.warn(`${n} Security Event: ${e}`,u(u({},r),t))}var b,H,T=C(()=>{"use strict";b=class{constructor(){this.attempts=new Map;this.maxAttempts=5;this.timeWindow=6e4}isAllowed(t,n="SDK"){let r=Date.now(),o=(this.attempts.get(t)||[]).filter(a=>r-a<this.timeWindow);return o.length>=this.maxAttempts?(console.warn(`${n} Security: Rate limit exceeded for ${t}`),!1):(o.push(r),this.attempts.set(t,o),!0)}reset(t){this.attempts.delete(t)}},H=new b});var F={};K(F,{createSignedState:()=>pt,generateHMAC:()=>P,generateSecureToken:()=>j,parseSignedState:()=>ut,verifyHMAC:()=>q});async function P(e,t){let n=new TextEncoder,r=n.encode(t),i=n.encode(e),o=await crypto.subtle.importKey("raw",r,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",o,i);return Array.from(new Uint8Array(a)).map(c=>c.toString(16).padStart(2,"0")).join("")}async function q(e,t,n){try{let r=await P(e,n);return dt(t,r)}catch(r){return!1}}function dt(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r++)n|=e.charCodeAt(r)^t.charCodeAt(r);return n===0}function j(e=32){let t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,n=>n.toString(16).padStart(2,"0")).join("")}async function pt(e,t){let n=y(u({},e),{timestamp:Date.now(),nonce:j(16)}),r=JSON.stringify(n),i=await P(r,t);return btoa(JSON.stringify({data:n,signature:i}))}async function ut(e,t,n=J,r="SDK"){try{let o=atob(e),a=JSON.parse(o);if(!a.data||!a.signature)return console.warn(`${r}: Invalid signed state format`),null;let{data:c,signature:s}=a,l=JSON.stringify(c);if(!await q(l,s,t))return console.warn(`${r}: State signature verification failed`),null;if(c.timestamp){let h=Date.now()-c.timestamp;if(h>n)return console.warn(`${r}: State parameter expired`,{age:h,maxAge:n}),null}let i=c,{timestamp:g,nonce:f}=i;return _(i,["timestamp","nonce"])}catch(o){return console.warn(`${r}: Failed to parse signed state`,o),null}}var G=C(()=>{"use strict";x()});function Z(e,t){if(!e.apiKey)throw new Error("apiKey is required");if(e.apiKey.length>z)throw new Error(`apiKey exceeds maximum length of ${z} characters`);if(!gt.test(e.apiKey))throw new Error("Invalid apiKey format. Expected pk_xxx (public) or sk_xxx (private)");if(typeof window!="undefined"&&e.apiKey.startsWith("sk_"))throw new Error(`Secret keys (sk_) should never be used in browser code for security reasons. Secret keys expose your account to unauthorized access if used client-side. Please use your public key (pk_) instead. If you need to use features that require a secret key (like custom challenge age), create the session server-side and pass the sessionId to startVerificationWithSession(). See: ${t.docsUrl}/server-side-sessions`);if(!e.returnUrl)throw new Error("returnUrl is required");if(e.returnUrl.length>S)throw new Error(`returnUrl exceeds maximum length of ${S} characters`);let n=ft(),r=A(e.returnUrl,n,t.brandName);if(!r.isValid)throw new Error(`returnUrl validation failed: ${r.error}`);if(e.cancelUrl){if(e.cancelUrl.length>S)throw new Error(`cancelUrl exceeds maximum length of ${S} characters`);let i=A(e.cancelUrl,n,t.brandName);if(!i.isValid)throw new Error(`cancelUrl validation failed: ${i.error}`)}if(e.defaultChallengeAge!==void 0){if(e.defaultChallengeAge<X)throw new Error(`defaultChallengeAge must be at least ${X}`);if(e.defaultChallengeAge>Y)throw new Error(`defaultChallengeAge cannot exceed ${Y}`)}if(e.defaultVerificationMode&&!["L1","L2"].includes(e.defaultVerificationMode))throw new Error("defaultVerificationMode must be L1 or L2");if(e.mode&&!["redirect","new-tab"].includes(e.mode))throw new Error("mode must be redirect or new-tab")}function ft(){if(typeof window=="undefined")return"production";let e=window.location.hostname;return e.includes("staging")||e.includes("stage")?"staging":"production"}async function Q(e,t,n,r="SDK"){let{createSignedState:i}=await Promise.resolve().then(()=>(G(),F));return i(e,n)}var X,Y,S,z,J,gt,x=C(()=>{"use strict";T();X=25,Y=150,S=2048,z=128,J=6e5,gt=/^(pk_|sk_)[a-zA-Z0-9_]+$/});var wt={};K(wt,{PrivateAV:()=>m,VERSION:()=>nt,default:()=>mt});function N(){crypto.randomUUID||(crypto.randomUUID=function(){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("");return[t.slice(0,8),t.slice(8,12),t.slice(12,16),t.slice(16,20),t.slice(20,32)].join("-")})}function L(e="SDK"){let t=[];if(!window.crypto||!window.crypto.getRandomValues)throw new Error(`${e} requires Web Crypto API support`);if(!window.crypto.subtle)throw new Error(`${e} requires Web Crypto subtle API for HMAC operations`);crypto.randomUUID||t.push("crypto.randomUUID not supported, using polyfill"),window.URLSearchParams||t.push("URLSearchParams not supported, consider adding a polyfill for IE 11 support"),t.length>0&&console.warn(`${e} Browser Compatibility:`,t.join("; "))}x();function V(e,t){let n=t.verifyUiUrl;if(!n||!n.startsWith("https://"))throw new Error(`HTTPS required for ${e} environment`);return n}function ht(e,t){let n=t.apiUrl;if(!n||!n.startsWith("https://"))throw new Error(`HTTPS required for API URLs in ${e} environment`);return n}function tt(e,t,n="SDK"){let r=window.location.protocol==="https:";switch(e){case"production":r||console.warn(`${n} Warning: HTTPS recommended for production environment`);break;case"staging":r||console.warn(`${n} Warning: HTTPS strongly recommended in staging environment`);break}try{V(e,t),ht(e,t)}catch(i){let o=i instanceof Error?i.message:String(i);throw new Error(`Environment configuration validation failed: ${o}`)}}T();var U=class{constructor(t,n,r){this.popupWindow=null;this.messageListener=null;this.popupMonitorInterval=null;this.unloadListener=null;this.isVerificationInProgress=!1;this.currentSessionId=null;this.lastVerifyUrl=null;this.lastSessionToken=null;this.temporaryHandoffToken=null;this.brandUrls=n,this.brandConstants=r,Z(t,{brandName:this.brandConstants.name,docsUrl:this.brandConstants.docsUrl});let i=t.environment||this.detectEnvironment();i!=="staging"&&i!=="production"&&(console.warn(`${this.brandConstants.name} SDK: Unknown environment '${i}', defaulting to 'production'`),i="production"),this.config=y(u({},t),{environment:i,mode:t.mode||"redirect"}),tt(this.config.environment,this.getUrlConfig(),this.brandConstants.name),B(this.config.environment,this.brandConstants.name),d("SDK_INITIALIZED",{environment:this.config.environment,mode:this.config.mode,origin:window.location.origin,protocol:window.location.protocol,hostname:window.location.hostname},this.brandConstants.name),this.setupAutoCleanup()}async verify(t={}){var i,o,a,c,s,l;let n=this.isPublicKey(),r;if(n)r=await this.createInternalSession(t);else throw new Error("Private API keys (sk_) should use the direct API, not the SDK. The SDK is designed for browser-based public key usage only.");if(!r)throw new Error("Failed to obtain sessionId from server");if(this.isVerificationInProgress){let p=new Error(`Verification already in progress for session ${(i=this.currentSessionId)==null?void 0:i.substring(0,8)}...`);throw d("RACE_CONDITION_PREVENTED",{currentSession:((o=this.currentSessionId)==null?void 0:o.substring(0,8))+"...",attemptedSession:"new-session-attempt",origin:window.location.origin},this.brandConstants.name),(c=(a=this.config).onError)==null||c.call(a,p),p}this.isVerificationInProgress=!0,this.currentSessionId=r;try{let p=`${this.config.apiKey}:${window.location.origin}`;if(!H.isAllowed(p,this.brandConstants.name)){let f=new Error("Too many verification attempts. Please wait before trying again.");throw d("RATE_LIMIT_EXCEEDED",{apiKey:this.config.apiKey.substring(0,8)+"...",origin:window.location.origin,sessionId:r?r.substring(0,8)+"...":"undefined"},this.brandConstants.name),(l=(s=this.config).onError)==null||l.call(s,f),f}let g=await this.buildVerificationUrl(t,r);d("VERIFICATION_INITIATED",{environment:this.config.environment,mode:this.config.mode,sessionId:r?r.substring(0,8)+"...":"undefined",origin:window.location.origin},this.brandConstants.name),this.config.mode==="new-tab"?this.openNewTab(g,r):(this.unlockVerification(),this.redirect(g))}catch(p){throw this.unlockVerification(),p}}async buildVerificationUrl(t,n){let r=this.config.verifyUrl||V(this.config.environment,this.getUrlConfig()),i=t.challengeAge!==void 0,o=t.verificationMode!==void 0,a=i||o,c=await Q({merchantId:this.config.apiKey,sessionId:n,returnUrl:this.config.returnUrl,cancelUrl:this.config.cancelUrl,challengeAge:t.challengeAge||this.config.defaultChallengeAge,verificationMode:t.verificationMode||this.config.defaultVerificationMode,hasOverrides:a,externalUserId:t.externalUserId,timestamp:Date.now(),apiUrl:this.getPortalApiUrl(),engineUrl:this.getEngineUrl(),wsUrl:this.getWebSocketUrl(),environment:this.config.environment,features:{testMode:!1,warmupPeriodMs:500,qualityThreshold:.6},handoffToken:this.temporaryHandoffToken||void 0,sessionToken:this.lastSessionToken||void 0,verifyUrl:this.lastVerifyUrl||void 0},this.config.environment,this.getHmacSecret(),this.brandConstants.name);if(this.lastVerifyUrl)try{let l=new URL(this.lastVerifyUrl);return l.searchParams.set("state",c),l.searchParams.set("mode",this.config.mode),t.skipIntro&&l.searchParams.set("skip_intro","true"),t.autoReturn&&l.searchParams.set("auto_return","true"),l.toString()}catch(l){}let s=new URLSearchParams({state:c,sessionId:n,mode:this.config.mode});return t.skipIntro&&s.set("skip_intro","true"),t.autoReturn&&s.set("auto_return","true"),`${r}/?${s.toString()}`}redirect(t){window.location.href=t}openNewTab(t,n){var a,c;if(this.cleanup(),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null),this.popupWindow=window.open(t,this.brandConstants.popupName,"width=600,height=700"),!this.popupWindow){(c=(a=this.config).onError)==null||c.call(a,new Error("Failed to open verification window. Please check popup blocker settings."));return}let r=this.getTrustedOrigins(),i=this.brandConstants.messageType,o=this.brandConstants.legacyMessageType;this.messageListener=s=>{var g,f,E,h,D,$;if(!O(s,r,[],this.brandConstants.name)){d("POSTMESSAGE_ORIGIN_BLOCKED",{origin:s.origin,environment:this.config.environment,expectedOrigins:`${this.brandConstants.name} trusted origins for ${this.config.environment}`,messageType:(g=s.data)==null?void 0:g.type},this.brandConstants.name);return}let l=W(s,n,i,o);if(!l.isValid){d("POSTMESSAGE_VALIDATION_FAILED",{error:l.error,origin:s.origin,sessionId:n.substring(0,8)+"...",messageType:(f=s.data)==null?void 0:f.type},this.brandConstants.name);return}let p={sessionId:s.data.sessionId,status:s.data.status};d("VERIFICATION_COMPLETED",{status:p.status,sessionId:n.substring(0,8)+"...",origin:s.origin},this.brandConstants.name),this.cleanup(),this.unlockVerification(),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null),p.status==="verified"?(h=(E=this.config).onComplete)==null||h.call(E,p):($=(D=this.config).onError)==null||$.call(D,new Error(`Verification failed: ${p.status}`))},window.addEventListener("message",this.messageListener),this.popupMonitorInterval=setInterval(()=>{var s,l;this.popupWindow&&this.popupWindow.closed&&(d("POPUP_CLOSED_BY_USER",{sessionId:n.substring(0,8)+"...",environment:this.config.environment},this.brandConstants.name),this.cleanup(),this.unlockVerification(),(l=(s=this.config).onCancel)==null||l.call(s))},500)}setupAutoCleanup(){if(this.unloadListener=()=>{d("SDK_AUTO_CLEANUP",{environment:this.config.environment,trigger:"page_unload"},this.brandConstants.name),this.cleanup(),this.unlockVerification()},window.addEventListener("beforeunload",this.unloadListener),window.addEventListener("pagehide",this.unloadListener),window.history&&window.history.pushState){let t=window.history.pushState;window.history.pushState=(...n)=>(this.cleanup(),this.unlockVerification(),t.apply(window.history,n))}}detectEnvironment(){let t=window.location.hostname;return t.includes("staging")||t.includes("stage")?"staging":"production"}getEnvironment(){return this.config.environment}unlockVerification(){this.isVerificationInProgress=!1,this.currentSessionId=null,d("VERIFICATION_UNLOCKED",{environment:this.config.environment,origin:window.location.origin},this.brandConstants.name)}cleanup(){this.popupWindow&&!this.popupWindow.closed&&this.popupWindow.close(),this.popupWindow=null,this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.popupMonitorInterval&&(clearInterval(this.popupMonitorInterval),this.popupMonitorInterval=null)}removeAutoCleanupListeners(){this.unloadListener&&(window.removeEventListener("beforeunload",this.unloadListener),window.removeEventListener("pagehide",this.unloadListener),this.unloadListener=null)}destroy(){d("SDK_DESTROYED",{environment:this.config.environment,origin:window.location.origin},this.brandConstants.name),this.cleanup(),this.unlockVerification(),this.removeAutoCleanupListeners()}getPortalApiUrl(){return this.config.apiUrl?this.config.apiUrl:this.getUrlConfig().apiUrl}getEngineUrl(){return this.getUrlConfig().engineUrl}getWebSocketUrl(){return this.getUrlConfig().wsUrl}isPublicKey(){return this.config.apiKey.startsWith("pk_")}async createInternalSession(t){var n,r;try{let i=this.getPortalApiUrl(),o=await fetch(`${i}/api/v1/sessions/create`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({merchantId:this.config.apiKey,returnUrl:this.config.returnUrl,cancelUrl:this.config.cancelUrl,challengeAge:t.challengeAge,verificationMode:t.verificationMode,merchantName:document.title||window.location.hostname,externalUserId:t.externalUserId})});if(!o.ok){let s=await o.json().catch(()=>({}));throw new Error(`Failed to create session: ${o.status} ${o.statusText}. ${s.message||""}`)}let a=await o.json(),c=a.sessionId;if(!c)throw new Error("Server did not return a sessionId");return a.verifyUrl&&(this.lastVerifyUrl=a.verifyUrl),a.sessionToken&&(this.lastSessionToken=a.sessionToken),a.handoffToken&&(this.temporaryHandoffToken=a.handoffToken),d("INTERNAL_SESSION_CREATED",{sessionId:c.substring(0,8)+"...",environment:this.config.environment,apiKeyType:"public"},this.brandConstants.name),c}catch(i){let o=i instanceof Error?i.message:String(i);throw d("INTERNAL_SESSION_FAILED",{error:o,environment:this.config.environment,apiKeyType:"public"},this.brandConstants.name),(r=(n=this.config).onError)==null||r.call(n,i),new Error(`Failed to create verification session: ${o}`)}}getUrlConfig(){return this.brandUrls[this.config.environment]||this.brandUrls.production}getTrustedOrigins(){return this.getUrlConfig().trustedOrigins}getHmacSecret(){return this.config.environment==="staging"?this.brandConstants.hmacSecretStaging:this.brandConstants.hmacSecretProd}};var et={production:{apiUrl:"https://api.privateav.com",verifyUiUrl:"https://verify.privateav.com",engineUrl:"https://engine.privateav.com",wsUrl:"wss://engine.privateav.com/api/websocket/stream",trustedOrigins:["https://verify.privateav.com","https://portal.privateav.com","https://api.privateav.com"]},staging:{apiUrl:"https://api.staging.privateav.com",verifyUiUrl:"https://verify.staging.privateav.com",engineUrl:"https://engine.staging.privateav.com",wsUrl:"wss://engine.staging.privateav.com/api/websocket/stream",trustedOrigins:["https://verify.staging.privateav.com","https://portal.staging.privateav.com","https://api.staging.privateav.com"]}},k={name:"PrivateAV",hmacSecretProd:"privateav-prod-hmac-2025",hmacSecretStaging:"privateav-stage-hmac-2025",messageType:"privateav:verification:complete",legacyMessageType:"privateav-verification",popupName:"privateav-verify",docsUrl:"https://docs.privateav.com"};var m=class extends U{constructor(t){super(t,et,k)}},nt="3.4.2";m.VERSION=nt;typeof window!="undefined"&&(N(),L(`${k.name} SDK`));var mt=m;return ct(wt);})();
3
3
  if(typeof PrivateAVSDK !== "undefined" && PrivateAVSDK.PrivateAV) { window.PrivateAV = PrivateAVSDK.PrivateAV; window.PrivateAV.VERSION = PrivateAVSDK.VERSION; }