mcp-scraper 0.90.5 → 0.90.7

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 (46) hide show
  1. package/CHANGELOG.md +38 -2
  2. package/README.md +2 -2
  3. package/dist/{analytics-repository-WNJESD4A.js → analytics-repository-FXS45ZTM.js} +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/mcp-scraper-cli.js +1 -1
  6. package/dist/bin/mcp-scraper-core.js +1 -1
  7. package/dist/bin/mcp-scraper-install.js +1 -1
  8. package/dist/bin/mcp-stdio-server.js +1 -1
  9. package/dist/bin/paa-harvest.js +1 -1
  10. package/dist/{chunk-5RTZPHIY.js → chunk-5NQY2N7J.js} +105 -105
  11. package/dist/{chunk-COIA4RW4.js → chunk-74HHYSAZ.js} +1 -1
  12. package/dist/{chunk-BVSK6YHX.js → chunk-B2C7JU4O.js} +1 -1
  13. package/dist/{chunk-56UT5M5Y.js → chunk-BDLR4CCL.js} +3 -3
  14. package/dist/{chunk-YEFXVTMJ.js → chunk-CTX3NMZQ.js} +1 -1
  15. package/dist/{chunk-W4QBJ7WW.js → chunk-DSK6RKBS.js} +2 -2
  16. package/dist/{chunk-AAJG5OHF.js → chunk-I7IS7NTC.js} +1 -1
  17. package/dist/{chunk-Q5SUDDSQ.js → chunk-IGJKAECE.js} +1 -1
  18. package/dist/chunk-KDDU6BW3.js +48 -0
  19. package/dist/{chunk-XSYLDTMI.js → chunk-LPEIHMYH.js} +1 -1
  20. package/dist/{chunk-IRWULJS5.js → chunk-OT2HUS2G.js} +1 -1
  21. package/dist/{chunk-PNDXAOZD.js → chunk-QUFR3KG2.js} +1 -1
  22. package/dist/{chunk-ZJOD3YKH.js → chunk-R7LCD65B.js} +8 -8
  23. package/dist/{chunk-XXK5PLRB.js → chunk-TBTA7VVZ.js} +9 -8
  24. package/dist/{chunk-KKHTMYCD.js → chunk-TOJBPATJ.js} +1 -0
  25. package/dist/{chunk-4OTWTGKC.js → chunk-UKFNSXP3.js} +1 -1
  26. package/dist/chunk-WEPU72WA.js +1 -0
  27. package/dist/{chunk-D6BTAT5Y.js → chunk-YGBTTW5D.js} +1 -1
  28. package/dist/{chunk-NC32JCZT.js → chunk-YTEAWZEN.js} +1 -1
  29. package/dist/chunk-ZKQRA6NQ.js +1279 -0
  30. package/dist/{db-XN7YPDGC.js → db-SVSD2AWJ.js} +1 -1
  31. package/dist/{extract-bundle-MQM3P7VS.js → extract-bundle-INT6JMJP.js} +1 -1
  32. package/dist/{gmail-service-DTUP6EWC.js → gmail-service-YCPMGW3E.js} +1 -1
  33. package/dist/index.cjs +46 -46
  34. package/dist/index.js +1 -1
  35. package/dist/{lead-list-enrichment-repository-AIMOP7YM.js → lead-list-enrichment-repository-B6Q4O4DG.js} +1 -1
  36. package/dist/{location-data-repository-25D3GHXE.js → location-data-repository-CBI5K7MR.js} +1 -1
  37. package/dist/server-LYWW6XYE.js +4956 -0
  38. package/dist/{site-extract-repository-IZT3NTWY.js → site-extract-repository-VPYOC3CP.js} +1 -1
  39. package/dist/{stripe-event-worker-5QNWGHVK.js → stripe-event-worker-AQVRF24K.js} +1 -1
  40. package/dist/worker-U43KLOLN.js +1 -0
  41. package/package.json +1 -1
  42. package/dist/chunk-5JCPVCBT.js +0 -1280
  43. package/dist/chunk-ARKQYLKU.js +0 -1
  44. package/dist/chunk-X4YCWF4B.js +0 -48
  45. package/dist/server-NTIME7TQ.js +0 -6520
  46. package/dist/worker-Z27YG7TE.js +0 -1
@@ -1,5 +1,5 @@
1
- import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,c as yt,d as an,e as on,q as f,r as v,sa as G,ta as Ce,v as U,w as J}from"./chunk-4OTWTGKC.js";import{a as Fe,e as en}from"./chunk-Q5SUDDSQ.js";import{d as nn,g as je,i as qe,k as _t,m as mt,o as rn,r as He,t as sn,u as pt}from"./chunk-D6BTAT5Y.js";import{B as dt,F as D,G as Yt,P as Xt,Q as Gt,R as he,S as lt,T as Qt,U as ut,W as X,Y as ce,_ as Ue,r as Me,s as Jt,x as zt}from"./chunk-YEFXVTMJ.js";import{Ab as Wt,Eb as oe,G as qt,Hb as Bt,Ib as ct,Nb as Vt,Q as ke,Rb as Kt,S as Ht,t as ae,ub as T,vb as Pe,xb as st,yb as at,zb as ot}from"./chunk-KKHTMYCD.js";import{createCipheriv as Di,createDecipheriv as Ti,randomBytes as xi,scryptSync as Li}from"crypto";import{setScheduleEntitlementTool as $i}from"mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";import{createHash as Si,randomUUID as hi}from"crypto";import{exportJWK as Ni,importPKCS8 as Ci,SignJWT as Ri}from"jose";function wi(e=process.env.OAUTH_ISSUER){let t=e?.trim()||"https://mcpscraper.dev",n=new URL(t);if(n.protocol!=="https:"||n.username||n.password||n.search||n.hash||n.pathname!=="/"&&n.pathname!=="")throw new Error("OAUTH_ISSUER must be an HTTPS origin without credentials, path, query, or fragment");return n.origin}var Oi=wi(),We=null;async function dn(){if(We)return We;let e=process.env.OAUTH_SIGNING_KEY;if(!e?.trim())throw new Error("OAUTH_SIGNING_KEY is not set");let t=e.includes("BEGIN")?e:Buffer.from(e,"base64").toString("utf8"),n=await Ci(t,"RS256",{extractable:!0}),i=await Ni(n),r={kty:i.kty,n:i.n,e:i.e},s=Si("sha256").update(JSON.stringify({e:r.e,kty:r.kty,n:r.n})).digest("base64url").slice(0,16);return r.kid=s,r.alg="RS256",r.use="sig",We={privateKey:n,publicJwk:r,kid:s},We}async function Ts(){return(await dn()).publicJwk}async function ln(e){let{privateKey:t,kid:n}=await dn();return new Ri({scope:e.scope,plan:e.plan}).setProtectedHeader({alg:"RS256",kid:n}).setIssuer(Oi).setSubject(e.identity).setAudience(e.audience).setIssuedAt().setJti(hi()).setExpirationTime(`${e.ttlSeconds}s`).sign(t)}var ki=()=>(process.env.MCP_MEMORY_BASE_URL??"https://memory.mcpscraper.dev").replace(/\/$/,""),Pi=()=>(process.env.MCP_MEMORY_RESOURCE_URL??"https://memory.mcpscraper.dev/mcp").replace(/\/$/,""),Mi=()=>process.env.MCP_MEMORY_ADMIN_KEY?.trim()??"",Ui=300;function Fi(e){let t=e.split(`
2
- `).find(i=>i.startsWith("data:")),n=t?t.slice(5).trim():e;return JSON.parse(n)}function gt(e){return e?(process.env.MEMORY_OPERATOR_IDENTITIES??"").split(",").map(n=>n.trim().toLowerCase()).filter(Boolean).includes(e.trim().toLowerCase()):!1}function un(){return Li(Fe(),"mcp-memory-key-v1",32)}function Fs(e){let t=xi(12),n=Di("aes-256-gcm",un(),t),i=Buffer.concat([n.update(e,"utf8"),n.final()]),r=n.getAuthTag();return`${t.toString("base64")}:${r.toString("base64")}:${i.toString("base64")}`}function js(e){try{let[t,n,i]=e.split(":"),r=Ti("aes-256-gcm",un(),Buffer.from(t,"base64"));return r.setAuthTag(Buffer.from(n,"base64")),Buffer.concat([r.update(Buffer.from(i,"base64")),r.final()]).toString("utf8")}catch{return null}}async function _n(e,t,n){try{let i=await fetch(`${ki()}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream",authorization:`Bearer ${n}`},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"tools/call",params:{name:e,arguments:t}})}),r=await i.text();if(!i.ok)return{ok:!1,error:`memory ${e} failed (${i.status})`};let s=Fi(r);if(s.error)return{ok:!1,error:s.error.message??`memory ${e} failed`};if(s.result?.structuredContent)return s.result.structuredContent;let a=s.result?.content?.find(o=>o.type==="text")?.text;if(a)try{return JSON.parse(a)}catch{return{ok:!1,error:a}}return{ok:!1,error:`memory ${e} returned no result`}}catch(i){return{ok:!1,error:i?.message??"memory call failed"}}}function mn(e){return e.email}function ji(e){return mn(e)}function qs(e){return gt(e.email)?"unlimited":e.memory_plan==="pro"||e.memory_plan==="team"?e.memory_plan:"free"}async function Hs(e){try{let{key:t}=await pn(e);if(!t)return;(await _n("listVaultsTool",{},t)).ok&&await Bt(e.id,!0)}catch{}}function qi(e){return e?!!Yt[e]?.includes_memory:!1}function F(e){return e.memory_plan==="team"?"team":qi(e.subscription_tier)||e.memory_plan==="pro"?"pro":"free"}async function pn(e,t){try{let n=gt(e.email),i=n?"unlimited":t??F(e),r=n?"memory.read memory.write memory.admin":"memory.read memory.write";return{key:await ln({identity:mn(e),scope:r,plan:i,audience:Pi(),ttlSeconds:Ui})}}catch(n){return{key:null,error:n instanceof Error?n.message:"memory service authorization unavailable"}}}async function z(e,t){let n=gt(e.email)?"unlimited":t,{key:i,error:r}=await pn(e,n);if(!i)return{ok:!1,error:r??"memory unavailable"};let s=await _n("listVaultsTool",{},i);return{ok:s.ok,error:s.error}}async function Be(e){let t=Mi();if(!t)return{ok:!1,error:"memory not configured (MCP_MEMORY_ADMIN_KEY missing)"};let n=ji(e),i=await $i.execute({apiKey:t,granteeIdentity:n,mcpScraperApiKey:e.api_key},{});return{ok:i.ok,error:i.error}}var yn=["active","trialing","past_due"];function Re(e){return yn.includes(e)}function gn(e,t){for(let n of yn){let i=e.find(r=>r.status===n&&t(r));if(i)return i}}var Hi="price_1TtYPAS8aAcsk3TGHOgrDZiQ";function Wi(e=new Date){return`${e.getUTCFullYear()}-${String(e.getUTCMonth()+1).padStart(2,"0")}`}var Bi=new Set(["connected","needs_reauth"]);function Vi(e){return Bi.has(String(e.lifecycleStatus??""))}async function Ki(e,t){let n=await ae().execute({sql:"SELECT connection_id FROM connected_account_charges WHERE user_id = ? AND period_start = ?",args:[Number(e),t]});return new Set(n.rows.map(i=>String(i.connection_id)))}async function Ji(e,t,n){await en();let i=Number(e),r=ae();return await r.batch([{sql:`
1
+ import{a as Zt,s as tn}from"./chunk-YTEAWZEN.js";import{T as cn,a as de,b as Ne,c as yt,d as an,e as on,q as f,r as v,sa as G,ta as Ce,v as U,w as J}from"./chunk-UKFNSXP3.js";import{a as Fe,e as en}from"./chunk-IGJKAECE.js";import{d as nn,g as je,i as qe,k as _t,m as mt,o as rn,r as He,t as sn,u as pt}from"./chunk-YGBTTW5D.js";import{B as dt,F as D,G as Yt,P as Xt,Q as Gt,R as he,S as lt,T as Qt,U as ut,W as X,Y as ce,_ as Ue,r as Me,s as Jt,x as zt}from"./chunk-CTX3NMZQ.js";import{Ab as Wt,Eb as oe,G as qt,Hb as Bt,Ib as ct,Nb as Vt,Q as ke,Rb as Kt,S as Ht,t as ae,ub as T,vb as Pe,xb as st,yb as at,zb as ot}from"./chunk-TOJBPATJ.js";import{createCipheriv as Di,createDecipheriv as Ti,randomBytes as xi,scryptSync as Li}from"crypto";import{setScheduleEntitlementTool as $i}from"mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";import{createHash as Si,randomUUID as hi}from"crypto";import{exportJWK as Ni,importPKCS8 as Ci,SignJWT as Ri}from"jose";function wi(e=process.env.OAUTH_ISSUER){let t=e?.trim()||"https://mcpscraper.dev",n=new URL(t);if(n.protocol!=="https:"||n.username||n.password||n.search||n.hash||n.pathname!=="/"&&n.pathname!=="")throw new Error("OAUTH_ISSUER must be an HTTPS origin without credentials, path, query, or fragment");return n.origin}var Oi=wi(),We=null;async function dn(){if(We)return We;let e=process.env.OAUTH_SIGNING_KEY;if(!e?.trim())throw new Error("OAUTH_SIGNING_KEY is not set");let t=e.includes("BEGIN")?e:Buffer.from(e,"base64").toString("utf8"),n=await Ci(t,"RS256",{extractable:!0}),i=await Ni(n),r={kty:i.kty,n:i.n,e:i.e},s=Si("sha256").update(JSON.stringify({e:r.e,kty:r.kty,n:r.n})).digest("base64url").slice(0,16);return r.kid=s,r.alg="RS256",r.use="sig",We={privateKey:n,publicJwk:r,kid:s},We}async function Ls(){return(await dn()).publicJwk}async function ln(e){let{privateKey:t,kid:n}=await dn();return new Ri({scope:e.scope,plan:e.plan}).setProtectedHeader({alg:"RS256",kid:n}).setIssuer(Oi).setSubject(e.identity).setAudience(e.audience).setIssuedAt().setJti(hi()).setExpirationTime(`${e.ttlSeconds}s`).sign(t)}var ki=()=>(process.env.MCP_MEMORY_BASE_URL??"https://memory.mcpscraper.dev").replace(/\/$/,""),Pi=()=>(process.env.MCP_MEMORY_RESOURCE_URL??"https://memory.mcpscraper.dev/mcp").replace(/\/$/,""),Mi=()=>process.env.MCP_MEMORY_ADMIN_KEY?.trim()??"",Ui=300;function Fi(e){let t=e.split(`
2
+ `).find(i=>i.startsWith("data:")),n=t?t.slice(5).trim():e;return JSON.parse(n)}function gt(e){return e?(process.env.MEMORY_OPERATOR_IDENTITIES??"").split(",").map(n=>n.trim().toLowerCase()).filter(Boolean).includes(e.trim().toLowerCase()):!1}function un(){return Li(Fe(),"mcp-memory-key-v1",32)}function qs(e){let t=xi(12),n=Di("aes-256-gcm",un(),t),i=Buffer.concat([n.update(e,"utf8"),n.final()]),r=n.getAuthTag();return`${t.toString("base64")}:${r.toString("base64")}:${i.toString("base64")}`}function Hs(e){try{let[t,n,i]=e.split(":"),r=Ti("aes-256-gcm",un(),Buffer.from(t,"base64"));return r.setAuthTag(Buffer.from(n,"base64")),Buffer.concat([r.update(Buffer.from(i,"base64")),r.final()]).toString("utf8")}catch{return null}}async function _n(e,t,n){try{let i=await fetch(`${ki()}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream",authorization:`Bearer ${n}`},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"tools/call",params:{name:e,arguments:t}})}),r=await i.text();if(!i.ok)return{ok:!1,error:`memory ${e} failed (${i.status})`};let s=Fi(r);if(s.error)return{ok:!1,error:s.error.message??`memory ${e} failed`};if(s.result?.structuredContent)return s.result.structuredContent;let a=s.result?.content?.find(o=>o.type==="text")?.text;if(a)try{return JSON.parse(a)}catch{return{ok:!1,error:a}}return{ok:!1,error:`memory ${e} returned no result`}}catch(i){return{ok:!1,error:i?.message??"memory call failed"}}}function mn(e){return e.email}function ji(e){return mn(e)}function Ws(e){return gt(e.email)?"unlimited":e.memory_plan==="pro"||e.memory_plan==="team"?e.memory_plan:"free"}async function Bs(e){try{let{key:t}=await pn(e);if(!t)return;(await _n("listVaultsTool",{},t)).ok&&await Bt(e.id,!0)}catch{}}function qi(e){return e?!!Yt[e]?.includes_memory:!1}function F(e){return e.memory_plan==="team"?"team":qi(e.subscription_tier)||e.memory_plan==="pro"?"pro":"free"}async function pn(e,t){try{let n=gt(e.email),i=n?"unlimited":t??F(e),r=n?"memory.read memory.write memory.admin":"memory.read memory.write";return{key:await ln({identity:mn(e),scope:r,plan:i,audience:Pi(),ttlSeconds:Ui})}}catch(n){return{key:null,error:n instanceof Error?n.message:"memory service authorization unavailable"}}}async function z(e,t){let n=gt(e.email)?"unlimited":t,{key:i,error:r}=await pn(e,n);if(!i)return{ok:!1,error:r??"memory unavailable"};let s=await _n("listVaultsTool",{},i);return{ok:s.ok,error:s.error}}async function Be(e){let t=Mi();if(!t)return{ok:!1,error:"memory not configured (MCP_MEMORY_ADMIN_KEY missing)"};let n=ji(e),i=await $i.execute({apiKey:t,granteeIdentity:n,mcpScraperApiKey:e.api_key},{});return{ok:i.ok,error:i.error}}var yn=["active","trialing","past_due"];function Re(e){return yn.includes(e)}function gn(e,t){for(let n of yn){let i=e.find(r=>r.status===n&&t(r));if(i)return i}}var Hi="price_1TtYPAS8aAcsk3TGHOgrDZiQ";function Wi(e=new Date){return`${e.getUTCFullYear()}-${String(e.getUTCMonth()+1).padStart(2,"0")}`}var Bi=new Set(["connected","needs_reauth"]);function Vi(e){return Bi.has(String(e.lifecycleStatus??""))}async function Ki(e,t){let n=await ae().execute({sql:"SELECT connection_id FROM connected_account_charges WHERE user_id = ? AND period_start = ?",args:[Number(e),t]});return new Set(n.rows.map(i=>String(i.connection_id)))}async function Ji(e,t,n){await en();let i=Number(e),r=ae();return await r.batch([{sql:`
3
3
  INSERT OR IGNORE INTO connected_account_charge_transfers (
4
4
  user_id, period_start, from_connection_id, to_connection_id, provider_config_key
5
5
  )
@@ -62,32 +62,86 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
62
62
  last_error_code = excluded.last_error_code,
63
63
  checked_at = datetime('now'),
64
64
  synced_at = CASE WHEN ? THEN datetime('now') ELSE connected_account_billing.synced_at END,
65
- updated_at = datetime('now')`,args:[Number(e.userId),e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,e.quantity,e.status,e.lastErrorCode,e.synced?1:0,e.synced?1:0]});let t=await Et(e.userId);if(!t)throw new Error("connected account billing state was not persisted");return t}var j=class extends Error{constructor(n,i,r=409,s){super(n);this.code=i;this.status=r;this.details=s;this.name="ConnectedAccountBillingError"}code;status;details};function bt(){let e=process.env.CONNECTED_ACCOUNT_PRICE_ID?.trim();return e||Hi||null}function vt(e,t){let n=Math.max(0,Math.round(e));return{provider:"nango",billingMode:"flat_recurring_credits",priceId:bt(),unitAmountCredits:Me,interval:"month",quantity:n,projectedMonthlyCredits:n*Me,status:t?.status??"pending",lastErrorCode:t?.last_error_code??null,syncedAt:t?.synced_at??null,usage:zt.usage}}function le(e){return e.items.data.find(t=>!!t.price?.id&&t.price.id in D)}function Xs(e){return gn(e,t=>!!le(t))}function zi(e){return e instanceof j?e.code:"stripe_connection_billing_failed"}async function Ve(e,t,n){await ft({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:bt(),quantity:t,status:n instanceof j&&n.code!=="stripe_connection_billing_failed"?"blocked":"error",lastErrorCode:zi(n),synced:!1})}async function Gs(e,t){let n=[...new Set(t.filter(Vi).map(c=>c.connectionId))],i=n.length,r=bt();if(!r){let c=new j("Connected-account billing is not configured.","connected_account_price_not_configured",503);throw await Ve(e,i,c),c}if(!e.subscription_id||!(e.subscription_tier??"")||!Object.values(D).some(c=>c.tier===e.subscription_tier)){if(i===0){let d=await ft({userId:e.id,stripeSubscriptionId:null,stripeSubscriptionItemId:null,priceId:r,quantity:0,status:"synced",lastErrorCode:null,synced:!0});return vt(0,d)}let c=new j("An active paid plan is required before connected accounts can be billed.","paid_plan_required",403);throw await Ve(e,i,c),c}let s=await Et(e.id),a=Math.max(0,s?.quantity??0),o=Wi();try{let c=await Ki(e.id,o),d=n.filter(u=>!c.has(u));for(let u of d){if(await Ji(e.id,u,o))continue;let y=Jt,E=await Kt(e.id,y,Ue.CONNECTED_ACCOUNT_FEE,`1 connected account at ${Me} credits/month (${o})`,`connection-fee:${u}:${o}`);if(!E.ok){let b=new j(`Insufficient credits to connect. Balance: ${X(E.balance_mc)} credits. Connecting requires ${X(y)} credits (${X(y-E.balance_mc)} short). Upgrade your plan or wait for your credits to refresh.`,"insufficient_credits",402,{balanceCredits:X(E.balance_mc),requiredCredits:X(y),shortByCredits:X(Math.max(0,y-E.balance_mc))});throw await Ve(e,a,b),b}await ae().execute({sql:`INSERT INTO connected_account_charges (user_id, connection_id, period_start, amount_mc)
66
- VALUES (?, ?, ?, ?) ON CONFLICT(user_id, connection_id, period_start) DO NOTHING`,args:[Number(e.id),u,o,y]}),E.duplicate||await Zt(e.id,1)}let _=await ft({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:r,quantity:i,status:"synced",lastErrorCode:null,synced:!0});return vt(i,_)}catch(c){throw c instanceof j?c:(await Ve(e,a,c),new j("Unable to update connected-account billing.","stripe_connection_billing_failed",503))}}async function Qs(e,t){return vt(t,await Et(e))}import{createHash as rr}from"crypto";import{z as H}from"zod";import{createHash as Yi,randomUUID as Q}from"crypto";function I(e){return e??v()}function Ke(e){return Yi("sha256").update(JSON.stringify(e)).digest("hex")}async function Z(e){let t=await I(e.db).query("SELECT id::text AS id FROM analytics_connections WHERE id::text=$1 AND site_id=$2",[e.connectionId,e.siteId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return t.rows[0].id}async function ia(e){let t=nn.parse(e.capability),n=I(e.db),i=await Z({siteId:e.siteId,connectionId:e.connectionId,db:n});await n.query(`INSERT INTO analytics_crm_connection_capabilities(
65
+ updated_at = datetime('now')`,args:[Number(e.userId),e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,e.quantity,e.status,e.lastErrorCode,e.synced?1:0,e.synced?1:0]});let t=await Et(e.userId);if(!t)throw new Error("connected account billing state was not persisted");return t}var j=class extends Error{constructor(n,i,r=409,s){super(n);this.code=i;this.status=r;this.details=s;this.name="ConnectedAccountBillingError"}code;status;details};function bt(){let e=process.env.CONNECTED_ACCOUNT_PRICE_ID?.trim();return e||Hi||null}function vt(e,t){let n=Math.max(0,Math.round(e));return{provider:"nango",billingMode:"flat_recurring_credits",priceId:bt(),unitAmountCredits:Me,interval:"month",quantity:n,projectedMonthlyCredits:n*Me,status:t?.status??"pending",lastErrorCode:t?.last_error_code??null,syncedAt:t?.synced_at??null,usage:zt.usage}}function le(e){return e.items.data.find(t=>!!t.price?.id&&t.price.id in D)}function Qs(e){return gn(e,t=>!!le(t))}function zi(e){return e instanceof j?e.code:"stripe_connection_billing_failed"}async function Ve(e,t,n){await ft({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:bt(),quantity:t,status:n instanceof j&&n.code!=="stripe_connection_billing_failed"?"blocked":"error",lastErrorCode:zi(n),synced:!1})}async function Zs(e,t){let n=[...new Set(t.filter(Vi).map(c=>c.connectionId))],i=n.length,r=bt();if(!r){let c=new j("Connected-account billing is not configured.","connected_account_price_not_configured",503);throw await Ve(e,i,c),c}if(!e.subscription_id||!(e.subscription_tier??"")||!Object.values(D).some(c=>c.tier===e.subscription_tier)){if(i===0){let d=await ft({userId:e.id,stripeSubscriptionId:null,stripeSubscriptionItemId:null,priceId:r,quantity:0,status:"synced",lastErrorCode:null,synced:!0});return vt(0,d)}let c=new j("An active paid plan is required before connected accounts can be billed.","paid_plan_required",403);throw await Ve(e,i,c),c}let s=await Et(e.id),a=Math.max(0,s?.quantity??0),o=Wi();try{let c=await Ki(e.id,o),d=n.filter(u=>!c.has(u));for(let u of d){if(await Ji(e.id,u,o))continue;let y=Jt,E=await Kt(e.id,y,Ue.CONNECTED_ACCOUNT_FEE,`1 connected account at ${Me} credits/month (${o})`,`connection-fee:${u}:${o}`);if(!E.ok){let b=new j(`Insufficient credits to connect. Balance: ${X(E.balance_mc)} credits. Connecting requires ${X(y)} credits (${X(y-E.balance_mc)} short). Upgrade your plan or wait for your credits to refresh.`,"insufficient_credits",402,{balanceCredits:X(E.balance_mc),requiredCredits:X(y),shortByCredits:X(Math.max(0,y-E.balance_mc))});throw await Ve(e,a,b),b}await ae().execute({sql:`INSERT INTO connected_account_charges (user_id, connection_id, period_start, amount_mc)
66
+ VALUES (?, ?, ?, ?) ON CONFLICT(user_id, connection_id, period_start) DO NOTHING`,args:[Number(e.id),u,o,y]}),E.duplicate||await Zt(e.id,1)}let _=await ft({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:r,quantity:i,status:"synced",lastErrorCode:null,synced:!0});return vt(i,_)}catch(c){throw c instanceof j?c:(await Ve(e,a,c),new j("Unable to update connected-account billing.","stripe_connection_billing_failed",503))}}async function ea(e,t){return vt(t,await Et(e))}function fn(e,t){return e&&(t??0)>0}import{createHash as Mo,createHmac as kt,generateKeyPairSync as Qr,randomUUID as se,sign as Zr}from"crypto";import es from"twilio";import{z as l}from"zod";import{z as C}from"zod";var Yi=new Set(["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLE","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UYW","UZS","VED","VES","VND","VUV","WST","XAF","XAG","XAU","XBA","XBB","XBC","XBD","XCD","XDR","XOF","XPD","XPF","XPT","XSU","XTS","XUA","XXX","YER","ZAR","ZMW","ZWG"]),we=C.string().trim().length(3).transform(e=>e.toUpperCase()).refine(e=>Yi.has(e),"Provide a valid ISO-4217 currency."),Ke=C.number().int("Money must be represented as integer minor units.").min(0,"Money cannot be negative.").max(Number.MAX_SAFE_INTEGER),Je=C.string().trim().min(1).max(80).default("1"),Xi=C.enum(["semantic_markup","source_event","crm_field","transaction"]),Gi=C.object({mode:C.literal("none"),ruleVersion:Je}).strict(),Qi=C.object({mode:C.literal("fixed"),valueMinor:Ke,currency:we,ruleVersion:Je}).strict(),Zi=C.object({mode:C.literal("dynamic"),source:Xi,currency:we,fallbackValueMinor:Ke.nullable().default(null),ruleVersion:Je}).strict(),vn=C.discriminatedUnion("mode",[Gi,Qi,Zi]),er=C.object({linkedEventName:C.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),relation:C.enum(["before","after","either"]),intervalSeconds:C.number().int().min(0).max(10*365*24*60*60).nullable(),overrideValueMinor:Ke,currency:we}).strict(),ze=C.object({targetEventName:C.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),base:vn,conditionalOverride:er.nullable().default(null),ruleVersion:Je}).strict().superRefine((e,t)=>{let n=e.conditionalOverride;n&&e.base.mode!=="none"&&n.currency!==e.base.currency&&t.addIssue({code:"custom",path:["conditionalOverride","currency"],message:"Conditional override currency must match the base value currency."})});function Q(e,t){let n=Date.parse(e);if(!Number.isFinite(n))throw new Error(`${t} must be an ISO timestamp.`);return n}function tr(e,t){let n=Ke.parse(e.valueMinor),i=En(t,e.currency);return Q(e.observedAt,"observedAt"),{valueMinor:n,currency:i,observedAt:new Date(e.observedAt).toISOString()}}function nr(e){return vn.parse(e)}function En(e,t){let i=(Array.isArray(e)?e:[e,t]).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>we.parse(r));if(i.length===0)throw new Error("A currency is required for a monetary value.");if(new Set(i).size!==1)throw new Error(`Mixed currencies are not compatible: ${[...new Set(i)].join(", ")}.`);return i[0]}function ir(e,t={}){let n=nr(e);if(n.mode==="none")return{valueMinor:null,currency:null,provenance:{mode:"none",source:null,observedAt:null,fallback:!1,ruleVersion:n.ruleVersion,resolution:"absent",baseValueMinor:null,resolvedValueMinor:null,currency:null,linkedEvent:null}};if(n.mode==="fixed"){let s=t.observedAt?new Date(Q(t.observedAt,"observedAt")).toISOString():null;return{valueMinor:n.valueMinor,currency:n.currency,provenance:{mode:"fixed",source:null,observedAt:s,fallback:!1,ruleVersion:n.ruleVersion,resolution:"fixed",baseValueMinor:n.valueMinor,resolvedValueMinor:n.valueMinor,currency:n.currency,linkedEvent:null}}}let i=t.observations?.[n.source];if(i){let s=tr(i,n.currency);return{valueMinor:s.valueMinor,currency:s.currency,provenance:{mode:"dynamic",source:n.source,observedAt:s.observedAt,fallback:!1,ruleVersion:n.ruleVersion,resolution:"dynamic",baseValueMinor:s.valueMinor,resolvedValueMinor:s.valueMinor,currency:s.currency,linkedEvent:null}}}let r=n.fallbackValueMinor;return{valueMinor:r,currency:r===null?null:n.currency,provenance:{mode:"dynamic",source:n.source,observedAt:null,fallback:r!==null,ruleVersion:n.ruleVersion,resolution:r===null?"absent":"fallback",baseValueMinor:r,resolvedValueMinor:r,currency:r===null?null:n.currency,linkedEvent:null}}}function rr(e,t,n){let i=Q(t.occurredAt,"targetEvent.occurredAt"),r=n.filter(s=>{if(s.eventName!==e.linkedEventName)return!1;let o=(Q(s.occurredAt,"linkedEvent.occurredAt")-i)/1e3;return e.relation==="before"&&o>0||e.relation==="after"&&o<0?!1:e.intervalSeconds===null||Math.abs(o)<=e.intervalSeconds});return r.sort((s,a)=>{let o=Math.abs(Q(s.occurredAt,"linkedEvent.occurredAt")-i),c=Math.abs(Q(a.occurredAt,"linkedEvent.occurredAt")-i);return o-c||s.eventId.localeCompare(a.eventId)}),r[0]??null}function bn(e,t){let n=ze.parse(e);if(t.targetEvent.eventName!==n.targetEventName)throw new Error(`Value rule targets ${n.targetEventName}, not ${t.targetEvent.eventName}.`);let i=ir({...n.base,ruleVersion:n.ruleVersion},t);if(!n.conditionalOverride)return i;let r=rr(n.conditionalOverride,t.targetEvent,t.linkedEvents);if(!r)return i;if(t.providerOperation==="restatement"&&r.identityTier!=="confirmed")throw new Error("Candidate-only evidence cannot be used for a provider restatement.");let s=i.currency?En(i.currency,n.conditionalOverride.currency):we.parse(n.conditionalOverride.currency);return{valueMinor:n.conditionalOverride.overrideValueMinor,currency:s,provenance:{...i.provenance,ruleVersion:n.ruleVersion,resolution:"conditional_override",resolvedValueMinor:n.conditionalOverride.overrideValueMinor,currency:s,linkedEvent:{eventId:r.eventId,eventName:r.eventName,occurredAt:new Date(Q(r.occurredAt,"linkedEvent.occurredAt")).toISOString(),identityTier:r.identityTier??"candidate"}}}}var An=l.object({gclid:l.string().trim().max(500).optional(),gbraid:l.string().trim().max(500).optional(),wbraid:l.string().trim().max(500).optional(),fbclid:l.string().trim().max(500).optional(),fbp:l.string().trim().max(500).optional(),fbc:l.string().trim().max(500).optional(),ttclid:l.string().trim().max(500).optional(),rdt_cid:l.string().trim().max(500).optional(),msclkid:l.string().trim().max(500).optional(),li_fat_id:l.string().trim().max(500).optional(),snapclid:l.string().trim().max(500).optional()}).strict(),sr=l.object({site_analytics:l.enum(["granted","denied","unknown"]),enhanced_matching:l.enum(["granted","denied","unknown"]),advertising_measurement:l.enum(["granted","denied","unknown"])}).strict(),ar=l.object({analytics:l.enum(["granted","denied","unknown"]).default("unknown"),adUserData:l.enum(["granted","denied","unknown"]).default("unknown"),adPersonalization:l.enum(["granted","denied","unknown"]).default("unknown"),globalPrivacyControl:l.boolean().default(!1),occurredAt:l.string().datetime(),receiptId:l.string().uuid().optional(),policyVersion:l.number().int().positive().optional(),purposes:sr.optional()}).strict().transform(e=>({...e,purposes:e.purposes??{site_analytics:e.analytics,enhanced_matching:e.adUserData,advertising_measurement:e.adPersonalization}})),In=l.enum(["browser","form","call","crm","transaction","custom_server","conversion","delivery"]),or=l.object({schemaVersion:l.literal(1).default(1),eventId:l.string().trim().min(8).max(200),sourceEventId:l.string().trim().min(1).max(300).optional(),source:l.string().trim().min(1).max(80).default("xray"),sourceAccountRef:l.string().trim().max(240).optional(),eventKind:In,eventName:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),occurredAt:l.string().datetime(),visitorId:l.string().trim().max(160).optional(),sessionId:l.string().trim().max(160).optional(),personRef:l.string().trim().max(240).optional(),orderId:l.string().trim().max(240).optional(),callId:l.string().trim().max(240).optional(),dealId:l.string().trim().max(240).optional(),path:l.string().trim().max(2e3).optional(),canonicalUrl:l.string().url().max(3e3).optional(),sourceName:l.string().trim().max(180).optional(),medium:l.string().trim().max(180).optional(),campaign:l.string().trim().max(240).optional(),clickIds:An.optional(),consent:ar.optional(),valueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).optional(),properties:l.record(l.string().max(80),l.unknown()).default({})}).strict(),Ye=or.extend({sourceEventId:l.string().trim().min(1).max(300),source:l.string().trim().min(1).max(80),sourceAccountRef:l.string().trim().min(1).max(240)}),oa=l.object({sourceEventId:l.string().trim().min(1).max(300),source:l.string().trim().min(1).max(80),sourceAccountRef:l.string().trim().min(1).max(240),contactId:l.string().trim().max(240).optional(),dealId:l.string().trim().min(1).max(240),pipelineId:l.string().trim().max(240).optional(),stageId:l.string().trim().min(1).max(240),stageName:l.string().trim().max(240).optional(),occurredAt:l.string().datetime(),valueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).optional(),visitorId:l.string().trim().max(160).optional(),sessionId:l.string().trim().max(160).optional(),clickIds:An.optional(),email:l.string().email().max(320).optional(),phone:l.string().trim().max(80).optional(),orderId:l.string().trim().max(240).optional(),status:l.enum(["open","won","lost","spam","unknown"]).default("unknown")}).strict(),cr=l.object({eventName:l.string().regex(/^[a-z][a-z0-9_]{1,79}$/).optional(),eventKind:In.optional(),source:l.string().trim().max(80).optional(),stageId:l.string().trim().max(240).optional(),status:l.enum(["open","won","lost","spam","unknown"]).optional(),answered:l.boolean().optional(),minimumCallDurationSeconds:l.number().int().min(0).max(86400).optional(),excludedTags:l.array(l.string().trim().max(80)).max(30).default([]),requiredTags:l.array(l.string().trim().max(80)).max(30).default([])}).strict(),Sn=l.object({name:l.string().trim().min(1).max(120),conversionKind:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),condition:cr,defaultValueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),defaultCurrency:l.string().trim().regex(/^[A-Za-z]{3}$/).default("USD"),valueRule:ze.optional(),enabled:l.boolean().default(!0)}).strict();function dr(e){let t=e.trim().toLowerCase().replace(/\.$/,"");if(!t||t.includes("://")||/[/?#]/.test(t))return"";try{let n=new URL(`https://${t}`).hostname.toLowerCase().replace(/\.$/,"");return!n||n.length>253||n!=="localhost"&&!n.includes(".")||n.split(".").some(i=>!i||i.length>63||!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(i))?"":n}catch{return""}}var lr=l.string().trim().max(253).transform(dr).refine(Boolean,"Provide a valid bare hostname."),Oe=l.string().trim().max(80).regex(/^[A-Za-z][A-Za-z0-9_-]{0,79}$/).refine(e=>(e.match(/\d/g)?.length??0)<7,"Semantic dimensions cannot contain phone-like values.").transform(e=>e.toLowerCase()),ur=l.object({value:l.number().finite().min(0).max(1e12).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).transform(e=>e.toUpperCase()).optional(),orderId:l.string().trim().min(1).max(200).optional(),contentId:l.string().trim().min(1).max(200).optional(),contentType:l.string().trim().min(1).max(80).optional(),placement:Oe.optional(),component:Oe.optional(),action:Oe.optional(),destination:Oe.optional(),plan:Oe.optional()}).strict(),At=l.object({name:l.string().trim().min(1).max(120),eventName:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),triggerKind:l.enum(["page","click","form","semantic"]),path:l.string().trim().startsWith("/").max(2e3).optional(),pathMatch:l.enum(["exact","prefix"]).default("exact"),selector:l.string().trim().min(1).max(500).optional(),hostnames:l.array(lr).max(25).transform(e=>[...new Set(e)]).default([]),metadata:ur.optional(),valueRule:ze.optional(),oncePerSession:l.boolean().default(!1),enabled:l.boolean().default(!0)}).strict().superRefine((e,t)=>{e.triggerKind==="page"&&!e.path&&t.addIssue({code:"custom",path:["path"],message:"Page triggers require a path."}),["click","form"].includes(e.triggerKind)&&!e.selector&&t.addIssue({code:"custom",path:["selector"],message:"Click and form triggers require a selector."}),e.triggerKind==="semantic"&&(e.path||e.selector)&&t.addIssue({code:"custom",path:["triggerKind"],message:"Semantic triggers use data-xray-event and cannot include a path or selector."})});import{createHmac as _r,randomUUID as It}from"crypto";import va from"ipaddr.js";import{randomUUID as hn}from"crypto";async function ua(e){return(await v().query(`SELECT id, site_id, name, status, version, approved_at
67
+ FROM analytics_identity_namespaces
68
+ WHERE site_id=$1 AND status IN ('draft','approved','disabled')
69
+ ORDER BY CASE status WHEN 'approved' THEN 0 WHEN 'draft' THEN 1 ELSE 2 END,
70
+ version DESC, name, id`,[e.siteId])).rows.map(n=>({id:n.id,siteId:n.site_id,name:n.name,status:n.status,version:n.version,approvedAt:n.approved_at===null?null:new Date(n.approved_at).toISOString()}))}var Nn={domain:"host",application:"server",phone:"call",crm:"crm"},Cn={host:"domain",server:"application",call:"phone",crm:"crm"};function Rn(e,t){let n=t.trim().toLowerCase();if(!n||n.length>500)throw new f("analytics_namespace_source_invalid","Provide a valid namespace source.",400);if(e==="domain"&&(n.includes("://")||/[/?#]/.test(n)||!n.includes(".")))throw new f("analytics_namespace_domain_invalid","Provide a bare approved domain.",400);return n}async function _a(e){let t=e.name.trim();if(!t||t.length>160)throw new f("analytics_namespace_name_invalid","Provide a namespace name.",400);let n=await v().connect();await n.query("BEGIN");try{await n.query("SELECT pg_advisory_xact_lock(hashtext($1))",[e.siteId]);let r=(await n.query(`SELECT id, site_id, name, status, version, approved_at
71
+ FROM analytics_identity_namespaces
72
+ WHERE site_id=$1 AND status IN ('draft','approved','disabled')
73
+ ORDER BY version DESC LIMIT 1`,[e.siteId])).rows[0];if(r){if(r.name!==t)throw new f("analytics_namespace_already_exists","This site already belongs to an identity namespace.",409);return await n.query("COMMIT"),{id:r.id,siteId:r.site_id,name:r.name,status:r.status,version:r.version,approvedAt:r.approved_at?.toISOString()??null}}let a=(await n.query(`INSERT INTO analytics_identity_namespaces(
74
+ id, site_id, name, status, approved_hosts, approved_sources, version, approved_by_user_id
75
+ ) VALUES ($1,$2,$3,'draft','[]'::jsonb,'[]'::jsonb,1,$4)
76
+ RETURNING id, site_id, name, status, version, approved_at`,[hn(),e.siteId,t,e.createdByUserId])).rows[0];return await n.query("COMMIT"),{id:a.id,siteId:a.site_id,name:a.name,status:a.status,version:a.version,approvedAt:a.approved_at?.toISOString()??null}}catch(i){throw await n.query("ROLLBACK"),i}finally{n.release()}}async function ma(e){let t=Rn(e.sourceKind,e.sourceRef),n=await v().connect();await n.query("BEGIN");try{let i=await n.query(`SELECT id, status FROM analytics_identity_namespaces
77
+ WHERE id=$1 AND site_id=$2 FOR UPDATE`,[e.namespaceId,e.siteId]);if(!i.rows[0])throw new f("analytics_namespace_not_found","Identity namespace not found.",404);if(["archived","disabled"].includes(i.rows[0].status))throw new f("analytics_namespace_inactive","Identity namespace is not active.",409);let r=Nn[e.sourceKind],s=await n.query(`INSERT INTO analytics_identity_sources(id, namespace_id, site_id, source_kind, source_ref, status)
78
+ VALUES ($1,$2,$3,$4,$5,'approved')
79
+ ON CONFLICT(namespace_id, source_kind, source_ref) DO UPDATE
80
+ SET status='approved', revoked_at=NULL
81
+ RETURNING id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at`,[hn(),e.namespaceId,e.siteId,r,t]);await n.query(`UPDATE analytics_identity_namespaces
82
+ SET status='approved', approved_by_user_id=$3, approved_at=COALESCE(approved_at, now()),
83
+ approved_hosts=CASE WHEN $4='host'
84
+ THEN (SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_hosts || to_jsonb($5::text)) value)
85
+ ELSE approved_hosts END,
86
+ approved_sources=(SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_sources || to_jsonb(($4 || ':' || $5)::text)) value),
87
+ updated_at=now()
88
+ WHERE id=$1 AND site_id=$2`,[e.namespaceId,e.siteId,e.approvedByUserId,r,t]),await n.query("COMMIT");let a=s.rows[0];return{id:a.id,namespaceId:a.namespace_id,siteId:a.site_id,sourceKind:Cn[a.source_kind],sourceRef:a.source_ref,status:a.status,createdAt:a.created_at instanceof Date?a.created_at.toISOString():new Date(a.created_at).toISOString(),revokedAt:a.revoked_at==null?null:a.revoked_at instanceof Date?a.revoked_at.toISOString():new Date(a.revoked_at).toISOString()}}catch(i){throw await n.query("ROLLBACK"),i}finally{n.release()}}async function Xe(e){let t=v();if(!(await t.query(`SELECT id FROM analytics_identity_namespaces
89
+ WHERE id=$1 AND site_id=$2 AND status='approved'`,[e.namespaceId,e.siteId])).rows[0])throw new f("analytics_namespace_boundary","The identity namespace is not approved for this site.",403);let i=[...new Set(e.identityNodeIds??[])];if(i.length&&(await t.query(`SELECT id FROM analytics_identity_nodes
90
+ WHERE site_id=$1 AND namespace_id=$2 AND id = ANY($3::uuid[])`,[e.siteId,e.namespaceId,i])).rows.length!==i.length)throw new f("analytics_namespace_boundary","Identity evidence cannot cross namespaces.",403);if(e.personId&&!(await t.query("SELECT id FROM analytics_people WHERE id=$1 AND site_id=$2 AND namespace_id=$3",[e.personId,e.siteId,e.namespaceId])).rows[0])throw new f("analytics_namespace_boundary","The person does not belong to this namespace.",403);if(e.source){let r=Rn(e.source.kind,e.source.ref);if(!(await t.query(`SELECT id FROM analytics_identity_sources
91
+ WHERE namespace_id=$1 AND site_id=$2 AND source_kind=$3 AND source_ref=$4 AND status='approved'`,[e.namespaceId,e.siteId,Nn[e.source.kind],r])).rows[0])throw new f("analytics_namespace_source_unapproved","This identity source is not approved.",403)}}async function pa(e){return await Xe(e),(await v().query(`SELECT id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at
92
+ FROM analytics_identity_sources
93
+ WHERE namespace_id=$1 AND site_id=$2
94
+ ORDER BY source_kind, source_ref`,[e.namespaceId,e.siteId])).rows.map(n=>({id:n.id,namespaceId:n.namespace_id,siteId:n.site_id,sourceKind:Cn[n.source_kind],sourceRef:n.source_ref,status:n.status,createdAt:n.created_at.toISOString(),revokedAt:n.revoked_at?.toISOString()??null}))}function mr(){let e=process.env.ANALYTICS_IDENTITY_SECRET?.trim()||process.env.SESSION_SECRET?.trim();if(!e)throw new f("analytics_identity_secret_missing","Candidate identity derivation is not configured.",503);return e}function St(e,t){return _r("sha256",mr()).update(`xray-candidate:v1:${e}:${t}`).digest("hex")}async function Aa(e){await Xe(e);let t=Math.max(1,Math.min(200,Math.floor(e.limit??50)));return(await v().query(`SELECT a.id, a.model_version, a.first_observed_at, a.last_observed_at, a.expires_at,
95
+ array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution > 0), NULL) supporting,
96
+ array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution < 0), NULL) conflicting
97
+ FROM analytics_candidate_associations a
98
+ LEFT JOIN analytics_candidate_evidence e ON e.association_id=a.id AND e.namespace_id=a.namespace_id
99
+ WHERE a.site_id=$1 AND a.namespace_id=$2 AND a.status='active' AND a.confidence_band='medium'
100
+ AND a.expires_at > $3::timestamptz
101
+ GROUP BY a.id
102
+ ORDER BY a.updated_at DESC LIMIT $4`,[e.siteId,e.namespaceId,e.now??new Date().toISOString(),t])).rows.map(i=>({associationId:i.id,band:"medium",supportingFeatures:i.supporting??[],conflictingFeatures:i.conflicting??[],modelVersion:i.model_version,firstObservedAt:i.first_observed_at.toISOString(),lastObservedAt:i.last_observed_at.toISOString(),expiresAt:i.expires_at.toISOString()}))}async function wn(e){await Xe({siteId:e.siteId,namespaceId:e.namespaceId,personId:e.personId});let t=new Date(e.occurredAt??Date.now());if(!e.evidenceRef.trim())throw new f("analytics_candidate_promotion_evidence_required","Deterministic evidence is required.",400);let n=e.promotedBy??"system";if(n==="user"&&!e.promotedByUserId)throw new f("analytics_candidate_promotion_actor_required","User-confirmed promotion requires an actor.",400);let i=St("journey_pattern",`${e.evidenceKind}:${e.evidenceRef.trim().toLowerCase()}`),s=await v().connect();await s.query("BEGIN");try{let a=await s.query(`UPDATE analytics_candidate_associations
103
+ SET status='promoted', promoted_person_id=$4, promoted_at=$5, updated_at=now()
104
+ WHERE id=$1 AND site_id=$2 AND namespace_id=$3
105
+ AND (status IN ('active','expired') OR (status='promoted' AND promoted_person_id=$4))
106
+ RETURNING id,left_identity_node_id,right_identity_node_id`,[e.associationId,e.siteId,e.namespaceId,e.personId,t.toISOString()]);if(!a.rows[0])throw new f("analytics_candidate_not_found","Candidate association not found in this namespace.",404);return await s.query(`INSERT INTO analytics_candidate_promotions(
107
+ id, site_id, namespace_id, association_id, person_id, evidence_kind,
108
+ evidence_ref_hmac, promoted_by, promoted_by_user_id, promoted_at
109
+ ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
110
+ ON CONFLICT(association_id, person_id) DO NOTHING`,[It(),e.siteId,e.namespaceId,e.associationId,e.personId,e.evidenceKind,i,n,e.promotedByUserId??null,t.toISOString()]),await s.query(`INSERT INTO analytics_privacy_audits(
111
+ id, site_id, namespace_ref, subject_ref, action, idempotency_key,
112
+ actor_user_id, result_code, affected_counts, completed_at
113
+ ) VALUES ($1,$2,$3,$4,'candidate_promoted',$5,$6,'promoted',$7::jsonb,$8)
114
+ ON CONFLICT(site_id, idempotency_key) DO NOTHING`,[It(),e.siteId,e.namespaceId,e.associationId,`candidate-promotion:${e.associationId}:${e.personId}`,e.promotedByUserId??null,JSON.stringify({candidateAssociations:1,deterministicPeople:1}),t.toISOString()]),await s.query(`INSERT INTO analytics_identity_promotion_receipts(
115
+ id,site_id,namespace_id,canonical_person_id,canonical_person_ref_hmac,
116
+ evidence_kind,evidence_ref_hmac,prior_person_ids,prior_identity_node_ids,
117
+ candidate_association_ids,affected_history_counts,schema_version,idempotency_key,promoted_at
118
+ ) VALUES($1,$2,$3,$4,$5,$6,$7,'{}'::uuid[],$8::uuid[],$9::uuid[],$10::jsonb,
119
+ 'xray.identity-promotion.v1',$11,$12)
120
+ ON CONFLICT(site_id,idempotency_key) DO NOTHING`,[It(),e.siteId,e.namespaceId,e.personId,St("journey_pattern",`person:${e.personId}`),e.evidenceKind,i,[a.rows[0].left_identity_node_id,a.rows[0].right_identity_node_id],[e.associationId],JSON.stringify({events:0,sessions:0,touches:0,conversions:0,candidateTouches:0}),St("journey_pattern",`promotion:${e.siteId}:${e.associationId}:${e.personId}:${e.evidenceKind}:${e.evidenceRef}`),t.toISOString()]),await s.query("COMMIT"),{associationId:e.associationId,personId:e.personId,promotedAt:t.toISOString(),reason:e.evidenceKind}}catch(a){throw await s.query("ROLLBACK"),a}finally{s.release()}}import{createHash as Sr}from"crypto";import{z as H}from"zod";import{createHash as pr,randomUUID as Z}from"crypto";function I(e){return e??v()}function Ge(e){return pr("sha256").update(JSON.stringify(e)).digest("hex")}async function ee(e){let t=await I(e.db).query("SELECT id::text AS id FROM analytics_connections WHERE id::text=$1 AND site_id=$2",[e.connectionId,e.siteId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return t.rows[0].id}async function Ca(e){let t=nn.parse(e.capability),n=I(e.db),i=await ee({siteId:e.siteId,connectionId:e.connectionId,db:n});await n.query(`INSERT INTO analytics_crm_connection_capabilities(
67
121
  site_id,connection_id,provider,contract_version,mode,schema_fingerprint,allowed_operations,evidence,verified_at,updated_at
68
122
  ) VALUES($1,$2,$3,1,$4,$5,$6::jsonb,$7::jsonb,$8,now())
69
123
  ON CONFLICT(connection_id,contract_version) DO UPDATE SET
70
124
  mode=EXCLUDED.mode,schema_fingerprint=EXCLUDED.schema_fingerprint,
71
125
  allowed_operations=EXCLUDED.allowed_operations,evidence=EXCLUDED.evidence,
72
- verified_at=EXCLUDED.verified_at,updated_at=now()`,[e.siteId,i,t.provider,t.mode,t.evidence.tenantSchemaFingerprint,JSON.stringify([...new Set(e.allowedOperations)].sort()),JSON.stringify(t.evidence),t.evidence.evaluatedAt])}async function ra(e){let t=je.parse(e.plan),n=I(e.db),i=await Z({siteId:e.siteId,connectionId:t.connectionId,db:n}),r=await n.query("SELECT plan,request_fingerprint FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,t.planId]);if(r.rowCount){if(r.rows[0].request_fingerprint!==t.requestFingerprint)throw new f("idempotency_conflict","This plan identifier was already used for different arguments.",409);return{plan:je.parse(r.rows[0].plan),reused:!0}}return await n.query(`INSERT INTO analytics_crm_provisioning_plans(
126
+ verified_at=EXCLUDED.verified_at,updated_at=now()`,[e.siteId,i,t.provider,t.mode,t.evidence.tenantSchemaFingerprint,JSON.stringify([...new Set(e.allowedOperations)].sort()),JSON.stringify(t.evidence),t.evidence.evaluatedAt])}async function Ra(e){let t=je.parse(e.plan),n=I(e.db),i=await ee({siteId:e.siteId,connectionId:t.connectionId,db:n}),r=await n.query("SELECT plan,request_fingerprint FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,t.planId]);if(r.rowCount){if(r.rows[0].request_fingerprint!==t.requestFingerprint)throw new f("idempotency_conflict","This plan identifier was already used for different arguments.",409);return{plan:je.parse(r.rows[0].plan),reused:!0}}return await n.query(`INSERT INTO analytics_crm_provisioning_plans(
73
127
  id,site_id,connection_id,provider,contract_version,tenant_schema_version,plan,status,
74
128
  created_by_user_id,public_plan_id,schema_fingerprint,request_fingerprint,created_at,updated_at
75
- ) VALUES($1,$2,$3,$4,1,$5,$6::jsonb,'preview',$7,$8,$9,$10,$11,$11)`,[Q(),e.siteId,i,t.provider,t.schemaFingerprint,JSON.stringify(t),e.createdByUserId,t.planId,t.schemaFingerprint,t.requestFingerprint,t.createdAt]),{plan:t,reused:!1}}async function sa(e){let t=await I(e.db).query("SELECT plan FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,e.planId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return je.parse(t.rows[0].plan)}async function aa(e){let t=qe.parse(e.receipt),n=I(e.db),i=await n.query("SELECT id::text AS id,request_fingerprint FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,t.planId]);if(!i.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);if(i.rows[0].request_fingerprint!==t.planFingerprint)throw new f("idempotency_conflict","The approved plan no longer matches the persisted plan.",409);let r=await n.query(`SELECT r.receipt FROM analytics_crm_provisioning_receipts r
129
+ ) VALUES($1,$2,$3,$4,1,$5,$6::jsonb,'preview',$7,$8,$9,$10,$11,$11)`,[Z(),e.siteId,i,t.provider,t.schemaFingerprint,JSON.stringify(t),e.createdByUserId,t.planId,t.schemaFingerprint,t.requestFingerprint,t.createdAt]),{plan:t,reused:!1}}async function wa(e){let t=await I(e.db).query("SELECT plan FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,e.planId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return je.parse(t.rows[0].plan)}async function Oa(e){let t=qe.parse(e.receipt),n=I(e.db),i=await n.query("SELECT id::text AS id,request_fingerprint FROM analytics_crm_provisioning_plans WHERE site_id=$1 AND public_plan_id=$2",[e.siteId,t.planId]);if(!i.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);if(i.rows[0].request_fingerprint!==t.planFingerprint)throw new f("idempotency_conflict","The approved plan no longer matches the persisted plan.",409);let r=await n.query(`SELECT r.receipt FROM analytics_crm_provisioning_receipts r
76
130
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
77
131
  WHERE p.site_id=$1 AND r.public_receipt_id=$2`,[e.siteId,t.receiptId]);if(r.rowCount&&qe.parse(r.rows[0].receipt).planFingerprint!==t.planFingerprint)throw new f("idempotency_conflict","This receipt identifier was already used for different arguments.",409);let s=t.status==="tested"?"test_write":"create_field",a=t.status==="failed"?"failed":"accepted";return await n.query(`INSERT INTO analytics_crm_provisioning_receipts(
78
132
  id,plan_id,operation,status,safe_error_code,warnings,created_at,public_receipt_id,receipt
79
133
  ) VALUES($1,$2,$3,$4,$5,'[]'::jsonb,$6,$7,$8::jsonb)
80
134
  ON CONFLICT (public_receipt_id) WHERE public_receipt_id IS NOT NULL
81
- DO UPDATE SET operation=EXCLUDED.operation,status=EXCLUDED.status,safe_error_code=EXCLUDED.safe_error_code,receipt=EXCLUDED.receipt`,[Q(),i.rows[0].id,s,a,t.errorCode??null,t.occurredAt,t.receiptId,JSON.stringify(t)]),await n.query(`UPDATE analytics_crm_provisioning_plans
135
+ DO UPDATE SET operation=EXCLUDED.operation,status=EXCLUDED.status,safe_error_code=EXCLUDED.safe_error_code,receipt=EXCLUDED.receipt`,[Z(),i.rows[0].id,s,a,t.errorCode??null,t.occurredAt,t.receiptId,JSON.stringify(t)]),await n.query(`UPDATE analytics_crm_provisioning_plans
82
136
  SET status=$3,approved_by_user_id=$4,approved_at=COALESCE(approved_at,$5),
83
137
  approved_field_ids=$6::jsonb,updated_at=$5
84
- WHERE site_id=$1 AND public_plan_id=$2`,[e.siteId,t.planId,t.status==="tested"?"verified":t.status==="failed"?"failed":"approved",e.approvedByUserId,t.occurredAt,JSON.stringify([...new Set(e.approvedFieldInternalNames)].sort())]),t}async function oa(e){let t=await I(e.db).query(`SELECT r.receipt FROM analytics_crm_provisioning_receipts r
138
+ WHERE site_id=$1 AND public_plan_id=$2`,[e.siteId,t.planId,t.status==="tested"?"verified":t.status==="failed"?"failed":"approved",e.approvedByUserId,t.occurredAt,JSON.stringify([...new Set(e.approvedFieldInternalNames)].sort())]),t}async function Da(e){let t=await I(e.db).query(`SELECT r.receipt FROM analytics_crm_provisioning_receipts r
85
139
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
86
- WHERE p.site_id=$1 AND r.public_receipt_id=$2`,[e.siteId,e.receiptId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return qe.parse(t.rows[0].receipt)}var At=e=>e instanceof Date?e.toISOString():e;function It(e){return rn.parse({syncId:e.sync_id,siteId:e.site_id,connectionId:e.connection_id,provider:e.provider,state:e.state,mode:e.mode,cursor:typeof e.cursor=="string"?e.cursor:e.cursor==null?null:JSON.stringify(e.cursor),lastStartedAt:At(e.last_started_at),lastSuccessAt:At(e.last_success_at),nextRunAt:At(e.next_run_at),imported:Number(e.imported),deduplicated:Number(e.deduplicated),rejected:Number(e.rejected),lastErrorCode:e.last_error_code,requestFingerprint:e.request_fingerprint})}async function ca(e){let t=I(e.db),n=await Z({siteId:e.siteId,connectionId:e.connectionId,db:t}),i=Ke({siteId:e.siteId,connectionId:n,provider:e.provider,mode:e.mode,mapping:e.mapping,mappingVersion:e.mappingVersion??1,capabilityEvidence:e.capabilityEvidence??{},backfillFrom:e.backfillFrom??null}),r=await t.query("SELECT * FROM analytics_crm_sync_runs WHERE site_id=$1 AND idempotency_key=$2",[e.siteId,e.idempotencyKey]);if(r.rowCount){if(r.rows[0].request_fingerprint!==i)throw new f("idempotency_conflict","This Idempotency-Key was already used for different CRM sync arguments.",409);return{reused:!0,status:It(r.rows[0])}}let s=await t.query(`INSERT INTO analytics_crm_sync_runs(
140
+ WHERE p.site_id=$1 AND r.public_receipt_id=$2`,[e.siteId,e.receiptId]);if(!t.rowCount)throw new f("analytics_crm_resource_not_found","CRM resource was not found.",404);return qe.parse(t.rows[0].receipt)}var ht=e=>e instanceof Date?e.toISOString():e;function Nt(e){return rn.parse({syncId:e.sync_id,siteId:e.site_id,connectionId:e.connection_id,provider:e.provider,state:e.state,mode:e.mode,cursor:typeof e.cursor=="string"?e.cursor:e.cursor==null?null:JSON.stringify(e.cursor),lastStartedAt:ht(e.last_started_at),lastSuccessAt:ht(e.last_success_at),nextRunAt:ht(e.next_run_at),imported:Number(e.imported),deduplicated:Number(e.deduplicated),rejected:Number(e.rejected),lastErrorCode:e.last_error_code,requestFingerprint:e.request_fingerprint})}async function Ta(e){let t=I(e.db),n=await ee({siteId:e.siteId,connectionId:e.connectionId,db:t}),i=Ge({siteId:e.siteId,connectionId:n,provider:e.provider,mode:e.mode,mapping:e.mapping,mappingVersion:e.mappingVersion??1,capabilityEvidence:e.capabilityEvidence??{},backfillFrom:e.backfillFrom??null}),r=await t.query("SELECT * FROM analytics_crm_sync_runs WHERE site_id=$1 AND idempotency_key=$2",[e.siteId,e.idempotencyKey]);if(r.rowCount){if(r.rows[0].request_fingerprint!==i)throw new f("idempotency_conflict","This Idempotency-Key was already used for different CRM sync arguments.",409);return{reused:!0,status:Nt(r.rows[0])}}let s=await t.query(`INSERT INTO analytics_crm_sync_runs(
87
141
  sync_id,site_id,connection_id,provider,mode,state,mapping,mapping_version,capability_evidence,idempotency_key,request_fingerprint,last_started_at
88
142
  ) VALUES($1,$2,$3,$4,$5,'queued',$6::jsonb,$7,$8::jsonb,$9,$10,now()) RETURNING *`,[e.syncId,e.siteId,n,e.provider,e.mode,JSON.stringify(e.mapping),e.mappingVersion??1,JSON.stringify(e.capabilityEvidence??{}),e.idempotencyKey,i]);return await t.query(`INSERT INTO analytics_crm_sync_state(connection_id,status,last_started_at,updated_at)
89
143
  VALUES($1,'pending',now(),now()) ON CONFLICT(connection_id)
90
- DO UPDATE SET status='pending',last_started_at=now(),updated_at=now()`,[n]),{reused:!1,status:It(s.rows[0])}}async function da(e){let t=await I(e.db).query("SELECT * FROM analytics_crm_sync_runs WHERE site_id=$1 AND sync_id=$2",[e.siteId,e.syncId]);return t.rowCount?It(t.rows[0]):null}async function la(e){let t=I(e.db);return(await t.query(`UPDATE analytics_crm_sync_runs SET next_run_at=$4,interval_seconds=$5,updated_at=now()
144
+ DO UPDATE SET status='pending',last_started_at=now(),updated_at=now()`,[n]),{reused:!1,status:Nt(s.rows[0])}}async function xa(e){let t=await I(e.db).query("SELECT * FROM analytics_crm_sync_runs WHERE site_id=$1 AND sync_id=$2",[e.siteId,e.syncId]);return t.rowCount?Nt(t.rows[0]):null}async function La(e){let t=I(e.db);return(await t.query(`UPDATE analytics_crm_sync_runs SET next_run_at=$4,interval_seconds=$5,updated_at=now()
91
145
  WHERE site_id=$1 AND sync_id=$2 AND connection_id::text=$3 AND state <> 'cancelled'`,[e.siteId,e.syncId,e.connectionId,e.nextRunAt,e.intervalSeconds])).rowCount?(e.intervalSeconds===null?await t.query(`DELETE FROM analytics_reconciliation_jobs
92
146
  WHERE connection_id::text=$1 AND status='pending'`,[e.connectionId]):await t.query(`INSERT INTO analytics_reconciliation_jobs(id,connection_id,status,next_attempt_at)
93
147
  VALUES($1,$2,'pending',$3)
@@ -95,15 +149,15 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
95
149
  status=CASE WHEN analytics_reconciliation_jobs.status='leased' THEN 'leased' ELSE 'pending' END,
96
150
  next_attempt_at=CASE WHEN analytics_reconciliation_jobs.status='leased'
97
151
  THEN analytics_reconciliation_jobs.next_attempt_at ELSE EXCLUDED.next_attempt_at END,
98
- updated_at=now()`,[Q(),e.connectionId,e.nextRunAt]),!0):!1}async function ua(e){let t=I(e.db),n=await t.query(`UPDATE analytics_crm_sync_runs SET state='cancelled',next_run_at=NULL,updated_at=now()
99
- WHERE site_id=$1 AND sync_id=$2 AND state <> 'cancelled' RETURNING connection_id::text AS connection_id`,[e.siteId,e.syncId]);return n.rowCount?(await t.query("UPDATE analytics_crm_sync_state SET status='disabled',next_sync_at=NULL,updated_at=now() WHERE connection_id::text=$1",[n.rows[0].connection_id]),!0):!1}async function _a(e){let t=I(e.db);await Z({siteId:e.siteId,connectionId:e.connectionId,db:t}),await t.query(`INSERT INTO analytics_crm_sync_state(connection_id,direction,status,last_started_at,updated_at)
152
+ updated_at=now()`,[Z(),e.connectionId,e.nextRunAt]),!0):!1}async function $a(e){let t=I(e.db),n=await t.query(`UPDATE analytics_crm_sync_runs SET state='cancelled',next_run_at=NULL,updated_at=now()
153
+ WHERE site_id=$1 AND sync_id=$2 AND state <> 'cancelled' RETURNING connection_id::text AS connection_id`,[e.siteId,e.syncId]);return n.rowCount?(await t.query("UPDATE analytics_crm_sync_state SET status='disabled',next_sync_at=NULL,updated_at=now() WHERE connection_id::text=$1",[n.rows[0].connection_id]),!0):!1}async function ka(e){let t=I(e.db);await ee({siteId:e.siteId,connectionId:e.connectionId,db:t}),await t.query(`INSERT INTO analytics_crm_sync_state(connection_id,direction,status,last_started_at,updated_at)
100
154
  VALUES($1,'inbound','running',now(),now())
101
155
  ON CONFLICT(connection_id) DO UPDATE SET
102
156
  direction=CASE WHEN analytics_crm_sync_state.direction='outbound' THEN 'bidirectional' ELSE analytics_crm_sync_state.direction END,
103
157
  status='running',last_started_at=now(),last_error_code=NULL,updated_at=now()`,[e.connectionId]),await t.query(`UPDATE analytics_crm_sync_runs SET state='running',last_started_at=now(),last_error_code=NULL,updated_at=now()
104
158
  WHERE sync_id=(SELECT sync_id FROM analytics_crm_sync_runs
105
159
  WHERE site_id=$1 AND connection_id::text=$2 AND state NOT IN ('cancelled','webhook_only')
106
- ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId])}async function ma(e){let t=I(e.db);await Z({siteId:e.siteId,connectionId:e.connectionId,db:t}),await t.query(`INSERT INTO analytics_crm_sync_state(
160
+ ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId])}async function Pa(e){let t=I(e.db);await ee({siteId:e.siteId,connectionId:e.connectionId,db:t}),await t.query(`INSERT INTO analytics_crm_sync_state(
107
161
  connection_id,cursor,direction,status,last_started_at,last_completed_at,last_success_at,next_sync_at,updated_at
108
162
  ) VALUES($1,$2::jsonb,'inbound','healthy',now(),now(),now(),$3,now())
109
163
  ON CONFLICT(connection_id) DO UPDATE SET
@@ -118,7 +172,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
118
172
  WHERE site_id=$1 AND connection_id::text=$2 AND state <> 'cancelled'
119
173
  ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId,e.hasMore?"queued":"completed",JSON.stringify(e.cursor??null),e.nextRunAt,e.imported,e.deduplicated,e.rejected]),await t.query(`INSERT INTO analytics_crm_sync_receipts(
120
174
  id,site_id,connection_id,direction,operation,subject_ref,external_receipt_id,status,occurred_at
121
- ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,'accepted',now())`,[Q(),e.siteId,e.connectionId,e.receiptFingerprint])}async function pa(e){let t=I(e.db);await Z({siteId:e.siteId,connectionId:e.connectionId,db:t});let n=e.terminal?"failed":"retrying";await t.query(`INSERT INTO analytics_crm_sync_state(connection_id,direction,status,last_completed_at,last_error_code,next_sync_at,updated_at)
175
+ ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,'accepted',now())`,[Z(),e.siteId,e.connectionId,e.receiptFingerprint])}async function Ma(e){let t=I(e.db);await ee({siteId:e.siteId,connectionId:e.connectionId,db:t});let n=e.terminal?"failed":"retrying";await t.query(`INSERT INTO analytics_crm_sync_state(connection_id,direction,status,last_completed_at,last_error_code,next_sync_at,updated_at)
122
176
  VALUES($1,'inbound','degraded',now(),$2,$3,now())
123
177
  ON CONFLICT(connection_id) DO UPDATE SET
124
178
  direction=CASE WHEN analytics_crm_sync_state.direction='outbound' THEN 'bidirectional' ELSE analytics_crm_sync_state.direction END,
@@ -129,7 +183,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
129
183
  WHERE site_id=$1 AND connection_id::text=$2 AND state <> 'cancelled'
130
184
  ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId,e.safeErrorCode,e.nextRunAt]),await t.query(`INSERT INTO analytics_crm_sync_receipts(
131
185
  id,site_id,connection_id,direction,operation,subject_ref,external_receipt_id,status,safe_error_code,occurred_at
132
- ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,$5,$6,now())`,[Q(),e.siteId,e.connectionId,e.receiptFingerprint,n,e.safeErrorCode])}function fn(e){return He.parse({policyId:e.policy_id,siteId:e.site_id,provider:e.provider,connectionId:e.connection_id,kind:e.kind,enabled:e.enabled,version:Number(e.version),provisioningReceiptId:e.provisioning_receipt_id,schemaFingerprint:e.schema_fingerprint,mappingVersion:e.mapping_version==null?null:Number(e.mapping_version),mapping:e.mapping??null,allowedFields:e.allowed_fields,selectedEvents:e.selected_events,purpose:e.purpose,updatedAt:e.updated_at instanceof Date?e.updated_at.toISOString():new Date(e.updated_at).toISOString()})}async function ya(e){let t=He.parse(e.policy),n=I(e.db),i=await Z({siteId:t.siteId,connectionId:t.connectionId,db:n});if(t.enabled){let a=(await n.query(`SELECT r.receipt->>'status' receipt_status,p.status plan_status,p.schema_fingerprint plan_schema_fingerprint,
186
+ ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,$5,$6,now())`,[Z(),e.siteId,e.connectionId,e.receiptFingerprint,n,e.safeErrorCode])}function On(e){return He.parse({policyId:e.policy_id,siteId:e.site_id,provider:e.provider,connectionId:e.connection_id,kind:e.kind,enabled:e.enabled,version:Number(e.version),provisioningReceiptId:e.provisioning_receipt_id,schemaFingerprint:e.schema_fingerprint,mappingVersion:e.mapping_version==null?null:Number(e.mapping_version),mapping:e.mapping??null,allowedFields:e.allowed_fields,selectedEvents:e.selected_events,purpose:e.purpose,updatedAt:e.updated_at instanceof Date?e.updated_at.toISOString():new Date(e.updated_at).toISOString()})}async function Ua(e){let t=He.parse(e.policy),n=I(e.db),i=await ee({siteId:t.siteId,connectionId:t.connectionId,db:n});if(t.enabled){let a=(await n.query(`SELECT r.receipt->>'status' receipt_status,p.status plan_status,p.schema_fingerprint plan_schema_fingerprint,
133
187
  c.schema_fingerprint current_schema_fingerprint
134
188
  FROM analytics_crm_provisioning_receipts r
135
189
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
@@ -147,14 +201,14 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
147
201
  AND analytics_crm_outbound_policies.connection_id=EXCLUDED.connection_id
148
202
  AND analytics_crm_outbound_policies.kind=EXCLUDED.kind
149
203
  AND analytics_crm_outbound_policies.version=EXCLUDED.version
150
- RETURNING *`,[t.policyId,t.siteId,i,t.provider,t.kind,t.enabled,t.version,t.provisioningReceiptId,t.schemaFingerprint,t.mappingVersion,JSON.stringify(t.mapping),JSON.stringify([...new Set(t.allowedFields)].sort()),JSON.stringify([...new Set(t.selectedEvents)].sort()),t.purpose,e.createdByUserId]);if(!r.rowCount)throw new f("idempotency_conflict","This policy identifier is already bound to another immutable policy version.",409);return fn(r.rows[0])}async function vn(e){return(await I(e.db).query("SELECT * FROM analytics_crm_outbound_policies WHERE site_id=$1 ORDER BY updated_at DESC,policy_id",[e.siteId])).rows.map(fn)}function St(e){return sn.parse({jobId:e.job_id,policyId:e.policy_id,siteId:e.site_id,personId:e.person_id,kind:e.kind,state:e.state,policyVersion:Number(e.policy_version),mappingVersion:e.mapping_version==null?null:Number(e.mapping_version),attempts:Number(e.attempts),nextAttemptAt:e.next_attempt_at==null?null:e.next_attempt_at instanceof Date?e.next_attempt_at.toISOString():e.next_attempt_at,safeErrorCode:e.safe_error_code,requestFingerprint:e.request_fingerprint})}async function En(e){let t=He.parse(e.policy);if(!t.enabled)throw new f("analytics_crm_outbound_policy_disabled","The CRM outbound policy is disabled.",409);let n=I(e.db);if(!(await n.query(`SELECT p.id::text id FROM analytics_people p
204
+ RETURNING *`,[t.policyId,t.siteId,i,t.provider,t.kind,t.enabled,t.version,t.provisioningReceiptId,t.schemaFingerprint,t.mappingVersion,JSON.stringify(t.mapping),JSON.stringify([...new Set(t.allowedFields)].sort()),JSON.stringify([...new Set(t.selectedEvents)].sort()),t.purpose,e.createdByUserId]);if(!r.rowCount)throw new f("idempotency_conflict","This policy identifier is already bound to another immutable policy version.",409);return On(r.rows[0])}async function Dn(e){return(await I(e.db).query("SELECT * FROM analytics_crm_outbound_policies WHERE site_id=$1 ORDER BY updated_at DESC,policy_id",[e.siteId])).rows.map(On)}function Ct(e){return sn.parse({jobId:e.job_id,policyId:e.policy_id,siteId:e.site_id,personId:e.person_id,kind:e.kind,state:e.state,policyVersion:Number(e.policy_version),mappingVersion:e.mapping_version==null?null:Number(e.mapping_version),attempts:Number(e.attempts),nextAttemptAt:e.next_attempt_at==null?null:e.next_attempt_at instanceof Date?e.next_attempt_at.toISOString():e.next_attempt_at,safeErrorCode:e.safe_error_code,requestFingerprint:e.request_fingerprint})}async function Tn(e){let t=He.parse(e.policy);if(!t.enabled)throw new f("analytics_crm_outbound_policy_disabled","The CRM outbound policy is disabled.",409);let n=I(e.db);if(!(await n.query(`SELECT p.id::text id FROM analytics_people p
151
205
  WHERE p.id=$1 AND p.site_id=$2 AND
152
206
  (p.crm_person_ref IS NOT NULL OR EXISTS (
153
207
  SELECT 1 FROM analytics_identity_edges e JOIN analytics_identity_nodes n ON n.id=e.identity_node_id
154
- WHERE e.person_id=p.id AND n.kind IN ('email','phone','customer_id') AND e.confidence >= 0.99))`,[e.personId,t.siteId])).rowCount)throw new f("analytics_crm_outbound_confirmed_person_required","CRM outbound delivery requires a confirmed person.",409);let r=await n.query("SELECT * FROM analytics_crm_outbound_jobs WHERE site_id=$1 AND idempotency_key=$2",[t.siteId,e.idempotencyKey]);if(r.rowCount){if(r.rows[0].request_fingerprint!==e.requestFingerprint)throw new f("idempotency_conflict","This idempotency key was already used for another CRM outbound request.",409);return{job:St(r.rows[0]),reused:!0}}let s=await n.query(`INSERT INTO analytics_crm_outbound_jobs(
208
+ WHERE e.person_id=p.id AND n.kind IN ('email','phone','customer_id') AND e.confidence >= 0.99))`,[e.personId,t.siteId])).rowCount)throw new f("analytics_crm_outbound_confirmed_person_required","CRM outbound delivery requires a confirmed person.",409);let r=await n.query("SELECT * FROM analytics_crm_outbound_jobs WHERE site_id=$1 AND idempotency_key=$2",[t.siteId,e.idempotencyKey]);if(r.rowCount){if(r.rows[0].request_fingerprint!==e.requestFingerprint)throw new f("idempotency_conflict","This idempotency key was already used for another CRM outbound request.",409);return{job:Ct(r.rows[0]),reused:!0}}let s=await n.query(`INSERT INTO analytics_crm_outbound_jobs(
155
209
  job_id,policy_id,site_id,person_id,kind,policy_version,mapping_version,source_event_id,
156
210
  payload_ciphertext,idempotency_key,request_fingerprint,next_attempt_at
157
- ) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,now()) RETURNING *`,[e.jobId,t.policyId,t.siteId,e.personId,t.kind,t.version,t.mappingVersion,e.sourceEventId??null,e.payloadCiphertext,e.idempotencyKey,e.requestFingerprint]);return{job:St(s.rows[0]),reused:!1}}async function bn(e){let t=await I(e.db).query(`WITH due AS (
211
+ ) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,now()) RETURNING *`,[e.jobId,t.policyId,t.siteId,e.personId,t.kind,t.version,t.mappingVersion,e.sourceEventId??null,e.payloadCiphertext,e.idempotencyKey,e.requestFingerprint]);return{job:Ct(s.rows[0]),reused:!1}}async function xn(e){let t=await I(e.db).query(`WITH due AS (
158
212
  SELECT j.job_id FROM analytics_crm_outbound_jobs j
159
213
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
160
214
  WHERE p.enabled=true AND p.provider NOT IN ('salesforce','pipedrive')
@@ -169,7 +223,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
169
223
  RETURNING j.*,p.provider,p.connection_id::text,p.mapping,p.allowed_fields,p.purpose,s.owner_user_id,
170
224
  EXISTS(SELECT 1 FROM analytics_crm_connection_capabilities c
171
225
  WHERE c.connection_id=p.connection_id AND c.contract_version=1 AND c.schema_fingerprint=p.schema_fingerprint) schema_current`,[Math.max(1,Math.min(50,e.limit)),e.leaseSeconds??90]);for(let n of t.rows)await I(e.db).query(`INSERT INTO analytics_crm_outbound_attempts(id,job_id,attempt,status,started_at)
172
- VALUES($1,$2,$3,'started',now()) ON CONFLICT(job_id,attempt) DO NOTHING`,[Q(),n.job_id,Number(n.attempts)]);return t.rows.map(n=>({job:St(n),provider:n.provider,connectionId:n.connection_id,ownerUserId:Number(n.owner_user_id),payloadCiphertext:n.payload_ciphertext,mapping:n.mapping,allowedFields:n.allowed_fields,purpose:n.purpose,schemaCurrent:n.schema_current}))}async function An(e){return(await I(e.db).query(`SELECT EXISTS(
226
+ VALUES($1,$2,$3,'started',now()) ON CONFLICT(job_id,attempt) DO NOTHING`,[Z(),n.job_id,Number(n.attempts)]);return t.rows.map(n=>({job:Ct(n),provider:n.provider,connectionId:n.connection_id,ownerUserId:Number(n.owner_user_id),payloadCiphertext:n.payload_ciphertext,mapping:n.mapping,allowedFields:n.allowed_fields,purpose:n.purpose,schemaCurrent:n.schema_current}))}async function Ln(e){return(await I(e.db).query(`SELECT EXISTS(
173
227
  SELECT 1
174
228
  FROM analytics_crm_outbound_jobs j
175
229
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
@@ -212,81 +266,27 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
212
266
  AND (($3='site_analytics' AND consent.site_analytics=true) OR
213
267
  ($3='advertising_measurement' AND consent.advertising_measurement=true))
214
268
  ))
215
- ) authorized`,[e.jobId,e.attempt,e.purpose,e.consentReceiptRef])).rows[0]?.authorized===!0}async function In(e){let t=I(e.db);return(await t.query(`UPDATE analytics_crm_outbound_jobs
269
+ ) authorized`,[e.jobId,e.attempt,e.purpose,e.consentReceiptRef])).rows[0]?.authorized===!0}async function $n(e){let t=I(e.db);return(await t.query(`UPDATE analytics_crm_outbound_jobs
216
270
  SET state='cancelled',payload_ciphertext='',next_attempt_at=NULL,
217
271
  lease_expires_at=NULL,cancelled_at=now(),safe_error_code=$3,updated_at=now()
218
272
  WHERE job_id=$1 AND state='running' AND attempts=$2`,[e.jobId,e.attempt,e.safeErrorCode.slice(0,80)])).rowCount?(await t.query(`UPDATE analytics_crm_outbound_attempts
219
273
  SET status='cancelled',safe_error_code=$3,completed_at=now()
220
- WHERE job_id=$1 AND attempt=$2 AND status='started'`,[e.jobId,e.attempt,e.safeErrorCode.slice(0,80)]),!0):!1}async function Je(e){let t=I(e.db),n=await t.query("SELECT attempts,max_attempts FROM analytics_crm_outbound_jobs WHERE job_id=$1",[e.jobId]);if(!n.rowCount)throw new f("analytics_crm_resource_not_found","CRM outbound job was not found.",404);let i=Number(n.rows[0].attempts),r=e.status!=="retrying"||i>=Number(n.rows[0].max_attempts),s=e.status==="accepted"?"delivered":e.status==="retrying"&&!r?"retrying":"dead_letter",a=`crmout_${Ke({jobId:e.jobId,attempt:i,status:e.status}).slice(0,24)}`;return await t.query(`UPDATE analytics_crm_outbound_jobs SET state=$2,safe_error_code=$3,next_attempt_at=$4,
274
+ WHERE job_id=$1 AND attempt=$2 AND status='started'`,[e.jobId,e.attempt,e.safeErrorCode.slice(0,80)]),!0):!1}async function Qe(e){let t=I(e.db),n=await t.query("SELECT attempts,max_attempts FROM analytics_crm_outbound_jobs WHERE job_id=$1",[e.jobId]);if(!n.rowCount)throw new f("analytics_crm_resource_not_found","CRM outbound job was not found.",404);let i=Number(n.rows[0].attempts),r=e.status!=="retrying"||i>=Number(n.rows[0].max_attempts),s=e.status==="accepted"?"delivered":e.status==="retrying"&&!r?"retrying":"dead_letter",a=`crmout_${Ge({jobId:e.jobId,attempt:i,status:e.status}).slice(0,24)}`;return await t.query(`UPDATE analytics_crm_outbound_jobs SET state=$2,safe_error_code=$3,next_attempt_at=$4,
221
275
  lease_expires_at=NULL,delivered_at=CASE WHEN $2='delivered' THEN now() ELSE delivered_at END,updated_at=now()
222
276
  WHERE job_id=$1 AND state='running'`,[e.jobId,s,e.safeErrorCode??null,s==="retrying"?e.retryAt??null:null]),await t.query(`INSERT INTO analytics_crm_outbound_attempts(id,job_id,attempt,status,safe_error_code,completed_at)
223
- VALUES($1,$2,$3,$4,$5,now()) ON CONFLICT(job_id,attempt) DO UPDATE SET status=EXCLUDED.status,safe_error_code=EXCLUDED.safe_error_code,completed_at=now()`,[Q(),e.jobId,i,e.status==="accepted"?"accepted":s==="retrying"?"retrying":"failed",e.safeErrorCode??null]),await t.query(`INSERT INTO analytics_crm_outbound_receipts(receipt_id,job_id,status,external_receipt_id,safe_error_code)
224
- VALUES($1,$2,$3,$4,$5) ON CONFLICT(receipt_id) DO NOTHING`,[a,e.jobId,s==="retrying"?"retrying":e.status,e.externalReceiptId??null,e.safeErrorCode??null]),pt.parse({receiptId:a,jobId:e.jobId,status:s==="retrying"?"retrying":e.status,...e.externalReceiptId?{externalReceiptId:e.externalReceiptId}:{},...e.safeErrorCode?{safeErrorCode:e.safeErrorCode}:{},occurredAt:new Date().toISOString()})}async function ga(e){return(await I(e.db).query(`SELECT r.* FROM analytics_crm_outbound_receipts r
277
+ VALUES($1,$2,$3,$4,$5,now()) ON CONFLICT(job_id,attempt) DO UPDATE SET status=EXCLUDED.status,safe_error_code=EXCLUDED.safe_error_code,completed_at=now()`,[Z(),e.jobId,i,e.status==="accepted"?"accepted":s==="retrying"?"retrying":"failed",e.safeErrorCode??null]),await t.query(`INSERT INTO analytics_crm_outbound_receipts(receipt_id,job_id,status,external_receipt_id,safe_error_code)
278
+ VALUES($1,$2,$3,$4,$5) ON CONFLICT(receipt_id) DO NOTHING`,[a,e.jobId,s==="retrying"?"retrying":e.status,e.externalReceiptId??null,e.safeErrorCode??null]),pt.parse({receiptId:a,jobId:e.jobId,status:s==="retrying"?"retrying":e.status,...e.externalReceiptId?{externalReceiptId:e.externalReceiptId}:{},...e.safeErrorCode?{safeErrorCode:e.safeErrorCode}:{},occurredAt:new Date().toISOString()})}async function Fa(e){return(await I(e.db).query(`SELECT r.* FROM analytics_crm_outbound_receipts r
225
279
  JOIN analytics_crm_outbound_jobs j ON j.job_id=r.job_id
226
280
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
227
281
  WHERE j.site_id=$1 AND p.provider NOT IN ('salesforce','pipedrive')
228
- ORDER BY r.occurred_at DESC LIMIT $2`,[e.siteId,Math.max(1,Math.min(100,e.limit??25))])).rows.map(n=>pt.parse({receiptId:n.receipt_id,jobId:n.job_id,status:n.status,...n.external_receipt_id?{externalReceiptId:n.external_receipt_id}:{},...n.safe_error_code?{safeErrorCode:n.safe_error_code}:{},occurredAt:n.occurred_at instanceof Date?n.occurred_at.toISOString():n.occurred_at}))}import{createHash as hn}from"crypto";var Gi=["hubspot","salesforce","highlevel","zoho","pipedrive","keap"],fa=["hubspot","highlevel","zoho","keap"];var q=e=>{let t={describe:!1,discover_schema:!1,incremental_read:!1,webhook:!1,create_fields:!1,upsert_person:!1,append_activity:!1,test_write:!1,list_outcomes:!1,pipeline_write:!1};for(let n of e)t[n]=!0;return Object.freeze(t)},ue=["describe","discover_schema","incremental_read","webhook","upsert_person","append_activity","test_write","list_outcomes","pipeline_write"],Sn=Object.freeze({hubspot:{provider:"hubspot",displayName:"HubSpot",providerConfigKeys:["hubspot"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"deals",activityObject:"notes",supportedObjects:["contacts","companies","deals","notes"],metadataEndpoint:"/crm/v3/properties/{objectType}",customFieldEndpoint:"/crm/v3/properties/{objectType}",externalIdStrategy:"email or an approved unique contact property",writablePersonFields:["email","firstname","lastname","phone"],requiredPersonFields:[],stageField:"dealstage",valueField:"amount",associations:["contact_to_company","contact_to_deal","note_to_contact"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-hubspot-ratelimit-remaining","retry-after"],caveats:["Effective properties and writable scopes are tenant-specific."],safeFallback:"note"},salesforce:{provider:"salesforce",displayName:"Salesforce",providerConfigKeys:["salesforce"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"Contact",pipelineObject:"Opportunity",activityObject:"Task",supportedObjects:["Lead","Contact","Account","Opportunity","Task"],metadataEndpoint:"/services/data/{version}/sobjects/{object}/describe",customFieldEndpoint:"Metadata API",externalIdStrategy:"approved External ID field",writablePersonFields:["Email","FirstName","LastName","Phone"],requiredPersonFields:["LastName"],stageField:"StageName",valueField:"Amount",associations:["Contact.AccountId","Opportunity.AccountId","OpportunityContactRole"],pagination:"cursor",batchLimit:200,rateLimitHeaders:["sforce-limit-info","retry-after"],caveats:["Required fields, validation rules, record types and field-level security are tenant-specific."],safeFallback:"activity"},highlevel:{provider:"highlevel",displayName:"HighLevel",providerConfigKeys:["highlevel","gohighlevel"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"opportunities",activityObject:"notes",supportedObjects:["contacts","companies","opportunities","notes"],metadataEndpoint:"/locations/{locationId}/customFields",customFieldEndpoint:"/locations/{locationId}/customFields",externalIdStrategy:"location-scoped email/phone or approved custom field",writablePersonFields:["email","firstName","lastName","phone"],requiredPersonFields:[],stageField:"pipelineStageId",valueField:"monetaryValue",associations:["contact.location","opportunity.contact"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Location context and installed OAuth scopes determine effective access."],safeFallback:"note"},zoho:{provider:"zoho",displayName:"Zoho CRM",providerConfigKeys:["zoho","zoho-crm"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"Contacts",pipelineObject:"Deals",activityObject:"Notes",supportedObjects:["Leads","Contacts","Accounts","Deals","Notes"],metadataEndpoint:"/crm/v7/settings/fields",customFieldEndpoint:"/crm/v7/settings/fields",externalIdStrategy:"approved unique field and duplicate-check preference",writablePersonFields:["Email","First_Name","Last_Name","Phone"],requiredPersonFields:["Last_Name"],stageField:"Stage",valueField:"Amount",associations:["Contact_Name","Account_Name","Parent_Id"],pagination:"page",batchLimit:100,rateLimitHeaders:["x-api-credits-remaining","retry-after"],caveats:["Custom field APIs, editions and API credits vary by tenant."],safeFallback:"note"},pipedrive:{provider:"pipedrive",displayName:"Pipedrive",providerConfigKeys:["pipedrive"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"persons",pipelineObject:"deals",activityObject:"notes",supportedObjects:["persons","organizations","deals","activities","notes"],metadataEndpoint:"/v1/personFields",customFieldEndpoint:"/v1/personFields",externalIdStrategy:"approved namespaced custom field; custom-field keys are tenant-specific",writablePersonFields:["name","email","phone"],requiredPersonFields:["name"],stageField:"stage_id",valueField:"value",associations:["person_id","org_id","deal_id"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Custom-field hashes must be discovered from the connected tenant."],safeFallback:"note"},keap:{provider:"keap",displayName:"Keap",providerConfigKeys:["keap","infusionsoft"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"opportunities",activityObject:"notes",supportedObjects:["contacts","companies","opportunities","notes","tags"],metadataEndpoint:"/v1/contactCustomFields",customFieldEndpoint:"/v1/contactCustomFields",externalIdStrategy:"email or approved custom field",writablePersonFields:["email_addresses","given_name","family_name","phone_numbers"],requiredPersonFields:[],stageField:"stage_id",valueField:"projected_revenue",associations:["contact.company","opportunity.contact"],pagination:"offset",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Custom fields, opportunity access and throttling depend on account entitlements."],safeFallback:"note"},callrail:{provider:"callrail",displayName:"CallRail",providerConfigKeys:["callrail"],auth:"api_key",operations:q(["describe","incremental_read","webhook","list_outcomes"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Read and webhook call outcomes only; no CRM person or pipeline writes."],safeFallback:"webhook_only"},twilio:{provider:"twilio",displayName:"Twilio",providerConfigKeys:["twilio"],auth:"account_token",operations:q(["describe","incremental_read","webhook","list_outcomes"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"page",batchLimit:100,rateLimitHeaders:["twilio-concurrent-requests","retry-after"],caveats:["Read and webhook call outcomes only; no CRM person or pipeline writes."],safeFallback:"webhook_only"},ctm:{provider:"ctm",displayName:"CallTrackingMetrics",providerConfigKeys:["ctm","calltrackingmetrics"],auth:"api_key",operations:q(["describe","webhook"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"webhook_only",batchLimit:null,rateLimitHeaders:["retry-after"],caveats:["Webhook-only until incremental cursor semantics are documented and proven."],safeFallback:"webhook_only"}}),Qi=Object.freeze({gohighlevel:"highlevel",ghl:"highlevel","high-level":"highlevel",infusionsoft:"keap","zoho-crm":"zoho",calltrackingmetrics:"ctm","call-tracking-metrics":"ctm"});function ee(e){let t=e.trim().toLowerCase().replace(/[ _]+/g,"-"),n=Qi[t]??t;if(!(n in Sn))throw new Error("analytics_provider_unsupported");return n}function ze(e){return Sn[ee(e)]}function _e(e,t){let n=ze(e);if(!n.operations[t])throw new Error(`analytics_provider_operation_unsupported:${n.provider}:${t}`);return n}var $=Object.freeze({describe:"describe-xray-crm-capabilities",discoverSchema:"discover-xray-crm-schema",upsertPerson:"upsert-xray-person",appendActivity:"append-xray-journey-activity",testWrite:"test-xray-write",listOutcomes:"list-xray-outcomes",createFields:"create-xray-custom-fields",pipelineEvent:"apply-xray-pipeline-event"}),Zi=Object.freeze({hubspot:["crm.objects.deals.read"],salesforce:["api"],highlevel:["opportunities.readonly"],zoho:["ZohoCRM.modules.deals.READ"],pipedrive:["deals:read"],keap:["full"]});function va(e){let t=ee(e.provider);if(!Gi.includes(t))throw new Error("analytics_crm_provider_required");let n=t,i=ze(n),r=new Set(e.compiledActions??[]),s=new Set(e.advertisedTools??[]),a=new Set(e.grantedScopes??[]),o=e.documented===!0,c=e.normalizedAdapter===!0,d=$.listOutcomes,_=c&&r.has(d),u=s.has(d),y=Zi[n],E=y.every(w=>a.has(w)),b=new Set(e.tenantObjects??[]),V=!!(i.pipelineObject&&b.has(i.pipelineObject)),P=o&&_&&u&&E&&V,h=i.operations.webhook&&e.webhookAdvertised===!0,L=[...o?[]:["official_documentation"],...c?[]:["normalized_adapter"],...r.has(d)?[]:[`compiled_action:${d}`],...u?[]:[`connection_tool:${d}`],...y.filter(w=>!a.has(w)).map(w=>`scope:${w}`),...!V&&i.pipelineObject?[`tenant_object:${i.pipelineObject}`]:[]],m=P&&h?"incremental_and_webhook":P?"incremental_only":h?"webhook_only":e.manualBackfillAvailable===!0?"manual_backfill":"unavailable",K=(w,A)=>i.operations[w]&&r.has(A)&&s.has(A);return{provider:n,mode:m,canSyncNow:P,canSchedule:P,canProvisionFields:K("create_fields",$.createFields),canUpsertPerson:K("upsert_person",$.upsertPerson),canApplyPipelineEvent:K("pipeline_write",$.pipelineEvent),supportedObjects:e.tenantObjects?i.supportedObjects.filter(w=>b.has(w)):[],evidence:{documented:o,normalizedAdapter:c,advertisedTools:[...s].sort(),grantedScopes:[...a].sort(),missingRequirements:L,tenantSchemaFingerprint:e.tenantSchemaFingerprint??null,evaluatedAt:e.evaluatedAt??new Date().toISOString()},caveats:i.caveats}}var Nn=[{internalName:"xray_person_id",label:"X-Ray Person ID",type:"string",writable:!0},{internalName:"xray_journey_url",label:"X-Ray Detailed Journey",type:"url",writable:!0},{internalName:"xray_first_touch",label:"X-Ray First Touch",type:"string",writable:!0},{internalName:"xray_last_non_direct_touch",label:"X-Ray Last Non-Direct Touch",type:"string",writable:!0},{internalName:"xray_converting_touch",label:"X-Ray Converting Touch",type:"string",writable:!0},{internalName:"xray_landing_page",label:"X-Ray Landing Page",type:"url",writable:!0},{internalName:"xray_conversion_page",label:"X-Ray Conversion Page",type:"url",writable:!0},{internalName:"xray_session_count",label:"X-Ray Session Count",type:"number",writable:!0},{internalName:"xray_event_count",label:"X-Ray Event Count",type:"number",writable:!0},{internalName:"xray_consent_receipt_ref",label:"X-Ray Consent Receipt",type:"string",writable:!0}];function te(e,t){return`${e}_${hn("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function Nt(e){return hn("sha256").update(JSON.stringify(e)).digest("hex")}function er(e){return Nt([...e].sort((t,n)=>`${t.object}:${t.internalName}`.localeCompare(`${n.object}:${n.internalName}`)))}function N(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function C(e,t=300){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):void 0}function tr(e){let t=C(e,80)?.toLowerCase()??"";return["number","integer","double","currency","decimal","percent","monetary"].some(n=>t.includes(n))?"number":["datetime","date","timestamp"].some(n=>t.includes(n))?"datetime":["bool","checkbox"].some(n=>t.includes(n))?"boolean":["url","uri"].some(n=>t.includes(n))?"url":"string"}function me(e){let t=C(e.object,100),n=C(e.internalName,160),i=C(e.label,160);return!t||!n||!i?null:{object:t,internalName:n,label:i,type:tr(e.type),writable:e.writable,...e.required?{required:!0}:{}}}function ht(e){return Array.isArray(e)?e.flatMap(t=>{if(!N(t))return[];let n=C(t.id,240),i=C(t.name??t.label,240);if(!n||!i)return[];let r=Array.isArray(t.stages)?t.stages.flatMap(s=>{if(!N(s))return[];let a=C(s.id,240),o=C(s.name??s.label,240);return a&&o?[{id:a,name:o}]:[]}):[];return[{id:n,name:i,stages:r}]}):[]}function nr(e,t){let n=N(t)?t:{},i=[],r=[],s=ht(n.pipelines),a=o=>{o&&i.push(o)};if(e==="hubspot"){for(let[o,c]of[["contacts","contacts"],["deals","deals"]])if(Array.isArray(n[o])){r.push(c);for(let d of n[o])N(d)&&a(me({object:c,internalName:d.name,label:d.label,type:d.type,writable:d.archived!==!0&&d.providerDefined!==!0}))}}else if(e==="salesforce"){if(Array.isArray(n.objects))for(let o of n.objects){if(!N(o))continue;let c=C(o.object,100);if(!c)continue;r.push(c);let d=N(o.permissions)?o.permissions:{};if(Array.isArray(o.fields))for(let _ of o.fields)N(_)&&a(me({object:c,internalName:_.name,label:_.label,type:_.type,writable:d.update===!0&&_.updateable===!0,required:_.required===!0}))}}else if(e==="highlevel"){if(Array.isArray(n.customFields)){for(let o of n.customFields)if(N(o)){let c=o.model==="opportunity"?"opportunities":"contacts";r.push(c),a(me({object:c,internalName:o.fieldKey??o.id,label:o.name,type:o.dataType,writable:!0}))}}}else if(e==="zoho"){let o=Array.isArray(n.moduleResults)?n.moduleResults:[n];for(let c of o){if(!N(c))continue;let d=C(c.module,100);if(d&&(r.push(d),Array.isArray(c.fields)))for(let _ of c.fields)N(_)&&a(me({object:d,internalName:_.apiName,label:_.label,type:_.dataType,writable:_.writable===!0,required:_.required===!0}))}}else if(e==="pipedrive"){if(Array.isArray(n.fields)){for(let c of n.fields)if(N(c)){let d=c.objectType==="deal"?"deals":"persons";r.push(d),a(me({object:d,internalName:c.code,label:c.name,type:c.fieldType,writable:c.writable===!0}))}}let o=Array.isArray(n.stages)?n.stages:[];s=ht(Array.isArray(n.pipelines)?n.pipelines.map(c=>N(c)?{...c,id:String(c.id??""),stages:o.filter(d=>N(d)&&String(d.pipelineId)===String(c.id)).map(d=>({...d,id:String(d.id??"")}))}:c):[])}else if(e==="keap"){if(r.push("contacts"),Array.isArray(n.contactFields))for(let c of n.contactFields)N(c)&&a(me({object:"contacts",internalName:c.fieldName??c.id,label:c.label,type:c.fieldType,writable:!0}));let o=Array.isArray(n.opportunityStages)?n.opportunityStages:[];o.length&&(s=[{id:"opportunities",name:"Opportunities",stages:ht([{id:"opportunities",name:"Opportunities",stages:o}])[0]?.stages??[]}])}return{fields:i,objects:[...new Set(r)],pipelines:s,...Array.isArray(n.allowedOperations)?{allowedOperations:n.allowedOperations.filter(o=>typeof o=="string")}:{}}}function ir(e){return!N(e)||!Array.isArray(e.fields)?[]:e.fields.flatMap(t=>{if(!N(t))return[];let n=C(t.object,100),i=C(t.internalName??t.internal_name,160);if(!n||!i)return[];let r=C(t.id??t.providerFieldId,240);return[{object:n,internalName:i,...r?{providerFieldId:r}:{}}]})}function Ye(e){let t=ee(e);if(t==="callrail"||t==="twilio"||t==="ctm")throw new Error("analytics_crm_provider_required");return t}function Ia(e){let t=Ye(e.provider),n=_e(t,"discover_schema");if(!n.personObject||!e.connectionId.trim())throw new Error("analytics_crm_provisioning_invalid_scope");let i={},r=[];for(let d of Nn){let _=e.fields.find(u=>u.object===n.personObject&&(u.internalName.toLowerCase()===d.internalName||u.label.toLowerCase()===d.label.toLowerCase()));_?_.writable&&(i[d.internalName]=_.internalName):r.push({...d,object:n.personObject})}let s=e.now??new Date().toISOString(),a=er(e.fields),o={provider:t,connectionId:e.connectionId,existingMappings:i,proposedFields:r,schemaFingerprint:a},c=Nt(o);return{planId:te("crmplan",o),provider:t,connectionId:e.connectionId,personObject:n.personObject,existingMappings:i,proposedFields:r,fallback:n.safeFallback==="activity"?"activity":"note",permissionRequirements:["schema:read",...r.length?["schema:write"]:[],"records:write"],schemaFingerprint:a,requestFingerprint:c,createdAt:s}}async function Sa(e){let t=_e(e.plan.provider,"create_fields"),n=te("crmplan",{provider:e.plan.provider,connectionId:e.plan.connectionId,existingMappings:e.plan.existingMappings,proposedFields:e.plan.proposedFields,schemaFingerprint:e.plan.schemaFingerprint}),i=Nt({provider:e.plan.provider,connectionId:e.plan.connectionId,existingMappings:e.plan.existingMappings,proposedFields:e.plan.proposedFields,schemaFingerprint:e.plan.schemaFingerprint});if(e.plan.planId!==n||e.plan.personObject!==t.personObject||e.plan.requestFingerprint!==i)throw new Error("analytics_crm_provisioning_plan_tampered");let r=new Set(Nn.map(c=>c.internalName));if(e.plan.proposedFields.some(c=>c.object!==t.personObject||!r.has(c.internalName)))throw new Error("analytics_crm_provisioning_plan_tampered");if(!Number.isInteger(e.approvedByUserId)||e.approvedByUserId<=0)throw new Error("analytics_crm_provisioning_approval_required");let s=new Set(e.approvedFieldInternalNames);if([...s].some(c=>!e.plan.proposedFields.some(d=>d.internalName===c)))throw new Error("analytics_crm_provisioning_field_not_in_plan");let a=e.plan.proposedFields.filter(c=>s.has(c.internalName)),o=te("crmreceipt",{planId:e.plan.planId,fields:[...s].sort()});try{let c=a.length?await e.dependencies.callAction({connectionId:e.plan.connectionId,action:$.createFields,payload:{provider:e.plan.provider,fields:a},idempotencyKey:o}):{fields:[]};return{receiptId:o,planId:e.plan.planId,provider:e.plan.provider,connectionId:e.plan.connectionId,status:"approved",createdFields:ir(c),existingMappings:e.plan.existingMappings,cleanup:{supported:!1,instructions:"Created empty X-Ray fields may be removed manually after confirming they are not populated."},planFingerprint:e.plan.requestFingerprint,occurredAt:e.now??new Date().toISOString()}}catch(c){return{receiptId:o,planId:e.plan.planId,provider:e.plan.provider,connectionId:e.plan.connectionId,status:"failed",createdFields:[],existingMappings:e.plan.existingMappings,cleanup:{supported:!1,instructions:"No cleanup was attempted."},planFingerprint:e.plan.requestFingerprint,occurredAt:e.now??new Date().toISOString(),errorCode:C(c instanceof Error?c.message:c,80)?.replace(/[^a-zA-Z0-9_:-]/g,"_")||"analytics_crm_provisioning_failed"}}}async function ha(e){if(e.receipt.status!=="approved")throw new Error("analytics_crm_provisioning_not_approved");_e(e.receipt.provider,"test_write");let t=te("crmtest",e.receipt.receiptId),n=await e.dependencies.callAction({connectionId:e.receipt.connectionId,action:$.testWrite,payload:{provider:e.receipt.provider,marker:"X-Ray reversible connection test",cleanupRequested:!0},idempotencyKey:t});if(!N(n)||n.ok!==!0)throw new Error("analytics_crm_test_write_not_verified");return{...e.receipt,status:"tested",occurredAt:e.now??new Date().toISOString()}}async function Cn(e){let t=Ye(e.provider);if(_e(t,"upsert_person"),e.person.identityTier!=="confirmed"||!e.person.deterministicIdentity.value.trim())throw new Error("analytics_crm_person_requires_confirmed_identity");let n=te("crmperson",{provider:t,connectionId:e.connectionId,personId:e.person.personId,identity:e.person.deterministicIdentity,consent:e.person.consentReceiptRef}),i={provider:t,identity:e.person.deterministicIdentity,contact:e.person.contact,journey:{personId:e.person.personId,firstTouch:e.person.firstTouch,lastNonDirectTouch:e.person.lastNonDirectTouch,convertingTouch:e.person.convertingTouch,landingPage:e.person.landingPage,conversionPage:e.person.conversionPage,sessionCount:e.person.sessionCount,eventCount:e.person.eventCount,campaignClickCoverage:e.person.campaignClickCoverage,consentReceiptRef:e.person.consentReceiptRef,detailedJourneyUrl:e.person.detailedJourneyUrl},mapping:e.mapping??{},createDeal:!1},r=await e.dependencies.callAction({connectionId:e.connectionId,action:$.upsertPerson,payload:i,idempotencyKey:n}),s=N(r)?C(r.recordRef??r.id,240):void 0;return{receiptId:n,provider:t,operation:"person_upsert",dealCreated:!1,...s?{providerRecordRef:s}:{}}}async function Rn(e){let t=Ye(e.provider);if(_e(t,"pipeline_write"),e.person.identityTier!=="confirmed")throw new Error("analytics_crm_pipeline_requires_confirmed_identity");if(e.event.eventName!==e.mapping.eventName)throw new Error("analytics_crm_pipeline_event_not_mapped");if(e.mapping.valueSource==="verified_revenue"&&(!Number.isSafeInteger(e.event.verifiedRevenueMinor)||e.event.verifiedRevenueMinor<0))throw new Error("analytics_crm_pipeline_verified_revenue_required");let n=te("crmpipeline",{provider:t,connectionId:e.connectionId,eventId:e.event.eventId,mappingVersion:e.mapping.version});return await e.dependencies.callAction({connectionId:e.connectionId,action:$.pipelineEvent,payload:{provider:t,command:"apply_pipeline_event",person:{personId:e.person.personId,identity:e.person.deterministicIdentity},event:e.event,mapping:e.mapping},idempotencyKey:n}),{receiptId:n,provider:t,operation:"pipeline_event",dealCreatedOrUpdated:!0}}async function Na(e){let t=Ye(e.provider),n=ze(t),i=t==="highlevel"?{locationId:e.discoveryContext?.locationId}:t==="zoho"?{module:e.discoveryContext?.zohoModules?.[0]??"Contacts"}:{};if(t==="highlevel"&&!C(i.locationId,128))throw new Error("analytics_crm_highlevel_location_required");let r=(y,E)=>e.dependencies.callAction({connectionId:e.connectionId,action:$.discoverSchema,payload:y,idempotencyKey:te("crmdiscover",{provider:t,connectionId:e.connectionId,actionPayload:y,suffix:E})}),s=await r(i);if(t==="zoho"){let y=[...new Set(e.discoveryContext?.zohoModules??["Contacts","Deals"])],E=[s];for(let b of y.slice(1))E.push(await r({module:b},b));s={moduleResults:E}}let a=nr(t,s),o=a.fields,c=Object.entries(n.operations).filter(([,y])=>y).map(([y])=>y),d=a.allowedOperations?new Set(a.allowedOperations.map(y=>C(y,80)).filter(y=>!!y)):null,_=d?c.filter(y=>d.has(y)):c,u=new Set(n.supportedObjects);return{provider:t,publicProfile:n,connectionId:e.connectionId,fields:o,objects:a.objects.length?a.objects.filter(y=>u.has(y)):n.supportedObjects,pipelines:a.pipelines,allowedOperations:_,discoveredAt:e.now??new Date().toISOString()}}var sr=25,ar=25e3,wn=H.object({person:_t,event:mt.nullable(),mapping:H.object({version:H.number().int().positive(),eventName:H.string(),pipelineId:H.string(),stageId:H.string(),operation:H.enum(["create_or_update_deal","update_stage"]),valueSource:H.enum(["none","verified_revenue"]),activationEligible:H.boolean()}).strict().nullable()}).strict();function or(e,t){return`${e}_${rr("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function Xe(e){return cn(e)??void 0}function cr(e,t,n){return e.purpose==="necessary_form_fulfillment"?t.eventKind==="form":e.purpose==="site_analytics"?n.siteAnalytics:n.advertisingMeasurement}function k(e,t){return e.has(t)}function dr(e){let t=new Set(e.policy.allowedFields),n=e.contact?{...k(t,"contact.email")&&e.contact.email?{email:e.contact.email}:{},...k(t,"contact.phone")&&e.contact.phone?{phone:e.contact.phone}:{},...k(t,"contact.firstName")&&e.contact.firstName?{firstName:e.contact.firstName}:{},...k(t,"contact.lastName")&&e.contact.lastName?{lastName:e.contact.lastName}:{}}:void 0,i=[e.event.sourceName??e.event.source,e.event.medium,e.event.campaign].filter(Boolean).map(a=>String(a).slice(0,240)).join(" / "),r=e.policy.purpose==="advertising_measurement"&&e.consent.advertisingMeasurement?G(e.event.clickIds):{},s=Object.entries(r).filter(([a])=>k(t,`clickIds.${a}`)).map(([a])=>a).sort().join(",");return _t.parse({identityTier:"confirmed",personId:e.personId,deterministicIdentity:{kind:"crm_id",value:e.crmPersonRef},...n&&Object.keys(n).length?{contact:n}:{},...k(t,"attribution.firstTouch")&&i?{firstTouch:i}:{},...k(t,"attribution.lastNonDirectTouch")&&i?{lastNonDirectTouch:i}:{},...k(t,"attribution.convertingTouch")&&i?{convertingTouch:i}:{},...k(t,"attribution.landingPage")&&Xe(e.event.canonicalUrl)?{landingPage:Xe(e.event.canonicalUrl)}:{},...k(t,"attribution.conversionPage")&&Xe(e.event.canonicalUrl)?{conversionPage:Xe(e.event.canonicalUrl)}:{},sessionCount:e.sessionCount,eventCount:e.eventCount,...s?{campaignClickCoverage:s}:{},consentReceiptRef:e.consent.receiptId??`purpose:${e.policy.purpose}`,detailedJourneyUrl:`https://mcpscraper.dev/dashboard/analytics/people/${encodeURIComponent(e.personId)}`})}async function On(e){let t=(await vn({siteId:e.siteId,db:e.db})).filter(s=>s.enabled&&cr(s,e.event,e.consent)).filter(s=>s.selectedEvents.length===0||s.selectedEvents.includes(e.event.eventName));if(!t.length)return{queued:0,reused:0};let n=await e.db.query(`SELECT p.crm_person_ref,
282
+ ORDER BY r.occurred_at DESC LIMIT $2`,[e.siteId,Math.max(1,Math.min(100,e.limit??25))])).rows.map(n=>pt.parse({receiptId:n.receipt_id,jobId:n.job_id,status:n.status,...n.external_receipt_id?{externalReceiptId:n.external_receipt_id}:{},...n.safe_error_code?{safeErrorCode:n.safe_error_code}:{},occurredAt:n.occurred_at instanceof Date?n.occurred_at.toISOString():n.occurred_at}))}import{createHash as Pn}from"crypto";var gr=["hubspot","salesforce","highlevel","zoho","pipedrive","keap"],ja=["hubspot","highlevel","zoho","keap"];var q=e=>{let t={describe:!1,discover_schema:!1,incremental_read:!1,webhook:!1,create_fields:!1,upsert_person:!1,append_activity:!1,test_write:!1,list_outcomes:!1,pipeline_write:!1};for(let n of e)t[n]=!0;return Object.freeze(t)},ue=["describe","discover_schema","incremental_read","webhook","upsert_person","append_activity","test_write","list_outcomes","pipeline_write"],kn=Object.freeze({hubspot:{provider:"hubspot",displayName:"HubSpot",providerConfigKeys:["hubspot"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"deals",activityObject:"notes",supportedObjects:["contacts","companies","deals","notes"],metadataEndpoint:"/crm/v3/properties/{objectType}",customFieldEndpoint:"/crm/v3/properties/{objectType}",externalIdStrategy:"email or an approved unique contact property",writablePersonFields:["email","firstname","lastname","phone"],requiredPersonFields:[],stageField:"dealstage",valueField:"amount",associations:["contact_to_company","contact_to_deal","note_to_contact"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-hubspot-ratelimit-remaining","retry-after"],caveats:["Effective properties and writable scopes are tenant-specific."],safeFallback:"note"},salesforce:{provider:"salesforce",displayName:"Salesforce",providerConfigKeys:["salesforce"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"Contact",pipelineObject:"Opportunity",activityObject:"Task",supportedObjects:["Lead","Contact","Account","Opportunity","Task"],metadataEndpoint:"/services/data/{version}/sobjects/{object}/describe",customFieldEndpoint:"Metadata API",externalIdStrategy:"approved External ID field",writablePersonFields:["Email","FirstName","LastName","Phone"],requiredPersonFields:["LastName"],stageField:"StageName",valueField:"Amount",associations:["Contact.AccountId","Opportunity.AccountId","OpportunityContactRole"],pagination:"cursor",batchLimit:200,rateLimitHeaders:["sforce-limit-info","retry-after"],caveats:["Required fields, validation rules, record types and field-level security are tenant-specific."],safeFallback:"activity"},highlevel:{provider:"highlevel",displayName:"HighLevel",providerConfigKeys:["highlevel","gohighlevel"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"opportunities",activityObject:"notes",supportedObjects:["contacts","companies","opportunities","notes"],metadataEndpoint:"/locations/{locationId}/customFields",customFieldEndpoint:"/locations/{locationId}/customFields",externalIdStrategy:"location-scoped email/phone or approved custom field",writablePersonFields:["email","firstName","lastName","phone"],requiredPersonFields:[],stageField:"pipelineStageId",valueField:"monetaryValue",associations:["contact.location","opportunity.contact"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Location context and installed OAuth scopes determine effective access."],safeFallback:"note"},zoho:{provider:"zoho",displayName:"Zoho CRM",providerConfigKeys:["zoho","zoho-crm"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"Contacts",pipelineObject:"Deals",activityObject:"Notes",supportedObjects:["Leads","Contacts","Accounts","Deals","Notes"],metadataEndpoint:"/crm/v7/settings/fields",customFieldEndpoint:"/crm/v7/settings/fields",externalIdStrategy:"approved unique field and duplicate-check preference",writablePersonFields:["Email","First_Name","Last_Name","Phone"],requiredPersonFields:["Last_Name"],stageField:"Stage",valueField:"Amount",associations:["Contact_Name","Account_Name","Parent_Id"],pagination:"page",batchLimit:100,rateLimitHeaders:["x-api-credits-remaining","retry-after"],caveats:["Custom field APIs, editions and API credits vary by tenant."],safeFallback:"note"},pipedrive:{provider:"pipedrive",displayName:"Pipedrive",providerConfigKeys:["pipedrive"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"persons",pipelineObject:"deals",activityObject:"notes",supportedObjects:["persons","organizations","deals","activities","notes"],metadataEndpoint:"/v1/personFields",customFieldEndpoint:"/v1/personFields",externalIdStrategy:"approved namespaced custom field; custom-field keys are tenant-specific",writablePersonFields:["name","email","phone"],requiredPersonFields:["name"],stageField:"stage_id",valueField:"value",associations:["person_id","org_id","deal_id"],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Custom-field hashes must be discovered from the connected tenant."],safeFallback:"note"},keap:{provider:"keap",displayName:"Keap",providerConfigKeys:["keap","infusionsoft"],auth:"oauth2",operations:q([...ue,"create_fields"]),personObject:"contacts",pipelineObject:"opportunities",activityObject:"notes",supportedObjects:["contacts","companies","opportunities","notes","tags"],metadataEndpoint:"/v1/contactCustomFields",customFieldEndpoint:"/v1/contactCustomFields",externalIdStrategy:"email or approved custom field",writablePersonFields:["email_addresses","given_name","family_name","phone_numbers"],requiredPersonFields:[],stageField:"stage_id",valueField:"projected_revenue",associations:["contact.company","opportunity.contact"],pagination:"offset",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Custom fields, opportunity access and throttling depend on account entitlements."],safeFallback:"note"},callrail:{provider:"callrail",displayName:"CallRail",providerConfigKeys:["callrail"],auth:"api_key",operations:q(["describe","incremental_read","webhook","list_outcomes"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"cursor",batchLimit:100,rateLimitHeaders:["x-ratelimit-remaining","retry-after"],caveats:["Read and webhook call outcomes only; no CRM person or pipeline writes."],safeFallback:"webhook_only"},twilio:{provider:"twilio",displayName:"Twilio",providerConfigKeys:["twilio"],auth:"account_token",operations:q(["describe","incremental_read","webhook","list_outcomes"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"page",batchLimit:100,rateLimitHeaders:["twilio-concurrent-requests","retry-after"],caveats:["Read and webhook call outcomes only; no CRM person or pipeline writes."],safeFallback:"webhook_only"},ctm:{provider:"ctm",displayName:"CallTrackingMetrics",providerConfigKeys:["ctm","calltrackingmetrics"],auth:"api_key",operations:q(["describe","webhook"]),personObject:null,pipelineObject:null,activityObject:"calls",supportedObjects:["calls"],metadataEndpoint:null,customFieldEndpoint:null,externalIdStrategy:null,writablePersonFields:[],requiredPersonFields:[],stageField:null,valueField:null,associations:[],pagination:"webhook_only",batchLimit:null,rateLimitHeaders:["retry-after"],caveats:["Webhook-only until incremental cursor semantics are documented and proven."],safeFallback:"webhook_only"}}),fr=Object.freeze({gohighlevel:"highlevel",ghl:"highlevel","high-level":"highlevel",infusionsoft:"keap","zoho-crm":"zoho",calltrackingmetrics:"ctm","call-tracking-metrics":"ctm"});function te(e){let t=e.trim().toLowerCase().replace(/[ _]+/g,"-"),n=fr[t]??t;if(!(n in kn))throw new Error("analytics_provider_unsupported");return n}function Ze(e){return kn[te(e)]}function _e(e,t){let n=Ze(e);if(!n.operations[t])throw new Error(`analytics_provider_operation_unsupported:${n.provider}:${t}`);return n}var $=Object.freeze({describe:"describe-xray-crm-capabilities",discoverSchema:"discover-xray-crm-schema",upsertPerson:"upsert-xray-person",appendActivity:"append-xray-journey-activity",testWrite:"test-xray-write",listOutcomes:"list-xray-outcomes",createFields:"create-xray-custom-fields",pipelineEvent:"apply-xray-pipeline-event"}),vr=Object.freeze({hubspot:["crm.objects.deals.read"],salesforce:["api"],highlevel:["opportunities.readonly"],zoho:["ZohoCRM.modules.deals.READ"],pipedrive:["deals:read"],keap:["full"]});function qa(e){let t=te(e.provider);if(!gr.includes(t))throw new Error("analytics_crm_provider_required");let n=t,i=Ze(n),r=new Set(e.compiledActions??[]),s=new Set(e.advertisedTools??[]),a=new Set(e.grantedScopes??[]),o=e.documented===!0,c=e.normalizedAdapter===!0,d=$.listOutcomes,_=c&&r.has(d),u=s.has(d),y=vr[n],E=y.every(w=>a.has(w)),b=new Set(e.tenantObjects??[]),V=!!(i.pipelineObject&&b.has(i.pipelineObject)),P=o&&_&&u&&E&&V,h=i.operations.webhook&&e.webhookAdvertised===!0,L=[...o?[]:["official_documentation"],...c?[]:["normalized_adapter"],...r.has(d)?[]:[`compiled_action:${d}`],...u?[]:[`connection_tool:${d}`],...y.filter(w=>!a.has(w)).map(w=>`scope:${w}`),...!V&&i.pipelineObject?[`tenant_object:${i.pipelineObject}`]:[]],m=P&&h?"incremental_and_webhook":P?"incremental_only":h?"webhook_only":e.manualBackfillAvailable===!0?"manual_backfill":"unavailable",K=(w,A)=>i.operations[w]&&r.has(A)&&s.has(A);return{provider:n,mode:m,canSyncNow:P,canSchedule:P,canProvisionFields:K("create_fields",$.createFields),canUpsertPerson:K("upsert_person",$.upsertPerson),canApplyPipelineEvent:K("pipeline_write",$.pipelineEvent),supportedObjects:e.tenantObjects?i.supportedObjects.filter(w=>b.has(w)):[],evidence:{documented:o,normalizedAdapter:c,advertisedTools:[...s].sort(),grantedScopes:[...a].sort(),missingRequirements:L,tenantSchemaFingerprint:e.tenantSchemaFingerprint??null,evaluatedAt:e.evaluatedAt??new Date().toISOString()},caveats:i.caveats}}var Mn=[{internalName:"xray_person_id",label:"X-Ray Person ID",type:"string",writable:!0},{internalName:"xray_journey_url",label:"X-Ray Detailed Journey",type:"url",writable:!0},{internalName:"xray_first_touch",label:"X-Ray First Touch",type:"string",writable:!0},{internalName:"xray_last_non_direct_touch",label:"X-Ray Last Non-Direct Touch",type:"string",writable:!0},{internalName:"xray_converting_touch",label:"X-Ray Converting Touch",type:"string",writable:!0},{internalName:"xray_landing_page",label:"X-Ray Landing Page",type:"url",writable:!0},{internalName:"xray_conversion_page",label:"X-Ray Conversion Page",type:"url",writable:!0},{internalName:"xray_session_count",label:"X-Ray Session Count",type:"number",writable:!0},{internalName:"xray_event_count",label:"X-Ray Event Count",type:"number",writable:!0},{internalName:"xray_consent_receipt_ref",label:"X-Ray Consent Receipt",type:"string",writable:!0}];function ne(e,t){return`${e}_${Pn("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function wt(e){return Pn("sha256").update(JSON.stringify(e)).digest("hex")}function Er(e){return wt([...e].sort((t,n)=>`${t.object}:${t.internalName}`.localeCompare(`${n.object}:${n.internalName}`)))}function N(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function R(e,t=300){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):void 0}function br(e){let t=R(e,80)?.toLowerCase()??"";return["number","integer","double","currency","decimal","percent","monetary"].some(n=>t.includes(n))?"number":["datetime","date","timestamp"].some(n=>t.includes(n))?"datetime":["bool","checkbox"].some(n=>t.includes(n))?"boolean":["url","uri"].some(n=>t.includes(n))?"url":"string"}function me(e){let t=R(e.object,100),n=R(e.internalName,160),i=R(e.label,160);return!t||!n||!i?null:{object:t,internalName:n,label:i,type:br(e.type),writable:e.writable,...e.required?{required:!0}:{}}}function Rt(e){return Array.isArray(e)?e.flatMap(t=>{if(!N(t))return[];let n=R(t.id,240),i=R(t.name??t.label,240);if(!n||!i)return[];let r=Array.isArray(t.stages)?t.stages.flatMap(s=>{if(!N(s))return[];let a=R(s.id,240),o=R(s.name??s.label,240);return a&&o?[{id:a,name:o}]:[]}):[];return[{id:n,name:i,stages:r}]}):[]}function Ar(e,t){let n=N(t)?t:{},i=[],r=[],s=Rt(n.pipelines),a=o=>{o&&i.push(o)};if(e==="hubspot"){for(let[o,c]of[["contacts","contacts"],["deals","deals"]])if(Array.isArray(n[o])){r.push(c);for(let d of n[o])N(d)&&a(me({object:c,internalName:d.name,label:d.label,type:d.type,writable:d.archived!==!0&&d.providerDefined!==!0}))}}else if(e==="salesforce"){if(Array.isArray(n.objects))for(let o of n.objects){if(!N(o))continue;let c=R(o.object,100);if(!c)continue;r.push(c);let d=N(o.permissions)?o.permissions:{};if(Array.isArray(o.fields))for(let _ of o.fields)N(_)&&a(me({object:c,internalName:_.name,label:_.label,type:_.type,writable:d.update===!0&&_.updateable===!0,required:_.required===!0}))}}else if(e==="highlevel"){if(Array.isArray(n.customFields)){for(let o of n.customFields)if(N(o)){let c=o.model==="opportunity"?"opportunities":"contacts";r.push(c),a(me({object:c,internalName:o.fieldKey??o.id,label:o.name,type:o.dataType,writable:!0}))}}}else if(e==="zoho"){let o=Array.isArray(n.moduleResults)?n.moduleResults:[n];for(let c of o){if(!N(c))continue;let d=R(c.module,100);if(d&&(r.push(d),Array.isArray(c.fields)))for(let _ of c.fields)N(_)&&a(me({object:d,internalName:_.apiName,label:_.label,type:_.dataType,writable:_.writable===!0,required:_.required===!0}))}}else if(e==="pipedrive"){if(Array.isArray(n.fields)){for(let c of n.fields)if(N(c)){let d=c.objectType==="deal"?"deals":"persons";r.push(d),a(me({object:d,internalName:c.code,label:c.name,type:c.fieldType,writable:c.writable===!0}))}}let o=Array.isArray(n.stages)?n.stages:[];s=Rt(Array.isArray(n.pipelines)?n.pipelines.map(c=>N(c)?{...c,id:String(c.id??""),stages:o.filter(d=>N(d)&&String(d.pipelineId)===String(c.id)).map(d=>({...d,id:String(d.id??"")}))}:c):[])}else if(e==="keap"){if(r.push("contacts"),Array.isArray(n.contactFields))for(let c of n.contactFields)N(c)&&a(me({object:"contacts",internalName:c.fieldName??c.id,label:c.label,type:c.fieldType,writable:!0}));let o=Array.isArray(n.opportunityStages)?n.opportunityStages:[];o.length&&(s=[{id:"opportunities",name:"Opportunities",stages:Rt([{id:"opportunities",name:"Opportunities",stages:o}])[0]?.stages??[]}])}return{fields:i,objects:[...new Set(r)],pipelines:s,...Array.isArray(n.allowedOperations)?{allowedOperations:n.allowedOperations.filter(o=>typeof o=="string")}:{}}}function Ir(e){return!N(e)||!Array.isArray(e.fields)?[]:e.fields.flatMap(t=>{if(!N(t))return[];let n=R(t.object,100),i=R(t.internalName??t.internal_name,160);if(!n||!i)return[];let r=R(t.id??t.providerFieldId,240);return[{object:n,internalName:i,...r?{providerFieldId:r}:{}}]})}function et(e){let t=te(e);if(t==="callrail"||t==="twilio"||t==="ctm")throw new Error("analytics_crm_provider_required");return t}function Va(e){let t=et(e.provider),n=_e(t,"discover_schema");if(!n.personObject||!e.connectionId.trim())throw new Error("analytics_crm_provisioning_invalid_scope");let i={},r=[];for(let d of Mn){let _=e.fields.find(u=>u.object===n.personObject&&(u.internalName.toLowerCase()===d.internalName||u.label.toLowerCase()===d.label.toLowerCase()));_?_.writable&&(i[d.internalName]=_.internalName):r.push({...d,object:n.personObject})}let s=e.now??new Date().toISOString(),a=Er(e.fields),o={provider:t,connectionId:e.connectionId,existingMappings:i,proposedFields:r,schemaFingerprint:a},c=wt(o);return{planId:ne("crmplan",o),provider:t,connectionId:e.connectionId,personObject:n.personObject,existingMappings:i,proposedFields:r,fallback:n.safeFallback==="activity"?"activity":"note",permissionRequirements:["schema:read",...r.length?["schema:write"]:[],"records:write"],schemaFingerprint:a,requestFingerprint:c,createdAt:s}}async function Ka(e){let t=_e(e.plan.provider,"create_fields"),n=ne("crmplan",{provider:e.plan.provider,connectionId:e.plan.connectionId,existingMappings:e.plan.existingMappings,proposedFields:e.plan.proposedFields,schemaFingerprint:e.plan.schemaFingerprint}),i=wt({provider:e.plan.provider,connectionId:e.plan.connectionId,existingMappings:e.plan.existingMappings,proposedFields:e.plan.proposedFields,schemaFingerprint:e.plan.schemaFingerprint});if(e.plan.planId!==n||e.plan.personObject!==t.personObject||e.plan.requestFingerprint!==i)throw new Error("analytics_crm_provisioning_plan_tampered");let r=new Set(Mn.map(c=>c.internalName));if(e.plan.proposedFields.some(c=>c.object!==t.personObject||!r.has(c.internalName)))throw new Error("analytics_crm_provisioning_plan_tampered");if(!Number.isInteger(e.approvedByUserId)||e.approvedByUserId<=0)throw new Error("analytics_crm_provisioning_approval_required");let s=new Set(e.approvedFieldInternalNames);if([...s].some(c=>!e.plan.proposedFields.some(d=>d.internalName===c)))throw new Error("analytics_crm_provisioning_field_not_in_plan");let a=e.plan.proposedFields.filter(c=>s.has(c.internalName)),o=ne("crmreceipt",{planId:e.plan.planId,fields:[...s].sort()});try{let c=a.length?await e.dependencies.callAction({connectionId:e.plan.connectionId,action:$.createFields,payload:{provider:e.plan.provider,fields:a},idempotencyKey:o}):{fields:[]};return{receiptId:o,planId:e.plan.planId,provider:e.plan.provider,connectionId:e.plan.connectionId,status:"approved",createdFields:Ir(c),existingMappings:e.plan.existingMappings,cleanup:{supported:!1,instructions:"Created empty X-Ray fields may be removed manually after confirming they are not populated."},planFingerprint:e.plan.requestFingerprint,occurredAt:e.now??new Date().toISOString()}}catch(c){return{receiptId:o,planId:e.plan.planId,provider:e.plan.provider,connectionId:e.plan.connectionId,status:"failed",createdFields:[],existingMappings:e.plan.existingMappings,cleanup:{supported:!1,instructions:"No cleanup was attempted."},planFingerprint:e.plan.requestFingerprint,occurredAt:e.now??new Date().toISOString(),errorCode:R(c instanceof Error?c.message:c,80)?.replace(/[^a-zA-Z0-9_:-]/g,"_")||"analytics_crm_provisioning_failed"}}}async function Ja(e){if(e.receipt.status!=="approved")throw new Error("analytics_crm_provisioning_not_approved");_e(e.receipt.provider,"test_write");let t=ne("crmtest",e.receipt.receiptId),n=await e.dependencies.callAction({connectionId:e.receipt.connectionId,action:$.testWrite,payload:{provider:e.receipt.provider,marker:"X-Ray reversible connection test",cleanupRequested:!0},idempotencyKey:t});if(!N(n)||n.ok!==!0)throw new Error("analytics_crm_test_write_not_verified");return{...e.receipt,status:"tested",occurredAt:e.now??new Date().toISOString()}}async function Un(e){let t=et(e.provider);if(_e(t,"upsert_person"),e.person.identityTier!=="confirmed"||!e.person.deterministicIdentity.value.trim())throw new Error("analytics_crm_person_requires_confirmed_identity");let n=ne("crmperson",{provider:t,connectionId:e.connectionId,personId:e.person.personId,identity:e.person.deterministicIdentity,consent:e.person.consentReceiptRef}),i={provider:t,identity:e.person.deterministicIdentity,contact:e.person.contact,journey:{personId:e.person.personId,firstTouch:e.person.firstTouch,lastNonDirectTouch:e.person.lastNonDirectTouch,convertingTouch:e.person.convertingTouch,landingPage:e.person.landingPage,conversionPage:e.person.conversionPage,sessionCount:e.person.sessionCount,eventCount:e.person.eventCount,campaignClickCoverage:e.person.campaignClickCoverage,consentReceiptRef:e.person.consentReceiptRef,detailedJourneyUrl:e.person.detailedJourneyUrl},mapping:e.mapping??{},createDeal:!1},r=await e.dependencies.callAction({connectionId:e.connectionId,action:$.upsertPerson,payload:i,idempotencyKey:n}),s=N(r)?R(r.recordRef??r.id,240):void 0;return{receiptId:n,provider:t,operation:"person_upsert",dealCreated:!1,...s?{providerRecordRef:s}:{}}}async function Fn(e){let t=et(e.provider);if(_e(t,"pipeline_write"),e.person.identityTier!=="confirmed")throw new Error("analytics_crm_pipeline_requires_confirmed_identity");if(e.event.eventName!==e.mapping.eventName)throw new Error("analytics_crm_pipeline_event_not_mapped");if(e.mapping.valueSource==="verified_revenue"&&(!Number.isSafeInteger(e.event.verifiedRevenueMinor)||e.event.verifiedRevenueMinor<0))throw new Error("analytics_crm_pipeline_verified_revenue_required");let n=ne("crmpipeline",{provider:t,connectionId:e.connectionId,eventId:e.event.eventId,mappingVersion:e.mapping.version});return await e.dependencies.callAction({connectionId:e.connectionId,action:$.pipelineEvent,payload:{provider:t,command:"apply_pipeline_event",person:{personId:e.person.personId,identity:e.person.deterministicIdentity},event:e.event,mapping:e.mapping},idempotencyKey:n}),{receiptId:n,provider:t,operation:"pipeline_event",dealCreatedOrUpdated:!0}}async function za(e){let t=et(e.provider),n=Ze(t),i=t==="highlevel"?{locationId:e.discoveryContext?.locationId}:t==="zoho"?{module:e.discoveryContext?.zohoModules?.[0]??"Contacts"}:{};if(t==="highlevel"&&!R(i.locationId,128))throw new Error("analytics_crm_highlevel_location_required");let r=(y,E)=>e.dependencies.callAction({connectionId:e.connectionId,action:$.discoverSchema,payload:y,idempotencyKey:ne("crmdiscover",{provider:t,connectionId:e.connectionId,actionPayload:y,suffix:E})}),s=await r(i);if(t==="zoho"){let y=[...new Set(e.discoveryContext?.zohoModules??["Contacts","Deals"])],E=[s];for(let b of y.slice(1))E.push(await r({module:b},b));s={moduleResults:E}}let a=Ar(t,s),o=a.fields,c=Object.entries(n.operations).filter(([,y])=>y).map(([y])=>y),d=a.allowedOperations?new Set(a.allowedOperations.map(y=>R(y,80)).filter(y=>!!y)):null,_=d?c.filter(y=>d.has(y)):c,u=new Set(n.supportedObjects);return{provider:t,publicProfile:n,connectionId:e.connectionId,fields:o,objects:a.objects.length?a.objects.filter(y=>u.has(y)):n.supportedObjects,pipelines:a.pipelines,allowedOperations:_,discoveredAt:e.now??new Date().toISOString()}}var hr=25,Nr=25e3,jn=H.object({person:_t,event:mt.nullable(),mapping:H.object({version:H.number().int().positive(),eventName:H.string(),pipelineId:H.string(),stageId:H.string(),operation:H.enum(["create_or_update_deal","update_stage"]),valueSource:H.enum(["none","verified_revenue"]),activationEligible:H.boolean()}).strict().nullable()}).strict();function Cr(e,t){return`${e}_${Sr("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function tt(e){return cn(e)??void 0}function Rr(e,t,n){return e.purpose==="necessary_form_fulfillment"?t.eventKind==="form":e.purpose==="site_analytics"?n.siteAnalytics:n.advertisingMeasurement}function k(e,t){return e.has(t)}function wr(e){let t=new Set(e.policy.allowedFields),n=e.contact?{...k(t,"contact.email")&&e.contact.email?{email:e.contact.email}:{},...k(t,"contact.phone")&&e.contact.phone?{phone:e.contact.phone}:{},...k(t,"contact.firstName")&&e.contact.firstName?{firstName:e.contact.firstName}:{},...k(t,"contact.lastName")&&e.contact.lastName?{lastName:e.contact.lastName}:{}}:void 0,i=[e.event.sourceName??e.event.source,e.event.medium,e.event.campaign].filter(Boolean).map(a=>String(a).slice(0,240)).join(" / "),r=e.policy.purpose==="advertising_measurement"&&e.consent.advertisingMeasurement?G(e.event.clickIds):{},s=Object.entries(r).filter(([a])=>k(t,`clickIds.${a}`)).map(([a])=>a).sort().join(",");return _t.parse({identityTier:"confirmed",personId:e.personId,deterministicIdentity:{kind:"crm_id",value:e.crmPersonRef},...n&&Object.keys(n).length?{contact:n}:{},...k(t,"attribution.firstTouch")&&i?{firstTouch:i}:{},...k(t,"attribution.lastNonDirectTouch")&&i?{lastNonDirectTouch:i}:{},...k(t,"attribution.convertingTouch")&&i?{convertingTouch:i}:{},...k(t,"attribution.landingPage")&&tt(e.event.canonicalUrl)?{landingPage:tt(e.event.canonicalUrl)}:{},...k(t,"attribution.conversionPage")&&tt(e.event.canonicalUrl)?{conversionPage:tt(e.event.canonicalUrl)}:{},sessionCount:e.sessionCount,eventCount:e.eventCount,...s?{campaignClickCoverage:s}:{},consentReceiptRef:e.consent.receiptId??`purpose:${e.policy.purpose}`,detailedJourneyUrl:`https://mcpscraper.dev/dashboard/analytics/people/${encodeURIComponent(e.personId)}`})}async function qn(e){let t=(await Dn({siteId:e.siteId,db:e.db})).filter(s=>s.enabled&&Rr(s,e.event,e.consent)).filter(s=>s.selectedEvents.length===0||s.selectedEvents.includes(e.event.eventName));if(!t.length)return{queued:0,reused:0};let n=await e.db.query(`SELECT p.crm_person_ref,
229
283
  (SELECT count(DISTINCT s.id)::text FROM analytics_sessions s WHERE s.site_id=p.site_id AND s.person_id=p.id) session_count,
230
284
  ((SELECT count(*) FROM analytics_events e WHERE e.site_id=p.site_id AND e.person_id=p.id)+
231
285
  (SELECT count(*) FROM analytics_external_events x WHERE x.site_id=p.site_id AND x.person_id=p.id))::text event_count
232
- FROM analytics_people p WHERE p.site_id=$1 AND p.id=$2`,[e.siteId,e.personId]);if(!n.rows[0])return{queued:0,reused:0};let i=0,r=0;for(let s of t){if(s.kind==="pipeline_event"&&(!s.mapping||s.mapping.eventName!==e.event.eventName))continue;let a=dr({personId:e.personId,crmPersonRef:n.rows[0].crm_person_ref,event:e.event,policy:s,consent:e.consent,sessionCount:Number(n.rows[0].session_count),eventCount:Number(n.rows[0].event_count)}),o=s.kind==="pipeline_event"?mt.parse({eventId:e.canonicalEventId,eventName:e.event.eventName,occurredAt:e.event.occurredAt,...s.mapping?.valueSource==="verified_revenue"&&e.event.valueMinor!==void 0?{verifiedRevenueMinor:e.event.valueMinor,currency:e.event.currency?.toUpperCase()}:{}}):null;if(s.kind==="pipeline_event"&&s.mapping?.valueSource==="verified_revenue"&&o?.verifiedRevenueMinor===void 0)continue;let c=wn.parse({person:a,event:o,mapping:s.mapping}),d=`${s.policyId}:${s.version}:${e.canonicalEventId}`,_=Ke({policy:s,personId:e.personId,event:o,projection:a});(await En({jobId:or("crmjob",{idempotencyKey:d}),policy:s,personId:e.personId,sourceEventId:e.canonicalEventId,payloadCiphertext:de(JSON.stringify(c),"crm-outbound-payload"),idempotencyKey:d,requestFingerprint:_,db:e.db})).reused?r+=1:i+=1}return{queued:i,reused:r}}var Ge={async resolveIdentity(e){return(await Ht(e))?.email??null},async callAction(e){return tn({identity:e.identity,connectionId:e.connectionId,tool:e.action,input:e.payload,classification:"action",operationKind:"sync",requestId:e.idempotencyKey})},authorizeSend:e=>An(e),cancelUnauthorized:e=>In(e)};function lr(e){let t=e instanceof Error?e.message:String(e);return/schema_changed|mapping_version|not_mapped|verified_revenue|required|disabled/i.test(t)?{code:"crm_outbound_contract_invalid",retryable:!1,rateLimited:!1}:/429|rate.?limit|too many/i.test(t)?{code:"crm_outbound_rate_limited",retryable:!0,rateLimited:!0}:/401|403|scope|permission|unauthorized|forbidden/i.test(t)?{code:"crm_outbound_authorization_required",retryable:!1,rateLimited:!1}:{code:"crm_outbound_provider_unavailable",retryable:!0,rateLimited:!1}}async function Pa(e=10,t=Date.now()+ar,n=Ge){let i=Math.max(1,Math.min(sr,e)),r=v();await r.query(`INSERT INTO analytics_crm_outbound_worker_state(worker_key,last_started_at,last_error_code,updated_at)
233
- VALUES('default',now(),NULL,now()) ON CONFLICT(worker_key) DO UPDATE SET last_started_at=now(),last_error_code=NULL,updated_at=now()`);try{let s=await bn({limit:i,leaseSeconds:90}),a=0,o=0,c=0;for(let u of s){if(Date.now()>=t){await Je({jobId:u.job.jobId,status:"retrying",safeErrorCode:"crm_outbound_tick_deadline",retryAt:new Date(Date.now()+6e4).toISOString()}),o+=1;continue}try{if(!u.schemaCurrent)throw new Error("analytics_crm_schema_changed");let y=Ne(u.payloadCiphertext,"crm-outbound-payload");if(!y)throw new Error("crm_outbound_payload_unreadable");let E=wn.parse(JSON.parse(y)),b=await n.resolveIdentity(u.ownerUserId);if(!b)throw new Error("crm_outbound_owner_identity_unavailable");if(!await(n.authorizeSend??(n===Ge?Ge.authorizeSend:async()=>!0))({jobId:u.job.jobId,attempt:u.job.attempts,purpose:u.purpose,consentReceiptRef:E.person.consentReceiptRef})){await(n.cancelUnauthorized??Ge.cancelUnauthorized)({jobId:u.job.jobId,attempt:u.job.attempts,safeErrorCode:"crm_outbound_privacy_fence_closed"}),c+=1;continue}let h={callAction:({connectionId:m,action:K,payload:w,idempotencyKey:A})=>n.callAction({identity:b,connectionId:m,action:K,payload:w,idempotencyKey:A})},L=u.job.kind==="person_summary"?await Cn({provider:u.provider,connectionId:u.connectionId,person:E.person,dependencies:h}):await Rn({provider:u.provider,connectionId:u.connectionId,person:E.person,event:E.event,mapping:E.mapping,dependencies:h});await Je({jobId:u.job.jobId,status:"accepted",externalReceiptId:L.receiptId}),a+=1}catch(y){let E=lr(y),b=new Date(Date.now()+(E.rateLimited?30*6e4:Math.min(360*6e4,3e4*2**u.job.attempts))).toISOString();await Je({jobId:u.job.jobId,status:E.retryable?"retrying":"failed",safeErrorCode:E.code,...E.retryable?{retryAt:b}:{}}),E.retryable&&u.job.attempts<5?o+=1:c+=1}}let d=await r.query("SELECT count(*)::int due FROM analytics_crm_outbound_jobs WHERE state IN ('pending','retrying') AND next_attempt_at <= now()"),_={claimed:s.length,delivered:a,retried:o,deadLettered:c,remainingDue:Number(d.rows[0]?.due??0)};return await r.query(`UPDATE analytics_crm_outbound_worker_state SET last_completed_at=now(),last_success_at=now(),
286
+ FROM analytics_people p WHERE p.site_id=$1 AND p.id=$2`,[e.siteId,e.personId]);if(!n.rows[0])return{queued:0,reused:0};let i=0,r=0;for(let s of t){if(s.kind==="pipeline_event"&&(!s.mapping||s.mapping.eventName!==e.event.eventName))continue;let a=wr({personId:e.personId,crmPersonRef:n.rows[0].crm_person_ref,event:e.event,policy:s,consent:e.consent,sessionCount:Number(n.rows[0].session_count),eventCount:Number(n.rows[0].event_count)}),o=s.kind==="pipeline_event"?mt.parse({eventId:e.canonicalEventId,eventName:e.event.eventName,occurredAt:e.event.occurredAt,...s.mapping?.valueSource==="verified_revenue"&&e.event.valueMinor!==void 0?{verifiedRevenueMinor:e.event.valueMinor,currency:e.event.currency?.toUpperCase()}:{}}):null;if(s.kind==="pipeline_event"&&s.mapping?.valueSource==="verified_revenue"&&o?.verifiedRevenueMinor===void 0)continue;let c=jn.parse({person:a,event:o,mapping:s.mapping}),d=`${s.policyId}:${s.version}:${e.canonicalEventId}`,_=Ge({policy:s,personId:e.personId,event:o,projection:a});(await Tn({jobId:Cr("crmjob",{idempotencyKey:d}),policy:s,personId:e.personId,sourceEventId:e.canonicalEventId,payloadCiphertext:de(JSON.stringify(c),"crm-outbound-payload"),idempotencyKey:d,requestFingerprint:_,db:e.db})).reused?r+=1:i+=1}return{queued:i,reused:r}}var nt={async resolveIdentity(e){return(await Ht(e))?.email??null},async callAction(e){return tn({identity:e.identity,connectionId:e.connectionId,tool:e.action,input:e.payload,classification:"action",operationKind:"sync",requestId:e.idempotencyKey})},authorizeSend:e=>Ln(e),cancelUnauthorized:e=>$n(e)};function Or(e){let t=e instanceof Error?e.message:String(e);return/schema_changed|mapping_version|not_mapped|verified_revenue|required|disabled/i.test(t)?{code:"crm_outbound_contract_invalid",retryable:!1,rateLimited:!1}:/429|rate.?limit|too many/i.test(t)?{code:"crm_outbound_rate_limited",retryable:!0,rateLimited:!0}:/401|403|scope|permission|unauthorized|forbidden/i.test(t)?{code:"crm_outbound_authorization_required",retryable:!1,rateLimited:!1}:{code:"crm_outbound_provider_unavailable",retryable:!0,rateLimited:!1}}async function so(e=10,t=Date.now()+Nr,n=nt){let i=Math.max(1,Math.min(hr,e)),r=v();await r.query(`INSERT INTO analytics_crm_outbound_worker_state(worker_key,last_started_at,last_error_code,updated_at)
287
+ VALUES('default',now(),NULL,now()) ON CONFLICT(worker_key) DO UPDATE SET last_started_at=now(),last_error_code=NULL,updated_at=now()`);try{let s=await xn({limit:i,leaseSeconds:90}),a=0,o=0,c=0;for(let u of s){if(Date.now()>=t){await Qe({jobId:u.job.jobId,status:"retrying",safeErrorCode:"crm_outbound_tick_deadline",retryAt:new Date(Date.now()+6e4).toISOString()}),o+=1;continue}try{if(!u.schemaCurrent)throw new Error("analytics_crm_schema_changed");let y=Ne(u.payloadCiphertext,"crm-outbound-payload");if(!y)throw new Error("crm_outbound_payload_unreadable");let E=jn.parse(JSON.parse(y)),b=await n.resolveIdentity(u.ownerUserId);if(!b)throw new Error("crm_outbound_owner_identity_unavailable");if(!await(n.authorizeSend??(n===nt?nt.authorizeSend:async()=>!0))({jobId:u.job.jobId,attempt:u.job.attempts,purpose:u.purpose,consentReceiptRef:E.person.consentReceiptRef})){await(n.cancelUnauthorized??nt.cancelUnauthorized)({jobId:u.job.jobId,attempt:u.job.attempts,safeErrorCode:"crm_outbound_privacy_fence_closed"}),c+=1;continue}let h={callAction:({connectionId:m,action:K,payload:w,idempotencyKey:A})=>n.callAction({identity:b,connectionId:m,action:K,payload:w,idempotencyKey:A})},L=u.job.kind==="person_summary"?await Un({provider:u.provider,connectionId:u.connectionId,person:E.person,dependencies:h}):await Fn({provider:u.provider,connectionId:u.connectionId,person:E.person,event:E.event,mapping:E.mapping,dependencies:h});await Qe({jobId:u.job.jobId,status:"accepted",externalReceiptId:L.receiptId}),a+=1}catch(y){let E=Or(y),b=new Date(Date.now()+(E.rateLimited?30*6e4:Math.min(360*6e4,3e4*2**u.job.attempts))).toISOString();await Qe({jobId:u.job.jobId,status:E.retryable?"retrying":"failed",safeErrorCode:E.code,...E.retryable?{retryAt:b}:{}}),E.retryable&&u.job.attempts<5?o+=1:c+=1}}let d=await r.query("SELECT count(*)::int due FROM analytics_crm_outbound_jobs WHERE state IN ('pending','retrying') AND next_attempt_at <= now()"),_={claimed:s.length,delivered:a,retried:o,deadLettered:c,remainingDue:Number(d.rows[0]?.due??0)};return await r.query(`UPDATE analytics_crm_outbound_worker_state SET last_completed_at=now(),last_success_at=now(),
234
288
  last_error_code=NULL,last_claimed=$1,last_remaining_due=$2,updated_at=now() WHERE worker_key='default'`,[_.claimed,_.remainingDue]),_}catch(s){throw await r.query(`UPDATE analytics_crm_outbound_worker_state SET last_completed_at=now(),last_error_code='crm_outbound_worker_failed',updated_at=now()
235
- WHERE worker_key='default'`).catch(()=>{}),s}}function Dn(e,t){return e&&(t??0)>0}import{createHash as ko,createHmac as kt,generateKeyPairSync as Qr,randomUUID as se,sign as Zr}from"crypto";import es from"twilio";import{z as l}from"zod";import{z as R}from"zod";var ur=new Set(["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLE","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UYW","UZS","VED","VES","VND","VUV","WST","XAF","XAG","XAU","XBA","XBB","XBC","XBD","XCD","XDR","XOF","XPD","XPF","XPT","XSU","XTS","XUA","XXX","YER","ZAR","ZMW","ZWG"]),we=R.string().trim().length(3).transform(e=>e.toUpperCase()).refine(e=>ur.has(e),"Provide a valid ISO-4217 currency."),Qe=R.number().int("Money must be represented as integer minor units.").min(0,"Money cannot be negative.").max(Number.MAX_SAFE_INTEGER),Ze=R.string().trim().min(1).max(80).default("1"),_r=R.enum(["semantic_markup","source_event","crm_field","transaction"]),mr=R.object({mode:R.literal("none"),ruleVersion:Ze}).strict(),pr=R.object({mode:R.literal("fixed"),valueMinor:Qe,currency:we,ruleVersion:Ze}).strict(),yr=R.object({mode:R.literal("dynamic"),source:_r,currency:we,fallbackValueMinor:Qe.nullable().default(null),ruleVersion:Ze}).strict(),Tn=R.discriminatedUnion("mode",[mr,pr,yr]),gr=R.object({linkedEventName:R.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),relation:R.enum(["before","after","either"]),intervalSeconds:R.number().int().min(0).max(10*365*24*60*60).nullable(),overrideValueMinor:Qe,currency:we}).strict(),et=R.object({targetEventName:R.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),base:Tn,conditionalOverride:gr.nullable().default(null),ruleVersion:Ze}).strict().superRefine((e,t)=>{let n=e.conditionalOverride;n&&e.base.mode!=="none"&&n.currency!==e.base.currency&&t.addIssue({code:"custom",path:["conditionalOverride","currency"],message:"Conditional override currency must match the base value currency."})});function ne(e,t){let n=Date.parse(e);if(!Number.isFinite(n))throw new Error(`${t} must be an ISO timestamp.`);return n}function fr(e,t){let n=Qe.parse(e.valueMinor),i=xn(t,e.currency);return ne(e.observedAt,"observedAt"),{valueMinor:n,currency:i,observedAt:new Date(e.observedAt).toISOString()}}function vr(e){return Tn.parse(e)}function xn(e,t){let i=(Array.isArray(e)?e:[e,t]).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>we.parse(r));if(i.length===0)throw new Error("A currency is required for a monetary value.");if(new Set(i).size!==1)throw new Error(`Mixed currencies are not compatible: ${[...new Set(i)].join(", ")}.`);return i[0]}function Er(e,t={}){let n=vr(e);if(n.mode==="none")return{valueMinor:null,currency:null,provenance:{mode:"none",source:null,observedAt:null,fallback:!1,ruleVersion:n.ruleVersion,resolution:"absent",baseValueMinor:null,resolvedValueMinor:null,currency:null,linkedEvent:null}};if(n.mode==="fixed"){let s=t.observedAt?new Date(ne(t.observedAt,"observedAt")).toISOString():null;return{valueMinor:n.valueMinor,currency:n.currency,provenance:{mode:"fixed",source:null,observedAt:s,fallback:!1,ruleVersion:n.ruleVersion,resolution:"fixed",baseValueMinor:n.valueMinor,resolvedValueMinor:n.valueMinor,currency:n.currency,linkedEvent:null}}}let i=t.observations?.[n.source];if(i){let s=fr(i,n.currency);return{valueMinor:s.valueMinor,currency:s.currency,provenance:{mode:"dynamic",source:n.source,observedAt:s.observedAt,fallback:!1,ruleVersion:n.ruleVersion,resolution:"dynamic",baseValueMinor:s.valueMinor,resolvedValueMinor:s.valueMinor,currency:s.currency,linkedEvent:null}}}let r=n.fallbackValueMinor;return{valueMinor:r,currency:r===null?null:n.currency,provenance:{mode:"dynamic",source:n.source,observedAt:null,fallback:r!==null,ruleVersion:n.ruleVersion,resolution:r===null?"absent":"fallback",baseValueMinor:r,resolvedValueMinor:r,currency:r===null?null:n.currency,linkedEvent:null}}}function br(e,t,n){let i=ne(t.occurredAt,"targetEvent.occurredAt"),r=n.filter(s=>{if(s.eventName!==e.linkedEventName)return!1;let o=(ne(s.occurredAt,"linkedEvent.occurredAt")-i)/1e3;return e.relation==="before"&&o>0||e.relation==="after"&&o<0?!1:e.intervalSeconds===null||Math.abs(o)<=e.intervalSeconds});return r.sort((s,a)=>{let o=Math.abs(ne(s.occurredAt,"linkedEvent.occurredAt")-i),c=Math.abs(ne(a.occurredAt,"linkedEvent.occurredAt")-i);return o-c||s.eventId.localeCompare(a.eventId)}),r[0]??null}function Ln(e,t){let n=et.parse(e);if(t.targetEvent.eventName!==n.targetEventName)throw new Error(`Value rule targets ${n.targetEventName}, not ${t.targetEvent.eventName}.`);let i=Er({...n.base,ruleVersion:n.ruleVersion},t);if(!n.conditionalOverride)return i;let r=br(n.conditionalOverride,t.targetEvent,t.linkedEvents);if(!r)return i;if(t.providerOperation==="restatement"&&r.identityTier!=="confirmed")throw new Error("Candidate-only evidence cannot be used for a provider restatement.");let s=i.currency?xn(i.currency,n.conditionalOverride.currency):we.parse(n.conditionalOverride.currency);return{valueMinor:n.conditionalOverride.overrideValueMinor,currency:s,provenance:{...i.provenance,ruleVersion:n.ruleVersion,resolution:"conditional_override",resolvedValueMinor:n.conditionalOverride.overrideValueMinor,currency:s,linkedEvent:{eventId:r.eventId,eventName:r.eventName,occurredAt:new Date(ne(r.occurredAt,"linkedEvent.occurredAt")).toISOString(),identityTier:r.identityTier??"candidate"}}}}var $n=l.object({gclid:l.string().trim().max(500).optional(),gbraid:l.string().trim().max(500).optional(),wbraid:l.string().trim().max(500).optional(),fbclid:l.string().trim().max(500).optional(),fbp:l.string().trim().max(500).optional(),fbc:l.string().trim().max(500).optional(),ttclid:l.string().trim().max(500).optional(),rdt_cid:l.string().trim().max(500).optional(),msclkid:l.string().trim().max(500).optional(),li_fat_id:l.string().trim().max(500).optional(),snapclid:l.string().trim().max(500).optional()}).strict(),Ar=l.object({site_analytics:l.enum(["granted","denied","unknown"]),enhanced_matching:l.enum(["granted","denied","unknown"]),advertising_measurement:l.enum(["granted","denied","unknown"])}).strict(),Ir=l.object({analytics:l.enum(["granted","denied","unknown"]).default("unknown"),adUserData:l.enum(["granted","denied","unknown"]).default("unknown"),adPersonalization:l.enum(["granted","denied","unknown"]).default("unknown"),globalPrivacyControl:l.boolean().default(!1),occurredAt:l.string().datetime(),receiptId:l.string().uuid().optional(),policyVersion:l.number().int().positive().optional(),purposes:Ar.optional()}).strict().transform(e=>({...e,purposes:e.purposes??{site_analytics:e.analytics,enhanced_matching:e.adUserData,advertising_measurement:e.adPersonalization}})),kn=l.enum(["browser","form","call","crm","transaction","custom_server","conversion","delivery"]),Sr=l.object({schemaVersion:l.literal(1).default(1),eventId:l.string().trim().min(8).max(200),sourceEventId:l.string().trim().min(1).max(300).optional(),source:l.string().trim().min(1).max(80).default("xray"),sourceAccountRef:l.string().trim().max(240).optional(),eventKind:kn,eventName:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),occurredAt:l.string().datetime(),visitorId:l.string().trim().max(160).optional(),sessionId:l.string().trim().max(160).optional(),personRef:l.string().trim().max(240).optional(),orderId:l.string().trim().max(240).optional(),callId:l.string().trim().max(240).optional(),dealId:l.string().trim().max(240).optional(),path:l.string().trim().max(2e3).optional(),canonicalUrl:l.string().url().max(3e3).optional(),sourceName:l.string().trim().max(180).optional(),medium:l.string().trim().max(180).optional(),campaign:l.string().trim().max(240).optional(),clickIds:$n.optional(),consent:Ir.optional(),valueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).optional(),properties:l.record(l.string().max(80),l.unknown()).default({})}).strict(),tt=Sr.extend({sourceEventId:l.string().trim().min(1).max(300),source:l.string().trim().min(1).max(80),sourceAccountRef:l.string().trim().min(1).max(240)}),Wa=l.object({sourceEventId:l.string().trim().min(1).max(300),source:l.string().trim().min(1).max(80),sourceAccountRef:l.string().trim().min(1).max(240),contactId:l.string().trim().max(240).optional(),dealId:l.string().trim().min(1).max(240),pipelineId:l.string().trim().max(240).optional(),stageId:l.string().trim().min(1).max(240),stageName:l.string().trim().max(240).optional(),occurredAt:l.string().datetime(),valueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).optional(),visitorId:l.string().trim().max(160).optional(),sessionId:l.string().trim().max(160).optional(),clickIds:$n.optional(),email:l.string().email().max(320).optional(),phone:l.string().trim().max(80).optional(),orderId:l.string().trim().max(240).optional(),status:l.enum(["open","won","lost","spam","unknown"]).default("unknown")}).strict(),hr=l.object({eventName:l.string().regex(/^[a-z][a-z0-9_]{1,79}$/).optional(),eventKind:kn.optional(),source:l.string().trim().max(80).optional(),stageId:l.string().trim().max(240).optional(),status:l.enum(["open","won","lost","spam","unknown"]).optional(),answered:l.boolean().optional(),minimumCallDurationSeconds:l.number().int().min(0).max(86400).optional(),excludedTags:l.array(l.string().trim().max(80)).max(30).default([]),requiredTags:l.array(l.string().trim().max(80)).max(30).default([])}).strict(),Pn=l.object({name:l.string().trim().min(1).max(120),conversionKind:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),condition:hr,defaultValueMinor:l.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),defaultCurrency:l.string().trim().regex(/^[A-Za-z]{3}$/).default("USD"),valueRule:et.optional(),enabled:l.boolean().default(!0)}).strict();function Nr(e){let t=e.trim().toLowerCase().replace(/\.$/,"");if(!t||t.includes("://")||/[/?#]/.test(t))return"";try{let n=new URL(`https://${t}`).hostname.toLowerCase().replace(/\.$/,"");return!n||n.length>253||n!=="localhost"&&!n.includes(".")||n.split(".").some(i=>!i||i.length>63||!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(i))?"":n}catch{return""}}var Cr=l.string().trim().max(253).transform(Nr).refine(Boolean,"Provide a valid bare hostname."),Oe=l.string().trim().max(80).regex(/^[A-Za-z][A-Za-z0-9_-]{0,79}$/).refine(e=>(e.match(/\d/g)?.length??0)<7,"Semantic dimensions cannot contain phone-like values.").transform(e=>e.toLowerCase()),Rr=l.object({value:l.number().finite().min(0).max(1e12).optional(),currency:l.string().trim().regex(/^[A-Za-z]{3}$/).transform(e=>e.toUpperCase()).optional(),orderId:l.string().trim().min(1).max(200).optional(),contentId:l.string().trim().min(1).max(200).optional(),contentType:l.string().trim().min(1).max(80).optional(),placement:Oe.optional(),component:Oe.optional(),action:Oe.optional(),destination:Oe.optional(),plan:Oe.optional()}).strict(),Ct=l.object({name:l.string().trim().min(1).max(120),eventName:l.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),triggerKind:l.enum(["page","click","form","semantic"]),path:l.string().trim().startsWith("/").max(2e3).optional(),pathMatch:l.enum(["exact","prefix"]).default("exact"),selector:l.string().trim().min(1).max(500).optional(),hostnames:l.array(Cr).max(25).transform(e=>[...new Set(e)]).default([]),metadata:Rr.optional(),valueRule:et.optional(),oncePerSession:l.boolean().default(!1),enabled:l.boolean().default(!0)}).strict().superRefine((e,t)=>{e.triggerKind==="page"&&!e.path&&t.addIssue({code:"custom",path:["path"],message:"Page triggers require a path."}),["click","form"].includes(e.triggerKind)&&!e.selector&&t.addIssue({code:"custom",path:["selector"],message:"Click and form triggers require a selector."}),e.triggerKind==="semantic"&&(e.path||e.selector)&&t.addIssue({code:"custom",path:["triggerKind"],message:"Semantic triggers use data-xray-event and cannot include a path or selector."})});import{createHmac as wr,randomUUID as Rt}from"crypto";import eo from"ipaddr.js";import{randomUUID as Mn}from"crypto";async function Ja(e){return(await v().query(`SELECT id, site_id, name, status, version, approved_at
236
- FROM analytics_identity_namespaces
237
- WHERE site_id=$1 AND status IN ('draft','approved','disabled')
238
- ORDER BY CASE status WHEN 'approved' THEN 0 WHEN 'draft' THEN 1 ELSE 2 END,
239
- version DESC, name, id`,[e.siteId])).rows.map(n=>({id:n.id,siteId:n.site_id,name:n.name,status:n.status,version:n.version,approvedAt:n.approved_at===null?null:new Date(n.approved_at).toISOString()}))}var Un={domain:"host",application:"server",phone:"call",crm:"crm"},Fn={host:"domain",server:"application",call:"phone",crm:"crm"};function jn(e,t){let n=t.trim().toLowerCase();if(!n||n.length>500)throw new f("analytics_namespace_source_invalid","Provide a valid namespace source.",400);if(e==="domain"&&(n.includes("://")||/[/?#]/.test(n)||!n.includes(".")))throw new f("analytics_namespace_domain_invalid","Provide a bare approved domain.",400);return n}async function za(e){let t=e.name.trim();if(!t||t.length>160)throw new f("analytics_namespace_name_invalid","Provide a namespace name.",400);let n=await v().connect();await n.query("BEGIN");try{await n.query("SELECT pg_advisory_xact_lock(hashtext($1))",[e.siteId]);let r=(await n.query(`SELECT id, site_id, name, status, version, approved_at
240
- FROM analytics_identity_namespaces
241
- WHERE site_id=$1 AND status IN ('draft','approved','disabled')
242
- ORDER BY version DESC LIMIT 1`,[e.siteId])).rows[0];if(r){if(r.name!==t)throw new f("analytics_namespace_already_exists","This site already belongs to an identity namespace.",409);return await n.query("COMMIT"),{id:r.id,siteId:r.site_id,name:r.name,status:r.status,version:r.version,approvedAt:r.approved_at?.toISOString()??null}}let a=(await n.query(`INSERT INTO analytics_identity_namespaces(
243
- id, site_id, name, status, approved_hosts, approved_sources, version, approved_by_user_id
244
- ) VALUES ($1,$2,$3,'draft','[]'::jsonb,'[]'::jsonb,1,$4)
245
- RETURNING id, site_id, name, status, version, approved_at`,[Mn(),e.siteId,t,e.createdByUserId])).rows[0];return await n.query("COMMIT"),{id:a.id,siteId:a.site_id,name:a.name,status:a.status,version:a.version,approvedAt:a.approved_at?.toISOString()??null}}catch(i){throw await n.query("ROLLBACK"),i}finally{n.release()}}async function Ya(e){let t=jn(e.sourceKind,e.sourceRef),n=await v().connect();await n.query("BEGIN");try{let i=await n.query(`SELECT id, status FROM analytics_identity_namespaces
246
- WHERE id=$1 AND site_id=$2 FOR UPDATE`,[e.namespaceId,e.siteId]);if(!i.rows[0])throw new f("analytics_namespace_not_found","Identity namespace not found.",404);if(["archived","disabled"].includes(i.rows[0].status))throw new f("analytics_namespace_inactive","Identity namespace is not active.",409);let r=Un[e.sourceKind],s=await n.query(`INSERT INTO analytics_identity_sources(id, namespace_id, site_id, source_kind, source_ref, status)
247
- VALUES ($1,$2,$3,$4,$5,'approved')
248
- ON CONFLICT(namespace_id, source_kind, source_ref) DO UPDATE
249
- SET status='approved', revoked_at=NULL
250
- RETURNING id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at`,[Mn(),e.namespaceId,e.siteId,r,t]);await n.query(`UPDATE analytics_identity_namespaces
251
- SET status='approved', approved_by_user_id=$3, approved_at=COALESCE(approved_at, now()),
252
- approved_hosts=CASE WHEN $4='host'
253
- THEN (SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_hosts || to_jsonb($5::text)) value)
254
- ELSE approved_hosts END,
255
- approved_sources=(SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_sources || to_jsonb(($4 || ':' || $5)::text)) value),
256
- updated_at=now()
257
- WHERE id=$1 AND site_id=$2`,[e.namespaceId,e.siteId,e.approvedByUserId,r,t]),await n.query("COMMIT");let a=s.rows[0];return{id:a.id,namespaceId:a.namespace_id,siteId:a.site_id,sourceKind:Fn[a.source_kind],sourceRef:a.source_ref,status:a.status,createdAt:a.created_at instanceof Date?a.created_at.toISOString():new Date(a.created_at).toISOString(),revokedAt:a.revoked_at==null?null:a.revoked_at instanceof Date?a.revoked_at.toISOString():new Date(a.revoked_at).toISOString()}}catch(i){throw await n.query("ROLLBACK"),i}finally{n.release()}}async function nt(e){let t=v();if(!(await t.query(`SELECT id FROM analytics_identity_namespaces
258
- WHERE id=$1 AND site_id=$2 AND status='approved'`,[e.namespaceId,e.siteId])).rows[0])throw new f("analytics_namespace_boundary","The identity namespace is not approved for this site.",403);let i=[...new Set(e.identityNodeIds??[])];if(i.length&&(await t.query(`SELECT id FROM analytics_identity_nodes
259
- WHERE site_id=$1 AND namespace_id=$2 AND id = ANY($3::uuid[])`,[e.siteId,e.namespaceId,i])).rows.length!==i.length)throw new f("analytics_namespace_boundary","Identity evidence cannot cross namespaces.",403);if(e.personId&&!(await t.query("SELECT id FROM analytics_people WHERE id=$1 AND site_id=$2 AND namespace_id=$3",[e.personId,e.siteId,e.namespaceId])).rows[0])throw new f("analytics_namespace_boundary","The person does not belong to this namespace.",403);if(e.source){let r=jn(e.source.kind,e.source.ref);if(!(await t.query(`SELECT id FROM analytics_identity_sources
260
- WHERE namespace_id=$1 AND site_id=$2 AND source_kind=$3 AND source_ref=$4 AND status='approved'`,[e.namespaceId,e.siteId,Un[e.source.kind],r])).rows[0])throw new f("analytics_namespace_source_unapproved","This identity source is not approved.",403)}}async function Xa(e){return await nt(e),(await v().query(`SELECT id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at
261
- FROM analytics_identity_sources
262
- WHERE namespace_id=$1 AND site_id=$2
263
- ORDER BY source_kind, source_ref`,[e.namespaceId,e.siteId])).rows.map(n=>({id:n.id,namespaceId:n.namespace_id,siteId:n.site_id,sourceKind:Fn[n.source_kind],sourceRef:n.source_ref,status:n.status,createdAt:n.created_at.toISOString(),revokedAt:n.revoked_at?.toISOString()??null}))}function Or(){let e=process.env.ANALYTICS_IDENTITY_SECRET?.trim()||process.env.SESSION_SECRET?.trim();if(!e)throw new f("analytics_identity_secret_missing","Candidate identity derivation is not configured.",503);return e}function wt(e,t){return wr("sha256",Or()).update(`xray-candidate:v1:${e}:${t}`).digest("hex")}async function io(e){await nt(e);let t=Math.max(1,Math.min(200,Math.floor(e.limit??50)));return(await v().query(`SELECT a.id, a.model_version, a.first_observed_at, a.last_observed_at, a.expires_at,
264
- array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution > 0), NULL) supporting,
265
- array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution < 0), NULL) conflicting
266
- FROM analytics_candidate_associations a
267
- LEFT JOIN analytics_candidate_evidence e ON e.association_id=a.id AND e.namespace_id=a.namespace_id
268
- WHERE a.site_id=$1 AND a.namespace_id=$2 AND a.status='active' AND a.confidence_band='medium'
269
- AND a.expires_at > $3::timestamptz
270
- GROUP BY a.id
271
- ORDER BY a.updated_at DESC LIMIT $4`,[e.siteId,e.namespaceId,e.now??new Date().toISOString(),t])).rows.map(i=>({associationId:i.id,band:"medium",supportingFeatures:i.supporting??[],conflictingFeatures:i.conflicting??[],modelVersion:i.model_version,firstObservedAt:i.first_observed_at.toISOString(),lastObservedAt:i.last_observed_at.toISOString(),expiresAt:i.expires_at.toISOString()}))}async function qn(e){await nt({siteId:e.siteId,namespaceId:e.namespaceId,personId:e.personId});let t=new Date(e.occurredAt??Date.now());if(!e.evidenceRef.trim())throw new f("analytics_candidate_promotion_evidence_required","Deterministic evidence is required.",400);let n=e.promotedBy??"system";if(n==="user"&&!e.promotedByUserId)throw new f("analytics_candidate_promotion_actor_required","User-confirmed promotion requires an actor.",400);let i=wt("journey_pattern",`${e.evidenceKind}:${e.evidenceRef.trim().toLowerCase()}`),s=await v().connect();await s.query("BEGIN");try{let a=await s.query(`UPDATE analytics_candidate_associations
272
- SET status='promoted', promoted_person_id=$4, promoted_at=$5, updated_at=now()
273
- WHERE id=$1 AND site_id=$2 AND namespace_id=$3
274
- AND (status IN ('active','expired') OR (status='promoted' AND promoted_person_id=$4))
275
- RETURNING id,left_identity_node_id,right_identity_node_id`,[e.associationId,e.siteId,e.namespaceId,e.personId,t.toISOString()]);if(!a.rows[0])throw new f("analytics_candidate_not_found","Candidate association not found in this namespace.",404);return await s.query(`INSERT INTO analytics_candidate_promotions(
276
- id, site_id, namespace_id, association_id, person_id, evidence_kind,
277
- evidence_ref_hmac, promoted_by, promoted_by_user_id, promoted_at
278
- ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
279
- ON CONFLICT(association_id, person_id) DO NOTHING`,[Rt(),e.siteId,e.namespaceId,e.associationId,e.personId,e.evidenceKind,i,n,e.promotedByUserId??null,t.toISOString()]),await s.query(`INSERT INTO analytics_privacy_audits(
280
- id, site_id, namespace_ref, subject_ref, action, idempotency_key,
281
- actor_user_id, result_code, affected_counts, completed_at
282
- ) VALUES ($1,$2,$3,$4,'candidate_promoted',$5,$6,'promoted',$7::jsonb,$8)
283
- ON CONFLICT(site_id, idempotency_key) DO NOTHING`,[Rt(),e.siteId,e.namespaceId,e.associationId,`candidate-promotion:${e.associationId}:${e.personId}`,e.promotedByUserId??null,JSON.stringify({candidateAssociations:1,deterministicPeople:1}),t.toISOString()]),await s.query(`INSERT INTO analytics_identity_promotion_receipts(
284
- id,site_id,namespace_id,canonical_person_id,canonical_person_ref_hmac,
285
- evidence_kind,evidence_ref_hmac,prior_person_ids,prior_identity_node_ids,
286
- candidate_association_ids,affected_history_counts,schema_version,idempotency_key,promoted_at
287
- ) VALUES($1,$2,$3,$4,$5,$6,$7,'{}'::uuid[],$8::uuid[],$9::uuid[],$10::jsonb,
288
- 'xray.identity-promotion.v1',$11,$12)
289
- ON CONFLICT(site_id,idempotency_key) DO NOTHING`,[Rt(),e.siteId,e.namespaceId,e.personId,wt("journey_pattern",`person:${e.personId}`),e.evidenceKind,i,[a.rows[0].left_identity_node_id,a.rows[0].right_identity_node_id],[e.associationId],JSON.stringify({events:0,sessions:0,touches:0,conversions:0,candidateTouches:0}),wt("journey_pattern",`promotion:${e.siteId}:${e.associationId}:${e.personId}:${e.evidenceKind}:${e.evidenceRef}`),t.toISOString()]),await s.query("COMMIT"),{associationId:e.associationId,personId:e.personId,promotedAt:t.toISOString(),reason:e.evidenceKind}}catch(a){throw await s.query("ROLLBACK"),a}finally{s.release()}}import{createHash as Dr,randomUUID as Hn}from"crypto";import{z as g}from"zod";var ie=g.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9_.:-]+$/),Ot=g.string().trim().min(1).max(160).regex(/^[a-zA-Z][a-zA-Z0-9_.:-]*$/),Tr=g.discriminatedUnion("kind",[g.object({kind:g.literal("event_completed"),eventName:ie,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("event_frequency"),eventName:ie,minimum:g.number().int().min(1).max(1e3),withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("event_recency"),eventName:ie,withinDays:g.number().int().min(1).max(3650)}).strict(),g.object({kind:g.literal("page_visited"),path:g.string().trim().startsWith("/").max(2e3),withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("referrer_equals"),value:g.string().trim().min(1).max(500)}).strict(),g.object({kind:g.literal("source_equals"),value:g.string().trim().min(1).max(180)}).strict(),g.object({kind:g.literal("call_outcome"),outcome:ie,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("crm_stage"),stage:ie}).strict(),g.object({kind:g.literal("property_equals"),property:Ot,value:g.union([g.string().max(500),g.number().finite(),g.boolean()])}).strict(),g.object({kind:g.literal("property_present"),property:Ot}).strict()]),xr=g.object({id:ie,label:g.string().trim().min(1).max(160),operation:g.enum(["add","subtract"]),points:g.number().int().min(0).max(1e5),cap:g.number().int().min(0).max(1e5).optional(),predicates:g.array(Tr).min(1).max(50)}).strict(),Wn=g.object({namespaceId:ie,name:g.string().trim().min(1).max(160),kind:g.enum(["fit","engagement","combined"]),targetObject:g.enum(["person","visitor"]),minimum:g.number().int().min(-1e6).max(1e6),maximum:g.number().int().min(-1e6).max(1e6),groups:g.array(xr).min(1).max(100),permittedProperties:g.array(Ot).max(200).default([]),enabled:g.boolean().default(!0)}).strict().superRefine((e,t)=>{e.minimum>=e.maximum&&t.addIssue({code:"custom",path:["maximum"],message:"maximum must be greater than minimum"});let n=new Set(e.permittedProperties);for(let[i,r]of e.groups.entries())for(let[s,a]of r.predicates.entries())(a.kind==="property_equals"||a.kind==="property_present")&&!n.has(a.property)&&t.addIssue({code:"custom",path:["groups",i,"predicates",s,"property"],message:"property is not allowlisted"})});function Bn(){return{definitions:new Map,evaluations:new Map,evaluationHistory:[]}}var Y=class extends Error{constructor(n,i){super(i);this.code=n;this.name="AnalyticsLeadScoringError"}code};function Dt(e){let t=e instanceof Date?e.toISOString():e??new Date().toISOString();if(!Number.isFinite(Date.parse(t)))throw new Y("analytics_score_invalid_time","A valid evaluation time is required.");return new Date(t).toISOString()}function De(e,t){return`${e}:${t}`}function Tt(e){return{...e,groups:e.groups.map(t=>({...t,predicates:t.predicates.map(n=>({...n}))})),permittedProperties:[...e.permittedProperties]}}function Lr(e,t,n){let i=Date.parse(e),r=Date.parse(t);return!Number.isFinite(i)||i>r?!1:n===void 0||r-i<=n*864e5}function $r(e,t,n){let i=(r,s,a)=>(r??[]).filter(o=>o.name===s&&Lr(o.occurredAt,n,a));switch(e.kind){case"event_completed":{let r=i(t.events,e.eventName,e.withinDays);return r.length?r.map(s=>s.ref):null}case"event_frequency":{let r=i(t.events,e.eventName,e.withinDays);return r.length>=e.minimum?r.map(s=>s.ref):null}case"event_recency":{let r=i(t.events,e.eventName,e.withinDays);return r.length?r.map(s=>s.ref):null}case"page_visited":{let r=i(t.pages,e.path,e.withinDays);return r.length?r.map(s=>s.ref):null}case"referrer_equals":{let r=(t.referrers??[]).filter(s=>s.name===e.value);return r.length?r.map(s=>s.ref):null}case"source_equals":{let r=(t.sources??[]).filter(s=>s.name===e.value);return r.length?r.map(s=>s.ref):null}case"call_outcome":{let r=i(t.calls,e.outcome,e.withinDays);return r.length?r.map(s=>s.ref):null}case"crm_stage":{let r=i(t.crmStages,e.stage);return r.length?r.map(s=>s.ref):null}case"property_equals":return t.permittedProperties?.[e.property]===e.value?[`property:${e.property}`]:null;case"property_present":{let r=t.permittedProperties?.[e.property];return r!=null?[`property:${e.property}`]:null}}}function kr(e){let t=n=>Array.isArray(n)?n.map(t):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).sort(([i],[r])=>i.localeCompare(r)).map(([i,r])=>[i,t(r)])):n;return Dr("sha256").update(JSON.stringify(t(e))).digest("hex")}function Vn(e){let t=Wn.parse(e.definition),n=e.id??Hn();if(e.tables.definitions.has(De(t.namespaceId,n)))throw new Y("analytics_score_exists","A lead score with this ID already exists.");let i=Dt(e.now),r={id:n,...t,groups:t.groups.map(s=>({...s,predicates:s.predicates.map(a=>({...a}))})),version:1,createdAt:i,updatedAt:i};return e.tables.definitions.set(De(t.namespaceId,n),r),Tt(r)}function oo(e){let t=e.tables.definitions.get(De(e.namespaceId,e.scoreId));if(!t)throw new Y("analytics_score_not_found","Lead score not found.");if(t.version!==e.expectedVersion)throw new Y("analytics_score_version_conflict","The lead score changed; reload before updating.");let n=Wn.parse(e.definition);if(n.namespaceId!==e.namespaceId)throw new Y("analytics_score_namespace_mismatch","Lead scores cannot move between namespaces.");let i={...t,...n,groups:n.groups.map(r=>({...r,predicates:r.predicates.map(s=>({...s}))})),version:t.version+1,updatedAt:Dt(e.now)};return e.tables.definitions.set(De(e.namespaceId,e.scoreId),i),Tt(i)}function co(e){return[...e.tables.definitions.values()].filter(t=>t.namespaceId===e.namespaceId).sort((t,n)=>t.name.localeCompare(n.name)).map(Tt)}function Kn(e){let t=e.tables.definitions.get(De(e.namespaceId,e.scoreId));if(!t||!t.enabled)throw new Y("analytics_score_unavailable","Lead score is missing or disabled.");let n=Dt(e.now),i=t.groups.map(_=>{let u=_.predicates.map(b=>$r(b,e.facts,n)),y=u.every(b=>b!==null),E=y?Math.min(_.points,_.cap??_.points):0;return{groupId:_.id,operation:_.operation,matched:y,points:_.operation==="subtract"?-E:E,evidenceRefs:y?[...new Set(u.flatMap(b=>b??[]))].sort():[]}}),r=i.reduce((_,u)=>_+u.points,0),s=Math.max(t.minimum,Math.min(t.maximum,r)),a=[...new Set(i.flatMap(_=>_.evidenceRefs))].sort(),o=kr({namespaceId:e.namespaceId,scoreId:e.scoreId,version:t.version,subjectRef:e.subjectRef,identityTier:e.identityTier,components:i,value:s}),c=e.tables.evaluations.get(o);if(c)return{...c,components:c.components.map(_=>({..._,evidenceRefs:[..._.evidenceRefs]})),evidenceRefs:[...c.evidenceRefs]};let d={id:Hn(),namespaceId:e.namespaceId,subjectRef:e.subjectRef,identityTier:e.identityTier,scoreId:t.id,scoreVersion:t.version,scoreKind:t.kind,value:s,components:i,evidenceRefs:a,evaluatedAt:n,idempotencyKey:o,providerEligible:e.identityTier==="confirmed"};return e.tables.evaluations.set(o,d),e.tables.evaluationHistory.push(d),{...d,components:d.components.map(_=>({..._,evidenceRefs:[..._.evidenceRefs]})),evidenceRefs:[...d.evidenceRefs]}}import{createHmac as Pr,timingSafeEqual as Mr}from"crypto";function p(e,t=500){if(typeof e!="string"&&typeof e!="number")return;let n=String(e).trim();return n?n.slice(0,t):void 0}function W(e){let t=Number(e);return Number.isFinite(t)?t:void 0}function re(e){if(typeof e=="boolean")return e;if(e==="true"||e==="1"||e===1)return!0;if(e==="false"||e==="0"||e===0)return!1}function Te(e){if(Array.isArray(e))return e.map(n=>p(n,80)).filter(n=>!!n).slice(0,30);let t=p(e,1e3);return t?t.split(",").map(n=>n.trim()).filter(Boolean).slice(0,30):[]}function B(...e){for(let t of e){let n=p(t,100);if(!n)continue;let i=new Date(n);if(Number.isFinite(i.getTime()))return i.toISOString()}return new Date().toISOString()}function pe(e,t,n){return Pr(e,t).update(n).digest("base64")}function ye(e,t){if(!e||e.length!==t.length)return!1;try{return Mr(Buffer.from(e),Buffer.from(t))}catch{return!1}}function ge(e,t=Date.now(),n=300*1e3){let i=p(e,100);if(!i)return!1;let r=Number(i),s=Number.isFinite(r)?r>1e10?r:r*1e3:Date.parse(i);return Number.isFinite(s)&&Math.abs(t-s)<=n}function _o(e){let t=new URL(e.requestUrl);for(let s of e.internalRewriteQueryKeys??[])t.searchParams.delete(s);let n=e.publicOrigin?.trim();if(n){let s=new URL(n);if(s.protocol!=="https:"||s.username||s.password)throw new Error("analytics webhook public origin must be an HTTPS origin");return s.pathname=t.pathname,s.search=t.search,s.hash="",s.toString()}let i=e.forwardedProto?.split(",")[0]?.trim(),r=e.forwardedHost?.split(",")[0]?.trim();return i&&(t.protocol=`${i}:`),r&&(t.host=r),t.toString()}function Jn(e){return ge(e.payloadTimestamp,e.now)&&ye(e.signature,pe("sha1",e.secret,e.rawBody))}function zn(e){let t=e.payload,n=p(t.resource_id??t.id,240)||"unknown",i=B(t.timestamp,t.start_time,t.created_at),r=Te(t.tags??t.tag),s=p(t.lead_status,80),a=s==="not_a_lead"||r.some(c=>c.toLowerCase()==="spam")||re(t.spam)===!0,o={...p(t.gclid)?{gclid:p(t.gclid)}:{},...p(t.gbraid)?{gbraid:p(t.gbraid)}:{},...p(t.wbraid)?{wbraid:p(t.wbraid)}:{},...p(t.fbclid)?{fbclid:p(t.fbclid)}:{},...p(t.msclkid)?{msclkid:p(t.msclkid)}:{}};return{schemaVersion:1,eventId:`callrail_${n}_${e.phase}`,sourceEventId:`${n}:${e.phase}:${i}`,source:"callrail",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:e.phase==="pre_call"?"call_started":e.phase==="routing_complete"?"call_routed":e.phase==="call_modified"?"call_modified":"call_completed",occurredAt:i,callId:n,personRef:p(t.person_resource_id,240),visitorId:p(t.visitor_id??t.browser_id??t.ga,160),canonicalUrl:p(t.landing_page_url,3e3),sourceName:p(t.utm_source??t.source_name,180),medium:p(t.utm_medium??t.medium,180),campaign:p(t.utm_campaign??t.campaign,240),clickIds:o,properties:{answered:re(t.answered)??!1,durationSeconds:W(t.duration)??0,status:a?"spam":s||"unknown",tags:r,direction:p(t.direction,40)||"unknown",trackingNumber:p(t.tracking_phone_number,80)||null,changes:Te(t.changes)}}}function Yn(e){return ge(e.requestTime,e.now)&&ye(e.signature.trim(),pe("sha1",e.secret,`${e.requestTime}${e.rawBody}`))}function Xn(e){let t=e.payload,n=p(t.activity_id??t.call_id??t.id,240)||"unknown",i=B(t.timestamp,t.event_time,t.started_at,t.created_at),r=Te(t.tags??t.tag_list),s=p(t.status??t.disposition,80)||"unknown",a=s.toLowerCase().includes("spam")||r.some(o=>o.toLowerCase()==="spam");return{schemaVersion:1,eventId:`ctm_${n}_${e.phase}`,sourceEventId:`${n}:${e.phase}:${i}`,source:"calltrackingmetrics",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:e.phase.includes("start")?"call_started":e.phase.includes("answer")?"call_answered":"call_completed",occurredAt:i,callId:n,personRef:p(t.contact_id??t.visitor_id,240),visitorId:p(t.visitor_id??t.cookie_id,160),sessionId:p(t.session_id,160),canonicalUrl:p(t.landing_page_url??t.landing_url,3e3),sourceName:p(t.source??t.utm_source,180),medium:p(t.medium??t.utm_medium,180),campaign:p(t.campaign??t.utm_campaign,240),clickIds:{...p(t.gclid)?{gclid:p(t.gclid)}:{},...p(t.fbclid)?{fbclid:p(t.fbclid)}:{},...p(t.msclkid)?{msclkid:p(t.msclkid)}:{}},properties:{answered:re(t.answered)??e.phase.includes("answer"),durationSeconds:W(t.duration??t.talk_time)??0,status:a?"spam":s,tags:r,direction:p(t.direction,40)||"unknown",trackingNumber:p(t.tracking_number??t.dialed_number,80)||null,score:W(t.score)??null}}}import Ur from"twilio";function Gn(e){return Ur.validateRequest(e.authToken,e.signature,e.url,e.params)}function Qn(e){let t=e.params,n=p(t.CallSid,240)||"unknown",i=(p(t.CallStatus,80)||"unknown").toLowerCase(),r=B(t.Timestamp,t.CallTimestamp,t.StartTime),s=["completed","busy","failed","no-answer","canceled"].includes(i),a=["in-progress","answered","completed"].includes(i);return{schemaVersion:1,eventId:`twilio_${n}_${i}`,sourceEventId:`${n}:${i}`,source:"twilio",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:s?"call_completed":a?"call_answered":"call_started",occurredAt:r,callId:n,visitorId:p(t.XRayVisitorId,160),sessionId:p(t.XRaySessionId,160),personRef:p(t.ContactId,240),properties:{answered:re(t.Answered)??a,durationSeconds:W(t.CallDuration??t.Duration)??0,status:i,direction:p(t.Direction,40)||"unknown",trackingNumber:p(t.To,80)||null,attributionLink:t.XRaySessionId?"explicit_session":"unattributed"}}}import{createCipheriv as Fr,createDecipheriv as jr,createHash as qr,createHmac as Hr}from"crypto";var xe={session:"xrs_",visitor:"xrv_",person:"xrp_",cursor:"xrc_",candidate:"xri_"};function Lt(e){return qr("sha256").update(`xray-report:${e}:`).update(Fe()).digest()}function O(e,t,n){let i=Lt("reference"),r=Buffer.from(`v1:${e}:${t}`),s=Buffer.from(n),a=Hr("sha256",Lt("reference-iv")).update(r).update(s).digest().subarray(0,12),o=Fr("aes-256-gcm",i,a);o.setAAD(r);let c=Buffer.concat([o.update(s),o.final()]);return`${xe[e]}${Buffer.concat([a,c,o.getAuthTag()]).toString("base64url")}`}function it(e,t,n){let i=xe[e];if(!n.startsWith(i))throw new Error("analytics_reference_invalid");try{let r=Buffer.from(n.slice(i.length),"base64url");if(r.length<29)throw new Error("short reference");let s=r.subarray(0,12),a=r.subarray(r.length-16),o=r.subarray(12,r.length-16),c=jr("aes-256-gcm",Lt("reference"),s);return c.setAAD(Buffer.from(`v1:${e}:${t}`)),c.setAuthTag(a),Buffer.concat([c.update(o),c.final()]).toString("utf8")}catch{throw new Error("analytics_reference_invalid")}}function Wr(e,t){return O("cursor",e,JSON.stringify(t))}function ve(e,t){if(!t)return null;try{let n=JSON.parse(it("cursor",e,t));if(!n.at||!n.id||Number.isNaN(Date.parse(n.at)))throw new Error("invalid");return n}catch{throw new Error("analytics_cursor_invalid")}}function Ee(e){if(e===void 0)return 50;if(!Number.isInteger(e)||e<1||e>100)throw new Error("analytics_limit_invalid");return e}function xt(e){if(typeof e!="string"||!e)return null;try{let t=new URL(e);return`${t.origin}${t.pathname}`.slice(0,2e3)}catch{return null}}function fe(e){if(e==null)return null;let t=Number(e);return Number.isFinite(t)?t:null}function S(e){let t=e instanceof Date?e:new Date(e);if(!Number.isFinite(t.getTime()))throw new Error("analytics_timestamp_invalid");return t.toISOString()}function Zn(e){return e===null?null:S(e)}function be(e,t,n,i){let r=t.length>n,s=t.slice(0,n),a=s.at(-1);return{items:s.map(i),pageInfo:{hasNextPage:r,nextCursor:r&&a?Wr(e,{at:a._cursorAt,id:a._cursorId}):null}}}async function Ae(e,t){await U(t,e.siteId,e.userId)}async function ho(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsSessions:keyset */
289
+ WHERE worker_key='default'`).catch(()=>{}),s}}import{createHash as Dr,randomUUID as Hn}from"crypto";import{z as g}from"zod";var ie=g.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9_.:-]+$/),Ot=g.string().trim().min(1).max(160).regex(/^[a-zA-Z][a-zA-Z0-9_.:-]*$/),Tr=g.discriminatedUnion("kind",[g.object({kind:g.literal("event_completed"),eventName:ie,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("event_frequency"),eventName:ie,minimum:g.number().int().min(1).max(1e3),withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("event_recency"),eventName:ie,withinDays:g.number().int().min(1).max(3650)}).strict(),g.object({kind:g.literal("page_visited"),path:g.string().trim().startsWith("/").max(2e3),withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("referrer_equals"),value:g.string().trim().min(1).max(500)}).strict(),g.object({kind:g.literal("source_equals"),value:g.string().trim().min(1).max(180)}).strict(),g.object({kind:g.literal("call_outcome"),outcome:ie,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("crm_stage"),stage:ie}).strict(),g.object({kind:g.literal("property_equals"),property:Ot,value:g.union([g.string().max(500),g.number().finite(),g.boolean()])}).strict(),g.object({kind:g.literal("property_present"),property:Ot}).strict()]),xr=g.object({id:ie,label:g.string().trim().min(1).max(160),operation:g.enum(["add","subtract"]),points:g.number().int().min(0).max(1e5),cap:g.number().int().min(0).max(1e5).optional(),predicates:g.array(Tr).min(1).max(50)}).strict(),Wn=g.object({namespaceId:ie,name:g.string().trim().min(1).max(160),kind:g.enum(["fit","engagement","combined"]),targetObject:g.enum(["person","visitor"]),minimum:g.number().int().min(-1e6).max(1e6),maximum:g.number().int().min(-1e6).max(1e6),groups:g.array(xr).min(1).max(100),permittedProperties:g.array(Ot).max(200).default([]),enabled:g.boolean().default(!0)}).strict().superRefine((e,t)=>{e.minimum>=e.maximum&&t.addIssue({code:"custom",path:["maximum"],message:"maximum must be greater than minimum"});let n=new Set(e.permittedProperties);for(let[i,r]of e.groups.entries())for(let[s,a]of r.predicates.entries())(a.kind==="property_equals"||a.kind==="property_present")&&!n.has(a.property)&&t.addIssue({code:"custom",path:["groups",i,"predicates",s,"property"],message:"property is not allowlisted"})});function Bn(){return{definitions:new Map,evaluations:new Map,evaluationHistory:[]}}var Y=class extends Error{constructor(n,i){super(i);this.code=n;this.name="AnalyticsLeadScoringError"}code};function Dt(e){let t=e instanceof Date?e.toISOString():e??new Date().toISOString();if(!Number.isFinite(Date.parse(t)))throw new Y("analytics_score_invalid_time","A valid evaluation time is required.");return new Date(t).toISOString()}function De(e,t){return`${e}:${t}`}function Tt(e){return{...e,groups:e.groups.map(t=>({...t,predicates:t.predicates.map(n=>({...n}))})),permittedProperties:[...e.permittedProperties]}}function Lr(e,t,n){let i=Date.parse(e),r=Date.parse(t);return!Number.isFinite(i)||i>r?!1:n===void 0||r-i<=n*864e5}function $r(e,t,n){let i=(r,s,a)=>(r??[]).filter(o=>o.name===s&&Lr(o.occurredAt,n,a));switch(e.kind){case"event_completed":{let r=i(t.events,e.eventName,e.withinDays);return r.length?r.map(s=>s.ref):null}case"event_frequency":{let r=i(t.events,e.eventName,e.withinDays);return r.length>=e.minimum?r.map(s=>s.ref):null}case"event_recency":{let r=i(t.events,e.eventName,e.withinDays);return r.length?r.map(s=>s.ref):null}case"page_visited":{let r=i(t.pages,e.path,e.withinDays);return r.length?r.map(s=>s.ref):null}case"referrer_equals":{let r=(t.referrers??[]).filter(s=>s.name===e.value);return r.length?r.map(s=>s.ref):null}case"source_equals":{let r=(t.sources??[]).filter(s=>s.name===e.value);return r.length?r.map(s=>s.ref):null}case"call_outcome":{let r=i(t.calls,e.outcome,e.withinDays);return r.length?r.map(s=>s.ref):null}case"crm_stage":{let r=i(t.crmStages,e.stage);return r.length?r.map(s=>s.ref):null}case"property_equals":return t.permittedProperties?.[e.property]===e.value?[`property:${e.property}`]:null;case"property_present":{let r=t.permittedProperties?.[e.property];return r!=null?[`property:${e.property}`]:null}}}function kr(e){let t=n=>Array.isArray(n)?n.map(t):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).sort(([i],[r])=>i.localeCompare(r)).map(([i,r])=>[i,t(r)])):n;return Dr("sha256").update(JSON.stringify(t(e))).digest("hex")}function Vn(e){let t=Wn.parse(e.definition),n=e.id??Hn();if(e.tables.definitions.has(De(t.namespaceId,n)))throw new Y("analytics_score_exists","A lead score with this ID already exists.");let i=Dt(e.now),r={id:n,...t,groups:t.groups.map(s=>({...s,predicates:s.predicates.map(a=>({...a}))})),version:1,createdAt:i,updatedAt:i};return e.tables.definitions.set(De(t.namespaceId,n),r),Tt(r)}function lo(e){let t=e.tables.definitions.get(De(e.namespaceId,e.scoreId));if(!t)throw new Y("analytics_score_not_found","Lead score not found.");if(t.version!==e.expectedVersion)throw new Y("analytics_score_version_conflict","The lead score changed; reload before updating.");let n=Wn.parse(e.definition);if(n.namespaceId!==e.namespaceId)throw new Y("analytics_score_namespace_mismatch","Lead scores cannot move between namespaces.");let i={...t,...n,groups:n.groups.map(r=>({...r,predicates:r.predicates.map(s=>({...s}))})),version:t.version+1,updatedAt:Dt(e.now)};return e.tables.definitions.set(De(e.namespaceId,e.scoreId),i),Tt(i)}function uo(e){return[...e.tables.definitions.values()].filter(t=>t.namespaceId===e.namespaceId).sort((t,n)=>t.name.localeCompare(n.name)).map(Tt)}function Kn(e){let t=e.tables.definitions.get(De(e.namespaceId,e.scoreId));if(!t||!t.enabled)throw new Y("analytics_score_unavailable","Lead score is missing or disabled.");let n=Dt(e.now),i=t.groups.map(_=>{let u=_.predicates.map(b=>$r(b,e.facts,n)),y=u.every(b=>b!==null),E=y?Math.min(_.points,_.cap??_.points):0;return{groupId:_.id,operation:_.operation,matched:y,points:_.operation==="subtract"?-E:E,evidenceRefs:y?[...new Set(u.flatMap(b=>b??[]))].sort():[]}}),r=i.reduce((_,u)=>_+u.points,0),s=Math.max(t.minimum,Math.min(t.maximum,r)),a=[...new Set(i.flatMap(_=>_.evidenceRefs))].sort(),o=kr({namespaceId:e.namespaceId,scoreId:e.scoreId,version:t.version,subjectRef:e.subjectRef,identityTier:e.identityTier,components:i,value:s}),c=e.tables.evaluations.get(o);if(c)return{...c,components:c.components.map(_=>({..._,evidenceRefs:[..._.evidenceRefs]})),evidenceRefs:[...c.evidenceRefs]};let d={id:Hn(),namespaceId:e.namespaceId,subjectRef:e.subjectRef,identityTier:e.identityTier,scoreId:t.id,scoreVersion:t.version,scoreKind:t.kind,value:s,components:i,evidenceRefs:a,evaluatedAt:n,idempotencyKey:o,providerEligible:e.identityTier==="confirmed"};return e.tables.evaluations.set(o,d),e.tables.evaluationHistory.push(d),{...d,components:d.components.map(_=>({..._,evidenceRefs:[..._.evidenceRefs]})),evidenceRefs:[...d.evidenceRefs]}}import{createHmac as Pr,timingSafeEqual as Mr}from"crypto";function p(e,t=500){if(typeof e!="string"&&typeof e!="number")return;let n=String(e).trim();return n?n.slice(0,t):void 0}function W(e){let t=Number(e);return Number.isFinite(t)?t:void 0}function re(e){if(typeof e=="boolean")return e;if(e==="true"||e==="1"||e===1)return!0;if(e==="false"||e==="0"||e===0)return!1}function Te(e){if(Array.isArray(e))return e.map(n=>p(n,80)).filter(n=>!!n).slice(0,30);let t=p(e,1e3);return t?t.split(",").map(n=>n.trim()).filter(Boolean).slice(0,30):[]}function B(...e){for(let t of e){let n=p(t,100);if(!n)continue;let i=new Date(n);if(Number.isFinite(i.getTime()))return i.toISOString()}return new Date().toISOString()}function pe(e,t,n){return Pr(e,t).update(n).digest("base64")}function ye(e,t){if(!e||e.length!==t.length)return!1;try{return Mr(Buffer.from(e),Buffer.from(t))}catch{return!1}}function ge(e,t=Date.now(),n=300*1e3){let i=p(e,100);if(!i)return!1;let r=Number(i),s=Number.isFinite(r)?r>1e10?r:r*1e3:Date.parse(i);return Number.isFinite(s)&&Math.abs(t-s)<=n}function po(e){let t=new URL(e.requestUrl);for(let s of e.internalRewriteQueryKeys??[])t.searchParams.delete(s);let n=e.publicOrigin?.trim();if(n){let s=new URL(n);if(s.protocol!=="https:"||s.username||s.password)throw new Error("analytics webhook public origin must be an HTTPS origin");return s.pathname=t.pathname,s.search=t.search,s.hash="",s.toString()}let i=e.forwardedProto?.split(",")[0]?.trim(),r=e.forwardedHost?.split(",")[0]?.trim();return i&&(t.protocol=`${i}:`),r&&(t.host=r),t.toString()}function Jn(e){return ge(e.payloadTimestamp,e.now)&&ye(e.signature,pe("sha1",e.secret,e.rawBody))}function zn(e){let t=e.payload,n=p(t.resource_id??t.id,240)||"unknown",i=B(t.timestamp,t.start_time,t.created_at),r=Te(t.tags??t.tag),s=p(t.lead_status,80),a=s==="not_a_lead"||r.some(c=>c.toLowerCase()==="spam")||re(t.spam)===!0,o={...p(t.gclid)?{gclid:p(t.gclid)}:{},...p(t.gbraid)?{gbraid:p(t.gbraid)}:{},...p(t.wbraid)?{wbraid:p(t.wbraid)}:{},...p(t.fbclid)?{fbclid:p(t.fbclid)}:{},...p(t.msclkid)?{msclkid:p(t.msclkid)}:{}};return{schemaVersion:1,eventId:`callrail_${n}_${e.phase}`,sourceEventId:`${n}:${e.phase}:${i}`,source:"callrail",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:e.phase==="pre_call"?"call_started":e.phase==="routing_complete"?"call_routed":e.phase==="call_modified"?"call_modified":"call_completed",occurredAt:i,callId:n,personRef:p(t.person_resource_id,240),visitorId:p(t.visitor_id??t.browser_id??t.ga,160),canonicalUrl:p(t.landing_page_url,3e3),sourceName:p(t.utm_source??t.source_name,180),medium:p(t.utm_medium??t.medium,180),campaign:p(t.utm_campaign??t.campaign,240),clickIds:o,properties:{answered:re(t.answered)??!1,durationSeconds:W(t.duration)??0,status:a?"spam":s||"unknown",tags:r,direction:p(t.direction,40)||"unknown",trackingNumber:p(t.tracking_phone_number,80)||null,changes:Te(t.changes)}}}function Yn(e){return ge(e.requestTime,e.now)&&ye(e.signature.trim(),pe("sha1",e.secret,`${e.requestTime}${e.rawBody}`))}function Xn(e){let t=e.payload,n=p(t.activity_id??t.call_id??t.id,240)||"unknown",i=B(t.timestamp,t.event_time,t.started_at,t.created_at),r=Te(t.tags??t.tag_list),s=p(t.status??t.disposition,80)||"unknown",a=s.toLowerCase().includes("spam")||r.some(o=>o.toLowerCase()==="spam");return{schemaVersion:1,eventId:`ctm_${n}_${e.phase}`,sourceEventId:`${n}:${e.phase}:${i}`,source:"calltrackingmetrics",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:e.phase.includes("start")?"call_started":e.phase.includes("answer")?"call_answered":"call_completed",occurredAt:i,callId:n,personRef:p(t.contact_id??t.visitor_id,240),visitorId:p(t.visitor_id??t.cookie_id,160),sessionId:p(t.session_id,160),canonicalUrl:p(t.landing_page_url??t.landing_url,3e3),sourceName:p(t.source??t.utm_source,180),medium:p(t.medium??t.utm_medium,180),campaign:p(t.campaign??t.utm_campaign,240),clickIds:{...p(t.gclid)?{gclid:p(t.gclid)}:{},...p(t.fbclid)?{fbclid:p(t.fbclid)}:{},...p(t.msclkid)?{msclkid:p(t.msclkid)}:{}},properties:{answered:re(t.answered)??e.phase.includes("answer"),durationSeconds:W(t.duration??t.talk_time)??0,status:a?"spam":s,tags:r,direction:p(t.direction,40)||"unknown",trackingNumber:p(t.tracking_number??t.dialed_number,80)||null,score:W(t.score)??null}}}import Ur from"twilio";function Gn(e){return Ur.validateRequest(e.authToken,e.signature,e.url,e.params)}function Qn(e){let t=e.params,n=p(t.CallSid,240)||"unknown",i=(p(t.CallStatus,80)||"unknown").toLowerCase(),r=B(t.Timestamp,t.CallTimestamp,t.StartTime),s=["completed","busy","failed","no-answer","canceled"].includes(i),a=["in-progress","answered","completed"].includes(i);return{schemaVersion:1,eventId:`twilio_${n}_${i}`,sourceEventId:`${n}:${i}`,source:"twilio",sourceAccountRef:e.sourceAccountRef,eventKind:"call",eventName:s?"call_completed":a?"call_answered":"call_started",occurredAt:r,callId:n,visitorId:p(t.XRayVisitorId,160),sessionId:p(t.XRaySessionId,160),personRef:p(t.ContactId,240),properties:{answered:re(t.Answered)??a,durationSeconds:W(t.CallDuration??t.Duration)??0,status:i,direction:p(t.Direction,40)||"unknown",trackingNumber:p(t.To,80)||null,attributionLink:t.XRaySessionId?"explicit_session":"unattributed"}}}import{createCipheriv as Fr,createDecipheriv as jr,createHash as qr,createHmac as Hr}from"crypto";var xe={session:"xrs_",visitor:"xrv_",person:"xrp_",cursor:"xrc_",candidate:"xri_"};function Lt(e){return qr("sha256").update(`xray-report:${e}:`).update(Fe()).digest()}function O(e,t,n){let i=Lt("reference"),r=Buffer.from(`v1:${e}:${t}`),s=Buffer.from(n),a=Hr("sha256",Lt("reference-iv")).update(r).update(s).digest().subarray(0,12),o=Fr("aes-256-gcm",i,a);o.setAAD(r);let c=Buffer.concat([o.update(s),o.final()]);return`${xe[e]}${Buffer.concat([a,c,o.getAuthTag()]).toString("base64url")}`}function it(e,t,n){let i=xe[e];if(!n.startsWith(i))throw new Error("analytics_reference_invalid");try{let r=Buffer.from(n.slice(i.length),"base64url");if(r.length<29)throw new Error("short reference");let s=r.subarray(0,12),a=r.subarray(r.length-16),o=r.subarray(12,r.length-16),c=jr("aes-256-gcm",Lt("reference"),s);return c.setAAD(Buffer.from(`v1:${e}:${t}`)),c.setAuthTag(a),Buffer.concat([c.update(o),c.final()]).toString("utf8")}catch{throw new Error("analytics_reference_invalid")}}function Wr(e,t){return O("cursor",e,JSON.stringify(t))}function ve(e,t){if(!t)return null;try{let n=JSON.parse(it("cursor",e,t));if(!n.at||!n.id||Number.isNaN(Date.parse(n.at)))throw new Error("invalid");return n}catch{throw new Error("analytics_cursor_invalid")}}function Ee(e){if(e===void 0)return 50;if(!Number.isInteger(e)||e<1||e>100)throw new Error("analytics_limit_invalid");return e}function xt(e){if(typeof e!="string"||!e)return null;try{let t=new URL(e);return`${t.origin}${t.pathname}`.slice(0,2e3)}catch{return null}}function fe(e){if(e==null)return null;let t=Number(e);return Number.isFinite(t)?t:null}function S(e){let t=e instanceof Date?e:new Date(e);if(!Number.isFinite(t.getTime()))throw new Error("analytics_timestamp_invalid");return t.toISOString()}function Zn(e){return e===null?null:S(e)}function be(e,t,n,i){let r=t.length>n,s=t.slice(0,n),a=s.at(-1);return{items:s.map(i),pageInfo:{hasNextPage:r,nextCursor:r&&a?Wr(e,{at:a._cursorAt,id:a._cursorId}):null}}}async function Ae(e,t){await U(t,e.siteId,e.userId)}async function Co(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsSessions:keyset */
290
290
  WITH ranked AS (
291
291
  SELECT s.*,
292
292
  row_number() OVER (PARTITION BY s.visitor_hmac ORDER BY s.started_at, s.id)::int AS session_number
@@ -322,7 +322,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
322
322
  SELECT 1 FROM analytics_events ee
323
323
  WHERE ee.site_id = $1 AND ee.session_hmac = r.session_hmac AND ee.event_name = $8
324
324
  ))
325
- ORDER BY r.started_at DESC, r.id DESC LIMIT $9`,[e.siteId,i?.at??null,i?.id??null,e.returning??null,e.converted??null,e.minimumDurationMs??null,e.maximumDurationMs??null,e.eventName?.slice(0,160)??null,n+1])).rows.map(a=>({...a,_cursorAt:S(a.started_at),_cursorId:a.internal_id}));return be(e.siteId,s,n,a=>({sessionRef:O("session",e.siteId,a.internal_id),visitorRef:O("visitor",e.siteId,`visitor:${a.visitor_hmac}`),personRef:a.person_id?O("person",e.siteId,a.person_id):null,returning:a.session_number>1,sessionNumber:a.session_number,startedAt:S(a.started_at),lastActiveAt:S(a.last_active_at),endedAt:Zn(a.ended_at),durationMs:fe(a.duration_ms),landingPath:a.landing_path,exitPath:a.exit_path,pages:a.pageview_count,events:a.event_count,device:a.device_class,location:{country:a.country_code,region:a.region_code},acquisition:{source:a.source,medium:a.medium,campaign:a.campaign},conversions:a.conversion_count,revenue:a.revenue_minor===null?null:{valueMinor:Number(a.revenue_minor),currency:a.currency}}))}async function No(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsVisitors:keyset */
325
+ ORDER BY r.started_at DESC, r.id DESC LIMIT $9`,[e.siteId,i?.at??null,i?.id??null,e.returning??null,e.converted??null,e.minimumDurationMs??null,e.maximumDurationMs??null,e.eventName?.slice(0,160)??null,n+1])).rows.map(a=>({...a,_cursorAt:S(a.started_at),_cursorId:a.internal_id}));return be(e.siteId,s,n,a=>({sessionRef:O("session",e.siteId,a.internal_id),visitorRef:O("visitor",e.siteId,`visitor:${a.visitor_hmac}`),personRef:a.person_id?O("person",e.siteId,a.person_id):null,returning:a.session_number>1,sessionNumber:a.session_number,startedAt:S(a.started_at),lastActiveAt:S(a.last_active_at),endedAt:Zn(a.ended_at),durationMs:fe(a.duration_ms),landingPath:a.landing_path,exitPath:a.exit_path,pages:a.pageview_count,events:a.event_count,device:a.device_class,location:{country:a.country_code,region:a.region_code},acquisition:{source:a.source,medium:a.medium,campaign:a.campaign},conversions:a.conversion_count,revenue:a.revenue_minor===null?null:{valueMinor:Number(a.revenue_minor),currency:a.currency}}))}async function Ro(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsVisitors:keyset */
326
326
  WITH visitor_sessions AS (
327
327
  SELECT COALESCE(s.person_id::text, s.visitor_hmac) AS identity_key, s.person_id,
328
328
  min(s.started_at) AS first_seen_at, max(s.last_active_at) AS last_seen_at,
@@ -344,7 +344,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
344
344
  WHERE ($2::timestamptz IS NULL OR (v.last_seen_at, v.last_session_id) < ($2::timestamptz, $3::uuid))
345
345
  AND ($4::boolean IS NULL OR (v.session_count > 1) = $4)
346
346
  AND ($5::boolean IS NULL OR (COALESCE(c.conversion_count,0) > 0) = $5)
347
- ORDER BY v.last_seen_at DESC, v.last_session_id DESC LIMIT $6`,[e.siteId,i?.at??null,i?.id??null,e.returning??null,e.converted??null,n+1])).rows.map(a=>({...a,_cursorAt:S(a.last_seen_at),_cursorId:a.last_session_id}));return be(e.siteId,s,n,a=>({visitorRef:O("visitor",e.siteId,a.person_id?`person:${a.person_id}`:`visitor:${a.identity_key}`),personRef:a.person_id?O("person",e.siteId,a.person_id):null,known:!!a.person_id,returning:a.session_count>1,sessions:a.session_count,firstSeenAt:S(a.first_seen_at),lastSeenAt:S(a.last_seen_at),durationMs:fe(a.duration_ms),pages:a.pageview_count,events:a.event_count,conversions:a.conversion_count,revenue:a.revenue_minor===null?null:{valueMinor:Number(a.revenue_minor),currency:a.currency}}))}async function Br(e,t){if(t.startsWith(xe.person))return{kind:"person",personId:it("person",e,t),visitorHmac:null,sessionId:null};if(t.startsWith(xe.visitor)){let n=it("visitor",e,t);if(n.startsWith("person:"))return{kind:"visitor",personId:n.slice(7),visitorHmac:null,sessionId:null};if(n.startsWith("visitor:"))return{kind:"visitor",personId:null,visitorHmac:n.slice(8),sessionId:null};throw new Error("analytics_reference_invalid")}if(t.startsWith(xe.session))return{kind:"session",personId:null,visitorHmac:null,sessionId:it("session",e,t)};throw new Error("analytics_reference_invalid")}var Vr=2160*60*60*1e3,Kr=366*24*60*60*1e3;function Jr(e,t){let n=t===void 0?Date.now():Date.parse(t),i=e===void 0?n-Vr:Date.parse(e);if(!Number.isFinite(i)||!Number.isFinite(n)||i>=n||n-i>Kr)throw new f("analytics_journey_date_range_invalid","Choose a valid from-inclusive, to-exclusive date range of at most 366 days.",400);return{from:new Date(i).toISOString(),to:new Date(n).toISOString()}}async function Co(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),r;try{r=await Br(e.siteId,e.reference)}catch{throw new f("analytics_journey_not_found","Journey not found.",404)}if(!(await t.query(`/* analyticsEnhancedJourney:subject */
347
+ ORDER BY v.last_seen_at DESC, v.last_session_id DESC LIMIT $6`,[e.siteId,i?.at??null,i?.id??null,e.returning??null,e.converted??null,n+1])).rows.map(a=>({...a,_cursorAt:S(a.last_seen_at),_cursorId:a.last_session_id}));return be(e.siteId,s,n,a=>({visitorRef:O("visitor",e.siteId,a.person_id?`person:${a.person_id}`:`visitor:${a.identity_key}`),personRef:a.person_id?O("person",e.siteId,a.person_id):null,known:!!a.person_id,returning:a.session_count>1,sessions:a.session_count,firstSeenAt:S(a.first_seen_at),lastSeenAt:S(a.last_seen_at),durationMs:fe(a.duration_ms),pages:a.pageview_count,events:a.event_count,conversions:a.conversion_count,revenue:a.revenue_minor===null?null:{valueMinor:Number(a.revenue_minor),currency:a.currency}}))}async function Br(e,t){if(t.startsWith(xe.person))return{kind:"person",personId:it("person",e,t),visitorHmac:null,sessionId:null};if(t.startsWith(xe.visitor)){let n=it("visitor",e,t);if(n.startsWith("person:"))return{kind:"visitor",personId:n.slice(7),visitorHmac:null,sessionId:null};if(n.startsWith("visitor:"))return{kind:"visitor",personId:null,visitorHmac:n.slice(8),sessionId:null};throw new Error("analytics_reference_invalid")}if(t.startsWith(xe.session))return{kind:"session",personId:null,visitorHmac:null,sessionId:it("session",e,t)};throw new Error("analytics_reference_invalid")}var Vr=2160*60*60*1e3,Kr=366*24*60*60*1e3;function Jr(e,t){let n=t===void 0?Date.now():Date.parse(t),i=e===void 0?n-Vr:Date.parse(e);if(!Number.isFinite(i)||!Number.isFinite(n)||i>=n||n-i>Kr)throw new f("analytics_journey_date_range_invalid","Choose a valid from-inclusive, to-exclusive date range of at most 366 days.",400);return{from:new Date(i).toISOString(),to:new Date(n).toISOString()}}async function wo(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),r;try{r=await Br(e.siteId,e.reference)}catch{throw new f("analytics_journey_not_found","Journey not found.",404)}if(!(await t.query(`/* analyticsEnhancedJourney:subject */
348
348
  SELECT 1 WHERE
349
349
  ($2::uuid IS NOT NULL AND EXISTS (SELECT 1 FROM analytics_people p WHERE p.site_id=$1 AND p.id=$2))
350
350
  OR ($3::text IS NOT NULL AND EXISTS (SELECT 1 FROM analytics_sessions s WHERE s.site_id=$1 AND s.visitor_hmac=$3))
@@ -515,7 +515,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
515
515
  f.source,f.medium,f.campaign,f.referrer
516
516
  FROM ranged_sessions s LEFT JOIN event_stats e ON e.session_hmac=s.session_hmac
517
517
  LEFT JOIN first_touch f ON f.session_hmac=s.session_hmac LEFT JOIN conversion_stats c ON c.session_hmac=s.session_hmac
518
- ORDER BY s.started_at DESC,s.id DESC LIMIT 50`,[...o])]),V=d.rows.map(m=>({...m,_cursorAt:S(m.occurred_at),_cursorId:m.stable_id})),P=be(e.siteId,V,n,m=>({occurredAt:S(m.occurred_at),type:m.entry_type,name:m.name,path:m.path,referrer:xt(m.referrer),acquisition:m.source||m.medium||m.campaign?{source:m.source,medium:m.medium,campaign:m.campaign}:null,value:m.value_minor===null?null:{valueMinor:Number(m.value_minor),currency:m.currency},evidenceClass:m.evidence_class,provenance:m.provenance})),h=_.rows[0]??{resolved_person_id:null,sessions:0,pageviews:0,events:0,conversions:0,revenue_minor:null,currency:null,total_engagement_ms:null,average_engagement_ms:null},L=h.resolved_person_id??r.personId;return{subject:{kind:L?"person":r.kind,reference:e.reference,personRef:L?O("person",e.siteId,L):null},range:{...a,fromInclusive:!0,toExclusive:!0},journeyTier:"confirmed",candidateAssisted:null,summary:{sessions:Number(h.sessions),pageviews:Number(h.pageviews),events:Number(h.events),conversions:Number(h.conversions),revenue:h.revenue_minor===null?null:{valueMinor:Number(h.revenue_minor),currency:h.currency},totalEngagementMs:fe(h.total_engagement_ms),averageEngagementMs:fe(h.average_engagement_ms)},commonPages:u.rows.map(m=>({path:m.path,visits:Number(m.visits),uniqueSessions:Number(m.unique_sessions),engagedMs:fe(m.engaged_ms),conversions:Number(m.conversions)})),acquisition:y.rows.map(m=>({source:m.source,medium:m.medium,campaign:m.campaign,referrer:xt(m.referrer),sessions:Number(m.sessions),events:Number(m.events),conversions:Number(m.conversions)})),eventBreakdown:E.rows.map(m=>({name:m.name,count:Number(m.count),uniqueSessions:Number(m.unique_sessions),conversions:Number(m.conversions)})),sessions:b.rows.map(m=>({sessionRef:O("session",e.siteId,m.internal_id),startedAt:S(m.started_at),endedAt:Zn(m.ended_at),durationMs:fe(m.duration_ms),pageviews:Number(m.pageviews),events:Number(m.events),conversions:Number(m.conversions),revenue:m.revenue_minor===null?null:{valueMinor:Number(m.revenue_minor),currency:m.currency},landingPath:m.landing_path,exitPath:m.exit_path,acquisition:m.source||m.medium||m.campaign||m.referrer?{source:m.source,medium:m.medium,campaign:m.campaign,referrer:xt(m.referrer)}:null})),...P}}async function Ro(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsConfirmedJourneys:keyset */
518
+ ORDER BY s.started_at DESC,s.id DESC LIMIT 50`,[...o])]),V=d.rows.map(m=>({...m,_cursorAt:S(m.occurred_at),_cursorId:m.stable_id})),P=be(e.siteId,V,n,m=>({occurredAt:S(m.occurred_at),type:m.entry_type,name:m.name,path:m.path,referrer:xt(m.referrer),acquisition:m.source||m.medium||m.campaign?{source:m.source,medium:m.medium,campaign:m.campaign}:null,value:m.value_minor===null?null:{valueMinor:Number(m.value_minor),currency:m.currency},evidenceClass:m.evidence_class,provenance:m.provenance})),h=_.rows[0]??{resolved_person_id:null,sessions:0,pageviews:0,events:0,conversions:0,revenue_minor:null,currency:null,total_engagement_ms:null,average_engagement_ms:null},L=h.resolved_person_id??r.personId;return{subject:{kind:L?"person":r.kind,reference:e.reference,personRef:L?O("person",e.siteId,L):null},range:{...a,fromInclusive:!0,toExclusive:!0},journeyTier:"confirmed",candidateAssisted:null,summary:{sessions:Number(h.sessions),pageviews:Number(h.pageviews),events:Number(h.events),conversions:Number(h.conversions),revenue:h.revenue_minor===null?null:{valueMinor:Number(h.revenue_minor),currency:h.currency},totalEngagementMs:fe(h.total_engagement_ms),averageEngagementMs:fe(h.average_engagement_ms)},commonPages:u.rows.map(m=>({path:m.path,visits:Number(m.visits),uniqueSessions:Number(m.unique_sessions),engagedMs:fe(m.engaged_ms),conversions:Number(m.conversions)})),acquisition:y.rows.map(m=>({source:m.source,medium:m.medium,campaign:m.campaign,referrer:xt(m.referrer),sessions:Number(m.sessions),events:Number(m.events),conversions:Number(m.conversions)})),eventBreakdown:E.rows.map(m=>({name:m.name,count:Number(m.count),uniqueSessions:Number(m.unique_sessions),conversions:Number(m.conversions)})),sessions:b.rows.map(m=>({sessionRef:O("session",e.siteId,m.internal_id),startedAt:S(m.started_at),endedAt:Zn(m.ended_at),durationMs:fe(m.duration_ms),pageviews:Number(m.pageviews),events:Number(m.events),conversions:Number(m.conversions),revenue:m.revenue_minor===null?null:{valueMinor:Number(m.revenue_minor),currency:m.currency},landingPath:m.landing_path,exitPath:m.exit_path,acquisition:m.source||m.medium||m.campaign||m.referrer?{source:m.source,medium:m.medium,campaign:m.campaign,referrer:xt(m.referrer)}:null})),...P}}async function Oo(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsConfirmedJourneys:keyset */
519
519
  SELECT p.id AS person_id, p.namespace_id, sessions.first_seen_at,
520
520
  sessions.last_seen_at, COALESCE(sessions.session_count,0)::int AS session_count,
521
521
  COALESCE(events.event_count,0)::int AS event_count,
@@ -539,7 +539,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
539
539
  ) conversions ON true
540
540
  WHERE p.site_id=$1 AND n.status='approved'
541
541
  AND ($2::timestamptz IS NULL OR (sessions.last_seen_at,p.id) < ($2::timestamptz,$3::uuid))
542
- ORDER BY last_seen_at DESC, p.id DESC LIMIT $4`,[e.siteId,i?.at??null,i?.id??null,n+1])).rows.map(o=>({...o,_cursorAt:S(o.last_seen_at),_cursorId:o.person_id}));return{journeyTier:"confirmed",...be(e.siteId,s,n,o=>({journeyTier:"confirmed",personRef:O("person",e.siteId,o.person_id),firstSeenAt:S(o.first_seen_at),lastSeenAt:S(o.last_seen_at),sessions:o.session_count,events:o.event_count,conversions:o.conversion_count,revenue:o.revenue_minor===null?null:{valueMinor:Number(o.revenue_minor),currency:o.currency},evidenceClass:"deterministic"}))}}async function wo(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsBestGuessJourneys:keyset */
542
+ ORDER BY last_seen_at DESC, p.id DESC LIMIT $4`,[e.siteId,i?.at??null,i?.id??null,n+1])).rows.map(o=>({...o,_cursorAt:S(o.last_seen_at),_cursorId:o.person_id}));return{journeyTier:"confirmed",...be(e.siteId,s,n,o=>({journeyTier:"confirmed",personRef:O("person",e.siteId,o.person_id),firstSeenAt:S(o.first_seen_at),lastSeenAt:S(o.last_seen_at),sessions:o.session_count,events:o.event_count,conversions:o.conversion_count,revenue:o.revenue_minor===null?null:{valueMinor:Number(o.revenue_minor),currency:o.currency},evidenceClass:"deterministic"}))}}async function Do(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsBestGuessJourneys:keyset */
543
543
  SELECT ca.id AS association_id, ca.namespace_id, ca.model_version, ca.expires_at, ca.updated_at,
544
544
  ca.left_identity_node_id AS left_node_id, ca.right_identity_node_id AS right_node_id,
545
545
  COALESCE(stats.confirmed_sessions,0)::int AS confirmed_sessions,
@@ -593,7 +593,7 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
593
593
  WHERE ca.site_id=$1 AND n.status='approved' AND ca.status='active'
594
594
  AND ca.confidence_band='high' AND ca.expires_at > now()
595
595
  AND ($2::timestamptz IS NULL OR (ca.updated_at,ca.id) < ($2::timestamptz,$3::uuid))
596
- ORDER BY ca.updated_at DESC, ca.id DESC LIMIT $4`,[e.siteId,i?.at??null,i?.id??null,n+1])).rows.map(o=>({...o,_cursorAt:S(o.updated_at),_cursorId:o.association_id}));return{journeyTier:"candidate_assisted",totalsAreSeparated:!0,...be(e.siteId,s,n,o=>({journeyTier:"candidate_assisted",inferenceRef:O("candidate",e.siteId,o.association_id),confirmedTotals:{sessions:o.confirmed_sessions,events:o.confirmed_events,conversions:o.confirmed_conversions,revenue:o.confirmed_revenue_minor===null?null:{valueMinor:Number(o.confirmed_revenue_minor),currency:o.currency}},inferredIncrementalTotals:{sessions:o.inferred_sessions,events:o.inferred_events,conversions:o.inferred_conversions,revenue:o.inferred_revenue_minor===null?null:{valueMinor:Number(o.inferred_revenue_minor),currency:o.currency}},candidateCount:1,confidenceBand:"high",modelVersion:o.model_version,featureClasses:o.feature_kinds,coverage:o.inferred_sessions>0?"incremental_sessions_available":"no_incremental_sessions",expiresAt:S(o.expires_at),provenance:"consented_high_confidence_candidate_association"}))}}async function Oo(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsInferenceReview:keyset */
596
+ ORDER BY ca.updated_at DESC, ca.id DESC LIMIT $4`,[e.siteId,i?.at??null,i?.id??null,n+1])).rows.map(o=>({...o,_cursorAt:S(o.updated_at),_cursorId:o.association_id}));return{journeyTier:"candidate_assisted",totalsAreSeparated:!0,...be(e.siteId,s,n,o=>({journeyTier:"candidate_assisted",inferenceRef:O("candidate",e.siteId,o.association_id),confirmedTotals:{sessions:o.confirmed_sessions,events:o.confirmed_events,conversions:o.confirmed_conversions,revenue:o.confirmed_revenue_minor===null?null:{valueMinor:Number(o.confirmed_revenue_minor),currency:o.currency}},inferredIncrementalTotals:{sessions:o.inferred_sessions,events:o.inferred_events,conversions:o.inferred_conversions,revenue:o.inferred_revenue_minor===null?null:{valueMinor:Number(o.inferred_revenue_minor),currency:o.currency}},candidateCount:1,confidenceBand:"high",modelVersion:o.model_version,featureClasses:o.feature_kinds,coverage:o.inferred_sessions>0?"incremental_sessions_available":"no_incremental_sessions",expiresAt:S(o.expires_at),provenance:"consented_high_confidence_candidate_association"}))}}async function To(e,t=v()){await Ae(e,t);let n=Ee(e.limit),i=ve(e.siteId,e.cursor),s=(await t.query(`/* analyticsInferenceReview:keyset */
597
597
  SELECT ca.id AS association_id, ca.updated_at, ca.first_observed_at, ca.last_observed_at,
598
598
  ca.expires_at, ca.model_version, ca.confidence_band,
599
599
  COALESCE(array_agg(DISTINCT ce.feature_kind ORDER BY ce.feature_kind)
@@ -608,30 +608,30 @@ import{a as Zt,s as tn}from"./chunk-NC32JCZT.js";import{T as cn,a as de,b as Ne,
608
608
  GROUP BY ca.id
609
609
  ORDER BY ca.updated_at DESC, ca.id DESC LIMIT $4`,[e.siteId,i?.at??null,i?.id??null,n+1])).rows.map(a=>({...a,_cursorAt:S(a.updated_at),_cursorId:a.association_id}));return be(e.siteId,s,n,a=>({inferenceRef:O("candidate",e.siteId,a.association_id),confidenceBand:a.confidence_band,modelVersion:a.model_version,featureClasses:a.feature_kinds,firstObservedAt:S(a.first_observed_at),lastObservedAt:S(a.last_observed_at),expiresAt:S(a.expires_at),action:"diagnostic_only",eligibleForConfirmedMetrics:!1,eligibleForCrmOrActivation:!1}))}import{createHash as zr,createVerify as Yr,verify as Xr}from"crypto";function ei(e){if(!ge(e.timestamp,e.now))return!1;let t=`${e.method.toUpperCase()}${e.url}${e.rawBody}${e.timestamp}`;return ye(e.signature,pe("sha256",e.clientSecret,t))}var Gr=`-----BEGIN PUBLIC KEY-----
610
610
  MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
611
- -----END PUBLIC KEY-----`;function ti(e){try{if(e.ghlSignature&&e.ghlSignature!=="N/A")return Xr(null,Buffer.from(e.rawBody,"utf8"),e.ed25519PublicKey||Gr,Buffer.from(e.ghlSignature,"base64"));if(e.legacySignature&&e.legacySignature!=="N/A"&&e.legacyRsaPublicKey){let t=Yr("SHA256");return t.update(e.rawBody),t.verify(e.legacyRsaPublicKey,e.legacySignature,"base64")}return!1}catch{return!1}}function $t(e){return{schemaVersion:1,eventId:`crm_${zr("sha256").update(`${e.source}:${e.sourceEventId}`).digest("hex").slice(0,24)}`,sourceEventId:e.sourceEventId,source:e.source,sourceAccountRef:e.sourceAccountRef,eventKind:"crm",eventName:"crm_stage_changed",occurredAt:e.occurredAt,visitorId:e.visitorId,sessionId:e.sessionId,personRef:e.contactId,dealId:e.dealId,orderId:e.orderId,valueMinor:e.valueMinor,currency:e.currency,clickIds:e.clickIds,properties:{pipelineId:e.pipelineId||null,stageId:e.stageId,stageName:e.stageName||null,status:e.status}}}function ni(e){let t=e.item,n=p(t.objectId,240)||"unknown",i=p(t.propertyValue,240)||"unknown";return{sourceEventId:`deal:${n}:stage:${i}:${p(t.occurredAt,100)||"unknown"}`,source:"hubspot",sourceAccountRef:e.sourceAccountRef,dealId:n,stageId:i,stageName:e.stageName,occurredAt:B(t.occurredAt),valueMinor:e.valueMinor,currency:e.currency,status:/closed.?won/i.test(i)?"won":/closed.?lost/i.test(i)?"lost":"open"}}function ii(e){let t=e.payload,n=t.opportunity&&typeof t.opportunity=="object"?t.opportunity:t,i=p(n.id??t.id,240)||"unknown",r=p(n.pipelineStageId??t.pipelineStageId,240)||"unknown",s=(p(n.status??t.status,80)||"open").toLowerCase();return{sourceEventId:`opportunity:${i}:stage:${r}:${p(t.timestamp??t.dateAdded,100)||"unknown"}`,source:"highlevel",sourceAccountRef:e.sourceAccountRef,contactId:p(n.contactId??t.contactId,240),dealId:i,pipelineId:p(n.pipelineId??t.pipelineId,240),stageId:r,stageName:p(n.pipelineStageName??t.pipelineStageName,240),occurredAt:B(t.timestamp,t.dateAdded,n.updatedAt),valueMinor:Math.round((W(n.monetaryValue??t.monetaryValue)??0)*100),currency:p(n.currency??t.currency,3)?.toUpperCase(),status:s.includes("won")?"won":s.includes("lost")?"lost":s.includes("spam")?"spam":"open"}}var ts=90;function si(e){let t=e.consent;if(!t)return{necessary:!0,siteAnalytics:!1,enhancedMatching:!1,advertisingMeasurement:!1,receiptId:null,reason:"missing"};if(t.globalPrivacyControl)return{necessary:!0,siteAnalytics:!1,enhancedMatching:!1,advertisingMeasurement:!1,receiptId:t.receiptId??null,reason:"gpc"};let n=t.purposes,i={necessary:!0,siteAnalytics:n.site_analytics==="granted",enhancedMatching:n.enhanced_matching==="granted",advertisingMeasurement:n.advertising_measurement==="granted",receiptId:t.receiptId??null};return{...i,reason:i.siteAnalytics||i.enhancedMatching||i.advertisingMeasurement?"granted":"denied"}}function ns(e){let t=[];return e.confirmedPeople<e.minimumConfirmedPeople&&t.push(`confirmed_people:${e.confirmedPeople}/${e.minimumConfirmedPeople}`),e.positiveOutcomes<e.minimumPositiveOutcomes&&t.push(`positive_outcomes:${e.positiveOutcomes}/${e.minimumPositiveOutcomes}`),e.validatedManifest||t.push("validated_calibrated_manifest"),{...e,eligible:t.length===0,missingEvidence:t}}var is={callrail:{expectedEventTypes:["call"],expectedEventPhases:["pre_call","routing_complete","post_call","call_modified"],signatureMode:"callrail_hmac_sha1_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!0},calltrackingmetrics:{expectedEventTypes:["call"],expectedEventPhases:["call_started","call_answered","call_complete","call_modified"],signatureMode:"ctm_hmac_sha1_time_and_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!1},twilio:{expectedEventTypes:["call_status"],expectedEventPhases:["initiated","ringing","in-progress","completed","busy","failed","no-answer","canceled"],signatureMode:"twilio_sdk_exact_url_and_form_body",freshnessSlaSeconds:86400,supportsReconciliation:!0},hubspot:{expectedEventTypes:["deal.propertyChange"],expectedEventPhases:["dealstage"],signatureMode:"hubspot_v3_hmac_sha256_exact_url_body_timestamp",freshnessSlaSeconds:86400,supportsReconciliation:!1},highlevel:{expectedEventTypes:["OpportunityStageUpdate"],expectedEventPhases:["open","won","lost","spam"],signatureMode:"highlevel_ed25519_or_legacy_rsa",freshnessSlaSeconds:86400,supportsReconciliation:!1},generic_crm:{expectedEventTypes:["crm_stage_changed","transaction","custom_server"],expectedEventPhases:["open","qualified","won","lost","spam"],signatureMode:"xray_hmac_sha256_timestamp_and_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!1}},rs=/(^|_)(api_?key|access_?key|api_?token|auth_?token|token|password|private_?key|secret|signing_?key)($|_)/i;function ss(e){let t=(n,i)=>{if(!(!n||typeof n!="object"))for(let[r,s]of Object.entries(n)){let a=i?`${i}.${r}`:r,o=r.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase();if(rs.test(o)&&!/public_?key/i.test(o))throw new f("analytics_connection_config_contains_credential",`Connection config cannot contain credentials (${a}). Use the encrypted webhook secret or service connection instead.`,400);t(s,a)}};t(e,"")}function Xo(e){return e instanceof Error&&e.message==="webhook_secret_unavailable"?"webhook_secret_unavailable":e instanceof f?e.code.slice(0,80):"invalid_webhook_payload"}function Pt(e){let t=e.provider,n=is[t];if(!n)throw new f("analytics_connection_provider_unavailable","This analytics connection is not available in the current public release.",404);return{callbackPath:`/analytics/v1/webhooks/${t}/${e.connectionId}`,expectedEventTypes:[...n.expectedEventTypes],expectedEventPhases:[...n.expectedEventPhases],signatureMode:n.signatureMode,freshnessSlaSeconds:n.freshnessSlaSeconds,reconciliationCapability:n.supportsReconciliation?e.serviceConnectionRef?"available":"connection_required":"webhook_only"}}function Go(e,t){let n=String(e.id),i=String(e.provider),r=Pt({provider:i,connectionId:n,serviceConnectionRef:typeof e.service_connection_ref=="string"?e.service_connection_ref:null}),s=String(e.readiness??"configured_unverified"),a=e.verification_evidence==="provider"||e.verification_evidence==="synthetic"?e.verification_evidence:null,o=!!e.webhook_secret_configured,c=e.last_event_at?String(e.last_event_at):null,d=s==="live"&&c?Date.now()-Date.parse(c)>r.freshnessSlaSeconds*1e3:!1;return{...e,callbackUrl:new URL(r.callbackPath,`${t.replace(/\/$/,"")}/`).toString(),expectedEventTypes:r.expectedEventTypes,expectedEventPhases:r.expectedEventPhases,signatureMode:r.signatureMode,freshnessSlaSeconds:r.freshnessSlaSeconds,freshness:d?"stale":c?"fresh":"awaiting_first_event",reconciliationCapability:r.reconciliationCapability,lastVerifiedReceipt:e.last_verified_receipt_id?{receiptId:String(e.last_verified_receipt_id),evidence:a,verifiedAt:e.last_verified_at?String(e.last_verified_at):null}:a?{receiptId:null,evidence:a,verifiedAt:e.last_verified_at?String(e.last_verified_at):null}:null,safeError:e.last_error_code?{code:String(e.last_error_code)}:null,setupChecklist:{callbackUrlGenerated:!0,callbackConfigured:a==="provider",signatureConfigured:i==="highlevel"||o,syntheticTestPassed:a==="synthetic"||a==="provider",providerReceiptReceived:a==="provider"},evidenceStillMissing:a==="provider"?[]:["Send a real provider-signed event to the callback URL to mark this connection live."]}}async function Qo(e){let t=Ct.parse(e.definition),n=v();await J(n,e.siteId,e.userId);let i=t.enabled?"active":"disabled";return(await n.query(`INSERT INTO analytics_event_definitions(
611
+ -----END PUBLIC KEY-----`;function ti(e){try{if(e.ghlSignature&&e.ghlSignature!=="N/A")return Xr(null,Buffer.from(e.rawBody,"utf8"),e.ed25519PublicKey||Gr,Buffer.from(e.ghlSignature,"base64"));if(e.legacySignature&&e.legacySignature!=="N/A"&&e.legacyRsaPublicKey){let t=Yr("SHA256");return t.update(e.rawBody),t.verify(e.legacyRsaPublicKey,e.legacySignature,"base64")}return!1}catch{return!1}}function $t(e){return{schemaVersion:1,eventId:`crm_${zr("sha256").update(`${e.source}:${e.sourceEventId}`).digest("hex").slice(0,24)}`,sourceEventId:e.sourceEventId,source:e.source,sourceAccountRef:e.sourceAccountRef,eventKind:"crm",eventName:"crm_stage_changed",occurredAt:e.occurredAt,visitorId:e.visitorId,sessionId:e.sessionId,personRef:e.contactId,dealId:e.dealId,orderId:e.orderId,valueMinor:e.valueMinor,currency:e.currency,clickIds:e.clickIds,properties:{pipelineId:e.pipelineId||null,stageId:e.stageId,stageName:e.stageName||null,status:e.status}}}function ni(e){let t=e.item,n=p(t.objectId,240)||"unknown",i=p(t.propertyValue,240)||"unknown";return{sourceEventId:`deal:${n}:stage:${i}:${p(t.occurredAt,100)||"unknown"}`,source:"hubspot",sourceAccountRef:e.sourceAccountRef,dealId:n,stageId:i,stageName:e.stageName,occurredAt:B(t.occurredAt),valueMinor:e.valueMinor,currency:e.currency,status:/closed.?won/i.test(i)?"won":/closed.?lost/i.test(i)?"lost":"open"}}function ii(e){let t=e.payload,n=t.opportunity&&typeof t.opportunity=="object"?t.opportunity:t,i=p(n.id??t.id,240)||"unknown",r=p(n.pipelineStageId??t.pipelineStageId,240)||"unknown",s=(p(n.status??t.status,80)||"open").toLowerCase();return{sourceEventId:`opportunity:${i}:stage:${r}:${p(t.timestamp??t.dateAdded,100)||"unknown"}`,source:"highlevel",sourceAccountRef:e.sourceAccountRef,contactId:p(n.contactId??t.contactId,240),dealId:i,pipelineId:p(n.pipelineId??t.pipelineId,240),stageId:r,stageName:p(n.pipelineStageName??t.pipelineStageName,240),occurredAt:B(t.timestamp,t.dateAdded,n.updatedAt),valueMinor:Math.round((W(n.monetaryValue??t.monetaryValue)??0)*100),currency:p(n.currency??t.currency,3)?.toUpperCase(),status:s.includes("won")?"won":s.includes("lost")?"lost":s.includes("spam")?"spam":"open"}}var ts=90;function si(e){let t=e.consent;if(!t)return{necessary:!0,siteAnalytics:!1,enhancedMatching:!1,advertisingMeasurement:!1,receiptId:null,reason:"missing"};if(t.globalPrivacyControl)return{necessary:!0,siteAnalytics:!1,enhancedMatching:!1,advertisingMeasurement:!1,receiptId:t.receiptId??null,reason:"gpc"};let n=t.purposes,i={necessary:!0,siteAnalytics:n.site_analytics==="granted",enhancedMatching:n.enhanced_matching==="granted",advertisingMeasurement:n.advertising_measurement==="granted",receiptId:t.receiptId??null};return{...i,reason:i.siteAnalytics||i.enhancedMatching||i.advertisingMeasurement?"granted":"denied"}}function ns(e){let t=[];return e.confirmedPeople<e.minimumConfirmedPeople&&t.push(`confirmed_people:${e.confirmedPeople}/${e.minimumConfirmedPeople}`),e.positiveOutcomes<e.minimumPositiveOutcomes&&t.push(`positive_outcomes:${e.positiveOutcomes}/${e.minimumPositiveOutcomes}`),e.validatedManifest||t.push("validated_calibrated_manifest"),{...e,eligible:t.length===0,missingEvidence:t}}var is={callrail:{expectedEventTypes:["call"],expectedEventPhases:["pre_call","routing_complete","post_call","call_modified"],signatureMode:"callrail_hmac_sha1_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!0},calltrackingmetrics:{expectedEventTypes:["call"],expectedEventPhases:["call_started","call_answered","call_complete","call_modified"],signatureMode:"ctm_hmac_sha1_time_and_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!1},twilio:{expectedEventTypes:["call_status"],expectedEventPhases:["initiated","ringing","in-progress","completed","busy","failed","no-answer","canceled"],signatureMode:"twilio_sdk_exact_url_and_form_body",freshnessSlaSeconds:86400,supportsReconciliation:!0},hubspot:{expectedEventTypes:["deal.propertyChange"],expectedEventPhases:["dealstage"],signatureMode:"hubspot_v3_hmac_sha256_exact_url_body_timestamp",freshnessSlaSeconds:86400,supportsReconciliation:!1},highlevel:{expectedEventTypes:["OpportunityStageUpdate"],expectedEventPhases:["open","won","lost","spam"],signatureMode:"highlevel_ed25519_or_legacy_rsa",freshnessSlaSeconds:86400,supportsReconciliation:!1},generic_crm:{expectedEventTypes:["crm_stage_changed","transaction","custom_server"],expectedEventPhases:["open","qualified","won","lost","spam"],signatureMode:"xray_hmac_sha256_timestamp_and_exact_body",freshnessSlaSeconds:86400,supportsReconciliation:!1}},rs=/(^|_)(api_?key|access_?key|api_?token|auth_?token|token|password|private_?key|secret|signing_?key)($|_)/i;function ss(e){let t=(n,i)=>{if(!(!n||typeof n!="object"))for(let[r,s]of Object.entries(n)){let a=i?`${i}.${r}`:r,o=r.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase();if(rs.test(o)&&!/public_?key/i.test(o))throw new f("analytics_connection_config_contains_credential",`Connection config cannot contain credentials (${a}). Use the encrypted webhook secret or service connection instead.`,400);t(s,a)}};t(e,"")}function Qo(e){return e instanceof Error&&e.message==="webhook_secret_unavailable"?"webhook_secret_unavailable":e instanceof f?e.code.slice(0,80):"invalid_webhook_payload"}function Pt(e){let t=e.provider,n=is[t];if(!n)throw new f("analytics_connection_provider_unavailable","This analytics connection is not available in the current public release.",404);return{callbackPath:`/analytics/v1/webhooks/${t}/${e.connectionId}`,expectedEventTypes:[...n.expectedEventTypes],expectedEventPhases:[...n.expectedEventPhases],signatureMode:n.signatureMode,freshnessSlaSeconds:n.freshnessSlaSeconds,reconciliationCapability:n.supportsReconciliation?e.serviceConnectionRef?"available":"connection_required":"webhook_only"}}function Zo(e,t){let n=String(e.id),i=String(e.provider),r=Pt({provider:i,connectionId:n,serviceConnectionRef:typeof e.service_connection_ref=="string"?e.service_connection_ref:null}),s=String(e.readiness??"configured_unverified"),a=e.verification_evidence==="provider"||e.verification_evidence==="synthetic"?e.verification_evidence:null,o=!!e.webhook_secret_configured,c=e.last_event_at?String(e.last_event_at):null,d=s==="live"&&c?Date.now()-Date.parse(c)>r.freshnessSlaSeconds*1e3:!1;return{...e,callbackUrl:new URL(r.callbackPath,`${t.replace(/\/$/,"")}/`).toString(),expectedEventTypes:r.expectedEventTypes,expectedEventPhases:r.expectedEventPhases,signatureMode:r.signatureMode,freshnessSlaSeconds:r.freshnessSlaSeconds,freshness:d?"stale":c?"fresh":"awaiting_first_event",reconciliationCapability:r.reconciliationCapability,lastVerifiedReceipt:e.last_verified_receipt_id?{receiptId:String(e.last_verified_receipt_id),evidence:a,verifiedAt:e.last_verified_at?String(e.last_verified_at):null}:a?{receiptId:null,evidence:a,verifiedAt:e.last_verified_at?String(e.last_verified_at):null}:null,safeError:e.last_error_code?{code:String(e.last_error_code)}:null,setupChecklist:{callbackUrlGenerated:!0,callbackConfigured:a==="provider",signatureConfigured:i==="highlevel"||o,syntheticTestPassed:a==="synthetic"||a==="provider",providerReceiptReceived:a==="provider"},evidenceStillMissing:a==="provider"?[]:["Send a real provider-signed event to the callback URL to mark this connection live."]}}async function ec(e){let t=At.parse(e.definition),n=v();await J(n,e.siteId,e.userId);let i=t.enabled?"active":"disabled";return(await n.query(`INSERT INTO analytics_event_definitions(
612
612
  id, site_id, name, event_name, trigger_kind, definition, status, created_by_user_id
613
613
  ) VALUES ($1,$2,$3,$4,$5,$6::jsonb,$7,$8)
614
614
  ON CONFLICT(site_id, name) DO UPDATE SET event_name=EXCLUDED.event_name,
615
615
  trigger_kind=EXCLUDED.trigger_kind, definition=EXCLUDED.definition,
616
616
  status=EXCLUDED.status, version=analytics_event_definitions.version+1, updated_at=now()
617
- RETURNING id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at`,[se(),e.siteId,t.name,t.eventName,t.triggerKind,JSON.stringify(t),i,e.userId])).rows[0]}async function Zo(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at
617
+ RETURNING id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at`,[se(),e.siteId,t.name,t.eventName,t.triggerKind,JSON.stringify(t),i,e.userId])).rows[0]}async function tc(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at
618
618
  FROM analytics_event_definitions WHERE site_id=$1 AND status <> 'archived'
619
619
  ORDER BY created_at DESC`,[e])).rows}async function Mt(e){let t=v();e.requireEditor?await J(t,e.siteId,e.userId):await U(t,e.siteId,e.userId);let i=(await t.query(`SELECT id, definition, version, status FROM analytics_event_definitions
620
- WHERE id=$1 AND site_id=$2`,[e.definitionId,e.siteId])).rows[0];if(!i||i.status==="archived")throw new f("analytics_event_definition_not_found","Event definition not found.",404);return{db:t,row:i}}async function ec(e){let{db:t,row:n}=await Mt({...e,requireEditor:!0}),i=Ct.parse({...n.definition,...e.changes}),r=i.enabled?"active":"disabled";return(await t.query(`UPDATE analytics_event_definitions SET
620
+ WHERE id=$1 AND site_id=$2`,[e.definitionId,e.siteId])).rows[0];if(!i||i.status==="archived")throw new f("analytics_event_definition_not_found","Event definition not found.",404);return{db:t,row:i}}async function nc(e){let{db:t,row:n}=await Mt({...e,requireEditor:!0}),i=At.parse({...n.definition,...e.changes}),r=i.enabled?"active":"disabled";return(await t.query(`UPDATE analytics_event_definitions SET
621
621
  name=$3, event_name=$4, trigger_kind=$5, definition=$6::jsonb,
622
622
  status=$7, version=version+1, updated_at=now()
623
623
  WHERE id=$1 AND site_id=$2
624
- RETURNING id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at`,[e.definitionId,e.siteId,i.name,i.eventName,i.triggerKind,JSON.stringify(i),r])).rows[0]}async function tc(e){let t=v();await J(t,e.siteId,e.userId);let n=await t.query(`UPDATE analytics_event_definitions SET status='archived', updated_at=now()
624
+ RETURNING id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at`,[e.definitionId,e.siteId,i.name,i.eventName,i.triggerKind,JSON.stringify(i),r])).rows[0]}async function ic(e){let t=v();await J(t,e.siteId,e.userId);let n=await t.query(`UPDATE analytics_event_definitions SET status='archived', updated_at=now()
625
625
  WHERE id=$1 AND site_id=$2
626
- RETURNING id, status`,[e.definitionId,e.siteId]);if(!n.rows[0])throw new f("analytics_event_definition_not_found","Event definition not found.",404);return n.rows[0]}function as(e,t,n){let i=t.hostnames.length===0||t.hostnames.includes(n.hostname),r=t.triggerKind===n.triggerKind,s=t.triggerKind==="page"?t.pathMatch==="prefix"?n.path.startsWith(t.path??"/"):n.path===t.path:null,a=t.triggerKind==="semantic"?n.tagEventName===t.eventName:null,o=t.triggerKind==="click"||t.triggerKind==="form"?n.selectorMatched===!0:null;return{definitionId:e,eventName:t.eventName,triggerKind:t.triggerKind,matched:t.enabled&&i&&r&&(s??a??o??!1),checks:{hostname:i,triggerKind:r,path:s,tag:a,selector:o}}}async function nc(e){let{row:t}=await Mt({...e,requireEditor:!1});return as(e.definitionId,t.definition,e.preview)}async function ic(e){let{db:t,row:n}=await Mt({...e,requireEditor:!1}),i=Math.max(0,Math.min(15e3,Math.trunc(e.timeoutMs??0))),r=Math.max(1,Math.min(86400,Math.trunc(e.maxAgeSeconds??300))),s=Date.now()+i;do{let o=(await t.query(`SELECT event_id, received_at
626
+ RETURNING id, status`,[e.definitionId,e.siteId]);if(!n.rows[0])throw new f("analytics_event_definition_not_found","Event definition not found.",404);return n.rows[0]}function as(e,t,n){let i=t.hostnames.length===0||t.hostnames.includes(n.hostname),r=t.triggerKind===n.triggerKind,s=t.triggerKind==="page"?t.pathMatch==="prefix"?n.path.startsWith(t.path??"/"):n.path===t.path:null,a=t.triggerKind==="semantic"?n.tagEventName===t.eventName:null,o=t.triggerKind==="click"||t.triggerKind==="form"?n.selectorMatched===!0:null;return{definitionId:e,eventName:t.eventName,triggerKind:t.triggerKind,matched:t.enabled&&i&&r&&(s??a??o??!1),checks:{hostname:i,triggerKind:r,path:s,tag:a,selector:o}}}async function rc(e){let{row:t}=await Mt({...e,requireEditor:!1});return as(e.definitionId,t.definition,e.preview)}async function sc(e){let{db:t,row:n}=await Mt({...e,requireEditor:!1}),i=Math.max(0,Math.min(15e3,Math.trunc(e.timeoutMs??0))),r=Math.max(1,Math.min(86400,Math.trunc(e.maxAgeSeconds??300))),s=Date.now()+i;do{let o=(await t.query(`SELECT event_id, received_at
627
627
  FROM analytics_events
628
628
  WHERE site_id=$1 AND event_definition_id=$2 AND event_definition_version=$3
629
629
  AND received_at >= now() - ($4 * interval '1 second')
630
630
  ORDER BY received_at DESC, id DESC
631
- LIMIT 1`,[e.siteId,e.definitionId,n.version,r])).rows[0];if(o)return{status:"observed_live_match",definitionId:e.definitionId,definitionVersion:n.version,eventId:o.event_id,observedAt:new Date(o.received_at).toISOString(),maxAgeSeconds:r};let c=s-Date.now();if(c<=0)break;await new Promise(d=>setTimeout(d,Math.min(500,c)))}while(Date.now()<=s);return{status:"not_observed",definitionId:e.definitionId,definitionVersion:n.version,eventId:null,observedAt:null,maxAgeSeconds:r}}async function rc(e){let t=await v().query(`SELECT s.owner_user_id, s.id AS site_id, d.id, d.version, d.definition
631
+ LIMIT 1`,[e.siteId,e.definitionId,n.version,r])).rows[0];if(o)return{status:"observed_live_match",definitionId:e.definitionId,definitionVersion:n.version,eventId:o.event_id,observedAt:new Date(o.received_at).toISOString(),maxAgeSeconds:r};let c=s-Date.now();if(c<=0)break;await new Promise(d=>setTimeout(d,Math.min(500,c)))}while(Date.now()<=s);return{status:"not_observed",definitionId:e.definitionId,definitionVersion:n.version,eventId:null,observedAt:null,maxAgeSeconds:r}}async function ac(e){let t=await v().query(`SELECT s.owner_user_id, s.id AS site_id, d.id, d.version, d.definition
632
632
  FROM analytics_pixels p JOIN analytics_sites s ON s.id=p.site_id
633
633
  LEFT JOIN analytics_event_definitions d ON d.site_id=s.id AND d.status='active'
634
- WHERE p.public_id=$1 AND p.status='active'`,[e]);return{ownerUserId:t.rows[0]?Number(t.rows[0].owner_user_id):null,siteId:t.rows[0]?.site_id??null,definitions:t.rows.filter(n=>n.id&&n.version&&n.definition).map(n=>({...n.definition,id:n.id,version:n.version}))}}async function sc(e){ss(e.config??{});let t=v();await J(t,e.siteId,e.userId);let n=e.webhookSecret?de(e.webhookSecret,`connection-secret:${e.provider}:${e.sourceAccountRef}`):null;return(await t.query(`INSERT INTO analytics_connections(
634
+ WHERE p.public_id=$1 AND p.status='active'`,[e]);return{ownerUserId:t.rows[0]?Number(t.rows[0].owner_user_id):null,siteId:t.rows[0]?.site_id??null,definitions:t.rows.filter(n=>n.id&&n.version&&n.definition).map(n=>({...n.definition,id:n.id,version:n.version}))}}async function oc(e){ss(e.config??{});let t=v();await J(t,e.siteId,e.userId);let n=e.webhookSecret?de(e.webhookSecret,`connection-secret:${e.provider}:${e.sourceAccountRef}`):null;return(await t.query(`INSERT INTO analytics_connections(
635
635
  id, site_id, provider, name, source_account_ref, service_connection_ref,
636
636
  secret_ciphertext, config, created_by_user_id
637
637
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9)
@@ -646,17 +646,17 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
646
646
  readiness, last_verified_at, last_event_at, last_reconciled_at, last_error_code,
647
647
  verification_evidence, last_verified_receipt_id,
648
648
  (secret_ciphertext IS NOT NULL) AS webhook_secret_configured,
649
- created_at, updated_at`,[se(),e.siteId,e.provider.trim().toLowerCase().slice(0,80),e.name.trim().slice(0,120),e.sourceAccountRef.trim().slice(0,240),e.serviceConnectionRef?.trim().slice(0,240)||null,n,JSON.stringify(e.config??{}),e.userId])).rows[0]}async function ac(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, site_id, provider, name, source_account_ref, service_connection_ref,
649
+ created_at, updated_at`,[se(),e.siteId,e.provider.trim().toLowerCase().slice(0,80),e.name.trim().slice(0,120),e.sourceAccountRef.trim().slice(0,240),e.serviceConnectionRef?.trim().slice(0,240)||null,n,JSON.stringify(e.config??{}),e.userId])).rows[0]}async function cc(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, site_id, provider, name, source_account_ref, service_connection_ref,
650
650
  readiness, last_verified_at, last_event_at, last_reconciled_at,
651
651
  last_error_code, verification_evidence, last_verified_receipt_id,
652
652
  created_at, updated_at,
653
653
  (secret_ciphertext IS NOT NULL) AS webhook_secret_configured
654
- FROM analytics_connections WHERE site_id = $1 ORDER BY created_at`,[e])).rows}async function oc(e){let n=(await v().query(`SELECT id, site_id, provider, source_account_ref, secret_ciphertext,
654
+ FROM analytics_connections WHERE site_id = $1 ORDER BY created_at`,[e])).rows}async function dc(e){let n=(await v().query(`SELECT id, site_id, provider, source_account_ref, secret_ciphertext,
655
655
  readiness, config
656
656
  FROM analytics_connections WHERE id = $1 AND readiness <> 'disabled'`,[e])).rows[0];if(!n)return null;let i=`connection-secret:${n.provider}:${n.source_account_ref}`;return{id:n.id,siteId:n.site_id,provider:n.provider,sourceAccountRef:n.source_account_ref,secret:n.secret_ciphertext?Ne(n.secret_ciphertext,i):null,readiness:n.readiness,config:n.config||{}}}async function ai(e){let t=v();await J(t,e.siteId,e.userId);let i=(await t.query(`SELECT id, site_id, provider, source_account_ref, service_connection_ref,
657
657
  secret_ciphertext, readiness, config
658
658
  FROM analytics_connections
659
- WHERE id=$1 AND site_id=$2 AND readiness <> 'disabled'`,[e.connectionId,e.siteId])).rows[0];if(!i)throw new f("analytics_connection_not_found","Analytics connection not found.",404);return i}function os(e){return e.secret_ciphertext?Ne(e.secret_ciphertext,`connection-secret:${e.provider}:${e.source_account_ref}`):null}function cs(e){let t=e.now??Date.now(),n=new Date(t).toISOString(),i=e.secret||"xray-ephemeral-synthetic-fixture-secret";if(e.provider==="callrail"){let c={resource_id:"xray-test-call",timestamp:n,answered:!0,duration:30},d=JSON.stringify(c);return{signatureVerified:Jn({rawBody:d,signature:e.tamperSignature?"invalid":kt("sha1",i).update(d).digest("base64"),secret:i,payloadTimestamp:n,now:t}),event:zn({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"post_call"})}}if(e.provider==="calltrackingmetrics"){let c={activity_id:"xray-test-call",timestamp:n,status:"completed"},d=JSON.stringify(c),_=String(Math.floor(t/1e3));return{signatureVerified:Yn({rawBody:d,requestTime:_,signature:e.tamperSignature?"invalid":kt("sha1",i).update(_+d).digest("base64"),secret:i,now:t}),event:Xn({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"call_complete"})}}if(e.provider==="twilio"){let c={CallSid:"CA_XRAY_TEST",CallStatus:"completed",Timestamp:n},d=e.tamperSignature?"invalid":es.getExpectedTwilioSignature(i,e.callbackUrl,c);return{signatureVerified:Gn({authToken:i,signature:d,url:e.callbackUrl,params:c}),event:Qn({params:c,sourceAccountRef:e.sourceAccountRef})}}if(e.provider==="hubspot"){let c={subscriptionType:"deal.propertyChange",propertyName:"dealstage",objectId:"xray-test-deal",propertyValue:"qualified",occurredAt:String(t)},d=JSON.stringify([c]),_=String(t),u=kt("sha256",i).update(`POST${e.callbackUrl}${d}${_}`).digest("base64"),y=e.tamperSignature?"invalid":u;return{signatureVerified:ei({clientSecret:i,signature:y,timestamp:_,method:"POST",url:e.callbackUrl,rawBody:d,now:t}),event:$t(ni({item:c,sourceAccountRef:e.sourceAccountRef}))}}if(e.provider==="highlevel"){let c={timestamp:n,opportunity:{id:"xray-test-opportunity",pipelineStageId:"qualified",status:"open"}},d=JSON.stringify(c),{privateKey:_,publicKey:u}=Qr("ed25519"),y=e.tamperSignature?Buffer.alloc(64).toString("base64"):Zr(null,Buffer.from(d),_).toString("base64");return{signatureVerified:ti({rawBody:d,ghlSignature:y,ed25519PublicKey:u.export({type:"spki",format:"pem"}).toString()}),event:$t(ii({payload:c,sourceAccountRef:e.sourceAccountRef}))}}let r=tt.parse({schemaVersion:1,eventId:"generic_xray_test",sourceEventId:"xray-test-event",source:"generic_crm",sourceAccountRef:e.sourceAccountRef,eventKind:"crm",eventName:"crm_stage_changed",occurredAt:n,dealId:"xray-test-deal",properties:{stageId:"qualified",status:"open"}}),s=JSON.stringify(r),a=String(t),o=an(e.provider,a,s,i);return{signatureVerified:on(e.tamperSignature?`${o.startsWith("0")?"1":"0"}${o.slice(1)}`:o,o),event:r}}async function cc(e){let t=await ai(e),n=os(t);if(t.provider!=="highlevel"&&!n)throw new f("analytics_connection_secret_unavailable","Configure the provider webhook validation secret before running a connection test.",409);let i=Pt({provider:t.provider,connectionId:t.id,serviceConnectionRef:t.service_connection_ref}),r=new URL(i.callbackPath,`${e.requestOrigin.replace(/\/$/,"")}/`).toString(),s=cs({provider:t.provider,sourceAccountRef:t.source_account_ref,callbackUrl:r,secret:n});if(!s.signatureVerified)throw await ri({connectionId:t.id,readiness:"degraded",errorCode:"synthetic_signature_test_failed"}),new f("analytics_connection_test_failed","Connection signature test failed.",409);let a=await ri({connectionId:t.id,readiness:"verified",evidence:"synthetic"}),o=a?.verification_evidence??"synthetic";return{status:a?.readiness??"verified",evidence:o,provider:t.provider,eventType:s.event.eventKind,eventPhase:s.event.eventName,connection:a,evidenceStillMissing:o==="provider"?[]:["A real provider-signed receipt is required before this connection becomes live."]}}async function dc(e){let t=await ai(e),n=Pt({provider:t.provider,connectionId:t.id,serviceConnectionRef:t.service_connection_ref});return{capability:n.reconciliationCapability,started:!1,evidence:null,nextAction:n.reconciliationCapability==="available"?"Reconciliation is available; the reconciliation worker must claim and execute this request.":n.reconciliationCapability==="connection_required"?"Connect the provider read API before reconciliation can run.":"This provider is webhook only; use webhook retries or historical backfill."}}async function lc(e){let t=se(),n=e.rawBody?de(e.rawBody,"webhook-payload"):null,i=await v().query(`INSERT INTO analytics_webhook_receipts(
659
+ WHERE id=$1 AND site_id=$2 AND readiness <> 'disabled'`,[e.connectionId,e.siteId])).rows[0];if(!i)throw new f("analytics_connection_not_found","Analytics connection not found.",404);return i}function os(e){return e.secret_ciphertext?Ne(e.secret_ciphertext,`connection-secret:${e.provider}:${e.source_account_ref}`):null}function cs(e){let t=e.now??Date.now(),n=new Date(t).toISOString(),i=e.secret||"xray-ephemeral-synthetic-fixture-secret";if(e.provider==="callrail"){let c={resource_id:"xray-test-call",timestamp:n,answered:!0,duration:30},d=JSON.stringify(c);return{signatureVerified:Jn({rawBody:d,signature:e.tamperSignature?"invalid":kt("sha1",i).update(d).digest("base64"),secret:i,payloadTimestamp:n,now:t}),event:zn({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"post_call"})}}if(e.provider==="calltrackingmetrics"){let c={activity_id:"xray-test-call",timestamp:n,status:"completed"},d=JSON.stringify(c),_=String(Math.floor(t/1e3));return{signatureVerified:Yn({rawBody:d,requestTime:_,signature:e.tamperSignature?"invalid":kt("sha1",i).update(_+d).digest("base64"),secret:i,now:t}),event:Xn({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"call_complete"})}}if(e.provider==="twilio"){let c={CallSid:"CA_XRAY_TEST",CallStatus:"completed",Timestamp:n},d=e.tamperSignature?"invalid":es.getExpectedTwilioSignature(i,e.callbackUrl,c);return{signatureVerified:Gn({authToken:i,signature:d,url:e.callbackUrl,params:c}),event:Qn({params:c,sourceAccountRef:e.sourceAccountRef})}}if(e.provider==="hubspot"){let c={subscriptionType:"deal.propertyChange",propertyName:"dealstage",objectId:"xray-test-deal",propertyValue:"qualified",occurredAt:String(t)},d=JSON.stringify([c]),_=String(t),u=kt("sha256",i).update(`POST${e.callbackUrl}${d}${_}`).digest("base64"),y=e.tamperSignature?"invalid":u;return{signatureVerified:ei({clientSecret:i,signature:y,timestamp:_,method:"POST",url:e.callbackUrl,rawBody:d,now:t}),event:$t(ni({item:c,sourceAccountRef:e.sourceAccountRef}))}}if(e.provider==="highlevel"){let c={timestamp:n,opportunity:{id:"xray-test-opportunity",pipelineStageId:"qualified",status:"open"}},d=JSON.stringify(c),{privateKey:_,publicKey:u}=Qr("ed25519"),y=e.tamperSignature?Buffer.alloc(64).toString("base64"):Zr(null,Buffer.from(d),_).toString("base64");return{signatureVerified:ti({rawBody:d,ghlSignature:y,ed25519PublicKey:u.export({type:"spki",format:"pem"}).toString()}),event:$t(ii({payload:c,sourceAccountRef:e.sourceAccountRef}))}}let r=Ye.parse({schemaVersion:1,eventId:"generic_xray_test",sourceEventId:"xray-test-event",source:"generic_crm",sourceAccountRef:e.sourceAccountRef,eventKind:"crm",eventName:"crm_stage_changed",occurredAt:n,dealId:"xray-test-deal",properties:{stageId:"qualified",status:"open"}}),s=JSON.stringify(r),a=String(t),o=an(e.provider,a,s,i);return{signatureVerified:on(e.tamperSignature?`${o.startsWith("0")?"1":"0"}${o.slice(1)}`:o,o),event:r}}async function lc(e){let t=await ai(e),n=os(t);if(t.provider!=="highlevel"&&!n)throw new f("analytics_connection_secret_unavailable","Configure the provider webhook validation secret before running a connection test.",409);let i=Pt({provider:t.provider,connectionId:t.id,serviceConnectionRef:t.service_connection_ref}),r=new URL(i.callbackPath,`${e.requestOrigin.replace(/\/$/,"")}/`).toString(),s=cs({provider:t.provider,sourceAccountRef:t.source_account_ref,callbackUrl:r,secret:n});if(!s.signatureVerified)throw await ri({connectionId:t.id,readiness:"degraded",errorCode:"synthetic_signature_test_failed"}),new f("analytics_connection_test_failed","Connection signature test failed.",409);let a=await ri({connectionId:t.id,readiness:"verified",evidence:"synthetic"}),o=a?.verification_evidence??"synthetic";return{status:a?.readiness??"verified",evidence:o,provider:t.provider,eventType:s.event.eventKind,eventPhase:s.event.eventName,connection:a,evidenceStillMissing:o==="provider"?[]:["A real provider-signed receipt is required before this connection becomes live."]}}async function uc(e){let t=await ai(e),n=Pt({provider:t.provider,connectionId:t.id,serviceConnectionRef:t.service_connection_ref});return{capability:n.reconciliationCapability,started:!1,evidence:null,nextAction:n.reconciliationCapability==="available"?"Reconciliation is available; the reconciliation worker must claim and execute this request.":n.reconciliationCapability==="connection_required"?"Connect the provider read API before reconciliation can run.":"This provider is webhook only; use webhook retries or historical backfill."}}async function _c(e){let t=se(),n=e.rawBody?de(e.rawBody,"webhook-payload"):null,i=await v().query(`INSERT INTO analytics_webhook_receipts(
660
660
  id, site_id, connection_id, provider, source_account_ref, source_event_id,
661
661
  signature_status, payload_ciphertext, payload_expires_at
662
662
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,now() + interval '7 days')
@@ -665,7 +665,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
665
665
  WHEN analytics_webhook_receipts.normalization_status = 'accepted' THEN 'replayed'
666
666
  ELSE analytics_webhook_receipts.normalization_status
667
667
  END
668
- RETURNING id, normalization_status`,[t,e.siteId,e.connectionId,e.provider,e.sourceAccountRef,e.sourceEventId,e.signatureStatus,n]);return{id:i.rows[0].id,duplicate:i.rows[0].id!==t,status:i.rows[0].normalization_status}}async function uc(e){await v().query(`UPDATE analytics_webhook_receipts SET
668
+ RETURNING id, normalization_status`,[t,e.siteId,e.connectionId,e.provider,e.sourceAccountRef,e.sourceEventId,e.signatureStatus,n]);return{id:i.rows[0].id,duplicate:i.rows[0].id!==t,status:i.rows[0].normalization_status}}async function mc(e){await v().query(`UPDATE analytics_webhook_receipts SET
669
669
  normalization_status = $2,
670
670
  error_code = $3,
671
671
  normalized_at = now()
@@ -683,7 +683,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
683
683
  updated_at = now()
684
684
  WHERE id = $1
685
685
  RETURNING id, readiness, last_verified_at, last_event_at, last_reconciled_at,
686
- last_error_code, verification_evidence, last_verified_receipt_id`,[e.connectionId,e.readiness,e.errorCode??null,!!e.receipt,!!e.reconciled,e.evidence??null,e.receiptId??null])).rows[0]??null}async function _c(e){let t=Pn.parse(e.rule),n=v();return await J(n,e.siteId,e.userId),(await n.query(`INSERT INTO analytics_conversion_rules(
686
+ last_error_code, verification_evidence, last_verified_receipt_id`,[e.connectionId,e.readiness,e.errorCode??null,!!e.receipt,!!e.reconciled,e.evidence??null,e.receiptId??null])).rows[0]??null}async function pc(e){let t=Sn.parse(e.rule),n=v();return await J(n,e.siteId,e.userId),(await n.query(`INSERT INTO analytics_conversion_rules(
687
687
  id, site_id, name, conversion_kind, condition, default_value_minor,
688
688
  default_currency, status, created_by_user_id
689
689
  ) VALUES ($1,$2,$3,$4,$5::jsonb,$6,$7,$8,$9)
@@ -695,7 +695,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
695
695
  status = EXCLUDED.status,
696
696
  version = analytics_conversion_rules.version + 1,
697
697
  updated_at = now()
698
- RETURNING *`,[se(),e.siteId,t.name,t.conversionKind,JSON.stringify({...t.condition,...t.valueRule?{valueRule:t.valueRule}:{}}),t.defaultValueMinor??null,t.defaultCurrency.toUpperCase(),t.enabled?"active":"disabled",e.userId])).rows[0]}async function mc(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
698
+ RETURNING *`,[se(),e.siteId,t.name,t.conversionKind,JSON.stringify({...t.condition,...t.valueRule?{valueRule:t.valueRule}:{}}),t.defaultValueMinor??null,t.defaultCurrency.toUpperCase(),t.enabled?"active":"disabled",e.userId])).rows[0]}async function yc(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
699
699
  default_currency, version, status, created_at, updated_at
700
700
  FROM analytics_conversion_rules WHERE site_id = $1 AND status <> 'archived'
701
701
  ORDER BY created_at`,[e])).rows.map(r=>{let s=r.condition&&typeof r.condition=="object"?r.condition:{},{valueRule:a,...o}=s;return{...r,condition:o,value_rule:a??null}})}function ds(e){let t=e.properties.tags;return Array.isArray(t)?t.filter(n=>typeof n=="string"):[]}function ls(e,t){let n=[],i=e.condition;i.eventName&&i.eventName!==t.eventName&&n.push("event_name_mismatch"),i.eventKind&&i.eventKind!==t.eventKind&&n.push("event_kind_mismatch"),i.source&&i.source!==t.source&&n.push("source_mismatch"),i.stageId&&i.stageId!==t.properties.stageId&&n.push("stage_mismatch"),i.status&&i.status!==t.properties.status&&n.push("status_mismatch"),i.answered!==void 0&&i.answered!==!!t.properties.answered&&n.push("answered_mismatch"),i.minimumCallDurationSeconds!==void 0&&Number(t.properties.durationSeconds??0)<i.minimumCallDurationSeconds&&n.push("call_too_short");let r=ds(t);return i.excludedTags.some(s=>r.includes(s))&&n.push("excluded_tag"),i.requiredTags.some(s=>!r.includes(s))&&n.push("required_tag_missing"),(t.properties.status==="spam"||r.includes("spam"))&&n.push("spam_excluded"),{matches:n.length===0,reasons:n}}async function us(e,t,n){if(!si(n).enhancedMatching)return{personId:null,namespaceId:null,identityTier:"unlinked"};let s=(await e.query(`SELECT id FROM analytics_identity_namespaces
@@ -718,14 +718,14 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
718
718
  ON r.id=s.latest_receipt_id AND r.site_id=s.site_id
719
719
  WHERE m.site_id=$1 AND m.connection_id::text=$2
720
720
  AND m.provider_person_ref=$3 AND m.person_id::text=$4
721
- LIMIT 1`,[t.siteId,t.context.connectionId,t.context.providerContactId,t.context.expectedPersonId])).rows[0];if(!i)return{personId:null,namespaceId:null,consent:void 0,reason:"mapping_unavailable"};let r,s;try{r=ee(t.context.provider),s=ee(i.connection_provider)}catch{return{personId:null,namespaceId:null,consent:void 0,reason:"provider_mismatch"}}if(r!==s)return{personId:null,namespaceId:null,consent:void 0,reason:"provider_mismatch"};if(!i.receipt_id||!i.effective_at)return{personId:null,namespaceId:null,consent:void 0,reason:"consent_missing"};if(i.action==="withdraw")return{personId:null,namespaceId:null,consent:void 0,reason:"consent_withdrawn"};if(i.gpc||i.action==="gpc")return{personId:null,namespaceId:null,consent:void 0,reason:"consent_gpc"};let a=new Date(t.at??Date.now()).getTime();if(i.expires_at&&new Date(i.expires_at).getTime()<=a)return{personId:null,namespaceId:null,consent:void 0,reason:"consent_expired"};if(!i.enhanced_matching)return{personId:null,namespaceId:null,consent:void 0,reason:"enhanced_matching_denied"};if(!i.advertising_measurement)return{personId:null,namespaceId:null,consent:void 0,reason:"advertising_measurement_denied"};let o=new Date(i.effective_at).toISOString();return{personId:i.person_id,namespaceId:i.namespace_id,reason:"eligible",consent:{analytics:i.site_analytics?"granted":"denied",adUserData:"granted",adPersonalization:"granted",globalPrivacyControl:!1,occurredAt:o,receiptId:i.receipt_id,policyVersion:i.policy_version??void 0,purposes:{site_analytics:i.site_analytics?"granted":"denied",enhanced_matching:"granted",advertising_measurement:"granted"}}}}async function ms(e,t){let n=G(t.eventClickIds),i=await e.query(`SELECT click_ids FROM analytics_attribution_touches
721
+ LIMIT 1`,[t.siteId,t.context.connectionId,t.context.providerContactId,t.context.expectedPersonId])).rows[0];if(!i)return{personId:null,namespaceId:null,consent:void 0,reason:"mapping_unavailable"};let r,s;try{r=te(t.context.provider),s=te(i.connection_provider)}catch{return{personId:null,namespaceId:null,consent:void 0,reason:"provider_mismatch"}}if(r!==s)return{personId:null,namespaceId:null,consent:void 0,reason:"provider_mismatch"};if(!i.receipt_id||!i.effective_at)return{personId:null,namespaceId:null,consent:void 0,reason:"consent_missing"};if(i.action==="withdraw")return{personId:null,namespaceId:null,consent:void 0,reason:"consent_withdrawn"};if(i.gpc||i.action==="gpc")return{personId:null,namespaceId:null,consent:void 0,reason:"consent_gpc"};let a=new Date(t.at??Date.now()).getTime();if(i.expires_at&&new Date(i.expires_at).getTime()<=a)return{personId:null,namespaceId:null,consent:void 0,reason:"consent_expired"};if(!i.enhanced_matching)return{personId:null,namespaceId:null,consent:void 0,reason:"enhanced_matching_denied"};if(!i.advertising_measurement)return{personId:null,namespaceId:null,consent:void 0,reason:"advertising_measurement_denied"};let o=new Date(i.effective_at).toISOString();return{personId:i.person_id,namespaceId:i.namespace_id,reason:"eligible",consent:{analytics:i.site_analytics?"granted":"denied",adUserData:"granted",adPersonalization:"granted",globalPrivacyControl:!1,occurredAt:o,receiptId:i.receipt_id,policyVersion:i.policy_version??void 0,purposes:{site_analytics:i.site_analytics?"granted":"denied",enhanced_matching:"granted",advertising_measurement:"granted"}}}}async function ms(e,t){let n=G(t.eventClickIds),i=await e.query(`SELECT click_ids FROM analytics_attribution_touches
722
722
  WHERE site_id=$1 AND person_id=$2
723
723
  AND occurred_at <= $3::timestamptz
724
724
  AND occurred_at >= $3::timestamptz - ($4::text || ' days')::interval
725
725
  AND click_ids <> '{}'::jsonb
726
726
  ORDER BY occurred_at DESC, id DESC`,[t.siteId,t.personId,t.occurredAt,ts]),r={};for(let s of i.rows)for(let[a,o]of Object.entries(G(s.click_ids)))a in r||(r[a]=o);return{...r,...n}}function ps(e,t){let n=e.valueMinor??Number(t.default_value_minor??0),i=e.valueMinor!==void 0?"dynamic":(t.default_value_minor!==null,"fixed"),r=e.valueMinor!==void 0?"source_event":null,s={mode:e.valueMinor!==void 0?"dynamic":"fixed",source:r,observedAt:e.valueMinor!==void 0?e.occurredAt:null,fallback:!1,ruleVersion:String(t.version),resolution:i,baseValueMinor:n,resolvedValueMinor:n,currency:(e.currency||t.default_currency||"USD").toUpperCase(),linkedEvent:null};return{valueMinor:n,currency:s.currency,provenance:s}}async function ys(e,t){if(!t.rule.value_rule)return ps(t.event,t.rule);let n=t.rule.value_rule.conditionalOverride?.linkedEventName,i=n&&t.personId?(await e.query(`SELECT id, event_name, occurred_at FROM analytics_external_events
727
727
  WHERE site_id=$1 AND person_id=$2 AND event_name=$3 AND id<>$4
728
- ORDER BY occurred_at DESC LIMIT 100`,[t.siteId,t.personId,n,t.insertedEventId])).rows.map(s=>({eventId:s.id,eventName:s.event_name,occurredAt:s.occurred_at.toISOString(),identityTier:"confirmed"})):[],r=t.event.valueMinor===void 0?void 0:{source_event:{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt},crm_field:t.event.source.includes("crm")?{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt}:void 0,transaction:t.event.eventKind==="transaction"?{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt}:void 0};return Ln(t.rule.value_rule,{targetEvent:{eventId:t.insertedEventId,eventName:t.event.eventName,occurredAt:t.event.occurredAt,identityTier:t.personId?"confirmed":"candidate"},linkedEvents:i,observations:r,observedAt:t.event.occurredAt,providerOperation:"new_conversion"})}async function gs(e){if(!e.namespaceId||!e.personId)return[];let t=await e.client.query(`SELECT id, name, score_kind, rules, minimum_score, maximum_score, version
728
+ ORDER BY occurred_at DESC LIMIT 100`,[t.siteId,t.personId,n,t.insertedEventId])).rows.map(s=>({eventId:s.id,eventName:s.event_name,occurredAt:s.occurred_at.toISOString(),identityTier:"confirmed"})):[],r=t.event.valueMinor===void 0?void 0:{source_event:{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt},crm_field:t.event.source.includes("crm")?{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt}:void 0,transaction:t.event.eventKind==="transaction"?{valueMinor:t.event.valueMinor,currency:(t.event.currency||t.rule.default_currency||"USD").toUpperCase(),observedAt:t.event.occurredAt}:void 0};return bn(t.rule.value_rule,{targetEvent:{eventId:t.insertedEventId,eventName:t.event.eventName,occurredAt:t.event.occurredAt,identityTier:t.personId?"confirmed":"candidate"},linkedEvents:i,observations:r,observedAt:t.event.occurredAt,providerOperation:"new_conversion"})}async function gs(e){if(!e.namespaceId||!e.personId)return[];let t=await e.client.query(`SELECT id, name, score_kind, rules, minimum_score, maximum_score, version
729
729
  FROM analytics_score_definitions WHERE site_id=$1 AND status='active'`,[e.siteId]);if(!t.rowCount)return[];let n=await e.client.query(`SELECT id, event_name, event_kind, occurred_at, source, properties
730
730
  FROM analytics_external_events WHERE site_id=$1 AND person_id=$2
731
731
  ORDER BY occurred_at DESC LIMIT 5000`,[e.siteId,e.personId]),i={events:n.rows.map(s=>({ref:s.id,name:s.event_name,occurredAt:s.occurred_at.toISOString()})),pages:n.rows.filter(s=>typeof s.properties.path=="string").map(s=>({ref:s.id,name:String(s.properties.path),occurredAt:s.occurred_at.toISOString()})),sources:n.rows.map(s=>({ref:s.id,name:s.source,occurredAt:s.occurred_at.toISOString()})),calls:n.rows.filter(s=>s.event_kind==="call").map(s=>({ref:s.id,name:String(s.properties.outcome??s.properties.status??s.event_name),occurredAt:s.occurred_at.toISOString()})),crmStages:n.rows.filter(s=>s.event_kind==="crm").map(s=>({ref:s.id,name:String(s.properties.stageId??s.properties.stageName??s.event_name),occurredAt:s.occurred_at.toISOString()}))},r=[];for(let s of t.rows){let a=s.rules&&typeof s.rules=="object"&&!Array.isArray(s.rules)?s.rules:{},o=Array.isArray(s.rules)?s.rules:a.groups;if(!Array.isArray(o)||o.length===0)continue;let c=Array.isArray(a.permittedProperties)?a.permittedProperties.filter(d=>typeof d=="string"):[];try{let d=Bn();Vn({tables:d,id:s.id,definition:{namespaceId:e.namespaceId,name:s.name,kind:s.score_kind,targetObject:"person",minimum:s.minimum_score,maximum:s.maximum_score,groups:o,permittedProperties:c,enabled:!0},now:e.occurredAt});let _=Kn({tables:d,namespaceId:e.namespaceId,scoreId:s.id,subjectRef:e.personId,identityTier:"confirmed",facts:i,now:e.occurredAt});await e.client.query(`INSERT INTO analytics_score_evaluations(
@@ -741,7 +741,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
741
741
  WHERE m.target_id=t.id AND m.status IN ('validated','active')) AS validated_manifest
742
742
  FROM analytics_prediction_targets t
743
743
  JOIN analytics_event_definitions d ON d.id=t.target_event_definition_id
744
- WHERE t.site_id=$1 AND t.namespace_id=$2 AND t.status<>'disabled'`,[e.siteId,e.namespaceId])).rows.map(n=>ns({targetId:n.id,confirmedPeople:Number(n.confirmed_people),positiveOutcomes:Number(n.positive_outcomes),minimumConfirmedPeople:n.minimum_confirmed_people,minimumPositiveOutcomes:n.minimum_positive_outcomes,validatedManifest:n.validated_manifest})):[]}async function oi(e){let t=tt.parse(e.event),n=e.db??v();e.userId!==void 0&&await J(n,e.siteId,e.userId);let i=!e.transactionClient,r=e.transactionClient??await n.connect();try{i&&await r.query("BEGIN");let s=e.trustedCrmContext?await _s(r,{siteId:e.siteId,context:e.trustedCrmContext}):null,a=e.trustedCrmContext?tt.parse({...t,personRef:void 0,consent:s?.consent,properties:{...t.properties,_xrayCrmLinkReason:s?.reason??"mapping_unavailable"}}):t,o=si(a),c=s?.personId&&s.namespaceId?{personId:s.personId,namespaceId:s.namespaceId,identityTier:"confirmed"}:e.trustedCrmContext?{personId:null,namespaceId:null,identityTier:"unlinked"}:await us(r,e.siteId,a),d=c.personId,_=await r.query(`INSERT INTO analytics_external_events(
744
+ WHERE t.site_id=$1 AND t.namespace_id=$2 AND t.status<>'disabled'`,[e.siteId,e.namespaceId])).rows.map(n=>ns({targetId:n.id,confirmedPeople:Number(n.confirmed_people),positiveOutcomes:Number(n.positive_outcomes),minimumConfirmedPeople:n.minimum_confirmed_people,minimumPositiveOutcomes:n.minimum_positive_outcomes,validatedManifest:n.validated_manifest})):[]}async function oi(e){let t=Ye.parse(e.event),n=e.db??v();e.userId!==void 0&&await J(n,e.siteId,e.userId);let i=!e.transactionClient,r=e.transactionClient??await n.connect();try{i&&await r.query("BEGIN");let s=e.trustedCrmContext?await _s(r,{siteId:e.siteId,context:e.trustedCrmContext}):null,a=e.trustedCrmContext?Ye.parse({...t,personRef:void 0,consent:s?.consent,properties:{...t.properties,_xrayCrmLinkReason:s?.reason??"mapping_unavailable"}}):t,o=si(a),c=s?.personId&&s.namespaceId?{personId:s.personId,namespaceId:s.namespaceId,identityTier:"confirmed"}:e.trustedCrmContext?{personId:null,namespaceId:null,identityTier:"unlinked"}:await us(r,e.siteId,a),d=c.personId,_=await r.query(`INSERT INTO analytics_external_events(
745
745
  id, site_id, receipt_id, person_id, source, source_account_ref,
746
746
  source_event_id, event_kind, event_name, occurred_at, visitor_hmac,
747
747
  session_hmac, call_id, deal_id, order_id, value_minor, currency,
@@ -760,7 +760,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
760
760
  WHERE site_id = $1 AND status = 'active' AND readiness IN ('verified','live')`,[e.siteId]),bi=await ms(r,{siteId:e.siteId,personId:d,occurredAt:a.occurredAt,eventClickIds:a.clickIds}),Ai=de(JSON.stringify({eventId:Se.rows[0].id,eventName:A.conversion_kind,eventTime:a.occurredAt,valueMinor:$e,currency:jt,valueProvenance:M.provenance,attributionModelProvenance:{model:typeof a.properties.attributionModel=="string"?a.properties.attributionModel:"unassigned",evidenceTier:"confirmed"},orderId:a.orderId,clickIds:bi,source:a.source,personId:d,identityTier:"confirmed",namespaceId:c.namespaceId,consent:{receiptId:o.receiptId,advertisingMeasurement:!0}}),"activation-payload");for(let Ii of Ei.rows)await r.query(`INSERT INTO analytics_activation_jobs(
761
761
  id, destination_id, conversion_id, person_id, payload_ciphertext
762
762
  ) VALUES ($1,$2,$3,$4,$5)
763
- ON CONFLICT(destination_id, conversion_id) DO NOTHING`,[se(),Ii.id,Se.rows[0].id,d,Ai])}let P=await gs({client:r,siteId:e.siteId,namespaceId:c.namespaceId,personId:d,occurredAt:a.occurredAt}),h=await fs({client:r,siteId:e.siteId,namespaceId:c.namespaceId});d&&await On({siteId:e.siteId,personId:d,canonicalEventId:u,event:a,consent:{...o.receiptId?{receiptId:o.receiptId}:{},siteAnalytics:o.siteAnalytics,advertisingMeasurement:o.advertisingMeasurement},db:r}),i&&await r.query("COMMIT");let L=null,m=typeof a.properties.candidateAssociationId=="string"?a.properties.candidateAssociationId:null,K=typeof a.properties.deterministicEvidenceRef=="string"?a.properties.deterministicEvidenceRef:null,w=a.properties.deterministicEvidenceKind;return d&&c.namespaceId&&m&&K&&["verified_email","verified_phone","crm_contact","signed_linker","authenticated_user"].includes(String(w))&&(L=await qn({siteId:e.siteId,namespaceId:c.namespaceId,associationId:m,personId:d,evidenceKind:w,evidenceRef:K,occurredAt:a.occurredAt}).catch(()=>null)),{id:_.rows[0]?.id??null,created:!!_.rowCount,personId:d,identityTier:c.identityTier,namespaceId:c.namespaceId,conversionIds:b,consentEligibility:o,valueProvenance:V,scoreEvaluationIds:P,predictionEvidence:h,candidatePromotion:L}}catch(s){throw i&&await r.query("ROLLBACK"),s}finally{i&&r.release()}}async function pc(e,t,n){let i=v();if(await U(i,e,t),!(await i.query("SELECT 1 FROM analytics_people WHERE id = $1 AND site_id = $2",[n,e])).rowCount)throw new f("analytics_person_not_found","Attributed person not found.",404);let[s,a,o,c,d]=await Promise.all([i.query(`SELECT id, started_at, last_active_at, ended_at, duration_ms, landing_path,
763
+ ON CONFLICT(destination_id, conversion_id) DO NOTHING`,[se(),Ii.id,Se.rows[0].id,d,Ai])}let P=await gs({client:r,siteId:e.siteId,namespaceId:c.namespaceId,personId:d,occurredAt:a.occurredAt}),h=await fs({client:r,siteId:e.siteId,namespaceId:c.namespaceId});d&&await qn({siteId:e.siteId,personId:d,canonicalEventId:u,event:a,consent:{...o.receiptId?{receiptId:o.receiptId}:{},siteAnalytics:o.siteAnalytics,advertisingMeasurement:o.advertisingMeasurement},db:r}),i&&await r.query("COMMIT");let L=null,m=typeof a.properties.candidateAssociationId=="string"?a.properties.candidateAssociationId:null,K=typeof a.properties.deterministicEvidenceRef=="string"?a.properties.deterministicEvidenceRef:null,w=a.properties.deterministicEvidenceKind;return d&&c.namespaceId&&m&&K&&["verified_email","verified_phone","crm_contact","signed_linker","authenticated_user"].includes(String(w))&&(L=await wn({siteId:e.siteId,namespaceId:c.namespaceId,associationId:m,personId:d,evidenceKind:w,evidenceRef:K,occurredAt:a.occurredAt}).catch(()=>null)),{id:_.rows[0]?.id??null,created:!!_.rowCount,personId:d,identityTier:c.identityTier,namespaceId:c.namespaceId,conversionIds:b,consentEligibility:o,valueProvenance:V,scoreEvaluationIds:P,predictionEvidence:h,candidatePromotion:L}}catch(s){throw i&&await r.query("ROLLBACK"),s}finally{i&&r.release()}}async function gc(e,t,n){let i=v();if(await U(i,e,t),!(await i.query("SELECT 1 FROM analytics_people WHERE id = $1 AND site_id = $2",[n,e])).rowCount)throw new f("analytics_person_not_found","Attributed person not found.",404);let[s,a,o,c,d]=await Promise.all([i.query(`SELECT id, started_at, last_active_at, ended_at, duration_ms, landing_path,
764
764
  exit_path, pageview_count, event_count
765
765
  FROM analytics_sessions WHERE site_id = $1 AND person_id = $2 ORDER BY started_at`,[e,n]),i.query(`SELECT occurred_at, source, medium, campaign, referrer, landing_path
766
766
  FROM analytics_attribution_touches WHERE site_id = $1 AND person_id = $2 ORDER BY occurred_at`,[e,n]),i.query(`SELECT source, event_kind, event_name, occurred_at, value_minor, currency
@@ -769,7 +769,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
769
769
  d.platform, d.name AS destination_name
770
770
  FROM analytics_activation_jobs j
771
771
  JOIN analytics_activation_destinations d ON d.id = j.destination_id
772
- WHERE d.site_id = $1 AND j.person_id = $2 ORDER BY j.created_at`,[e,n])]),_=u=>{if(typeof u!="string"||!u)return null;try{let y=new URL(u);return`${y.origin}${y.pathname}`.slice(0,2e3)}catch{return null}};return{personRef:O("person",e,n),sessions:s.rows.map(u=>({sessionRef:O("session",e,String(u.id)),started_at:u.started_at,last_active_at:u.last_active_at,ended_at:u.ended_at,duration_ms:u.duration_ms,landing_path:u.landing_path,exit_path:u.exit_path,pageview_count:u.pageview_count,event_count:u.event_count})),touches:a.rows.map(u=>({occurred_at:u.occurred_at,source:u.source,medium:u.medium,campaign:u.campaign,referrer:_(u.referrer),landing_path:u.landing_path})),externalEvents:o.rows.map(u=>({source:u.source,event_kind:u.event_kind,event_name:u.event_name,occurred_at:u.occurred_at,value_minor:u.value_minor,currency:u.currency})),conversions:c.rows.map(u=>({conversion_kind:u.conversion_kind,value_minor:u.value_minor,currency:u.currency,occurred_at:u.occurred_at,rule_version:u.rule_version})),deliveries:d.rows.map(u=>({status:u.status,attempts:u.attempts,response_category:u.response_category,created_at:u.created_at,delivered_at:u.delivered_at,platform:u.platform,destination_name:u.destination_name}))}}async function yc(e,t){let n=v();await U(n,e,t);let r=(await n.query(`SELECT
772
+ WHERE d.site_id = $1 AND j.person_id = $2 ORDER BY j.created_at`,[e,n])]),_=u=>{if(typeof u!="string"||!u)return null;try{let y=new URL(u);return`${y.origin}${y.pathname}`.slice(0,2e3)}catch{return null}};return{personRef:O("person",e,n),sessions:s.rows.map(u=>({sessionRef:O("session",e,String(u.id)),started_at:u.started_at,last_active_at:u.last_active_at,ended_at:u.ended_at,duration_ms:u.duration_ms,landing_path:u.landing_path,exit_path:u.exit_path,pageview_count:u.pageview_count,event_count:u.event_count})),touches:a.rows.map(u=>({occurred_at:u.occurred_at,source:u.source,medium:u.medium,campaign:u.campaign,referrer:_(u.referrer),landing_path:u.landing_path})),externalEvents:o.rows.map(u=>({source:u.source,event_kind:u.event_kind,event_name:u.event_name,occurred_at:u.occurred_at,value_minor:u.value_minor,currency:u.currency})),conversions:c.rows.map(u=>({conversion_kind:u.conversion_kind,value_minor:u.value_minor,currency:u.currency,occurred_at:u.occurred_at,rule_version:u.rule_version})),deliveries:d.rows.map(u=>({status:u.status,attempts:u.attempts,response_category:u.response_category,created_at:u.created_at,delivered_at:u.delivered_at,platform:u.platform,destination_name:u.destination_name}))}}async function fc(e,t){let n=v();await U(n,e,t);let r=(await n.query(`SELECT
773
773
  count(*)::int AS total_events,
774
774
  count(*) FILTER (WHERE person_id IS NOT NULL)::int AS identified_events,
775
775
  count(*) FILTER (WHERE click_ids <> '{}'::jsonb)::int AS events_with_click_id,
@@ -817,4 +817,4 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
817
817
  )
818
818
  ORDER BY edge.confidence DESC, edge.last_seen_at DESC
819
819
  LIMIT 1
820
- FOR SHARE OF p, ns, cs, receipt`,[t.siteId,Ce("customer_id",t.stableUserId)])).rows[0]??null}async function Ut(e,t){let n=process.env.MCP_SCRAPER_XRAY_SITE_ID?.trim();if(!n)return{status:"skipped",eventName:Le,reason:"site_not_configured"};if(!vs(n))return{status:"skipped",eventName:Le,reason:"site_id_invalid"};let i=String(e.userId).trim();if(!i||!e.invoiceId.trim()||!Number.isSafeInteger(e.amountPaidMinor)||e.amountPaidMinor<0||!/^[a-z]{3}$/i.test(e.currency)||!Number.isFinite(new Date(e.occurredAt).getTime()))throw new Error("analytics_first_party_outcome_invalid");let r=t??{db:v(),record:(a,o)=>oi({...a,transactionClient:o})},s=await r.db.connect();try{await s.query("BEGIN");let a=await Es(s,{siteId:n,stableUserId:i});if(!a)return await s.query("ROLLBACK"),{status:"skipped",eventName:Le,reason:"identity_or_consent_unavailable"};let o={schemaVersion:1,eventId:`mcp_invoice_${e.invoiceId}`.slice(0,200),sourceEventId:`stripe:invoice:${e.invoiceId}`.slice(0,300),source:"mcp_scraper",sourceAccountRef:"first_party_billing",eventKind:"transaction",eventName:Le,occurredAt:e.occurredAt,personRef:i,orderId:e.invoiceId,valueMinor:e.amountPaidMinor,currency:e.currency.toUpperCase(),consent:{analytics:"granted",adUserData:"granted",adPersonalization:a.advertising_measurement?"granted":"denied",globalPrivacyControl:!1,occurredAt:new Date(a.effective_at).toISOString(),receiptId:a.receipt_id,policyVersion:a.policy_version,purposes:{site_analytics:"granted",enhanced_matching:"granted",advertising_measurement:a.advertising_measurement?"granted":"denied"}},properties:{product:"mcp_scraper",billingKind:"base_plan_paid_invoice",revenueProvenance:"stripe_paid_invoice"}},c=await r.record({siteId:n,event:o},s);return await s.query("COMMIT"),{status:"recorded",eventName:Le,reason:"recorded",created:c.created,conversionIds:c.conversionIds}}catch(a){throw await s.query("ROLLBACK").catch(()=>{}),a}finally{s.release()}}function ci(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}function Ie(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function bs(e){let t=e.subscription;if(t)return Ie(t);let n=e.parent;return Ie(n?.subscription_details?.subscription)}async function As(e,t){let n=await T(e);return n||!t||(n=await ke(t),n&&await Pe(n.id,e)),n}async function Is(e,t,n){let i=t.memory_subscription_id;if(!(!i||i===n))try{let r=await e.subscriptions.retrieve(i);r.status!=="canceled"&&!r.cancel_at_period_end&&await e.subscriptions.update(i,{cancel_at_period_end:!0})}catch(r){console.error("[stripe] could not wind down standalone memory subscription",i,r instanceof Error?r.message:r)}}async function Ft(e,t,n){if(!t.id||t.status!=="paid")return{status:"not_applicable",invoiceId:t.id??null};let i=t.lines.data.some(y=>{let E=ci(y);return!!E&&E in D});if(!Dn(i,t.total))return{status:"not_applicable",invoiceId:t.id};let r=bs(t),a=(r?le(await e.subscriptions.retrieve(r))?.price?.id:void 0)??t.lines.data.map(ci).find(y=>!!y&&y in D),o=a?D[a]:void 0;if(!o)return{status:"not_applicable",invoiceId:t.id};let c=Ie(t.customer);if(!c)throw new Error("Paid subscription invoice has no Stripe customer");let d=await As(c,t.customer_email);if(!d)throw new Error("Paid subscription invoice does not map to an MCP Scraper account");let _=await Wt({invoiceId:t.id,userId:d.id,subscriptionId:r??d.subscription_id,tier:o.tier,concurrency:o.concurrency,creditsMc:o.credits_mc,description:`${o.label} subscription credits`,neverExpires:!!o.credits_never_expire,includedMemoryPlan:o.includes_memory?"pro":null});o.includes_memory&&(await Is(e,d,r??d.subscription_id),await z(d,F({...d,memory_plan:"pro",subscription_tier:o.tier})));let u=await Be(d);u.ok||console.warn("[stripe] scheduled-action credential sync failed:",u.error??"unknown error");try{await Ut({userId:d.id,invoiceId:t.id,amountPaidMinor:t.amount_paid,currency:t.currency,occurredAt:new Date(((t.status_transitions?.paid_at??n)||Math.floor(Date.now()/1e3))*1e3).toISOString()})}catch(y){console.error("[stripe] X-Ray paid outcome failed",{invoiceId:t.id,error:y instanceof Error?y.message:String(y)})}return{status:_.granted?"fulfilled":"already_fulfilled",invoiceId:t.id,userId:d.id,tier:o.tier}}async function di(e,t,n){let i=await e.checkout.sessions.retrieve(t,{expand:["invoice"]});if(i.mode!=="subscription")throw new Error("Checkout session is not a subscription purchase");if(i.payment_status!=="paid"&&i.payment_status!=="no_payment_required")return{status:"not_applicable",invoiceId:Ie(i.invoice)??null};let r=Ie(i.customer);if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=typeof i.invoice=="object"&&i.invoice&&!("deleted"in i.invoice)?i.invoice:await e.invoices.retrieve(Ie(i.invoice)??"");if(!s?.id)throw new Error("Paid subscription checkout has no invoice");return Ft(e,s,i.created)}var li="scale_credit_pack";function rt(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function ui(e){let t=Number(e);if(!Number.isSafeInteger(t)||t<1||t>ut)throw new Error(`quantity must be a whole number from 1 to ${ut}`);return t}function Oc(e){return e.subscription_tier==="scale"}function Dc(e,t){let n=ui(t);return{purchase_kind:li,account_user_id:String(e),eligible_tier:"scale",increment_quantity:String(n),increment_usd:String(he),credits_per_increment:String(lt)}}async function _i(e,t,n){let i=await e.checkout.sessions.retrieve(t);if(i.mode!=="payment"||i.metadata?.purchase_kind!==li)return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};if(i.payment_status!=="paid")return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};let r=rt(i.customer);if(!r)throw new Error("Paid Scale credit-pack checkout has no Stripe customer");if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=ui(i.metadata.increment_quantity),a=s*he*100;if(i.currency!=="usd"||i.amount_subtotal!==a)throw new Error("Scale credit-pack checkout amount does not match the product contract");let o=await e.checkout.sessions.listLineItems(i.id,{limit:2}),c=o.data[0];if(o.data.length!==1||c?.quantity!==s||c.price?.currency!=="usd"||c.price?.unit_amount!==he*100)throw new Error("Scale credit-pack checkout line item does not match the product contract");let d=await T(r);if(!d)throw new Error("Paid Scale credit-pack checkout does not map to an MCP Scraper account");if(i.metadata.account_user_id!==String(d.id)||i.metadata.eligible_tier!=="scale")throw new Error("Scale credit-pack checkout account metadata does not match the billing account");let _=rt(i.payment_intent);if(!_)throw new Error("Paid Scale credit-pack checkout has no payment intent");let u=s*lt;return{status:(await Vt(d.id,s*Qt,Ue.TOPUP,`$${s*he} Scale credit pack (${u.toLocaleString("en-US")} credits)`,`stripe-payment-intent:${_}`,{neverExpires:!1})).duplicate?"already_fulfilled":"fulfilled",paymentIntentId:_,userId:d.id,quantity:s,credits:u}}import Ss from"stripe";import{Hono as hs}from"hono";var x=new Ss(process.env.STRIPE_SECRET_KEY,{apiVersion:"2026-02-25.clover"});async function Ns(e,t){if(!(!e||e===t))try{let n=await x.subscriptions.retrieve(e),i=n.items.data[0]?.price?.id,r=n.status!=="canceled"&&!n.cancel_at_period_end;i&&i in ce&&r&&await x.subscriptions.update(e,{cancel_at_period_end:!0})}catch(n){console.error("[stripe] could not wind down standalone memory subscription",e,n instanceof Error?n.message:n)}}var Cs=new hs;Cs.post("/webhooks",async e=>{let t=e.req.header("stripe-signature"),n=await e.req.text(),i;try{i=x.webhooks.constructEvent(n,t,process.env.STRIPE_WEBHOOK_SECRET)}catch{return e.json({error:"Invalid signature"},400)}try{let r=await qt(i.id,i.type,i.created);return e.json({received:!0,disposition:r})}catch(r){let s=r instanceof Error?r.message:String(r);return console.error("[stripe] webhook enqueue failed",i.id,s),e.json({error:"Webhook enqueue failed"},500)}});async function Wc(e){if(e.type==="checkout.session.completed"||e.type==="checkout.session.async_payment_succeeded"){let t=e.data.object;t.mode==="payment"?await _i(x,t.id):await di(x,t.id);return}if(e.type==="invoice.created"){let t=e.data.object;mi(t)&&t.status==="draft"&&await x.invoices.update(t.id,{description:Xt,footer:Gt,custom_fields:[{name:"Pack benefit",value:"2 browsers per $5 monthly pack"},{name:"Billing cadence",value:"Monthly"}]});return}if(e.type==="invoice.paid"||e.type==="invoice.payment_succeeded"){let t=e.data.object;if(mi(t)){let i=t.customer_email?void 0:await yi(t.customer,void 0),r=t.customer_email??i?.email;if(!r)throw new Error("Paid concurrency invoice has no customer receipt email");await Rs(t.id,r);return}if(t.lines.data.map(gi).find(i=>i&&i in ce))return;await Ft(x,t,e.created)}if(e.type==="customer.subscription.created"||e.type==="customer.subscription.updated"){let t=e.data.object,n=pi(t);if(n){let s=await T(t.customer);if(!s)return;let a=Re(t.status);await st(s.id,a?ws(n):0),await at(s.id,a?t.id:null);return}let i=le(t)?.price?.id??t.items.data[0]?.price?.id;if(i&&i in ce){let s=ce[i],a=await yi(t.customer,t.customer_email);if(a){let o=Re(t.status),c=o?s.plan:"free";await oe(a.id,c,o?t.id:null),await z(a,F({...a,memory_plan:c}))}return}let r=await T(t.customer);if(!r)return;if(i&&i in D){let s=D[i],a=Re(t.status),o=a?s.tier:null;if(await ot(r.id,o,a?s.concurrency:0,a?t.id:null),s.includes_memory){let c=a?"pro":"free";a&&await Ns(r.memory_subscription_id,t.id),await oe(r.id,c,null),await z(r,F({...r,memory_plan:c}))}else r.memory_subscription_id===t.id&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"})));if(a){let c=await Be(r);c.ok||console.warn("[stripe] scheduled-action credential sync failed:",c.error??"unknown error")}}}if(e.type==="customer.subscription.deleted"){let t=e.data.object;if(pi(t)){let i=await T(t.customer);i&&(await st(i.id,0),await at(i.id,null));return}let n=le(t)?.price?.id??t.items.data[0]?.price?.id;if(n&&n in D){let i=D[n],r=await T(t.customer);r&&(await ot(r.id,null,0,null),(i.includes_memory||r.memory_subscription_id===t.id)&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"}))));return}if(n&&n in ce||await ct(t.id)){let i=await ct(t.id)??await T(t.customer);i&&(await oe(i.id,"free",null),await z(i,F({...i,memory_plan:"free"})));return}}}function mi(e){return e.lines.data.some(t=>gi(t)===dt)}async function Rs(e,t){let i=(await x.invoicePayments.list({invoice:e,status:"paid",limit:10})).data.find(a=>a.status==="paid");if(!i)throw new Error("Paid concurrency invoice has no paid Stripe payment");let r;if(i.payment.type==="charge")r=i.payment.charge;else if(i.payment.type==="payment_intent"&&i.payment.payment_intent){let a=typeof i.payment.payment_intent=="string"?i.payment.payment_intent:i.payment.payment_intent.id;r=(await x.paymentIntents.retrieve(a,{expand:["latest_charge"]})).latest_charge}if(!r)throw new Error("Paid concurrency invoice has no receipt-capable charge");let s=typeof r=="string"?await x.charges.retrieve(r):r;s.receipt_email!==t&&await x.charges.update(s.id,{receipt_email:t})}function pi(e){return e.items.data.find(t=>t.price?.id===dt)}function ws(e){let t=e.quantity??1;if(!Number.isSafeInteger(t)||t<1)throw new Error("Stripe concurrency pack quantity must be a positive safe integer");return t}function gi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}async function yi(e,t){let n=await T(e);if(n)return n;if(t)return n=await ke(t),n&&await Pe(n.id,e),n}export{Oi as a,Ts as b,ln as c,gt as d,Fs as e,js as f,_n as g,ji as h,qs as i,Hs as j,qi as k,pn as l,Be as m,Et as n,j as o,le as p,Xs as q,Gs as r,Qs as s,et as t,tt as u,Pn as v,Nr as w,Rr as x,Ct as y,Ja as z,za as A,Ya as B,Xa as C,io as D,qn as E,ia as F,ra as G,sa as H,aa as I,oa as J,ca as K,da as L,la as M,ua as N,_a as O,ma as P,pa as Q,ya as R,vn as S,ga as T,Gi as U,fa as V,ee as W,ze as X,$ as Y,va as Z,er as _,Ia as $,Sa as aa,ha as ba,Cn as ca,Rn as da,Na as ea,Pa as fa,Bn as ga,Vn as ha,oo as ia,co as ja,Kn as ka,_o as la,Jn as ma,zn as na,Yn as oa,Xn as pa,Gn as qa,Qn as ra,it as sa,ho as ta,No as ua,Co as va,Ro as wa,wo as xa,Oo as ya,ei as za,ti as Aa,$t as Ba,ni as Ca,ii as Da,ss as Ea,Xo as Fa,Go as Ga,Qo as Ha,Zo as Ia,ec as Ja,tc as Ka,nc as La,ic as Ma,rc as Na,sc as Oa,ac as Pa,oc as Qa,cc as Ra,dc as Sa,lc as Ta,uc as Ua,ri as Va,_c as Wa,mc as Xa,oi as Ya,pc as Za,yc as _a,Ft as $a,di as ab,ui as bb,Oc as cb,Dc as db,_i as eb,x as fb,Cs as gb,Wc as hb};
820
+ FOR SHARE OF p, ns, cs, receipt`,[t.siteId,Ce("customer_id",t.stableUserId)])).rows[0]??null}async function Ut(e,t){let n=process.env.MCP_SCRAPER_XRAY_SITE_ID?.trim();if(!n)return{status:"skipped",eventName:Le,reason:"site_not_configured"};if(!vs(n))return{status:"skipped",eventName:Le,reason:"site_id_invalid"};let i=String(e.userId).trim();if(!i||!e.invoiceId.trim()||!Number.isSafeInteger(e.amountPaidMinor)||e.amountPaidMinor<0||!/^[a-z]{3}$/i.test(e.currency)||!Number.isFinite(new Date(e.occurredAt).getTime()))throw new Error("analytics_first_party_outcome_invalid");let r=t??{db:v(),record:(a,o)=>oi({...a,transactionClient:o})},s=await r.db.connect();try{await s.query("BEGIN");let a=await Es(s,{siteId:n,stableUserId:i});if(!a)return await s.query("ROLLBACK"),{status:"skipped",eventName:Le,reason:"identity_or_consent_unavailable"};let o={schemaVersion:1,eventId:`mcp_invoice_${e.invoiceId}`.slice(0,200),sourceEventId:`stripe:invoice:${e.invoiceId}`.slice(0,300),source:"mcp_scraper",sourceAccountRef:"first_party_billing",eventKind:"transaction",eventName:Le,occurredAt:e.occurredAt,personRef:i,orderId:e.invoiceId,valueMinor:e.amountPaidMinor,currency:e.currency.toUpperCase(),consent:{analytics:"granted",adUserData:"granted",adPersonalization:a.advertising_measurement?"granted":"denied",globalPrivacyControl:!1,occurredAt:new Date(a.effective_at).toISOString(),receiptId:a.receipt_id,policyVersion:a.policy_version,purposes:{site_analytics:"granted",enhanced_matching:"granted",advertising_measurement:a.advertising_measurement?"granted":"denied"}},properties:{product:"mcp_scraper",billingKind:"base_plan_paid_invoice",revenueProvenance:"stripe_paid_invoice"}},c=await r.record({siteId:n,event:o},s);return await s.query("COMMIT"),{status:"recorded",eventName:Le,reason:"recorded",created:c.created,conversionIds:c.conversionIds}}catch(a){throw await s.query("ROLLBACK").catch(()=>{}),a}finally{s.release()}}function ci(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}function Ie(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function bs(e){let t=e.subscription;if(t)return Ie(t);let n=e.parent;return Ie(n?.subscription_details?.subscription)}async function As(e,t){let n=await T(e);return n||!t||(n=await ke(t),n&&await Pe(n.id,e)),n}async function Is(e,t,n){let i=t.memory_subscription_id;if(!(!i||i===n))try{let r=await e.subscriptions.retrieve(i);r.status!=="canceled"&&!r.cancel_at_period_end&&await e.subscriptions.update(i,{cancel_at_period_end:!0})}catch(r){console.error("[stripe] could not wind down standalone memory subscription",i,r instanceof Error?r.message:r)}}async function Ft(e,t,n){if(!t.id||t.status!=="paid")return{status:"not_applicable",invoiceId:t.id??null};let i=t.lines.data.some(y=>{let E=ci(y);return!!E&&E in D});if(!fn(i,t.total))return{status:"not_applicable",invoiceId:t.id};let r=bs(t),a=(r?le(await e.subscriptions.retrieve(r))?.price?.id:void 0)??t.lines.data.map(ci).find(y=>!!y&&y in D),o=a?D[a]:void 0;if(!o)return{status:"not_applicable",invoiceId:t.id};let c=Ie(t.customer);if(!c)throw new Error("Paid subscription invoice has no Stripe customer");let d=await As(c,t.customer_email);if(!d)throw new Error("Paid subscription invoice does not map to an MCP Scraper account");let _=await Wt({invoiceId:t.id,userId:d.id,subscriptionId:r??d.subscription_id,tier:o.tier,concurrency:o.concurrency,creditsMc:o.credits_mc,description:`${o.label} subscription credits`,neverExpires:!!o.credits_never_expire,includedMemoryPlan:o.includes_memory?"pro":null});o.includes_memory&&(await Is(e,d,r??d.subscription_id),await z(d,F({...d,memory_plan:"pro",subscription_tier:o.tier})));let u=await Be(d);u.ok||console.warn("[stripe] scheduled-action credential sync failed:",u.error??"unknown error");try{await Ut({userId:d.id,invoiceId:t.id,amountPaidMinor:t.amount_paid,currency:t.currency,occurredAt:new Date(((t.status_transitions?.paid_at??n)||Math.floor(Date.now()/1e3))*1e3).toISOString()})}catch(y){console.error("[stripe] X-Ray paid outcome failed",{invoiceId:t.id,error:y instanceof Error?y.message:String(y)})}return{status:_.granted?"fulfilled":"already_fulfilled",invoiceId:t.id,userId:d.id,tier:o.tier}}async function di(e,t,n){let i=await e.checkout.sessions.retrieve(t,{expand:["invoice"]});if(i.mode!=="subscription")throw new Error("Checkout session is not a subscription purchase");if(i.payment_status!=="paid"&&i.payment_status!=="no_payment_required")return{status:"not_applicable",invoiceId:Ie(i.invoice)??null};let r=Ie(i.customer);if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=typeof i.invoice=="object"&&i.invoice&&!("deleted"in i.invoice)?i.invoice:await e.invoices.retrieve(Ie(i.invoice)??"");if(!s?.id)throw new Error("Paid subscription checkout has no invoice");return Ft(e,s,i.created)}var li="scale_credit_pack";function rt(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function ui(e){let t=Number(e);if(!Number.isSafeInteger(t)||t<1||t>ut)throw new Error(`quantity must be a whole number from 1 to ${ut}`);return t}function Tc(e){return e.subscription_tier==="scale"}function xc(e,t){let n=ui(t);return{purchase_kind:li,account_user_id:String(e),eligible_tier:"scale",increment_quantity:String(n),increment_usd:String(he),credits_per_increment:String(lt)}}async function _i(e,t,n){let i=await e.checkout.sessions.retrieve(t);if(i.mode!=="payment"||i.metadata?.purchase_kind!==li)return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};if(i.payment_status!=="paid")return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};let r=rt(i.customer);if(!r)throw new Error("Paid Scale credit-pack checkout has no Stripe customer");if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=ui(i.metadata.increment_quantity),a=s*he*100;if(i.currency!=="usd"||i.amount_subtotal!==a)throw new Error("Scale credit-pack checkout amount does not match the product contract");let o=await e.checkout.sessions.listLineItems(i.id,{limit:2}),c=o.data[0];if(o.data.length!==1||c?.quantity!==s||c.price?.currency!=="usd"||c.price?.unit_amount!==he*100)throw new Error("Scale credit-pack checkout line item does not match the product contract");let d=await T(r);if(!d)throw new Error("Paid Scale credit-pack checkout does not map to an MCP Scraper account");if(i.metadata.account_user_id!==String(d.id)||i.metadata.eligible_tier!=="scale")throw new Error("Scale credit-pack checkout account metadata does not match the billing account");let _=rt(i.payment_intent);if(!_)throw new Error("Paid Scale credit-pack checkout has no payment intent");let u=s*lt;return{status:(await Vt(d.id,s*Qt,Ue.TOPUP,`$${s*he} Scale credit pack (${u.toLocaleString("en-US")} credits)`,`stripe-payment-intent:${_}`,{neverExpires:!1})).duplicate?"already_fulfilled":"fulfilled",paymentIntentId:_,userId:d.id,quantity:s,credits:u}}import Ss from"stripe";import{Hono as hs}from"hono";import{waitUntil as Ns}from"@vercel/functions";var x=new Ss(process.env.STRIPE_SECRET_KEY,{apiVersion:"2026-02-25.clover"});async function Cs(e,t){if(!(!e||e===t))try{let n=await x.subscriptions.retrieve(e),i=n.items.data[0]?.price?.id,r=n.status!=="canceled"&&!n.cancel_at_period_end;i&&i in ce&&r&&await x.subscriptions.update(e,{cancel_at_period_end:!0})}catch(n){console.error("[stripe] could not wind down standalone memory subscription",e,n instanceof Error?n.message:n)}}var Rs=new hs;Rs.post("/webhooks",async e=>{let t=e.req.header("stripe-signature"),n=await e.req.text(),i;try{i=x.webhooks.constructEvent(n,t,process.env.STRIPE_WEBHOOK_SECRET)}catch{return e.json({error:"Invalid signature"},400)}try{let r=await qt(i.id,i.type,i.created);return r==="queued"&&ws(),e.json({received:!0,disposition:r})}catch(r){let s=r instanceof Error?r.message:String(r);return console.error("[stripe] webhook enqueue failed",i.id,s),e.json({error:"Webhook enqueue failed"},500)}});function ws(){let e=import("./stripe-event-worker-AQVRF24K.js").then(({drainStripeEventQueue:t})=>t({limit:10,leaseSeconds:300})).catch(t=>{console.error("[stripe] immediate queue drain failed; the scheduled drain will retry",t instanceof Error?t.message:String(t))});Ns(e)}async function Kc(e){if(e.type==="checkout.session.completed"||e.type==="checkout.session.async_payment_succeeded"){let t=e.data.object;t.mode==="payment"?await _i(x,t.id):await di(x,t.id);return}if(e.type==="invoice.created"){let t=e.data.object;mi(t)&&t.status==="draft"&&await x.invoices.update(t.id,{description:Xt,footer:Gt,custom_fields:[{name:"Pack benefit",value:"2 browsers per $5 monthly pack"},{name:"Billing cadence",value:"Monthly"}]});return}if(e.type==="invoice.paid"||e.type==="invoice.payment_succeeded"){let t=e.data.object;if(mi(t)){let i=t.customer_email?void 0:await yi(t.customer,void 0),r=t.customer_email??i?.email;if(!r)throw new Error("Paid concurrency invoice has no customer receipt email");await Os(t.id,r);return}if(t.lines.data.map(gi).find(i=>i&&i in ce))return;await Ft(x,t,e.created)}if(e.type==="customer.subscription.created"||e.type==="customer.subscription.updated"){let t=e.data.object,n=pi(t);if(n){let s=await T(t.customer);if(!s)return;let a=Re(t.status);await st(s.id,a?Ds(n):0),await at(s.id,a?t.id:null);return}let i=le(t)?.price?.id??t.items.data[0]?.price?.id;if(i&&i in ce){let s=ce[i],a=await yi(t.customer,t.customer_email);if(a){let o=Re(t.status),c=o?s.plan:"free";await oe(a.id,c,o?t.id:null),await z(a,F({...a,memory_plan:c}))}return}let r=await T(t.customer);if(!r)return;if(i&&i in D){let s=D[i],a=Re(t.status),o=a?s.tier:null;if(await ot(r.id,o,a?s.concurrency:0,a?t.id:null),s.includes_memory){let c=a?"pro":"free";a&&await Cs(r.memory_subscription_id,t.id),await oe(r.id,c,null),await z(r,F({...r,memory_plan:c}))}else r.memory_subscription_id===t.id&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"})));if(a){let c=await Be(r);c.ok||console.warn("[stripe] scheduled-action credential sync failed:",c.error??"unknown error")}}}if(e.type==="customer.subscription.deleted"){let t=e.data.object;if(pi(t)){let i=await T(t.customer);i&&(await st(i.id,0),await at(i.id,null));return}let n=le(t)?.price?.id??t.items.data[0]?.price?.id;if(n&&n in D){let i=D[n],r=await T(t.customer);r&&(await ot(r.id,null,0,null),(i.includes_memory||r.memory_subscription_id===t.id)&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"}))));return}if(n&&n in ce||await ct(t.id)){let i=await ct(t.id)??await T(t.customer);i&&(await oe(i.id,"free",null),await z(i,F({...i,memory_plan:"free"})));return}}}function mi(e){return e.lines.data.some(t=>gi(t)===dt)}async function Os(e,t){let i=(await x.invoicePayments.list({invoice:e,status:"paid",limit:10})).data.find(a=>a.status==="paid");if(!i)throw new Error("Paid concurrency invoice has no paid Stripe payment");let r;if(i.payment.type==="charge")r=i.payment.charge;else if(i.payment.type==="payment_intent"&&i.payment.payment_intent){let a=typeof i.payment.payment_intent=="string"?i.payment.payment_intent:i.payment.payment_intent.id;r=(await x.paymentIntents.retrieve(a,{expand:["latest_charge"]})).latest_charge}if(!r)throw new Error("Paid concurrency invoice has no receipt-capable charge");let s=typeof r=="string"?await x.charges.retrieve(r):r;s.receipt_email!==t&&await x.charges.update(s.id,{receipt_email:t})}function pi(e){return e.items.data.find(t=>t.price?.id===dt)}function Ds(e){let t=e.quantity??1;if(!Number.isSafeInteger(t)||t<1)throw new Error("Stripe concurrency pack quantity must be a positive safe integer");return t}function gi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}async function yi(e,t){let n=await T(e);if(n)return n;if(t)return n=await ke(t),n&&await Pe(n.id,e),n}export{Oi as a,Ls as b,ln as c,gt as d,qs as e,Hs as f,_n as g,ji as h,Ws as i,Bs as j,qi as k,pn as l,Be as m,Et as n,j as o,le as p,Qs as q,Zs as r,ea as s,ze as t,Ye as u,Sn as v,dr as w,ur as x,At as y,ua as z,_a as A,ma as B,pa as C,Aa as D,wn as E,Ca as F,Ra as G,wa as H,Oa as I,Da as J,Ta as K,xa as L,La as M,$a as N,ka as O,Pa as P,Ma as Q,Ua as R,Dn as S,Fa as T,gr as U,ja as V,te as W,Ze as X,$ as Y,qa as Z,Er as _,Va as $,Ka as aa,Ja as ba,Un as ca,Fn as da,za as ea,so as fa,Bn as ga,Vn as ha,lo as ia,uo as ja,Kn as ka,po as la,Jn as ma,zn as na,Yn as oa,Xn as pa,Gn as qa,Qn as ra,it as sa,Co as ta,Ro as ua,wo as va,Oo as wa,Do as xa,To as ya,ei as za,ti as Aa,$t as Ba,ni as Ca,ii as Da,ss as Ea,Qo as Fa,Zo as Ga,ec as Ha,tc as Ia,nc as Ja,ic as Ka,rc as La,sc as Ma,ac as Na,oc as Oa,cc as Pa,dc as Qa,lc as Ra,uc as Sa,_c as Ta,mc as Ua,ri as Va,pc as Wa,yc as Xa,oi as Ya,gc as Za,fc as _a,Ft as $a,di as ab,ui as bb,Tc as cb,xc as db,_i as eb,x as fb,Rs as gb,Kc as hb};