corsair 0.1.133 → 0.1.134

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.
@@ -1,4 +1,4 @@
1
- import { B as BrowserDeliveryPayload } from './index-MnbnpwOk.js';
1
+ import { B as BrowserDeliveryPayload } from './index-DUHdJscv.js';
2
2
 
3
3
  /**
4
4
  * Browser (client) delivery — hub redirects the user's browser to the app with `?d=<token>`.
@@ -6,7 +6,7 @@ import{a as ve,b as Qt,c as Xt}from"./chunk-6IURNA4L.js";import{a as Uo,b as Te,
6
6
  window.parent.postMessage(message, targetOrigin);
7
7
  }
8
8
  })();
9
- </script></body></html>`}var Fa=new Set(["localhost","127.0.0.1","[::1]","::1"]);function sr(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Fa.has(n)}catch{return!1}}function Pn(e){return e==="development"?"browser":"server"}function Yo(e){return Pn(e)==="browser"}function Qo(e){return sr(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as $a}from"crypto";var Ae=60*1e3,Fe=300*1e3;import{createHmac as Ua,randomBytes as Na,timingSafeEqual as La}from"crypto";function ge(){return Na(16).toString("base64url")}function An(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Ua("sha256",t).update(e).digest("base64url")}function ae(e,n){let t=n.trim();if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[o,i]=r;if(!o||!i)return null;let s=An(o,t);try{if(!La(Buffer.from(i,"utf8"),Buffer.from(s,"utf8")))return null}catch{return null}let a;try{a=JSON.parse(Buffer.from(o,"base64url").toString("utf8"))}catch{return null}return a.exp*1e3<Date.now()?null:a}function Yn(e,n,t){let r=Math.floor(Date.now()/1e3),o={...e,iat:r,exp:t},i=Buffer.from(JSON.stringify(o)).toString("base64url"),s=An(i,n);return`${i}.${s}`}function Rn(e,n,t){let r=Math.floor(Date.now()/1e3);return Yn(e,n,r+Math.floor(t/1e3))}function Ue(e){return decodeURIComponent(e)}function ar(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function Xo(e){let n=e.trim();return n.length>0?n:null}function Qe(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Xe(e,n){if(!Xo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??$a(16).toString("base64url"),iat:t,exp:t+Math.floor(Ae/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=An(o,n);return`${o}.${i}`}function Re(e,n){return Xo(n)?ae(e,n):null}function ja(e){let n=ir(e.hubOrigin),t={connectJti:e.requestId,projectId:e.projectId,hubSuccessUrl:e.hubOrigin,deliveryMode:e.deliveryMode,hubOrigin:n,requestId:e.requestId};switch(e.deliveryMode){case"connections.sync":return{...t,plugin:"connections.sync",tenantId:"*"};case"connect.create_link":return{...t,plugin:"connect.create_link",tenantId:e.tenantId,connectLinkPlugins:e.plugins}}}function cr(e){let n=Xe(ja(e),e.signingSecret);return Qe(e.deliveryUrl,n)}function ei(e){if(Pn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Wa(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:cr(r)}}var xn="https://auth.corsair.dev";var fe=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}},In=class extends Error{constructor(){super("Hub credentials are missing. Pass hub: { projectApiKey, signingSecret } to createCorsair() with non-empty values, or omit `hub` entirely if you are not using Corsair Hub."),this.name="HubCredentialsMissingError"}};function ur(e){let n=(e.apiUrl?.trim()||xn).replace(/\/$/,""),t=e.projectApiKey?.trim()??"",r=e.signingSecret?.trim()??"";if(!t||!r)throw new In;return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1,tunnel:e.tunnel}}function Qn(e){return ur(e)}function qa(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function F(e){let n=T(e).hub;if(!n||!qa(n))throw new fe;return n}function ni(e){return e.replace(/\/$/,"")}function Xn(e){return e.oauthCallbackUrl?ni(e.oauthCallbackUrl.trim()):`${ni(e.apiUrl)}/oauth/callback`}function en(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";throw new Error("Hub API key must start with ck_dev_ (development) or ck_prod_ (production)")}import{createCipheriv as ti,createDecipheriv as ri,randomBytes as et,scrypt as Ka}from"crypto";import{promisify as Za}from"util";var oi=Za(Ka),nt="aes-256-gcm",ii=12,tt=16,Ga=16,Ne=32;function ye(){return et(Ne).toString("base64")}async function me(e,n){let t=et(Ga),r=await oi(n,t,Ne),o=et(ii),i=ti(nt,r,o,{authTagLength:tt}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[t.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function X(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),u=await oi(n,s,Ne),d=ri(nt,u,a,{authTagLength:tt});return d.setAuthTag(c),Buffer.concat([d.update(l),d.final()]).toString("utf8")}function lr(e,n){let t=Buffer.from(n,"base64"),r=et(ii),o=ti(nt,t,r,{authTagLength:tt}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function Sn(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=ri(nt,i,s,{authTagLength:tt});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function xe(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=lr(o,n);return t}function he(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Sn(o,n);return t}function _n(e,n,t){let r=he(e,n);return xe(r,t)}function si(e,n,t){let r={};for(let o of t)r[`get_${o}`]=async()=>(await e())[o]??null,r[`set_${o}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await n({[o]:s})};return r}var dr=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function U(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...W[n].integration,...i],a=null,c={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let k=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!k)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:k.id,config:dr(k.config),dek:k.dek??null},a},updateIntegration:async k=>{let b=await c.getIntegration();await o.db.updateTable("corsair_integrations").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",b.id).execute(),a=null}},l=null,u=async()=>{if(l)return l;let k=await c.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await X(k.dek,r),l},d=async()=>{let k=await c.getIntegration(),b=await u(),v=k.config;return!v||Object.keys(v).length===0?{}:he(v,b)},p=Promise.resolve(),g=k=>{let b=p.then(()=>f(k));return p=b.catch(()=>{}),b},f=async k=>{let b=await u(),v;try{v=await d()}catch(O){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,O),v={}}let P={...v};for(let[O,H]of Object.entries(k))H===null?delete P[O]:P[O]=H;let M=xe(P,b);await c.updateIntegration({config:M})};return{get_dek:u,issue_new_dek:async()=>{let k=await c.getIntegration(),b=ye(),v={};if(k.dek){let M=await X(k.dek,r),O=k.config;O&&Object.keys(O).length>0&&(v=_n(O,M,b))}let P=await me(b,r);return await c.updateIntegration({config:v,dek:P}),l=b,b},...si(d,g,s)}}function B(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,c=[...W[n].account,...s],l=null,u=null,d=async()=>{if(u)return u;let w=!1;for(;;){let A=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!A){if(!w&&a){w=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return u={id:A.id,config:dr(A.config),dek:A.dek??null},u}},p={kek:o,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(l)return l;let w=!1;for(;;){let A=await d(),R=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",A.id).executeTakeFirst();if(!R){if(!w&&a){w=!0,await a();continue}throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`)}return l={id:R.id,config:dr(R.config),dek:R.dek??null},l}},updateAccount:async w=>{let A=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...w.config!==void 0?{config:w.config}:{},...w.dek!==void 0?{dek:w.dek}:{},updated_at:new Date}).where("id","=",A.id).execute(),l=null}},g=null,f=null,h=async()=>{if(g)return g;let w=await p.getAccount();if(!w.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await X(w.dek,o),g},k=async()=>{if(f)return f;let w=await p.getIntegration();if(!w.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await X(w.dek,o),f},b=async()=>{let w=await p.getAccount(),A=await h(),R=w.config;return!R||Object.keys(R).length===0?{}:he(R,A)},v=async()=>{let w=await p.getIntegration(),A=await k(),R=w.config;return!R||Object.keys(R).length===0?{}:he(R,A)},P=Promise.resolve(),M=w=>{let A=P.then(()=>O(w));return P=A.catch(()=>{}),A},O=async w=>{let A=await h(),R;try{R=await b()}catch(_){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,_),R={}}let Y={...R};for(let[_,oe]of Object.entries(w))oe===null?delete Y[_]:Y[_]=oe;let de=xe(Y,A);await p.updateAccount({config:de})},H={get_dek:h,issue_new_dek:async()=>{let w=await p.getAccount(),A=ye(),R={};if(w.dek){let de=await X(w.dek,o),_=w.config;_&&Object.keys(_).length>0&&(R=_n(_,de,A))}let Y=await me(A,o);return await p.updateAccount({config:R,dek:Y}),g=A,A},...si(b,M,c)};return n==="oauth_2"&&(H.get_integration_credentials=async()=>{let w=await v();return{...w,client_id:w.client_id||null,client_secret:w.client_secret||null,redirect_url:w.redirect_url??null}}),H}async function ai(e,n,t){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!r)throw new Error(`Integration "${n}" not found.`);let o=ye(),i=await me(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function ci(e,n,t,r){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let s=ye(),a=await me(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var za=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function Ie(e){return za.has(e)}function Ja(e,n){return Ie(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Va(e){return!Ie(e)}function Ya(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function Qa(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function Xa(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!Ya(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function ui(e,n){if(!e)return!1;let t=V(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function ec(e,n){let r=e.authConfig?.[n]?.integration??[];return[...W[n].integration,...r]}function nc(e,n){let r=e.authConfig?.[n]?.account??[];return[...W[n].account,...r]}function tc(e,n,t){let r=t.filter(a=>a.required&&!a.configured).map(a=>a.name),o=t.filter(a=>a.level==="integration"&&a.required&&!a.configured).map(a=>a.name),i=t.filter(a=>a.level==="account"&&a.required&&a.configured),s;return o.length>0?s="missing_integration":r.length===0?s="ready":i.length>0?s="partial":s="not_started",{plugin:e,authType:n,status:s,connected:Xa(n,t),fields:t,missingRequiredFields:r}}async function Le(e,n,t){let r=S(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,s=i?.[r]?.integration??[],a=i?.[r]?.account??[],c=U({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=B({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),u=ec(n,r),d=nc(n,r),p=[];for(let g of u)p.push({name:g,level:"integration",required:Ja(r,g),configured:await ui(c,g)});for(let g of d)p.push({name:g,level:"account",required:Va(g),configured:await ui(l,g)});if(Qa(r,p)){let g=p.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return tc(n.id,r,p)}async function En(e,n,t={}){let r=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,i=[];for(let s of e.plugins){if(o&&!o.has(s.id))continue;let a=await Le(e,s,r);a&&i.push(a)}return i}function rt(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var li=Symbol.for("corsair:internal"),di=new WeakMap,pi=new WeakMap;function rc(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function oc(e){if(e.database){let t=di.get(e.database);return t||(t=new Map,di.set(e.database,t)),t}let n=pi.get(e);return n||(n=new Map,pi.set(e,n)),n}function ic(e){return e.multiTenancy?{withTenant:()=>({}),[li]:e}:{[li]:e}}async function nn(e,n){if(!e.database)return;let t=n.trim()||"default",r=oc(e),o=rc(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-OA5K3SZE.js");await a(ic(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import*as Dn from"crypto";function Se(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function pr(e,{maxAgeMs:n}={}){try{let t=e.includes(".")?e.split(".")[0]:e,r=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));if(r!==null&&typeof r=="object"&&"plugin"in r&&"tenantId"in r&&typeof r.plugin=="string"&&typeof r.tenantId=="string"){let o=r;return n!==void 0&&typeof o.iat=="number"&&Date.now()-o.iat>n?null:o}return null}catch{return null}}function tn(e,n){let t=Dn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var gr=600*1e3;function ot(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=Dn.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!Dn.timingSafeEqual(s,a)?null:pr(r,{maxAgeMs:gr})}function gi(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function fi(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType,status:e.status,connected:e.connected,verified:e.verified,missingFields:e.missingFields,webhookLink:e.webhookLink,webhookSecret:e.webhookSecret}}async function rn(e,n){await I({hub:e,path:"/connections/report",body:gi(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function sc(e,n){try{let t=F(e);I({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof fe)return}}async function ac(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!S(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Le(n,e.plugin,r);o&&mi(e.hub,fi({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function yi(e,n){sc(e,n)}function mi(e,n){I({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function on(e){ac(e).catch(()=>{})}async function be(e,n){let t=T(e);if(!S(n.plugin))return;let o=await Le(t,n.plugin,n.tenantId);o&&yi(e,fi({tenantId:n.tenantId.trim()||"default",plugin:n.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:n.verified??o.connected,missingFields:o.missingRequiredFields,webhookLink:n.webhookLink,webhookSecret:n.webhookSecret}))}async function it(e,n,t){for(let r of e){if(r.id!==n)continue;let o=r.oauthWebhookTenantLinkResolver;return o?o(t):null}return null}var hi=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function cc(e){let n=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.pluginId).executeTakeFirst();if(!n)throw new Error(`Integration '${e.pluginId}' not found. Run setupCorsair before registering webhook tenant links.`);let t=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",n.id).executeTakeFirst();if(!t)throw new Error(`Account not found for tenant '${e.tenantId}' and integration '${e.pluginId}'.`);return{integrationId:n.id,accountId:t.id}}async function uc(e){let n=await e.database.db.selectFrom("corsair_accounts").selectAll().where("id","=",e.accountId).executeTakeFirst();if(!n?.dek)throw new Error(`Account '${e.accountId}' has no DEK.`);let t=await X(n.dek,e.kek),r=hi(n.config),o={};Object.keys(r).length>0&&(o=he(r,t)),o[e.link.linkType]=e.link.externalId;let i=xe(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function sn(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await cc({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let u=B({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),d=`set_${i.linkType}`,p=u[d];typeof p=="function"&&(await p(i.externalId),l=!0)}l||await uc({database:n,kek:t,accountId:c,link:i})}async function fr(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let c=await X(a.dek,t),u=hi(a.config)[o];if(!u)continue;if(Sn(u,c)===i)return a}catch{continue}return null}async function st(e){return(await fr(e))?.tenant_id??null}async function bi(e){return st({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as ki from"querystring";function $e(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:o}=e,i={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:o};return`${n.authUrl}?${ki.stringify(i)}`}async function wi(e,n){try{return await j({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function an(e,n,t,r){if(!n.subscribe)return;let o=F(e),i=await wi(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await be(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var K=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ci(e){let n=e.oauthConfig;if(!n)throw new K("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function lc(e,n,t,r){await e.db.transaction().execute(async o=>{let i=o.selectFrom("corsair_integrations").select(["id"]).where("name","=",n);e.isPg===!0&&(i=i.forUpdate());let s=await i.executeTakeFirst();if(!s)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).where("integration_id","=",s.id).executeTakeFirst())return;let c=ye(),l=await me(c,r),u=new Date;await o.insertInto("corsair_accounts").values({id:Je(),created_at:u,updated_at:u,tenant_id:t,integration_id:s.id,config:{},dek:l}).execute()})}async function yr(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=T(e,()=>new K("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=q(s,n,p=>new K("plugin_not_found",p)),c=Ci(a),u=await U({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!u)throw new Error(`client_id not configured for '${n}'`);if(i){let p=new URL($e({oauthConfig:c,clientId:u,redirectUri:o,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let d=tn(Se(n,r),s.kek);return{url:$e({oauthConfig:c,clientId:u,redirectUri:o,state:d}),state:d}}function dc(e,n){return{...n??{},...e}}async function On(e,n){let{code:t,state:r,redirectUri:o}=n,i=T(e,()=>new K("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new K("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let h=ot(r,i.kek);if(!h)throw new K("invalid_state","Invalid or tampered state parameter");s=h.plugin,a=h.tenantId}if(!i.database)throw new K("no_database","No database configured on corsair instance");let c=q(i,s,h=>new K("plugin_not_found",h)),l=Ci(c),u=U({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),d=await u.get_client_id(),p=await u.get_client_secret();if(!d||!p)throw new K("credentials_not_configured",`Credentials not configured for '${s}'`);await lc(i.database,s,a,i.kek);let g=await at(t,d,p,l,o);if(!g.access_token)throw new K("no_access_token",`No access_token returned from ${l.providerName}`);let f=B({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...c.authConfig?.oauth_2?.account??[]]});await f.set_access_token(g.access_token),g.refresh_token&&await f.set_refresh_token(g.refresh_token),g.expires_in&&await f.set_expires_at(String(Math.floor(Date.now()/1e3)+g.expires_in)),await be(e,{plugin:c,tenantId:a}).catch(()=>{});try{let h=dc(g,n.callbackParams),k=await it(i.plugins,s,h);if(k){try{let b=c.authConfig?.oauth_2?.account??[];await sn({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:k,authType:"oauth_2",extraAccountFields:b})}catch(b){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,b)}i.hub&&rn(i.hub,{plugin:s,tenantId:a,link:k,authType:"oauth_2"})}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,h)}if(c.subscribe)try{await an(e,c,a,f)}catch(h){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,h)}return{plugin:s,tenantId:a}}async function pc(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??an,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let c=t.plugins.find(u=>u.id===a.integrationName);if(!c?.subscribe)continue;let l=`${c.id}/${a.tenantId}`;try{let u=S(c)??"oauth_2",d=B({authType:u,integrationName:c.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...c.authConfig?.[u]?.account??[]]}),p=c.keyBuilder;if(p){let g=Object.create(d,{get_expires_at:{value:async()=>"0"}});await p({authType:u,keys:g,hub:t.hub},"endpoint")}await o(n,c,a.tenantId,d),i.push(l)}catch(u){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,u),s.push(l)}}return{renewed:i,failed:s}}async function vi(e){let n=T(e);if(!n.database)return{renewed:[],failed:[]};let t=await n.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id as tenantId","i.name as integrationName"]).where("a.dek","is not",null).execute();return pc({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function gc(e,n={}){let t=!1,r=()=>{t||(t=!0,vi(e).catch(i=>console.warn("[corsair:renewal] renewal pass failed:",i)).finally(()=>{t=!1}))};r();let o=setInterval(r,(n.intervalMinutes??45)*6e4);return o.unref?.(),()=>clearInterval(o)}async function Ti(e){if(!T(e).database)throw new Error("A database must be configured to provision Corsair integrations");await ct(e,{silent:!0})}async function cn(e,n){let t=T(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await nn(t,n)}var fc=Symbol.for("corsair:internal"),yc=new Set(["access_token","refresh_token","expires_at","scope"]);function mc(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function hc(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Ie(t)&&!yc.has(t)):n.filter(t=>!Ie(t))}function Pi(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function bc(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function kc(e){return{[fc]:Pi(e)}}async function ut(e,n,t={}){let r=Xn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Pi(e),a=kc(e);for(let c of e.plugins){if(i&&!i.has(c.id))continue;let l=S(c);if(!l)continue;let u=mc(l),d=t.providerNameOverrides?.[c.id]??Pe(c.id),p=await Le(s,c,n),g=qn(c,l),f=hc(l,g),h={plugin:c.id,providerName:d,authKind:u,alreadyConfigured:p?.connected??!1};if(f.length>0&&(h.credentialFields=f),u==="oauth"){let b=t.oauthModeOverrides?.[c.id]??(l==="managed"?"managed":"byo");if(h.oauthMode=b,!t.skipOAuthUrlGeneration&&b!=="managed")try{let v=await yr(a,c.id,{tenantId:n,redirectUri:r,hubConnect:!0});h.oauthUrl=v.url}catch(v){v instanceof Error&&/client_id not configured/i.test(v.message)||(h.setupError=v instanceof Error?v.message:`Could not prepare OAuth for ${c.id}`)}}o.push(h)}return o}async function Ag(e,n,t={}){let r=T(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return ut({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function Ai(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await nn(e.internalConfig??bc(e),n)}async function Ri(e,n){await cn(e,n)}async function xi(e,n){let t=en(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ve({deliveryUrl:n.deliveryUrl})),I({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:Zn})}async function Ii(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await Ai(t,n.tenantId);let r=await ut(t,n.tenantId,{pluginIds:[n.plugin.id]});if(r.length===0)throw new Error(`Plugin '${n.plugin.id}' is not configured on this Corsair instance`);return xi(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function lt(e,n){let t=T(e),r=F(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await Ri(e,n.tenantId);let i=n.plugin?[n.plugin]:void 0,s=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,a=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,c=await ut(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(c.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return xi(r,{tenantId:n.tenantId,plugins:c,deliveryUrl:n.deliveryUrl})}async function dt(e,n){let t=n.tenantId.trim();if(!t)throw new Error("tenantId is required");let r=n.plugins.map(s=>s.trim()).filter(Boolean);if(r.length===0)throw new Error("At least one plugin is required");let o=T(e);if(!o.hub)throw new Error("Hub is not configured on this Corsair instance");if(!o.database)throw new Error("Database not configured");let i=await wc(o.hub,{plugins:o.plugins,database:o.database,kek:o.kek,multiTenancy:o.multiTenancy},{tenantId:t,pluginIds:r});return{connectUrl:i.connectUrl,expiresAt:i.expiresAt}}async function wc(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-2RQ2BS7X.js"),{postHubConnectSession:i}=await import("./connect-QAYRTPRA.js"),s={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await o(s,t.tenantId);let a=await r(s,t.tenantId,{pluginIds:t.pluginIds});if(a.length===0)throw new Error("No connectable plugins found for this tenant");let c=a.find(l=>l.setupError);if(c)throw new Error(c.setupError??`Could not prepare connect link for ${c.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}function un(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var ee=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Cc(e){let n=e.oauthConfig;if(!n)throw new ee("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function mr(e,n){let t=T(e,()=>new ee("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ee("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new ee("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=ot(n,t.kek);if(!o)throw new ee("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=q(t,i,p=>new ee("plugin_not_found",p)),c=Cc(a),u=await U({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!u)throw new ee("client_id_not_configured",`client_id not configured for '${i}'`);let d=$e({oauthConfig:c,clientId:u,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:c.providerName,oauthUrl:d,state:n}}import{AsyncLocalStorage as Tc}from"async_hooks";import{randomBytes as Pc}from"crypto";import{v4 as Ac}from"uuid";async function pt(e,n){let t=en(e.projectApiKey),r={permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,expiresAt:n.expiresAt};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ve({deliveryUrl:n.deliveryUrl})),I({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:zn})}function gt(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var hr="Permission approval required. Set manual.approvalBaseUrl (or use hub for hosted approval) so an approval URL can be generated. Optionally set manual.onApprovalRequired to customize the agent message.";function kr(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Si(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function br(e){return gt(e)}async function wr(e,n){if(kr(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Si(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await pt(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:vc(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function vc(e){try{return JSON.parse(e)}catch{return e}}async function ft(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await wr(e,n);return{...n,approvalUrl:r}}async function Cr(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:c,tenantId:l,expiresAt:u,operationPath:d}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:c});let g=await wr({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(c),tenant_id:l,expires_at:u});return kr(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):br(g):hr:r?g?br(g):`Action '${d}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:hr}var _e=class extends Error{reason;constructor(n,t="pending"){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError",this.reason=t}};var Ei=new Tc,ln=class extends Error{endpointPath;riskLevel;constructor(n,t){super(`Action '${n}' is a '${t}' operation and is forbidden in readonly mode. Only read operations are permitted \u2014 rewrite the script to avoid write/destructive actions.`),this.name="ReadonlyForbiddenError",this.endpointPath=n,this.riskLevel=t}};function vr(e){return Ei.run(!0,e)}function Di(){return Ei.getStore()===!0}function Tr(e,n){if(Di()&&n!=="read")throw new ln(e,n)}var Rc={open:{read:"allow",write:"allow",destructive:"allow"},cautious:{read:"allow",write:"allow",destructive:"require_approval"},strict:{read:"allow",write:"require_approval",destructive:"deny"},readonly:{read:"allow",write:"deny",destructive:"deny"}};function xc(e,n,t){return t!==void 0?t:Rc[n][e]}function Pr(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let o=parseInt(r[1],10);switch(r[2]){case"d":t+=o*864e5;break;case"h":t+=o*36e5;break;case"m":t+=o*6e4;break;case"s":t+=o*1e3;break}}return t>0?t:600*1e3}function Oi(e){return{async find_by_permission_id(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst()},async find_by_token(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst()},async set_executing(n){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",n).execute()},async set_completed(n){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}}}async function _i(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!o)return{result:"blocked",reason:"pending"};if(o.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}};if(o.status==="denied")return{result:"blocked",reason:"denied"};if(o.status==="expired"||o.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function Mi(e){let n=xc(e.riskLevel,e.mode,e.override);if(n==="allow")return{result:"allow"};let t=e.meta?.irreversible?" (irreversible)":"",r=e.meta?.description?`${e.meta.description}${t}`:`${e.pluginId}.${e.endpointPath}${t}`;if(n==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
9
+ </script></body></html>`}var Fa=new Set(["localhost","127.0.0.1","[::1]","::1"]);function sr(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Fa.has(n)}catch{return!1}}function Pn(e){return e==="development"?"browser":"server"}function Yo(e){return Pn(e)==="browser"}function Qo(e){return sr(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as $a}from"crypto";var Ae=60*1e3,Fe=300*1e3;import{createHmac as Ua,randomBytes as Na,timingSafeEqual as La}from"crypto";function ge(){return Na(16).toString("base64url")}function An(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Ua("sha256",t).update(e).digest("base64url")}function ae(e,n){let t=n.trim();if(!t)return null;let r=e.split(".");if(r.length!==2)return null;let[o,i]=r;if(!o||!i)return null;let s=An(o,t);try{if(!La(Buffer.from(i,"utf8"),Buffer.from(s,"utf8")))return null}catch{return null}let a;try{a=JSON.parse(Buffer.from(o,"base64url").toString("utf8"))}catch{return null}return a.exp*1e3<Date.now()?null:a}function Yn(e,n,t){let r=Math.floor(Date.now()/1e3),o={...e,iat:r,exp:t},i=Buffer.from(JSON.stringify(o)).toString("base64url"),s=An(i,n);return`${i}.${s}`}function Rn(e,n,t){let r=Math.floor(Date.now()/1e3);return Yn(e,n,r+Math.floor(t/1e3))}function Ue(e){return decodeURIComponent(e)}function ar(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function Xo(e){let n=e.trim();return n.length>0?n:null}function Qe(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Xe(e,n){if(!Xo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??$a(16).toString("base64url"),iat:t,exp:t+Math.floor(Ae/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=An(o,n);return`${o}.${i}`}function Re(e,n){return Xo(n)?ae(e,n):null}function ja(e){let n=ir(e.hubOrigin),t={connectJti:e.requestId,projectId:e.projectId,hubSuccessUrl:e.hubOrigin,deliveryMode:e.deliveryMode,hubOrigin:n,requestId:e.requestId};switch(e.deliveryMode){case"connections.sync":return{...t,plugin:"connections.sync",tenantId:"*"};case"connect.create_link":return{...t,plugin:"connect.create_link",tenantId:e.tenantId,connectLinkPlugins:e.plugins}}}function cr(e){let n=Xe(ja(e),e.signingSecret);return Qe(e.deliveryUrl,n)}function ei(e){if(Pn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Wa(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:cr(r)}}var xn="https://auth.corsair.dev";var fe=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}},In=class extends Error{constructor(){super("Hub credentials are missing. Pass hub: { projectApiKey, signingSecret } to createCorsair() with non-empty values, or omit `hub` entirely if you are not using Corsair Hub."),this.name="HubCredentialsMissingError"}};function ur(e){let n=(e.apiUrl?.trim()||xn).replace(/\/$/,""),t=e.projectApiKey?.trim()??"",r=e.signingSecret?.trim()??"";if(!t||!r)throw new In;return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1,tunnel:e.tunnel}}function Qn(e){return ur(e)}function qa(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function F(e){let n=T(e).hub;if(!n||!qa(n))throw new fe;return n}function ni(e){return e.replace(/\/$/,"")}function Xn(e){return e.oauthCallbackUrl?ni(e.oauthCallbackUrl.trim()):`${ni(e.apiUrl)}/oauth/callback`}function en(e){if(e.startsWith("ck_dev_"))return"development";if(e.startsWith("ck_prod_"))return"production";if(e.startsWith("ck_cloud_"))return"cloud";throw new Error("Hub API key must start with ck_dev_ (development), ck_prod_ (production), or ck_cloud_ (cloud)")}import{createCipheriv as ti,createDecipheriv as ri,randomBytes as et,scrypt as Ka}from"crypto";import{promisify as Za}from"util";var oi=Za(Ka),nt="aes-256-gcm",ii=12,tt=16,Ga=16,Ne=32;function ye(){return et(Ne).toString("base64")}async function me(e,n){let t=et(Ga),r=await oi(n,t,Ne),o=et(ii),i=ti(nt,r,o,{authTagLength:tt}),s=Buffer.concat([i.update(e,"utf8"),i.final()]),a=i.getAuthTag();return[t.toString("base64"),o.toString("base64"),a.toString("base64"),s.toString("base64")].join(":")}async function X(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),u=await oi(n,s,Ne),d=ri(nt,u,a,{authTagLength:tt});return d.setAuthTag(c),Buffer.concat([d.update(l),d.final()]).toString("utf8")}function lr(e,n){let t=Buffer.from(n,"base64"),r=et(ii),o=ti(nt,t,r,{authTagLength:tt}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function Sn(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=ri(nt,i,s,{authTagLength:tt});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function xe(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=lr(o,n);return t}function he(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Sn(o,n);return t}function _n(e,n,t){let r=he(e,n);return xe(r,t)}function si(e,n,t){let r={};for(let o of t)r[`get_${o}`]=async()=>(await e())[o]??null,r[`set_${o}`]=async i=>{let s=[null,void 0,""].includes(i)?null:i;await n({[o]:s})};return r}var dr=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function U(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...W[n].integration,...i],a=null,c={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let k=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!k)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:k.id,config:dr(k.config),dek:k.dek??null},a},updateIntegration:async k=>{let b=await c.getIntegration();await o.db.updateTable("corsair_integrations").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",b.id).execute(),a=null}},l=null,u=async()=>{if(l)return l;let k=await c.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await X(k.dek,r),l},d=async()=>{let k=await c.getIntegration(),b=await u(),v=k.config;return!v||Object.keys(v).length===0?{}:he(v,b)},p=Promise.resolve(),g=k=>{let b=p.then(()=>f(k));return p=b.catch(()=>{}),b},f=async k=>{let b=await u(),v;try{v=await d()}catch(O){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,O),v={}}let P={...v};for(let[O,H]of Object.entries(k))H===null?delete P[O]:P[O]=H;let M=xe(P,b);await c.updateIntegration({config:M})};return{get_dek:u,issue_new_dek:async()=>{let k=await c.getIntegration(),b=ye(),v={};if(k.dek){let M=await X(k.dek,r),O=k.config;O&&Object.keys(O).length>0&&(v=_n(O,M,b))}let P=await me(b,r);return await c.updateIntegration({config:v,dek:P}),l=b,b},...si(d,g,s)}}function B(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,c=[...W[n].account,...s],l=null,u=null,d=async()=>{if(u)return u;let w=!1;for(;;){let A=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!A){if(!w&&a){w=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return u={id:A.id,config:dr(A.config),dek:A.dek??null},u}},p={kek:o,integrationName:t,tenantId:r,getIntegration:d,getAccount:async()=>{if(l)return l;let w=!1;for(;;){let A=await d(),R=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",A.id).executeTakeFirst();if(!R){if(!w&&a){w=!0,await a();continue}throw new Error(`Account not found for tenant "${r}" and integration "${t}". Make sure to create the account first.`)}return l={id:R.id,config:dr(R.config),dek:R.dek??null},l}},updateAccount:async w=>{let A=await p.getAccount();await i.db.updateTable("corsair_accounts").set({...w.config!==void 0?{config:w.config}:{},...w.dek!==void 0?{dek:w.dek}:{},updated_at:new Date}).where("id","=",A.id).execute(),l=null}},g=null,f=null,h=async()=>{if(g)return g;let w=await p.getAccount();if(!w.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await X(w.dek,o),g},k=async()=>{if(f)return f;let w=await p.getIntegration();if(!w.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await X(w.dek,o),f},b=async()=>{let w=await p.getAccount(),A=await h(),R=w.config;return!R||Object.keys(R).length===0?{}:he(R,A)},v=async()=>{let w=await p.getIntegration(),A=await k(),R=w.config;return!R||Object.keys(R).length===0?{}:he(R,A)},P=Promise.resolve(),M=w=>{let A=P.then(()=>O(w));return P=A.catch(()=>{}),A},O=async w=>{let A=await h(),R;try{R=await b()}catch(_){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,_),R={}}let Y={...R};for(let[_,oe]of Object.entries(w))oe===null?delete Y[_]:Y[_]=oe;let de=xe(Y,A);await p.updateAccount({config:de})},H={get_dek:h,issue_new_dek:async()=>{let w=await p.getAccount(),A=ye(),R={};if(w.dek){let de=await X(w.dek,o),_=w.config;_&&Object.keys(_).length>0&&(R=_n(_,de,A))}let Y=await me(A,o);return await p.updateAccount({config:R,dek:Y}),g=A,A},...si(b,M,c)};return n==="oauth_2"&&(H.get_integration_credentials=async()=>{let w=await v();return{...w,client_id:w.client_id||null,client_secret:w.client_secret||null,redirect_url:w.redirect_url??null}}),H}async function ai(e,n,t){let r=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!r)throw new Error(`Integration "${n}" not found.`);let o=ye(),i=await me(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function ci(e,n,t,r){let o=await e.db.selectFrom("corsair_integrations").selectAll().where("name","=",n).executeTakeFirst();if(!o)throw new Error(`Integration "${n}" not found.`);let i=await e.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",o.id).executeTakeFirst();if(!i)throw new Error(`Account not found for tenant "${t}" and integration "${n}".`);let s=ye(),a=await me(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var za=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function Ie(e){return za.has(e)}function Ja(e,n){return Ie(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Va(e){return!Ie(e)}function Ya(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function Qa(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function Xa(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!Ya(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function ui(e,n){if(!e)return!1;let t=V(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function ec(e,n){let r=e.authConfig?.[n]?.integration??[];return[...W[n].integration,...r]}function nc(e,n){let r=e.authConfig?.[n]?.account??[];return[...W[n].account,...r]}function tc(e,n,t){let r=t.filter(a=>a.required&&!a.configured).map(a=>a.name),o=t.filter(a=>a.level==="integration"&&a.required&&!a.configured).map(a=>a.name),i=t.filter(a=>a.level==="account"&&a.required&&a.configured),s;return o.length>0?s="missing_integration":r.length===0?s="ready":i.length>0?s="partial":s="not_started",{plugin:e,authType:n,status:s,connected:Xa(n,t),fields:t,missingRequiredFields:r}}async function Le(e,n,t){let r=S(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,s=i?.[r]?.integration??[],a=i?.[r]?.account??[],c=U({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=B({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),u=ec(n,r),d=nc(n,r),p=[];for(let g of u)p.push({name:g,level:"integration",required:Ja(r,g),configured:await ui(c,g)});for(let g of d)p.push({name:g,level:"account",required:Va(g),configured:await ui(l,g)});if(Qa(r,p)){let g=p.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return tc(n.id,r,p)}async function En(e,n,t={}){let r=n.trim()||"default",o=t.pluginIds?.length?new Set(t.pluginIds):null,i=[];for(let s of e.plugins){if(o&&!o.has(s.id))continue;let a=await Le(e,s,r);a&&i.push(a)}return i}function rt(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var li=Symbol.for("corsair:internal"),di=new WeakMap,pi=new WeakMap;function rc(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function oc(e){if(e.database){let t=di.get(e.database);return t||(t=new Map,di.set(e.database,t)),t}let n=pi.get(e);return n||(n=new Map,pi.set(e,n)),n}function ic(e){return e.multiTenancy?{withTenant:()=>({}),[li]:e}:{[li]:e}}async function nn(e,n){if(!e.database)return;let t=n.trim()||"default",r=oc(e),o=rc(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-F5KBWBTE.js");await a(ic(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import*as Dn from"crypto";function Se(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function pr(e,{maxAgeMs:n}={}){try{let t=e.includes(".")?e.split(".")[0]:e,r=JSON.parse(Buffer.from(t,"base64url").toString("utf-8"));if(r!==null&&typeof r=="object"&&"plugin"in r&&"tenantId"in r&&typeof r.plugin=="string"&&typeof r.tenantId=="string"){let o=r;return n!==void 0&&typeof o.iat=="number"&&Date.now()-o.iat>n?null:o}return null}catch{return null}}function tn(e,n){let t=Dn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var gr=600*1e3;function ot(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=Dn.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!Dn.timingSafeEqual(s,a)?null:pr(r,{maxAgeMs:gr})}function gi(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function fi(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType,status:e.status,connected:e.connected,verified:e.verified,missingFields:e.missingFields,webhookLink:e.webhookLink,webhookSecret:e.webhookSecret}}async function rn(e,n){await I({hub:e,path:"/connections/report",body:gi(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function sc(e,n){try{let t=F(e);I({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof fe)return}}async function ac(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!S(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Le(n,e.plugin,r);o&&mi(e.hub,fi({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function yi(e,n){sc(e,n)}function mi(e,n){I({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function on(e){ac(e).catch(()=>{})}async function be(e,n){let t=T(e);if(!S(n.plugin))return;let o=await Le(t,n.plugin,n.tenantId);o&&yi(e,fi({tenantId:n.tenantId.trim()||"default",plugin:n.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:n.verified??o.connected,missingFields:o.missingRequiredFields,webhookLink:n.webhookLink,webhookSecret:n.webhookSecret}))}async function it(e,n,t){for(let r of e){if(r.id!==n)continue;let o=r.oauthWebhookTenantLinkResolver;return o?o(t):null}return null}var hi=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function cc(e){let n=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.pluginId).executeTakeFirst();if(!n)throw new Error(`Integration '${e.pluginId}' not found. Run setupCorsair before registering webhook tenant links.`);let t=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",n.id).executeTakeFirst();if(!t)throw new Error(`Account not found for tenant '${e.tenantId}' and integration '${e.pluginId}'.`);return{integrationId:n.id,accountId:t.id}}async function uc(e){let n=await e.database.db.selectFrom("corsair_accounts").selectAll().where("id","=",e.accountId).executeTakeFirst();if(!n?.dek)throw new Error(`Account '${e.accountId}' has no DEK.`);let t=await X(n.dek,e.kek),r=hi(n.config),o={};Object.keys(r).length>0&&(o=he(r,t)),o[e.link.linkType]=e.link.externalId;let i=xe(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function sn(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await cc({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let u=B({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),d=`set_${i.linkType}`,p=u[d];typeof p=="function"&&(await p(i.externalId),l=!0)}l||await uc({database:n,kek:t,accountId:c,link:i})}async function fr(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let c=await X(a.dek,t),u=hi(a.config)[o];if(!u)continue;if(Sn(u,c)===i)return a}catch{continue}return null}async function st(e){return(await fr(e))?.tenant_id??null}async function bi(e){return st({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as ki from"querystring";function $e(e){let{oauthConfig:n,clientId:t,redirectUri:r,state:o}=e,i={...n.authParams,client_id:t,redirect_uri:r,response_type:"code",scope:n.scopes.join(" "),state:o};return`${n.authUrl}?${ki.stringify(i)}`}async function wi(e,n){try{return await j({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function an(e,n,t,r){if(!n.subscribe)return;let o=F(e),i=await wi(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await be(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var K=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ci(e){let n=e.oauthConfig;if(!n)throw new K("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function lc(e,n,t,r){await e.db.transaction().execute(async o=>{let i=o.selectFrom("corsair_integrations").select(["id"]).where("name","=",n);e.isPg===!0&&(i=i.forUpdate());let s=await i.executeTakeFirst();if(!s)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.selectFrom("corsair_accounts").select("id").where("tenant_id","=",t).where("integration_id","=",s.id).executeTakeFirst())return;let c=ye(),l=await me(c,r),u=new Date;await o.insertInto("corsair_accounts").values({id:Je(),created_at:u,updated_at:u,tenant_id:t,integration_id:s.id,config:{},dek:l}).execute()})}async function yr(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=T(e,()=>new K("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=q(s,n,p=>new K("plugin_not_found",p)),c=Ci(a),u=await U({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!u)throw new Error(`client_id not configured for '${n}'`);if(i){let p=new URL($e({oauthConfig:c,clientId:u,redirectUri:o,state:""}));return p.searchParams.delete("state"),{url:p.toString(),state:""}}let d=tn(Se(n,r),s.kek);return{url:$e({oauthConfig:c,clientId:u,redirectUri:o,state:d}),state:d}}function dc(e,n){return{...n??{},...e}}async function On(e,n){let{code:t,state:r,redirectUri:o}=n,i=T(e,()=>new K("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new K("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let h=ot(r,i.kek);if(!h)throw new K("invalid_state","Invalid or tampered state parameter");s=h.plugin,a=h.tenantId}if(!i.database)throw new K("no_database","No database configured on corsair instance");let c=q(i,s,h=>new K("plugin_not_found",h)),l=Ci(c),u=U({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),d=await u.get_client_id(),p=await u.get_client_secret();if(!d||!p)throw new K("credentials_not_configured",`Credentials not configured for '${s}'`);await lc(i.database,s,a,i.kek);let g=await at(t,d,p,l,o);if(!g.access_token)throw new K("no_access_token",`No access_token returned from ${l.providerName}`);let f=B({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...c.authConfig?.oauth_2?.account??[]]});await f.set_access_token(g.access_token),g.refresh_token&&await f.set_refresh_token(g.refresh_token),g.expires_in&&await f.set_expires_at(String(Math.floor(Date.now()/1e3)+g.expires_in)),await be(e,{plugin:c,tenantId:a}).catch(()=>{});try{let h=dc(g,n.callbackParams),k=await it(i.plugins,s,h);if(k){try{let b=c.authConfig?.oauth_2?.account??[];await sn({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:k,authType:"oauth_2",extraAccountFields:b})}catch(b){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,b)}i.hub&&rn(i.hub,{plugin:s,tenantId:a,link:k,authType:"oauth_2"})}}catch(h){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,h)}if(c.subscribe)try{await an(e,c,a,f)}catch(h){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,h)}return{plugin:s,tenantId:a}}async function pc(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??an,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let c=t.plugins.find(u=>u.id===a.integrationName);if(!c?.subscribe)continue;let l=`${c.id}/${a.tenantId}`;try{let u=S(c)??"oauth_2",d=B({authType:u,integrationName:c.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...c.authConfig?.[u]?.account??[]]}),p=c.keyBuilder;if(p){let g=Object.create(d,{get_expires_at:{value:async()=>"0"}});await p({authType:u,keys:g,hub:t.hub},"endpoint")}await o(n,c,a.tenantId,d),i.push(l)}catch(u){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,u),s.push(l)}}return{renewed:i,failed:s}}async function vi(e){let n=T(e);if(!n.database)return{renewed:[],failed:[]};let t=await n.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id as tenantId","i.name as integrationName"]).where("a.dek","is not",null).execute();return pc({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function gc(e,n={}){let t=!1,r=()=>{t||(t=!0,vi(e).catch(i=>console.warn("[corsair:renewal] renewal pass failed:",i)).finally(()=>{t=!1}))};r();let o=setInterval(r,(n.intervalMinutes??45)*6e4);return o.unref?.(),()=>clearInterval(o)}async function Ti(e){if(!T(e).database)throw new Error("A database must be configured to provision Corsair integrations");await ct(e,{silent:!0})}async function cn(e,n){let t=T(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await nn(t,n)}var fc=Symbol.for("corsair:internal"),yc=new Set(["access_token","refresh_token","expires_at","scope"]);function mc(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function hc(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!Ie(t)&&!yc.has(t)):n.filter(t=>!Ie(t))}function Pi(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function bc(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function kc(e){return{[fc]:Pi(e)}}async function ut(e,n,t={}){let r=Xn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Pi(e),a=kc(e);for(let c of e.plugins){if(i&&!i.has(c.id))continue;let l=S(c);if(!l)continue;let u=mc(l),d=t.providerNameOverrides?.[c.id]??Pe(c.id),p=await Le(s,c,n),g=qn(c,l),f=hc(l,g),h={plugin:c.id,providerName:d,authKind:u,alreadyConfigured:p?.connected??!1};if(f.length>0&&(h.credentialFields=f),u==="oauth"){let b=t.oauthModeOverrides?.[c.id]??(l==="managed"?"managed":"byo");if(h.oauthMode=b,!t.skipOAuthUrlGeneration&&b!=="managed")try{let v=await yr(a,c.id,{tenantId:n,redirectUri:r,hubConnect:!0});h.oauthUrl=v.url}catch(v){v instanceof Error&&/client_id not configured/i.test(v.message)||(h.setupError=v instanceof Error?v.message:`Could not prepare OAuth for ${c.id}`)}}o.push(h)}return o}async function Ag(e,n,t={}){let r=T(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return ut({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function Ai(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await nn(e.internalConfig??bc(e),n)}async function Ri(e,n){await cn(e,n)}async function xi(e,n){let t=en(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ve({deliveryUrl:n.deliveryUrl})),I({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:Zn})}async function Ii(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await Ai(t,n.tenantId);let r=await ut(t,n.tenantId,{pluginIds:[n.plugin.id]});if(r.length===0)throw new Error(`Plugin '${n.plugin.id}' is not configured on this Corsair instance`);return xi(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function lt(e,n){let t=T(e),r=F(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await Ri(e,n.tenantId);let i=n.plugin?[n.plugin]:void 0,s=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,a=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,c=await ut(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(c.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return xi(r,{tenantId:n.tenantId,plugins:c,deliveryUrl:n.deliveryUrl})}async function dt(e,n){let t=n.tenantId.trim();if(!t)throw new Error("tenantId is required");let r=n.plugins.map(s=>s.trim()).filter(Boolean);if(r.length===0)throw new Error("At least one plugin is required");let o=T(e);if(!o.hub)throw new Error("Hub is not configured on this Corsair instance");if(!o.database)throw new Error("Database not configured");let i=await wc(o.hub,{plugins:o.plugins,database:o.database,kek:o.kek,multiTenancy:o.multiTenancy},{tenantId:t,pluginIds:r});return{connectUrl:i.connectUrl,expiresAt:i.expiresAt}}async function wc(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-H6TCRLGW.js"),{postHubConnectSession:i}=await import("./connect-KHX6PKUD.js"),s={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await o(s,t.tenantId);let a=await r(s,t.tenantId,{pluginIds:t.pluginIds});if(a.length===0)throw new Error("No connectable plugins found for this tenant");let c=a.find(l=>l.setupError);if(c)throw new Error(c.setupError??`Could not prepare connect link for ${c.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}function un(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var ee=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Cc(e){let n=e.oauthConfig;if(!n)throw new ee("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function mr(e,n){let t=T(e,()=>new ee("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ee("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new ee("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=ot(n,t.kek);if(!o)throw new ee("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=q(t,i,p=>new ee("plugin_not_found",p)),c=Cc(a),u=await U({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!u)throw new ee("client_id_not_configured",`client_id not configured for '${i}'`);let d=$e({oauthConfig:c,clientId:u,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:c.providerName,oauthUrl:d,state:n}}import{AsyncLocalStorage as Tc}from"async_hooks";import{randomBytes as Pc}from"crypto";import{v4 as Ac}from"uuid";async function pt(e,n){let t=en(e.projectApiKey),r={permissionId:n.permissionId,permissionToken:n.permissionToken,plugin:n.plugin,endpoint:n.endpoint,args:n.args,tenantId:n.tenantId,expiresAt:n.expiresAt};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ve({deliveryUrl:n.deliveryUrl})),I({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:zn})}function gt(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var hr="Permission approval required. Set manual.approvalBaseUrl (or use hub for hosted approval) so an approval URL can be generated. Optionally set manual.onApprovalRequired to customize the agent message.";function kr(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Si(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function br(e){return gt(e)}async function wr(e,n){if(kr(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Si(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await pt(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:vc(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function vc(e){try{return JSON.parse(e)}catch{return e}}async function ft(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await wr(e,n);return{...n,approvalUrl:r}}async function Cr(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:c,tenantId:l,expiresAt:u,operationPath:d}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:c});let g=await wr({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(c),tenant_id:l,expires_at:u});return kr(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):br(g):hr:r?g?br(g):`Action '${d}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:hr}var _e=class extends Error{reason;constructor(n,t="pending"){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError",this.reason=t}};var Ei=new Tc,ln=class extends Error{endpointPath;riskLevel;constructor(n,t){super(`Action '${n}' is a '${t}' operation and is forbidden in readonly mode. Only read operations are permitted \u2014 rewrite the script to avoid write/destructive actions.`),this.name="ReadonlyForbiddenError",this.endpointPath=n,this.riskLevel=t}};function vr(e){return Ei.run(!0,e)}function Di(){return Ei.getStore()===!0}function Tr(e,n){if(Di()&&n!=="read")throw new ln(e,n)}var Rc={open:{read:"allow",write:"allow",destructive:"allow"},cautious:{read:"allow",write:"allow",destructive:"require_approval"},strict:{read:"allow",write:"require_approval",destructive:"deny"},readonly:{read:"allow",write:"deny",destructive:"deny"}};function xc(e,n,t){return t!==void 0?t:Rc[n][e]}function Pr(e){let n=/(\d+)(d|h|m|s)/g,t=0,r;for(;(r=n.exec(e))!==null;){let o=parseInt(r[1],10);switch(r[2]){case"d":t+=o*864e5;break;case"h":t+=o*36e5;break;case"m":t+=o*6e4;break;case"s":t+=o*1e3;break}}return t>0?t:600*1e3}function Oi(e){return{async find_by_permission_id(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst()},async find_by_token(n){if(e)return e.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst()},async set_executing(n){e&&await e.db.updateTable("corsair_permissions").set({status:"executing",updated_at:new Date}).where("id","=",n).execute()},async set_completed(n){e&&await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}}}async function _i(e,n,t){let r=Date.now()+t;for(;Date.now()<r;){let o=await e.db.selectFrom("corsair_permissions").select(["id","status"]).where("id","=",n).executeTakeFirst();if(!o)return{result:"blocked",reason:"pending"};if(o.status==="approved")return{result:"allow",onComplete:async()=>{await e.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",n).execute()}};if(o.status==="denied")return{result:"blocked",reason:"denied"};if(o.status==="expired"||o.status==="failed")return{result:"blocked",reason:"timeout"};await new Promise(i=>setTimeout(i,500))}return{result:"blocked",reason:"timeout"}}async function Mi(e){let n=xc(e.riskLevel,e.mode,e.override);if(n==="allow")return{result:"allow"};let t=e.meta?.irreversible?" (irreversible)":"",r=e.meta?.description?`${e.meta.description}${t}`:`${e.pluginId}.${e.endpointPath}${t}`;if(n==="deny"||!e.db)return console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 denied by permission mode '${e.mode}'.`,`
10
10
  Action: ${r}`,`
11
11
  To allow this, update the permission mode or add an override in your corsair config.`),{result:"blocked",reason:"policy"};let o=JSON.stringify(e.args),i=new Date().toISOString(),s=e.tenantId??"default",a=await e.db.db.selectFrom("corsair_permissions").selectAll().where("plugin","=",e.pluginId).where("endpoint","=",e.endpointPath).where("args","=",o).where("tenant_id","=",s).where("expires_at",">",i).where("status","in",["pending","approved","executing"]).orderBy("created_at","desc").limit(1).executeTakeFirst();if(a){if(a.status==="approved"){let f=e.db,h=a.id;return{result:"allow",onComplete:async()=>{await f.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",h).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
12
12
  Action: ${r}`,`
@@ -59,7 +59,7 @@ ${ha(o,d)}`),h.join(`
59
59
  `)}}}return Ao(ze(e),"Path not found. Available operations")}function da(e){let n=e;for(;;){let t=te(n),r=re(t);if(So(r)){let o=ne(t);if(!o)return n;n=o;continue}return n}}function Cn(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=da(e),t=te(n);if(re(t)==="ZodObject"){let o=Zt(n,t),i=[];for(let[s,a]of Object.entries(o)){let c=te(a),l=re(c),u=l==="ZodOptional"||l==="ZodNullable",d=da(a),p=Tl(a);i.push({key:s,optional:u,type:J(d),...p!==void 0?{description:p}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:J(n)}}function Kt(e,n=0){if(e===void 0)return"{}";if(e.kind==="inline")return e.type;if(e.kind==="object"){if(e.fields.length===0)return"{}";let t=la.repeat(n+1),r=la.repeat(n);return`{
60
60
  ${e.fields.map(i=>{let s=i.optional?`${i.key}?`:i.key,a=i.description?` // ${i.description}`:"";return`${t}${s}: ${i.type}${a}`}).join(`
61
61
  `)}
62
- ${r}}`}return"unknown"}function Sl(e,n){let t=ze(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(u=>u.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let u of t){let{shortPath:d,lookupKey:p}=Il(u,n),g=Me(r.endpointMeta,p),f=Me(r.endpointSchemas,p);!g&&!f||o.push({path:u,shortPath:d,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Cn(f?.input),output:Cn(f?.output)})}o.sort((u,d)=>u.path.localeCompare(d.path));let i=[],s=ze(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let u of s){let p=u.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),h=Do(r.webhooks,f.split("."));if(h===null)continue;let k=h.join("."),b=Me(r.webhookSchemas,k.toLowerCase()),v=b?.response?J(b.response):void 0;i.push({path:u,description:b?.description,payload:Cn(b?.payload),responseType:v,usageExample:ha(n,h)})}i.sort((u,d)=>u.path.localeCompare(d.path));let a=[],c=ze(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(c)&&l)for(let u of c){let p=u.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("db."))continue;let f=g.slice(3),h=f.lastIndexOf(".");if(h===-1)continue;let k=f.slice(0,h);if(f.slice(h+1)!=="search")continue;let v=ma(l,k);if(!v)continue;let[P,M]=v,O=Eo(M),H=Object.entries(O).map(([w,A])=>({field:w,type:A.type,operators:A.operators}));a.push({path:u,entityName:P,filters:[{field:"entity_id",type:"string",operators:_o},...H]})}return a.sort((u,d)=>u.path.localeCompare(d.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as ba}from"crypto";async function _l(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=ba(),o=ba(),i=await fetch(n.watchUrl,{method:"POST",signal:AbortSignal.timeout(2e4),headers:{authorization:`Bearer ${t}`,"content-type":"application/json"},body:JSON.stringify({id:r,type:"web_hook",address:n.webhookUrl,token:o,...n.body})});if(!i.ok)throw new Error(`Google channel watch failed (${i.status}): ${await i.text()}`);return{webhookLink:{linkType:"channel_id",externalId:r},webhookSecret:o}}import{randomUUID as El}from"crypto";var Gt="https://graph.microsoft.com/v1.0",Oo=2e4,Dl=60;async function Ol(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let c=await fetch(`${Gt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Oo)});if(c.ok){let{value:l}=await c.json(),u=(l??[]).filter(d=>d.notificationUrl===n.webhookUrl);await Promise.all(u.map(d=>fetch(`${Gt}/subscriptions/${d.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Oo)}).catch(()=>{})))}}catch{}let o=El(),i=new Date(Date.now()+Dl*6e4).toISOString(),s=await fetch(`${Gt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Oo),body:JSON.stringify({changeType:n.changeType,notificationUrl:n.webhookUrl,resource:n.resource,expirationDateTime:i,clientState:o})});if(!s.ok)throw new Error(`MS Graph subscribe failed (${s.status}): ${await s.text()}`);let a=await s.json();return a.id?(await e.keys.set_webhook_signature(o),{webhookLink:{linkType:"subscription_id",externalId:a.id},webhookSecret:o}):null}function ka(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Ml(e,n){let t=ka(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let o=r.pluginTenantWebhookMatcher(n);return o?{plugin:t,tenantMatch:o}:null}function Hl(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function wa(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Ca(e){if(typeof e=="string"){let n=e.trim();return n.length>0?n:void 0}if(typeof e=="number"&&Number.isFinite(e))return String(e)}function jn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function Bl(e){return jn(e.body)}function va(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return zt(Array.isArray(r)?r:[r])}function Ta(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=zt(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=va({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let c of o){let l=n[c],u=Array.isArray(l)?l[0]:l;if(!(!u||typeof u!="string"))try{let p=(u.startsWith("http")?new URL(u):new URL(`https://example.invalid${u.startsWith("/")?u:`/${u}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=jn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return zt([s?.validationToken])??null}function Fl(e){if(Ta(e))return!0;let n=jn(e.body??e.payload);return wa(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function zt(e){for(let n of e){let t=Ca(n);if(t)return t}}function Ul(e){let t=jn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Wn=Symbol.for("corsair:internal");function xa(e){let n=e.database?Fo(e.database):void 0,t=e.kek,r=n&&t?Hs(e.plugins,n,t):Lt(!!n,!!t),o=Bs(e),i={plugins:e.plugins,database:n,kek:t,multiTenancy:!!e.multiTenancy,permissions:o,manual:e.manual,hub:e.hub?Qn(e.hub):void 0},s=Oi(n),a=ra(i);if(e.multiTenancy){let u=Object.assign({withTenant:d=>{if(!d)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let p=To(e.plugins,{database:n,tenantId:d,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i});return Object.assign(p,{[Wn]:i})},keys:r,permissions:s,manage:a},{[Wn]:i});return Pa(u,i.hub),Ra(u,i.hub),u}let c=To(e.plugins,{database:n,tenantId:void 0,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i}),l=Object.assign({},c,{keys:r,permissions:s,manage:a,[Wn]:i});return Pa(l,i.hub),Ra(l,i.hub),l}function Pa(e,n){n?.projectApiKey?.startsWith("ck_dev_")&&import("./loop-ZHQU6EL6.js").then(t=>t.startConnectLoop(e)).catch(()=>{})}function Nl(e){return e?.projectApiKey?.startsWith("ck_dev_")?e.tunnel!==!1&&process.env.CORSAIR_TUNNEL!=="0":!1}var Aa=globalThis.__corsairTunnels??=new Set,Ll=1e3,$l=3e4;function Wl(e){let n=e.schedule??((s,a)=>void setTimeout(s,a).unref?.()),t=e.minDelayMs??Ll,r=e.maxDelayMs??$l,o=t,i=()=>{let s=!1,a=()=>{s||(s=!0,n(i,o),o=Math.min(o*2,r))};e.start(a).then(()=>{o=t}).catch(a)};i()}function Ra(e,n){if(!Nl(n))return;let t=n.projectApiKey;if(Aa.has(t))return;let r=Number(process.env.PORT);if(!Number.isInteger(r)||r<1||r>65535){console.error("[corsair] PORT is not set \u2014 dev tunnel skipped. Set PORT to your app port, or run `corsair http <port>`.");return}Aa.add(t);let o=typeof n.tunnel=="object"?n.tunnel:{},i=process.env.CORSAIR_FRP_HOST??o.shareHost??Qt;Wl({start:s=>import("./hub/tunnel/run-tunnel.js").then(a=>a.runTunnel({port:r,apiUrl:n.apiUrl,apiKey:t,shareHost:i,onClose:s})).then(({url:a})=>{console.log(`[corsair] tunnel active: ${a}${Xt}`)}).catch(a=>{throw console.warn(`[corsair] tunnel down: ${a instanceof Error?a.message:String(a)}. Retrying \u2014 run \`corsair setup\` if it doesn't recover.`),a})})}var jl={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},repositories:{list:{}}},discord:{guilds:{list:{}},channels:{list:{}}},hubspot:{contacts:{getMany:{}},companies:{getMany:{}},deals:{getMany:{}}},gmail:{messages:{list:{}},labels:{list:{}},drafts:{list:{}},threads:{list:{}}},googlecalendar:{events:{getMany:{}}},googlemeet:{conferenceRecords:{list:{}}},googledrive:{files:{list:{}},folders:{list:{}},sharedDrives:{list:{}}},notion:{databases:{getManyDatabases:{}},databasePages:{getManyDatabasePages:{}},users:{getManyUsers:{}}},airtable:{bases:{getMany:{}}},todoist:{projects:{getMany:{}},tasks:{getMany:{}}},cal:{bookings:{list:{}}},zohomail:{folders:{list:{}},messages:{list:{}}}},Mo=jl;async function ct(e,n){let t=[],r=n?.silent??!1,o=g=>{t.push(g),r||console.log(g)},i=g=>{t.push(g),r||console.warn(g)},s=n?.caller??"script",a=No(e);if(!a)throw new Error("setupCorsair: invalid corsair instance");if(!a.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let c=nd(e,a.plugins,n),l={...a,database:a.database},u=l.database.db;await od(u,i);let d=await id(u,l,c.tenantId,c.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await cd(e,c,n.credentials,l,o,i);let p=await ld(d,c,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=xa({plugins:a.plugins,database:u,kek:a.kek,multiTenancy:!0}).withTenant(c.tenantId);await dd(g,a.plugins,p,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
62
+ ${r}}`}return"unknown"}function Sl(e,n){let t=ze(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(u=>u.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let u of t){let{shortPath:d,lookupKey:p}=Il(u,n),g=Me(r.endpointMeta,p),f=Me(r.endpointSchemas,p);!g&&!f||o.push({path:u,shortPath:d,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Cn(f?.input),output:Cn(f?.output)})}o.sort((u,d)=>u.path.localeCompare(d.path));let i=[],s=ze(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let u of s){let p=u.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),h=Do(r.webhooks,f.split("."));if(h===null)continue;let k=h.join("."),b=Me(r.webhookSchemas,k.toLowerCase()),v=b?.response?J(b.response):void 0;i.push({path:u,description:b?.description,payload:Cn(b?.payload),responseType:v,usageExample:ha(n,h)})}i.sort((u,d)=>u.path.localeCompare(d.path));let a=[],c=ze(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(c)&&l)for(let u of c){let p=u.toLowerCase().slice(n.length+1),g=p.startsWith(".")?p.slice(1):p;if(!g.startsWith("db."))continue;let f=g.slice(3),h=f.lastIndexOf(".");if(h===-1)continue;let k=f.slice(0,h);if(f.slice(h+1)!=="search")continue;let v=ma(l,k);if(!v)continue;let[P,M]=v,O=Eo(M),H=Object.entries(O).map(([w,A])=>({field:w,type:A.type,operators:A.operators}));a.push({path:u,entityName:P,filters:[{field:"entity_id",type:"string",operators:_o},...H]})}return a.sort((u,d)=>u.path.localeCompare(d.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as ba}from"crypto";async function _l(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=ba(),o=ba(),i=await fetch(n.watchUrl,{method:"POST",signal:AbortSignal.timeout(2e4),headers:{authorization:`Bearer ${t}`,"content-type":"application/json"},body:JSON.stringify({id:r,type:"web_hook",address:n.webhookUrl,token:o,...n.body})});if(!i.ok)throw new Error(`Google channel watch failed (${i.status}): ${await i.text()}`);return{webhookLink:{linkType:"channel_id",externalId:r},webhookSecret:o}}import{randomUUID as El}from"crypto";var Gt="https://graph.microsoft.com/v1.0",Oo=2e4,Dl=60;async function Ol(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let c=await fetch(`${Gt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Oo)});if(c.ok){let{value:l}=await c.json(),u=(l??[]).filter(d=>d.notificationUrl===n.webhookUrl);await Promise.all(u.map(d=>fetch(`${Gt}/subscriptions/${d.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Oo)}).catch(()=>{})))}}catch{}let o=El(),i=new Date(Date.now()+Dl*6e4).toISOString(),s=await fetch(`${Gt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Oo),body:JSON.stringify({changeType:n.changeType,notificationUrl:n.webhookUrl,resource:n.resource,expirationDateTime:i,clientState:o})});if(!s.ok)throw new Error(`MS Graph subscribe failed (${s.status}): ${await s.text()}`);let a=await s.json();return a.id?(await e.keys.set_webhook_signature(o),{webhookLink:{linkType:"subscription_id",externalId:a.id},webhookSecret:o}):null}function ka(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Ml(e,n){let t=ka(e,n);if(!t)return null;let r=e[t];if(!r?.pluginTenantWebhookMatcher)return null;let o=r.pluginTenantWebhookMatcher(n);return o?{plugin:t,tenantMatch:o}:null}function Hl(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function wa(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Ca(e){if(typeof e=="string"){let n=e.trim();return n.length>0?n:void 0}if(typeof e=="number"&&Number.isFinite(e))return String(e)}function jn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function Bl(e){return jn(e.body)}function va(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return zt(Array.isArray(r)?r:[r])}function Ta(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=zt(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=va({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let c of o){let l=n[c],u=Array.isArray(l)?l[0]:l;if(!(!u||typeof u!="string"))try{let p=(u.startsWith("http")?new URL(u):new URL(`https://example.invalid${u.startsWith("/")?u:`/${u}`}`)).searchParams.get("validationToken");if(p?.trim())return p.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=jn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return zt([s?.validationToken])??null}function Fl(e){if(Ta(e))return!0;let n=jn(e.body??e.payload);return wa(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function zt(e){for(let n of e){let t=Ca(n);if(t)return t}}function Ul(e){let t=jn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var Wn=Symbol.for("corsair:internal");function xa(e){let n=e.database?Fo(e.database):void 0,t=e.kek,r=n&&t?Hs(e.plugins,n,t):Lt(!!n,!!t),o=Bs(e),i={plugins:e.plugins,database:n,kek:t,multiTenancy:!!e.multiTenancy,permissions:o,manual:e.manual,hub:e.hub?Qn(e.hub):void 0},s=Oi(n),a=ra(i);if(e.multiTenancy){let u=Object.assign({withTenant:d=>{if(!d)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let p=To(e.plugins,{database:n,tenantId:d,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i});return Object.assign(p,{[Wn]:i})},keys:r,permissions:s,manage:a},{[Wn]:i});return Pa(u,i.hub),Ra(u,i.hub),u}let c=To(e.plugins,{database:n,tenantId:void 0,kek:t,rootErrorHandlers:e.errorHandlers,permissionsOptions:o,manualConfig:e.manual,hubConfig:i.hub,internalConfig:i}),l=Object.assign({},c,{keys:r,permissions:s,manage:a,[Wn]:i});return Pa(l,i.hub),Ra(l,i.hub),l}function Pa(e,n){n?.projectApiKey?.startsWith("ck_dev_")&&import("./loop-2KDDOHJ4.js").then(t=>t.startConnectLoop(e)).catch(()=>{})}function Nl(e){return e?.projectApiKey?.startsWith("ck_dev_")?e.tunnel!==!1&&process.env.CORSAIR_TUNNEL!=="0":!1}var Aa=globalThis.__corsairTunnels??=new Set,Ll=1e3,$l=3e4;function Wl(e){let n=e.schedule??((s,a)=>void setTimeout(s,a).unref?.()),t=e.minDelayMs??Ll,r=e.maxDelayMs??$l,o=t,i=()=>{let s=!1,a=()=>{s||(s=!0,n(i,o),o=Math.min(o*2,r))};e.start(a).then(()=>{o=t}).catch(a)};i()}function Ra(e,n){if(!Nl(n))return;let t=n.projectApiKey;if(Aa.has(t))return;let r=Number(process.env.PORT);if(!Number.isInteger(r)||r<1||r>65535){console.error("[corsair] PORT is not set \u2014 dev tunnel skipped. Set PORT to your app port, or run `corsair http <port>`.");return}Aa.add(t);let o=typeof n.tunnel=="object"?n.tunnel:{},i=process.env.CORSAIR_FRP_HOST??o.shareHost??Qt;Wl({start:s=>import("./hub/tunnel/run-tunnel.js").then(a=>a.runTunnel({port:r,apiUrl:n.apiUrl,apiKey:t,shareHost:i,onClose:s})).then(({url:a})=>{console.log(`[corsair] tunnel active: ${a}${Xt}`)}).catch(a=>{throw console.warn(`[corsair] tunnel down: ${a instanceof Error?a.message:String(a)}. Retrying \u2014 run \`corsair setup\` if it doesn't recover.`),a})})}var jl={slack:{channels:{list:{}},users:{list:{}}},linear:{projects:{list:{}},issues:{list:{}},users:{list:{}}},github:{issues:{list:{}},repositories:{list:{}}},discord:{guilds:{list:{}},channels:{list:{}}},hubspot:{contacts:{getMany:{}},companies:{getMany:{}},deals:{getMany:{}}},gmail:{messages:{list:{}},labels:{list:{}},drafts:{list:{}},threads:{list:{}}},googlecalendar:{events:{getMany:{}}},googlemeet:{conferenceRecords:{list:{}}},googledrive:{files:{list:{}},folders:{list:{}},sharedDrives:{list:{}}},notion:{databases:{getManyDatabases:{}},databasePages:{getManyDatabasePages:{}},users:{getManyUsers:{}}},airtable:{bases:{getMany:{}}},todoist:{projects:{getMany:{}},tasks:{getMany:{}}},cal:{bookings:{list:{}}},zohomail:{folders:{list:{}},messages:{list:{}}}},Mo=jl;async function ct(e,n){let t=[],r=n?.silent??!1,o=g=>{t.push(g),r||console.log(g)},i=g=>{t.push(g),r||console.warn(g)},s=n?.caller??"script",a=No(e);if(!a)throw new Error("setupCorsair: invalid corsair instance");if(!a.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let c=nd(e,a.plugins,n),l={...a,database:a.database},u=l.database.db;await od(u,i);let d=await id(u,l,c.tenantId,c.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await cd(e,c,n.credentials,l,o,i);let p=await ld(d,c,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=xa({plugins:a.plugins,database:u,kek:a.kek,multiTenancy:!0}).withTenant(c.tenantId);await dd(g,a.plugins,p,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
63
63
  `)}function Ho(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...W[n][t],...r])}function ed(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let o=n.find(a=>a.id===t);if(!o)continue;let i=S(o);if(!i)continue;let s=Ho(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function nd(e,n,t){let r=Lo(e),o=t?.tenantId?.trim(),i=o!==void 0&&o.length>0;if(r&&t?.backfill&&!i)throw new Error("setupCorsair: tenantId is required for backfill on a multi-tenant instance");if(r&&ed(t?.credentials,n)&&!i)throw new Error("setupCorsair: tenantId is required when setting account-level credentials on a multi-tenant instance");if(i&&!o)throw new Error("setupCorsair: tenantId must be a non-empty string");return{multiTenant:r,tenantIdProvided:i,tenantId:i?o:"default",provisionAccounts:!r||i}}function Sa(e,n){return Te(e)?n===0?!0:Object.values(e).every(t=>Sa(t,n-1)):!1}function td(e){return Sa(e,4)}var rd=Wo;function Jt(e){if(e instanceof Jl){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Xl?Jt(r):"unknown";return n}return e instanceof Gl?`${Jt(e.unwrap())} | null`:e instanceof Vl?`${Jt(e.unwrap())} | undefined`:e instanceof Zl?e.options.join(" | "):e instanceof Ql?"string":e instanceof zl?"number":e instanceof ql?"boolean":e instanceof Kl?"date":e instanceof Yl?"jsonb":"unknown"}async function od(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(rd))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
64
64
  Schema: ${JSON.stringify(Jt(i),null,2)}`)}async function id(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let c=a.id,l=S(a),u=await e.selectFrom("corsair_integrations").selectAll().where("name","=",c).executeTakeFirst();if(!u){let h=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:h,name:c,config:{},created_at:i,updated_at:i}).execute(),u=await e.selectFrom("corsair_integrations").selectAll().where("id","=",h).executeTakeFirst(),o(`[corsair:setup] Created integration: ${c}`)}let d=l?a.authConfig?.[l]?.integration??[]:[],p=l?a.authConfig?.[l]?.account??[]:[],g=l&&u?U({authType:l,integrationName:c,kek:n.kek,database:n.database,extraIntegrationFields:d}):void 0;if(u&&!u.dek&&g&&(await g.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${c}`)),!u||!l||!g)continue;let f;if(r){let h=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",u.id).executeTakeFirst();if(!h){let k=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:k,tenant_id:t,integration_id:u.id,config:{},created_at:i,updated_at:i}).execute(),h=await e.selectFrom("corsair_accounts").selectAll().where("id","=",k).executeTakeFirst(),o(`[corsair:setup] Created account: ${c}`)}f=h&&B({authType:l,integrationName:c,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:p}),h&&f&&!h.dek&&(await f.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${c}`))}s.set(c,{pluginId:c,authType:l,integration:g,account:f,integrationFields:[...W[l].integration,...d],accountFields:r?[...W[l].account,...p]:[]})}return s}function sd(e){if(!Te(e))return;let n=e.keys;return Te(n)?n:void 0}function ad(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function cd(e,n,t,r,o,i){let s=sd(e),a=n.provisionAccounts?ad(e,n.tenantId):void 0;for(let[c,l]of Object.entries(t)){let u=r.plugins.find(b=>b.id===c);if(!u){i(`[corsair:setup] Unknown plugin '${c}' \u2014 skipping credentials.`);continue}let d=S(u);if(!d){i(`[corsair:setup] Plugin '${c}' has no auth type \u2014 skipping credentials.`);continue}let p=Ho(u,d,"integration"),g=Ho(u,d,"account"),f=s?.[c],h=a?.[c],k=Te(h)?h.keys:void 0;for(let[b,v]of Object.entries(l))if(v){if(p.has(b)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${c}.${b}' is an integration-level credential shared across all tenants. You passed tenantId="${n.tenantId}", which only scopes account-level credentials. Run setup without --tenant if you intend to change this credential globally.`);let P=V(f,`set_${b}`);if(!P){i(`[corsair:setup] Cannot set integration field '${b}' for '${c}'.`);continue}await P(v),o(`[corsair:setup] Set ${c} integration.${b}`);continue}if(g.has(b)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${c}.${b}' on a multi-tenant instance`);let P=V(k,`set_${b}`);if(!P){i(`[corsair:setup] Cannot set account field '${b}' for '${c}'.`);continue}await P(v),o(`[corsair:setup] Set ${c} account.${b} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${b}' for plugin '${c}'.`)}}}var Ia=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function ud(e,n,t,r,o,i,s,a,c){let l=[],u=[];for(let p of o){if(Ia.has(p))continue;let g=V(t,`get_${p}`);if(!g)continue;let f=null;try{let h=await g();f=typeof h=="string"?h:null}catch{}f||l.push(p)}if(r&&i.length>0)for(let p of i){if(Ia.has(p))continue;let g=V(r,`get_${p}`);if(!g)continue;let f=null;try{let h=await g();f=typeof h=="string"?h:null}catch{}f||u.push(p)}let d=l.length===0&&u.length===0;if(d)a(`[corsair:setup] '${e}' (${n}) is configured \u2713`);else if(n==="managed")a(`[corsair:setup] '${e}' (managed) is not connected yet. Use Connect in your app \u2014 Corsair Hub delivers OAuth tokens after authorization.`);else{let p=[...l,...u];if(c==="cli"){let g=p.map(f=>`${f}=VALUE`).join(" ");a(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
65
65
  corsair setup --${e} ${g}`)}else{let g=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let f of l)g.push(` await corsair.keys.${e}.set_${f}(value)`);for(let f of u){let h=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;g.push(` await ${h}.keys.set_${f}(value)`)}a(g.join(`
@@ -1 +1 @@
1
- import{ga as a,ha as b,ia as c}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{c as createHubConnectSession,b as createHubConnectSessionForPlugin,a as postHubConnectSession};
1
+ import{ga as a,ha as b,ia as c}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{c as createHubConnectSession,b as createHubConnectSessionForPlugin,a as postHubConnectSession};
package/dist/core.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair, s as shouldStartTunnel, b as superviseTunnel } from './index-DaD8PYPJ.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair, s as shouldStartTunnel, b as superviseTunnel } from './index-PD73vqiL.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { A as AuthTypes, f as AccountKeyManagerFor, I as IntegrationKeyManagerFor, H as HubConfig, g as CorsairPluginSubscribeResult } from './index-C36Hsxv5.js';
4
- export { h as AccountFieldNames, n as AgentMessageRole, o as AgentReply, v as AllProviders, l as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, i as BaseKeyManager, w as BaseProviders, a2 as BeforeHookResult, D as BindEndpoints, ap as BindWebhooks, an as Bivariant, E as BoundEndpointFn, F as BoundEndpointTree, aq as BoundWebhook, ar as BoundWebhookTree, p as ChatHandle, q as ChatMessage, r as ChatSummary, s as CorsairChatsNamespace, u as CorsairClient, G as CorsairContext, J as CorsairEndpoint, M as CorsairErrorHandler, c as CorsairIntegration, a3 as CorsairKeyBuilder, a4 as CorsairKeyBuilderBase, as as CorsairOAuthWebhookTenantLinkResolver, X as CorsairPermissionsNamespace, C as CorsairPlugin, a5 as CorsairPluginContext, a6 as CorsairPluginSubscribe, aj as CorsairRunsNamespace, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, at as CorsairWebhook, au as CorsairWebhookHandler, av as CorsairWebhookMatcher, aw as CorsairWebhookTenantMatcher, aC as CorsairWorkflowsNamespace, t as CreateChatResult, a7 as EndpointHooks, a8 as EndpointMetaEntry, K as EndpointPathsOf, a9 as EndpointRiskLevel, L as EndpointTree, Y as EnforcePermissionOptions, Z as EnforcePermissionResult, N as ErrorContext, Q as ErrorHandler, R as ErrorHandlerAndMatchFunction, S as ErrorMatcher, j as IntegrationFieldNames, aa as KeyBuilderContext, k as OAuth2IntegrationCredentials, O as OAuthConfig, ab as PermissionMode, ac as PermissionPolicy, x as PickAuth, P as PluginAuthConfig, ad as PluginEndpointMeta, ae as PluginPermissionsConfig, z as ProviderDisplayNames, ax as RawWebhookRequest, a0 as ReadonlyForbiddenError, af as RequiredPluginEndpointMeta, ag as RequiredPluginEndpointSchemas, ah as RequiredPluginWebhookSchemas, U as RetryStrategies, V as RetryStrategy, T as TokenResponse, aD as TriggerRunResult, ao as UnionToIntersection, ai as WebhookHooks, ay as WebhookPathsOf, az as WebhookRequest, aA as WebhookResponse, W as WebhookTenantMatch, aB as WebhookTree, ak as WorkflowRun, al as WorkflowRunStatus, am as WorkflowRunStep, aE as WorkflowStatus, aF as WorkflowSummary, _ as assertReadonlyAllowed, m as exchangeCodeForTokens, y as formatProviderDisplayName, $ as isReadonlyScopeActive, a1 as runReadonly } from './index-C36Hsxv5.js';
5
- export { A as AuthMissingError, C as CorsairKekMissingError, D as DocSchemaFieldRow, b as DocSchemaShape, c as DocsApiEndpoint, d as DocsDbEntity, e as DocsDbFilterField, f as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, h as PermissionRequiredError, P as PluginDocsIntrospection, l as PluginWebhookMatchers, R as ReconnectRequiredError, a as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, n as asRecord, j as collectPluginWebhookMatchers, o as decodePubSubData, p as extractMicrosoftGraphValidationToken, q as firstString, g as formatDocSchemaShape, s as getHeader, i as introspectPluginForDocs, t as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, k as matchWebhookPluginAndTenant, u as readBodyRecord, v as readQueryParam, r as resolveConnectLink, w as toExternalId } from './tenant-match-utils-BpNPko6c.js';
3
+ import { A as AuthTypes, f as AccountKeyManagerFor, I as IntegrationKeyManagerFor, H as HubConfig, g as CorsairPluginSubscribeResult } from './index-CkxZbZgd.js';
4
+ export { h as AccountFieldNames, n as AgentMessageRole, o as AgentReply, v as AllProviders, l as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, i as BaseKeyManager, w as BaseProviders, a2 as BeforeHookResult, D as BindEndpoints, ap as BindWebhooks, an as Bivariant, E as BoundEndpointFn, F as BoundEndpointTree, aq as BoundWebhook, ar as BoundWebhookTree, p as ChatHandle, q as ChatMessage, r as ChatSummary, s as CorsairChatsNamespace, u as CorsairClient, G as CorsairContext, J as CorsairEndpoint, M as CorsairErrorHandler, c as CorsairIntegration, a3 as CorsairKeyBuilder, a4 as CorsairKeyBuilderBase, as as CorsairOAuthWebhookTenantLinkResolver, X as CorsairPermissionsNamespace, C as CorsairPlugin, a5 as CorsairPluginContext, a6 as CorsairPluginSubscribe, aj as CorsairRunsNamespace, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, at as CorsairWebhook, au as CorsairWebhookHandler, av as CorsairWebhookMatcher, aw as CorsairWebhookTenantMatcher, aC as CorsairWorkflowsNamespace, t as CreateChatResult, a7 as EndpointHooks, a8 as EndpointMetaEntry, K as EndpointPathsOf, a9 as EndpointRiskLevel, L as EndpointTree, Y as EnforcePermissionOptions, Z as EnforcePermissionResult, N as ErrorContext, Q as ErrorHandler, R as ErrorHandlerAndMatchFunction, S as ErrorMatcher, j as IntegrationFieldNames, aa as KeyBuilderContext, k as OAuth2IntegrationCredentials, O as OAuthConfig, ab as PermissionMode, ac as PermissionPolicy, x as PickAuth, P as PluginAuthConfig, ad as PluginEndpointMeta, ae as PluginPermissionsConfig, z as ProviderDisplayNames, ax as RawWebhookRequest, a0 as ReadonlyForbiddenError, af as RequiredPluginEndpointMeta, ag as RequiredPluginEndpointSchemas, ah as RequiredPluginWebhookSchemas, U as RetryStrategies, V as RetryStrategy, T as TokenResponse, aD as TriggerRunResult, ao as UnionToIntersection, ai as WebhookHooks, ay as WebhookPathsOf, az as WebhookRequest, aA as WebhookResponse, W as WebhookTenantMatch, aB as WebhookTree, ak as WorkflowRun, al as WorkflowRunStatus, am as WorkflowRunStep, aE as WorkflowStatus, aF as WorkflowSummary, _ as assertReadonlyAllowed, m as exchangeCodeForTokens, y as formatProviderDisplayName, $ as isReadonlyScopeActive, a1 as runReadonly } from './index-CkxZbZgd.js';
5
+ export { A as AuthMissingError, C as CorsairKekMissingError, D as DocSchemaFieldRow, b as DocSchemaShape, c as DocsApiEndpoint, d as DocsDbEntity, e as DocsDbFilterField, f as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, h as PermissionRequiredError, P as PluginDocsIntrospection, l as PluginWebhookMatchers, R as ReconnectRequiredError, a as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, n as asRecord, j as collectPluginWebhookMatchers, o as decodePubSubData, p as extractMicrosoftGraphValidationToken, q as firstString, g as formatDocSchemaShape, s as getHeader, i as introspectPluginForDocs, t as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, k as matchWebhookPluginAndTenant, u as readBodyRecord, v as readQueryParam, r as resolveConnectLink, w as toExternalId } from './tenant-match-utils-Cv9F7soB.js';
6
6
  import 'kysely';
7
7
  import 'zod';
8
8
  import 'pg';
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{$b as L,D as e,E as f,F as g,G as h,H as i,I as j,J as k,K as l,L as m,Lb as y,M as n,Mb as z,N as o,Nb as A,O as p,Ob as B,Sb as C,Tb as D,Ub as E,Vb as F,Wb as G,Xb as H,Yb as I,Zb as J,_b as K,a,ac as M,b,bc as N,c,cc as O,dc as P,eb as w,ec as Q,fc as R,gc as S,hc as T,ic as U,ja as q,jc as V,kc as W,ma as r,na as s,oa as t,pa as u,qa as v,xb as x}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import{h as d}from"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{w as AuthMissingError,d as BASE_AUTH_FIELDS,T as CORSAIR_INTERNAL,x as CorsairKekMissingError,F as MS_GRAPH_API_BASE,r as PermissionRequiredError,a as ProviderDisplayNames,s as ReadonlyForbiddenError,c as ReconnectRequiredError,M as asRecord,v as assertReadonlyAllowed,J as collectPluginWebhookMatchers,n as createAccountKeyManager,U as createCorsair,m as createIntegrationKeyManager,S as decodePubSubData,k as decryptConfig,g as decryptDEK,i as decryptWithDEK,j as encryptConfig,f as encryptDEK,h as encryptWithDEK,A as exchangeCodeForTokens,P as extractMicrosoftGraphValidationToken,R as firstString,C as formatDocSchemaShape,b as formatProviderDisplayName,e as generateDEK,K as getHeader,B as getOAuthAccessToken,E as googleChannelSubscribe,p as initializeAccountDEK,o as initializeIntegrationDEK,D as introspectPluginForDocs,Q as isMicrosoftGraphValidationHandshake,u as isReadonlyScopeActive,y as logEvent,z as logEventFromContext,H as matchWebhookPlugin,I as matchWebhookPluginAndTenant,G as msGraphSubscribe,l as reEncryptConfig,N as readBodyRecord,O as readQueryParam,q as resolveConnectLink,t as runReadonly,V as shouldStartTunnel,W as superviseTunnel,L as toExternalId};
1
+ import{$b as L,D as e,E as f,F as g,G as h,H as i,I as j,J as k,K as l,L as m,Lb as y,M as n,Mb as z,N as o,Nb as A,O as p,Ob as B,Sb as C,Tb as D,Ub as E,Vb as F,Wb as G,Xb as H,Yb as I,Zb as J,_b as K,a,ac as M,b,bc as N,c,cc as O,dc as P,eb as w,ec as Q,fc as R,gc as S,hc as T,ic as U,ja as q,jc as V,kc as W,ma as r,na as s,oa as t,pa as u,qa as v,xb as x}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import{h as d}from"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{w as AuthMissingError,d as BASE_AUTH_FIELDS,T as CORSAIR_INTERNAL,x as CorsairKekMissingError,F as MS_GRAPH_API_BASE,r as PermissionRequiredError,a as ProviderDisplayNames,s as ReadonlyForbiddenError,c as ReconnectRequiredError,M as asRecord,v as assertReadonlyAllowed,J as collectPluginWebhookMatchers,n as createAccountKeyManager,U as createCorsair,m as createIntegrationKeyManager,S as decodePubSubData,k as decryptConfig,g as decryptDEK,i as decryptWithDEK,j as encryptConfig,f as encryptDEK,h as encryptWithDEK,A as exchangeCodeForTokens,P as extractMicrosoftGraphValidationToken,R as firstString,C as formatDocSchemaShape,b as formatProviderDisplayName,e as generateDEK,K as getHeader,B as getOAuthAccessToken,E as googleChannelSubscribe,p as initializeAccountDEK,o as initializeIntegrationDEK,D as introspectPluginForDocs,Q as isMicrosoftGraphValidationHandshake,u as isReadonlyScopeActive,y as logEvent,z as logEventFromContext,H as matchWebhookPlugin,I as matchWebhookPluginAndTenant,G as msGraphSubscribe,l as reEncryptConfig,N as readBodyRecord,O as readQueryParam,q as resolveConnectLink,t as runReadonly,V as shouldStartTunnel,W as superviseTunnel,L as toExternalId};
package/dist/hub.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { aV as HubOAuthMode, A as AuthTypes, aW as HubConnectSessionResult, aX as HubPermissionSessionResult, H as HubConfig, aY as HubConfigInput, aZ as HubConnectSessionInput, a_ as HubListProjectConnectionsInput, f as AccountKeyManagerFor, a$ as HubPermissionSessionInput } from './index-C36Hsxv5.js';
2
- export { b0 as DEFAULT_HUB_API_URL, b1 as HubEnvironmentSlug, y as formatProviderDisplayName } from './index-C36Hsxv5.js';
3
- import { k as TunnelType, R as RunResultPayload, P as ProbeResultPayload, g as ProcessCorsairRequest, m as WebhookTenantLink } from './index-MnbnpwOk.js';
4
- export { n as BROWSER_DELIVERY_TTL_MS, o as BrowserDeliveryMode, B as BrowserDeliveryPayload, S as SIGNED_TUNNEL_REPLAY_WINDOW_MS, j as TunnelEnvelope } from './index-MnbnpwOk.js';
5
- export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-DyJuTM83.js';
1
+ import { aV as HubOAuthMode, A as AuthTypes, aW as HubConnectSessionResult, aX as HubPermissionSessionResult, H as HubConfig, aY as HubConfigInput, aZ as HubConnectSessionInput, a_ as HubListProjectConnectionsInput, f as AccountKeyManagerFor, a$ as HubPermissionSessionInput } from './index-CkxZbZgd.js';
2
+ export { b0 as DEFAULT_HUB_API_URL, b1 as HubEnvironmentSlug, y as formatProviderDisplayName } from './index-CkxZbZgd.js';
3
+ import { k as TunnelType, R as RunResultPayload, P as ProbeResultPayload, g as ProcessCorsairRequest, m as WebhookTenantLink } from './index-DUHdJscv.js';
4
+ export { n as BROWSER_DELIVERY_TTL_MS, o as BrowserDeliveryMode, B as BrowserDeliveryPayload, S as SIGNED_TUNNEL_REPLAY_WINDOW_MS, j as TunnelEnvelope } from './index-DUHdJscv.js';
5
+ export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-lY7x4meY.js';
6
6
  import 'zod';
7
7
  import './db.js';
8
8
  import 'kysely';
@@ -81,7 +81,7 @@ declare function parseOAuthRefreshResponse(payload: unknown): HubOAuthRefreshRes
81
81
  declare function parseConnectStatusResponse(payload: unknown): ConnectStatusResponse;
82
82
  declare function parseHubApiErrorBody(payload: unknown): string | null;
83
83
 
84
- type HubEnvironmentSlug = 'development' | 'production';
84
+ type HubEnvironmentSlug = 'development' | 'production' | 'cloud';
85
85
  type DeliveryTransport = 'browser' | 'server';
86
86
  declare function isLoopbackUrl(url: string): boolean;
87
87
  declare function resolveDeliveryTransport(slug: HubEnvironmentSlug): DeliveryTransport;
@@ -146,7 +146,7 @@ declare function normalizeHubConfig(input: HubConfigInput): HubConfig;
146
146
  declare function resolveHubConfigInput(input: HubConfigInput): HubConfig;
147
147
  declare function getHubConfig(corsair: unknown): HubConfig;
148
148
  declare function resolveHubOAuthCallbackUrl(config: HubConfig): string;
149
- declare function inferHubEnvironmentSlug(apiKey: string): 'development' | 'production';
149
+ declare function inferHubEnvironmentSlug(apiKey: string): 'development' | 'production' | 'cloud';
150
150
 
151
151
  /**
152
152
  * Creates a hosted Hub connect session from a corsair instance.
package/dist/hub.js CHANGED
@@ -1 +1 @@
1
- import{$a as _,A as z,Aa as P,B as A,Ba as Q,C as B,Ca as R,Da as S,Ea as T,Fa as U,Ga as V,Ha as W,T as C,Ua as X,Va as Y,_a as Z,ab as $,b as a,bb as aa,cb as ba,d as b,db as ca,e as c,f as d,fb as da,g as e,gb as ea,h as f,hb as fa,i as g,ia as D,ib as ga,j as i,jb as ha,k as j,ka as E,kb as ia,l as k,la as F,lb as ja,m as l,mb as ka,n as m,nb as la,o as n,ob as ma,p as o,pb as na,q as p,qb as oa,r as q,ra as G,rb as pa,s as r,sa as H,sb as qa,t as s,ta as I,tb as ra,u as t,ua as J,ub as sa,v as u,va as K,vb as ta,w as v,wa as L,wb as ua,x as w,xa as M,y as x,ya as N,z as y,za as O}from"./chunk-XTXURVDQ.js";import{a as h,b as va,c as wa,d as xa,e as ya,f as za}from"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{m as BROWSER_DELIVERY_TTL_MS,wa as CORSAIR_TUNNEL_PATH,va as CORSAIR_TUNNEL_ZONE,u as DEFAULT_HUB_API_URL,xa as FRPC_VERSION,w as HubCredentialsMissingError,v as HubNotConfiguredError,V as ManagedOAuthDeliveryError,n as SIGNED_TUNNEL_REPLAY_WINDOW_MS,ea as attachManagedRefreshAuth,p as buildBrowserDeliveryRedirectUrl,s as buildClientBridgeBrowserDeliveryUrl,ga as createConnectSessionJti,la as createConnectTokenJti,D as createHubConnectSession,E as createHubPermissionSession,fa as createHubRouteHandlers,ra as createPermissionSessionJti,o as createSignedTokenJti,ka as decodeConnectSessionTokenFromPath,qa as decodeConnectTokenFromPath,ua as decodePermissionTokenFromPath,Q as deliverConnectCreateLink,U as deliverSignedEnvelope,S as describeDeliveryNetworkError,pa as encodeConnectTokenForPath,O as extractConnectLinkFromDeliveryAck,H as extractProbeFromDeliveryAck,G as extractRunFromDeliveryAck,N as extractSyncFromDeliveryAck,F as formatHubApprovalMessage,a as formatProviderDisplayName,T as formatServerDeliveryError,ya as frpcPlatformKey,ha as getConnectSessionExpiryMs,X as getConnectStatusForTenant,ma as getConnectTokenExpiryMs,z as getHubConfig,da as getManagedAccessToken,Z as handleHubDeliveryGet,_ as handleHubDeliveryPost,aa as handleHubDeliveryRequest,$ as hubDeliveryToResponse,B as inferHubEnvironmentSlug,i as isLoopbackUrl,M as isServerDeliveryAckSuccessful,Y as listHubProjectConnections,x as normalizeHubConfig,P as parseConnectLinkFromDeliveryBody,b as parseConnectSessionResponse,f as parseConnectStatusResponse,g as parseHubApiErrorBody,e as parseOAuthRefreshResponse,d as parsePermissionSessionResponse,c as parseProjectConnectionsResponse,L as parseServerDeliveryAckBody,R as parseSyncFromDeliveryBody,t as prepareClientBridgeDeliveryTransport,W as processManagedOAuthDelivery,C as registerHubWebhookTenantLink,j as resolveDeliveryTransport,za as resolveFrpcBinary,y as resolveHubConfigInput,h as resolveHubDeliveryUrl,A as resolveHubOAuthCallbackUrl,ba as respondToHubDelivery,ca as respondToHubDeliveryFromRequest,q as signBrowserDeliveryToken,ia as signConnectSessionToken,na as signConnectToken,I as signDeliveryEnvelope,sa as signPermissionToken,k as usesBrowserDelivery,l as validateProductionDeliveryUrl,r as verifyBrowserDeliveryToken,ja as verifyConnectSessionToken,oa as verifyConnectToken,J as verifyDeliveryEnvelope,ta as verifyPermissionToken,K as verifySignedTunnelDelivery};
1
+ import{$a as _,A as z,Aa as P,B as A,Ba as Q,C as B,Ca as R,Da as S,Ea as T,Fa as U,Ga as V,Ha as W,T as C,Ua as X,Va as Y,_a as Z,ab as $,b as a,bb as aa,cb as ba,d as b,db as ca,e as c,f as d,fb as da,g as e,gb as ea,h as f,hb as fa,i as g,ia as D,ib as ga,j as i,jb as ha,k as j,ka as E,kb as ia,l as k,la as F,lb as ja,m as l,mb as ka,n as m,nb as la,o as n,ob as ma,p as o,pb as na,q as p,qb as oa,r as q,ra as G,rb as pa,s as r,sa as H,sb as qa,t as s,ta as I,tb as ra,u as t,ua as J,ub as sa,v as u,va as K,vb as ta,w as v,wa as L,wb as ua,x as w,xa as M,y as x,ya as N,z as y,za as O}from"./chunk-XQZJJTZ7.js";import{a as h,b as va,c as wa,d as xa,e as ya,f as za}from"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{m as BROWSER_DELIVERY_TTL_MS,wa as CORSAIR_TUNNEL_PATH,va as CORSAIR_TUNNEL_ZONE,u as DEFAULT_HUB_API_URL,xa as FRPC_VERSION,w as HubCredentialsMissingError,v as HubNotConfiguredError,V as ManagedOAuthDeliveryError,n as SIGNED_TUNNEL_REPLAY_WINDOW_MS,ea as attachManagedRefreshAuth,p as buildBrowserDeliveryRedirectUrl,s as buildClientBridgeBrowserDeliveryUrl,ga as createConnectSessionJti,la as createConnectTokenJti,D as createHubConnectSession,E as createHubPermissionSession,fa as createHubRouteHandlers,ra as createPermissionSessionJti,o as createSignedTokenJti,ka as decodeConnectSessionTokenFromPath,qa as decodeConnectTokenFromPath,ua as decodePermissionTokenFromPath,Q as deliverConnectCreateLink,U as deliverSignedEnvelope,S as describeDeliveryNetworkError,pa as encodeConnectTokenForPath,O as extractConnectLinkFromDeliveryAck,H as extractProbeFromDeliveryAck,G as extractRunFromDeliveryAck,N as extractSyncFromDeliveryAck,F as formatHubApprovalMessage,a as formatProviderDisplayName,T as formatServerDeliveryError,ya as frpcPlatformKey,ha as getConnectSessionExpiryMs,X as getConnectStatusForTenant,ma as getConnectTokenExpiryMs,z as getHubConfig,da as getManagedAccessToken,Z as handleHubDeliveryGet,_ as handleHubDeliveryPost,aa as handleHubDeliveryRequest,$ as hubDeliveryToResponse,B as inferHubEnvironmentSlug,i as isLoopbackUrl,M as isServerDeliveryAckSuccessful,Y as listHubProjectConnections,x as normalizeHubConfig,P as parseConnectLinkFromDeliveryBody,b as parseConnectSessionResponse,f as parseConnectStatusResponse,g as parseHubApiErrorBody,e as parseOAuthRefreshResponse,d as parsePermissionSessionResponse,c as parseProjectConnectionsResponse,L as parseServerDeliveryAckBody,R as parseSyncFromDeliveryBody,t as prepareClientBridgeDeliveryTransport,W as processManagedOAuthDelivery,C as registerHubWebhookTenantLink,j as resolveDeliveryTransport,za as resolveFrpcBinary,y as resolveHubConfigInput,h as resolveHubDeliveryUrl,A as resolveHubOAuthCallbackUrl,ba as respondToHubDelivery,ca as respondToHubDeliveryFromRequest,q as signBrowserDeliveryToken,ia as signConnectSessionToken,na as signConnectToken,I as signDeliveryEnvelope,sa as signPermissionToken,k as usesBrowserDelivery,l as validateProductionDeliveryUrl,r as verifyBrowserDeliveryToken,ja as verifyConnectSessionToken,oa as verifyConnectToken,J as verifyDeliveryEnvelope,ta as verifyPermissionToken,K as verifySignedTunnelDelivery};
@@ -297,7 +297,7 @@ type AllProviders = 'ably' | 'abstract' | 'abuseipdb' | 'abyssale' | 'accredible
297
297
  type AuthTypes = 'oauth_2' | 'api_key' | 'bot_token' | 'managed';
298
298
  type PickAuth<T extends AuthTypes> = T;
299
299
 
300
- type HubEnvironmentSlug = 'development' | 'production';
300
+ type HubEnvironmentSlug = 'development' | 'production' | 'cloud';
301
301
  type HubOAuthMode = 'byo' | 'managed';
302
302
  declare const DEFAULT_HUB_API_URL = "https://auth.corsair.dev";
303
303
  type HubConfigInput = {
@@ -1,4 +1,4 @@
1
- import { W as WebhookTenantMatch, A as AuthTypes } from './index-C36Hsxv5.js';
1
+ import { W as WebhookTenantMatch, A as AuthTypes } from './index-CkxZbZgd.js';
2
2
  import { CorsairDatabase, CorsairAccount } from './db.js';
3
3
 
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { CorsairDatabase } from './db.js';
2
- import { C as CorsairPlugin, a as CorsairPermissionsOptions, b as CorsairManualConfig, H as HubConfig, c as CorsairIntegration, d as CorsairTenantWrapper, e as CorsairSingleTenantClient } from './index-C36Hsxv5.js';
2
+ import { C as CorsairPlugin, a as CorsairPermissionsOptions, b as CorsairManualConfig, H as HubConfig, c as CorsairIntegration, d as CorsairTenantWrapper, e as CorsairSingleTenantClient } from './index-CkxZbZgd.js';
3
3
 
4
4
  declare const CORSAIR_INTERNAL: unique symbol;
5
5
  type CorsairInternalConfig = {
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { ZodTypeAny, z } from 'zod';
2
- import { e as CorsairSingleTenantClient, d as CorsairTenantWrapper, C as CorsairPlugin, u as CorsairClient, aG as ManagementOk, aH as Tenant, aI as CreateTenantInput, aJ as PluginInfo, aK as ConnectionStatus, aL as PermissionLookupInput, aM as PermissionRecord, aN as CreateConnectLinkInput, aO as ConnectLink, aP as ResolvedConnectLink, aQ as OAuthCallbackInput, aR as OAuthCallbackResult, aS as ConnectRequest, X as CorsairPermissionsNamespace, ar as BoundWebhookTree, ax as RawWebhookRequest, aw as CorsairWebhookTenantMatcher, w as BaseProviders, aA as WebhookResponse } from './index-C36Hsxv5.js';
3
- export { aT as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions, aU as PluginConnectionState, a0 as ReadonlyForbiddenError, a1 as runReadonly } from './index-C36Hsxv5.js';
4
- import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-BpNPko6c.js';
5
- export { A as AuthMissingError, C as CorsairKekMissingError, h as PermissionRequiredError, l as PluginWebhookMatchers, R as ReconnectRequiredError, a as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, n as asRecord, j as collectPluginWebhookMatchers, o as decodePubSubData, q as firstString, g as formatDocSchemaShape, s as getHeader, m as matchWebhookPlugin, k as matchWebhookPluginAndTenant, u as readBodyRecord, r as resolveConnectLink, w as toExternalId } from './tenant-match-utils-BpNPko6c.js';
6
- export { c as createCorsair } from './index-DaD8PYPJ.js';
2
+ import { e as CorsairSingleTenantClient, d as CorsairTenantWrapper, C as CorsairPlugin, u as CorsairClient, aG as ManagementOk, aH as Tenant, aI as CreateTenantInput, aJ as PluginInfo, aK as ConnectionStatus, aL as PermissionLookupInput, aM as PermissionRecord, aN as CreateConnectLinkInput, aO as ConnectLink, aP as ResolvedConnectLink, aQ as OAuthCallbackInput, aR as OAuthCallbackResult, aS as ConnectRequest, X as CorsairPermissionsNamespace, ar as BoundWebhookTree, ax as RawWebhookRequest, aw as CorsairWebhookTenantMatcher, w as BaseProviders, aA as WebhookResponse } from './index-CkxZbZgd.js';
3
+ export { aT as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions, aU as PluginConnectionState, a0 as ReadonlyForbiddenError, a1 as runReadonly } from './index-CkxZbZgd.js';
4
+ import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-Cv9F7soB.js';
5
+ export { A as AuthMissingError, C as CorsairKekMissingError, h as PermissionRequiredError, l as PluginWebhookMatchers, R as ReconnectRequiredError, a as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, n as asRecord, j as collectPluginWebhookMatchers, o as decodePubSubData, q as firstString, g as formatDocSchemaShape, s as getHeader, m as matchWebhookPlugin, k as matchWebhookPluginAndTenant, u as readBodyRecord, r as resolveConnectLink, w as toExternalId } from './tenant-match-utils-Cv9F7soB.js';
6
+ export { c as createCorsair } from './index-PD73vqiL.js';
7
7
  export { SetupCorsairOptions, setupCorsair } from './setup.js';
8
- export { O as OAuthCallbackTunnelPayload, f as ProcessCorsairOptions, g as ProcessCorsairRequest, l as ResolveAccountFromWebhookLinkInput, T as TunnelAck, j as TunnelEnvelope, k as TunnelType, m as WebhookTenantLink, W as WebhookTunnelPayload, p as processCorsair, r as resolveAccountFromWebhookLink, h as resolveTenantFromWebhookLink, i as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './index-MnbnpwOk.js';
8
+ export { O as OAuthCallbackTunnelPayload, f as ProcessCorsairOptions, g as ProcessCorsairRequest, l as ResolveAccountFromWebhookLinkInput, T as TunnelAck, j as TunnelEnvelope, k as TunnelType, m as WebhookTenantLink, W as WebhookTunnelPayload, p as processCorsair, r as resolveAccountFromWebhookLink, h as resolveTenantFromWebhookLink, i as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './index-DUHdJscv.js';
9
9
  import './db.js';
10
10
  import 'kysely';
11
11
  import 'pg';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{$b as cn,Ab as J,Bb as Y,Cb as K,Db as G,Eb as X,Fb as Q,Gb as V,Hb as nn,Ia as H,Ib as en,Jb as tn,Kb as rn,P as O,Pb as P,Qa as W,Qb as w,Rb as x,Sb as R,U as A,V as L,W as E,Wa as q,X as v,Xa as N,Xb as on,Ya as j,Yb as sn,Za as B,Zb as an,_b as un,ac as pn,bc as ln,c as S,eb as D,fc as dn,gc as mn,hc as T,ic as gn,ja as F,ma as M,na as _,oa as $,xb as U,yb as Z,zb as z}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";import{z as p}from"zod";function f(e){let t=e[T];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function y(e,t){let o=w(f(e),t);return typeof o=="string"?o:Array.isArray(o)?o.join(`
1
+ import{$b as cn,Ab as J,Bb as Y,Cb as K,Db as G,Eb as X,Fb as Q,Gb as V,Hb as nn,Ia as H,Ib as en,Jb as tn,Kb as rn,P as O,Pb as P,Qa as W,Qb as w,Rb as x,Sb as R,U as A,V as L,W as E,Wa as q,X as v,Xa as N,Xb as on,Ya as j,Yb as sn,Za as B,Zb as an,_b as un,ac as pn,bc as ln,c as S,eb as D,fc as dn,gc as mn,hc as T,ic as gn,ja as F,ma as M,na as _,oa as $,xb as U,yb as Z,zb as z}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";import{z as p}from"zod";function f(e){let t=e[T];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function y(e,t){let o=w(f(e),t);return typeof o=="string"?o:Array.isArray(o)?o.join(`
2
2
  `):Object.values(o).flat().join(`
3
3
  `)}function fn(e,t){return x(f(e),t)}function k(e,t){return P(f(e),t)}function h(e,t){let o=f(e),n=t.toLowerCase(),i=n.indexOf(".");if(i===-1)return null;let u=n.slice(0,i),r=n.slice(i+1),s=o.find(c=>c.id===u);if(!s?.endpointSchemas)return null;let a=r;a.startsWith("api.")&&(a=a.slice(4));for(let[c,g]of Object.entries(s.endpointSchemas))if(c.toLowerCase()===a)return g.input??null;return null}function C(e){let t=Cn(e);return e.description&&(t=t.describe(e.description)),e.optional&&(t=t.optional()),t}function Cn(e){switch(e.kind){case"string":return e.enum&&e.enum.length>0?p.enum(e.enum):p.string();case"number":return p.number();case"boolean":return p.boolean();case"literal":return p.literal(e.value);case"object":{let t={};for(let[o,n]of Object.entries(e.fields))t[o]=C(n);return p.object(t)}case"array":return p.array(C(e.items));case"unknown":return p.unknown()}}function yn(e,t){let o=t?.tenantId?Pn(e,t.tenantId):e;return(t?.operations??kn(y(o,{plugin:t?.plugin,type:"api"}))).map(i=>{let u=k(o,i),s=h(o,i)??(u?.input?C(u.input):p.object({}));return{name:hn(i),operation:i,description:u?.description??i,schema:s,execute:a=>wn(o,i,a??{})}})}function kn(e){return e.split(`
4
4
  `).map(t=>t.trim()).filter(Boolean)}function hn(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function Pn(e,t){let o=e.withTenant;return typeof o=="function"?o.call(e,t):e}async function wn(e,t,o){let n=t.split("."),i=n.pop();if(!i)throw new Error(`Invalid operation path: ${t}`);let u=e;for(let s of n)if(u=u?.[s],u==null)throw new Error(`Unknown operation path: ${t}`);let r=u[i];if(typeof r!="function")throw new Error(`Operation is not callable: ${t}`);return r.call(u,o)}var l=class extends Error{status;code;extra;constructor(t,o,n,i={}){super(n),this.name="CorsairClientError",this.status=t,this.code=o,this.extra=i}};function xn(e){return e.endsWith("/")?e.slice(0,-1):e}async function I(e){let t={};try{t=await e.json()}catch{}let o=typeof t.error=="string"?t.error:"request_failed",n=typeof t.message=="string"?t.message:`Request failed (${e.status})`,{error:i,message:u,...r}=t;return new l(e.status,o,n,r)}function Rn(e){let t=xn(e.baseURL),o=e.fetch??((...r)=>globalThis.fetch(...r));async function n(r,s){let a=s&&Object.keys(s).length?`?${new URLSearchParams(s).toString()}`:"",c=await o(`${t}${r}${a}`,{method:"GET"});if(!c.ok)throw await I(c);return await c.json()}async function i(r,s){let a=await o(`${t}${r}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)});if(!a.ok)throw await I(a);return await a.json()}let u=encodeURIComponent;return{ok:()=>n("/ok"),tenants:{list:()=>n("/tenants"),create:r=>i("/tenants",r),get:r=>n(`/tenants/${u(r)}`)},plugins:{list:()=>n("/plugins"),get:r=>n(`/plugins/${u(r)}`)},connectionStatus:{get:r=>{let s={};return r?.tenantId&&(s.tenantId=r.tenantId),n("/connection-status",s)}},permissions:{get:r=>"id"in r?n(`/permissions/${u(r.id)}`):i("/permissions/lookup-by-token",{token:r.token})},connect:{createLink:r=>i("/connect/links",r),resolve:r=>n("/connect/resolve",{state:r}),oauthCallback:r=>i("/connect/oauth/callback",r)},connectRequest:{get:r=>{let s={};return r?.tenantId&&(s.tenantId=r.tenantId),n("/connect/request",s)},clear:r=>i("/connect/request/clear",r??{})}}}var Tn=Symbol.for("corsair:internal");function In(e,t){let o=e;for(let n of t){if(!o||typeof o!="object")return null;o=o[n]}return typeof o=="function"?o:null}function b(e){return e[Tn]?.database}async function bn(e,t){let o=new Date().toISOString(),n=await e.permissions.find_by_token(t);if(!n)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(n.status!=="approved")return console.error(`executePermission: permission '${n.id}' is '${n.status}', expected 'approved'.`),{endpoint:n.endpoint,plugin:n.plugin,result:null,error:`executePermission: permission '${n.id}' is '${n.status}', expected 'approved'.`};if(n.expires_at<o){let a=b(e);return a&&await a.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",n.id).execute(),console.error(`executePermission: permission '${n.id}' has expired.`),{error:`executePermission: permission '${n.id}' has expired.`,endpoint:n.endpoint,plugin:n.plugin,result:null}}let i=n.tenant_id??"default",r=(e.withTenant?e.withTenant(i):e)[n.plugin];if(!r?.api)return console.error(`executePermission: plugin '${n.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${n.plugin}' not found or has no API on this corsair instance.`,plugin:n.plugin,endpoint:n.endpoint,result:null};let s=In(r.api,n.endpoint.split("."));if(!s)return console.error(`executePermission: endpoint '${n.endpoint}' not found in plugin '${n.plugin}'.`),{endpoint:n.endpoint,plugin:n.plugin,result:null,error:`executePermission: endpoint '${n.endpoint}' not found in plugin '${n.plugin}'.`};await e.permissions.set_executing(n.id);try{let a=typeof n.args=="string"?JSON.parse(n.args):n.args,c=await s(a);return await e.permissions.set_completed(n.id),{plugin:n.plugin,endpoint:n.endpoint,result:c}}catch(a){let c=a instanceof Error?a.message:String(a),g=b(e);return g&&await g.db.updateTable("corsair_permissions").set({status:"failed",error:c,updated_at:new Date}).where("id","=",n.id).execute(),{plugin:n.plugin,endpoint:n.endpoint,result:null,error:c}}}export{D as AuthMissingError,l as CorsairClientError,U as CorsairKekMissingError,N as DEFAULT_BODY_STALL_TIMEOUT_MS,q as DEFAULT_MAX_BODY_BYTES,M as PermissionRequiredError,_ as ReadonlyForbiddenError,S as ReconnectRequiredError,pn as asRecord,yn as buildCorsairTools,an as collectPluginWebhookMatchers,gn as createCorsair,Rn as createCorsairClient,mn as decodePubSubData,bn as executePermission,dn as firstString,C as formFieldToZod,R as formatDocSchemaShape,un as getHeader,h as getInputSchema,fn as getSchema,k as getStructuredSchema,y as listOperations,Z as managementHandler,on as matchWebhookPlugin,sn as matchWebhookPluginAndTenant,W as processCorsair,H as processWebhook,ln as readBodyRecord,J as registerCorsairRawBodyParser,L as resolveAccountFromWebhookLink,B as resolveBodyStallTimeoutMs,F as resolveConnectLink,j as resolveMaxBodyBytes,v as resolveTenantFromWebhookLink,E as resolveTenantIdFromWebhookLink,$ as runReadonly,A as setWebhookTenantLink,O as setupCorsair,nn as toAstroHandler,z as toExpressHandler,cn as toExternalId,Y as toFastifyHandler,K as toHonoHandler,G as toNextJsHandler,X as toNodeHandler,tn as toNuxtHandler,V as toRemixHandler,Q as toSvelteKitHandler,en as toTanStackHandler,rn as toWebHandler};
@@ -1 +1 @@
1
- import{Ra as a,Sa as b,Ta as c}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{a as deriveAck,b as pollOnce,c as startConnectLoop};
1
+ import{Ra as a,Sa as b,Ta as c}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{a as deriveAck,b as pollOnce,c as startConnectLoop};
package/dist/oauth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OAuthConfig } from './index-C36Hsxv5.js';
1
+ import { O as OAuthConfig } from './index-CkxZbZgd.js';
2
2
  import 'zod';
3
3
  import './db.js';
4
4
  import 'kysely';
package/dist/oauth.js CHANGED
@@ -1 +1 @@
1
- import{$ as f,R as a,S as b,Y as c,Z as d,_ as e,aa as g,ba as h}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{d as OAuthCallbackError,c as buildOAuthAuthorizeUrl,b as decodeOAuthState,a as encodeOAuthState,e as generateOAuthUrl,f as processOAuthCallback,g as renewSubscriptions,h as startSubscriptionRenewal};
1
+ import{$ as f,R as a,S as b,Y as c,Z as d,_ as e,aa as g,ba as h}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{d as OAuthCallbackError,c as buildOAuthAuthorizeUrl,b as decodeOAuthState,a as encodeOAuthState,e as generateOAuthUrl,f as processOAuthCallback,g as renewSubscriptions,h as startSubscriptionRenewal};
@@ -1 +1 @@
1
- import{P as a,Q as b}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as applySetupCredentials,a as setupCorsair};
1
+ import{P as a,Q as b}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as applySetupCredentials,a as setupCorsair};
@@ -1 +1 @@
1
- import{ca as a,da as b,ea as c,fa as d}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as buildConnectPluginManifest,a as buildConnectPluginManifestFromContext,d as ensureConnectAccountRows,c as ensureConnectAccountRowsFromContext};
1
+ import{ca as a,da as b,ea as c,fa as d}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as buildConnectPluginManifest,a as buildConnectPluginManifestFromContext,d as ensureConnectAccountRows,c as ensureConnectAccountRowsFromContext};
package/dist/setup.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as CorsairInternalConfig } from './index-DaD8PYPJ.js';
2
- import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-C36Hsxv5.js';
1
+ import { a as CorsairInternalConfig } from './index-PD73vqiL.js';
2
+ import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-CkxZbZgd.js';
3
3
  import { CorsairDatabase } from './db.js';
4
4
  import 'zod';
5
5
  import './orm.js';
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{P as a,Q as b}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as applySetupCredentials,a as setupCorsair};
1
+ import{P as a,Q as b}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{b as applySetupCredentials,a as setupCorsair};
@@ -1,4 +1,4 @@
1
- import { a9 as EndpointRiskLevel, C as CorsairPlugin, av as CorsairWebhookMatcher, aw as CorsairWebhookTenantMatcher, ax as RawWebhookRequest, v as AllProviders, W as WebhookTenantMatch } from './index-C36Hsxv5.js';
1
+ import { a9 as EndpointRiskLevel, C as CorsairPlugin, av as CorsairWebhookMatcher, aw as CorsairWebhookTenantMatcher, ax as RawWebhookRequest, v as AllProviders, W as WebhookTenantMatch } from './index-CkxZbZgd.js';
2
2
 
3
3
  type PermissionRequiredReason = 'denied' | 'policy' | 'timeout' | 'pending';
4
4
  /**
package/dist/tunnel.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { B as BrowserDeliveryPayload, R as RunResultPayload, P as ProbeResultPayload } from './index-MnbnpwOk.js';
2
- export { O as OAuthCallbackTunnelPayload, e as OAuthTokensTunnelPayload, f as ProcessCorsairOptions, g as ProcessCorsairRequest, a as RunStepResult, b as RunTriggerType, c as RunTunnelPayload, T as TunnelAck, j as TunnelEnvelope, k as TunnelType, W as WebhookTunnelPayload, d as applyPermissionDecision, p as processCorsair, r as resolveAccountFromWebhookLink, h as resolveTenantFromWebhookLink, i as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './index-MnbnpwOk.js';
3
- export { v as verifyBrowserDeliveryToken } from './browser-delivery-DyJuTM83.js';
4
- import './index-C36Hsxv5.js';
1
+ import { B as BrowserDeliveryPayload, R as RunResultPayload, P as ProbeResultPayload } from './index-DUHdJscv.js';
2
+ export { O as OAuthCallbackTunnelPayload, e as OAuthTokensTunnelPayload, f as ProcessCorsairOptions, g as ProcessCorsairRequest, a as RunStepResult, b as RunTriggerType, c as RunTunnelPayload, T as TunnelAck, j as TunnelEnvelope, k as TunnelType, W as WebhookTunnelPayload, d as applyPermissionDecision, p as processCorsair, r as resolveAccountFromWebhookLink, h as resolveTenantFromWebhookLink, i as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './index-DUHdJscv.js';
3
+ export { v as verifyBrowserDeliveryToken } from './browser-delivery-lY7x4meY.js';
4
+ import './index-CkxZbZgd.js';
5
5
  import 'zod';
6
6
  import './db.js';
7
7
  import 'kysely';
package/dist/tunnel.js CHANGED
@@ -1 +1 @@
1
- import{Ja as f,Ka as g,La as h,Ma as i,Na as j,Oa as k,Pa as l,Qa as m,U as b,V as c,W as d,X as e,s as a}from"./chunk-XTXURVDQ.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{l as applyPermissionDecision,f as executeWorkflowRun,h as isAuthCredentialsBrowserDelivery,k as isByoOAuthBrowserDelivery,j as isManagedBrowserDelivery,i as isPermissionBrowserDelivery,m as processCorsair,c as resolveAccountFromWebhookLink,e as resolveTenantFromWebhookLink,d as resolveTenantIdFromWebhookLink,g as runReadonlyProbe,b as setWebhookTenantLink,a as verifyBrowserDeliveryToken};
1
+ import{Ja as f,Ka as g,La as h,Ma as i,Na as j,Oa as k,Pa as l,Qa as m,U as b,V as c,W as d,X as e,s as a}from"./chunk-XQZJJTZ7.js";import"./chunk-6IURNA4L.js";import"./chunk-7AYINDN2.js";import"./chunk-N66TLOH2.js";import"./chunk-Z2KT4F2U.js";import"./chunk-SOY77BN4.js";export{l as applyPermissionDecision,f as executeWorkflowRun,h as isAuthCredentialsBrowserDelivery,k as isByoOAuthBrowserDelivery,j as isManagedBrowserDelivery,i as isPermissionBrowserDelivery,m as processCorsair,c as resolveAccountFromWebhookLink,e as resolveTenantFromWebhookLink,d as resolveTenantIdFromWebhookLink,g as runReadonlyProbe,b as setWebhookTenantLink,a as verifyBrowserDeliveryToken};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.133",
3
+ "version": "0.1.134",
4
4
  "description": "Open-source integration layer for AI agents and apps. Managed OAuth, webhooks, and one API for 200+ integrations, with credentials that stay in your own database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -83,12 +83,12 @@
83
83
  "zod": "^4.1.13"
84
84
  },
85
85
  "optionalDependencies": {
86
- "@corsair-dev/frpc-darwin-arm64": "0.1.117",
87
- "@corsair-dev/frpc-linux-arm64": "0.1.117",
88
86
  "@corsair-dev/frpc-darwin-x64": "0.1.117",
87
+ "@corsair-dev/frpc-darwin-arm64": "0.1.117",
89
88
  "@corsair-dev/frpc-linux-x64": "0.1.117",
90
89
  "@corsair-dev/frpc-win32-arm64": "0.1.117",
91
- "@corsair-dev/frpc-win32-x64": "0.1.117"
90
+ "@corsair-dev/frpc-win32-x64": "0.1.117",
91
+ "@corsair-dev/frpc-linux-arm64": "0.1.117"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@testing-library/react": "^16.3.2",