mcp-scraper 0.95.2 → 0.96.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +67 -1
  2. package/README.md +21 -3
  3. package/dist/actions-R4EJDLRO.js +1 -0
  4. package/dist/artifacts-4ZDNP2JW.js +1 -0
  5. package/dist/artifacts-N62OPIT5.js +1 -0
  6. package/dist/artifacts-PSADD5OC.js +1 -0
  7. package/dist/artifacts-RUR3OHAK.js +1 -0
  8. package/dist/bin/api-server.js +1 -1
  9. package/dist/bin/mcp-scraper-cli.js +22 -22
  10. package/dist/bin/mcp-scraper-core.js +1 -1
  11. package/dist/bin/mcp-scraper-install.js +1 -1
  12. package/dist/bin/mcp-stdio-server.js +1 -1
  13. package/dist/bin/paa-harvest.js +1 -1
  14. package/dist/blob-store-GIH26EDO.js +1 -0
  15. package/dist/bundle-FCXZMIRB.js +1 -0
  16. package/dist/chunk-24YDQ3EO.js +5 -0
  17. package/dist/chunk-3F7AFM53.js +1 -0
  18. package/dist/chunk-4HZXATHB.js +27 -0
  19. package/dist/chunk-55ZANTHL.js +3 -0
  20. package/dist/chunk-5BKSKLHX.js +1 -0
  21. package/dist/chunk-5LYINW7Z.js +8 -0
  22. package/dist/chunk-63VWBMYR.js +3 -0
  23. package/dist/chunk-6BD75VKS.js +218 -0
  24. package/dist/chunk-6N5EC7ZO.js +1 -0
  25. package/dist/chunk-7POHNTVW.js +1 -0
  26. package/dist/chunk-7SR7MEU5.js +62 -0
  27. package/dist/chunk-7WPCGRD7.js +182 -0
  28. package/dist/chunk-B3JRL45T.js +1 -0
  29. package/dist/chunk-B4ZKPLSP.js +1 -0
  30. package/dist/chunk-BPKTUCV7.js +12 -0
  31. package/dist/chunk-C7MGJUTU.js +1 -0
  32. package/dist/{chunk-W2BVJ7S2.js → chunk-CNSVZTTT.js} +4 -4
  33. package/dist/chunk-CORWWDHL.js +1 -0
  34. package/dist/chunk-CVQUHVHX.js +1 -0
  35. package/dist/chunk-FB4KBB5W.js +16 -0
  36. package/dist/{chunk-Y3Q4FIKK.js → chunk-H6MODA7W.js} +199 -84
  37. package/dist/chunk-HCK6PLM3.js +3 -0
  38. package/dist/chunk-HNNYXMSI.js +1 -0
  39. package/dist/chunk-HUNSEGUN.js +57 -0
  40. package/dist/{chunk-MC4W6TZT.js → chunk-HVQZRQRJ.js} +41 -8
  41. package/dist/chunk-IFPION5D.js +121 -0
  42. package/dist/chunk-IY6ZUUY7.js +173 -0
  43. package/dist/chunk-JHT6A4U6.js +11 -0
  44. package/dist/chunk-JMZIDHYQ.js +2 -0
  45. package/dist/chunk-KXJCGV3H.js +1 -0
  46. package/dist/chunk-MVMWPKRC.js +2 -0
  47. package/dist/chunk-NALXKTUU.js +1 -0
  48. package/dist/chunk-NNOX3FYG.js +198 -0
  49. package/dist/chunk-OILOHQNL.js +2 -0
  50. package/dist/chunk-OLYPLX5C.js +1 -0
  51. package/dist/chunk-QER2ELZP.js +1 -0
  52. package/dist/chunk-RDHGQ2WZ.js +1 -0
  53. package/dist/chunk-RIHI3KH7.js +955 -0
  54. package/dist/chunk-RN4VG3VH.js +4 -0
  55. package/dist/chunk-RYX4FJVH.js +1 -0
  56. package/dist/chunk-SDQW7IJN.js +1 -0
  57. package/dist/{chunk-ENZUJEIM.js → chunk-SE4VKLEC.js} +1 -1
  58. package/dist/chunk-SEZETSB3.js +1 -0
  59. package/dist/chunk-SFUOSJ3A.js +159 -0
  60. package/dist/chunk-UIOSADPB.js +1718 -0
  61. package/dist/{chunk-ZH75KWBI.js → chunk-UNEJYZ4T.js} +1 -1
  62. package/dist/chunk-UXNR3K6I.js +1 -0
  63. package/dist/{chunk-VREXSMC6.js → chunk-VVSHZV5S.js} +5 -5
  64. package/dist/chunk-WNUXMPVX.js +1 -0
  65. package/dist/chunk-WP3QS4CJ.js +1 -0
  66. package/dist/chunk-ZTMQEDIB.js +41 -0
  67. package/dist/contracts-GUXGFCVV.js +1 -0
  68. package/dist/core-schema-423BSTE6.js +936 -0
  69. package/dist/dispatch-P7IY75LH.js +1 -0
  70. package/dist/index.cjs +103 -213
  71. package/dist/index.d.cts +184 -169
  72. package/dist/index.d.ts +184 -169
  73. package/dist/index.js +1 -1
  74. package/dist/media-artifacts-67CJWI7O.js +1 -0
  75. package/dist/metering-ZH2P62IC.js +1 -0
  76. package/dist/migrations-3AKEC5QE.js +1 -0
  77. package/dist/queue-AC4XKD6Z.js +1 -0
  78. package/dist/reconciliation-UZUZ6B74.js +1 -0
  79. package/dist/report-artifact-offload-6OOY2PTM.js +1 -0
  80. package/dist/repository-4EC5EXVN.js +1 -0
  81. package/dist/{location-data-repository-A2QZVP7O.js → repository-CYXVMYAI.js} +1 -1
  82. package/dist/server-DXZ27KQO.js +5825 -0
  83. package/dist/settlement-6CS4JZTY.js +1 -0
  84. package/dist/worker-ATRD6VKM.js +1 -0
  85. package/package.json +2 -2
  86. package/dist/analytics-repository-DZZKDZL6.js +0 -1
  87. package/dist/chunk-6DRKDSXY.js +0 -182
  88. package/dist/chunk-6ND5AFV5.js +0 -27
  89. package/dist/chunk-7XDBGQDY.js +0 -6
  90. package/dist/chunk-7YOXSMHG.js +0 -1565
  91. package/dist/chunk-BLVBUMH5.js +0 -21
  92. package/dist/chunk-EDQ57S4P.js +0 -1
  93. package/dist/chunk-GLTECY3U.js +0 -1282
  94. package/dist/chunk-GPSPSJBJ.js +0 -1
  95. package/dist/chunk-HE45FFBU.js +0 -1
  96. package/dist/chunk-HUV2WTRW.js +0 -1
  97. package/dist/chunk-IXJQHXDC.js +0 -2595
  98. package/dist/chunk-K3D2S36Q.js +0 -16
  99. package/dist/chunk-KFOFU3LA.js +0 -1
  100. package/dist/chunk-LMWU7VPZ.js +0 -63
  101. package/dist/chunk-O4LUUIYG.js +0 -4
  102. package/dist/chunk-OLSW4AN4.js +0 -19
  103. package/dist/chunk-RLFCJGHA.js +0 -100
  104. package/dist/chunk-T4VTJNDZ.js +0 -84
  105. package/dist/chunk-TMB56NCA.js +0 -1
  106. package/dist/chunk-VXOXB3IB.js +0 -1
  107. package/dist/chunk-WO3N5FH2.js +0 -5
  108. package/dist/chunk-WO46LTBW.js +0 -1
  109. package/dist/chunk-XPEJB4BZ.js +0 -1
  110. package/dist/db-CDEZHBRN.js +0 -1
  111. package/dist/extract-bundle-SXC6EWJR.js +0 -26
  112. package/dist/gmail-service-EWR76XE7.js +0 -1
  113. package/dist/lead-list-enrichment-repository-SIWGXWQV.js +0 -1
  114. package/dist/operation-metering-UJ53YX7S.js +0 -1
  115. package/dist/server-QVEKDIDQ.js +0 -5014
  116. package/dist/site-extract-repository-23ND4N77.js +0 -1
  117. package/dist/stripe-event-worker-LPXTITVC.js +0 -1
  118. package/dist/worker-EDN2TJH3.js +0 -1
  119. /package/dist/{chunk-YGBTTW5D.js → chunk-2IATUJO6.js} +0 -0
  120. /package/dist/{chunk-6DTXIZY2.js → chunk-4ZVO6GX4.js} +0 -0
  121. /package/dist/{chunk-XG6GCEUE.js → chunk-U4WIJZCX.js} +0 -0
@@ -1,5 +1,59 @@
1
- import{a as Zt,s as tn}from"./chunk-OLSW4AN4.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-IXJQHXDC.js";import{a as Fe,e as en}from"./chunk-T4VTJNDZ.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{$ as ce,A as zt,E as dt,I as D,J as Yt,S as Xt,T as Gt,U as he,V as lt,W as Qt,X as ut,Z as X,ba as Ue,u as Me,v as Jt}from"./chunk-EDQ57S4P.js";import{Ab as ot,Bb as Wt,Fb as oe,H as qt,Ib as Bt,Jb as ct,Ob as Vt,R as ke,Sb as Kt,T as Ht,t as ae,vb as T,wb as Pe,yb as st,zb as at}from"./chunk-7YOXSMHG.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:`
1
+ import{H as sn,_ as an,c as Yt,j as ut,k as je,m as nn,z as rn}from"./chunk-SFUOSJ3A.js";import{B as gn,a as f,b as v,c as ue,d as Oe,e as yt,f as ln,g as un,h as U,i as $,l as _n,m as mn,n as pn,p as gt,u as B,v as Q,z as yn}from"./chunk-NNOX3FYG.js";import{a as qe}from"./chunk-NALXKTUU.js";import{a as Kt,b as Jt,f as zt}from"./chunk-6BD75VKS.js";import{d as on,g as He,i as We,k as _t,m as mt,o as cn,r as Be,t as dn,u as pt}from"./chunk-2IATUJO6.js";import{D as L,E as Qt,N as Zt,O as en,P as Re,Q as dt,R as tn,S as lt,U as te,W as le,p as Fe,q as Gt,v as Xt,z as ct}from"./chunk-CORWWDHL.js";import{f as Ue}from"./chunk-5LYINW7Z.js";import{a as I}from"./chunk-WNUXMPVX.js";import{randomUUID as Fi}from"crypto";async function fn(e,t,n){return(await I().execute({sql:`INSERT OR IGNORE INTO stripe_events
2
+ (event_id, event_type, stripe_created_at, status, attempt_count, received_at, next_attempt_at, processed_at, updated_at)
3
+ VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,n]})).rowsAffected===1?"queued":"duplicate"}async function ra(e=50,t=300){let n=Math.max(1,Math.min(500,Math.trunc(e))),i=await I().execute({sql:`SELECT event_id
4
+ FROM stripe_events
5
+ WHERE (status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
6
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds'))
7
+ ORDER BY COALESCE(next_attempt_at, received_at), received_at
8
+ LIMIT ?`,args:[t,n]}),r=[];for(let s of i.rows){let a=String(s.event_id),o=Fi();if((await I().execute({sql:`UPDATE stripe_events
9
+ SET status = 'processing', attempt_count = attempt_count + 1,
10
+ claim_token = ?, claimed_at = datetime('now'), last_error = NULL,
11
+ last_error_code = NULL, updated_at = datetime('now')
12
+ WHERE event_id = ?
13
+ AND ((status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
14
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[o,a,t]})).rowsAffected!==1)continue;let l=await I().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[a]});r.push({eventId:a,eventType:l.rows[0]?.event_type!=null?String(l.rows[0].event_type):null,attemptCount:Number(l.rows[0]?.attempt_count??1),token:o})}return r}async function sa(e,t){return(await I().execute({sql:`UPDATE stripe_events
15
+ SET status = 'processed',
16
+ claim_token = NULL,
17
+ claimed_at = NULL,
18
+ next_attempt_at = NULL,
19
+ completed_at = datetime('now'),
20
+ last_error = NULL,
21
+ processed_at = datetime('now'),
22
+ updated_at = datetime('now')
23
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function aa(e,t,n,i,r){return(await I().execute({sql:`UPDATE stripe_events
24
+ SET status = 'retryable',
25
+ claim_token = NULL,
26
+ claimed_at = NULL,
27
+ last_error = ?,
28
+ last_error_code = ?,
29
+ next_attempt_at = datetime('now', '+' || ? || ' seconds'),
30
+ updated_at = datetime('now')
31
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[n.slice(0,500),i.slice(0,100),Math.max(0,Math.trunc(r)),e,t]})).rowsAffected===1}async function oa(e,t,n,i){return(await I().execute({sql:`UPDATE stripe_events
32
+ SET status = 'dead_letter', claim_token = NULL, claimed_at = NULL,
33
+ last_error = ?, last_error_code = ?, next_attempt_at = NULL, updated_at = datetime('now')
34
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[n.slice(0,500),i.slice(0,100),e,t]})).rowsAffected===1}async function ca(){let t=(await I().execute(`
35
+ SELECT
36
+ SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending,
37
+ SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) AS processing,
38
+ SUM(CASE WHEN status = 'retryable' THEN 1 ELSE 0 END) AS retryable,
39
+ SUM(CASE WHEN status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letter,
40
+ MIN(CASE WHEN status IN ('pending', 'retryable') THEN COALESCE(next_attempt_at, received_at) END) AS oldest_due_at
41
+ FROM stripe_events
42
+ `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}import zs from"stripe";import{Hono as Ys}from"hono";import{waitUntil as Gs}from"@vercel/functions";async function P(e){let t=await I().execute({sql:"SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1",args:[e]});return t.rows[0]?ut(t.rows[0]):void 0}async function Ve(e,t){await I().execute({sql:"UPDATE users SET stripe_customer_id = ? WHERE id = ?",args:[t,e]})}async function ft(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("concurrency pack quantity must be a non-negative safe integer");await I().execute({sql:"UPDATE users SET concurrency_pack_quantity = ?, extra_concurrency_slots = ? WHERE id = ?",args:[t,t*2,e]})}async function vt(e,t){await I().execute({sql:"UPDATE users SET concurrency_stripe_sub_id = ? WHERE id = ?",args:[t,e]})}async function Et(e,t,n,i){await I().execute({sql:"UPDATE users SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ? WHERE id = ?",args:[t,Math.max(0,Math.round(n)),i,e]})}async function vn(e){if(!e.invoiceId||e.invoiceId.length>500)throw new Error("invoice id is required and must be bounded");if(!Number.isSafeInteger(e.creditsMc)||e.creditsMc<=0)throw new Error("subscription credit amount must be a positive integer");await Jt(e.userId);let t=I(),n=e.neverExpires?"9999-12-31 23:59:59":null,i=await t.batch([{sql:`INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi)
43
+ VALUES (?, ?, 'subscription', ?, ?)`,args:[e.userId,e.creditsMc,e.description,e.invoiceId]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
44
+ SELECT ?, ?, ?, 'subscription', ?, COALESCE(?, datetime('now', ?)), ?
45
+ WHERE changes() = 1`,args:[e.userId,e.creditsMc,e.creditsMc,e.invoiceId,n,Kt,e.neverExpires?1:0]},{sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[e.creditsMc,e.userId]},{sql:`UPDATE users
46
+ SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ?,
47
+ memory_plan = CASE WHEN ? IS NOT NULL THEN ? ELSE memory_plan END,
48
+ memory_subscription_id = CASE WHEN ? IS NOT NULL THEN NULL ELSE memory_subscription_id END
49
+ WHERE id = ?
50
+ AND EXISTS (
51
+ SELECT 1 FROM ledger
52
+ WHERE stripe_pi = ? AND user_id = ? AND amount_mc = ? AND operation = 'subscription'
53
+ )`,args:[e.tier,Math.max(0,Math.round(e.concurrency)),e.subscriptionId,e.includedMemoryPlan,e.includedMemoryPlan,e.includedMemoryPlan,e.userId,e.invoiceId,e.userId,e.creditsMc]}],"write"),s=(await t.execute({sql:`SELECT l.user_id, l.amount_mc, l.operation, u.balance_mc
54
+ FROM ledger l JOIN users u ON u.id = l.user_id
55
+ WHERE l.stripe_pi = ? LIMIT 1`,args:[e.invoiceId]})).rows[0];if(!s||Number(s.user_id)!==e.userId||Number(s.amount_mc)!==e.creditsMc||String(s.operation)!=="subscription")throw new Error("invoice idempotency key conflicts with an existing grant");return{granted:i[0]?.rowsAffected===1,balance_mc:Number(s.balance_mc??0)}}async function _e(e,t,n){await I().execute({sql:"UPDATE users SET memory_plan = ?, memory_subscription_id = ? WHERE id = ?",args:[t,n,e]})}async function ma(e){let n=(await I().execute({sql:"SELECT memory_provisioned FROM users WHERE id = ?",args:[e]})).rows[0];return Number(n?.memory_provisioned??0)===1}async function En(e,t){await I().execute({sql:"UPDATE users SET memory_provisioned = ? WHERE id = ?",args:[t?1:0,e]})}async function bt(e){let t=await I().execute({sql:"SELECT * FROM users WHERE memory_subscription_id = ? AND active = 1",args:[e]});return t.rows[0]?ut(t.rows[0]):void 0}import{createCipheriv as Ji,createDecipheriv as zi,randomBytes as Yi,scryptSync as Gi}from"crypto";import{setScheduleEntitlementTool as Xi}from"mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";import{createHash as ji,randomUUID as qi}from"crypto";import{exportJWK as Hi,importPKCS8 as Wi,SignJWT as Bi}from"jose";function Vi(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 Ki=Vi(),Ke=null;async function bn(){if(Ke)return Ke;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 Wi(t,"RS256",{extractable:!0}),i=await Hi(n),r={kty:i.kty,n:i.n,e:i.e},s=ji("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",Ke={privateKey:n,publicJwk:r,kid:s},Ke}async function fa(){return(await bn()).publicJwk}async function In(e){let{privateKey:t,kid:n}=await bn();return new Bi({scope:e.scope,plan:e.plan}).setProtectedHeader({alg:"RS256",kid:n}).setIssuer(Ki).setSubject(e.identity).setAudience(e.audience).setIssuedAt().setJti(qi()).setExpirationTime(`${e.ttlSeconds}s`).sign(t)}var Qi=()=>(process.env.MCP_MEMORY_BASE_URL??"https://memory.mcpscraper.dev").replace(/\/$/,""),Zi=()=>(process.env.MCP_MEMORY_RESOURCE_URL??"https://memory.mcpscraper.dev/mcp").replace(/\/$/,""),er=()=>process.env.MCP_MEMORY_ADMIN_KEY?.trim()??"",tr=300;function nr(e){let t=e.split(`
56
+ `).find(i=>i.startsWith("data:")),n=t?t.slice(5).trim():e;return JSON.parse(n)}function It(e){return e?(process.env.MEMORY_OPERATOR_IDENTITIES??"").split(",").map(n=>n.trim().toLowerCase()).filter(Boolean).includes(e.trim().toLowerCase()):!1}function An(){return Gi(qe(),"mcp-memory-key-v1",32)}function Na(e){let t=Yi(12),n=Ji("aes-256-gcm",An(),t),i=Buffer.concat([n.update(e,"utf8"),n.final()]),r=n.getAuthTag();return`${t.toString("base64")}:${r.toString("base64")}:${i.toString("base64")}`}function Ca(e){try{let[t,n,i]=e.split(":"),r=zi("aes-256-gcm",An(),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 Sn(e,t,n){try{let i=await fetch(`${Qi()}/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=nr(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 hn(e){return e.email}function ir(e){return hn(e)}function wa(e){return It(e.email)?"unlimited":e.memory_plan==="pro"||e.memory_plan==="team"?e.memory_plan:"free"}async function Ra(e){try{let{key:t}=await Nn(e);if(!t)return;(await Sn("listVaultsTool",{},t)).ok&&await En(e.id,!0)}catch{}}function rr(e){return e?!!Qt[e]?.includes_memory:!1}function V(e){return e.memory_plan==="team"?"team":rr(e.subscription_tier)||e.memory_plan==="pro"?"pro":"free"}async function Nn(e,t){try{let n=It(e.email),i=n?"unlimited":t??V(e),r=n?"memory.read memory.write memory.admin":"memory.read memory.write";return{key:await In({identity:hn(e),scope:r,plan:i,audience:Zi(),ttlSeconds:tr})}}catch(n){return{key:null,error:n instanceof Error?n.message:"memory service authorization unavailable"}}}async function Z(e,t){let n=It(e.email)?"unlimited":t,{key:i,error:r}=await Nn(e,n);if(!i)return{ok:!1,error:r??"memory unavailable"};let s=await Sn("listVaultsTool",{},i);return{ok:s.ok,error:s.error}}async function Je(e){let t=er();if(!t)return{ok:!1,error:"memory not configured (MCP_MEMORY_ADMIN_KEY missing)"};let n=ir(e),i=await Xi.execute({apiKey:t,granteeIdentity:n,mcpScraperApiKey:e.api_key},{});return{ok:i.ok,error:i.error}}var Cn=["active","trialing","past_due"];function De(e){return Cn.includes(e)}function wn(e,t){for(let n of Cn){let i=e.find(r=>r.status===n&&t(r));if(i)return i}}var sr="price_1TtYPAS8aAcsk3TGHOgrDZiQ";function ar(e=new Date){return`${e.getUTCFullYear()}-${String(e.getUTCMonth()+1).padStart(2,"0")}`}var or=new Set(["connected","needs_reauth"]);function cr(e){return or.has(String(e.lifecycleStatus??""))}async function dr(e,t){let n=await I().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 lr(e,t,n){await sn();let i=Number(e),r=I();return await r.batch([{sql:`
3
57
  INSERT OR IGNORE INTO connected_account_charge_transfers (
4
58
  user_id, period_start, from_connection_id, to_connection_id, provider_config_key
5
59
  )
@@ -50,7 +104,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
50
104
  AND existing.connection_id = ?
51
105
  AND existing.period_start = ?
52
106
  )
53
- `,args:[t,i,n,i,n,t,i,t,n]}],"write"),(await r.execute({sql:"SELECT 1 FROM connected_account_charges WHERE user_id = ? AND connection_id = ? AND period_start = ? LIMIT 1",args:[i,t,n]})).rows.length>0}async function Et(e){let t=await ae().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[Number(e)]});return t.rows[0]?t.rows[0]:null}async function ft(e){await ae().execute({sql:`INSERT INTO connected_account_billing
107
+ `,args:[t,i,n,i,n,t,i,t,n]}],"write"),(await r.execute({sql:"SELECT 1 FROM connected_account_charges WHERE user_id = ? AND connection_id = ? AND period_start = ? LIMIT 1",args:[i,t,n]})).rows.length>0}async function ht(e){let t=await I().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[Number(e)]});return t.rows[0]?t.rows[0]:null}async function At(e){await I().execute({sql:`INSERT INTO connected_account_billing
54
108
  (user_id, stripe_subscription_id, stripe_subscription_item_id, price_id, quantity, status, last_error_code, checked_at, synced_at, updated_at)
55
109
  VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), CASE WHEN ? THEN datetime('now') ELSE NULL END, datetime('now'))
56
110
  ON CONFLICT(user_id) DO UPDATE SET
@@ -62,36 +116,36 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
62
116
  last_error_code = excluded.last_error_code,
63
117
  checked_at = datetime('now'),
64
118
  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 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
119
+ 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 ht(e.userId);if(!t)throw new Error("connected account billing state was not persisted");return t}var K=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 Nt(){let e=process.env.CONNECTED_ACCOUNT_PRICE_ID?.trim();return e||sr||null}function St(e,t){let n=Math.max(0,Math.round(e));return{provider:"nango",billingMode:"flat_recurring_credits",priceId:Nt(),unitAmountCredits:Fe,interval:"month",quantity:n,projectedMonthlyCredits:n*Fe,status:t?.status??"pending",lastErrorCode:t?.last_error_code??null,syncedAt:t?.synced_at??null,usage:Xt.usage}}function me(e){return e.items.data.find(t=>!!t.price?.id&&t.price.id in L)}function Ma(e){return wn(e,t=>!!me(t))}function ur(e){return e instanceof K?e.code:"stripe_connection_billing_failed"}async function ze(e,t,n){await At({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:Nt(),quantity:t,status:n instanceof K&&n.code!=="stripe_connection_billing_failed"?"blocked":"error",lastErrorCode:ur(n),synced:!1})}async function Ua(e,t){let n=[...new Set(t.filter(cr).map(c=>c.connectionId))],i=n.length,r=Nt();if(!r){let c=new K("Connected-account billing is not configured.","connected_account_price_not_configured",503);throw await ze(e,i,c),c}if(!e.subscription_id||!(e.subscription_tier??"")||!Object.values(L).some(c=>c.tier===e.subscription_tier)){if(i===0){let l=await At({userId:e.id,stripeSubscriptionId:null,stripeSubscriptionItemId:null,priceId:r,quantity:0,status:"synced",lastErrorCode:null,synced:!0});return St(0,l)}let c=new K("An active paid plan is required before connected accounts can be billed.","paid_plan_required",403);throw await ze(e,i,c),c}let s=await ht(e.id),a=Math.max(0,s?.quantity??0),o=ar();try{let c=await dr(e.id,o),l=n.filter(d=>!c.has(d));for(let d of l){if(await lr(e.id,d,o))continue;let p=Gt,E=await zt(e.id,p,Ue.CONNECTED_ACCOUNT_FEE,`1 connected account at ${Fe} credits/month (${o})`,`connection-fee:${d}:${o}`);if(!E.ok){let b=new K(`Insufficient credits to connect. Balance: ${te(E.balance_mc)} credits. Connecting requires ${te(p)} credits (${te(p-E.balance_mc)} short). Upgrade your plan or wait for your credits to refresh.`,"insufficient_credits",402,{balanceCredits:te(E.balance_mc),requiredCredits:te(p),shortByCredits:te(Math.max(0,p-E.balance_mc))});throw await ze(e,a,b),b}await I().execute({sql:`INSERT INTO connected_account_charges (user_id, connection_id, period_start, amount_mc)
120
+ VALUES (?, ?, ?, ?) ON CONFLICT(user_id, connection_id, period_start) DO NOTHING`,args:[Number(e.id),d,o,p]}),E.duplicate||await rn(e.id,1)}let _=await At({userId:e.id,stripeSubscriptionId:e.subscription_id,stripeSubscriptionItemId:null,priceId:r,quantity:i,status:"synced",lastErrorCode:null,synced:!0});return St(i,_)}catch(c){throw c instanceof K?c:(await ze(e,a,c),new K("Unable to update connected-account billing.","stripe_connection_billing_failed",503))}}async function Fa(e,t){return St(t,await ht(e))}import{createHash as Bc,createHmac as jt,generateKeyPairSync as Ss,randomUUID as de,sign as hs}from"crypto";import Ns from"twilio";import{z as u}from"zod";import{z as R}from"zod";var _r=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"]),Te=R.string().trim().length(3).transform(e=>e.toUpperCase()).refine(e=>_r.has(e),"Provide a valid ISO-4217 currency."),Ye=R.number().int("Money must be represented as integer minor units.").min(0,"Money cannot be negative.").max(Number.MAX_SAFE_INTEGER),Ge=R.string().trim().min(1).max(80).default("1"),mr=R.enum(["semantic_markup","source_event","crm_field","transaction"]),pr=R.object({mode:R.literal("none"),ruleVersion:Ge}).strict(),yr=R.object({mode:R.literal("fixed"),valueMinor:Ye,currency:Te,ruleVersion:Ge}).strict(),gr=R.object({mode:R.literal("dynamic"),source:mr,currency:Te,fallbackValueMinor:Ye.nullable().default(null),ruleVersion:Ge}).strict(),Rn=R.discriminatedUnion("mode",[pr,yr,gr]),fr=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:Ye,currency:Te}).strict(),Xe=R.object({targetEventName:R.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),base:Rn,conditionalOverride:fr.nullable().default(null),ruleVersion:Ge}).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 vr(e,t){let n=Ye.parse(e.valueMinor),i=On(t,e.currency);return ne(e.observedAt,"observedAt"),{valueMinor:n,currency:i,observedAt:new Date(e.observedAt).toISOString()}}function Er(e){return Rn.parse(e)}function On(e,t){let i=(Array.isArray(e)?e:[e,t]).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>Te.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 br(e,t={}){let n=Er(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=vr(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 Ir(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 Dn(e,t){let n=Xe.parse(e);if(t.targetEvent.eventName!==n.targetEventName)throw new Error(`Value rule targets ${n.targetEventName}, not ${t.targetEvent.eventName}.`);let i=br({...n.base,ruleVersion:n.ruleVersion},t);if(!n.conditionalOverride)return i;let r=Ir(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?On(i.currency,n.conditionalOverride.currency):Te.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 Tn=u.object({gclid:u.string().trim().max(500).optional(),gbraid:u.string().trim().max(500).optional(),wbraid:u.string().trim().max(500).optional(),fbclid:u.string().trim().max(500).optional(),fbp:u.string().trim().max(500).optional(),fbc:u.string().trim().max(500).optional(),ttclid:u.string().trim().max(500).optional(),rdt_cid:u.string().trim().max(500).optional(),msclkid:u.string().trim().max(500).optional(),li_fat_id:u.string().trim().max(500).optional(),snapclid:u.string().trim().max(500).optional()}).strict(),Ar=u.object({site_analytics:u.enum(["granted","denied","unknown"]),enhanced_matching:u.enum(["granted","denied","unknown"]),advertising_measurement:u.enum(["granted","denied","unknown"])}).strict(),Sr=u.object({analytics:u.enum(["granted","denied","unknown"]).default("unknown"),adUserData:u.enum(["granted","denied","unknown"]).default("unknown"),adPersonalization:u.enum(["granted","denied","unknown"]).default("unknown"),globalPrivacyControl:u.boolean().default(!1),occurredAt:u.string().datetime(),receiptId:u.string().uuid().optional(),policyVersion:u.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}})),xn=u.enum(["browser","form","call","crm","transaction","custom_server","conversion","delivery"]),hr=u.object({schemaVersion:u.literal(1).default(1),eventId:u.string().trim().min(8).max(200),sourceEventId:u.string().trim().min(1).max(300).optional(),source:u.string().trim().min(1).max(80).default("xray"),sourceAccountRef:u.string().trim().max(240).optional(),eventKind:xn,eventName:u.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),occurredAt:u.string().datetime(),visitorId:u.string().trim().max(160).optional(),sessionId:u.string().trim().max(160).optional(),personRef:u.string().trim().max(240).optional(),orderId:u.string().trim().max(240).optional(),callId:u.string().trim().max(240).optional(),dealId:u.string().trim().max(240).optional(),path:u.string().trim().max(2e3).optional(),canonicalUrl:u.string().url().max(3e3).optional(),sourceName:u.string().trim().max(180).optional(),medium:u.string().trim().max(180).optional(),campaign:u.string().trim().max(240).optional(),clickIds:Tn.optional(),consent:Sr.optional(),valueMinor:u.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:u.string().trim().regex(/^[A-Za-z]{3}$/).optional(),properties:u.record(u.string().max(80),u.unknown()).default({})}).strict(),Qe=hr.extend({sourceEventId:u.string().trim().min(1).max(300),source:u.string().trim().min(1).max(80),sourceAccountRef:u.string().trim().min(1).max(240)}),Va=u.object({sourceEventId:u.string().trim().min(1).max(300),source:u.string().trim().min(1).max(80),sourceAccountRef:u.string().trim().min(1).max(240),contactId:u.string().trim().max(240).optional(),dealId:u.string().trim().min(1).max(240),pipelineId:u.string().trim().max(240).optional(),stageId:u.string().trim().min(1).max(240),stageName:u.string().trim().max(240).optional(),occurredAt:u.string().datetime(),valueMinor:u.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),currency:u.string().trim().regex(/^[A-Za-z]{3}$/).optional(),visitorId:u.string().trim().max(160).optional(),sessionId:u.string().trim().max(160).optional(),clickIds:Tn.optional(),email:u.string().email().max(320).optional(),phone:u.string().trim().max(80).optional(),orderId:u.string().trim().max(240).optional(),status:u.enum(["open","won","lost","spam","unknown"]).default("unknown")}).strict(),Nr=u.object({eventName:u.string().regex(/^[a-z][a-z0-9_]{1,79}$/).optional(),eventKind:xn.optional(),source:u.string().trim().max(80).optional(),stageId:u.string().trim().max(240).optional(),status:u.enum(["open","won","lost","spam","unknown"]).optional(),answered:u.boolean().optional(),minimumCallDurationSeconds:u.number().int().min(0).max(86400).optional(),excludedTags:u.array(u.string().trim().max(80)).max(30).default([]),requiredTags:u.array(u.string().trim().max(80)).max(30).default([])}).strict(),Ln=u.object({name:u.string().trim().min(1).max(120),conversionKind:u.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),condition:Nr,defaultValueMinor:u.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),defaultCurrency:u.string().trim().regex(/^[A-Za-z]{3}$/).default("USD"),valueRule:Xe.optional(),enabled:u.boolean().default(!0)}).strict();function Cr(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 wr=u.string().trim().max(253).transform(Cr).refine(Boolean,"Provide a valid bare hostname."),xe=u.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=u.object({value:u.number().finite().min(0).max(1e12).optional(),currency:u.string().trim().regex(/^[A-Za-z]{3}$/).transform(e=>e.toUpperCase()).optional(),orderId:u.string().trim().min(1).max(200).optional(),contentId:u.string().trim().min(1).max(200).optional(),contentType:u.string().trim().min(1).max(80).optional(),placement:xe.optional(),component:xe.optional(),action:xe.optional(),destination:xe.optional(),plan:xe.optional()}).strict(),Ct=u.object({name:u.string().trim().min(1).max(120),eventName:u.string().trim().regex(/^[a-z][a-z0-9_]{1,79}$/),triggerKind:u.enum(["page","click","form","semantic"]),path:u.string().trim().startsWith("/").max(2e3).optional(),pathMatch:u.enum(["exact","prefix"]).default("exact"),selector:u.string().trim().min(1).max(500).optional(),hostnames:u.array(wr).max(25).transform(e=>[...new Set(e)]).default([]),metadata:Rr.optional(),valueRule:Xe.optional(),oncePerSession:u.boolean().default(!1),enabled:u.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 Or,randomUUID as wt}from"crypto";import io from"ipaddr.js";import{randomUUID as $n}from"crypto";async function Ga(e){return(await v().query(`SELECT id, site_id, name, status, version, approved_at
67
121
  FROM analytics_identity_namespaces
68
122
  WHERE site_id=$1 AND status IN ('draft','approved','disabled')
69
123
  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
124
+ 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 kn={domain:"host",application:"server",phone:"call",crm:"crm"},Pn={host:"domain",server:"application",call:"phone",crm:"crm"};function Mn(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 Xa(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
125
  FROM analytics_identity_namespaces
72
126
  WHERE site_id=$1 AND status IN ('draft','approved','disabled')
73
127
  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
128
  id, site_id, name, status, approved_hosts, approved_sources, version, approved_by_user_id
75
129
  ) 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)
130
+ RETURNING id, site_id, name, status, version, approved_at`,[$n(),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 Qa(e){let t=Mn(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
131
+ 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=kn[e.sourceKind],s=await n.query(`INSERT INTO analytics_identity_sources(id, namespace_id, site_id, source_kind, source_ref, status)
78
132
  VALUES ($1,$2,$3,$4,$5,'approved')
79
133
  ON CONFLICT(namespace_id, source_kind, source_ref) DO UPDATE
80
134
  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
135
+ RETURNING id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at`,[$n(),e.namespaceId,e.siteId,r,t]);await n.query(`UPDATE analytics_identity_namespaces
82
136
  SET status='approved', approved_by_user_id=$3, approved_at=COALESCE(approved_at, now()),
83
137
  approved_hosts=CASE WHEN $4='host'
84
138
  THEN (SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_hosts || to_jsonb($5::text)) value)
85
139
  ELSE approved_hosts END,
86
140
  approved_sources=(SELECT jsonb_agg(DISTINCT value) FROM jsonb_array_elements_text(approved_sources || to_jsonb(($4 || ':' || $5)::text)) value),
87
141
  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
142
+ 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:Pn[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 Ze(e){let t=v();if(!(await t.query(`SELECT id FROM analytics_identity_namespaces
89
143
  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
144
+ 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=Mn(e.source.kind,e.source.ref);if(!(await t.query(`SELECT id FROM analytics_identity_sources
145
+ WHERE namespace_id=$1 AND site_id=$2 AND source_kind=$3 AND source_ref=$4 AND status='approved'`,[e.namespaceId,e.siteId,kn[e.source.kind],r])).rows[0])throw new f("analytics_namespace_source_unapproved","This identity source is not approved.",403)}}async function Za(e){return await Ze(e),(await v().query(`SELECT id, namespace_id, site_id, source_kind, source_ref, status, created_at, revoked_at
92
146
  FROM analytics_identity_sources
93
147
  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,
148
+ 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:Pn[n.source_kind],sourceRef:n.source_ref,status:n.status,createdAt:n.created_at.toISOString(),revokedAt:n.revoked_at?.toISOString()??null}))}function Dr(){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 Rt(e,t){return Or("sha256",Dr()).update(`xray-candidate:v1:${e}:${t}`).digest("hex")}async function oo(e){await Ze(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
149
  array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution > 0), NULL) supporting,
96
150
  array_remove(array_agg(DISTINCT e.feature_kind) FILTER (WHERE e.contribution < 0), NULL) conflicting
97
151
  FROM analytics_candidate_associations a
@@ -99,7 +153,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
99
153
  WHERE a.site_id=$1 AND a.namespace_id=$2 AND a.status='active' AND a.confidence_band='medium'
100
154
  AND a.expires_at > $3::timestamptz
101
155
  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
156
+ 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 Un(e){await Ze({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=Rt("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
157
  SET status='promoted', promoted_person_id=$4, promoted_at=$5, updated_at=now()
104
158
  WHERE id=$1 AND site_id=$2 AND namespace_id=$3
105
159
  AND (status IN ('active','expired') OR (status='promoted' AND promoted_person_id=$4))
@@ -107,41 +161,41 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
107
161
  id, site_id, namespace_id, association_id, person_id, evidence_kind,
108
162
  evidence_ref_hmac, promoted_by, promoted_by_user_id, promoted_at
109
163
  ) 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(
164
+ ON CONFLICT(association_id, person_id) DO NOTHING`,[wt(),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
165
  id, site_id, namespace_ref, subject_ref, action, idempotency_key,
112
166
  actor_user_id, result_code, affected_counts, completed_at
113
167
  ) 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(
168
+ ON CONFLICT(site_id, idempotency_key) DO NOTHING`,[wt(),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
169
  id,site_id,namespace_id,canonical_person_id,canonical_person_ref_hmac,
116
170
  evidence_kind,evidence_ref_hmac,prior_person_ids,prior_identity_node_ids,
117
171
  candidate_association_ids,affected_history_counts,schema_version,idempotency_key,promoted_at
118
172
  ) VALUES($1,$2,$3,$4,$5,$6,$7,'{}'::uuid[],$8::uuid[],$9::uuid[],$10::jsonb,
119
173
  '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(
174
+ ON CONFLICT(site_id,idempotency_key) DO NOTHING`,[wt(),e.siteId,e.namespaceId,e.personId,Rt("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}),Rt("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 zr}from"crypto";import{z}from"zod";import{createHash as Tr,randomUUID as ie}from"crypto";function S(e){return e??v()}function et(e){return Tr("sha256").update(JSON.stringify(e)).digest("hex")}async function re(e){let t=await S(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 po(e){let t=on.parse(e.capability),n=S(e.db),i=await re({siteId:e.siteId,connectionId:e.connectionId,db:n});await n.query(`INSERT INTO analytics_crm_connection_capabilities(
121
175
  site_id,connection_id,provider,contract_version,mode,schema_fingerprint,allowed_operations,evidence,verified_at,updated_at
122
176
  ) VALUES($1,$2,$3,1,$4,$5,$6::jsonb,$7::jsonb,$8,now())
123
177
  ON CONFLICT(connection_id,contract_version) DO UPDATE SET
124
178
  mode=EXCLUDED.mode,schema_fingerprint=EXCLUDED.schema_fingerprint,
125
179
  allowed_operations=EXCLUDED.allowed_operations,evidence=EXCLUDED.evidence,
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(
180
+ 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 yo(e){let t=He.parse(e.plan),n=S(e.db),i=await re({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:He.parse(r.rows[0].plan),reused:!0}}return await n.query(`INSERT INTO analytics_crm_provisioning_plans(
127
181
  id,site_id,connection_id,provider,contract_version,tenant_schema_version,plan,status,
128
182
  created_by_user_id,public_plan_id,schema_fingerprint,request_fingerprint,created_at,updated_at
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
183
+ ) VALUES($1,$2,$3,$4,1,$5,$6::jsonb,'preview',$7,$8,$9,$10,$11,$11)`,[ie(),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 go(e){let t=await S(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 He.parse(t.rows[0].plan)}async function fo(e){let t=We.parse(e.receipt),n=S(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
130
184
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
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(
185
+ WHERE p.site_id=$1 AND r.public_receipt_id=$2`,[e.siteId,t.receiptId]);if(r.rowCount&&We.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(
132
186
  id,plan_id,operation,status,safe_error_code,warnings,created_at,public_receipt_id,receipt
133
187
  ) VALUES($1,$2,$3,$4,$5,'[]'::jsonb,$6,$7,$8::jsonb)
134
188
  ON CONFLICT (public_receipt_id) WHERE public_receipt_id IS NOT NULL
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
189
+ DO UPDATE SET operation=EXCLUDED.operation,status=EXCLUDED.status,safe_error_code=EXCLUDED.safe_error_code,receipt=EXCLUDED.receipt`,[ie(),i.rows[0].id,s,a,t.errorCode??null,t.occurredAt,t.receiptId,JSON.stringify(t)]),await n.query(`UPDATE analytics_crm_provisioning_plans
136
190
  SET status=$3,approved_by_user_id=$4,approved_at=COALESCE(approved_at,$5),
137
191
  approved_field_ids=$6::jsonb,updated_at=$5
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
192
+ 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 vo(e){let t=await S(e.db).query(`SELECT r.receipt FROM analytics_crm_provisioning_receipts r
139
193
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
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(
194
+ 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 We.parse(t.rows[0].receipt)}var Ot=e=>e instanceof Date?e.toISOString():e;function Dt(e){return cn.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:Ot(e.last_started_at),lastSuccessAt:Ot(e.last_success_at),nextRunAt:Ot(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 Eo(e){let t=S(e.db),n=await re({siteId:e.siteId,connectionId:e.connectionId,db:t}),i=et({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:Dt(r.rows[0])}}let s=await t.query(`INSERT INTO analytics_crm_sync_runs(
141
195
  sync_id,site_id,connection_id,provider,mode,state,mapping,mapping_version,capability_evidence,idempotency_key,request_fingerprint,last_started_at
142
196
  ) 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)
143
197
  VALUES($1,'pending',now(),now()) ON CONFLICT(connection_id)
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()
198
+ DO UPDATE SET status='pending',last_started_at=now(),updated_at=now()`,[n]),{reused:!1,status:Dt(s.rows[0])}}async function bo(e){let t=await S(e.db).query("SELECT * FROM analytics_crm_sync_runs WHERE site_id=$1 AND sync_id=$2",[e.siteId,e.syncId]);return t.rowCount?Dt(t.rows[0]):null}async function Io(e){let t=S(e.db);return(await t.query(`UPDATE analytics_crm_sync_runs SET next_run_at=$4,interval_seconds=$5,updated_at=now()
145
199
  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
146
200
  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)
147
201
  VALUES($1,$2,'pending',$3)
@@ -149,15 +203,15 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
149
203
  status=CASE WHEN analytics_reconciliation_jobs.status='leased' THEN 'leased' ELSE 'pending' END,
150
204
  next_attempt_at=CASE WHEN analytics_reconciliation_jobs.status='leased'
151
205
  THEN analytics_reconciliation_jobs.next_attempt_at ELSE EXCLUDED.next_attempt_at END,
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)
206
+ updated_at=now()`,[ie(),e.connectionId,e.nextRunAt]),!0):!1}async function Ao(e){let t=S(e.db),n=await t.query(`UPDATE analytics_crm_sync_runs SET state='cancelled',next_run_at=NULL,updated_at=now()
207
+ 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 So(e){let t=S(e.db);await re({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)
154
208
  VALUES($1,'inbound','running',now(),now())
155
209
  ON CONFLICT(connection_id) DO UPDATE SET
156
210
  direction=CASE WHEN analytics_crm_sync_state.direction='outbound' THEN 'bidirectional' ELSE analytics_crm_sync_state.direction END,
157
211
  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()
158
212
  WHERE sync_id=(SELECT sync_id FROM analytics_crm_sync_runs
159
213
  WHERE site_id=$1 AND connection_id::text=$2 AND state NOT IN ('cancelled','webhook_only')
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(
214
+ ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId])}async function ho(e){let t=S(e.db);await re({siteId:e.siteId,connectionId:e.connectionId,db:t}),await t.query(`INSERT INTO analytics_crm_sync_state(
161
215
  connection_id,cursor,direction,status,last_started_at,last_completed_at,last_success_at,next_sync_at,updated_at
162
216
  ) VALUES($1,$2::jsonb,'inbound','healthy',now(),now(),now(),$3,now())
163
217
  ON CONFLICT(connection_id) DO UPDATE SET
@@ -172,7 +226,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
172
226
  WHERE site_id=$1 AND connection_id::text=$2 AND state <> 'cancelled'
173
227
  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(
174
228
  id,site_id,connection_id,direction,operation,subject_ref,external_receipt_id,status,occurred_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)
229
+ ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,'accepted',now())`,[ie(),e.siteId,e.connectionId,e.receiptFingerprint])}async function No(e){let t=S(e.db);await re({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)
176
230
  VALUES($1,'inbound','degraded',now(),$2,$3,now())
177
231
  ON CONFLICT(connection_id) DO UPDATE SET
178
232
  direction=CASE WHEN analytics_crm_sync_state.direction='outbound' THEN 'bidirectional' ELSE analytics_crm_sync_state.direction END,
@@ -183,7 +237,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
183
237
  WHERE site_id=$1 AND connection_id::text=$2 AND state <> 'cancelled'
184
238
  ORDER BY created_at DESC LIMIT 1)`,[e.siteId,e.connectionId,e.safeErrorCode,e.nextRunAt]),await t.query(`INSERT INTO analytics_crm_sync_receipts(
185
239
  id,site_id,connection_id,direction,operation,subject_ref,external_receipt_id,status,safe_error_code,occurred_at
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,
240
+ ) VALUES($1,$2,$3,'inbound','historical_pull',NULL,$4,$5,$6,now())`,[ie(),e.siteId,e.connectionId,e.receiptFingerprint,n,e.safeErrorCode])}function Fn(e){return Be.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 Co(e){let t=Be.parse(e.policy),n=S(e.db),i=await re({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,
187
241
  c.schema_fingerprint current_schema_fingerprint
188
242
  FROM analytics_crm_provisioning_receipts r
189
243
  JOIN analytics_crm_provisioning_plans p ON p.id=r.plan_id
@@ -201,14 +255,14 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
201
255
  AND analytics_crm_outbound_policies.connection_id=EXCLUDED.connection_id
202
256
  AND analytics_crm_outbound_policies.kind=EXCLUDED.kind
203
257
  AND analytics_crm_outbound_policies.version=EXCLUDED.version
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
258
+ 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 jn(e){return(await S(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 Tt(e){return dn.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 qn(e){let t=Be.parse(e.policy);if(!t.enabled)throw new f("analytics_crm_outbound_policy_disabled","The CRM outbound policy is disabled.",409);let n=S(e.db);if(!(await n.query(`SELECT p.id::text id FROM analytics_people p
205
259
  WHERE p.id=$1 AND p.site_id=$2 AND
206
260
  (p.crm_person_ref IS NOT NULL OR EXISTS (
207
261
  SELECT 1 FROM analytics_identity_edges e JOIN analytics_identity_nodes n ON n.id=e.identity_node_id
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(
262
+ 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:Tt(r.rows[0]),reused:!0}}let s=await n.query(`INSERT INTO analytics_crm_outbound_jobs(
209
263
  job_id,policy_id,site_id,person_id,kind,policy_version,mapping_version,source_event_id,
210
264
  payload_ciphertext,idempotency_key,request_fingerprint,next_attempt_at
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 (
265
+ ) 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:Tt(s.rows[0]),reused:!1}}async function Hn(e){let t=await S(e.db).query(`WITH due AS (
212
266
  SELECT j.job_id FROM analytics_crm_outbound_jobs j
213
267
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
214
268
  WHERE p.enabled=true AND p.provider NOT IN ('salesforce','pipedrive')
@@ -222,8 +276,8 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
222
276
  WHERE j.job_id=due.job_id AND p.policy_id=j.policy_id AND s.id=j.site_id
223
277
  RETURNING j.*,p.provider,p.connection_id::text,p.mapping,p.allowed_fields,p.purpose,s.owner_user_id,
224
278
  EXISTS(SELECT 1 FROM analytics_crm_connection_capabilities c
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)
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(
279
+ 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 S(e.db).query(`INSERT INTO analytics_crm_outbound_attempts(id,job_id,attempt,status,started_at)
280
+ VALUES($1,$2,$3,'started',now()) ON CONFLICT(job_id,attempt) DO NOTHING`,[ie(),n.job_id,Number(n.attempts)]);return t.rows.map(n=>({job:Tt(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 Wn(e){return(await S(e.db).query(`SELECT EXISTS(
227
281
  SELECT 1
228
282
  FROM analytics_crm_outbound_jobs j
229
283
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
@@ -266,27 +320,88 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
266
320
  AND (($3='site_analytics' AND consent.site_analytics=true) OR
267
321
  ($3='advertising_measurement' AND consent.advertising_measurement=true))
268
322
  ))
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
323
+ ) authorized`,[e.jobId,e.attempt,e.purpose,e.consentReceiptRef])).rows[0]?.authorized===!0}async function Bn(e){let t=S(e.db);return(await t.query(`UPDATE analytics_crm_outbound_jobs
270
324
  SET state='cancelled',payload_ciphertext='',next_attempt_at=NULL,
271
325
  lease_expires_at=NULL,cancelled_at=now(),safe_error_code=$3,updated_at=now()
272
326
  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
273
327
  SET status='cancelled',safe_error_code=$3,completed_at=now()
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,
328
+ WHERE job_id=$1 AND attempt=$2 AND status='started'`,[e.jobId,e.attempt,e.safeErrorCode.slice(0,80)]),!0):!1}async function tt(e){let t=S(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_${et({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,
275
329
  lease_expires_at=NULL,delivered_at=CASE WHEN $2='delivered' THEN now() ELSE delivered_at END,updated_at=now()
276
330
  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)
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
331
+ 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()`,[ie(),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)
332
+ 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 wo(e){return(await S(e.db).query(`SELECT r.* FROM analytics_crm_outbound_receipts r
279
333
  JOIN analytics_crm_outbound_jobs j ON j.job_id=r.job_id
280
334
  JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
281
335
  WHERE j.site_id=$1 AND p.provider NOT IN ('salesforce','pipedrive')
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,
336
+ 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 Kn}from"crypto";var Lr=["hubspot","salesforce","highlevel","zoho","pipedrive","keap"],Ro=["hubspot","highlevel","zoho","keap"];var J=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)},pe=["describe","discover_schema","incremental_read","webhook","upsert_person","append_activity","test_write","list_outcomes","pipeline_write"],Vn=Object.freeze({hubspot:{provider:"hubspot",displayName:"HubSpot",providerConfigKeys:["hubspot"],auth:"oauth2",operations:J([...pe,"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:J([...pe,"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:J([...pe,"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:J([...pe,"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:J([...pe,"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:J([...pe,"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:J(["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:J(["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:J(["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"}}),$r=Object.freeze({gohighlevel:"highlevel",ghl:"highlevel","high-level":"highlevel",infusionsoft:"keap","zoho-crm":"zoho",calltrackingmetrics:"ctm","call-tracking-metrics":"ctm"});function se(e){let t=e.trim().toLowerCase().replace(/[ _]+/g,"-"),n=$r[t]??t;if(!(n in Vn))throw new Error("analytics_provider_unsupported");return n}function nt(e){return Vn[se(e)]}function ye(e,t){let n=nt(e);if(!n.operations[t])throw new Error(`analytics_provider_operation_unsupported:${n.provider}:${t}`);return n}var F=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"}),kr=Object.freeze({hubspot:["crm.objects.deals.read"],salesforce:["api"],highlevel:["opportunities.readonly"],zoho:["ZohoCRM.modules.deals.READ"],pipedrive:["deals:read"],keap:["full"]});function Oo(e){let t=se(e.provider);if(!Lr.includes(t))throw new Error("analytics_crm_provider_required");let n=t,i=nt(n),r=new Set(e.compiledActions??[]),s=new Set(e.advertisedTools??[]),a=new Set(e.grantedScopes??[]),o=e.documented===!0,c=e.normalizedAdapter===!0,l=F.listOutcomes,_=c&&r.has(l),d=s.has(l),p=kr[n],E=p.every(D=>a.has(D)),b=new Set(e.tenantObjects??[]),k=!!(i.pipelineObject&&b.has(i.pipelineObject)),x=o&&_&&d&&E&&k,h=i.operations.webhook&&e.webhookAdvertised===!0,C=[...o?[]:["official_documentation"],...c?[]:["normalized_adapter"],...r.has(l)?[]:[`compiled_action:${l}`],...d?[]:[`connection_tool:${l}`],...p.filter(D=>!a.has(D)).map(D=>`scope:${D}`),...!k&&i.pipelineObject?[`tenant_object:${i.pipelineObject}`]:[]],m=x&&h?"incremental_and_webhook":x?"incremental_only":h?"webhook_only":e.manualBackfillAvailable===!0?"manual_backfill":"unavailable",X=(D,A)=>i.operations[D]&&r.has(A)&&s.has(A);return{provider:n,mode:m,canSyncNow:x,canSchedule:x,canProvisionFields:X("create_fields",F.createFields),canUpsertPerson:X("upsert_person",F.upsertPerson),canApplyPipelineEvent:X("pipeline_write",F.pipelineEvent),supportedObjects:e.tenantObjects?i.supportedObjects.filter(D=>b.has(D)):[],evidence:{documented:o,normalizedAdapter:c,advertisedTools:[...s].sort(),grantedScopes:[...a].sort(),missingRequirements:C,tenantSchemaFingerprint:e.tenantSchemaFingerprint??null,evaluatedAt:e.evaluatedAt??new Date().toISOString()},caveats:i.caveats}}var Jn=[{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 ae(e,t){return`${e}_${Kn("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function Lt(e){return Kn("sha256").update(JSON.stringify(e)).digest("hex")}function Pr(e){return Lt([...e].sort((t,n)=>`${t.object}:${t.internalName}`.localeCompare(`${n.object}:${n.internalName}`)))}function w(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function O(e,t=300){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):void 0}function Mr(e){let t=O(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 ge(e){let t=O(e.object,100),n=O(e.internalName,160),i=O(e.label,160);return!t||!n||!i?null:{object:t,internalName:n,label:i,type:Mr(e.type),writable:e.writable,...e.required?{required:!0}:{}}}function xt(e){return Array.isArray(e)?e.flatMap(t=>{if(!w(t))return[];let n=O(t.id,240),i=O(t.name??t.label,240);if(!n||!i)return[];let r=Array.isArray(t.stages)?t.stages.flatMap(s=>{if(!w(s))return[];let a=O(s.id,240),o=O(s.name??s.label,240);return a&&o?[{id:a,name:o}]:[]}):[];return[{id:n,name:i,stages:r}]}):[]}function Ur(e,t){let n=w(t)?t:{},i=[],r=[],s=xt(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 l of n[o])w(l)&&a(ge({object:c,internalName:l.name,label:l.label,type:l.type,writable:l.archived!==!0&&l.providerDefined!==!0}))}}else if(e==="salesforce"){if(Array.isArray(n.objects))for(let o of n.objects){if(!w(o))continue;let c=O(o.object,100);if(!c)continue;r.push(c);let l=w(o.permissions)?o.permissions:{};if(Array.isArray(o.fields))for(let _ of o.fields)w(_)&&a(ge({object:c,internalName:_.name,label:_.label,type:_.type,writable:l.update===!0&&_.updateable===!0,required:_.required===!0}))}}else if(e==="highlevel"){if(Array.isArray(n.customFields)){for(let o of n.customFields)if(w(o)){let c=o.model==="opportunity"?"opportunities":"contacts";r.push(c),a(ge({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(!w(c))continue;let l=O(c.module,100);if(l&&(r.push(l),Array.isArray(c.fields)))for(let _ of c.fields)w(_)&&a(ge({object:l,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(w(c)){let l=c.objectType==="deal"?"deals":"persons";r.push(l),a(ge({object:l,internalName:c.code,label:c.name,type:c.fieldType,writable:c.writable===!0}))}}let o=Array.isArray(n.stages)?n.stages:[];s=xt(Array.isArray(n.pipelines)?n.pipelines.map(c=>w(c)?{...c,id:String(c.id??""),stages:o.filter(l=>w(l)&&String(l.pipelineId)===String(c.id)).map(l=>({...l,id:String(l.id??"")}))}:c):[])}else if(e==="keap"){if(r.push("contacts"),Array.isArray(n.contactFields))for(let c of n.contactFields)w(c)&&a(ge({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:xt([{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 Fr(e){return!w(e)||!Array.isArray(e.fields)?[]:e.fields.flatMap(t=>{if(!w(t))return[];let n=O(t.object,100),i=O(t.internalName??t.internal_name,160);if(!n||!i)return[];let r=O(t.id??t.providerFieldId,240);return[{object:n,internalName:i,...r?{providerFieldId:r}:{}}]})}function it(e){let t=se(e);if(t==="callrail"||t==="twilio"||t==="ctm")throw new Error("analytics_crm_provider_required");return t}function Lo(e){let t=it(e.provider),n=ye(t,"discover_schema");if(!n.personObject||!e.connectionId.trim())throw new Error("analytics_crm_provisioning_invalid_scope");let i={},r=[];for(let l of Jn){let _=e.fields.find(d=>d.object===n.personObject&&(d.internalName.toLowerCase()===l.internalName||d.label.toLowerCase()===l.label.toLowerCase()));_?_.writable&&(i[l.internalName]=_.internalName):r.push({...l,object:n.personObject})}let s=e.now??new Date().toISOString(),a=Pr(e.fields),o={provider:t,connectionId:e.connectionId,existingMappings:i,proposedFields:r,schemaFingerprint:a},c=Lt(o);return{planId:ae("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 $o(e){let t=ye(e.plan.provider,"create_fields"),n=ae("crmplan",{provider:e.plan.provider,connectionId:e.plan.connectionId,existingMappings:e.plan.existingMappings,proposedFields:e.plan.proposedFields,schemaFingerprint:e.plan.schemaFingerprint}),i=Lt({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(Jn.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(l=>l.internalName===c)))throw new Error("analytics_crm_provisioning_field_not_in_plan");let a=e.plan.proposedFields.filter(c=>s.has(c.internalName)),o=ae("crmreceipt",{planId:e.plan.planId,fields:[...s].sort()});try{let c=a.length?await e.dependencies.callAction({connectionId:e.plan.connectionId,action:F.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:Fr(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:O(c instanceof Error?c.message:c,80)?.replace(/[^a-zA-Z0-9_:-]/g,"_")||"analytics_crm_provisioning_failed"}}}async function ko(e){if(e.receipt.status!=="approved")throw new Error("analytics_crm_provisioning_not_approved");ye(e.receipt.provider,"test_write");let t=ae("crmtest",e.receipt.receiptId),n=await e.dependencies.callAction({connectionId:e.receipt.connectionId,action:F.testWrite,payload:{provider:e.receipt.provider,marker:"X-Ray reversible connection test",cleanupRequested:!0},idempotencyKey:t});if(!w(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 zn(e){let t=it(e.provider);if(ye(t,"upsert_person"),e.person.identityTier!=="confirmed"||!e.person.deterministicIdentity.value.trim())throw new Error("analytics_crm_person_requires_confirmed_identity");let n=ae("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:F.upsertPerson,payload:i,idempotencyKey:n}),s=w(r)?O(r.recordRef??r.id,240):void 0;return{receiptId:n,provider:t,operation:"person_upsert",dealCreated:!1,...s?{providerRecordRef:s}:{}}}async function Yn(e){let t=it(e.provider);if(ye(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=ae("crmpipeline",{provider:t,connectionId:e.connectionId,eventId:e.event.eventId,mappingVersion:e.mapping.version});return await e.dependencies.callAction({connectionId:e.connectionId,action:F.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 Po(e){let t=it(e.provider),n=nt(t),i=t==="highlevel"?{locationId:e.discoveryContext?.locationId}:t==="zoho"?{module:e.discoveryContext?.zohoModules?.[0]??"Contacts"}:{};if(t==="highlevel"&&!O(i.locationId,128))throw new Error("analytics_crm_highlevel_location_required");let r=(p,E)=>e.dependencies.callAction({connectionId:e.connectionId,action:F.discoverSchema,payload:p,idempotencyKey:ae("crmdiscover",{provider:t,connectionId:e.connectionId,actionPayload:p,suffix:E})}),s=await r(i);if(t==="zoho"){let p=[...new Set(e.discoveryContext?.zohoModules??["Contacts","Deals"])],E=[s];for(let b of p.slice(1))E.push(await r({module:b},b));s={moduleResults:E}}let a=Ur(t,s),o=a.fields,c=Object.entries(n.operations).filter(([,p])=>p).map(([p])=>p),l=a.allowedOperations?new Set(a.allowedOperations.map(p=>O(p,80)).filter(p=>!!p)):null,_=l?c.filter(p=>l.has(p)):c,d=new Set(n.supportedObjects);return{provider:t,publicProfile:n,connectionId:e.connectionId,fields:o,objects:a.objects.length?a.objects.filter(p=>d.has(p)):n.supportedObjects,pipelines:a.pipelines,allowedOperations:_,discoveredAt:e.now??new Date().toISOString()}}import{createHash as qr,randomUUID as q}from"crypto";var jr=[[/perplexity/i,"llm","Perplexity"],[/chatgpt|chat\.openai|openai/i,"llm","ChatGPT"],[/claude|anthropic/i,"llm","Claude"],[/\bgrok\b|xai/i,"llm","Grok"],[/ai[ _-]?overview|google[ _-]?ai|\bsge\b|gemini/i,"llm","Google AI Overview"],[/instagram/i,"social","Instagram"],[/facebook|\bfb\b|meta/i,"social","Facebook"],[/linkedin/i,"social","LinkedIn"],[/tiktok/i,"social","TikTok"],[/youtube|youtu\.be/i,"social","YouTube"],[/twitter|x\.com/i,"social","X"],[/\bg2\b|g2\.com/i,"review","G2"],[/trustpilot/i,"review","Trustpilot"],[/\bbbb\b|better business bureau/i,"review","BBB"],[/capterra/i,"review","Capterra"],[/yelp/i,"review","Yelp"],[/google|bing|duckduckgo|yahoo/i,"search","Search"]];function j(e,t=240){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):null}function Gn(e){try{return e?new URL(e).hostname.replace(/^www\./,""):""}catch{return""}}function Xn(e){let t=e.properties??{},n=j(e.source,180)||Gn(e.referrer)||"(direct)",i=j(e.medium,180)||(n==="(direct)"?"(none)":"referral"),r=e.clickIds??{},s=`${n} ${i} ${Gn(e.referrer)}`,a=n==="(direct)"?"direct":/email|newsletter/i.test(i)?"email":"referral",o=n==="(direct)"?"Direct":n;for(let[c,l,_]of jr)if(c.test(s)){a=l,o=_;break}return r.fbclid?(a="social",o=/instagram/i.test(s)?"Instagram":"Facebook"):r.ttclid?(a="social",o="TikTok"):r.rdt_cid?(a="social",o="Reddit"):r.gclid||r.gbraid||r.wbraid?(a="search",o="Google"):r.msclkid&&(a="search",o="Microsoft Ads"),{channelFamily:a,platform:o,source:n,medium:i,campaign:j(e.campaign),campaignId:j(t.campaign_id??t.utm_id),adSetId:j(t.adset_id??t.ad_set_id??t.adgroup_id??t.ad_group_id),adId:j(t.ad_id),creativeId:j(t.creative_id),placement:j(t.placement),term:j(t.utm_term),content:j(t.utm_content)}}import{randomBytes as Qn}from"crypto";function jo(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||`site-${Qn(4).toString("hex")}`}function Zn(e){if(!e||e==="null")return null;try{let t=new URL(e);return t.protocol!=="http:"&&t.protocol!=="https:"?null:t.hostname.toLowerCase().replace(/\.$/,"")}catch{return null}}function qo(){return`px_${Qn(18).toString("base64url")}`}var Hr=1800*1e3,Xo=1e4;function Wr(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.min(Math.trunc(e),Hr):null}function Br(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.min(Math.trunc(e),100):null}var Vr=/(email|phone|password|token|secret|authorization|cookie|name|address|form|body)/i;function ei(e){if(!e)return"/";try{return new URL(e,"https://analytics.invalid").pathname.slice(0,2e3)||"/"}catch{return"/"}}function fe(e){if(!e)return null;try{let t=new URL(e);return t.protocol!=="http:"&&t.protocol!=="https:"?null:(t.search="",t.hash="",t.toString().slice(0,3e3))}catch{return null}}function Kr(e){let t={};for(let[n,i]of Object.entries(e??{}).slice(0,24))!/^[a-z][a-z0-9_]{0,63}$/i.test(n)||Vr.test(n)||(i===null||typeof i=="boolean"||typeof i=="number"?t[n]=i:typeof i=="string"&&(t[n]=i.slice(0,300)));return t}async function Jr(e){if(!e.event.visitorId||!e.event.sessionId)return;let t=$("visitor_id",e.event.visitorId),n=$("session_id",e.event.sessionId),i=new Date(e.event.occurredAt);if(!Number.isFinite(i.getTime()))return;let r=ei(e.event.path||e.event.canonicalUrl),s=await e.client.query(`INSERT INTO analytics_sessions(
337
+ id, site_id, pixel_id, visitor_hmac, session_hmac, person_id,
338
+ started_at, last_active_at, landing_path, exit_path, pageview_count, event_count
339
+ ) VALUES ($1,$2,$3,$4,$5,$6,$7,$7,$8,$8,$9,1)
340
+ ON CONFLICT(site_id, session_hmac) DO UPDATE SET
341
+ person_id = COALESCE(analytics_sessions.person_id, EXCLUDED.person_id),
342
+ last_active_at = GREATEST(analytics_sessions.last_active_at, EXCLUDED.last_active_at),
343
+ ended_at = GREATEST(COALESCE(analytics_sessions.ended_at, EXCLUDED.last_active_at), EXCLUDED.last_active_at),
344
+ duration_ms = GREATEST(
345
+ analytics_sessions.duration_ms,
346
+ LEAST(1800000, (EXTRACT(EPOCH FROM (GREATEST(analytics_sessions.last_active_at, EXCLUDED.last_active_at) - analytics_sessions.started_at)) * 1000)::bigint)
347
+ ),
348
+ exit_path = EXCLUDED.exit_path,
349
+ pageview_count = analytics_sessions.pageview_count + EXCLUDED.pageview_count,
350
+ event_count = analytics_sessions.event_count + 1,
351
+ updated_at = now()
352
+ RETURNING id`,[q(),e.siteId,e.pixelId,t,n,e.personId??null,e.event.occurredAt,r,e.event.eventName==="page_view"?1:0]),a=U(e.event.clickIds);if(!!!(e.event.source||e.event.medium||e.event.campaign||e.event.referrer||Object.keys(a).length))return;let c=qr("sha256").update(JSON.stringify({siteId:e.siteId,sessionHmac:n,source:e.event.source??null,medium:e.event.medium??null,campaign:e.event.campaign??null,referrer:fe(e.event.referrer),clickIds:a,path:r})).digest("hex"),l=await e.client.query(`INSERT INTO analytics_attribution_touches(
353
+ id, site_id, session_id, person_id, visitor_hmac, occurred_at,
354
+ source, medium, campaign, referrer, click_ids, landing_path, touch_hash
355
+ ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11::jsonb,$12,$13)
356
+ ON CONFLICT(site_id, touch_hash) DO UPDATE SET
357
+ person_id = COALESCE(analytics_attribution_touches.person_id, EXCLUDED.person_id)
358
+ RETURNING id`,[q(),e.siteId,s.rows[0].id,e.personId??null,t,e.event.occurredAt,e.event.source?.slice(0,180)??null,e.event.medium?.slice(0,180)??null,e.event.campaign?.slice(0,240)??null,fe(e.event.referrer),JSON.stringify(a),r,c]);await e.client.query(`UPDATE analytics_sessions
359
+ SET first_touch_id = COALESCE(first_touch_id, $2), last_touch_id = $2, updated_at = now()
360
+ WHERE id = $1`,[s.rows[0].id,l.rows[0].id])}async function Qo(e){let t=v(),n=`air_${q()}`,i=Zn(e.origin),s=(await t.query(`SELECT p.id, p.site_id, p.status,
361
+ COALESCE(
362
+ (e.eligible AND e.access_expires_at > now()) OR e.trial_ends_at > now(),
363
+ false
364
+ ) AS entitled
365
+ FROM analytics_pixels p
366
+ JOIN analytics_sites s ON s.id = p.site_id
367
+ LEFT JOIN analytics_thorbit_entitlements e ON e.user_id = s.owner_user_id
368
+ WHERE p.public_id = $1`,[e.publicPixelId])).rows[0];if(!s||s.status!=="active"){let d=[s?"pixel_disabled":"pixel_unknown"];return await t.query(`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
369
+ VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,[q(),n,s?.site_id??null,s?.id??null,i,e.events.length,JSON.stringify(d)]),{requestId:n,accepted:0,rejected:e.events.length,reasonCodes:d,hostname:i,siteId:s?.site_id??null,pixelId:s?.id??null}}if(!s.entitled){let d=["thorbit_entitlement_required"];return await t.query(`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
370
+ VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,[q(),n,s.site_id,s.id,i,e.events.length,JSON.stringify(d)]),{requestId:n,accepted:0,rejected:e.events.length,reasonCodes:d,hostname:i,siteId:s.site_id,pixelId:s.id}}if(!i){let d=["origin_missing_or_invalid"];return await t.query(`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, rejected_count, reason_codes)
371
+ VALUES ($1, $2, $3, $4, $5, $6::jsonb)`,[q(),n,s.site_id,s.id,e.events.length,JSON.stringify(d)]),{requestId:n,accepted:0,rejected:e.events.length,reasonCodes:d,hostname:i,siteId:s.site_id,pixelId:s.id}}if((await t.query(`INSERT INTO analytics_pixel_domains(id, pixel_id, hostname, state, rejected_count)
372
+ VALUES ($1, $2, $3, 'observed_unverified', 0)
373
+ ON CONFLICT(pixel_id, hostname) DO UPDATE
374
+ SET last_seen_at = now(), updated_at = now()
375
+ RETURNING state`,[q(),s.id,i])).rows[0]?.state!=="approved"){await t.query(`UPDATE analytics_pixel_domains
376
+ SET rejected_count = rejected_count + $3, last_seen_at = now(), updated_at = now()
377
+ WHERE pixel_id = $1 AND hostname = $2`,[s.id,i,e.events.length]);let d=["domain_unapproved"];return await t.query(`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
378
+ VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,[q(),n,s.site_id,s.id,i,e.events.length,JSON.stringify(d)]),{requestId:n,accepted:0,rejected:e.events.length,reasonCodes:d,hostname:i,siteId:s.site_id,pixelId:s.id}}let o=await t.connect(),c=0,l=0,_=new Set;try{await o.query("BEGIN");for(let d of e.events)try{await pn(o,{siteId:s.site_id,pixelId:s.id,event:d});let p=Xn(d),E=d.identity,b=null,k=null;if(d.eventDefinitionId&&d.eventDefinitionVersion){let C=await o.query(`SELECT id, version FROM analytics_event_definitions
379
+ WHERE id=$1 AND site_id=$2 AND version=$3 AND event_name=$4 AND status='active'
380
+ LIMIT 1`,[d.eventDefinitionId,s.site_id,d.eventDefinitionVersion,d.eventName]);C.rows[0]&&(b=C.rows[0].id,k=C.rows[0].version)}let x=_n(d)&&(d.visitorId||d.sessionId)?await o.query(`SELECT e.person_id FROM analytics_identity_nodes n JOIN analytics_identity_edges e ON e.identity_node_id = n.id
381
+ WHERE n.site_id = $1 AND ((n.kind = 'visitor_id' AND n.value_hmac = $2) OR (n.kind = 'session_id' AND n.value_hmac = $3))
382
+ ORDER BY e.confidence DESC, e.last_seen_at DESC LIMIT 1`,[s.site_id,d.visitorId?$("visitor_id",d.visitorId):"",d.sessionId?$("session_id",d.sessionId):""]):{rows:[]};if((await o.query(`INSERT INTO analytics_events(
383
+ id, event_id, site_id, pixel_id, hostname, visitor_id, session_id, event_name,
384
+ occurred_at, path, canonical_url, title, referrer, source, medium, campaign,
385
+ device_class, properties, country_code, region_code, click_ids, person_id,
386
+ channel_family, platform, campaign_id, ad_set_id, ad_id, creative_id, placement, utm_term, utm_content,
387
+ engaged_ms, scroll_depth, visitor_hmac, session_hmac, event_definition_id, event_definition_version
388
+ ) VALUES (
389
+ $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18::jsonb, $19, $20, $21::jsonb, $22,
390
+ $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37
391
+ ) ON CONFLICT(site_id, event_id) DO NOTHING`,[q(),d.eventId,s.site_id,s.id,i,d.visitorId??null,d.sessionId??null,d.eventName,d.occurredAt,ei(d.path||d.canonicalUrl),fe(d.canonicalUrl),d.title?.slice(0,500)??null,fe(d.referrer),d.source?.slice(0,180)??null,d.medium?.slice(0,180)??null,d.campaign?.slice(0,240)??null,d.deviceClass??null,JSON.stringify(Kr(d.properties)),gt(e.geography?.countryCode,2),gt(e.geography?.regionCode,8),JSON.stringify(U(d.clickIds)),x.rows[0]?.person_id??null,p.channelFamily,p.platform,p.campaignId,p.adSetId,p.adId,p.creativeId,p.placement,p.term,p.content,Wr(d.engagedMs),Br(d.scrollDepth),d.visitorId?$("visitor_id",d.visitorId):null,d.sessionId?$("session_id",d.sessionId):null,b,k])).rowCount){c+=1;let C=x.rows[0]?.person_id;await Jr({client:o,siteId:s.site_id,pixelId:s.id,personId:C,event:d}),C&&d.eventName==="identify"&&await yn(o,{siteId:s.site_id,personId:C,visitorId:d.visitorId,sessionId:d.sessionId}),E&&mn(d)&&await gn(o,{siteId:s.site_id,visitorId:d.visitorId,sessionId:d.sessionId,email:E.email,phone:E.phone,customerId:E.customerId,orderId:E.orderId,clickIds:d.clickIds,occurredAt:d.occurredAt})}else l+=1,_.add("duplicate_event")}catch{l+=1,_.add("event_insert_failed")}await o.query(`UPDATE analytics_pixel_domains
392
+ SET accepted_count = accepted_count + $3,
393
+ rejected_count = rejected_count + $4,
394
+ last_seen_at = now(), updated_at = now()
395
+ WHERE pixel_id = $1 AND hostname = $2`,[s.id,i,c,l]),await o.query(`INSERT INTO analytics_ingestion_receipts(
396
+ id, request_id, site_id, pixel_id, hostname, accepted_count, rejected_count, reason_codes
397
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb)`,[q(),n,s.site_id,s.id,i,c,l,JSON.stringify([..._])]),await o.query("COMMIT")}catch(d){throw await o.query("ROLLBACK"),d}finally{o.release()}return{requestId:n,accepted:c,rejected:l,reasonCodes:[..._],hostname:i,siteId:s.site_id,pixelId:s.id}}var Yr=25,Gr=25e3,ti=z.object({person:_t,event:mt.nullable(),mapping:z.object({version:z.number().int().positive(),eventName:z.string(),pipelineId:z.string(),stageId:z.string(),operation:z.enum(["create_or_update_deal","update_stage"]),valueSource:z.enum(["none","verified_revenue"]),activationEligible:z.boolean()}).strict().nullable()}).strict();function Xr(e,t){return`${e}_${zr("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}`}function rt(e){return fe(e)??void 0}function Qr(e,t,n){return e.purpose==="necessary_form_fulfillment"?t.eventKind==="form":e.purpose==="site_analytics"?n.siteAnalytics:n.advertisingMeasurement}function H(e,t){return e.has(t)}function Zr(e){let t=new Set(e.policy.allowedFields),n=e.contact?{...H(t,"contact.email")&&e.contact.email?{email:e.contact.email}:{},...H(t,"contact.phone")&&e.contact.phone?{phone:e.contact.phone}:{},...H(t,"contact.firstName")&&e.contact.firstName?{firstName:e.contact.firstName}:{},...H(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?U(e.event.clickIds):{},s=Object.entries(r).filter(([a])=>H(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}:{},...H(t,"attribution.firstTouch")&&i?{firstTouch:i}:{},...H(t,"attribution.lastNonDirectTouch")&&i?{lastNonDirectTouch:i}:{},...H(t,"attribution.convertingTouch")&&i?{convertingTouch:i}:{},...H(t,"attribution.landingPage")&&rt(e.event.canonicalUrl)?{landingPage:rt(e.event.canonicalUrl)}:{},...H(t,"attribution.conversionPage")&&rt(e.event.canonicalUrl)?{conversionPage:rt(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 ni(e){let t=(await jn({siteId:e.siteId,db:e.db})).filter(s=>s.enabled&&Qr(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,
283
398
  (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,
284
399
  ((SELECT count(*) FROM analytics_events e WHERE e.site_id=p.site_id AND e.person_id=p.id)+
285
400
  (SELECT count(*) FROM analytics_external_events x WHERE x.site_id=p.site_id AND x.person_id=p.id))::text event_count
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(),
401
+ 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=Zr({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=ti.parse({person:a,event:o,mapping:s.mapping}),l=`${s.policyId}:${s.version}:${e.canonicalEventId}`,_=et({policy:s,personId:e.personId,event:o,projection:a});(await qn({jobId:Xr("crmjob",{idempotencyKey:l}),policy:s,personId:e.personId,sourceEventId:e.canonicalEventId,payloadCiphertext:ue(JSON.stringify(c),"crm-outbound-payload"),idempotencyKey:l,requestFingerprint:_,db:e.db})).reused?r+=1:i+=1}return{queued:i,reused:r}}var st={async resolveIdentity(e){return(await nn(e))?.email??null},async callAction(e){return an({identity:e.identity,connectionId:e.connectionId,tool:e.action,input:e.payload,classification:"action",operationKind:"sync",requestId:e.idempotencyKey})},authorizeSend:e=>Wn(e),cancelUnauthorized:e=>Bn(e)};function es(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 uc(e=10,t=Date.now()+Gr,n=st){let i=Math.max(1,Math.min(Yr,e)),r=v();await r.query(`INSERT INTO analytics_crm_outbound_worker_state(worker_key,last_started_at,last_error_code,updated_at)
402
+ 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 Hn({limit:i,leaseSeconds:90}),a=0,o=0,c=0;for(let d of s){if(Date.now()>=t){await tt({jobId:d.job.jobId,status:"retrying",safeErrorCode:"crm_outbound_tick_deadline",retryAt:new Date(Date.now()+6e4).toISOString()}),o+=1;continue}try{if(!d.schemaCurrent)throw new Error("analytics_crm_schema_changed");let p=Oe(d.payloadCiphertext,"crm-outbound-payload");if(!p)throw new Error("crm_outbound_payload_unreadable");let E=ti.parse(JSON.parse(p)),b=await n.resolveIdentity(d.ownerUserId);if(!b)throw new Error("crm_outbound_owner_identity_unavailable");if(!await(n.authorizeSend??(n===st?st.authorizeSend:async()=>!0))({jobId:d.job.jobId,attempt:d.job.attempts,purpose:d.purpose,consentReceiptRef:E.person.consentReceiptRef})){await(n.cancelUnauthorized??st.cancelUnauthorized)({jobId:d.job.jobId,attempt:d.job.attempts,safeErrorCode:"crm_outbound_privacy_fence_closed"}),c+=1;continue}let h={callAction:({connectionId:m,action:X,payload:D,idempotencyKey:A})=>n.callAction({identity:b,connectionId:m,action:X,payload:D,idempotencyKey:A})},C=d.job.kind==="person_summary"?await zn({provider:d.provider,connectionId:d.connectionId,person:E.person,dependencies:h}):await Yn({provider:d.provider,connectionId:d.connectionId,person:E.person,event:E.event,mapping:E.mapping,dependencies:h});await tt({jobId:d.job.jobId,status:"accepted",externalReceiptId:C.receiptId}),a+=1}catch(p){let E=es(p),b=new Date(Date.now()+(E.rateLimited?30*6e4:Math.min(360*6e4,3e4*2**d.job.attempts))).toISOString();await tt({jobId:d.job.jobId,status:E.retryable?"retrying":"failed",safeErrorCode:E.code,...E.retryable?{retryAt:b}:{}}),E.retryable&&d.job.attempts<5?o+=1:c+=1}}let l=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(l.rows[0]?.due??0)};return await r.query(`UPDATE analytics_crm_outbound_worker_state SET last_completed_at=now(),last_success_at=now(),
288
403
  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()
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 */
404
+ WHERE worker_key='default'`).catch(()=>{}),s}}import{createHash as ts,randomUUID as ii}from"crypto";import{z as g}from"zod";var oe=g.string().trim().min(1).max(160).regex(/^[a-zA-Z0-9_.:-]+$/),$t=g.string().trim().min(1).max(160).regex(/^[a-zA-Z][a-zA-Z0-9_.:-]*$/),ns=g.discriminatedUnion("kind",[g.object({kind:g.literal("event_completed"),eventName:oe,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("event_frequency"),eventName:oe,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:oe,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:oe,withinDays:g.number().int().min(1).max(3650).optional()}).strict(),g.object({kind:g.literal("crm_stage"),stage:oe}).strict(),g.object({kind:g.literal("property_equals"),property:$t,value:g.union([g.string().max(500),g.number().finite(),g.boolean()])}).strict(),g.object({kind:g.literal("property_present"),property:$t}).strict()]),is=g.object({id:oe,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(ns).min(1).max(50)}).strict(),ri=g.object({namespaceId:oe,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(is).min(1).max(100),permittedProperties:g.array($t).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 si(){return{definitions:new Map,evaluations:new Map,evaluationHistory:[]}}var ee=class extends Error{constructor(n,i){super(i);this.code=n;this.name="AnalyticsLeadScoringError"}code};function kt(e){let t=e instanceof Date?e.toISOString():e??new Date().toISOString();if(!Number.isFinite(Date.parse(t)))throw new ee("analytics_score_invalid_time","A valid evaluation time is required.");return new Date(t).toISOString()}function Le(e,t){return`${e}:${t}`}function Pt(e){return{...e,groups:e.groups.map(t=>({...t,predicates:t.predicates.map(n=>({...n}))})),permittedProperties:[...e.permittedProperties]}}function rs(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 ss(e,t,n){let i=(r,s,a)=>(r??[]).filter(o=>o.name===s&&rs(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 as(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 ts("sha256").update(JSON.stringify(t(e))).digest("hex")}function ai(e){let t=ri.parse(e.definition),n=e.id??ii();if(e.tables.definitions.has(Le(t.namespaceId,n)))throw new ee("analytics_score_exists","A lead score with this ID already exists.");let i=kt(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(Le(t.namespaceId,n),r),Pt(r)}function yc(e){let t=e.tables.definitions.get(Le(e.namespaceId,e.scoreId));if(!t)throw new ee("analytics_score_not_found","Lead score not found.");if(t.version!==e.expectedVersion)throw new ee("analytics_score_version_conflict","The lead score changed; reload before updating.");let n=ri.parse(e.definition);if(n.namespaceId!==e.namespaceId)throw new ee("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:kt(e.now)};return e.tables.definitions.set(Le(e.namespaceId,e.scoreId),i),Pt(i)}function gc(e){return[...e.tables.definitions.values()].filter(t=>t.namespaceId===e.namespaceId).sort((t,n)=>t.name.localeCompare(n.name)).map(Pt)}function oi(e){let t=e.tables.definitions.get(Le(e.namespaceId,e.scoreId));if(!t||!t.enabled)throw new ee("analytics_score_unavailable","Lead score is missing or disabled.");let n=kt(e.now),i=t.groups.map(_=>{let d=_.predicates.map(b=>ss(b,e.facts,n)),p=d.every(b=>b!==null),E=p?Math.min(_.points,_.cap??_.points):0;return{groupId:_.id,operation:_.operation,matched:p,points:_.operation==="subtract"?-E:E,evidenceRefs:p?[...new Set(d.flatMap(b=>b??[]))].sort():[]}}),r=i.reduce((_,d)=>_+d.points,0),s=Math.max(t.minimum,Math.min(t.maximum,r)),a=[...new Set(i.flatMap(_=>_.evidenceRefs))].sort(),o=as({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 l={id:ii(),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,l),e.tables.evaluationHistory.push(l),{...l,components:l.components.map(_=>({..._,evidenceRefs:[..._.evidenceRefs]})),evidenceRefs:[...l.evidenceRefs]}}import{createHmac as os,timingSafeEqual as cs}from"crypto";function y(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 Y(e){let t=Number(e);return Number.isFinite(t)?t:void 0}function ce(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 $e(e){if(Array.isArray(e))return e.map(n=>y(n,80)).filter(n=>!!n).slice(0,30);let t=y(e,1e3);return t?t.split(",").map(n=>n.trim()).filter(Boolean).slice(0,30):[]}function G(...e){for(let t of e){let n=y(t,100);if(!n)continue;let i=new Date(n);if(Number.isFinite(i.getTime()))return i.toISOString()}return new Date().toISOString()}function ve(e,t,n){return os(e,t).update(n).digest("base64")}function Ee(e,t){if(!e||e.length!==t.length)return!1;try{return cs(Buffer.from(e),Buffer.from(t))}catch{return!1}}function be(e,t=Date.now(),n=300*1e3){let i=y(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 Ec(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 ci(e){return be(e.payloadTimestamp,e.now)&&Ee(e.signature,ve("sha1",e.secret,e.rawBody))}function di(e){let t=e.payload,n=y(t.resource_id??t.id,240)||"unknown",i=G(t.timestamp,t.start_time,t.created_at),r=$e(t.tags??t.tag),s=y(t.lead_status,80),a=s==="not_a_lead"||r.some(c=>c.toLowerCase()==="spam")||ce(t.spam)===!0,o={...y(t.gclid)?{gclid:y(t.gclid)}:{},...y(t.gbraid)?{gbraid:y(t.gbraid)}:{},...y(t.wbraid)?{wbraid:y(t.wbraid)}:{},...y(t.fbclid)?{fbclid:y(t.fbclid)}:{},...y(t.msclkid)?{msclkid:y(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:y(t.person_resource_id,240),visitorId:y(t.visitor_id??t.browser_id??t.ga,160),canonicalUrl:y(t.landing_page_url,3e3),sourceName:y(t.utm_source??t.source_name,180),medium:y(t.utm_medium??t.medium,180),campaign:y(t.utm_campaign??t.campaign,240),clickIds:o,properties:{answered:ce(t.answered)??!1,durationSeconds:Y(t.duration)??0,status:a?"spam":s||"unknown",tags:r,direction:y(t.direction,40)||"unknown",trackingNumber:y(t.tracking_phone_number,80)||null,changes:$e(t.changes)}}}function li(e){return be(e.requestTime,e.now)&&Ee(e.signature.trim(),ve("sha1",e.secret,`${e.requestTime}${e.rawBody}`))}function ui(e){let t=e.payload,n=y(t.activity_id??t.call_id??t.id,240)||"unknown",i=G(t.timestamp,t.event_time,t.started_at,t.created_at),r=$e(t.tags??t.tag_list),s=y(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:y(t.contact_id??t.visitor_id,240),visitorId:y(t.visitor_id??t.cookie_id,160),sessionId:y(t.session_id,160),canonicalUrl:y(t.landing_page_url??t.landing_url,3e3),sourceName:y(t.source??t.utm_source,180),medium:y(t.medium??t.utm_medium,180),campaign:y(t.campaign??t.utm_campaign,240),clickIds:{...y(t.gclid)?{gclid:y(t.gclid)}:{},...y(t.fbclid)?{fbclid:y(t.fbclid)}:{},...y(t.msclkid)?{msclkid:y(t.msclkid)}:{}},properties:{answered:ce(t.answered)??e.phase.includes("answer"),durationSeconds:Y(t.duration??t.talk_time)??0,status:a?"spam":s,tags:r,direction:y(t.direction,40)||"unknown",trackingNumber:y(t.tracking_number??t.dialed_number,80)||null,score:Y(t.score)??null}}}import ds from"twilio";function _i(e){return ds.validateRequest(e.authToken,e.signature,e.url,e.params)}function mi(e){let t=e.params,n=y(t.CallSid,240)||"unknown",i=(y(t.CallStatus,80)||"unknown").toLowerCase(),r=G(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:y(t.XRayVisitorId,160),sessionId:y(t.XRaySessionId,160),personRef:y(t.ContactId,240),properties:{answered:ce(t.Answered)??a,durationSeconds:Y(t.CallDuration??t.Duration)??0,status:i,direction:y(t.Direction,40)||"unknown",trackingNumber:y(t.To,80)||null,attributionLink:t.XRaySessionId?"explicit_session":"unattributed"}}}import{createCipheriv as ls,createDecipheriv as us,createHash as _s,createHmac as ms}from"crypto";var ke={session:"xrs_",visitor:"xrv_",person:"xrp_",cursor:"xrc_",candidate:"xri_"};function Ut(e){return _s("sha256").update(`xray-report:${e}:`).update(qe()).digest()}function T(e,t,n){let i=Ut("reference"),r=Buffer.from(`v1:${e}:${t}`),s=Buffer.from(n),a=ms("sha256",Ut("reference-iv")).update(r).update(s).digest().subarray(0,12),o=ls("aes-256-gcm",i,a);o.setAAD(r);let c=Buffer.concat([o.update(s),o.final()]);return`${ke[e]}${Buffer.concat([a,c,o.getAuthTag()]).toString("base64url")}`}function at(e,t,n){let i=ke[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=us("aes-256-gcm",Ut("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 ps(e,t){return T("cursor",e,JSON.stringify(t))}function Ae(e,t){if(!t)return null;try{let n=JSON.parse(at("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 Se(e){if(e===void 0)return 50;if(!Number.isInteger(e)||e<1||e>100)throw new Error("analytics_limit_invalid");return e}function Mt(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 Ie(e){if(e==null)return null;let t=Number(e);return Number.isFinite(t)?t:null}function N(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 pi(e){return e===null?null:N(e)}function he(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?ps(e,{at:a._cursorAt,id:a._cursorId}):null}}}async function Ne(e,t){await B(t,e.siteId,e.userId)}async function Lc(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),s=(await t.query(`/* analyticsSessions:keyset */
290
405
  WITH ranked AS (
291
406
  SELECT s.*,
292
407
  row_number() OVER (PARTITION BY s.visitor_hmac ORDER BY s.started_at, s.id)::int AS session_number
@@ -322,7 +437,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
322
437
  SELECT 1 FROM analytics_events ee
323
438
  WHERE ee.site_id = $1 AND ee.session_hmac = r.session_hmac AND ee.event_name = $8
324
439
  ))
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 */
440
+ 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:N(a.started_at),_cursorId:a.internal_id}));return he(e.siteId,s,n,a=>({sessionRef:T("session",e.siteId,a.internal_id),visitorRef:T("visitor",e.siteId,`visitor:${a.visitor_hmac}`),personRef:a.person_id?T("person",e.siteId,a.person_id):null,returning:a.session_number>1,sessionNumber:a.session_number,startedAt:N(a.started_at),lastActiveAt:N(a.last_active_at),endedAt:pi(a.ended_at),durationMs:Ie(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 $c(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),s=(await t.query(`/* analyticsVisitors:keyset */
326
441
  WITH visitor_sessions AS (
327
442
  SELECT COALESCE(s.person_id::text, s.visitor_hmac) AS identity_key, s.person_id,
328
443
  min(s.started_at) AS first_seen_at, max(s.last_active_at) AS last_seen_at,
@@ -344,19 +459,19 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
344
459
  WHERE ($2::timestamptz IS NULL OR (v.last_seen_at, v.last_session_id) < ($2::timestamptz, $3::uuid))
345
460
  AND ($4::boolean IS NULL OR (v.session_count > 1) = $4)
346
461
  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 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 */
462
+ 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:N(a.last_seen_at),_cursorId:a.last_session_id}));return he(e.siteId,s,n,a=>({visitorRef:T("visitor",e.siteId,a.person_id?`person:${a.person_id}`:`visitor:${a.identity_key}`),personRef:a.person_id?T("person",e.siteId,a.person_id):null,known:!!a.person_id,returning:a.session_count>1,sessions:a.session_count,firstSeenAt:N(a.first_seen_at),lastSeenAt:N(a.last_seen_at),durationMs:Ie(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 ys(e,t){if(t.startsWith(ke.person))return{kind:"person",personId:at("person",e,t),visitorHmac:null,sessionId:null};if(t.startsWith(ke.visitor)){let n=at("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(ke.session))return{kind:"session",personId:null,visitorHmac:null,sessionId:at("session",e,t)};throw new Error("analytics_reference_invalid")}var gs=2160*60*60*1e3,fs=366*24*60*60*1e3;function vs(e,t){let n=t===void 0?Date.now():Date.parse(t),i=e===void 0?n-gs:Date.parse(e);if(!Number.isFinite(i)||!Number.isFinite(n)||i>=n||n-i>fs)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 kc(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),r;try{r=await ys(e.siteId,e.reference)}catch{throw new f("analytics_journey_not_found","Journey not found.",404)}if(!(await t.query(`/* analyticsEnhancedJourney:subject */
348
463
  SELECT 1 WHERE
349
464
  ($2::uuid IS NOT NULL AND EXISTS (SELECT 1 FROM analytics_people p WHERE p.site_id=$1 AND p.id=$2))
350
465
  OR ($3::text IS NOT NULL AND EXISTS (SELECT 1 FROM analytics_sessions s WHERE s.site_id=$1 AND s.visitor_hmac=$3))
351
466
  OR ($4::uuid IS NOT NULL AND EXISTS (SELECT 1 FROM analytics_sessions s WHERE s.site_id=$1 AND s.id=$4))
352
- LIMIT 1`,[e.siteId,r.personId,r.visitorHmac,r.sessionId])).rowCount)throw new f("analytics_journey_not_found","Journey not found.",404);let a=Jr(e.from,e.to),o=[e.siteId,r.personId,r.visitorHmac,r.sessionId,a.from,a.to],c=`
467
+ LIMIT 1`,[e.siteId,r.personId,r.visitorHmac,r.sessionId])).rowCount)throw new f("analytics_journey_not_found","Journey not found.",404);let a=vs(e.from,e.to),o=[e.siteId,r.personId,r.visitorHmac,r.sessionId,a.from,a.to],c=`
353
468
  SELECT s.id, s.session_hmac, s.visitor_hmac, s.person_id, s.started_at,
354
469
  s.last_active_at, s.ended_at, s.duration_ms, s.landing_path, s.exit_path
355
470
  FROM analytics_sessions s
356
471
  WHERE s.site_id=$1
357
472
  AND ($2::uuid IS NULL OR s.person_id=$2)
358
473
  AND ($3::text IS NULL OR s.visitor_hmac=$3 OR s.person_id=(SELECT person_id FROM analytics_sessions WHERE site_id=$1 AND visitor_hmac=$3 AND person_id IS NOT NULL LIMIT 1))
359
- AND ($4::uuid IS NULL OR s.id=$4)`,[d,_,u,y,E,b]=await Promise.all([t.query(`/* analyticsSessionTimeline:keyset */
474
+ AND ($4::uuid IS NULL OR s.id=$4)`,[l,_,d,p,E,b]=await Promise.all([t.query(`/* analyticsSessionTimeline:keyset */
360
475
  WITH subject_sessions AS (
361
476
  ${c}
362
477
  ), entries AS (
@@ -515,7 +630,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
515
630
  f.source,f.medium,f.campaign,f.referrer
516
631
  FROM ranged_sessions s LEFT JOIN event_stats e ON e.session_hmac=s.session_hmac
517
632
  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 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 */
633
+ ORDER BY s.started_at DESC,s.id DESC LIMIT 50`,[...o])]),k=l.rows.map(m=>({...m,_cursorAt:N(m.occurred_at),_cursorId:m.stable_id})),x=he(e.siteId,k,n,m=>({occurredAt:N(m.occurred_at),type:m.entry_type,name:m.name,path:m.path,referrer:Mt(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},C=h.resolved_person_id??r.personId;return{subject:{kind:C?"person":r.kind,reference:e.reference,personRef:C?T("person",e.siteId,C):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:Ie(h.total_engagement_ms),averageEngagementMs:Ie(h.average_engagement_ms)},commonPages:d.rows.map(m=>({path:m.path,visits:Number(m.visits),uniqueSessions:Number(m.unique_sessions),engagedMs:Ie(m.engaged_ms),conversions:Number(m.conversions)})),acquisition:p.rows.map(m=>({source:m.source,medium:m.medium,campaign:m.campaign,referrer:Mt(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:T("session",e.siteId,m.internal_id),startedAt:N(m.started_at),endedAt:pi(m.ended_at),durationMs:Ie(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:Mt(m.referrer)}:null})),...x}}async function Pc(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),s=(await t.query(`/* analyticsConfirmedJourneys:keyset */
519
634
  SELECT p.id AS person_id, p.namespace_id, sessions.first_seen_at,
520
635
  sessions.last_seen_at, COALESCE(sessions.session_count,0)::int AS session_count,
521
636
  COALESCE(events.event_count,0)::int AS event_count,
@@ -539,7 +654,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
539
654
  ) conversions ON true
540
655
  WHERE p.site_id=$1 AND n.status='approved'
541
656
  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 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 */
657
+ 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:N(o.last_seen_at),_cursorId:o.person_id}));return{journeyTier:"confirmed",...he(e.siteId,s,n,o=>({journeyTier:"confirmed",personRef:T("person",e.siteId,o.person_id),firstSeenAt:N(o.first_seen_at),lastSeenAt:N(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 Mc(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),s=(await t.query(`/* analyticsBestGuessJourneys:keyset */
543
658
  SELECT ca.id AS association_id, ca.namespace_id, ca.model_version, ca.expires_at, ca.updated_at,
544
659
  ca.left_identity_node_id AS left_node_id, ca.right_identity_node_id AS right_node_id,
545
660
  COALESCE(stats.confirmed_sessions,0)::int AS confirmed_sessions,
@@ -593,7 +708,7 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
593
708
  WHERE ca.site_id=$1 AND n.status='approved' AND ca.status='active'
594
709
  AND ca.confidence_band='high' AND ca.expires_at > now()
595
710
  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 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 */
711
+ 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:N(o.updated_at),_cursorId:o.association_id}));return{journeyTier:"candidate_assisted",totalsAreSeparated:!0,...he(e.siteId,s,n,o=>({journeyTier:"candidate_assisted",inferenceRef:T("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:N(o.expires_at),provenance:"consented_high_confidence_candidate_association"}))}}async function Uc(e,t=v()){await Ne(e,t);let n=Se(e.limit),i=Ae(e.siteId,e.cursor),s=(await t.query(`/* analyticsInferenceReview:keyset */
597
712
  SELECT ca.id AS association_id, ca.updated_at, ca.first_observed_at, ca.last_observed_at,
598
713
  ca.expires_at, ca.model_version, ca.confidence_band,
599
714
  COALESCE(array_agg(DISTINCT ce.feature_kind ORDER BY ce.feature_kind)
@@ -606,32 +721,32 @@ import{a as Zt,s as tn}from"./chunk-OLSW4AN4.js";import{T as cn,a as de,b as Ne,
606
721
  AND ca.confidence_band='medium' AND ca.expires_at > now()
607
722
  AND ($2::timestamptz IS NULL OR (ca.updated_at,ca.id) < ($2::timestamptz,$3::uuid))
608
723
  GROUP BY ca.id
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-----
724
+ 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:N(a.updated_at),_cursorId:a.association_id}));return he(e.siteId,s,n,a=>({inferenceRef:T("candidate",e.siteId,a.association_id),confidenceBand:a.confidence_band,modelVersion:a.model_version,featureClasses:a.feature_kinds,firstObservedAt:N(a.first_observed_at),lastObservedAt:N(a.last_observed_at),expiresAt:N(a.expires_at),action:"diagnostic_only",eligibleForConfirmedMetrics:!1,eligibleForCrmOrActivation:!1}))}import{createHash as Es,createVerify as bs,verify as Is}from"crypto";function yi(e){if(!be(e.timestamp,e.now))return!1;let t=`${e.method.toUpperCase()}${e.url}${e.rawBody}${e.timestamp}`;return Ee(e.signature,ve("sha256",e.clientSecret,t))}var As=`-----BEGIN PUBLIC KEY-----
610
725
  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 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(
726
+ -----END PUBLIC KEY-----`;function gi(e){try{if(e.ghlSignature&&e.ghlSignature!=="N/A")return Is(null,Buffer.from(e.rawBody,"utf8"),e.ed25519PublicKey||As,Buffer.from(e.ghlSignature,"base64"));if(e.legacySignature&&e.legacySignature!=="N/A"&&e.legacyRsaPublicKey){let t=bs("SHA256");return t.update(e.rawBody),t.verify(e.legacyRsaPublicKey,e.legacySignature,"base64")}return!1}catch{return!1}}function Ft(e){return{schemaVersion:1,eventId:`crm_${Es("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 fi(e){let t=e.item,n=y(t.objectId,240)||"unknown",i=y(t.propertyValue,240)||"unknown";return{sourceEventId:`deal:${n}:stage:${i}:${y(t.occurredAt,100)||"unknown"}`,source:"hubspot",sourceAccountRef:e.sourceAccountRef,dealId:n,stageId:i,stageName:e.stageName,occurredAt:G(t.occurredAt),valueMinor:e.valueMinor,currency:e.currency,status:/closed.?won/i.test(i)?"won":/closed.?lost/i.test(i)?"lost":"open"}}function vi(e){let t=e.payload,n=t.opportunity&&typeof t.opportunity=="object"?t.opportunity:t,i=y(n.id??t.id,240)||"unknown",r=y(n.pipelineStageId??t.pipelineStageId,240)||"unknown",s=(y(n.status??t.status,80)||"open").toLowerCase();return{sourceEventId:`opportunity:${i}:stage:${r}:${y(t.timestamp??t.dateAdded,100)||"unknown"}`,source:"highlevel",sourceAccountRef:e.sourceAccountRef,contactId:y(n.contactId??t.contactId,240),dealId:i,pipelineId:y(n.pipelineId??t.pipelineId,240),stageId:r,stageName:y(n.pipelineStageName??t.pipelineStageName,240),occurredAt:G(t.timestamp,t.dateAdded,n.updatedAt),valueMinor:Math.round((Y(n.monetaryValue??t.monetaryValue)??0)*100),currency:y(n.currency??t.currency,3)?.toUpperCase(),status:s.includes("won")?"won":s.includes("lost")?"lost":s.includes("spam")?"spam":"open"}}var Cs=90;function bi(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 ws(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 Rs={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}},Os=/(^|_)(api_?key|access_?key|api_?token|auth_?token|token|password|private_?key|secret|signing_?key)($|_)/i;function Ds(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(Os.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 cd(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 qt(e){let t=e.provider,n=Rs[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 dd(e,t){let n=String(e.id),i=String(e.provider),r=qt({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,l=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:l?"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 ld(e){let t=Ct.parse(e.definition),n=v();await Q(n,e.siteId,e.userId);let i=t.enabled?"active":"disabled";return(await n.query(`INSERT INTO analytics_event_definitions(
612
727
  id, site_id, name, event_name, trigger_kind, definition, status, created_by_user_id
613
728
  ) VALUES ($1,$2,$3,$4,$5,$6::jsonb,$7,$8)
614
729
  ON CONFLICT(site_id, name) DO UPDATE SET event_name=EXCLUDED.event_name,
615
730
  trigger_kind=EXCLUDED.trigger_kind, definition=EXCLUDED.definition,
616
731
  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 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
732
+ RETURNING id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at`,[de(),e.siteId,t.name,t.eventName,t.triggerKind,JSON.stringify(t),i,e.userId])).rows[0]}async function ud(e,t){let n=v();return await B(n,e,t),(await n.query(`SELECT id, name, event_name, trigger_kind, definition, version, status, created_at, updated_at
618
733
  FROM analytics_event_definitions WHERE site_id=$1 AND status <> 'archived'
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 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
734
+ ORDER BY created_at DESC`,[e])).rows}async function Ht(e){let t=v();e.requireEditor?await Q(t,e.siteId,e.userId):await B(t,e.siteId,e.userId);let i=(await t.query(`SELECT id, definition, version, status FROM analytics_event_definitions
735
+ 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 _d(e){let{db:t,row:n}=await Ht({...e,requireEditor:!0}),i=Ct.parse({...n.definition,...e.changes}),r=i.enabled?"active":"disabled";return(await t.query(`UPDATE analytics_event_definitions SET
621
736
  name=$3, event_name=$4, trigger_kind=$5, definition=$6::jsonb,
622
737
  status=$7, version=version+1, updated_at=now()
623
738
  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 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()
739
+ 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 md(e){let t=v();await Q(t,e.siteId,e.userId);let n=await t.query(`UPDATE analytics_event_definitions SET status='archived', updated_at=now()
625
740
  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 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
741
+ 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 Ts(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 pd(e){let{row:t}=await Ht({...e,requireEditor:!1});return Ts(e.definitionId,t.definition,e.preview)}async function yd(e){let{db:t,row:n}=await Ht({...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
742
  FROM analytics_events
628
743
  WHERE site_id=$1 AND event_definition_id=$2 AND event_definition_version=$3
629
744
  AND received_at >= now() - ($4 * interval '1 second')
630
745
  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 ac(e){let t=await v().query(`SELECT s.owner_user_id, s.id AS site_id, d.id, d.version, d.definition
746
+ 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(l=>setTimeout(l,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 gd(e){let t=await v().query(`SELECT s.owner_user_id, s.id AS site_id, d.id, d.version, d.definition
632
747
  FROM analytics_pixels p JOIN analytics_sites s ON s.id=p.site_id
633
748
  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 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(
749
+ 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 fd(e){Ds(e.config??{});let t=v();await Q(t,e.siteId,e.userId);let n=e.webhookSecret?ue(e.webhookSecret,`connection-secret:${e.provider}:${e.sourceAccountRef}`):null;return(await t.query(`INSERT INTO analytics_connections(
635
750
  id, site_id, provider, name, source_account_ref, service_connection_ref,
636
751
  secret_ciphertext, config, created_by_user_id
637
752
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9)
@@ -646,17 +761,17 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
646
761
  readiness, last_verified_at, last_event_at, last_reconciled_at, last_error_code,
647
762
  verification_evidence, last_verified_receipt_id,
648
763
  (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 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,
764
+ created_at, updated_at`,[de(),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 vd(e,t){let n=v();return await B(n,e,t),(await n.query(`SELECT id, site_id, provider, name, source_account_ref, service_connection_ref,
650
765
  readiness, last_verified_at, last_event_at, last_reconciled_at,
651
766
  last_error_code, verification_evidence, last_verified_receipt_id,
652
767
  created_at, updated_at,
653
768
  (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 dc(e){let n=(await v().query(`SELECT id, site_id, provider, source_account_ref, secret_ciphertext,
769
+ FROM analytics_connections WHERE site_id = $1 ORDER BY created_at`,[e])).rows}async function Ed(e){let n=(await v().query(`SELECT id, site_id, provider, source_account_ref, secret_ciphertext,
655
770
  readiness, config
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,
771
+ 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?Oe(n.secret_ciphertext,i):null,readiness:n.readiness,config:n.config||{}}}async function Ii(e){let t=v();await Q(t,e.siteId,e.userId);let i=(await t.query(`SELECT id, site_id, provider, source_account_ref, service_connection_ref,
657
772
  secret_ciphertext, readiness, config
658
773
  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=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(
774
+ 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 xs(e){return e.secret_ciphertext?Oe(e.secret_ciphertext,`connection-secret:${e.provider}:${e.source_account_ref}`):null}function Ls(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},l=JSON.stringify(c);return{signatureVerified:ci({rawBody:l,signature:e.tamperSignature?"invalid":jt("sha1",i).update(l).digest("base64"),secret:i,payloadTimestamp:n,now:t}),event:di({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"post_call"})}}if(e.provider==="calltrackingmetrics"){let c={activity_id:"xray-test-call",timestamp:n,status:"completed"},l=JSON.stringify(c),_=String(Math.floor(t/1e3));return{signatureVerified:li({rawBody:l,requestTime:_,signature:e.tamperSignature?"invalid":jt("sha1",i).update(_+l).digest("base64"),secret:i,now:t}),event:ui({payload:c,sourceAccountRef:e.sourceAccountRef,phase:"call_complete"})}}if(e.provider==="twilio"){let c={CallSid:"CA_XRAY_TEST",CallStatus:"completed",Timestamp:n},l=e.tamperSignature?"invalid":Ns.getExpectedTwilioSignature(i,e.callbackUrl,c);return{signatureVerified:_i({authToken:i,signature:l,url:e.callbackUrl,params:c}),event:mi({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)},l=JSON.stringify([c]),_=String(t),d=jt("sha256",i).update(`POST${e.callbackUrl}${l}${_}`).digest("base64"),p=e.tamperSignature?"invalid":d;return{signatureVerified:yi({clientSecret:i,signature:p,timestamp:_,method:"POST",url:e.callbackUrl,rawBody:l,now:t}),event:Ft(fi({item:c,sourceAccountRef:e.sourceAccountRef}))}}if(e.provider==="highlevel"){let c={timestamp:n,opportunity:{id:"xray-test-opportunity",pipelineStageId:"qualified",status:"open"}},l=JSON.stringify(c),{privateKey:_,publicKey:d}=Ss("ed25519"),p=e.tamperSignature?Buffer.alloc(64).toString("base64"):hs(null,Buffer.from(l),_).toString("base64");return{signatureVerified:gi({rawBody:l,ghlSignature:p,ed25519PublicKey:d.export({type:"spki",format:"pem"}).toString()}),event:Ft(vi({payload:c,sourceAccountRef:e.sourceAccountRef}))}}let r=Qe.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=ln(e.provider,a,s,i);return{signatureVerified:un(e.tamperSignature?`${o.startsWith("0")?"1":"0"}${o.slice(1)}`:o,o),event:r}}async function bd(e){let t=await Ii(e),n=xs(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=qt({provider:t.provider,connectionId:t.id,serviceConnectionRef:t.service_connection_ref}),r=new URL(i.callbackPath,`${e.requestOrigin.replace(/\/$/,"")}/`).toString(),s=Ls({provider:t.provider,sourceAccountRef:t.source_account_ref,callbackUrl:r,secret:n});if(!s.signatureVerified)throw await Ei({connectionId:t.id,readiness:"degraded",errorCode:"synthetic_signature_test_failed"}),new f("analytics_connection_test_failed","Connection signature test failed.",409);let a=await Ei({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 Id(e){let t=await Ii(e),n=qt({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 Ad(e){let t=de(),n=e.rawBody?ue(e.rawBody,"webhook-payload"):null,i=await v().query(`INSERT INTO analytics_webhook_receipts(
660
775
  id, site_id, connection_id, provider, source_account_ref, source_event_id,
661
776
  signature_status, payload_ciphertext, payload_expires_at
662
777
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,now() + interval '7 days')
@@ -665,11 +780,11 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
665
780
  WHEN analytics_webhook_receipts.normalization_status = 'accepted' THEN 'replayed'
666
781
  ELSE analytics_webhook_receipts.normalization_status
667
782
  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 mc(e){await v().query(`UPDATE analytics_webhook_receipts SET
783
+ 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 Sd(e){await v().query(`UPDATE analytics_webhook_receipts SET
669
784
  normalization_status = $2,
670
785
  error_code = $3,
671
786
  normalized_at = now()
672
- WHERE id = $1`,[e.receiptId,e.accepted?"accepted":"rejected",e.errorCode??null])}async function ri(e){return(await v().query(`UPDATE analytics_connections SET
787
+ WHERE id = $1`,[e.receiptId,e.accepted?"accepted":"rejected",e.errorCode??null])}async function Ei(e){return(await v().query(`UPDATE analytics_connections SET
673
788
  readiness = CASE WHEN readiness='live' AND $2='verified' THEN 'live' ELSE $2 END,
674
789
  last_error_code = $3,
675
790
  last_verified_at = CASE WHEN $2 IN ('verified','live') THEN now() ELSE last_verified_at END,
@@ -683,7 +798,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
683
798
  updated_at = now()
684
799
  WHERE id = $1
685
800
  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 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(
801
+ 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 hd(e){let t=Ln.parse(e.rule),n=v();return await Q(n,e.siteId,e.userId),(await n.query(`INSERT INTO analytics_conversion_rules(
687
802
  id, site_id, name, conversion_kind, condition, default_value_minor,
688
803
  default_currency, status, created_by_user_id
689
804
  ) VALUES ($1,$2,$3,$4,$5::jsonb,$6,$7,$8,$9)
@@ -695,15 +810,15 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
695
810
  status = EXCLUDED.status,
696
811
  version = analytics_conversion_rules.version + 1,
697
812
  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 yc(e,t){let n=v();return await U(n,e,t),(await n.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
813
+ RETURNING *`,[de(),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 Nd(e,t){let n=v();return await B(n,e,t),(await n.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
699
814
  default_currency, version, status, created_at, updated_at
700
815
  FROM analytics_conversion_rules WHERE site_id = $1 AND status <> 'archived'
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
702
- WHERE site_id=$1 AND status='approved' ORDER BY version DESC LIMIT 1`,[t])).rows[0]?.id??null,a=[];n.visitorId&&a.push(["visitor_id",n.visitorId]),n.sessionId&&a.push(["session_id",n.sessionId]),n.personRef&&a.push(["customer_id",n.personRef]);for(let[o,c]of Object.entries(G(n.clickIds)))a.push(["click_id",`${o}:${c}`]);for(let[o,c]of a){let d=await e.query(`SELECT e.person_id FROM analytics_identity_nodes n
816
+ 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 $s(e){let t=e.properties.tags;return Array.isArray(t)?t.filter(n=>typeof n=="string"):[]}function ks(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=$s(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 Ps(e,t,n){if(!bi(n).enhancedMatching)return{personId:null,namespaceId:null,identityTier:"unlinked"};let s=(await e.query(`SELECT id FROM analytics_identity_namespaces
817
+ WHERE site_id=$1 AND status='approved' ORDER BY version DESC LIMIT 1`,[t])).rows[0]?.id??null,a=[];n.visitorId&&a.push(["visitor_id",n.visitorId]),n.sessionId&&a.push(["session_id",n.sessionId]),n.personRef&&a.push(["customer_id",n.personRef]);for(let[o,c]of Object.entries(U(n.clickIds)))a.push(["click_id",`${o}:${c}`]);for(let[o,c]of a){let l=await e.query(`SELECT e.person_id FROM analytics_identity_nodes n
703
818
  JOIN analytics_identity_edges e ON e.identity_node_id = n.id
704
819
  WHERE n.site_id = $1 AND n.kind = $2 AND n.value_hmac = $3
705
820
  AND ($4::uuid IS NULL OR (n.namespace_id=$4 AND e.namespace_id=$4))
706
- ORDER BY e.confidence DESC, e.last_seen_at DESC LIMIT 1`,[t,o,Ce(o,c),s]);if(d.rows[0])return{personId:d.rows[0].person_id,namespaceId:s,identityTier:"confirmed"}}return{personId:null,namespaceId:s,identityTier:"unlinked"}}async function _s(e,t){let i=(await e.query(`SELECT m.person_id::text, m.namespace_id::text,
821
+ ORDER BY e.confidence DESC, e.last_seen_at DESC LIMIT 1`,[t,o,$(o,c),s]);if(l.rows[0])return{personId:l.rows[0].person_id,namespaceId:s,identityTier:"confirmed"}}return{personId:null,namespaceId:s,identityTier:"unlinked"}}async function Ms(e,t){let i=(await e.query(`SELECT m.person_id::text, m.namespace_id::text,
707
822
  c.provider AS connection_provider,
708
823
  s.latest_receipt_id::text AS receipt_id, s.policy_version,
709
824
  s.site_analytics, s.enhanced_matching, s.advertising_measurement,
@@ -718,20 +833,20 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
718
833
  ON r.id=s.latest_receipt_id AND r.site_id=s.site_id
719
834
  WHERE m.site_id=$1 AND m.connection_id::text=$2
720
835
  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=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
836
+ 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=se(t.context.provider),s=se(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 Us(e,t){let n=U(t.eventClickIds),i=await e.query(`SELECT click_ids FROM analytics_attribution_touches
722
837
  WHERE site_id=$1 AND person_id=$2
723
838
  AND occurred_at <= $3::timestamptz
724
839
  AND occurred_at >= $3::timestamptz - ($4::text || ' days')::interval
725
840
  AND click_ids <> '{}'::jsonb
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
841
+ ORDER BY occurred_at DESC, id DESC`,[t.siteId,t.personId,t.occurredAt,Cs]),r={};for(let s of i.rows)for(let[a,o]of Object.entries(U(s.click_ids)))a in r||(r[a]=o);return{...r,...n}}function Fs(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 js(e,t){if(!t.rule.value_rule)return Fs(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
842
  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 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
843
+ 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 Dn(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 qs(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
844
  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
845
  FROM analytics_external_events WHERE site_id=$1 AND person_id=$2
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(
846
+ 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(l=>typeof l=="string"):[];try{let l=si();ai({tables:l,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 _=oi({tables:l,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(
732
847
  id, site_id, namespace_id, definition_id, definition_version,
733
848
  person_id, score, contributions, evaluated_at
734
- ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9)`,[_.id,e.siteId,e.namespaceId,s.id,s.version,e.personId,_.value,JSON.stringify(_.components),_.evaluatedAt]),r.push(_.id)}catch{}}return r}async function fs(e){return e.namespaceId?(await e.client.query(`SELECT t.id, d.event_name, t.minimum_confirmed_people, t.minimum_positive_outcomes,
849
+ ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9)`,[_.id,e.siteId,e.namespaceId,s.id,s.version,e.personId,_.value,JSON.stringify(_.components),_.evaluatedAt]),r.push(_.id)}catch{}}return r}async function Hs(e){return e.namespaceId?(await e.client.query(`SELECT t.id, d.event_name, t.minimum_confirmed_people, t.minimum_positive_outcomes,
735
850
  (SELECT count(DISTINCT p.id)::text FROM analytics_people p
736
851
  WHERE p.site_id=t.site_id AND p.namespace_id=t.namespace_id) AS confirmed_people,
737
852
  (SELECT count(DISTINCT e.person_id)::text FROM analytics_external_events e
@@ -741,26 +856,26 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
741
856
  WHERE m.target_id=t.id AND m.status IN ('validated','active')) AS validated_manifest
742
857
  FROM analytics_prediction_targets t
743
858
  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=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(
859
+ WHERE t.site_id=$1 AND t.namespace_id=$2 AND t.status<>'disabled'`,[e.siteId,e.namespaceId])).rows.map(n=>ws({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 Ai(e){let t=Qe.parse(e.event),n=e.db??v();e.userId!==void 0&&await Q(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 Ms(r,{siteId:e.siteId,context:e.trustedCrmContext}):null,a=e.trustedCrmContext?Qe.parse({...t,personRef:void 0,consent:s?.consent,properties:{...t.properties,_xrayCrmLinkReason:s?.reason??"mapping_unavailable"}}):t,o=bi(a),c=s?.personId&&s.namespaceId?{personId:s.personId,namespaceId:s.namespaceId,identityTier:"confirmed"}:e.trustedCrmContext?{personId:null,namespaceId:null,identityTier:"unlinked"}:await Ps(r,e.siteId,a),l=c.personId,_=await r.query(`INSERT INTO analytics_external_events(
745
860
  id, site_id, receipt_id, person_id, source, source_account_ref,
746
861
  source_event_id, event_kind, event_name, occurred_at, visitor_hmac,
747
862
  session_hmac, call_id, deal_id, order_id, value_minor, currency,
748
863
  click_ids, properties
749
864
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18::jsonb,$19::jsonb)
750
865
  ON CONFLICT(site_id, source, source_account_ref, source_event_id) DO NOTHING
751
- RETURNING id`,[se(),e.siteId,e.receiptId??null,d,a.source,a.sourceAccountRef,a.sourceEventId,a.eventKind,a.eventName,a.occurredAt,a.visitorId?yt("visitor_id",a.visitorId):null,a.sessionId?yt("session_id",a.sessionId):null,a.callId??null,a.dealId??null,a.orderId??null,a.valueMinor??null,a.currency?.toUpperCase()??null,JSON.stringify(G(a.clickIds)),JSON.stringify({...a.properties,_xrayConsentEligibility:o,_xrayIdentityTier:c.identityTier,...c.namespaceId?{_xrayNamespaceId:c.namespaceId}:{}})]),u=_.rows[0]?.id??(await r.query(`SELECT id FROM analytics_external_events
752
- WHERE site_id=$1 AND source=$2 AND source_account_ref=$3 AND source_event_id=$4`,[e.siteId,a.source,a.sourceAccountRef,a.sourceEventId])).rows[0]?.id;if(!u)throw new f("analytics_external_event_conflict","The canonical event could not be resolved.",409);let E=(await r.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
866
+ RETURNING id`,[de(),e.siteId,e.receiptId??null,l,a.source,a.sourceAccountRef,a.sourceEventId,a.eventKind,a.eventName,a.occurredAt,a.visitorId?yt("visitor_id",a.visitorId):null,a.sessionId?yt("session_id",a.sessionId):null,a.callId??null,a.dealId??null,a.orderId??null,a.valueMinor??null,a.currency?.toUpperCase()??null,JSON.stringify(U(a.clickIds)),JSON.stringify({...a.properties,_xrayConsentEligibility:o,_xrayIdentityTier:c.identityTier,...c.namespaceId?{_xrayNamespaceId:c.namespaceId}:{}})]),d=_.rows[0]?.id??(await r.query(`SELECT id FROM analytics_external_events
867
+ WHERE site_id=$1 AND source=$2 AND source_account_ref=$3 AND source_event_id=$4`,[e.siteId,a.source,a.sourceAccountRef,a.sourceEventId])).rows[0]?.id;if(!d)throw new f("analytics_external_event_conflict","The canonical event could not be resolved.",409);let E=(await r.query(`SELECT id, name, conversion_kind, condition, default_value_minor,
753
868
  default_currency, version
754
- FROM analytics_conversion_rules WHERE site_id = $1 AND status = 'active'`,[e.siteId])).rows.filter(A=>ls({name:A.name,conversionKind:A.conversion_kind,condition:(({valueRule:M,...$e})=>$e)(A.condition),defaultValueMinor:A.default_value_minor?Number(A.default_value_minor):void 0,defaultCurrency:A.default_currency,valueRule:A.condition.valueRule,enabled:!0},a).matches),b=[],V={};for(let A of E){let M=await ys(r,{siteId:e.siteId,personId:d,insertedEventId:u,event:a,rule:{value_rule:A.condition.valueRule,default_value_minor:A.default_value_minor,default_currency:A.default_currency,version:A.version}}),$e=M.valueMinor??0,jt=(M.currency||A.default_currency||"USD").toUpperCase(),fi=M.provenance.resolution==="absent"?"absent":M.provenance.resolution==="fallback"?"dynamic":M.provenance.resolution,vi=se(),Se=await r.query(`INSERT INTO analytics_conversions(
869
+ FROM analytics_conversion_rules WHERE site_id = $1 AND status = 'active'`,[e.siteId])).rows.filter(A=>ks({name:A.name,conversionKind:A.conversion_kind,condition:(({valueRule:W,...Me})=>Me)(A.condition),defaultValueMinor:A.default_value_minor?Number(A.default_value_minor):void 0,defaultCurrency:A.default_currency,valueRule:A.condition.valueRule,enabled:!0},a).matches),b=[],k={};for(let A of E){let W=await js(r,{siteId:e.siteId,personId:l,insertedEventId:d,event:a,rule:{value_rule:A.condition.valueRule,default_value_minor:A.default_value_minor,default_currency:A.default_currency,version:A.version}}),Me=W.valueMinor??0,Vt=(W.currency||A.default_currency||"USD").toUpperCase(),Li=W.provenance.resolution==="absent"?"absent":W.provenance.resolution==="fallback"?"dynamic":W.provenance.resolution,$i=de(),we=await r.query(`INSERT INTO analytics_conversions(
755
870
  id, source_event_id, site_id, session_id, conversion_kind,
756
871
  value_minor, currency, occurred_at, person_id, rule_id, rule_version, order_id,
757
872
  value_source, value_provenance, session_hmac
758
873
  ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14::jsonb,$15)
759
- ON CONFLICT(site_id, source_event_id) DO NOTHING RETURNING id`,[vi,`rule:${A.id}:${a.source}:${a.sourceEventId}`,e.siteId,a.sessionId??null,A.conversion_kind,$e,jt,a.occurredAt,d,A.id,A.version,a.orderId??null,fi,JSON.stringify(M.provenance),a.sessionId?Ce("session_id",a.sessionId):null]);if(!Se.rowCount||(b.push(Se.rows[0].id),V[Se.rows[0].id]=M.provenance,!d||!o.advertisingMeasurement))continue;let Ei=await r.query(`SELECT id FROM analytics_activation_destinations
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(
874
+ ON CONFLICT(site_id, source_event_id) DO NOTHING RETURNING id`,[$i,`rule:${A.id}:${a.source}:${a.sourceEventId}`,e.siteId,a.sessionId??null,A.conversion_kind,Me,Vt,a.occurredAt,l,A.id,A.version,a.orderId??null,Li,JSON.stringify(W.provenance),a.sessionId?$("session_id",a.sessionId):null]);if(!we.rowCount||(b.push(we.rows[0].id),k[we.rows[0].id]=W.provenance,!l||!o.advertisingMeasurement))continue;let ki=await r.query(`SELECT id FROM analytics_activation_destinations
875
+ WHERE site_id = $1 AND status = 'active' AND readiness IN ('verified','live')`,[e.siteId]),Pi=await Us(r,{siteId:e.siteId,personId:l,occurredAt:a.occurredAt,eventClickIds:a.clickIds}),Mi=ue(JSON.stringify({eventId:we.rows[0].id,eventName:A.conversion_kind,eventTime:a.occurredAt,valueMinor:Me,currency:Vt,valueProvenance:W.provenance,attributionModelProvenance:{model:typeof a.properties.attributionModel=="string"?a.properties.attributionModel:"unassigned",evidenceTier:"confirmed"},orderId:a.orderId,clickIds:Pi,source:a.source,personId:l,identityTier:"confirmed",namespaceId:c.namespaceId,consent:{receiptId:o.receiptId,advertisingMeasurement:!0}}),"activation-payload");for(let Ui of ki.rows)await r.query(`INSERT INTO analytics_activation_jobs(
761
876
  id, destination_id, conversion_id, person_id, payload_ciphertext
762
877
  ) 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 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,
878
+ ON CONFLICT(destination_id, conversion_id) DO NOTHING`,[de(),Ui.id,we.rows[0].id,l,Mi])}let x=await qs({client:r,siteId:e.siteId,namespaceId:c.namespaceId,personId:l,occurredAt:a.occurredAt}),h=await Hs({client:r,siteId:e.siteId,namespaceId:c.namespaceId});l&&await ni({siteId:e.siteId,personId:l,canonicalEventId:d,event:a,consent:{...o.receiptId?{receiptId:o.receiptId}:{},siteAnalytics:o.siteAnalytics,advertisingMeasurement:o.advertisingMeasurement},db:r}),i&&await r.query("COMMIT");let C=null,m=typeof a.properties.candidateAssociationId=="string"?a.properties.candidateAssociationId:null,X=typeof a.properties.deterministicEvidenceRef=="string"?a.properties.deterministicEvidenceRef:null,D=a.properties.deterministicEvidenceKind;return l&&c.namespaceId&&m&&X&&["verified_email","verified_phone","crm_contact","signed_linker","authenticated_user"].includes(String(D))&&(C=await Un({siteId:e.siteId,namespaceId:c.namespaceId,associationId:m,personId:l,evidenceKind:D,evidenceRef:X,occurredAt:a.occurredAt}).catch(()=>null)),{id:_.rows[0]?.id??null,created:!!_.rowCount,personId:l,identityTier:c.identityTier,namespaceId:c.namespaceId,conversionIds:b,consentEligibility:o,valueProvenance:k,scoreEvaluationIds:x,predictionEvidence:h,candidatePromotion:C}}catch(s){throw i&&await r.query("ROLLBACK"),s}finally{i&&r.release()}}async function Cd(e,t,n){let i=v();if(await B(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,l]=await Promise.all([i.query(`SELECT id, started_at, last_active_at, ended_at, duration_ms, landing_path,
764
879
  exit_path, pageview_count, event_count
765
880
  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
881
  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 +884,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
769
884
  d.platform, d.name AS destination_name
770
885
  FROM analytics_activation_jobs j
771
886
  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 fc(e,t){let n=v();await U(n,e,t);let r=(await n.query(`SELECT
887
+ WHERE d.site_id = $1 AND j.person_id = $2 ORDER BY j.created_at`,[e,n])]),_=d=>{if(typeof d!="string"||!d)return null;try{let p=new URL(d);return`${p.origin}${p.pathname}`.slice(0,2e3)}catch{return null}};return{personRef:T("person",e,n),sessions:s.rows.map(d=>({sessionRef:T("session",e,String(d.id)),started_at:d.started_at,last_active_at:d.last_active_at,ended_at:d.ended_at,duration_ms:d.duration_ms,landing_path:d.landing_path,exit_path:d.exit_path,pageview_count:d.pageview_count,event_count:d.event_count})),touches:a.rows.map(d=>({occurred_at:d.occurred_at,source:d.source,medium:d.medium,campaign:d.campaign,referrer:_(d.referrer),landing_path:d.landing_path})),externalEvents:o.rows.map(d=>({source:d.source,event_kind:d.event_kind,event_name:d.event_name,occurred_at:d.occurred_at,value_minor:d.value_minor,currency:d.currency})),conversions:c.rows.map(d=>({conversion_kind:d.conversion_kind,value_minor:d.value_minor,currency:d.currency,occurred_at:d.occurred_at,rule_version:d.rule_version})),deliveries:l.rows.map(d=>({status:d.status,attempts:d.attempts,response_category:d.response_category,created_at:d.created_at,delivered_at:d.delivered_at,platform:d.platform,destination_name:d.destination_name}))}}async function wd(e,t){let n=v();await B(n,e,t);let r=(await n.query(`SELECT
773
888
  count(*)::int AS total_events,
774
889
  count(*) FILTER (WHERE person_id IS NOT NULL)::int AS identified_events,
775
890
  count(*) FILTER (WHERE click_ids <> '{}'::jsonb)::int AS events_with_click_id,
@@ -778,7 +893,7 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
778
893
  count(*) FILTER (WHERE event_kind = 'crm')::int AS crm_events,
779
894
  count(*) FILTER (WHERE event_kind = 'crm' AND person_id IS NOT NULL)::int AS joined_crm_events,
780
895
  count(*) FILTER (WHERE properties->>'status' = 'spam' OR properties->'tags' ? 'spam')::int AS spam_events
781
- FROM analytics_external_events WHERE site_id = $1`,[e])).rows[0],s=(a,o)=>o?a/o:null;return{...r,identifiedRate:s(r.identified_events,r.total_events),clickIdCaptureRate:s(r.events_with_click_id,r.total_events),phoneJoinRate:s(r.joined_call_events,r.call_events),crmStageJoinRate:s(r.joined_crm_events,r.crm_events)}}var Le="mcp_scraper_subscription_paid";function vs(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}async function Es(e,t){return(await e.query(`SELECT p.id::text AS person_id, p.namespace_id::text AS namespace_id,
896
+ FROM analytics_external_events WHERE site_id = $1`,[e])).rows[0],s=(a,o)=>o?a/o:null;return{...r,identifiedRate:s(r.identified_events,r.total_events),clickIdCaptureRate:s(r.events_with_click_id,r.total_events),phoneJoinRate:s(r.joined_call_events,r.call_events),crmStageJoinRate:s(r.joined_crm_events,r.crm_events)}}var Pe="mcp_scraper_subscription_paid";function Ws(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}async function Bs(e,t){return(await e.query(`SELECT p.id::text AS person_id, p.namespace_id::text AS namespace_id,
782
897
  cs.latest_receipt_id::text AS receipt_id, cs.policy_version,
783
898
  cs.site_analytics, cs.enhanced_matching, cs.advertising_measurement,
784
899
  cs.effective_at
@@ -817,4 +932,4 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
817
932
  )
818
933
  ORDER BY edge.confidence DESC, edge.last_seen_at DESC
819
934
  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(!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-LPXTITVC.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};
935
+ FOR SHARE OF p, ns, cs, receipt`,[t.siteId,$("customer_id",t.stableUserId)])).rows[0]??null}async function Wt(e,t){let n=process.env.MCP_SCRAPER_XRAY_SITE_ID?.trim();if(!n)return{status:"skipped",eventName:Pe,reason:"site_not_configured"};if(!Ws(n))return{status:"skipped",eventName:Pe,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)=>Ai({...a,transactionClient:o})},s=await r.db.connect();try{await s.query("BEGIN");let a=await Bs(s,{siteId:n,stableUserId:i});if(!a)return await s.query("ROLLBACK"),{status:"skipped",eventName:Pe,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:Pe,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:Pe,reason:"recorded",created:c.created,conversionIds:c.conversionIds}}catch(a){throw await s.query("ROLLBACK").catch(()=>{}),a}finally{s.release()}}function Si(e,t){return e&&(t??0)>0}function hi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}function Ce(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function Vs(e){let t=e.subscription;if(t)return Ce(t);let n=e.parent;return Ce(n?.subscription_details?.subscription)}async function Ks(e,t){let n=await P(e);return n||!t||(n=await je(t),n&&await Ve(n.id,e)),n}async function Js(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 Bt(e,t,n){if(!t.id||t.status!=="paid")return{status:"not_applicable",invoiceId:t.id??null};let i=t.lines.data.some(p=>{let E=hi(p);return!!E&&E in L});if(!Si(i,t.total))return{status:"not_applicable",invoiceId:t.id};let r=Vs(t),a=(r?me(await e.subscriptions.retrieve(r))?.price?.id:void 0)??t.lines.data.map(hi).find(p=>!!p&&p in L),o=a?L[a]:void 0;if(!o)return{status:"not_applicable",invoiceId:t.id};let c=Ce(t.customer);if(!c)throw new Error("Paid subscription invoice has no Stripe customer");let l=await Ks(c,t.customer_email);if(!l)throw new Error("Paid subscription invoice does not map to an MCP Scraper account");let _=await vn({invoiceId:t.id,userId:l.id,subscriptionId:r??l.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 Js(e,l,r??l.subscription_id),await Z(l,V({...l,memory_plan:"pro",subscription_tier:o.tier})));let d=await Je(l);d.ok||console.warn("[stripe] scheduled-action credential sync failed:",d.error??"unknown error");try{await Wt({userId:l.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(p){console.error("[stripe] X-Ray paid outcome failed",{invoiceId:t.id,error:p instanceof Error?p.message:String(p)})}return{status:_.granted?"fulfilled":"already_fulfilled",invoiceId:t.id,userId:l.id,tier:o.tier}}async function Ni(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:Ce(i.invoice)??null};let r=Ce(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(Ce(i.invoice)??"");if(!s?.id)throw new Error("Paid subscription checkout has no invoice");return Bt(e,s,i.created)}var Ci="scale_credit_pack";function ot(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function wi(e){let t=Number(e);if(!Number.isSafeInteger(t)||t<1||t>lt)throw new Error(`quantity must be a whole number from 1 to ${lt}`);return t}function Vd(e){return e.subscription_tier==="scale"}function Kd(e,t){let n=wi(t);return{purchase_kind:Ci,account_user_id:String(e),eligible_tier:"scale",increment_quantity:String(n),increment_usd:String(Re),credits_per_increment:String(dt)}}async function Ri(e,t,n){let i=await e.checkout.sessions.retrieve(t);if(i.mode!=="payment"||i.metadata?.purchase_kind!==Ci)return{status:"not_applicable",paymentIntentId:ot(i.payment_intent)??null};if(i.payment_status!=="paid")return{status:"not_applicable",paymentIntentId:ot(i.payment_intent)??null};let r=ot(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=wi(i.metadata.increment_quantity),a=s*Re*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!==Re*100)throw new Error("Scale credit-pack checkout line item does not match the product contract");let l=await P(r);if(!l)throw new Error("Paid Scale credit-pack checkout does not map to an MCP Scraper account");if(i.metadata.account_user_id!==String(l.id)||i.metadata.eligible_tier!=="scale")throw new Error("Scale credit-pack checkout account metadata does not match the billing account");let _=ot(i.payment_intent);if(!_)throw new Error("Paid Scale credit-pack checkout has no payment intent");let d=s*dt;return{status:(await Yt(l.id,s*tn,Ue.TOPUP,`$${s*Re} Scale credit pack (${d.toLocaleString("en-US")} credits)`,`stripe-payment-intent:${_}`,{neverExpires:!1})).duplicate?"already_fulfilled":"fulfilled",paymentIntentId:_,userId:l.id,quantity:s,credits:d}}var M=new zs(process.env.STRIPE_SECRET_KEY,{apiVersion:"2026-02-25.clover"});async function Xs(e,t){if(!(!e||e===t))try{let n=await M.subscriptions.retrieve(e),i=n.items.data[0]?.price?.id,r=n.status!=="canceled"&&!n.cancel_at_period_end;i&&i in le&&r&&await M.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 Qs=new Ys;Qs.post("/webhooks",async e=>{let t=e.req.header("stripe-signature"),n=await e.req.text(),i;try{i=M.webhooks.constructEvent(n,t,process.env.STRIPE_WEBHOOK_SECRET)}catch{return e.json({error:"Invalid signature"},400)}try{let r=await fn(i.id,i.type,i.created);return r==="queued"&&Zs(),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 Zs(){let e=import("./queue-AC4XKD6Z.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))});Gs(e)}async function ol(e){if(e.type==="checkout.session.completed"||e.type==="checkout.session.async_payment_succeeded"){let t=e.data.object;t.mode==="payment"?await Ri(M,t.id):await Ni(M,t.id);return}if(e.type==="invoice.created"){let t=e.data.object;Oi(t)&&t.status==="draft"&&await M.invoices.update(t.id,{description:Zt,footer:en,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(Oi(t)){let i=t.customer_email?void 0:await Ti(t.customer,void 0),r=t.customer_email??i?.email;if(!r)throw new Error("Paid concurrency invoice has no customer receipt email");await ea(t.id,r);return}if(t.lines.data.map(xi).find(i=>i&&i in le))return;await Bt(M,t,e.created)}if(e.type==="customer.subscription.created"||e.type==="customer.subscription.updated"){let t=e.data.object,n=Di(t);if(n){let s=await P(t.customer);if(!s)return;let a=De(t.status);await ft(s.id,a?ta(n):0),await vt(s.id,a?t.id:null);return}let i=me(t)?.price?.id??t.items.data[0]?.price?.id;if(i&&i in le){let s=le[i],a=await Ti(t.customer,t.customer_email);if(a){let o=De(t.status),c=o?s.plan:"free";await _e(a.id,c,o?t.id:null),await Z(a,V({...a,memory_plan:c}))}return}let r=await P(t.customer);if(!r)return;if(i&&i in L){let s=L[i],a=De(t.status),o=a?s.tier:null;if(await Et(r.id,o,a?s.concurrency:0,a?t.id:null),s.includes_memory){let c=a?"pro":"free";a&&await Xs(r.memory_subscription_id,t.id),await _e(r.id,c,null),await Z(r,V({...r,memory_plan:c}))}else r.memory_subscription_id===t.id&&(await _e(r.id,"free",null),await Z(r,V({...r,memory_plan:"free"})));if(a){let c=await Je(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(Di(t)){let i=await P(t.customer);i&&(await ft(i.id,0),await vt(i.id,null));return}let n=me(t)?.price?.id??t.items.data[0]?.price?.id;if(n&&n in L){let i=L[n],r=await P(t.customer);r&&(await Et(r.id,null,0,null),(i.includes_memory||r.memory_subscription_id===t.id)&&(await _e(r.id,"free",null),await Z(r,V({...r,memory_plan:"free"}))));return}if(n&&n in le||await bt(t.id)){let i=await bt(t.id)??await P(t.customer);i&&(await _e(i.id,"free",null),await Z(i,V({...i,memory_plan:"free"})));return}}}function Oi(e){return e.lines.data.some(t=>xi(t)===ct)}async function ea(e,t){let i=(await M.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 M.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 M.charges.retrieve(r):r;s.receipt_email!==t&&await M.charges.update(s.id,{receipt_email:t})}function Di(e){return e.items.data.find(t=>t.price?.id===ct)}function ta(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 xi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}async function Ti(e,t){let n=await P(e);if(n)return n;if(t)return n=await je(t),n&&await Ve(n.id,e),n}export{Ve as a,ft as b,vt as c,Et as d,_e as e,ma as f,Ki as g,fa as h,In as i,It as j,Na as k,Ca as l,Sn as m,ir as n,wa as o,Ra as p,rr as q,Nn as r,Je as s,ra as t,sa as u,aa as v,oa as w,ca as x,ht as y,K as z,me as A,Ma as B,Ua as C,Fa as D,Xe as E,Qe as F,Ln as G,Cr as H,Rr as I,Ct as J,Ga as K,Xa as L,Qa as M,Za as N,oo as O,Un as P,po as Q,yo as R,go as S,fo as T,vo as U,Eo as V,bo as W,Io as X,Ao as Y,So as Z,ho as _,No as $,Co as aa,jn as ba,wo as ca,Lr as da,Ro as ea,se as fa,nt as ga,F as ha,Oo as ia,Pr as ja,Lo as ka,$o as la,ko as ma,zn as na,Yn as oa,Po as pa,jo as qa,Zn as ra,qo as sa,Hr as ta,Xo as ua,fe as va,Qo as wa,uc as xa,si as ya,ai as za,yc as Aa,gc as Ba,oi as Ca,Ec as Da,ci as Ea,di as Fa,li as Ga,ui as Ha,_i as Ia,mi as Ja,at as Ka,Lc as La,$c as Ma,kc as Na,Pc as Oa,Mc as Pa,Uc as Qa,yi as Ra,gi as Sa,Ft as Ta,fi as Ua,vi as Va,Ds as Wa,cd as Xa,dd as Ya,ld as Za,ud as _a,_d as $a,md as ab,pd as bb,yd as cb,gd as db,fd as eb,vd as fb,Ed as gb,bd as hb,Id as ib,Ad as jb,Sd as kb,Ei as lb,hd as mb,Nd as nb,Ai as ob,Cd as pb,wd as qb,Bt as rb,Ni as sb,wi as tb,Vd as ub,Kd as vb,Ri as wb,M as xb,Qs as yb,ol as zb};