corsair 0.1.111 → 0.1.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-delivery-C47IyQKV.d.ts → browser-delivery-BJtn0HMO.d.ts} +1 -1
- package/dist/{chunk-T5GSKYTP.js → chunk-IT5JH3MM.js} +16 -16
- package/dist/client/react/index.d.ts +3 -3
- package/dist/{connect-XL5IRCO3.js → connect-HQAFXDQS.js} +1 -1
- package/dist/core.d.ts +6 -6
- package/dist/core.js +1 -1
- package/dist/hub.d.ts +7 -7
- package/dist/hub.js +1 -1
- package/dist/{index-CQVHpCrY.d.ts → index-B_P6rcu8.d.ts} +1 -1
- package/dist/{index-y3QBilws.d.ts → index-CsNw9hYU.d.ts} +3 -2
- package/dist/{index-Cn751yk3.d.ts → index-DcJhvFt7.d.ts} +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +1 -1
- package/dist/oauth.d.ts +3 -2
- package/dist/oauth.js +1 -1
- package/dist/{setup-GRBP3GDX.js → setup-GS4BAXOK.js} +1 -1
- package/dist/{setup-introspect-OFZ2ICYL.js → setup-introspect-KQHTBADC.js} +1 -1
- package/dist/setup.d.ts +3 -3
- package/dist/setup.js +1 -1
- package/dist/{tenant-match-utils-npYTTXCT.d.ts → tenant-match-utils-Dq3dd_Zs.d.ts} +2 -2
- package/dist/tunnel.d.ts +5 -5
- package/dist/tunnel.js +1 -1
- package/dist/{types-CcBQ3Vhg.d.ts → types-C24LhkXl.d.ts} +1 -0
- package/dist/{types-Cd8FiQ08.d.ts → types-Dt339hBs.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as ro,b as fe,c as oo,d as w,e as U,f as io,g as N,h as F,i as R,j as
|
|
1
|
+
import{a as ro,b as fe,c as oo,d as w,e as U,f as io,g as N,h as F,i as R,j as Tn,k as so,l as ao,m as At,n as uo,o as co}from"./chunk-WDF3YE27.js";import{a as to}from"./chunk-IGGCNGU2.js";import{ZodBoolean as Xu,ZodDate as ec,ZodEnum as nc,ZodNullable as tc,ZodNumber as rc,ZodObject as oc,ZodOptional as ic,ZodRecord as sc,ZodString as ac,ZodType as uc}from"zod";var vn=["abstract","activetrail","addresszen","agentmail","agentql","ahrefs","airtable","algolia","amplitude","asana","bitwarden","bluesky","box","cal","calendly","canva","cloudflare","cloudinary","confluence","cursor","databricks","datadog","deepseek","digitalocean","discord","dodopayments","dropbox","exa","facebook","figma","firecrawl","fireflies","gemini","github","gitlab","gmail","googlebigquery","googlecalendar","googledocs","googledrive","googlemaps","googlemeet","googlesheets","grafana","hackernews","hashnode","heygen","hubspot","insightoai","instagram","intercom","jira","linear","linkedin","mailchimp","monday","neon","notion","ollama","onedrive","onepassword","openai","openweathermap","oura","outlook","pagerduty","perplexityai","posthog","razorpay","reddit","resend","retailed","sentry","sharepoint","slack","spotify","strava","stripe","supabase","tally","tavily","teams","telegram","todoist","trello","twilio","twitter","twitterapiio","typeform","vapi","vercel","whatsapp","xquik","youtube","zendesk","zohomail","zoom"],lo={abstract:"Abstract",activetrail:"Active Trail",addresszen:"Addresszen",agentmail:"AgentMail",agentql:"AgentQL",ahrefs:"Ahrefs",airtable:"Airtable",algolia:"Algolia",amplitude:"Amplitude",asana:"Asana",bitwarden:"Bitwarden",bluesky:"Bluesky",box:"Box",cal:"Cal",calendly:"Calendly",canva:"Canva",cloudflare:"Cloudflare",cloudinary:"Cloudinary",confluence:"Confluence",cursor:"Cursor",databricks:"Databricks",datadog:"Datadog",deepseek:"DeepSeek",digitalocean:"DigitalOcean",discord:"Discord",dodopayments:"Dodo Payments",dropbox:"Dropbox",exa:"Exa",facebook:"Facebook",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",gemini:"Gemini",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googlebigquery:"Google BigQuery",googlecalendar:"Google Calendar",googledocs:"Google Docs",googledrive:"Google Drive",googlemaps:"Google Maps",googlemeet:"Google Meet",googlesheets:"Google Sheets",grafana:"Grafana",hackernews:"Hacker News",hashnode:"Hashnode",heygen:"HeyGen",hubspot:"HubSpot",insightoai:"Insighto.ai",instagram:"Instagram",intercom:"Intercom",jira:"Jira",linear:"Linear",linkedin:"LinkedIn",mailchimp:"Mailchimp",monday:"Monday",neon:"Neon",notion:"Notion",ollama:"Ollama",onedrive:"OneDrive",onepassword:"1Password",openai:"OpenAI",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",perplexityai:"Perplexity AI",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",retailed:"Retailed",sentry:"Sentry",sharepoint:"SharePoint",slack:"Slack",spotify:"Spotify",strava:"Strava",stripe:"Stripe",supabase:"Supabase",tally:"Tally",tavily:"Tavily",teams:"Teams",telegram:"Telegram",todoist:"Todoist",trello:"Trello",twilio:"Twilio",twitter:"Twitter",twitterapiio:"Twitter API IO",typeform:"Typeform",vapi:"Vapi",vercel:"Vercel",whatsapp:"WhatsApp",xquik:"XQuik",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom"};function ye(e){let n=lo[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}import{randomUUID as vs}from"crypto";var ks="corsair:client-bridge";function xt(e){return new URL(e).origin}function Fe(e){let n=JSON.stringify({type:ks,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(xt(e.hubOrigin));return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
|
|
2
2
|
(function () {
|
|
3
3
|
var message = ${n};
|
|
4
4
|
var targetOrigin = ${t};
|
|
@@ -6,17 +6,17 @@ import{a as ro,b as fe,c as oo,d as w,e as U,f as io,g as N,h as F,i as R,j as v
|
|
|
6
6
|
window.parent.postMessage(message, targetOrigin);
|
|
7
7
|
}
|
|
8
8
|
})();
|
|
9
|
-
</script></body></html>`}var bs=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Rt(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:bs.has(n)}catch{return!1}}function tn(e){return e==="development"?"browser":"server"}function po(e){return tn(e)==="browser"}function go(e){return Rt(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as vs}from"crypto";var me=60*1e3,Re=300*1e3;import{createHmac as ws,randomBytes as Cs,timingSafeEqual as Ts}from"crypto";function ie(){return Cs(16).toString("base64url")}function rn(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return ws("sha256",t).update(e).digest("base64url")}function ee(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=rn(o,t);try{if(!Ts(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 An(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=rn(i,n);return`${i}.${s}`}function on(e,n,t){let r=Math.floor(Date.now()/1e3);return An(e,n,r+Math.floor(t/1e3))}function Ie(e){return decodeURIComponent(e)}function It(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function fo(e){let n=e.trim();return n.length>0?n:null}function Ue(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Be(e,n){if(!fo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??vs(16).toString("base64url"),iat:t,exp:t+Math.floor(me/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=rn(o,n);return`${o}.${i}`}function he(e,n){return fo(n)?ee(e,n):null}function As(e){let n=xt(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 St(e){let n=Be(As(e),e.signingSecret);return Ue(e.deliveryUrl,n)}function yo(e){if(tn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Ps(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:St(r)}}var sn="https://auth.corsair.dev";var se=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function xn(e){let n=(e.apiUrl?.trim()||sn).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1}}function xs(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function H(e){let n=w(e).hub;if(!n||!xs(n))throw new se;return n}function mo(e){return e.replace(/\/$/,"")}function Rn(e){return e.oauthCallbackUrl?mo(e.oauthCallbackUrl.trim()):`${mo(e.apiUrl)}/oauth/callback`}function Le(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)")}function A(e){return typeof e=="string"&&e.length>0}function Rs(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Is(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function In(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!A(n.connectUrl)||!A(n.token)||!A(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId,environmentId:A(n.environmentId)?n.environmentId:n.projectId};return A(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Sn(e){if(!Array.isArray(e))throw new Error("Hub API returned an invalid connections response (expected array)");let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;if(!A(r.tenantId)||!A(r.plugin)||!Rs(r.status)||!Is(r.authType)||typeof r.connected!="boolean"||typeof r.verified!="boolean")continue;let o=Array.isArray(r.missingFields)?r.missingFields.filter(i=>typeof i=="string"):[];n.push({tenantId:r.tenantId,plugin:r.plugin,status:r.status,authType:r.authType,connected:r.connected,verified:r.verified,missingFields:o,reportedAt:A(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function _n(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!A(n.approvalUrl)||!A(n.token)||!A(n.projectId)||!A(n.expiresAt))throw new Error("Hub API returned an incomplete permission session (expected approvalUrl, token, projectId, and expiresAt)");return{approvalUrl:n.approvalUrl,token:n.token,projectId:n.projectId,expiresAt:n.expiresAt}}function En(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(A(n.access_token))return{access_token:n.access_token,refresh_token:A(n.refresh_token)?n.refresh_token:void 0,expires_in:(()=>{if(typeof n.expires_in=="number")return n.expires_in;if(typeof n.expires_in=="string"&&n.expires_in.trim().length>0){let t=Number(n.expires_in);return Number.isFinite(t)?t:void 0}})(),scope:A(n.scope)?n.scope:void 0};throw new Error(A(n.error)?A(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Ss(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function _s(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;A(r.name)&&n.push({name:r.name,level:r.level==="integration"||r.level==="account"?r.level:"account",required:r.required===!0,configured:r.configured===!0})}return n}function Es(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(i=>i.level==="integration"&&i.required&&!i.configured)?"missing_integration":t.some(i=>i.level==="account"&&i.required&&i.configured)?"partial":(r.length>0,"not_started")}function ho(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!A(n.tenantId)||!Array.isArray(n.plugins))throw new Error("Connect status response was incomplete (expected tenantId and plugins)");let t=[];for(let r of n.plugins){if(!r||typeof r!="object")continue;let o=r;if(!A(o.plugin)||typeof o.connected!="boolean")continue;let i=o.authKind==="oauth"||o.authKind==="api_key"||o.authKind==="bot_token"?o.authKind:"api_key",s=_s(o.fields),a=Ss(o.missingRequiredFields),u=Es(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:A(o.providerName)?o.providerName:o.plugin,authKind:i,status:u,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function Dn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}var Ds="3000",Os="/api/corsair";function Ms(e){return e.replace(/\/$/,"")}function ke(e){let n=e?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(n){let r=/^https?:\/\//i.test(n)?n:`https://${n}`;return Ms(r)}return`http://localhost:${process.env.PORT?.trim()||Ds}${Os}`}function ko(e){return e.replace(/\/$/,"")}function _t(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return ke()}catch{return null}}function bo(e){let n=_t(e);return n?{"x-corsair-delivery-url":n}:{}}async function wo(e){let n=e.headers.get("content-type")??"",t=await e.text();if(!t)return null;if(!n.includes("application/json")&&t.trimStart().startsWith("<"))throw new Error(`Hub API returned HTML instead of JSON (HTTP ${e.status}). Check HUB_API_URL and deploy the latest hub API.`);try{return JSON.parse(t)}catch{throw new Error(`Hub API returned invalid JSON (HTTP ${e.status})`)}}function Co(e,n,t){if(n===404&&t)return t;let r=Dn(e);return r||`Hub API returned HTTP ${n}`}async function _(e){let n=ko(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...bo(e.hub)},body:JSON.stringify(e.body)}),r=await wo(t);if(!t.ok)throw new Error(Co(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function $(e){let n=ko(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...bo(e.hub)}}),r=await wo(t);if(!t.ok)throw new Error(Co(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as To,createDecipheriv as vo,randomBytes as On,scrypt as Hs}from"crypto";import{promisify as Fs}from"util";var Po=Fs(Hs),Mn="aes-256-gcm",Ao=12,Hn=16,Us=16,an=32;function ae(){return On(an).toString("base64")}async function ue(e,n){let t=On(Us),r=await Po(n,t,an),o=On(Ao),i=To(Mn,r,o,{authTagLength:Hn}),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 Z(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"),u=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),c=await Po(n,s,an),p=vo(Mn,c,a,{authTagLength:Hn});return p.setAuthTag(u),Buffer.concat([p.update(l),p.final()]).toString("utf8")}function Et(e,n){let t=Buffer.from(n,"base64"),r=On(Ao),o=To(Mn,t,r,{authTagLength:Hn}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function un(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"),u=Buffer.from(o,"base64"),l=vo(Mn,i,s,{authTagLength:Hn});return l.setAuthTag(a),Buffer.concat([l.update(u),l.final()]).toString("utf8")}function be(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Et(o,n);return t}function ce(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=un(o,n);return t}function cn(e,n,t){let r=ce(e,n);return be(r,t)}function xo(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 Dt=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function O(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...F[n].integration,...i],a=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let m=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!m)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:m.id,config:Dt(m.config),dek:m.dek??null},a},updateIntegration:async m=>{let h=await u.getIntegration();await o.db.updateTable("corsair_integrations").set({...m.config!==void 0?{config:m.config}:{},...m.dek!==void 0?{dek:m.dek}:{},updated_at:new Date}).where("id","=",h.id).execute(),a=null}},l=null,c=async()=>{if(l)return l;let m=await u.getIntegration();if(!m.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await Z(m.dek,r),l},p=async()=>{let m=await u.getIntegration(),h=await c(),b=m.config;return!b||Object.keys(b).length===0?{}:ce(b,h)},d=Promise.resolve(),g=m=>{let h=d.then(()=>f(m));return d=h.catch(()=>{}),h},f=async m=>{let h=await c(),b;try{b=await p()}catch(x){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,x),b={}}let C={...b};for(let[x,E]of Object.entries(m))E===null?delete C[x]:C[x]=E;let S=be(C,h);await u.updateIntegration({config:S})};return{get_dek:c,issue_new_dek:async()=>{let m=await u.getIntegration(),h=ae(),b={};if(m.dek){let S=await Z(m.dek,r),x=m.config;x&&Object.keys(x).length>0&&(b=cn(x,S,h))}let C=await ue(h,r);return await u.updateIntegration({config:b,dek:C}),l=h,h},...xo(p,g,s)}}function D(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,u=[...F[n].account,...s],l=null,c=null,p=async()=>{if(c)return c;let k=!1;for(;;){let T=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!T){if(!k&&a){k=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return c={id:T.id,config:Dt(T.config),dek:T.dek??null},c}},d={kek:o,integrationName:t,tenantId:r,getIntegration:p,getAccount:async()=>{if(l)return l;let k=!1;for(;;){let T=await p(),v=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",T.id).executeTakeFirst();if(!v){if(!k&&a){k=!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:v.id,config:Dt(v.config),dek:v.dek??null},l}},updateAccount:async k=>{let T=await d.getAccount();await i.db.updateTable("corsair_accounts").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",T.id).execute(),l=null}},g=null,f=null,y=async()=>{if(g)return g;let k=await d.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await Z(k.dek,o),g},m=async()=>{if(f)return f;let k=await d.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await Z(k.dek,o),f},h=async()=>{let k=await d.getAccount(),T=await y(),v=k.config;return!v||Object.keys(v).length===0?{}:ce(v,T)},b=async()=>{let k=await d.getIntegration(),T=await m(),v=k.config;return!v||Object.keys(v).length===0?{}:ce(v,T)},C=Promise.resolve(),S=k=>{let T=C.then(()=>x(k));return C=T.catch(()=>{}),T},x=async k=>{let T=await y(),v;try{v=await h()}catch(P){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,P),v={}}let j={...v};for(let[P,Y]of Object.entries(k))Y===null?delete j[P]:j[P]=Y;let re=be(j,T);await d.updateAccount({config:re})},E={get_dek:y,issue_new_dek:async()=>{let k=await d.getAccount(),T=ae(),v={};if(k.dek){let re=await Z(k.dek,o),P=k.config;P&&Object.keys(P).length>0&&(v=cn(P,re,T))}let j=await ue(T,o);return await d.updateAccount({config:v,dek:j}),g=T,T},...xo(h,S,u)};return n==="oauth_2"&&(E.get_integration_credentials=async()=>{let k=await b();return{...k,client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),E}async function Ro(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=ae(),i=await ue(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function Io(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=ae(),a=await ue(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var Bs=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function we(e){return Bs.has(e)}function Ls(e,n){return we(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Ns(e){return!we(e)}function $s(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function Ws(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function js(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!$s(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function So(e,n){if(!e)return!1;let t=N(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function Ks(e,n){let r=e.authConfig?.[n]?.integration??[];return[...F[n].integration,...r]}function qs(e,n){let r=e.authConfig?.[n]?.account??[];return[...F[n].account,...r]}function Zs(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:js(n,t),fields:t,missingRequiredFields:r}}async function Se(e,n,t){let r=R(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??[],u=O({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=D({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),c=Ks(n,r),p=qs(n,r),d=[];for(let g of c)d.push({name:g,level:"integration",required:Ls(r,g),configured:await So(u,g)});for(let g of p)d.push({name:g,level:"account",required:Ns(g),configured:await So(l,g)});if(Ws(r,d)){let g=d.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return Zs(n.id,r,d)}async function ln(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 Se(e,s,r);a&&i.push(a)}return i}function Fn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var _o=Symbol.for("corsair:internal"),Eo=new WeakMap,Do=new WeakMap;function Gs(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function Js(e){if(e.database){let t=Eo.get(e.database);return t||(t=new Map,Eo.set(e.database,t)),t}let n=Do.get(e);return n||(n=new Map,Do.set(e,n)),n}function zs(e){return e.multiTenancy?{withTenant:()=>({}),[_o]:e}:{[_o]:e}}async function Ne(e,n){if(!e.database)return;let t=n.trim()||"default",r=Js(e),o=Gs(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-GRBP3GDX.js");await a(zs(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 Ce(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Ot(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 $e(e,n){let t=dn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Mt=600*1e3;function Un(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:Ot(r,{maxAgeMs:Mt})}function Oo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Mo(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 We(e,n){await _({hub:e,path:"/connections/report",body:Oo(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function Vs(e,n){try{let t=H(e);_({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof se)return}}async function Ys(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!R(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Se(n,e.plugin,r);o&&Fo(e.hub,Mo({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function Ho(e,n){Vs(e,n)}function Fo(e,n){_({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function pn(e){Ys(e).catch(()=>{})}async function le(e,n){let t=w(e);if(!R(n.plugin))return;let o=await Se(t,n.plugin,n.tenantId);o&&Ho(e,Mo({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 Bn(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 Uo=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function Qs(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 Xs(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 Z(n.dek,e.kek),r=Uo(n.config),o={};Object.keys(r).length>0&&(o=ce(r,t)),o[e.link.linkType]=e.link.externalId;let i=be(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function je(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:u}=await Qs({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let c=D({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),p=`set_${i.linkType}`,d=c[p];typeof d=="function"&&(await d(i.externalId),l=!0)}l||await Xs({database:n,kek:t,accountId:u,link:i})}async function Ht(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 u=await Z(a.dek,t),c=Uo(a.config)[o];if(!c)continue;if(un(c,u)===i)return a}catch{continue}return null}async function Ln(e){return(await Ht(e))?.tenant_id??null}async function Bo(e){return Ln({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as Lo 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}?${Lo.stringify(i)}`}async function No(e,n){try{return await $({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function Nn(e,n,t,r){if(!n.subscribe)return;let o=H(e),i=await No(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await le(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var B=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function $o(e){let n=e.oauthConfig;if(!n)throw new B("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function ea(e,n,t,r){let o=co(e),i=await o.integrations.findByName(n);if(!i)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.accounts.findOne({tenant_id:t,integration_id:i.id}))return;let a=ae(),u=await ue(a,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:u})}async function Ft(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=U(s,n,d=>new B("plugin_not_found",d)),u=$o(a),c=await O({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);if(i){let d=new URL(_e({oauthConfig:u,clientId:c,redirectUri:o,state:""}));return d.searchParams.delete("state"),{url:d.toString(),state:""}}let p=$e(Ce(n,r),s.kek);return{url:_e({oauthConfig:u,clientId:c,redirectUri:o,state:p}),state:p}}async function gn(e,n){let{code:t,state:r,redirectUri:o}=n,i=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new B("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let y=Un(r,i.kek);if(!y)throw new B("invalid_state","Invalid or tampered state parameter");s=y.plugin,a=y.tenantId}if(!i.database)throw new B("no_database","No database configured on corsair instance");let u=U(i,s,y=>new B("plugin_not_found",y)),l=$o(u),c=O({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),p=await c.get_client_id(),d=await c.get_client_secret();if(!p||!d)throw new B("credentials_not_configured",`Credentials not configured for '${s}'`);await ea(i.database,s,a,i.kek);let g=await $n(t,p,d,l,o);if(!g.access_token)throw new B("no_access_token",`No access_token returned from ${l.providerName}`);let f=D({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...u.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 le(e,{plugin:u,tenantId:a}).catch(()=>{});try{let y=await Bn(i.plugins,s,g);if(y){try{let m=u.authConfig?.oauth_2?.account??[];await je({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:y,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,m)}i.hub&&We(i.hub,{plugin:s,tenantId:a,link:y,authType:"oauth_2"})}}catch(y){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,y)}if(u.subscribe)try{await Nn(e,u,a,f)}catch(y){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,y)}return{plugin:s,tenantId:a}}async function na(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??Nn,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let u=t.plugins.find(c=>c.id===a.integrationName);if(!u?.subscribe)continue;let l=`${u.id}/${a.tenantId}`;try{let c=D({authType:"oauth_2",integrationName:u.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...u.authConfig?.oauth_2?.account??[]]}),p=u.keyBuilder;if(p){let d=Object.create(c,{get_expires_at:{value:async()=>"0"}});await p({authType:"oauth_2",keys:d},"endpoint")}await o(n,u,a.tenantId,c),i.push(l)}catch(c){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,c),s.push(l)}}return{renewed:i,failed:s}}async function Wo(e){let n=w(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 na({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function ta(e,n={}){let t=!1,r=()=>{t||(t=!0,Wo(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 jo(e){if(!w(e).database)throw new Error("A database must be configured to provision Corsair integrations");await Wn(e,{silent:!0})}async function Ke(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(t,n)}var ra=Symbol.for("corsair:internal"),oa=new Set(["access_token","refresh_token","expires_at","scope"]);function ia(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function sa(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!we(t)&&!oa.has(t)):n.filter(t=>!we(t))}function Ko(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function aa(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function ua(e){return{[ra]:Ko(e)}}async function jn(e,n,t={}){let r=Rn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Ko(e),a=ua(e);for(let u of e.plugins){if(i&&!i.has(u.id))continue;let l=R(u);if(!l)continue;let c=ia(l),p=t.providerNameOverrides?.[u.id]??ye(u.id),d=await Se(s,u,n),g=vn(u,l),f=sa(l,g),y={plugin:u.id,providerName:p,authKind:c,alreadyConfigured:d?.connected??!1};if(f.length>0&&(y.credentialFields=f),c==="oauth"){let h=t.oauthModeOverrides?.[u.id]??(l==="managed"?"managed":"byo");if(y.oauthMode=h,!t.skipOAuthUrlGeneration&&h!=="managed")try{let b=await Ft(a,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});y.oauthUrl=b.url}catch(b){y.setupError=b instanceof Error?b.message:`Could not prepare OAuth for ${u.id}`}}o.push(y)}return o}async function ed(e,n,t={}){let r=w(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return jn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function qo(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(e.internalConfig??aa(e),n)}async function Zo(e,n){await Ke(e,n)}async function Go(e,n){let t=Le(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ke({deliveryUrl:n.deliveryUrl})),_({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:In})}async function Ut(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await qo(t,n.tenantId);let r=await jn(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 Go(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function Kn(e,n){let t=w(e),r=H(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await Zo(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,u=await jn(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(u.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 Go(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}function Jo(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function ca(e,n){return n&&!n.has(e.id)?!1:R(e)!==null}async function zo(e,n,t={}){let r=w(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,s=await ln(r,o,{pluginIds:t.pluginIds}),a=new Map(s.map(l=>[l.plugin,l])),u=r.plugins.filter(l=>ca(l,i)).map(l=>{let c=R(l),p=a.get(l.id);return p?{plugin:l.id,providerName:ye(l.id),authKind:Jo(c),status:p.status,connected:p.connected,fields:p.fields.map(d=>({name:d.name,level:d.level,required:d.required,configured:d.configured})),missingRequiredFields:p.missingRequiredFields}:{plugin:l.id,providerName:ye(l.id),authKind:Jo(c),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:u}}async function Vo(e,n){let t=H(e);return $({hub:t,path:`/projects/${encodeURIComponent(n.projectId)}/connections`,notFoundMessage:"Hub REST API not found at /projects/:id/connections. Check HUB_API_URL and ensure the Hub API is deployed.",parseResponse:Sn})}function qe(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var G=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function la(e){let n=e.oauthConfig;if(!n)throw new G("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Bt(e,n){let t=w(e,()=>new G("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new G("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new G("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=Un(n,t.kek);if(!o)throw new G("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=U(t,i,d=>new G("plugin_not_found",d)),u=la(a),c=await O({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!c)throw new G("client_id_not_configured",`client_id not configured for '${i}'`);let p=_e({oauthConfig:u,clientId:c,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:u.providerName,oauthUrl:p,state:n}}import{AsyncLocalStorage as pa}from"async_hooks";import{randomBytes as ga}from"crypto";import{v4 as fa}from"uuid";async function qn(e,n){let t=Le(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=ke({deliveryUrl:n.deliveryUrl})),_({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:_n})}function Zn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Lt="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 $t(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Yo(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Nt(e){return Zn(e)}async function Wt(e,n){if($t(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Yo(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await qn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:da(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function da(e){try{return JSON.parse(e)}catch{return e}}async function Gn(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Wt(e,n);return{...n,approvalUrl:r}}async function jt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:u,tenantId:l,expiresAt:c,operationPath:p}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:u});let g=await Wt({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(u),tenant_id:l,expires_at:c});return $t(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):Nt(g):Lt:r?g?Nt(g):`Action '${p}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Lt}var Ze=class extends Error{constructor(n){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError"}};var Xo=new pa,Jn=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 Kt(e){return Xo.run(!0,e)}function ei(){return Xo.getStore()===!0}function qt(e,n){if(ei()&&n!=="read")throw new Jn(e,n)}var ya={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 ma(e,n,t){return t!==void 0?t:ya[n][e]}function Zt(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 ni(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 Qo(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 ti(e){let n=ma(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 bs=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Rt(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:bs.has(n)}catch{return!1}}function tn(e){return e==="development"?"browser":"server"}function po(e){return tn(e)==="browser"}function go(e){return Rt(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as Ts}from"crypto";var me=60*1e3,Re=300*1e3;import{createHmac as ws,randomBytes as Cs,timingSafeEqual as Ps}from"crypto";function ie(){return Cs(16).toString("base64url")}function rn(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return ws("sha256",t).update(e).digest("base64url")}function ee(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=rn(o,t);try{if(!Ps(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 An(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=rn(i,n);return`${i}.${s}`}function on(e,n,t){let r=Math.floor(Date.now()/1e3);return An(e,n,r+Math.floor(t/1e3))}function Ie(e){return decodeURIComponent(e)}function It(e){return encodeURIComponent(e).replace(/\./g,"%2E")}function fo(e){let n=e.trim();return n.length>0?n:null}function Ue(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Be(e,n){if(!fo(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??Ts(16).toString("base64url"),iat:t,exp:t+Math.floor(me/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=rn(o,n);return`${o}.${i}`}function he(e,n){return fo(n)?ee(e,n):null}function As(e){let n=xt(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 St(e){let n=Be(As(e),e.signingSecret);return Ue(e.deliveryUrl,n)}function yo(e){if(tn(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=vs(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:St(r)}}var sn="https://auth.corsair.dev";var se=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function xn(e){let n=(e.apiUrl?.trim()||sn).replace(/\/$/,""),t=e.projectApiKey.trim(),r=e.signingSecret.trim();if(!t||!r)throw new Error("Hub config requires non-empty projectApiKey and signingSecret");return{apiUrl:n,projectApiKey:t,signingSecret:r,oauthCallbackUrl:e.oauthCallbackUrl?.trim().replace(/\/$/,""),redirectURL:e.redirectURL?.trim()||void 0,allowWorkflowExecution:e.allowWorkflowExecution??!1}}function xs(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function H(e){let n=w(e).hub;if(!n||!xs(n))throw new se;return n}function mo(e){return e.replace(/\/$/,"")}function Rn(e){return e.oauthCallbackUrl?mo(e.oauthCallbackUrl.trim()):`${mo(e.apiUrl)}/oauth/callback`}function Le(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)")}function A(e){return typeof e=="string"&&e.length>0}function Rs(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Is(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function In(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!A(n.connectUrl)||!A(n.token)||!A(n.projectId))throw new Error("Hub API returned an incomplete connect session (expected connectUrl, token, and projectId)");let t={connectUrl:n.connectUrl,token:n.token,projectId:n.projectId,environmentId:A(n.environmentId)?n.environmentId:n.projectId};return A(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Sn(e){if(!Array.isArray(e))throw new Error("Hub API returned an invalid connections response (expected array)");let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;if(!A(r.tenantId)||!A(r.plugin)||!Rs(r.status)||!Is(r.authType)||typeof r.connected!="boolean"||typeof r.verified!="boolean")continue;let o=Array.isArray(r.missingFields)?r.missingFields.filter(i=>typeof i=="string"):[];n.push({tenantId:r.tenantId,plugin:r.plugin,status:r.status,authType:r.authType,connected:r.connected,verified:r.verified,missingFields:o,reportedAt:A(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function _n(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!A(n.approvalUrl)||!A(n.token)||!A(n.projectId)||!A(n.expiresAt))throw new Error("Hub API returned an incomplete permission session (expected approvalUrl, token, projectId, and expiresAt)");return{approvalUrl:n.approvalUrl,token:n.token,projectId:n.projectId,expiresAt:n.expiresAt}}function En(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(A(n.access_token))return{access_token:n.access_token,refresh_token:A(n.refresh_token)?n.refresh_token:void 0,expires_in:(()=>{if(typeof n.expires_in=="number")return n.expires_in;if(typeof n.expires_in=="string"&&n.expires_in.trim().length>0){let t=Number(n.expires_in);return Number.isFinite(t)?t:void 0}})(),scope:A(n.scope)?n.scope:void 0};throw new Error(A(n.error)?A(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Ss(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function _s(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;A(r.name)&&n.push({name:r.name,level:r.level==="integration"||r.level==="account"?r.level:"account",required:r.required===!0,configured:r.configured===!0})}return n}function Es(e,n,t,r){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"?e:n?"ready":t.some(i=>i.level==="integration"&&i.required&&!i.configured)?"missing_integration":t.some(i=>i.level==="account"&&i.required&&i.configured)?"partial":(r.length>0,"not_started")}function ho(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!A(n.tenantId)||!Array.isArray(n.plugins))throw new Error("Connect status response was incomplete (expected tenantId and plugins)");let t=[];for(let r of n.plugins){if(!r||typeof r!="object")continue;let o=r;if(!A(o.plugin)||typeof o.connected!="boolean")continue;let i=o.authKind==="oauth"||o.authKind==="api_key"||o.authKind==="bot_token"?o.authKind:"api_key",s=_s(o.fields),a=Ss(o.missingRequiredFields),u=Es(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:A(o.providerName)?o.providerName:o.plugin,authKind:i,status:u,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function Dn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}var Ds="3000",Os="/api/corsair";function Ms(e){return e.replace(/\/$/,"")}function ke(e){let n=e?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(n){let r=/^https?:\/\//i.test(n)?n:`https://${n}`;return Ms(r)}return`http://localhost:${process.env.PORT?.trim()||Ds}${Os}`}function ko(e){return e.replace(/\/$/,"")}function _t(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return ke()}catch{return null}}function bo(e){let n=_t(e);return n?{"x-corsair-delivery-url":n}:{}}async function wo(e){let n=e.headers.get("content-type")??"",t=await e.text();if(!t)return null;if(!n.includes("application/json")&&t.trimStart().startsWith("<"))throw new Error(`Hub API returned HTML instead of JSON (HTTP ${e.status}). Check HUB_API_URL and deploy the latest hub API.`);try{return JSON.parse(t)}catch{throw new Error(`Hub API returned invalid JSON (HTTP ${e.status})`)}}function Co(e,n,t){if(n===404&&t)return t;let r=Dn(e);return r||`Hub API returned HTTP ${n}`}async function _(e){let n=ko(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...bo(e.hub)},body:JSON.stringify(e.body)}),r=await wo(t);if(!t.ok)throw new Error(Co(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function $(e){let n=ko(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...bo(e.hub)}}),r=await wo(t);if(!t.ok)throw new Error(Co(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as Po,createDecipheriv as To,randomBytes as On,scrypt as Hs}from"crypto";import{promisify as Fs}from"util";var vo=Fs(Hs),Mn="aes-256-gcm",Ao=12,Hn=16,Us=16,an=32;function ae(){return On(an).toString("base64")}async function ue(e,n){let t=On(Us),r=await vo(n,t,an),o=On(Ao),i=Po(Mn,r,o,{authTagLength:Hn}),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 Z(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"),u=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),c=await vo(n,s,an),p=To(Mn,c,a,{authTagLength:Hn});return p.setAuthTag(u),Buffer.concat([p.update(l),p.final()]).toString("utf8")}function Et(e,n){let t=Buffer.from(n,"base64"),r=On(Ao),o=Po(Mn,t,r,{authTagLength:Hn}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function un(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"),u=Buffer.from(o,"base64"),l=To(Mn,i,s,{authTagLength:Hn});return l.setAuthTag(a),Buffer.concat([l.update(u),l.final()]).toString("utf8")}function be(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Et(o,n);return t}function ce(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=un(o,n);return t}function cn(e,n,t){let r=ce(e,n);return be(r,t)}function xo(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 Dt=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function O(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...F[n].integration,...i],a=null,u={kek:r,integrationName:t,getIntegration:async()=>{if(a)return a;let h=await o.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!h)throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`);return a={id:h.id,config:Dt(h.config),dek:h.dek??null},a},updateIntegration:async h=>{let m=await u.getIntegration();await o.db.updateTable("corsair_integrations").set({...h.config!==void 0?{config:h.config}:{},...h.dek!==void 0?{dek:h.dek}:{},updated_at:new Date}).where("id","=",m.id).execute(),a=null}},l=null,c=async()=>{if(l)return l;let h=await u.getIntegration();if(!h.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await Z(h.dek,r),l},p=async()=>{let h=await u.getIntegration(),m=await c(),b=h.config;return!b||Object.keys(b).length===0?{}:ce(b,m)},d=Promise.resolve(),g=h=>{let m=d.then(()=>f(h));return d=m.catch(()=>{}),m},f=async h=>{let m=await c(),b;try{b=await p()}catch(x){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,x),b={}}let C={...b};for(let[x,E]of Object.entries(h))E===null?delete C[x]:C[x]=E;let S=be(C,m);await u.updateIntegration({config:S})};return{get_dek:c,issue_new_dek:async()=>{let h=await u.getIntegration(),m=ae(),b={};if(h.dek){let S=await Z(h.dek,r),x=h.config;x&&Object.keys(x).length>0&&(b=cn(x,S,m))}let C=await ue(m,r);return await u.updateIntegration({config:b,dek:C}),l=m,m},...xo(p,g,s)}}function D(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,u=[...F[n].account,...s],l=null,c=null,p=async()=>{if(c)return c;let k=!1;for(;;){let P=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!P){if(!k&&a){k=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return c={id:P.id,config:Dt(P.config),dek:P.dek??null},c}},d={kek:o,integrationName:t,tenantId:r,getIntegration:p,getAccount:async()=>{if(l)return l;let k=!1;for(;;){let P=await p(),T=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",P.id).executeTakeFirst();if(!T){if(!k&&a){k=!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:T.id,config:Dt(T.config),dek:T.dek??null},l}},updateAccount:async k=>{let P=await d.getAccount();await i.db.updateTable("corsair_accounts").set({...k.config!==void 0?{config:k.config}:{},...k.dek!==void 0?{dek:k.dek}:{},updated_at:new Date}).where("id","=",P.id).execute(),l=null}},g=null,f=null,y=async()=>{if(g)return g;let k=await d.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return g=await Z(k.dek,o),g},h=async()=>{if(f)return f;let k=await d.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return f=await Z(k.dek,o),f},m=async()=>{let k=await d.getAccount(),P=await y(),T=k.config;return!T||Object.keys(T).length===0?{}:ce(T,P)},b=async()=>{let k=await d.getIntegration(),P=await h(),T=k.config;return!T||Object.keys(T).length===0?{}:ce(T,P)},C=Promise.resolve(),S=k=>{let P=C.then(()=>x(k));return C=P.catch(()=>{}),P},x=async k=>{let P=await y(),T;try{T=await m()}catch(v){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,v),T={}}let j={...T};for(let[v,Y]of Object.entries(k))Y===null?delete j[v]:j[v]=Y;let re=be(j,P);await d.updateAccount({config:re})},E={get_dek:y,issue_new_dek:async()=>{let k=await d.getAccount(),P=ae(),T={};if(k.dek){let re=await Z(k.dek,o),v=k.config;v&&Object.keys(v).length>0&&(T=cn(v,re,P))}let j=await ue(P,o);return await d.updateAccount({config:T,dek:j}),g=P,P},...xo(m,S,u)};return n==="oauth_2"&&(E.get_integration_credentials=async()=>{let k=await b();return{...k,client_id:k.client_id||null,client_secret:k.client_secret||null,redirect_url:k.redirect_url??null}}),E}async function Ro(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=ae(),i=await ue(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function Io(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=ae(),a=await ue(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var Bs=new Set(["webhook_signature","expires_at","scope","redirect_url","refresh_token"]);function we(e){return Bs.has(e)}function Ls(e,n){return we(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function Ns(e){return!we(e)}function $s(e){switch(e){case"oauth_2":case"managed":return["access_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function Ws(e,n){return e!=="oauth_2"&&e!=="managed"?!1:n.some(t=>t.level==="account"&&t.name==="expires_at"&&t.configured)}function js(e,n){let t=i=>n.find(s=>s.level==="account"&&s.name===i);if(!$s(e).every(i=>t(i)?.configured))return!1;let o=t("refresh_token");return o?.required?!!o.configured:!0}async function So(e,n){if(!e)return!1;let t=N(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function Ks(e,n){let r=e.authConfig?.[n]?.integration??[];return[...F[n].integration,...r]}function qs(e,n){let r=e.authConfig?.[n]?.account??[];return[...F[n].account,...r]}function Zs(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:js(n,t),fields:t,missingRequiredFields:r}}async function Se(e,n,t){let r=R(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??[],u=O({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=D({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),c=Ks(n,r),p=qs(n,r),d=[];for(let g of c)d.push({name:g,level:"integration",required:Ls(r,g),configured:await So(u,g)});for(let g of p)d.push({name:g,level:"account",required:Ns(g),configured:await So(l,g)});if(Ws(r,d)){let g=d.find(f=>f.level==="account"&&f.name==="refresh_token");g&&(g.required=!0)}return Zs(n.id,r,d)}async function ln(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 Se(e,s,r);a&&i.push(a)}return i}function Fn(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var _o=Symbol.for("corsair:internal"),Eo=new WeakMap,Do=new WeakMap;function Gs(e,n){let t=n.map(r=>r.id).sort().join("\0");return`${e}\0${t}`}function Js(e){if(e.database){let t=Eo.get(e.database);return t||(t=new Map,Eo.set(e.database,t)),t}let n=Do.get(e);return n||(n=new Map,Do.set(e,n)),n}function zs(e){return e.multiTenancy?{withTenant:()=>({}),[_o]:e}:{[_o]:e}}async function Ne(e,n){if(!e.database)return;let t=n.trim()||"default",r=Js(e),o=Gs(t,e.plugins),i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-GS4BAXOK.js");await a(zs(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 Ce(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Ot(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 $e(e,n){let t=dn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Mt=600*1e3;function Un(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:Ot(r,{maxAgeMs:Mt})}function Oo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Mo(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 We(e,n){await _({hub:e,path:"/connections/report",body:Oo(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function Vs(e,n){try{let t=H(e);_({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof se)return}}async function Ys(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!R(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Se(n,e.plugin,r);o&&Fo(e.hub,Mo({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function Ho(e,n){Vs(e,n)}function Fo(e,n){_({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function pn(e){Ys(e).catch(()=>{})}async function le(e,n){let t=w(e);if(!R(n.plugin))return;let o=await Se(t,n.plugin,n.tenantId);o&&Ho(e,Mo({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 Bn(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 Uo=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function Qs(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 Xs(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 Z(n.dek,e.kek),r=Uo(n.config),o={};Object.keys(r).length>0&&(o=ce(r,t)),o[e.link.linkType]=e.link.externalId;let i=be(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function je(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:u}=await Qs({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let c=D({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),p=`set_${i.linkType}`,d=c[p];typeof d=="function"&&(await d(i.externalId),l=!0)}l||await Xs({database:n,kek:t,accountId:u,link:i})}async function Ht(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 u=await Z(a.dek,t),c=Uo(a.config)[o];if(!c)continue;if(un(c,u)===i)return a}catch{continue}return null}async function Ln(e){return(await Ht(e))?.tenant_id??null}async function Bo(e){return Ln({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}import*as Lo 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}?${Lo.stringify(i)}`}async function No(e,n){try{return await $({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function Nn(e,n,t,r){if(!n.subscribe)return;let o=H(e),i=await No(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await le(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var B=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function $o(e){let n=e.oauthConfig;if(!n)throw new B("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function ea(e,n,t,r){let o=co(e),i=await o.integrations.findByName(n);if(!i)throw new Error(`Integration '${n}' not found. Run setupCorsair first.`);if(await o.accounts.findOne({tenant_id:t,integration_id:i.id}))return;let a=ae(),u=await ue(a,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:u})}async function Ft(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=U(s,n,d=>new B("plugin_not_found",d)),u=$o(a),c=await O({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!c)throw new Error(`client_id not configured for '${n}'`);if(i){let d=new URL(_e({oauthConfig:u,clientId:c,redirectUri:o,state:""}));return d.searchParams.delete("state"),{url:d.toString(),state:""}}let p=$e(Ce(n,r),s.kek);return{url:_e({oauthConfig:u,clientId:c,redirectUri:o,state:p}),state:p}}function na(e,n){return{...n??{},...e}}async function gn(e,n){let{code:t,state:r,redirectUri:o}=n,i=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new B("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let y=Un(r,i.kek);if(!y)throw new B("invalid_state","Invalid or tampered state parameter");s=y.plugin,a=y.tenantId}if(!i.database)throw new B("no_database","No database configured on corsair instance");let u=U(i,s,y=>new B("plugin_not_found",y)),l=$o(u),c=O({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),p=await c.get_client_id(),d=await c.get_client_secret();if(!p||!d)throw new B("credentials_not_configured",`Credentials not configured for '${s}'`);await ea(i.database,s,a,i.kek);let g=await $n(t,p,d,l,o);if(!g.access_token)throw new B("no_access_token",`No access_token returned from ${l.providerName}`);let f=D({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...u.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 le(e,{plugin:u,tenantId:a}).catch(()=>{});try{let y=na(g,n.callbackParams),h=await Bn(i.plugins,s,y);if(h){try{let m=u.authConfig?.oauth_2?.account??[];await je({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:h,authType:"oauth_2",extraAccountFields:m})}catch(m){console.warn(`[corsair:oauth] Failed to persist webhook tenant link for '${s}' tenant '${a}':`,m)}i.hub&&We(i.hub,{plugin:s,tenantId:a,link:h,authType:"oauth_2"})}}catch(y){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,y)}if(u.subscribe)try{await Nn(e,u,a,f)}catch(y){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,y)}return{plugin:s,tenantId:a}}async function ta(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??Nn,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let u=t.plugins.find(c=>c.id===a.integrationName);if(!u?.subscribe)continue;let l=`${u.id}/${a.tenantId}`;try{let c=D({authType:"oauth_2",integrationName:u.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...u.authConfig?.oauth_2?.account??[]]}),p=u.keyBuilder;if(p){let d=Object.create(c,{get_expires_at:{value:async()=>"0"}});await p({authType:"oauth_2",keys:d},"endpoint")}await o(n,u,a.tenantId,c),i.push(l)}catch(c){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,c),s.push(l)}}return{renewed:i,failed:s}}async function Wo(e){let n=w(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 ta({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function ra(e,n={}){let t=!1,r=()=>{t||(t=!0,Wo(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 jo(e){if(!w(e).database)throw new Error("A database must be configured to provision Corsair integrations");await Wn(e,{silent:!0})}async function Ke(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(t,n)}var oa=Symbol.for("corsair:internal"),ia=new Set(["access_token","refresh_token","expires_at","scope"]);function sa(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function aa(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!we(t)&&!ia.has(t)):n.filter(t=>!we(t))}function Ko(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function ua(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:e.multiTenancy??!1}}function ca(e){return{[oa]:Ko(e)}}async function jn(e,n,t={}){let r=Rn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Ko(e),a=ca(e);for(let u of e.plugins){if(i&&!i.has(u.id))continue;let l=R(u);if(!l)continue;let c=sa(l),p=t.providerNameOverrides?.[u.id]??ye(u.id),d=await Se(s,u,n),g=Tn(u,l),f=aa(l,g),y={plugin:u.id,providerName:p,authKind:c,alreadyConfigured:d?.connected??!1};if(f.length>0&&(y.credentialFields=f),c==="oauth"){let m=t.oauthModeOverrides?.[u.id]??(l==="managed"?"managed":"byo");if(y.oauthMode=m,!t.skipOAuthUrlGeneration&&m!=="managed")try{let b=await Ft(a,u.id,{tenantId:n,redirectUri:r,hubConnect:!0});y.oauthUrl=b.url}catch(b){y.setupError=b instanceof Error?b.message:`Could not prepare OAuth for ${u.id}`}}o.push(y)}return o}async function nd(e,n,t={}){let r=w(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return jn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function qo(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ne(e.internalConfig??ua(e),n)}async function Zo(e,n){await Ke(e,n)}async function Go(e,n){let t=Le(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return e.redirectURL&&(r.redirectUri=e.redirectURL),t==="development"&&(r.deliveryUrl=ke({deliveryUrl:n.deliveryUrl})),_({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:In})}async function Ut(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e,multiTenancy:n.multiTenancy};await qo(t,n.tenantId);let r=await jn(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 Go(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function Kn(e,n){let t=w(e),r=H(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r,multiTenancy:t.multiTenancy,internalConfig:t};await Zo(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,u=await jn(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(u.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 Go(r,{tenantId:n.tenantId,plugins:u,deliveryUrl:n.deliveryUrl})}function Jo(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function la(e,n){return n&&!n.has(e.id)?!1:R(e)!==null}async function zo(e,n,t={}){let r=w(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,s=await ln(r,o,{pluginIds:t.pluginIds}),a=new Map(s.map(l=>[l.plugin,l])),u=r.plugins.filter(l=>la(l,i)).map(l=>{let c=R(l),p=a.get(l.id);return p?{plugin:l.id,providerName:ye(l.id),authKind:Jo(c),status:p.status,connected:p.connected,fields:p.fields.map(d=>({name:d.name,level:d.level,required:d.required,configured:d.configured})),missingRequiredFields:p.missingRequiredFields}:{plugin:l.id,providerName:ye(l.id),authKind:Jo(c),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:u}}async function Vo(e,n){let t=H(e);return $({hub:t,path:`/projects/${encodeURIComponent(n.projectId)}/connections`,notFoundMessage:"Hub REST API not found at /projects/:id/connections. Check HUB_API_URL and ensure the Hub API is deployed.",parseResponse:Sn})}function qe(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}var G=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function da(e){let n=e.oauthConfig;if(!n)throw new G("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Bt(e,n){let t=w(e,()=>new G("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new G("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new G("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=Un(n,t.kek);if(!o)throw new G("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=U(t,i,d=>new G("plugin_not_found",d)),u=da(a),c=await O({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!c)throw new G("client_id_not_configured",`client_id not configured for '${i}'`);let p=_e({oauthConfig:u,clientId:c,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:u.providerName,oauthUrl:p,state:n}}import{AsyncLocalStorage as ga}from"async_hooks";import{randomBytes as fa}from"crypto";import{v4 as ya}from"uuid";async function qn(e,n){let t=Le(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=ke({deliveryUrl:n.deliveryUrl})),_({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:_n})}function Zn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Lt="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 $t(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Yo(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Nt(e){return Zn(e)}async function Wt(e,n){if($t(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Yo(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await qn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:pa(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function pa(e){try{return JSON.parse(e)}catch{return e}}async function Gn(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Wt(e,n);return{...n,approvalUrl:r}}async function jt(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:u,tenantId:l,expiresAt:c,operationPath:p}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:u});let g=await Wt({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(u),tenant_id:l,expires_at:c});return $t(t)?g?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:g}):Nt(g):Lt:r?g?Nt(g):`Action '${p}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Lt}var Ze=class extends Error{constructor(n){super(n),Object.setPrototypeOf(this,new.target.prototype),this.name="PermissionRequiredError"}};var Xo=new ga,Jn=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 Kt(e){return Xo.run(!0,e)}function ei(){return Xo.getStore()===!0}function qt(e,n){if(ei()&&n!=="read")throw new Jn(e,n)}var ma={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 ha(e,n,t){return t!==void 0?t:ma[n][e]}function Zt(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 ni(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 Qo(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 ti(e){let n=ha(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,y=a.id;return{result:"allow",onComplete:async()=>{await f.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",y).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
|
|
12
12
|
Action: ${r}`,`
|
|
13
13
|
Permission ID: ${a.id}`,`
|
|
14
|
-
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Qo(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let u=
|
|
14
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Qo(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let u=ya(),l=fa(32).toString("hex"),c=e.timeoutMs??600*1e3,p=new Date(Date.now()+c).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:u,created_at:new Date,updated_at:new Date,token:l,plugin:e.pluginId,endpoint:e.endpointPath,args:o,tenant_id:s,status:"pending",expires_at:p}).execute(),console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval required.`,`
|
|
15
15
|
Action: ${r}`,`
|
|
16
16
|
Permission ID: ${u}`,`
|
|
17
17
|
Permission token: ${l}`,`
|
|
18
18
|
Expires at: ${p}`,`
|
|
19
|
-
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Qo(e.db,u,c):{result:"blocked",reason:"pending",id:u,token:l,expiresAt:p}}var I=class extends Error{status;code;extra;constructor(n,t,r,o={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=o}};function M(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function ri(e){let n={error:e.code,message:e.message,...e.extra};return M(e.status,n)}function Te(e){return new I(404,"not_found",e)}function de(e,n={}){return new I(400,"bad_request",e,n)}function oi(e,n){return U(e,n,t=>Te(t))}async function ii(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=O({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=F[t].integration,i=r,s;try{s=await Promise.all(o.map(l=>i[`get_${l}`]()))}catch{s=o.map(()=>null)}let a=o.filter((l,c)=>s[c]==null),u;return t==="oauth_2"?u=!a.includes("client_id")&&!a.includes("client_secret"):u=a.length===0,{configured:u,missingFields:a}}async function si(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await ii(e,n);return{id:e.id,authType:t,configured:o,missingFields:i,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function zn(){return{ok:!0}}async function Ge(e){return Promise.all(e.plugins.map(n=>si(n,e)))}async function Vn(e,n){let t=oi(e,n);return si(t,e)}async function ha(e,n){return e.database?(await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.id as accountId","a.dek as dek","i.name as integrationName"]).where("a.tenant_id","=",n).execute()).map(r=>({integrationName:r.integrationName,hasCredentials:!!r.dek})):[]}async function ai(e,n){let t=await ha(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Je(e){let n=new Map;if(n.set("default",{id:"default",accounts:[],connectedPlugins:[]}),e.database){let t=await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id","a.dek as dek","i.name as integrationName"]).execute();for(let r of t){let o=r.tenant_id;if(!o)continue;let i=n.get(o);i||(i={id:o,accounts:[],connectedPlugins:[]},n.set(o,i));let s=!!r.dek;i.accounts.push({integrationName:r.integrationName,hasCredentials:s}),s&&i.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function Yn(e,n){if(!n)throw de("Tenant id must be a non-empty string");return ai(e,n)}async function Qn(e,n){let t=n?.id?.trim();if(!t)throw de("Tenant id is required",{missingFields:["id"]});return ai(e,t)}async function Xn(e,n){let t=n?.trim()||"default",r={},o=await ln(e,t);for(let i of o)r[i.plugin]=Fn(i);for(let i of e.plugins)i.id in r||(!i.options?.authType||!e.database||!e.kek?r[i.id]="missing_credentials":r[i.id]="not_connected");return r}async function Gt(e,n){if(!e.database)throw Te(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw Te(`Permission '${n}' not found`);return Gn(e,t)}function ka(e){if(!e.oauthConfig)throw de(`Plugin '${e.id}' has no oauthConfig`)}function ba(e){if(!e.manual)throw new I(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Jt(e){let n=ba(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new I(500,"connect_not_configured","Manual connect requires manual.baseUrl and manual.redirectUri. Use hub for hosted connect, or set both URLs for manual OAuth.");return n}function wa(e){let n=!!e.hub,t=qe(e.manual);if(!n&&!t)throw new I(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function ui(e){if(!e.database||!e.kek)throw new I(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Ca(e,n){let t=n?.plugin?.trim();if(!t)throw de("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=oi(e,t);ka(o);let i=Jt(e);ui(e);let s=await ii(o,e);if(!s.configured)throw new I(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=$e(Ce(t,r),e.kek),u;try{u=new URL(i.baseUrl)}catch{throw new I(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return u.searchParams.set("state",a),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+Mt).toISOString()}}async function Ta(e,n,t){ui(n);let o={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let s=t.providerName?.trim();s&&(o.providerName=s);let a=await Kn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function et(e,n,t){return wa(n),n.hub?Ta(e,n,t):Ca(n,t)}async function nt(e,n,t){if(n.hub&&!qe(n.manual))throw new I(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw de("state is required",{missingFields:["state"]});Jt(n);try{return await Bt(e,r)}catch(o){if(o instanceof G)switch(o.code){case"invalid_state":throw de("Invalid or expired state");case"client_id_not_configured":throw new I(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new I(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function tt(e,n,t){if(n.hub&&!qe(n.manual))throw new I(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),o=t?.state?.trim(),i=[];if(r||i.push("code"),o||i.push("state"),i.length)throw de("Missing required fields",{missingFields:i});let s=Jt(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw de("Invalid or expired state");case"credentials_not_configured":throw new I(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new I(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function zt(e,n){if(!e.database)throw Te("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw Te("Permission not found");return Gn(e,t)}async function ci(e,n){return"id"in n?Gt(e,n.id):zt(e,n.token)}import{createCipheriv as Sa,createDecipheriv as ep,randomBytes as gi,scryptSync as _a}from"crypto";import{createHmac as Vt,randomUUID as va,timingSafeEqual as di}from"crypto";function Yt(e){return e.run??null}function Qt(e){return e.probe??null}function pi(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function rt(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=Vt("sha256",e.signingSecret.trim()).update(n).digest("hex");return{body:n,headers:{"content-type":"application/json","x-corsair-signature":`sha256=${r}`,"x-corsair-timestamp":t,"x-corsair-project":e.projectId,"x-corsair-nonce":va()}}}function Xt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=pi(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Re)return!1;let i=Vt("sha256",n).update(e.body).digest("hex");try{return di(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function ze(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=pi(e.signatureHeader);if(!t)return{ok:!1,error:"Invalid tunnel signature"};let r=Number(e.timestampHeader);if(!Number.isFinite(r))return{ok:!1,error:"Invalid or missing tunnel timestamp"};if(Math.abs(Date.now()-r*1e3)>Re)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=Vt("sha256",n).update(e.body).digest("hex");try{if(!di(Buffer.from(i,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function Ve(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function ot(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function it(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function fn(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function er(e){return fn(Ve(e))}async function nr(e){let n=await ut({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=Ve(n.body),r=ot({httpOk:n.ok,status:n.status,body:t}),o=fn(t);if(!r||!o)throw new Error(at({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function st(e){return it(Ve(e))}function Pa(e){let n=e;for(;n;){if(n instanceof Error){let t=n.code;if(typeof t=="string")return t;n=n.cause;continue}if(typeof n=="object"&&n!==null&&"code"in n){let t=n.code;if(typeof t=="string")return t}break}}function li(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var Aa="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",xa="Check the delivery URL configured for this environment.";function Ra(e){return`${e.ack.error?`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`:`App rejected the signed delivery (HTTP ${e.status} from ${e.deliveryUrl})`}. ${Aa}`}function Ia(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${xa}`}function yn(e,n){let t=Pa(n),r=n instanceof Error?n.message:"Delivery request failed",o;switch(t){case"ECONNREFUSED":o="connection refused \u2014 nothing accepted a TCP connection on that host and port";break;case"ENOTFOUND":o="host not found \u2014 DNS could not resolve the hostname";break;case"ETIMEDOUT":case"UND_ERR_CONNECT_TIMEOUT":o="connection timed out before the app responded";break;case"ECONNRESET":o="connection reset while talking to the app";break;case"CERT_HAS_EXPIRED":case"UNABLE_TO_VERIFY_LEAF_SIGNATURE":case"DEPTH_ZERO_SELF_SIGNED_CERT":o=`TLS certificate error (${t})`;break;default:o=r==="fetch failed"&&t?`${r} (${t})`:r}return[`Could not reach ${e}`,o].join(". ")}function at(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:yn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Ra(e);if(e.status===404)return Ia(e);if(e.ack.error)return`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`;if(e.status>=500){let t=e.body.trim();return t?`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl}): ${li(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${li(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function ut(e){let{body:n,headers:t}=rt(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:yn(e.deliveryUrl,r)}}}var Ea="aes-256-gcm",Da=12,Oa=16,Ma=16,Ha=32;function Fa(e,n){return _a(e.trim(),n,Ha)}function tr(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=gi(Ma),o=Fa(t,r),i=gi(Da),s=Sa(Ea,o,i,{authTagLength:Oa}),a=JSON.stringify(e),u=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),u.toString("base64")].join(":")}var Ua=["invalid corsair instance","a database must be configured to sync connections from the app","a database must be configured on the corsair instance","signing secret is required to encrypt sync manifest"];function rr(e){if(e instanceof ro)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!Ua.some(t=>n.includes(t))}function Ba(e){if(!e)return[];let n=R(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!we(r)):[]}async function mn(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await Wn(e,{silent:!0});let[r,o]=await Promise.all([Je(t),Ge(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=Ba(t.plugins.find(u=>u.id===s.id));return{id:s.id,authType:s.authType,configured:s.configured,missingFields:s.missingFields,...a.length>0?{integrationCredentialFields:a}:{}}}),syncedAt:new Date().toISOString()};return tr(i,n)}async function ct(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=w(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 La(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 La(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-OFZ2ICYL.js"),{postHubConnectSession:i}=await import("./connect-XL5IRCO3.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 u=a.find(l=>l.setupError);if(u)throw new Error(u.setupError??`Could not prepare connect link for ${u.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}var ne=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function lt(e,n){let t=w(e,()=>new ne("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ne("no_database","Database not configured");let r=U(t,n.plugin,c=>new ne("plugin_not_found",c)),o=R(r);if(!o)throw new ne("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new ne("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Ke(e,n.tenantId);let i=new Set(vn(r,o)),a=r.authConfig?.[o]?.account??[],u=D({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new ne("invalid_credentials",`Unknown credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new ne("invalid_credentials",`Cannot set credential field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new ne("invalid_credentials","Provide at least one credential field to save");return await le(e,{plugin:r,tenantId:n.tenantId}).catch(()=>{}),{plugin:n.plugin,tenantId:n.tenantId}}var te=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function or(e,n){let t=w(e,()=>new te("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new te("no_database","Database not configured");let r=U(t,n.plugin,c=>new te("plugin_not_found",c)),o=R(r);if(!o)throw new te("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await jo(e);let i=new Set(so(r,o)),a=r.authConfig?.[o]?.integration??[],u=O({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new te("invalid_credentials",`Unknown integration credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new te("invalid_credentials",`Cannot set integration field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new te("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var dt=new Map;function Na(e){for(let[n,t]of dt)t<=e&&dt.delete(n)}function pt(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return Na(r),dt.has(t)?{ok:!1,error:"Delivery request already consumed"}:(dt.set(t,r+n),{ok:!0})}var ve=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Ye(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a}=n;if(!o.trim())throw new ve("no_access_token","Managed OAuth delivery missing access_token");let u=w(e,()=>new ve("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new ve("no_database","No database configured on corsair instance");let l=U(u,t,p=>new ve("plugin_not_found",p));await Ke(e,r);let c=D({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await c.set_access_token(o),i&&await c.set_refresh_token(i),s&&await c.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await c.set_scope(a),await le(e,{plugin:l,tenantId:r}).catch(()=>{});try{let p=await Bn(u.plugins,t,{access_token:o,refresh_token:i,scope:a});if(p){try{let d=l.authConfig?.managed?.account??[];await je({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:p,authType:"managed",extraAccountFields:d})}catch(d){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,d)}u.hub&&We(u.hub,{plugin:t,tenantId:r,link:p,authType:"managed"})}}catch(p){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,p)}return{plugin:t,tenantId:r}}function $a(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function fi(e,n,t=[]){for(let[r,o]of Object.entries(e))if($a(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=fi(o,n,[...t,r]);if(i)return i}return null}function Wa(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function ja(e){let n=e["x-goog-resource-uri"],t=e["x-goog-channel-id"];if(!n||!t)return null;let r={resourceId:e["x-goog-resource-id"]||"",resourceState:e["x-goog-resource-state"]||"",resourceUri:n,channelId:t,channelExpiration:e["x-goog-channel-expiration"]||""};return n.includes("/drive/")&&(r.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(r)).toString("base64"),messageId:e["x-goog-message-number"]||""}}}async function yi(e,n,t,r,o){let i=Wa(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=ja(i)||s);let u={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",c=e.withTenant?e.withTenant(l):e,p=o?.plugin,d=p?[p]:Pn;for(let g of d){let f=c[g];if(!f||!f.webhooks||!p&&f.pluginWebhookMatcher&&!f.pluginWebhookMatcher(u))continue;let y=fi(f.webhooks,u);if(!y)continue;let m=y.path.join("."),h={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let b=await y.webhook.handler(h),C=!!Object.keys(b.returnToSender||{})?.length;return{plugin:g,action:m,body:s,response:C?{...b?.returnToSender,success:!0}:{success:!0},...b.responseHeaders&&{responseHeaders:b.responseHeaders}}}catch(b){return console.error(`Error executing webhook handler for ${g}.${m}:`,b),{plugin:g,action:m,body:s,response:{success:!1,error:b instanceof Error?b.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHash as Ka}from"crypto";import*as Ee from"vm";var mi="__corsairFailedStep",qa=3e4,ir=class{constructor(n,t){this.wakeAt=n;this.stepName=t}__corsairSleep=!0};function hi(e){return typeof e=="object"&&e!==null&&e.__corsairSleep===!0}function ki(e,n){return`st_${Ka("sha256").update(`${n} ${e}`).digest("hex").slice(0,16)}`}function gt(e){if(e instanceof Error)return e.message;if(e!==null&&typeof e=="object"&&"message"in e){let n=e.message;if(typeof n=="string")return n}return String(e)}var bi=new Set(["constructor","prototype","__proto__"]);function pe(e,n){if(e===null)return null;let t=typeof e;return t==="function"?Ga(e,n):t==="object"?Za(e):e}function Za(e){return new Proxy(e,{get(n,t){if(!bi.has(t))return pe(Reflect.get(n,t,n),n)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function Ga(e,n){return new Proxy(e,{apply:(t,r,o)=>Ja(Reflect.apply(t,n,o)),construct(){throw new Error("Workflow code may not construct host objects")},get(t,r){if(!bi.has(r))return pe(Reflect.get(t,r,t),t)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function Ja(e){return e!==null&&typeof e=="object"&&typeof e.then=="function"?Promise.resolve(e).then(n=>pe(n,void 0),n=>{throw pe(n,void 0)}):pe(e,void 0)}function za(e){let n=Object.create(null),t=Ee.createContext(n,{name:"corsair-workflow",codeGeneration:{strings:!1,wasm:!1}}),o=Ee.runInContext("(s) => JSON.parse(s)",t,{filename:"corsair:sandbox:json"})(JSON.stringify(e.payload??null)),s=Ee.runInContext(`(function (hostRun, hostSleep) {
|
|
19
|
+
Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Qo(e.db,u,c):{result:"blocked",reason:"pending",id:u,token:l,expiresAt:p}}var I=class extends Error{status;code;extra;constructor(n,t,r,o={}){super(r??t),this.name="ManagementApiError",this.status=n,this.code=t,this.extra=o}};function M(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function ri(e){let n={error:e.code,message:e.message,...e.extra};return M(e.status,n)}function Pe(e){return new I(404,"not_found",e)}function de(e,n={}){return new I(400,"bad_request",e,n)}function oi(e,n){return U(e,n,t=>Pe(t))}async function ii(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=O({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=F[t].integration,i=r,s;try{s=await Promise.all(o.map(l=>i[`get_${l}`]()))}catch{s=o.map(()=>null)}let a=o.filter((l,c)=>s[c]==null),u;return t==="oauth_2"?u=!a.includes("client_id")&&!a.includes("client_secret"):u=a.length===0,{configured:u,missingFields:a}}async function si(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await ii(e,n);return{id:e.id,authType:t,configured:o,missingFields:i,oauth:r?{providerName:r.providerName,scopes:r.scopes,requiresRegisteredRedirect:!!r.requiresRegisteredRedirect}:null}}function zn(){return{ok:!0}}async function Ge(e){return Promise.all(e.plugins.map(n=>si(n,e)))}async function Vn(e,n){let t=oi(e,n);return si(t,e)}async function ka(e,n){return e.database?(await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.id as accountId","a.dek as dek","i.name as integrationName"]).where("a.tenant_id","=",n).execute()).map(r=>({integrationName:r.integrationName,hasCredentials:!!r.dek})):[]}async function ai(e,n){let t=await ka(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Je(e){let n=new Map;if(n.set("default",{id:"default",accounts:[],connectedPlugins:[]}),e.database){let t=await e.database.db.selectFrom("corsair_accounts as a").innerJoin("corsair_integrations as i","i.id","a.integration_id").select(["a.tenant_id","a.dek as dek","i.name as integrationName"]).execute();for(let r of t){let o=r.tenant_id;if(!o)continue;let i=n.get(o);i||(i={id:o,accounts:[],connectedPlugins:[]},n.set(o,i));let s=!!r.dek;i.accounts.push({integrationName:r.integrationName,hasCredentials:s}),s&&i.connectedPlugins.push(r.integrationName)}}return[...n.values()]}async function Yn(e,n){if(!n)throw de("Tenant id must be a non-empty string");return ai(e,n)}async function Qn(e,n){let t=n?.id?.trim();if(!t)throw de("Tenant id is required",{missingFields:["id"]});return ai(e,t)}async function Xn(e,n){let t=n?.trim()||"default",r={},o=await ln(e,t);for(let i of o)r[i.plugin]=Fn(i);for(let i of e.plugins)i.id in r||(!i.options?.authType||!e.database||!e.kek?r[i.id]="missing_credentials":r[i.id]="not_connected");return r}async function Gt(e,n){if(!e.database)throw Pe(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw Pe(`Permission '${n}' not found`);return Gn(e,t)}function ba(e){if(!e.oauthConfig)throw de(`Plugin '${e.id}' has no oauthConfig`)}function wa(e){if(!e.manual)throw new I(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Jt(e){let n=wa(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new I(500,"connect_not_configured","Manual connect requires manual.baseUrl and manual.redirectUri. Use hub for hosted connect, or set both URLs for manual OAuth.");return n}function Ca(e){let n=!!e.hub,t=qe(e.manual);if(!n&&!t)throw new I(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function ui(e){if(!e.database||!e.kek)throw new I(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Pa(e,n){let t=n?.plugin?.trim();if(!t)throw de("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=oi(e,t);ba(o);let i=Jt(e);ui(e);let s=await ii(o,e);if(!s.configured)throw new I(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=$e(Ce(t,r),e.kek),u;try{u=new URL(i.baseUrl)}catch{throw new I(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return u.searchParams.set("state",a),{connectUrl:u.toString(),expiresAt:new Date(Date.now()+Mt).toISOString()}}async function Ta(e,n,t){ui(n);let o={tenantId:t.tenantId?.trim()||"default",oauthMode:t.oauthMode},i=t.plugin?.trim();i&&(o.plugin=i);let s=t.providerName?.trim();s&&(o.providerName=s);let a=await Kn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function et(e,n,t){return Ca(n),n.hub?Ta(e,n,t):Pa(n,t)}async function nt(e,n,t){if(n.hub&&!qe(n.manual))throw new I(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw de("state is required",{missingFields:["state"]});Jt(n);try{return await Bt(e,r)}catch(o){if(o instanceof G)switch(o.code){case"invalid_state":throw de("Invalid or expired state");case"client_id_not_configured":throw new I(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new I(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function tt(e,n,t){if(n.hub&&!qe(n.manual))throw new I(400,"hub_mode","oauthCallback is not used with hub config. Hub delivers tokens to your deliveryUrl.");let r=t?.code?.trim(),o=t?.state?.trim(),i=[];if(r||i.push("code"),o||i.push("state"),i.length)throw de("Missing required fields",{missingFields:i});let s=Jt(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri,callbackParams:t.callbackParams})}catch(u){if(u instanceof Error&&u.name==="OAuthCallbackError")switch(u.code){case"invalid_state":throw de("Invalid or expired state");case"credentials_not_configured":throw new I(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new I(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function zt(e,n){if(!e.database)throw Pe("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw Pe("Permission not found");return Gn(e,t)}async function ci(e,n){return"id"in n?Gt(e,n.id):zt(e,n.token)}import{createCipheriv as _a,createDecipheriv as np,randomBytes as gi,scryptSync as Ea}from"crypto";import{createHmac as Vt,randomUUID as va,timingSafeEqual as di}from"crypto";function Yt(e){return e.run??null}function Qt(e){return e.probe??null}function pi(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function rt(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=Vt("sha256",e.signingSecret.trim()).update(n).digest("hex");return{body:n,headers:{"content-type":"application/json","x-corsair-signature":`sha256=${r}`,"x-corsair-timestamp":t,"x-corsair-project":e.projectId,"x-corsair-nonce":va()}}}function Xt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=pi(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Re)return!1;let i=Vt("sha256",n).update(e.body).digest("hex");try{return di(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function ze(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=pi(e.signatureHeader);if(!t)return{ok:!1,error:"Invalid tunnel signature"};let r=Number(e.timestampHeader);if(!Number.isFinite(r))return{ok:!1,error:"Invalid or missing tunnel timestamp"};if(Math.abs(Date.now()-r*1e3)>Re)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=Vt("sha256",n).update(e.body).digest("hex");try{if(!di(Buffer.from(i,"utf8"),Buffer.from(t,"utf8")))return{ok:!1,error:"Invalid tunnel signature"}}catch{return{ok:!1,error:"Invalid tunnel signature"}}return{ok:!0}}function Ve(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function ot(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function it(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function fn(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function er(e){return fn(Ve(e))}async function nr(e){let n=await ut({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=Ve(n.body),r=ot({httpOk:n.ok,status:n.status,body:t}),o=fn(t);if(!r||!o)throw new Error(at({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function st(e){return it(Ve(e))}function Aa(e){let n=e;for(;n;){if(n instanceof Error){let t=n.code;if(typeof t=="string")return t;n=n.cause;continue}if(typeof n=="object"&&n!==null&&"code"in n){let t=n.code;if(typeof t=="string")return t}break}}function li(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var xa="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",Ra="Check the delivery URL configured for this environment.";function Ia(e){return`${e.ack.error?`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`:`App rejected the signed delivery (HTTP ${e.status} from ${e.deliveryUrl})`}. ${xa}`}function Sa(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${Ra}`}function yn(e,n){let t=Aa(n),r=n instanceof Error?n.message:"Delivery request failed",o;switch(t){case"ECONNREFUSED":o="connection refused \u2014 nothing accepted a TCP connection on that host and port";break;case"ENOTFOUND":o="host not found \u2014 DNS could not resolve the hostname";break;case"ETIMEDOUT":case"UND_ERR_CONNECT_TIMEOUT":o="connection timed out before the app responded";break;case"ECONNRESET":o="connection reset while talking to the app";break;case"CERT_HAS_EXPIRED":case"UNABLE_TO_VERIFY_LEAF_SIGNATURE":case"DEPTH_ZERO_SELF_SIGNED_CERT":o=`TLS certificate error (${t})`;break;default:o=r==="fetch failed"&&t?`${r} (${t})`:r}return[`Could not reach ${e}`,o].join(". ")}function at(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:yn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Ia(e);if(e.status===404)return Sa(e);if(e.ack.error)return`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`;if(e.status>=500){let t=e.body.trim();return t?`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl}): ${li(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${li(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function ut(e){let{body:n,headers:t}=rt(e);try{let r=await fetch(e.deliveryUrl,{method:"POST",headers:t,body:n}),o=await r.text();return{ok:r.ok,status:r.status,body:o}}catch(r){return{ok:!1,status:0,body:yn(e.deliveryUrl,r)}}}var Da="aes-256-gcm",Oa=12,Ma=16,Ha=16,Fa=32;function Ua(e,n){return Ea(e.trim(),n,Fa)}function tr(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=gi(Ha),o=Ua(t,r),i=gi(Oa),s=_a(Da,o,i,{authTagLength:Ma}),a=JSON.stringify(e),u=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),u.toString("base64")].join(":")}var Ba=["invalid corsair instance","a database must be configured to sync connections from the app","a database must be configured on the corsair instance","signing secret is required to encrypt sync manifest"];function rr(e){if(e instanceof ro)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!Ba.some(t=>n.includes(t))}function La(e){if(!e)return[];let n=R(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!we(r)):[]}async function mn(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await Wn(e,{silent:!0});let[r,o]=await Promise.all([Je(t),Ge(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=La(t.plugins.find(u=>u.id===s.id));return{id:s.id,authType:s.authType,configured:s.configured,missingFields:s.missingFields,...a.length>0?{integrationCredentialFields:a}:{}}}),syncedAt:new Date().toISOString()};return tr(i,n)}async function ct(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=w(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 Na(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 Na(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-KQHTBADC.js"),{postHubConnectSession:i}=await import("./connect-HQAFXDQS.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 u=a.find(l=>l.setupError);if(u)throw new Error(u.setupError??`Could not prepare connect link for ${u.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}var ne=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function lt(e,n){let t=w(e,()=>new ne("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ne("no_database","Database not configured");let r=U(t,n.plugin,c=>new ne("plugin_not_found",c)),o=R(r);if(!o)throw new ne("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new ne("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Ke(e,n.tenantId);let i=new Set(Tn(r,o)),a=r.authConfig?.[o]?.account??[],u=D({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new ne("invalid_credentials",`Unknown credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new ne("invalid_credentials",`Cannot set credential field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new ne("invalid_credentials","Provide at least one credential field to save");return await le(e,{plugin:r,tenantId:n.tenantId}).catch(()=>{}),{plugin:n.plugin,tenantId:n.tenantId}}var te=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function or(e,n){let t=w(e,()=>new te("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new te("no_database","Database not configured");let r=U(t,n.plugin,c=>new te("plugin_not_found",c)),o=R(r);if(!o)throw new te("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await jo(e);let i=new Set(so(r,o)),a=r.authConfig?.[o]?.integration??[],u=O({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[c,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(c))throw new te("invalid_credentials",`Unknown integration credential field '${c}' for plugin '${n.plugin}'`);let d=N(u,`set_${c}`);if(!d)throw new te("invalid_credentials",`Cannot set integration field '${c}' for plugin '${n.plugin}'`);await d(p.trim()),l+=1}if(l===0)throw new te("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var dt=new Map;function $a(e){for(let[n,t]of dt)t<=e&&dt.delete(n)}function pt(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return $a(r),dt.has(t)?{ok:!1,error:"Delivery request already consumed"}:(dt.set(t,r+n),{ok:!0})}var Te=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Ye(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a}=n;if(!o.trim())throw new Te("no_access_token","Managed OAuth delivery missing access_token");let u=w(e,()=>new Te("invalid_corsair_instance","Invalid corsair instance"));if(!u.database)throw new Te("no_database","No database configured on corsair instance");let l=U(u,t,p=>new Te("plugin_not_found",p));await Ke(e,r);let c=D({authType:"managed",integrationName:t,tenantId:r,kek:u.kek,database:u.database});await c.set_access_token(o),i&&await c.set_refresh_token(i),s&&await c.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await c.set_scope(a),await le(e,{plugin:l,tenantId:r}).catch(()=>{});try{let p=await Bn(u.plugins,t,{access_token:o,refresh_token:i,scope:a});if(p){try{let d=l.authConfig?.managed?.account??[];await je({database:u.database,kek:u.kek,pluginId:t,tenantId:r,link:p,authType:"managed",extraAccountFields:d})}catch(d){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,d)}u.hub&&We(u.hub,{plugin:t,tenantId:r,link:p,authType:"managed"})}}catch(p){console.warn(`[corsair:managed-oauth] Failed to resolve webhook tenant link for '${t}' tenant '${r}':`,p)}return{plugin:t,tenantId:r}}function Wa(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function fi(e,n,t=[]){for(let[r,o]of Object.entries(e))if(Wa(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=fi(o,n,[...t,r]);if(i)return i}return null}function ja(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Ka(e){let n=e["x-goog-resource-uri"],t=e["x-goog-channel-id"];if(!n||!t)return null;let r={resourceId:e["x-goog-resource-id"]||"",resourceState:e["x-goog-resource-state"]||"",resourceUri:n,channelId:t,channelExpiration:e["x-goog-channel-expiration"]||""};return n.includes("/drive/")&&(r.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(r)).toString("base64"),messageId:e["x-goog-message-number"]||""}}}async function yi(e,n,t,r,o){let i=ja(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=Ka(i)||s);let u={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",c=e.withTenant?e.withTenant(l):e,p=o?.plugin,d=p?[p]:vn;for(let g of d){let f=c[g];if(!f||!f.webhooks||!p&&f.pluginWebhookMatcher&&!f.pluginWebhookMatcher(u))continue;let y=fi(f.webhooks,u);if(!y)continue;let h=y.path.join("."),m={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let b=await y.webhook.handler(m),C=!!Object.keys(b.returnToSender||{})?.length;return{plugin:g,action:h,body:s,response:C?{...b?.returnToSender,success:!0}:{success:!0},...b.responseHeaders&&{responseHeaders:b.responseHeaders}}}catch(b){return console.error(`Error executing webhook handler for ${g}.${h}:`,b),{plugin:g,action:h,body:s,response:{success:!1,error:b instanceof Error?b.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}import{createHash as qa}from"crypto";import*as Ee from"vm";var mi="__corsairFailedStep",Za=3e4,ir=class{constructor(n,t){this.wakeAt=n;this.stepName=t}__corsairSleep=!0};function hi(e){return typeof e=="object"&&e!==null&&e.__corsairSleep===!0}function ki(e,n){return`st_${qa("sha256").update(`${n} ${e}`).digest("hex").slice(0,16)}`}function gt(e){if(e instanceof Error)return e.message;if(e!==null&&typeof e=="object"&&"message"in e){let n=e.message;if(typeof n=="string")return n}return String(e)}var bi=new Set(["constructor","prototype","__proto__"]);function pe(e,n){if(e===null)return null;let t=typeof e;return t==="function"?Ja(e,n):t==="object"?Ga(e):e}function Ga(e){return new Proxy(e,{get(n,t){if(!bi.has(t))return pe(Reflect.get(n,t,n),n)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function Ja(e,n){return new Proxy(e,{apply:(t,r,o)=>za(Reflect.apply(t,n,o)),construct(){throw new Error("Workflow code may not construct host objects")},get(t,r){if(!bi.has(r))return pe(Reflect.get(t,r,t),t)},getPrototypeOf:()=>null,setPrototypeOf:()=>!1,defineProperty:()=>!1,set:()=>!1,deleteProperty:()=>!1})}function za(e){return e!==null&&typeof e=="object"&&typeof e.then=="function"?Promise.resolve(e).then(n=>pe(n,void 0),n=>{throw pe(n,void 0)}):pe(e,void 0)}function Va(e){let n=Object.create(null),t=Ee.createContext(n,{name:"corsair-workflow",codeGeneration:{strings:!1,wasm:!1}}),o=Ee.runInContext("(s) => JSON.parse(s)",t,{filename:"corsair:sandbox:json"})(JSON.stringify(e.payload??null)),s=Ee.runInContext(`(function (hostRun, hostSleep) {
|
|
20
20
|
const step = function step(name, fn) { return hostRun(name, fn); };
|
|
21
21
|
step.sleep = function sleep(name, ms) { return hostSleep(name, ms); };
|
|
22
22
|
return step;
|
|
@@ -39,28 +39,28 @@ ${e.code}
|
|
|
39
39
|
throw new Error('Workflow code must export a \`main\` function');
|
|
40
40
|
}
|
|
41
41
|
return main(__corsair, __payload, __step);
|
|
42
|
-
})()`,t,{filename:"corsair:workflow",timeout:e.timeoutMs});l.catch(()=>{});let c,p=new Promise((d,g)=>{c=setTimeout(()=>g(new Error(`Workflow exceeded ${e.timeoutMs}ms time limit`)),e.timeoutMs)});return Promise.race([l,p]).finally(()=>clearTimeout(c))}async function sr(e){let n=e.memoizedSteps??{},t=[],r=0,o=null,i=(async(s,a)=>{if(o)throw o;let u=r++,l=ki(s,u);if(Object.hasOwn(n,l))return pe(n[l].output,void 0);try{let c=await a();return t.push({stepId:l,name:s,seq:u,status:"completed",output:c}),c}catch(c){if(hi(c))throw c;let p=gt(c);t.push({stepId:l,name:s,seq:u,status:"failed",error:p});let d=new Error(p);throw d[mi]=s,d}});i.sleep=async(s,a)=>{if(o)throw o;let u=r++,l=ki(s,u);if(Object.hasOwn(n,l))return;t.push({stepId:l,name:s,seq:u,status:"completed",output:null});let c=Number.isFinite(a)?Math.max(0,a):0;throw o=new ir(Date.now()+c,s),o};try{await
|
|
42
|
+
})()`,t,{filename:"corsair:workflow",timeout:e.timeoutMs});l.catch(()=>{});let c,p=new Promise((d,g)=>{c=setTimeout(()=>g(new Error(`Workflow exceeded ${e.timeoutMs}ms time limit`)),e.timeoutMs)});return Promise.race([l,p]).finally(()=>clearTimeout(c))}async function sr(e){let n=e.memoizedSteps??{},t=[],r=0,o=null,i=(async(s,a)=>{if(o)throw o;let u=r++,l=ki(s,u);if(Object.hasOwn(n,l))return pe(n[l].output,void 0);try{let c=await a();return t.push({stepId:l,name:s,seq:u,status:"completed",output:c}),c}catch(c){if(hi(c))throw c;let p=gt(c);t.push({stepId:l,name:s,seq:u,status:"failed",error:p});let d=new Error(p);throw d[mi]=s,d}});i.sleep=async(s,a)=>{if(o)throw o;let u=r++,l=ki(s,u);if(Object.hasOwn(n,l))return;t.push({stepId:l,name:s,seq:u,status:"completed",output:null});let c=Number.isFinite(a)?Math.max(0,a):0;throw o=new ir(Date.now()+c,s),o};try{await Va({code:e.code,corsair:e.corsair,payload:e.payload,step:i,timeoutMs:e.timeoutMs??Za});let s=o;return s?{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()}:{status:"completed",steps:t}}catch(s){if(hi(s))return{status:"sleeping",steps:t,sleepUntil:new Date(s.wakeAt).toISOString()};let a=gt(s),u=s!==null&&typeof s=="object"?s[mi]:void 0;return{status:"failed",steps:t,error:{message:a,...u?{failedStep:u}:{}}}}}import*as ft from"vm";var wi=1e4;async function ar(e){let n=Object.create(null),t=ft.createContext(n,{name:"corsair-probe",codeGeneration:{strings:!1,wasm:!1}});n.corsair=pe(e.corsair,void 0);let r=Qa(e.timeoutMs),o=`(async () => {
|
|
43
43
|
const __result = await (async () => {
|
|
44
44
|
${e.code}
|
|
45
45
|
})();
|
|
46
46
|
return JSON.stringify(__result) ?? 'null';
|
|
47
|
-
})()`;try{let i=await Kt(()=>{let s=ft.runInContext(o,t,{filename:"corsair:probe",timeout:r});s.catch(()=>{});let a,u=new Promise((l,c)=>{a=setTimeout(()=>c(new Error(`Probe exceeded ${r}ms time limit`)),r)});return Promise.race([s,u]).finally(()=>clearTimeout(a))});return{status:"ok",value:Va(i)}}catch(i){return{status:"error",error:gt(i)}}}function Va(e){if(typeof e!="string")throw new Error(`Probe returned a non-string result (${typeof e})`);return JSON.parse(e)}function Ya(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?wi:Math.min(e,wi)}function De(e){return e.deliveryMode==="auth.credentials"}function hn(e){return e.deliveryMode==="connections.sync"}function yt(e){return e.deliveryMode==="connect.create_link"}function kn(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function bn(e){return e.deliveryMode==="oauth.tokens"}function mt(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!De(e)&&!hn(e)&&!yt(e)&&!kn(e)&&!bn(e)}function Qa(e){return{status:"ok",connectLink:{connectUrl:e.connectUrl,expiresAt:e.expiresAt},webhookResponse:{status:200,body:{status:"ok",connectUrl:e.connectUrl,expiresAt:e.expiresAt}}}}async function Xa(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await mn(e,n)}}}}}catch(t){return{status:"failed",retryable:rr(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function eu(e,n){try{let t=await ct(e,n);return Qa(t)}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function ur(e,n){if(e instanceof Headers)return e.get(n)??void 0;let t=e[n]??e[n.toLowerCase()];return Array.isArray(t)?t[0]:typeof t=="string"?t:void 0}async function nu(e,n,t){let r=typeof t.tenantId=="string"?t.tenantId:typeof t.query?.tenantId=="string"?t.query.tenantId:void 0;return r||(!n.database||!t.plugin||!t.linkType||!t.externalId?void 0:await Ln({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function tu(e,n,t){let r=await nu(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await yi(e,t.headers,t.body,o,t.plugin?{plugin:t.plugin}:void 0);if(!i.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(i.response&&i.response.success===!1)return{status:"failed",retryable:!1,error:typeof i.response.error=="string"?i.response.error:"Webhook handler failed"};let s=i.response?.returnToSender,a=s&&typeof s=="object"&&typeof s.validationToken=="string"&&Object.keys(s).length===1?s.validationToken:s||(i.response?.data??i.response);return{status:"ok",webhookResponse:{status:i.response?.statusCode??200,body:a,headers:i.responseHeaders}}}async function ru(e,n){return await gn(e,{code:n.code,state:n.state,redirectUri:n.redirectUri,...n.plugin&&n.tenantId?{trusted:!0,plugin:n.plugin,tenantId:n.tenantId}:{}}),{status:"ok"}}async function ou(e,n){return await Ye(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function lr(e,n,t){let r=await cr(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function cr(e,n,t){let r=w(e),o=n.token?.trim();if(!o)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let i=new Date().toISOString(),s=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",o).executeTakeFirst();return s?s.status!=="pending"?{status:"ok"}:s.expires_at<i?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",s.id).execute(),{status:"failed",retryable:!1,error:"Permission has expired"}):(await r.database.db.updateTable("corsair_permissions").set({status:t,updated_at:new Date}).where("id","=",s.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function iu(e,n){try{return await lt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function su(e,n){try{return await or(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}function Ci(e,n){let t=e;return n&&typeof t?.withTenant=="function"?t.withTenant(n):e}async function au(e,n){try{let t=Ci(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",run:await sr({corsair:t,code:n.code,payload:n.trigger?.payload??null,memoizedSteps:n.memoizedSteps})}}}}catch(t){return{status:"failed",retryable:!0,error:t instanceof Error?t.message:"Workflow run failed"}}}async function uu(e,n){try{let t=Ci(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",probe:await ar({corsair:t,code:n.code,timeoutMs:n.timeoutMs})}}}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Probe failed"}}}async function dr(e,n,t={}){let r=w(e),o=ur(n.headers,"x-corsair-signature"),i=ur(n.headers,"x-corsair-timestamp"),s=ur(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=ze({body:n.body,signatureHeader:o,timestampHeader:i,signingSecret:t.signingSecret});if(!u.ok)return{status:"failed",retryable:!1,error:u.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let l=pt(`nonce:${s.trim()}`,Re);if(!l.ok)return{status:"failed",retryable:!1,error:l.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let a;try{a=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}if(a.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status is deprecated; use connections.sync signed delivery instead"};switch(a.type){case"webhook":return tu(e,r,a.payload);case"oauth.callback":return ru(e,a.payload);case"oauth.tokens":return ou(e,a.payload);case"permission.approve":return cr(e,a.payload,"approved");case"permission.deny":return cr(e,a.payload,"denied");case"auth.credentials":return iu(e,a.payload);case"integration.credentials":return su(e,a.payload);case"connect.create_link":return eu(e,a.payload);case"connections.sync":{let u=t.signingSecret?.trim();return u?Xa(e,u):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}case"run":return t.allowWorkflowExecution?au(e,a.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};case"probe":return t.allowWorkflowExecution?uu(e,a.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${String(a.type)}`}}}var pr=new Map;function Ti(e){let n;try{n=H(e)}catch{return}let t=_t(n);t&&pr.get(n.projectApiKey)!==t&&(pr.set(n.projectApiKey,t),_({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{pr.delete(n.projectApiKey)}))}var cu=[".corsair.dev"];function lu(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function du(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:lu(n)?!0:cu.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function vi(e){return!e||!du(e)?null:{"Access-Control-Allow-Origin":e,"Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"content-type, x-corsair-signature, x-corsair-timestamp, x-corsair-project, x-corsair-nonce, access-control-request-private-network","Access-Control-Allow-Private-Network":"true","Access-Control-Max-Age":"0",Vary:"Origin"}}function Pi(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,o]of Object.entries(n))t.set(r,o);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function gr(e,n){let t=new URL(e);return n.error?(t.searchParams.set("error",n.error),t.toString()):n.connectedPlugin?(t.searchParams.set("connected",n.connectedPlugin),t.toString()):(n.status!==void 0&&t.searchParams.set("status",Buffer.from(JSON.stringify(n.status)).toString("base64url")),t.toString())}async function fr(e,n){let t=H(e),o=new URL(n).searchParams.get("d");if(!o)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let i=he(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=pt(`browser:${i.jti}`,me);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(hn(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connections sync delivery requires hubOrigin and requestId for client bridge"}};let a=await mn(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(yt(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connect link delivery requires hubOrigin and requestId for client bridge"}};let a=i.connectLinkPlugins?.filter(Boolean)??[];if(a.length===0)return{type:"json",status:400,body:{error:"Connect link delivery requires at least one plugin in connectLinkPlugins"}};let u=await ct(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:u.connectUrl,expiresAt:u.expiresAt}})}}if(De(i))return i.hubSuccessUrl?i.credentials?(await lt(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:gr(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:gr(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(kn(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await lr(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(bn(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Ye(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!mt(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await gn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let u=a instanceof Error?a.message:"Hub delivery failed";return hn(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:yt(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:De(i)&&i.hubSuccessUrl?{type:"redirect",url:gr(i.hubSuccessUrl,{error:u})}:De(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:i.hubSuccessUrl}}async function yr(e,n){let t=H(e),r=await dr(e,n,{signingSecret:t.signingSecret,allowWorkflowExecution:t.allowWorkflowExecution});if(r.status!=="ok")return{type:"json",status:r.retryable===!1?400:502,body:{error:r.error??"Tunnel processing failed"}};let o=r.webhookResponse;if(!o)return{type:"json",status:200,body:{status:"ok"}};let i=o.status??200,s=o.headers;return o.body&&typeof o.body=="object"&&!(o.body instanceof ArrayBuffer)?{type:"json",status:i,body:o.body,headers:s}:{type:"text",status:i,body:typeof o.body=="string"?o.body:o.body?JSON.stringify(o.body):null,headers:s}}function mr(e){if(e.type==="redirect")return Response.redirect(e.url,302);let n=new Headers;for(let[t,r]of Object.entries(e.headers??{}))typeof r=="string"&&n.set(t,r);return e.type==="json"?Response.json(e.body,{status:e.status,headers:n}):new Response(e.body,{status:e.status,headers:n})}async function hr(e,n){return n.method==="GET"?fr(e,n.url):yr(e,{headers:n.headers,body:n.body??""})}async function kr(e,n){try{let t=await hr(e,n);return mr(t)}catch(t){if(t instanceof se)return Response.json({error:t.message},{status:503});throw t}}async function Oe(e,n){Ti(e);let t=n.method.toUpperCase(),r=vi(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let o=await kr(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return Pi(o,r)}var W=class extends Error{pluginId;authType;constructor(n,t,r){super(r??`[auth-missing:${n}:${t}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n,this.authType=t}};var Ai=300;async function br(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,[a,u,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!l)throw new W(o,"managed");let c=Math.floor(Date.now()/1e3);if(!s&&a&&u&&Number(u)>c+Ai)return{accessToken:a,expiresAt:Number(u),refreshed:!1};if(!l&&a&&!s){let g=u?Number(u):null;if(g===null||g>c+Ai)return{accessToken:a,expiresAt:g??c+3600,refreshed:!1}}let p=await gu(r,o,i),d=p.expires_in?c+p.expires_in:u?Number(u):c+3600;return await t.set_access_token(p.access_token),await t.set_expires_at(String(d)),p.refresh_token&&await t.set_refresh_token(p.refresh_token),p.scope&&await t.set_scope(p.scope),{accessToken:p.access_token,expiresAt:d,refreshed:!0}}function pu(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function gu(e,n,t){try{return await _({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t},parseResponse:En})}catch(r){let o=r instanceof Error?r.message:"";throw pu(o)?new W(n,"managed"):r}}async function xi(e,n){e._refreshAuth=async()=>(await br(n,{forceRefresh:!0})).accessToken}function Ri(e){return{delivery:n=>Oe(e,n),deliveryOptions:n=>Oe(e,n)}}var Ii=1200*1e3;function wr(){return ie()}function Cr(){return Ii}function Tr(e,n){return on(e,n,Ii)}function vr(e,n){return ee(e,n)}function Pr(e){return Ie(e)}var Si=600*1e3;function Ar(){return ie()}function xr(){return Si}function Rr(e,n){return on(e,n,Si)}function Ir(e,n){return ee(e,n)}function Sr(e){return It(e)}function _r(e){return Ie(e)}function Er(){return ie()}function Dr(e,n,t){return An(e,n,Math.floor(t.getTime()/1e3))}function Or(e,n){return ee(e,n)}function Mr(e){return Ie(e)}function _i(e){return e&&typeof e=="object"?e:{}}async function Hr(e,n){return _({hub:e,path:"/threads",body:{tenantId:n.tenantId,message:n.message},parseResponse:t=>t})}async function Fr(e,n){return _({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages`,body:{tenantId:n.tenantId,message:n.message},notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>t})}async function Ur(e,n){return $({hub:e,path:`/threads?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=_i(t).threads;return Array.isArray(r)?r:[]}})}async function ht(e,n){return $({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>{let r=_i(t).messages;return Array.isArray(r)?r:[]}})}function kt(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){let s=t.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${t.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
|
|
47
|
+
})()`;try{let i=await Kt(()=>{let s=ft.runInContext(o,t,{filename:"corsair:probe",timeout:r});s.catch(()=>{});let a,u=new Promise((l,c)=>{a=setTimeout(()=>c(new Error(`Probe exceeded ${r}ms time limit`)),r)});return Promise.race([s,u]).finally(()=>clearTimeout(a))});return{status:"ok",value:Ya(i)}}catch(i){return{status:"error",error:gt(i)}}}function Ya(e){if(typeof e!="string")throw new Error(`Probe returned a non-string result (${typeof e})`);return JSON.parse(e)}function Qa(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?wi:Math.min(e,wi)}function De(e){return e.deliveryMode==="auth.credentials"}function hn(e){return e.deliveryMode==="connections.sync"}function yt(e){return e.deliveryMode==="connect.create_link"}function kn(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function bn(e){return e.deliveryMode==="oauth.tokens"}function mt(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!De(e)&&!hn(e)&&!yt(e)&&!kn(e)&&!bn(e)}function Xa(e){return{status:"ok",connectLink:{connectUrl:e.connectUrl,expiresAt:e.expiresAt},webhookResponse:{status:200,body:{status:"ok",connectUrl:e.connectUrl,expiresAt:e.expiresAt}}}}async function eu(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await mn(e,n)}}}}}catch(t){return{status:"failed",retryable:rr(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function nu(e,n){try{let t=await ct(e,n);return Xa(t)}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function ur(e,n){if(e instanceof Headers)return e.get(n)??void 0;let t=e[n]??e[n.toLowerCase()];return Array.isArray(t)?t[0]:typeof t=="string"?t:void 0}async function tu(e,n,t){let r=typeof t.tenantId=="string"?t.tenantId:typeof t.query?.tenantId=="string"?t.query.tenantId:void 0;return r||(!n.database||!t.plugin||!t.linkType||!t.externalId?void 0:await Ln({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function ru(e,n,t){let r=await tu(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await yi(e,t.headers,t.body,o,t.plugin?{plugin:t.plugin}:void 0);if(!i.plugin)return{status:"failed",retryable:!1,error:"No matching webhook handler found"};if(i.response&&i.response.success===!1)return{status:"failed",retryable:!1,error:typeof i.response.error=="string"?i.response.error:"Webhook handler failed"};let s=i.response?.returnToSender,a=s&&typeof s=="object"&&typeof s.validationToken=="string"&&Object.keys(s).length===1?s.validationToken:s||(i.response?.data??i.response);return{status:"ok",webhookResponse:{status:i.response?.statusCode??200,body:a,headers:i.responseHeaders}}}async function ou(e,n){return await gn(e,{code:n.code,state:n.state,redirectUri:n.redirectUri,callbackParams:n.callbackParams,...n.plugin&&n.tenantId?{trusted:!0,plugin:n.plugin,tenantId:n.tenantId}:{}}),{status:"ok"}}async function iu(e,n){return await Ye(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function lr(e,n,t){let r=await cr(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function cr(e,n,t){let r=w(e),o=n.token?.trim();if(!o)return{status:"failed",retryable:!1,error:"Permission token is required"};if(!r.database)return{status:"failed",retryable:!1,error:"Database not configured"};let i=new Date().toISOString(),s=await r.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",o).executeTakeFirst();return s?s.status!=="pending"?{status:"ok"}:s.expires_at<i?(await r.database.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",s.id).execute(),{status:"failed",retryable:!1,error:"Permission has expired"}):(await r.database.db.updateTable("corsair_permissions").set({status:t,updated_at:new Date}).where("id","=",s.id).execute(),{status:"ok"}):{status:"failed",retryable:!1,error:"Permission not found"}}async function su(e,n){try{return await lt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function au(e,n){try{return await or(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}function Ci(e,n){let t=e;return n&&typeof t?.withTenant=="function"?t.withTenant(n):e}async function uu(e,n){try{let t=Ci(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",run:await sr({corsair:t,code:n.code,payload:n.trigger?.payload??null,memoizedSteps:n.memoizedSteps})}}}}catch(t){return{status:"failed",retryable:!0,error:t instanceof Error?t.message:"Workflow run failed"}}}async function cu(e,n){try{let t=Ci(e,n.tenantId);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",probe:await ar({corsair:t,code:n.code,timeoutMs:n.timeoutMs})}}}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Probe failed"}}}async function dr(e,n,t={}){let r=w(e),o=ur(n.headers,"x-corsair-signature"),i=ur(n.headers,"x-corsair-timestamp"),s=ur(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let u=ze({body:n.body,signatureHeader:o,timestampHeader:i,signingSecret:t.signingSecret});if(!u.ok)return{status:"failed",retryable:!1,error:u.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let l=pt(`nonce:${s.trim()}`,Re);if(!l.ok)return{status:"failed",retryable:!1,error:l.error}}else if(!t.allowUnsignedTunnel)return{status:"failed",retryable:!1,error:"Tunnel signing secret is required"};let a;try{a=JSON.parse(n.body)}catch{return{status:"failed",retryable:!1,error:"Invalid tunnel envelope JSON"}}if(a.type==="connect.status")return{status:"failed",retryable:!1,error:"connect.status is deprecated; use connections.sync signed delivery instead"};switch(a.type){case"webhook":return ru(e,r,a.payload);case"oauth.callback":return ou(e,a.payload);case"oauth.tokens":return iu(e,a.payload);case"permission.approve":return cr(e,a.payload,"approved");case"permission.deny":return cr(e,a.payload,"denied");case"auth.credentials":return su(e,a.payload);case"integration.credentials":return au(e,a.payload);case"connect.create_link":return nu(e,a.payload);case"connections.sync":{let u=t.signingSecret?.trim();return u?eu(e,u):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}case"run":return t.allowWorkflowExecution?uu(e,a.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};case"probe":return t.allowWorkflowExecution?cu(e,a.payload):{status:"failed",retryable:!1,error:"Workflow execution is not enabled (set allowWorkflowExecution: true)"};default:return{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${String(a.type)}`}}}var pr=new Map;function Pi(e){let n;try{n=H(e)}catch{return}let t=_t(n);t&&pr.get(n.projectApiKey)!==t&&(pr.set(n.projectApiKey,t),_({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{pr.delete(n.projectApiKey)}))}var lu=[".corsair.dev"];function du(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function pu(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:du(n)?!0:lu.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Ti(e){return!e||!pu(e)?null:{"Access-Control-Allow-Origin":e,"Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"content-type, x-corsair-signature, x-corsair-timestamp, x-corsair-project, x-corsair-nonce, access-control-request-private-network","Access-Control-Allow-Private-Network":"true","Access-Control-Max-Age":"0",Vary:"Origin"}}function vi(e,n){if(!n)return e;let t=new Headers(e.headers);for(let[r,o]of Object.entries(n))t.set(r,o);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function gr(e,n){let t=new URL(e);return n.error?(t.searchParams.set("error",n.error),t.toString()):n.connectedPlugin?(t.searchParams.set("connected",n.connectedPlugin),t.toString()):(n.status!==void 0&&t.searchParams.set("status",Buffer.from(JSON.stringify(n.status)).toString("base64url")),t.toString())}async function fr(e,n){let t=H(e),o=new URL(n).searchParams.get("d");if(!o)return{type:"json",status:200,body:{status:"ok",message:"Corsair tunnel endpoint is active",timestamp:new Date().toISOString()}};let i=he(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=pt(`browser:${i.jti}`,me);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(hn(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connections sync delivery requires hubOrigin and requestId for client bridge"}};let a=await mn(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(yt(i)){if(!i.hubOrigin||!i.requestId)return{type:"json",status:400,body:{error:"Connect link delivery requires hubOrigin and requestId for client bridge"}};let a=i.connectLinkPlugins?.filter(Boolean)??[];if(a.length===0)return{type:"json",status:400,body:{error:"Connect link delivery requires at least one plugin in connectLinkPlugins"}};let u=await ct(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:u.connectUrl,expiresAt:u.expiresAt}})}}if(De(i))return i.hubSuccessUrl?i.credentials?(await lt(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:gr(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:gr(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(kn(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await lr(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(bn(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Ye(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!mt(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await gn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let u=a instanceof Error?a.message:"Hub delivery failed";return hn(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:yt(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:De(i)&&i.hubSuccessUrl?{type:"redirect",url:gr(i.hubSuccessUrl,{error:u})}:De(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Fe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:u})}:{type:"json",status:400,body:{error:u}}}return{type:"redirect",url:i.hubSuccessUrl}}async function yr(e,n){let t=H(e),r=await dr(e,n,{signingSecret:t.signingSecret,allowWorkflowExecution:t.allowWorkflowExecution});if(r.status!=="ok")return{type:"json",status:r.retryable===!1?400:502,body:{error:r.error??"Tunnel processing failed"}};let o=r.webhookResponse;if(!o)return{type:"json",status:200,body:{status:"ok"}};let i=o.status??200,s=o.headers;return o.body&&typeof o.body=="object"&&!(o.body instanceof ArrayBuffer)?{type:"json",status:i,body:o.body,headers:s}:{type:"text",status:i,body:typeof o.body=="string"?o.body:o.body?JSON.stringify(o.body):null,headers:s}}function mr(e){if(e.type==="redirect")return Response.redirect(e.url,302);let n=new Headers;for(let[t,r]of Object.entries(e.headers??{}))typeof r=="string"&&n.set(t,r);return e.type==="json"?Response.json(e.body,{status:e.status,headers:n}):new Response(e.body,{status:e.status,headers:n})}async function hr(e,n){return n.method==="GET"?fr(e,n.url):yr(e,{headers:n.headers,body:n.body??""})}async function kr(e,n){try{let t=await hr(e,n);return mr(t)}catch(t){if(t instanceof se)return Response.json({error:t.message},{status:503});throw t}}async function Oe(e,n){Pi(e);let t=n.method.toUpperCase(),r=Ti(n.headers.get("origin"));if(t==="OPTIONS")return r?new Response(null,{status:204,headers:r}):Response.json({error:"Method not allowed"},{status:405});if(t!=="GET"&&t!=="POST")return Response.json({error:"Method not allowed"},{status:405});let o=await kr(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return vi(o,r)}var W=class extends Error{pluginId;authType;constructor(n,t,r){super(r??`[auth-missing:${n}:${t}]`),Object.setPrototypeOf(this,new.target.prototype),this.name="AuthMissingError",this.pluginId=n,this.authType=t}};var Ai=300;async function br(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,[a,u,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!l)throw new W(o,"managed");let c=Math.floor(Date.now()/1e3);if(!s&&a&&u&&Number(u)>c+Ai)return{accessToken:a,expiresAt:Number(u),refreshed:!1};if(!l&&a&&!s){let g=u?Number(u):null;if(g===null||g>c+Ai)return{accessToken:a,expiresAt:g??c+3600,refreshed:!1}}let p=await fu(r,o,i),d=p.expires_in?c+p.expires_in:u?Number(u):c+3600;return await t.set_access_token(p.access_token),await t.set_expires_at(String(d)),p.refresh_token&&await t.set_refresh_token(p.refresh_token),p.scope&&await t.set_scope(p.scope),{accessToken:p.access_token,expiresAt:d,refreshed:!0}}function gu(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function fu(e,n,t){try{return await _({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t},parseResponse:En})}catch(r){let o=r instanceof Error?r.message:"";throw gu(o)?new W(n,"managed"):r}}async function xi(e,n){e._refreshAuth=async()=>(await br(n,{forceRefresh:!0})).accessToken}function Ri(e){return{delivery:n=>Oe(e,n),deliveryOptions:n=>Oe(e,n)}}var Ii=1200*1e3;function wr(){return ie()}function Cr(){return Ii}function Pr(e,n){return on(e,n,Ii)}function Tr(e,n){return ee(e,n)}function vr(e){return Ie(e)}var Si=600*1e3;function Ar(){return ie()}function xr(){return Si}function Rr(e,n){return on(e,n,Si)}function Ir(e,n){return ee(e,n)}function Sr(e){return It(e)}function _r(e){return Ie(e)}function Er(){return ie()}function Dr(e,n,t){return An(e,n,Math.floor(t.getTime()/1e3))}function Or(e,n){return ee(e,n)}function Mr(e){return Ie(e)}function _i(e){return e&&typeof e=="object"?e:{}}async function Hr(e,n){return _({hub:e,path:"/threads",body:{tenantId:n.tenantId,message:n.message},parseResponse:t=>t})}async function Fr(e,n){return _({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages`,body:{tenantId:n.tenantId,message:n.message},notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>t})}async function Ur(e,n){return $({hub:e,path:`/threads?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=_i(t).threads;return Array.isArray(r)?r:[]}})}async function ht(e,n){return $({hub:e,path:`/threads/${encodeURIComponent(n.threadId)}/messages?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Thread "${n.threadId}" not found`,parseResponse:t=>{let r=_i(t).messages;return Array.isArray(r)?r:[]}})}function kt(e,n){let t=[];e||t.push("database"),n||t.push("kek");let r={};return new Proxy(r,{get(o,i){let s=t.length>1;throw new Error(`corsair.keys.${String(i)}: Cannot access keys because ${t.join(" and ")} ${s?"are":"is"} not configured. Provide both 'database' and 'kek' in createCorsair() to enable key management.
|
|
48
48
|
|
|
49
|
-
To generate a KEK, run: openssl rand -base64 ${an}`)}})}async function fu(e){let n=!1;for(;;){let t=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.integrationName).executeTakeFirst();if(!t){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Integration "${e.integrationName}" not found. Make sure to create the integration first.`)}let r=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",t.id).executeTakeFirst();if(!r){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Account not found for tenant "${e.tenantId}" and integration "${e.integrationName}". Make sure to create the account first.`)}return{integrationId:t.id,accountId:r.id,integration:{id:t.id,config:t.config,dek:t.dek??null},account:{id:r.id,config:r.config,dek:r.dek??null}}}}async function Ei(e){let{integrationId:n,accountId:t}=await fu(e);return{integrationId:n,accountId:t}}function Br(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function yu(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await Ut(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins,multiTenancy:n.multiTenancy})).connectUrl}catch{return null}}async function mu(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await Ut(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):Br(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await yu({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return t?Br(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function hu(e,n,t){let r=$e(Ce(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):Br(e,i)}async function ku(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&qe(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?hu(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?mu({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy}):e.error.message}async function Di(e){let n=await ku(e);throw new W(e.error.pluginId,e.error.authType,n)}var bu=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Oi(e,n,t,r,o){let i={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(o).find(l=>o[l]?.match(e,i));return await(o[s||"DEFAULT"]?.handler||bu)(e,i)}function wu(e){return typeof e=="function"}function Lr({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:m,allPlugins:h,multiTenancy:b}){for(let[C,S]of Object.entries(e)){let x=n?.[C];if(wu(S)){let E=x,k=[...s,C].join("."),T=async(v={})=>{let j=l?.[k];qt(k,j?.riskLevel??"write");let re;if(u){let K=j,{result:Tn,reason:Q,onComplete:nn,token:oe,id:xe,expiresAt:q}=await ti({pluginId:o,endpointPath:k,args:v,mode:u.mode,override:u.overrides?.[k],riskLevel:K?.riskLevel??"write",meta:K,db:c,timeoutMs:p?Zt(p.timeout):void 0,tenantId:d,approvalMode:p?.mode});if(Tn==="blocked"){let X;throw Q==="denied"?X=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:Q==="policy"?X=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:Q==="timeout"?X=`Action '${k}' timed out waiting for approval.`:oe&&xe?X=await jt({permissionsOptions:p,manual:g,hub:f,permissionId:xe,permissionToken:oe,plugin:o,endpoint:k,args:v,tenantId:d??"default",expiresAt:q??new Date(Date.now()+(p?Zt(p.timeout):600*1e3)).toISOString(),operationPath:k}):X=`Action '${k}' requires user approval before it can run.`,new Ze(X)}re=nn}let P=async(K,Tn,Q)=>{try{return await S(Tn,Q)}catch(nn){if(nn instanceof Error){let oe=await Oi(nn,o,k,typeof Q=="object"&&Q!==null?Q:{args:Q},i);if(K<(oe.maxRetries||0)){let xe=K+1;console.log(`Retrying (${xe} / ${oe.maxRetries})...`);let q;if(oe.headersRetryAfterMs)q=oe.headersRetryAfterMs;else switch(oe.retryStrategy){case"exponential_backoff":q=Math.pow(2,xe-1)*1e3;break;case"exponential_backoff_jitter":let X=Math.pow(2,xe-1)*1e3,hs=(Math.random()-.5)*1e3;q=Math.max(0,X+hs);break;case"linear_1s":q=1e3;break;case"linear_2s":q=2e3;break;case"linear_3s":q=3e3;break;case"linear_4s":q=4e3;break;default:q=1e3;break}await new Promise(X=>setTimeout(X,q)),await P(xe,Tn,Q),console.log(`[corsair:${o}:${k}] Retry strategy:`,oe)}}throw nn}},Y;try{Y=a?await a(t,"endpoint"):void 0}catch(K){throw K instanceof W&&(y&&f&&pn({hub:f,database:c,kek:m,plugins:h??[],plugin:y,tenantId:d,verified:!1}),await Di({error:K,manual:g,hub:f,plugin:y,tenantId:d,database:c,kek:m,plugins:h,multiTenancy:b})),K}if(!E?.before&&!E?.after){let K=await P(0,{...t,key:Y},v);return await re?.(),y&&f&&pn({hub:f,database:c,kek:m,plugins:h??[],plugin:y,tenantId:d,verified:!0}),K}let en={...t,key:Y},Ae=E.before?await E.before(en,v):{ctx:en,args:v,continue:!0,passToAfter:void 0};if(Ae.continue===!1)return;let no=await P(0,Ae.ctx,Ae.args);return await E.after?.(Ae.ctx,no,Ae.passToAfter),await re?.(),y&&f&&pn({hub:f,database:c,kek:m,plugins:h??[],plugin:y,tenantId:d,verified:!0}),no};r[C]=T}else if(S&&typeof S=="object"){let E={};Lr({endpoints:S,hooks:x,ctx:t,tree:E,pluginId:o,errorHandlers:i,currentPath:[...s,C],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:m,allPlugins:h,multiTenancy:b}),r[C]=E}}}function Mi(e){return e&&typeof e=="object"?e:{}}async function Hi(e,n){let t=new URLSearchParams({tenantId:n.tenantId});return n.limit!=null&&t.set("limit",String(n.limit)),$({hub:e,path:`/runs?${t.toString()}`,parseResponse:r=>{let o=Mi(r).runs;return Array.isArray(o)?o:[]}})}async function Nr(e,n){return $({hub:e,path:`/runs/${encodeURIComponent(n.runId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Run "${n.runId}" not found`,parseResponse:t=>Mi(t).run})}async function $r(e,n,t){await _({hub:e,path:`/runs/${encodeURIComponent(t.runId)}/${n}?tenantId=${encodeURIComponent(t.tenantId)}`,body:{},notFoundMessage:`Run "${t.runId}" cannot be ${n==="cancel"?"canceled":`${n}d`} in its current state`,parseResponse:r=>r})}var Fi=(e,n)=>$r(e,"approve",n),Ui=(e,n)=>$r(e,"deny",n),Bi=(e,n)=>$r(e,"cancel",n);function Li(e,n){let t=()=>{if(!e)throw new Error("corsair.runs requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({get:()=>Nr(t(),{runId:o,tenantId:n}),approve:()=>Fi(t(),{runId:o,tenantId:n}),deny:()=>Ui(t(),{runId:o,tenantId:n}),cancel:()=>Bi(t(),{runId:o,tenantId:n})}));return r.list=o=>Hi(t(),{tenantId:n,limit:o?.limit}),r.get=o=>Nr(t(),{runId:o,tenantId:n}),r}function Ni(e,n){let t=()=>{if(!e)throw new Error("corsair.threads requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({message:i=>Fr(t(),{threadId:o,tenantId:n,message:i}),listMessages:()=>ht(t(),{threadId:o,tenantId:n})}));return r.create=o=>Hr(t(),{tenantId:n,message:o}),r.list=()=>Ur(t(),{tenantId:n}),r.listMessages=o=>ht(t(),{threadId:o,tenantId:n}),r}function Cu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Wr({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(Cu(s)){let u=a,l=async c=>{let p=(g,f)=>s.handler(g,f),d=o?await o(t,"webhook"):void 0;return!u?.before&&!u?.after?p({...t,key:d},c):(async()=>{let g={...t,key:d},f=u.before?await u.before(g,c):{ctx:g,args:c,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let y=await p(f.ctx,f.args);return y?.success===!0&&await u.after?.(f.ctx,y,f.passToAfter),y})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let u={};Wr({webhooks:s,hooks:a,ctx:t,webhooksTree:u,keyBuilder:o}),r[i]=u}}}function Tu(e){return e&&typeof e=="object"?e:{}}async function $i(e,n){return $({hub:e,path:`/workflows?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Tu(t).workflows;return Array.isArray(r)?r:[]}})}async function Wi(e,n){return _({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/run?tenantId=${encodeURIComponent(n.tenantId)}`,body:{payload:n.payload,idempotencyKey:n.idempotencyKey},notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>t})}function ji(e,n){let t=()=>{if(!e)throw new Error("corsair.workflows requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({run:i=>Wi(t(),{workflowId:o,tenantId:n,payload:i?.payload,idempotencyKey:i?.idempotencyKey})}));return r.list=()=>$i(t(),{tenantId:n}),r}function vu(e,n,t,r){let o=null;return async()=>{if(o)return o;if(!e)throw new Error("Database not configured");let{accountId:i}=await Ei({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function Pu(e,n,t,r,o){return e?At(e.db,n,t,r,o):{findByEntityId:async()=>null,existsByEntityId:async()=>!1,findIdByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function jr(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:u,internalConfig:l}=n,c=r??"default",p=l&&t?()=>Ne(l,c):void 0,d={},g={};for(let f of e)d[f.id]={},g[f.id]={};for(let f of e){let y=f.schema,m=vu(t,f.id,c,p);if(y?.entities){let P={};for(let[Y,en]of Object.entries(y.entities)){let Ae=t?At(t.db,m,Y,y.version,en):Pu(void 0,m,Y,y.version,en);P[Y]=Ae}g[f.id].db=P,d[f.id].db=P}let h=f.options,b=f.authConfig,C;if(t&&o&&h?.authType){let P=b?.[h.authType]?.account??[];C=D({authType:h.authType,integrationName:f.id,tenantId:c,kek:o,database:t,extraAccountFields:P,ensureProvisioned:p}),d[f.id].keys=C}let S={database:t,db:g[f.id]?.db??{},$getAccountId:m,...f.options?{options:f.options}:{},...C?{keys:C,authType:h?.authType}:{},tenantId:c,...u?{hub:u}:{}},x=f.endpoints??{},E=f.hooks,k={...i,...f.errorHandlers},T={},v=f.options?.permissions;Lr({endpoints:x,hooks:E,ctx:S,tree:T,pluginId:f.id,errorHandlers:k,currentPath:[],keyBuilder:f.keyBuilder,permissionsConfig:v,endpointMeta:f.endpointMeta,database:t,permissionsOptions:s,tenantId:r,manualConfig:a?{...a,oauthConfig:f.oauthConfig,kek:o,tenantId:c}:void 0,hubConfig:u,plugin:f,kek:o,allPlugins:e,multiTenancy:l?.multiTenancy}),Object.keys(T).length>0&&(d[f.id].api=T),S.endpoints=T;let j=f.webhooks??{},re=f.webhookHooks;if(Object.keys(j).length>0){let P={};Wr({webhooks:j,hooks:re,ctx:S,webhooksTree:P,keyBuilder:f.keyBuilder}),d[f.id].webhooks=P,f.pluginWebhookMatcher&&(d[f.id].pluginWebhookMatcher=f.pluginWebhookMatcher),f.pluginTenantWebhookMatcher&&(d[f.id].pluginTenantWebhookMatcher=f.pluginTenantWebhookMatcher)}}return d.threads=Ni(u,c),d.runs=Li(u,c),d.workflows=ji(u,c),d}function Ki(e,n,t){let r={};for(let o of e){let i=o.options,s=o.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],u=O({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=u}}return r}var Au="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function qi(e){let{permissions:n,approval:t}=e;if(n&&t)throw new Error("createCorsair was given both permissions and approval config. Use permissions only \u2014 approval is deprecated.");return t?(console.warn(`[corsair] ${Au}`),t):n}var Zi=[{method:"GET",pattern:"/ok",handler:async()=>M(200,zn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>M(200,await Je(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>M(201,await Qn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>M(200,await Yn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>M(200,await Ge(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>M(200,await Vn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>M(200,await Xn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>M(200,await Gt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?M(200,await zt(e,t)):M(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>M(200,await et(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>M(200,await nt(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>M(200,await tt(e,n,t))}];(()=>{let e=new Set;for(let n of Zi){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function xu(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let o={};for(let i=0;i<t.length;i++){let s=t[i],a=r[i];if(s.startsWith(":"))o[s.slice(1)]=decodeURIComponent(a);else if(s!==a)return null}return o}function Ru(e,n){if(!n)return e;let t=n.endsWith("/")?n.slice(0,-1):n;return e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length):e}async function Iu(e){if(!(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json")))try{let t=await e.text();return t?JSON.parse(t):void 0}catch{throw new I(400,"invalid_json","Request body is not valid JSON")}}var Su="/api/corsair";function Me(e,n={}){let t=n.basePath??Su,r=w(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=Ru(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await Oe(e,o);if(a!=="GET"&&a!=="POST")return M(405,{error:"method_not_allowed",message:`Method ${a} not allowed`});let u=Object.fromEntries(i.searchParams);for(let l of Zi){if(l.method!==a)continue;let c=xu(l.pattern,s);if(!c)continue;let p=await Iu(o);return await l.handler({corsair:e,internal:r,req:o,params:c,query:u,body:p})}throw Te(`No route for ${a} ${s}`)}catch(i){if(n.onError){let a=await n.onError(i,o);if(a)return a}if(i instanceof I)return ri(i);let s=i instanceof Error?i.message:"Internal server error";return M(500,{error:"internal_error",message:s})}}}function _u(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,o=`${t}://${n}${r}`,i=new Headers;for(let[u,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let c of l)i.append(u,c);else i.set(u,l);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:i};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),i.has("content-type")||i.set("content-type","application/json")),new Request(o,a)}async function Eu(e,n){e.status(n.status),n.headers.forEach((r,o)=>e.setHeader(o,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function Gi(e,n){let t=Me(e,n);return async(r,o,i)=>{try{let s=await t(_u(r));await Eu(o,s)}catch(s){i(s)}}}function Ji(e,n){let t=Me(e,n);return r=>t(r.req.raw)}function zi(e,n){let t=Me(e,n);return{GET:t,POST:t,OPTIONS:t}}function Vi(e){let n={[wn]:e};return{ok:zn,tenants:{list:()=>Je(e),create:t=>Qn(e,t),get:t=>Yn(e,t)},plugins:{list:()=>Ge(e),get:t=>Vn(e,t)},connectionStatus:{get:t=>Xn(e,t?.tenantId)},permissions:{get:t=>ci(e,t)},connect:{createLink:t=>et(n,e,t),resolve:t=>nt(n,e,t),oauthCallback:t=>tt(n,e,t)}}}async function Yi(e,n,t,r,o="pending"){if(!e)return null;try{let i=ao(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:n,event_type:t,payload:r,status:o}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function Du(e,n,t,r="pending"){try{let o=await e.$getAccountId();return Yi(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as Xi from"https";import*as bt from"querystring";var Ou=["expires_in","refresh_token_expires_in"];function Qi(e){let n={...e};for(let t of Ou){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function Mu(e){try{return Qi(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=bt.parse(e);return!n.access_token&&!n.error?null:Qi({...n})}function $n(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,u)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let c=bt.stringify(l),p={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(c).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let d=Xi.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let f="";g.on("data",y=>{f+=y}),g.on("end",()=>{if(g.statusCode!==200){u(new Error(`Token exchange failed (${g.statusCode}): ${f}`));return}let y=Mu(f);y?a(y):u(new Error(`Token endpoint returned non-JSON response: ${f}`))})});d.on("error",g=>u(new Error(`Request failed: ${g.message}`))),d.write(c),d.end()})}var es=" ";function z(e){let n=e;return n._def??n.def??{}}function V(e){let n=e.typeName;if(n)return n;let t=e.type;if(t)return`Zod${t.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}`}function J(e){return e.innerType??e.schema??e.out??e.in}function ts(e,n){switch(n){case"ZodPipe":return e.in??e.innerType;case"ZodEffects":return e.schema??e.innerType;case"ZodTransform":return e.schema??e.innerType??e.in;default:return J(e)}}function rs(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Ct(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Qe(e){return Array.isArray(e.options)?e.options:Array.isArray(e.values)?e.values:e.entries!==null&&typeof e.entries=="object"&&!Array.isArray(e.entries)?Object.values(e.entries):[]}function os(e,n){return e.description??n.description}function Hu(e){let n=e;for(;n;){let t=z(n),r=os(n,t);if(r)return r;let o=V(t);if(Jr(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=ts(t,o);continue}break}}function Jr(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function L(e){let n=z(e),t=V(n);switch(t){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"Date";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(n.value??Qe(n)[0]??"unknown");case"ZodEnum":return Qe(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=J(n);return r?L(r):"unknown"}case"ZodNullable":{let r=J(n);return`${r?L(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=J(n);return r?L(r):"unknown"}case"ZodArray":{let r=rs(n);if(!r)return"unknown[]";let o=z(r),i=V(o)==="ZodUnion",s=L(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Ct(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let u=V(z(a));return`${u==="ZodOptional"||u==="ZodNullable"?s+"?":s}: ${L(a)}`}).join(", ")} }`}case"ZodUnion":return Qe(n).map(r=>L(r)).join(" | ");case"ZodIntersection":return`${L(n.left)} & ${L(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=ts(n,t);return r?L(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ge(e){let n=z(e),t=V(n),r=os(e,n);switch(t){case"ZodString":return{kind:"string",optional:!1,description:r};case"ZodNumber":return{kind:"number",optional:!1,description:r};case"ZodBoolean":return{kind:"boolean",optional:!1,description:r};case"ZodLiteral":{let o=n.value??Qe(n)[0],i=typeof o=="string"||typeof o=="number"||typeof o=="boolean"?o:String(o??"");return{kind:"literal",optional:!1,description:r,value:i}}case"ZodEnum":{let o=Qe(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=J(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=J(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=J(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=rs(n);return{kind:"array",optional:!1,description:r,items:o?ge(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=Ct(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=ge(a);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=Qe(n);for(let i of o){let s=z(i);if(V(s)==="ZodObject")return{...ge(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=J(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function jy(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let o=t.slice(0,r),i=t.slice(r+1),s=e.find(c=>c.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=Pe(s.endpointMeta,a),l=Pe(s.endpointSchemas,a);return!u&&!l?null:{input:l?.input?ge(l.input):null,output:l?.output?ge(l.output):null,description:u?.description}}var zr=["equals","contains","startsWith","endsWith","in"],Fu=["equals","gt","gte","lt","lte","in"],Uu=["equals"],Bu=["equals","before","after","between"];function is(e){let n=z(e);switch(V(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=J(n);return r?is(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Vr(e){let n=z(e),t=V(n);if(Jr(t)){let i=J(n);return i?Vr(i):{}}if(t!=="ZodObject")return{};let r=Ct(e,n),o={};for(let[i,s]of Object.entries(r)){let a=is(s);a==="string"?o[i]={type:"string",operators:zr}:a==="number"?o[i]={type:"number",operators:Fu}:a==="boolean"?o[i]={type:"boolean",operators:Uu}:a==="date"&&(o[i]={type:"date",operators:Bu})}return o}function ss(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function qr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];typeof o=="function"?t.push(i.join(".")):o!==null&&typeof o=="object"&&qr(o,i,t)}}function Zr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Gr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Zr(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&Gr(o,i,t)}}function Yr(e,n){if(n.length===0)return null;let[t,...r]=n,o=Object.entries(e).find(([a])=>a.toLowerCase()===t);if(!o)return null;let[i,s]=o;if(r.length===0)return Zr(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Zr(s)){let a=Yr(s,r);if(a!==null)return[i,...a]}return null}function as(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let i=0;i<n.length;i++){let s=" ".repeat(i+2);t.push(`${s}${n[i]}: {`)}let r=" ".repeat(n.length+2),o=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${o}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let i=n.length-1;i>=0;i--){let s=" ".repeat(i+2);t.push(`${s}},`)}return t.push(" },"),t.push("})"),t.join(`
|
|
50
|
-
`)}var
|
|
49
|
+
To generate a KEK, run: openssl rand -base64 ${an}`)}})}async function yu(e){let n=!1;for(;;){let t=await e.database.db.selectFrom("corsair_integrations").selectAll().where("name","=",e.integrationName).executeTakeFirst();if(!t){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Integration "${e.integrationName}" not found. Make sure to create the integration first.`)}let r=await e.database.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",e.tenantId).where("integration_id","=",t.id).executeTakeFirst();if(!r){if(!n&&e.ensureProvisioned){n=!0,await e.ensureProvisioned();continue}throw new Error(`Account not found for tenant "${e.tenantId}" and integration "${e.integrationName}". Make sure to create the account first.`)}return{integrationId:t.id,accountId:r.id,integration:{id:t.id,config:t.config,dek:t.dek??null},account:{id:r.id,config:r.config,dek:r.dek??null}}}}async function Ei(e){let{integrationId:n,accountId:t}=await yu(e);return{integrationId:n,accountId:t}}function Br(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function mu(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await Ut(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins,multiTenancy:n.multiTenancy})).connectUrl}catch{return null}}async function hu(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await Ut(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):Br(e.pluginId,r.connectUrl)}catch{return`[auth-missing:${e.pluginId}:${e.authType}] Authentication required. Could not create connect link. Check hub configuration and server logs.`}let t=await mu({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy});return t?Br(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function ku(e,n,t){let r=$e(Ce(e,n.tenantId??t??"default"),n.kek),o=new URL(n.baseUrl);o.searchParams.set("state",r);let i=o.toString();return n.onAuthMissing?n.onAuthMissing({plugin:e,connectUrl:i,state:r}):Br(e,i)}async function bu(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&qe(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?ku(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?hu({manual:e.manual,hub:e.hub,plugin:e.plugin,pluginId:t,tenantId:n,authType:e.error.authType,database:e.database,kek:e.kek,plugins:e.plugins,multiTenancy:e.multiTenancy}):e.error.message}async function Di(e){let n=await bu(e);throw new W(e.error.pluginId,e.error.authType,n)}var wu=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function Oi(e,n,t,r,o){let i={pluginId:n,operation:t,input:r,originalError:e},s=Object.keys(o).find(l=>o[l]?.match(e,i));return await(o[s||"DEFAULT"]?.handler||wu)(e,i)}function Cu(e){return typeof e=="function"}function Lr({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:h,allPlugins:m,multiTenancy:b}){for(let[C,S]of Object.entries(e)){let x=n?.[C];if(Cu(S)){let E=x,k=[...s,C].join("."),P=async(T={})=>{let j=l?.[k];qt(k,j?.riskLevel??"write");let re;if(u){let K=j,{result:Pn,reason:Q,onComplete:nn,token:oe,id:xe,expiresAt:q}=await ti({pluginId:o,endpointPath:k,args:T,mode:u.mode,override:u.overrides?.[k],riskLevel:K?.riskLevel??"write",meta:K,db:c,timeoutMs:p?Zt(p.timeout):void 0,tenantId:d,approvalMode:p?.mode});if(Pn==="blocked"){let X;throw Q==="denied"?X=`Action '${k}' was denied by the user. Await further instructions before proceeding.`:Q==="policy"?X=`Action '${k}' is blocked by the permission policy. Update the corsair config to allow it.`:Q==="timeout"?X=`Action '${k}' timed out waiting for approval.`:oe&&xe?X=await jt({permissionsOptions:p,manual:g,hub:f,permissionId:xe,permissionToken:oe,plugin:o,endpoint:k,args:T,tenantId:d??"default",expiresAt:q??new Date(Date.now()+(p?Zt(p.timeout):600*1e3)).toISOString(),operationPath:k}):X=`Action '${k}' requires user approval before it can run.`,new Ze(X)}re=nn}let v=async(K,Pn,Q)=>{try{return await S(Pn,Q)}catch(nn){if(nn instanceof Error){let oe=await Oi(nn,o,k,typeof Q=="object"&&Q!==null?Q:{args:Q},i);if(K<(oe.maxRetries||0)){let xe=K+1;console.log(`Retrying (${xe} / ${oe.maxRetries})...`);let q;if(oe.headersRetryAfterMs)q=oe.headersRetryAfterMs;else switch(oe.retryStrategy){case"exponential_backoff":q=Math.pow(2,xe-1)*1e3;break;case"exponential_backoff_jitter":let X=Math.pow(2,xe-1)*1e3,hs=(Math.random()-.5)*1e3;q=Math.max(0,X+hs);break;case"linear_1s":q=1e3;break;case"linear_2s":q=2e3;break;case"linear_3s":q=3e3;break;case"linear_4s":q=4e3;break;default:q=1e3;break}await new Promise(X=>setTimeout(X,q)),await v(xe,Pn,Q),console.log(`[corsair:${o}:${k}] Retry strategy:`,oe)}}throw nn}},Y;try{Y=a?await a(t,"endpoint"):void 0}catch(K){throw K instanceof W&&(y&&f&&pn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!1}),await Di({error:K,manual:g,hub:f,plugin:y,tenantId:d,database:c,kek:h,plugins:m,multiTenancy:b})),K}if(!E?.before&&!E?.after){let K=await v(0,{...t,key:Y},T);return await re?.(),y&&f&&pn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!0}),K}let en={...t,key:Y},Ae=E.before?await E.before(en,T):{ctx:en,args:T,continue:!0,passToAfter:void 0};if(Ae.continue===!1)return;let no=await v(0,Ae.ctx,Ae.args);return await E.after?.(Ae.ctx,no,Ae.passToAfter),await re?.(),y&&f&&pn({hub:f,database:c,kek:h,plugins:m??[],plugin:y,tenantId:d,verified:!0}),no};r[C]=P}else if(S&&typeof S=="object"){let E={};Lr({endpoints:S,hooks:x,ctx:t,tree:E,pluginId:o,errorHandlers:i,currentPath:[...s,C],keyBuilder:a,permissionsConfig:u,endpointMeta:l,database:c,permissionsOptions:p,tenantId:d,manualConfig:g,hubConfig:f,plugin:y,kek:h,allPlugins:m,multiTenancy:b}),r[C]=E}}}function Mi(e){return e&&typeof e=="object"?e:{}}async function Hi(e,n){let t=new URLSearchParams({tenantId:n.tenantId});return n.limit!=null&&t.set("limit",String(n.limit)),$({hub:e,path:`/runs?${t.toString()}`,parseResponse:r=>{let o=Mi(r).runs;return Array.isArray(o)?o:[]}})}async function Nr(e,n){return $({hub:e,path:`/runs/${encodeURIComponent(n.runId)}?tenantId=${encodeURIComponent(n.tenantId)}`,notFoundMessage:`Run "${n.runId}" not found`,parseResponse:t=>Mi(t).run})}async function $r(e,n,t){await _({hub:e,path:`/runs/${encodeURIComponent(t.runId)}/${n}?tenantId=${encodeURIComponent(t.tenantId)}`,body:{},notFoundMessage:`Run "${t.runId}" cannot be ${n==="cancel"?"canceled":`${n}d`} in its current state`,parseResponse:r=>r})}var Fi=(e,n)=>$r(e,"approve",n),Ui=(e,n)=>$r(e,"deny",n),Bi=(e,n)=>$r(e,"cancel",n);function Li(e,n){let t=()=>{if(!e)throw new Error("corsair.runs requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({get:()=>Nr(t(),{runId:o,tenantId:n}),approve:()=>Fi(t(),{runId:o,tenantId:n}),deny:()=>Ui(t(),{runId:o,tenantId:n}),cancel:()=>Bi(t(),{runId:o,tenantId:n})}));return r.list=o=>Hi(t(),{tenantId:n,limit:o?.limit}),r.get=o=>Nr(t(),{runId:o,tenantId:n}),r}function Ni(e,n){let t=()=>{if(!e)throw new Error("corsair.threads requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({message:i=>Fr(t(),{threadId:o,tenantId:n,message:i}),listMessages:()=>ht(t(),{threadId:o,tenantId:n})}));return r.create=o=>Hr(t(),{tenantId:n,message:o}),r.list=()=>Ur(t(),{tenantId:n}),r.listMessages=o=>ht(t(),{threadId:o,tenantId:n}),r}function Pu(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Wr({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(Pu(s)){let u=a,l=async c=>{let p=(g,f)=>s.handler(g,f),d=o?await o(t,"webhook"):void 0;return!u?.before&&!u?.after?p({...t,key:d},c):(async()=>{let g={...t,key:d},f=u.before?await u.before(g,c):{ctx:g,args:c,continue:!0,passToAfter:void 0};if(f.continue===!1)return;let y=await p(f.ctx,f.args);return y?.success===!0&&await u.after?.(f.ctx,y,f.passToAfter),y})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let u={};Wr({webhooks:s,hooks:a,ctx:t,webhooksTree:u,keyBuilder:o}),r[i]=u}}}function Tu(e){return e&&typeof e=="object"?e:{}}async function $i(e,n){return $({hub:e,path:`/workflows?tenantId=${encodeURIComponent(n.tenantId)}`,parseResponse:t=>{let r=Tu(t).workflows;return Array.isArray(r)?r:[]}})}async function Wi(e,n){return _({hub:e,path:`/workflows/${encodeURIComponent(n.workflowId)}/run?tenantId=${encodeURIComponent(n.tenantId)}`,body:{payload:n.payload,idempotencyKey:n.idempotencyKey},notFoundMessage:`Workflow "${n.workflowId}" not found`,parseResponse:t=>t})}function ji(e,n){let t=()=>{if(!e)throw new Error("corsair.workflows requires Hub to be configured. Pass `hub` to createCorsair({ hub: { projectApiKey, ... } }).");return e},r=(o=>({run:i=>Wi(t(),{workflowId:o,tenantId:n,payload:i?.payload,idempotencyKey:i?.idempotencyKey})}));return r.list=()=>$i(t(),{tenantId:n}),r}function vu(e,n,t,r){let o=null;return async()=>{if(o)return o;if(!e)throw new Error("Database not configured");let{accountId:i}=await Ei({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function Au(e,n,t,r,o){return e?At(e.db,n,t,r,o):{findByEntityId:async()=>null,existsByEntityId:async()=>!1,findIdByEntityId:async()=>null,findById:async()=>null,findManyByEntityIds:async()=>[],list:async()=>[],search:async()=>[],upsertByEntityId:async()=>{throw new Error("Database not configured")},deleteById:async()=>!1,deleteByEntityId:async()=>!1,count:async()=>0}}function jr(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:u,internalConfig:l}=n,c=r??"default",p=l&&t?()=>Ne(l,c):void 0,d={},g={};for(let f of e)d[f.id]={},g[f.id]={};for(let f of e){let y=f.schema,h=vu(t,f.id,c,p);if(y?.entities){let v={};for(let[Y,en]of Object.entries(y.entities)){let Ae=t?At(t.db,h,Y,y.version,en):Au(void 0,h,Y,y.version,en);v[Y]=Ae}g[f.id].db=v,d[f.id].db=v}let m=f.options,b=f.authConfig,C;if(t&&o&&m?.authType){let v=b?.[m.authType]?.account??[];C=D({authType:m.authType,integrationName:f.id,tenantId:c,kek:o,database:t,extraAccountFields:v,ensureProvisioned:p}),d[f.id].keys=C}let S={database:t,db:g[f.id]?.db??{},$getAccountId:h,...f.options?{options:f.options}:{},...C?{keys:C,authType:m?.authType}:{},tenantId:c,...u?{hub:u}:{}},x=f.endpoints??{},E=f.hooks,k={...i,...f.errorHandlers},P={},T=f.options?.permissions;Lr({endpoints:x,hooks:E,ctx:S,tree:P,pluginId:f.id,errorHandlers:k,currentPath:[],keyBuilder:f.keyBuilder,permissionsConfig:T,endpointMeta:f.endpointMeta,database:t,permissionsOptions:s,tenantId:r,manualConfig:a?{...a,oauthConfig:f.oauthConfig,kek:o,tenantId:c}:void 0,hubConfig:u,plugin:f,kek:o,allPlugins:e,multiTenancy:l?.multiTenancy}),Object.keys(P).length>0&&(d[f.id].api=P),S.endpoints=P;let j=f.webhooks??{},re=f.webhookHooks;if(Object.keys(j).length>0){let v={};Wr({webhooks:j,hooks:re,ctx:S,webhooksTree:v,keyBuilder:f.keyBuilder}),d[f.id].webhooks=v,f.pluginWebhookMatcher&&(d[f.id].pluginWebhookMatcher=f.pluginWebhookMatcher),f.pluginTenantWebhookMatcher&&(d[f.id].pluginTenantWebhookMatcher=f.pluginTenantWebhookMatcher)}}return d.threads=Ni(u,c),d.runs=Li(u,c),d.workflows=ji(u,c),d}function Ki(e,n,t){let r={};for(let o of e){let i=o.options,s=o.authConfig;if(i?.authType){let a=s?.[i.authType]?.integration??[],u=O({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=u}}return r}var xu="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function qi(e){let{permissions:n,approval:t}=e;if(n&&t)throw new Error("createCorsair was given both permissions and approval config. Use permissions only \u2014 approval is deprecated.");return t?(console.warn(`[corsair] ${xu}`),t):n}var Zi=[{method:"GET",pattern:"/ok",handler:async()=>M(200,zn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>M(200,await Je(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>M(201,await Qn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>M(200,await Yn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>M(200,await Ge(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>M(200,await Vn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>M(200,await Xn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>M(200,await Gt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?M(200,await zt(e,t)):M(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>M(200,await et(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>M(200,await nt(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>M(200,await tt(e,n,t))}];(()=>{let e=new Set;for(let n of Zi){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Ru(e,n){let t=e.split("/").filter(Boolean),r=n.split("/").filter(Boolean);if(t.length!==r.length)return null;let o={};for(let i=0;i<t.length;i++){let s=t[i],a=r[i];if(s.startsWith(":"))o[s.slice(1)]=decodeURIComponent(a);else if(s!==a)return null}return o}function Iu(e,n){if(!n)return e;let t=n.endsWith("/")?n.slice(0,-1):n;return e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length):e}async function Su(e){if(!(e.method==="GET"||e.method==="HEAD"||!(e.headers.get("content-type")??"").includes("application/json")))try{let t=await e.text();return t?JSON.parse(t):void 0}catch{throw new I(400,"invalid_json","Request body is not valid JSON")}}var _u="/api/corsair";function Me(e,n={}){let t=n.basePath??_u,r=w(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=Iu(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await Oe(e,o);if(a!=="GET"&&a!=="POST")return M(405,{error:"method_not_allowed",message:`Method ${a} not allowed`});let u=Object.fromEntries(i.searchParams);for(let l of Zi){if(l.method!==a)continue;let c=Ru(l.pattern,s);if(!c)continue;let p=await Su(o);return await l.handler({corsair:e,internal:r,req:o,params:c,query:u,body:p})}throw Pe(`No route for ${a} ${s}`)}catch(i){if(n.onError){let a=await n.onError(i,o);if(a)return a}if(i instanceof I)return ri(i);let s=i instanceof Error?i.message:"Internal server error";return M(500,{error:"internal_error",message:s})}}}function Eu(e){let n=e.get?.("host")??"localhost",t=e.protocol??"http",r=e.originalUrl??e.url,o=`${t}://${n}${r}`,i=new Headers;for(let[u,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let c of l)i.append(u,c);else i.set(u,l);let s=e.method!=="GET"&&e.method!=="HEAD",a={method:e.method,headers:i};return s&&e.body!==void 0&&(a.body=typeof e.body=="string"?e.body:JSON.stringify(e.body),i.has("content-type")||i.set("content-type","application/json")),new Request(o,a)}async function Du(e,n){e.status(n.status),n.headers.forEach((r,o)=>e.setHeader(o,r));let t=Buffer.from(await n.arrayBuffer());e.send(t)}function Gi(e,n){let t=Me(e,n);return async(r,o,i)=>{try{let s=await t(Eu(r));await Du(o,s)}catch(s){i(s)}}}function Ji(e,n){let t=Me(e,n);return r=>t(r.req.raw)}function zi(e,n){let t=Me(e,n);return{GET:t,POST:t,OPTIONS:t}}function Vi(e){let n={[wn]:e};return{ok:zn,tenants:{list:()=>Je(e),create:t=>Qn(e,t),get:t=>Yn(e,t)},plugins:{list:()=>Ge(e),get:t=>Vn(e,t)},connectionStatus:{get:t=>Xn(e,t?.tenantId)},permissions:{get:t=>ci(e,t)},connect:{createLink:t=>et(n,e,t),resolve:t=>nt(n,e,t),oauthCallback:t=>tt(n,e,t)}}}async function Yi(e,n,t,r,o="pending"){if(!e)return null;try{let i=ao(),s=new Date;return await e.db.insertInto("corsair_events").values({id:i,created_at:s,updated_at:s,account_id:n,event_type:t,payload:r,status:o}).execute(),i}catch(i){return console.warn("Failed to log event:",i),null}}async function Ou(e,n,t,r="pending"){try{let o=await e.$getAccountId();return Yi(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as Xi from"https";import*as bt from"querystring";var Mu=["expires_in","refresh_token_expires_in"];function Qi(e){let n={...e};for(let t of Mu){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function Hu(e){try{return Qi(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=bt.parse(e);return!n.access_token&&!n.error?null:Qi({...n})}function $n(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,u)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let c=bt.stringify(l),p={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(c).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let d=Xi.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},g=>{let f="";g.on("data",y=>{f+=y}),g.on("end",()=>{if(g.statusCode!==200){u(new Error(`Token exchange failed (${g.statusCode}): ${f}`));return}let y=Hu(f);y?a(y):u(new Error(`Token endpoint returned non-JSON response: ${f}`))})});d.on("error",g=>u(new Error(`Request failed: ${g.message}`))),d.write(c),d.end()})}var es=" ";function z(e){let n=e;return n._def??n.def??{}}function V(e){let n=e.typeName;if(n)return n;let t=e.type;if(t)return`Zod${t.split("_").map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}`}function J(e){return e.innerType??e.schema??e.out??e.in}function ts(e,n){switch(n){case"ZodPipe":return e.in??e.innerType;case"ZodEffects":return e.schema??e.innerType;case"ZodTransform":return e.schema??e.innerType??e.in;default:return J(e)}}function rs(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function Ct(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Qe(e){return Array.isArray(e.options)?e.options:Array.isArray(e.values)?e.values:e.entries!==null&&typeof e.entries=="object"&&!Array.isArray(e.entries)?Object.values(e.entries):[]}function os(e,n){return e.description??n.description}function Fu(e){let n=e;for(;n;){let t=z(n),r=os(n,t);if(r)return r;let o=V(t);if(Jr(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=ts(t,o);continue}break}}function Jr(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function L(e){let n=z(e),t=V(n);switch(t){case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"Date";case"ZodNull":return"null";case"ZodUnknown":case"ZodAny":return"any";case"ZodLiteral":return String(n.value??Qe(n)[0]??"unknown");case"ZodEnum":return Qe(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=J(n);return r?L(r):"unknown"}case"ZodNullable":{let r=J(n);return`${r?L(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=J(n);return r?L(r):"unknown"}case"ZodArray":{let r=rs(n);if(!r)return"unknown[]";let o=z(r),i=V(o)==="ZodUnion",s=L(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=Ct(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let u=V(z(a));return`${u==="ZodOptional"||u==="ZodNullable"?s+"?":s}: ${L(a)}`}).join(", ")} }`}case"ZodUnion":return Qe(n).map(r=>L(r)).join(" | ");case"ZodIntersection":return`${L(n.left)} & ${L(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=ts(n,t);return r?L(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function ge(e){let n=z(e),t=V(n),r=os(e,n);switch(t){case"ZodString":return{kind:"string",optional:!1,description:r};case"ZodNumber":return{kind:"number",optional:!1,description:r};case"ZodBoolean":return{kind:"boolean",optional:!1,description:r};case"ZodLiteral":{let o=n.value??Qe(n)[0],i=typeof o=="string"||typeof o=="number"||typeof o=="boolean"?o:String(o??"");return{kind:"literal",optional:!1,description:r,value:i}}case"ZodEnum":{let o=Qe(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=J(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=J(n),i=o?ge(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=J(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=rs(n);return{kind:"array",optional:!1,description:r,items:o?ge(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=Ct(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=ge(a);return{kind:"object",optional:!1,description:r,fields:i}}case"ZodRecord":return{kind:"unknown",optional:!1,description:r};case"ZodUnion":{let o=Qe(n);for(let i of o){let s=z(i);if(V(s)==="ZodObject")return{...ge(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=J(n);return o?{...ge(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Ky(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r===-1)return null;let o=t.slice(0,r),i=t.slice(r+1),s=e.find(c=>c.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=ve(s.endpointMeta,a),l=ve(s.endpointSchemas,a);return!u&&!l?null:{input:l?.input?ge(l.input):null,output:l?.output?ge(l.output):null,description:u?.description}}var zr=["equals","contains","startsWith","endsWith","in"],Uu=["equals","gt","gte","lt","lte","in"],Bu=["equals"],Lu=["equals","before","after","between"];function is(e){let n=z(e);switch(V(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=J(n);return r?is(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Vr(e){let n=z(e),t=V(n);if(Jr(t)){let i=J(n);return i?Vr(i):{}}if(t!=="ZodObject")return{};let r=Ct(e,n),o={};for(let[i,s]of Object.entries(r)){let a=is(s);a==="string"?o[i]={type:"string",operators:zr}:a==="number"?o[i]={type:"number",operators:Uu}:a==="boolean"?o[i]={type:"boolean",operators:Bu}:a==="date"&&(o[i]={type:"date",operators:Lu})}return o}function ss(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function qr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];typeof o=="function"?t.push(i.join(".")):o!==null&&typeof o=="object"&&qr(o,i,t)}}function Zr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Gr(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Zr(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&Gr(o,i,t)}}function Yr(e,n){if(n.length===0)return null;let[t,...r]=n,o=Object.entries(e).find(([a])=>a.toLowerCase()===t);if(!o)return null;let[i,s]=o;if(r.length===0)return Zr(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Zr(s)){let a=Yr(s,r);if(a!==null)return[i,...a]}return null}function as(e,n){let t=[];t.push(`${e}({`),t.push(" webhookHooks: {");for(let i=0;i<n.length;i++){let s=" ".repeat(i+2);t.push(`${s}${n[i]}: {`)}let r=" ".repeat(n.length+2),o=r+" ";t.push(`${r}before(ctx, args) {`),t.push(`${o}return { ctx, args };`),t.push(`${r}},`),t.push(`${r}after(ctx, response) {`),t.push(`${r}},`);for(let i=n.length-1;i>=0;i--){let s=" ".repeat(i+2);t.push(`${s}},`)}return t.push(" },"),t.push("})"),t.join(`
|
|
50
|
+
`)}var Nu=new Set(vn);function He(e,n){let t=n?.type??"api",r=n?.plugin;if(r!==void 0){let i=e.find(a=>a.id===r);if(!i)return Nu.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:He(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return Gr(i.webhooks,[],a),a.map(u=>`${i.id}.webhooks.${u}`)}if(t==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(u=>`${i.id}.db.${u}.search`):[]}if(!i.endpoints)return[];let s=[];return qr(i.endpoints,[],s),s.map(a=>`${i.id}.api.${a}`)}let o={};if(t==="webhooks")for(let i of e){if(!i.webhooks)continue;let s=[];Gr(i.webhooks,[],s),o[i.id]=s.map(a=>`${i.id}.webhooks.${a}`)}else if(t==="db")for(let i of e){let s=i.schema?.entities;s&&(o[i.id]=Object.keys(s).map(a=>`${i.id}.db.${a}.search`))}else for(let i of e){if(!i.endpoints)continue;let s=[];qr(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function ve(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function $u(e,n){let t=e.toLowerCase(),r=n.toLowerCase();if(!t.startsWith(`${r}.`)){let i=t.slice(n.length+1),s=i.startsWith(".")?i.slice(1):i;return s.startsWith("api.")&&(s=s.slice(4)),{shortPath:s,lookupKey:s}}let o=e.slice(n.length+1);return o.toLowerCase().startsWith("api.")&&(o=o.slice(4)),{shortPath:o,lookupKey:o.toLowerCase()}}function Kr(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
|
|
51
51
|
${e.join(", ")}`:`${n}:
|
|
52
52
|
`+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
|
|
53
|
-
`)}function
|
|
54
|
-
`)}}}return Kr(He(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let c=i.slice(9);if(s.webhooks){let p=Yr(s.webhooks,c.split("."));if(p!==null){let d=p.join("."),g=
|
|
53
|
+
`)}function qy(e,n){let t=n.toLowerCase(),r=t.indexOf(".");if(r!==-1){let o=t.slice(0,r),i=t.slice(r+1),s=e.find(a=>a.id===o);if(s){if(i.startsWith("db.")){let c=i.slice(3),p=c.lastIndexOf(".");if(p!==-1){let d=c.slice(0,p),g=c.slice(p+1),f=s.schema?.entities;if(g==="search"&&f){let y=ss(f,d);if(y){let[h,m]=y,b=Vr(m),C=[`Search ${o} ${h} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${zr.join(", ")}]`];for(let[S,x]of Object.entries(b))C.push(` ${S}?: ${x.type} [${x.operators.join(", ")}]`);return C.push("}"),C.join(`
|
|
54
|
+
`)}}}return Kr(He(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let c=i.slice(9);if(s.webhooks){let p=Yr(s.webhooks,c.split("."));if(p!==null){let d=p.join("."),g=ve(s.webhookSchemas,d.toLowerCase()),f=g?.response?L(g.response):null,y=[];return g?.description&&y.push(g.description),g?.payload&&y.push(`payload ${wt(Xe(g.payload))}`),f&&y.push(`response: ${f}`),y.push(`usage:
|
|
55
55
|
${as(o,p)}`),y.join(`
|
|
56
56
|
|
|
57
|
-
`)}}return Kr(He(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=
|
|
57
|
+
`)}}return Kr(He(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let u=ve(s.endpointMeta,a),l=ve(s.endpointSchemas,a);if(u||l){let c=[],p=[u?.riskLevel?`[${u.riskLevel}]`:"",u?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),d=[u?.description,p].filter(Boolean).join(" ");return d&&c.push(d),l?.input&&c.push(`input ${wt(Xe(l.input))}`),l?.output&&c.push(`output ${wt(Xe(l.output))}`),c.join(`
|
|
58
58
|
|
|
59
|
-
`)}}}return Kr(He(e),"Path not found. Available operations")}function ns(e){let n=e;for(;;){let t=z(n),r=V(t);if(Jr(r)){let o=J(t);if(!o)return n;n=o;continue}return n}}function Xe(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=ns(e),t=z(n);if(V(t)==="ZodObject"){let o=Ct(n,t),i=[];for(let[s,a]of Object.entries(o)){let u=z(a),l=V(u),c=l==="ZodOptional"||l==="ZodNullable",p=ns(a),d=
|
|
59
|
+
`)}}}return Kr(He(e),"Path not found. Available operations")}function ns(e){let n=e;for(;;){let t=z(n),r=V(t);if(Jr(r)){let o=J(t);if(!o)return n;n=o;continue}return n}}function Xe(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=ns(e),t=z(n);if(V(t)==="ZodObject"){let o=Ct(n,t),i=[];for(let[s,a]of Object.entries(o)){let u=z(a),l=V(u),c=l==="ZodOptional"||l==="ZodNullable",p=ns(a),d=Fu(a);i.push({key:s,optional:c,type:L(p),...d!==void 0?{description:d}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:L(n)}}function wt(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=es.repeat(n+1),r=es.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
|
|
63
|
-
`)}function eo(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...F[n][t],...r])}function
|
|
64
|
-
Schema: ${JSON.stringify(
|
|
62
|
+
${r}}`}return"unknown"}function Wu(e,n){let t=He(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(c=>c.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let c of t){let{shortPath:p,lookupKey:d}=$u(c,n),g=ve(r.endpointMeta,d),f=ve(r.endpointSchemas,d);!g&&!f||o.push({path:c,shortPath:p,description:g?.description,riskLevel:g?.riskLevel,irreversible:g?.irreversible,input:Xe(f?.input),output:Xe(f?.output)})}o.sort((c,p)=>c.path.localeCompare(p.path));let i=[],s=He(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let c of s){let d=c.toLowerCase().slice(n.length+1),g=d.startsWith(".")?d.slice(1):d;if(!g.startsWith("webhooks."))continue;let f=g.slice(9),y=Yr(r.webhooks,f.split("."));if(y===null)continue;let h=y.join("."),m=ve(r.webhookSchemas,h.toLowerCase()),b=m?.response?L(m.response):void 0;i.push({path:c,description:m?.description,payload:Xe(m?.payload),responseType:b,usageExample:as(n,y)})}i.sort((c,p)=>c.path.localeCompare(p.path));let a=[],u=He(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(u)&&l)for(let c of u){let d=c.toLowerCase().slice(n.length+1),g=d.startsWith(".")?d.slice(1):d;if(!g.startsWith("db."))continue;let f=g.slice(3),y=f.lastIndexOf(".");if(y===-1)continue;let h=f.slice(0,y);if(f.slice(y+1)!=="search")continue;let b=ss(l,h);if(!b)continue;let[C,S]=b,x=Vr(S),E=Object.entries(x).map(([k,P])=>({field:k,type:P.type,operators:P.operators}));a.push({path:c,entityName:C,filters:[{field:"entity_id",type:"string",operators:zr},...E]})}return a.sort((c,p)=>c.path.localeCompare(p.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as us}from"crypto";async function ju(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=us(),o=us(),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 Ku}from"crypto";var Pt="https://graph.microsoft.com/v1.0",Qr=2e4,qu=60;async function Zu(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let u=await fetch(`${Pt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Qr)});if(u.ok){let{value:l}=await u.json(),c=(l??[]).filter(p=>p.notificationUrl===n.webhookUrl);await Promise.all(c.map(p=>fetch(`${Pt}/subscriptions/${p.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Qr)}).catch(()=>{})))}}catch{}let o=Ku(),i=new Date(Date.now()+qu*6e4).toISOString(),s=await fetch(`${Pt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Qr),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 cs(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function Gu(e,n){let t=cs(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 Ju(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function ls(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function ds(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 Cn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function zu(e){return Cn(e.body)}function ps(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return Tt(Array.isArray(r)?r:[r])}function gs(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let u of t){let l=Tt(Array.isArray(u)?u:[u]);if(l)return decodeURIComponent(l)}let r=ps({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 u of o){let l=n[u],c=Array.isArray(l)?l[0]:l;if(!(!c||typeof c!="string"))try{let d=(c.startsWith("http")?new URL(c):new URL(`https://example.invalid${c.startsWith("/")?c:`/${c}`}`)).searchParams.get("validationToken");if(d?.trim())return d.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=Cn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return Tt([s?.validationToken])??null}function Vu(e){if(gs(e))return!0;let n=Cn(e.body??e.payload);return ls(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function Tt(e){for(let n of e){let t=ds(n);if(t)return t}}function Yu(e){let t=Cn(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 fs(e){let n=e.database?to(e.database):void 0,t=n&&e.kek?Ki(e.plugins,n,e.kek):kt(!!n,!!e.kek),r=qi(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?xn(e.hub):void 0},i=ni(n),s=Vi(o);if(e.multiTenancy)return Object.assign({withTenant:u=>{if(!u)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let l=jr(e.plugins,{database:n,tenantId:u,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o});return Object.assign(l,{[wn]:o})},keys:t,permissions:i,manage:s},{[wn]:o});let a=jr(e.plugins,{database:n,tenantId:void 0,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o});return Object.assign({},a,{keys:t,permissions:i,manage:s,[wn]:o})}var Qu={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:{}}}},Xr=Qu;async function Wn(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=oo(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 u=lc(e,a.plugins,n),l={...a,database:a.database},c=l.database.db;await gc(c,i);let p=await fc(c,l,u.tenantId,u.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await hc(e,u,n.credentials,l,o,i);let d=await bc(p,u,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let g=fs({plugins:a.plugins,database:c,kek:a.kek,multiTenancy:!0}).withTenant(u.tenantId);await wc(g,a.plugins,d,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
|
|
63
|
+
`)}function eo(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...F[n][t],...r])}function cc(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=R(o);if(!i)continue;let s=eo(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function lc(e,n,t){let r=io(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&&cc(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 ms(e,n){return fe(e)?n===0?!0:Object.values(e).every(t=>ms(t,n-1)):!1}function dc(e){return ms(e,4)}var pc={...uo};function vt(e){if(e instanceof oc){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof uc?vt(r):"unknown";return n}return e instanceof tc?`${vt(e.unwrap())} | null`:e instanceof ic?`${vt(e.unwrap())} | undefined`:e instanceof nc?e.options.join(" | "):e instanceof ac?"string":e instanceof rc?"number":e instanceof Xu?"boolean":e instanceof ec?"date":e instanceof sc?"jsonb":"unknown"}async function gc(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(pc))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
|
|
64
|
+
Schema: ${JSON.stringify(vt(i),null,2)}`)}async function fc(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let u=a.id,l=R(a),c=await e.selectFrom("corsair_integrations").selectAll().where("name","=",u).executeTakeFirst();if(!c){let y=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:y,name:u,config:{},created_at:i,updated_at:i}).execute(),c=await e.selectFrom("corsair_integrations").selectAll().where("id","=",y).executeTakeFirst(),o(`[corsair:setup] Created integration: ${u}`)}let p=l?a.authConfig?.[l]?.integration??[]:[],d=l?a.authConfig?.[l]?.account??[]:[],g=l&&c?O({authType:l,integrationName:u,kek:n.kek,database:n.database,extraIntegrationFields:p}):void 0;if(c&&!c.dek&&g&&(await g.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${u}`)),!c||!l||!g)continue;let f;if(r){let y=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",c.id).executeTakeFirst();if(!y){let h=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:h,tenant_id:t,integration_id:c.id,config:{},created_at:i,updated_at:i}).execute(),y=await e.selectFrom("corsair_accounts").selectAll().where("id","=",h).executeTakeFirst(),o(`[corsair:setup] Created account: ${u}`)}f=y&&D({authType:l,integrationName:u,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:d}),y&&f&&!y.dek&&(await f.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${u}`))}s.set(u,{pluginId:u,authType:l,integration:g,account:f,integrationFields:[...F[l].integration,...p],accountFields:r?[...F[l].account,...d]:[]})}return s}function yc(e){if(!fe(e))return;let n=e.keys;return fe(n)?n:void 0}function mc(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function hc(e,n,t,r,o,i){let s=yc(e),a=n.provisionAccounts?mc(e,n.tenantId):void 0;for(let[u,l]of Object.entries(t)){let c=r.plugins.find(m=>m.id===u);if(!c){i(`[corsair:setup] Unknown plugin '${u}' \u2014 skipping credentials.`);continue}let p=R(c);if(!p){i(`[corsair:setup] Plugin '${u}' has no auth type \u2014 skipping credentials.`);continue}let d=eo(c,p,"integration"),g=eo(c,p,"account"),f=s?.[u],y=a?.[u],h=fe(y)?y.keys:void 0;for(let[m,b]of Object.entries(l))if(b){if(d.has(m)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${u}.${m}' 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 C=N(f,`set_${m}`);if(!C){i(`[corsair:setup] Cannot set integration field '${m}' for '${u}'.`);continue}await C(b),o(`[corsair:setup] Set ${u} integration.${m}`);continue}if(g.has(m)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${u}.${m}' on a multi-tenant instance`);let C=N(h,`set_${m}`);if(!C){i(`[corsair:setup] Cannot set account field '${m}' for '${u}'.`);continue}await C(b),o(`[corsair:setup] Set ${u} account.${m} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${m}' for plugin '${u}'.`)}}}var ys=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function kc(e,n,t,r,o,i,s,a,u){let l=[],c=[];for(let d of o){if(ys.has(d))continue;let g=N(t,`get_${d}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||l.push(d)}if(r&&i.length>0)for(let d of i){if(ys.has(d))continue;let g=N(r,`get_${d}`);if(!g)continue;let f=null;try{let y=await g();f=typeof y=="string"?y:null}catch{}f||c.push(d)}let p=l.length===0&&c.length===0;if(p)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 d=[...l,...c];if(u==="cli"){let g=d.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 c){let y=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;g.push(` await ${y}.keys.set_${f}(value)`)}a(g.join(`
|
|
66
|
-
`))}}return p}async function
|
|
66
|
+
`))}}return p}async function bc(e,n,t,r){let o=new Set;for(let i of e.values())await kc(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function wc(e,n,t,r,o){if(!dc(Xr)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=Xr,s=new Set(n.map(a=>a.id));for(let[a,u]of Object.entries(i)){if(!s.has(a))continue;if(!t.has(a)){r(`[corsair:setup] Skipping backfill for '${a}' \u2014 auth not configured.`);continue}let l=fe(e)?e[a]:void 0,c=fe(l)?l.api:void 0;if(c)for(let[p,d]of Object.entries(u))for(let[g,f]of Object.entries(d)){r(`[corsair:setup] Backfilling ${a} \u203A ${p}.${g}...`);try{let y=fe(c)?c[p]:void 0;await N(y,g)?.(f)}catch(y){o(`[corsair:setup] ${a} \u203A ${p}.${g} failed: `+(y instanceof Error?y.message:String(y)))}}}}export{lo as a,ye as b,Rt as c,tn as d,po as e,go as f,me as g,Re as h,ie as i,Ue as j,Be as k,he as l,St as m,yo as n,sn as o,se as p,xn as q,H as r,Rn as s,Le as t,In as u,Sn as v,_n as w,En as x,ho as y,Dn as z,ke as A,ae as B,ue as C,Z as D,Et as E,un as F,be as G,ce as H,cn as I,O as J,D as K,Ro as L,Io as M,Wn as N,hc as O,Ce as P,Ot as Q,We as R,je as S,Ht as T,Ln as U,Bo as V,_e as W,B as X,Ft as Y,gn as Z,Wo as _,ra as $,jn as aa,nd as ba,qo as ca,Zo as da,Go as ea,Ut as fa,Kn as ga,zo as ha,Vo as ia,Bt as ja,qn as ka,Zn as la,Ze as ma,Jn as na,Kt as oa,ei as pa,qt as qa,Yt as ra,Qt as sa,rt as ta,Xt as ua,ze as va,Ve as wa,ot as xa,it as ya,fn as za,er as Aa,nr as Ba,st as Ca,yn as Da,at as Ea,ut as Fa,Te as Ga,Ye as Ha,yi as Ia,sr as Ja,ar as Ka,De as La,kn as Ma,bn as Na,mt as Oa,lr as Pa,dr as Qa,fr as Ra,yr as Sa,mr as Ta,hr as Ua,kr as Va,Oe as Wa,W as Xa,br as Ya,xi as Za,Ri as _a,wr as $a,Cr as ab,Pr as bb,Tr as cb,vr as db,Ar as eb,xr as fb,Rr as gb,Ir as hb,Sr as ib,_r as jb,Er as kb,Dr as lb,Or as mb,Mr as nb,Me as ob,Gi as pb,Ji as qb,zi as rb,Yi as sb,Ou as tb,$n as ub,Ky as vb,He as wb,qy as xb,wt as yb,Wu as zb,ju as Ab,Pt as Bb,Zu as Cb,cs as Db,Gu as Eb,Ju as Fb,ls as Gb,ds as Hb,Cn as Ib,zu as Jb,ps as Kb,gs as Lb,Vu as Mb,Tt as Nb,Yu as Ob,wn as Pb,fs as Qb};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-
|
|
2
|
-
export { f as PermissionLookupInput } from '../../types-
|
|
3
|
-
import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-
|
|
1
|
+
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-C24LhkXl.js';
|
|
2
|
+
export { f as PermissionLookupInput } from '../../types-C24LhkXl.js';
|
|
3
|
+
import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-Dt339hBs.js';
|
|
4
4
|
import '../../index-eydqYIn0.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ea as a,fa as b,ga as c}from"./chunk-
|
|
1
|
+
import{ea as a,fa as b,ga as c}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{c as createHubConnectSession,b as createHubConnectSessionForPlugin,a as postHubConnectSession};
|
package/dist/core.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-
|
|
1
|
+
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-B_P6rcu8.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-
|
|
4
|
-
export { g as AccountFieldNames, a6 as AgentReply, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, M as BeforeHookResult, n as BindEndpoints, ae as BindWebhooks, ac as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, af as BoundWebhook, ag as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, N as CorsairKeyBuilder, Q as CorsairKeyBuilderBase, ah as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, S as CorsairPluginContext, U as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a7 as CorsairThreadsNamespace, ai as CorsairWebhook, aj as CorsairWebhookHandler, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, a8 as CreateThreadResult, V as EndpointHooks, X as EndpointMetaEntry, E as EndpointPathsOf, Y as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, i as IntegrationFieldNames, Z as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, _ as PermissionMode, $ as PermissionPolicy, P as PluginAuthConfig, a0 as PluginEndpointMeta, a1 as PluginPermissionsConfig, am as RawWebhookRequest, K as ReadonlyForbiddenError, a2 as RequiredPluginEndpointMeta, a3 as RequiredPluginEndpointSchemas, a4 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, a9 as ThreadHandle, aa as ThreadMessage, ab as ThreadSummary, T as TokenResponse, ad as UnionToIntersection, a5 as WebhookHooks, an as WebhookPathsOf, ao as WebhookRequest, ap as WebhookResponse, W as WebhookTenantMatch, aq as WebhookTree, G as assertReadonlyAllowed, l as exchangeCodeForTokens, J as isReadonlyScopeActive, L as runReadonly } from './index-
|
|
5
|
-
export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-
|
|
6
|
-
import { A as AuthTypes } from './types-
|
|
7
|
-
export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-
|
|
3
|
+
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-DcJhvFt7.js';
|
|
4
|
+
export { g as AccountFieldNames, a6 as AgentReply, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, M as BeforeHookResult, n as BindEndpoints, ae as BindWebhooks, ac as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, af as BoundWebhook, ag as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, N as CorsairKeyBuilder, Q as CorsairKeyBuilderBase, ah as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, S as CorsairPluginContext, U as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a7 as CorsairThreadsNamespace, ai as CorsairWebhook, aj as CorsairWebhookHandler, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, a8 as CreateThreadResult, V as EndpointHooks, X as EndpointMetaEntry, E as EndpointPathsOf, Y as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, i as IntegrationFieldNames, Z as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, _ as PermissionMode, $ as PermissionPolicy, P as PluginAuthConfig, a0 as PluginEndpointMeta, a1 as PluginPermissionsConfig, am as RawWebhookRequest, K as ReadonlyForbiddenError, a2 as RequiredPluginEndpointMeta, a3 as RequiredPluginEndpointSchemas, a4 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, a9 as ThreadHandle, aa as ThreadMessage, ab as ThreadSummary, T as TokenResponse, ad as UnionToIntersection, a5 as WebhookHooks, an as WebhookPathsOf, ao as WebhookRequest, ap as WebhookResponse, W as WebhookTenantMatch, aq as WebhookTree, G as assertReadonlyAllowed, l as exchangeCodeForTokens, J as isReadonlyScopeActive, L as runReadonly } from './index-DcJhvFt7.js';
|
|
5
|
+
export { A as AuthMissingError, D as DocSchemaFieldRow, a as DocSchemaShape, b as DocsApiEndpoint, c as DocsDbEntity, d as DocsDbFilterField, e as DocsWebhook, E as EndpointSchemaResult, I as IntrospectPluginForDocsResult, L as ListOperationsOptions, g as PermissionRequiredError, P as PluginDocsIntrospection, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, o as extractMicrosoftGraphValidationToken, p as firstString, f as formatDocSchemaShape, q as getHeader, i as introspectPluginForDocs, s as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, u as readQueryParam, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-Dq3dd_Zs.js';
|
|
6
|
+
import { A as AuthTypes } from './types-C24LhkXl.js';
|
|
7
|
+
export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-C24LhkXl.js';
|
|
8
8
|
import 'kysely';
|
|
9
9
|
import './index-eydqYIn0.js';
|
|
10
10
|
import 'zod';
|
package/dist/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ab as B,B as d,Bb as C,C as e,Cb as D,D as f,Db as E,E as g,Eb as F,F as h,Fb as G,G as i,Gb as H,H as j,Hb as I,I as k,Ib as J,J as l,Jb as K,K as m,Kb as L,L as n,Lb as M,M as o,Mb as N,Nb as O,Ob as P,Pb as Q,Qb as R,Xa as v,a,b,ja as p,ma as q,na as r,oa as s,pa as t,qa as u,sb as w,tb as x,ub as y,yb as z,zb as A}from"./chunk-
|
|
1
|
+
import{Ab as B,B as d,Bb as C,C as e,Cb as D,D as f,Db as E,E as g,Eb as F,F as h,Fb as G,G as i,Gb as H,H as j,Hb as I,I as k,Ib as J,J as l,Jb as K,K as m,Kb as L,L as n,Lb as M,M as o,Mb as N,Nb as O,Ob as P,Pb as Q,Qb as R,Xa as v,a,b,ja as p,ma as q,na as r,oa as s,pa as t,qa as u,sb as w,tb as x,ub as y,yb as z,zb as A}from"./chunk-IT5JH3MM.js";import{h as c}from"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{v as AuthMissingError,c as BASE_AUTH_FIELDS,Q as CORSAIR_INTERNAL,C as MS_GRAPH_API_BASE,q as PermissionRequiredError,a as ProviderDisplayNames,r as ReadonlyForbiddenError,J as asRecord,u as assertReadonlyAllowed,G as collectPluginWebhookMatchers,m as createAccountKeyManager,R as createCorsair,l as createIntegrationKeyManager,P as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,y as exchangeCodeForTokens,M as extractMicrosoftGraphValidationToken,O as firstString,z as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,H as getHeader,B as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,A as introspectPluginForDocs,N as isMicrosoftGraphValidationHandshake,t as isReadonlyScopeActive,w as logEvent,x as logEventFromContext,E as matchWebhookPlugin,F as matchWebhookPluginAndTenant,D as msGraphSubscribe,k as reEncryptConfig,K as readBodyRecord,L as readQueryParam,p as resolveConnectLink,s as runReadonly,I as toExternalId};
|
package/dist/hub.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { A as AuthTypes } from './types-
|
|
2
|
-
export { i as formatProviderDisplayName } from './types-
|
|
3
|
-
import { as as HubOAuthMode, at as HubConnectSessionResult, au as HubPermissionSessionResult, H as HubConfig, av as HubConfigInput, aw as HubConnectSessionInput, ax as HubListProjectConnectionsInput, A as AccountKeyManagerFor, ay as HubPermissionSessionInput } from './index-
|
|
4
|
-
export { az as DEFAULT_HUB_API_URL, aA as HubEnvironmentSlug } from './index-
|
|
5
|
-
import { k as TunnelType, R as RunResultPayload, P as ProbeResultPayload, g as ProcessCorsairRequest, m as WebhookTenantLink } from './index-
|
|
6
|
-
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-
|
|
7
|
-
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-
|
|
1
|
+
import { A as AuthTypes } from './types-C24LhkXl.js';
|
|
2
|
+
export { i as formatProviderDisplayName } from './types-C24LhkXl.js';
|
|
3
|
+
import { as as HubOAuthMode, at as HubConnectSessionResult, au as HubPermissionSessionResult, H as HubConfig, av as HubConfigInput, aw as HubConnectSessionInput, ax as HubListProjectConnectionsInput, A as AccountKeyManagerFor, ay as HubPermissionSessionInput } from './index-DcJhvFt7.js';
|
|
4
|
+
export { az as DEFAULT_HUB_API_URL, aA as HubEnvironmentSlug } from './index-DcJhvFt7.js';
|
|
5
|
+
import { k as TunnelType, R as RunResultPayload, P as ProbeResultPayload, g as ProcessCorsairRequest, m as WebhookTenantLink } from './index-CsNw9hYU.js';
|
|
6
|
+
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-CsNw9hYU.js';
|
|
7
|
+
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-BJtn0HMO.js';
|
|
8
8
|
import './index-eydqYIn0.js';
|
|
9
9
|
import 'zod';
|
|
10
10
|
import './db.js';
|
package/dist/hub.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$a as ea,A as z,Aa as P,Ba as Q,Ca as R,Da as S,Ea as T,Fa as U,Ga as V,Ha as W,R as A,Ra as X,Sa as Y,Ta as Z,Ua as _,Va as $,Wa as aa,Ya as ba,Za as ca,_a as da,ab as fa,b as a,bb as ga,c as b,cb as ha,d as c,db as ia,e as d,eb as ja,f as e,fb as ka,g as f,ga as B,gb as la,h as g,ha as C,hb as ma,i as h,ia as D,ib as na,j as i,jb as oa,k as j,ka as E,kb as pa,l as k,la as F,lb as qa,m as l,mb as ra,n as m,nb as sa,o as n,p as o,q as p,r as q,ra as G,s as r,sa as H,t as s,ta as I,u as t,ua as J,v as u,va as K,w as v,wa as L,x as w,xa as M,y as x,ya as N,z as y,za as O}from"./chunk-
|
|
1
|
+
import{$a as ea,A as z,Aa as P,Ba as Q,Ca as R,Da as S,Ea as T,Fa as U,Ga as V,Ha as W,R as A,Ra as X,Sa as Y,Ta as Z,Ua as _,Va as $,Wa as aa,Ya as ba,Za as ca,_a as da,ab as fa,b as a,bb as ga,c as b,cb as ha,d as c,db as ia,e as d,eb as ja,f as e,fb as ka,g as f,ga as B,gb as la,h as g,ha as C,hb as ma,i as h,ia as D,ib as na,j as i,jb as oa,k as j,ka as E,kb as pa,l as k,la as F,lb as qa,m as l,mb as ra,n as m,nb as sa,o as n,p as o,q as p,r as q,ra as G,s as r,sa as H,t as s,ta as I,u as t,ua as J,v as u,va as K,w as v,wa as L,x as w,xa as M,y as x,ya as N,z as y,za as O}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{f as BROWSER_DELIVERY_TTL_MS,n as DEFAULT_HUB_API_URL,o as HubNotConfiguredError,V as ManagedOAuthDeliveryError,g as SIGNED_TUNNEL_REPLAY_WINDOW_MS,ca as attachManagedRefreshAuth,i as buildBrowserDeliveryRedirectUrl,l as buildClientBridgeBrowserDeliveryUrl,ea as createConnectSessionJti,ja as createConnectTokenJti,B as createHubConnectSession,E as createHubPermissionSession,da as createHubRouteHandlers,pa as createPermissionSessionJti,h as createSignedTokenJti,ia as decodeConnectSessionTokenFromPath,oa as decodeConnectTokenFromPath,sa as decodePermissionTokenFromPath,Q as deliverConnectCreateLink,U as deliverSignedEnvelope,S as describeDeliveryNetworkError,na as encodeConnectTokenForPath,O as extractConnectLinkFromDeliveryAck,H as extractProbeFromDeliveryAck,G as extractRunFromDeliveryAck,N as extractSyncFromDeliveryAck,F as formatHubApprovalMessage,a as formatProviderDisplayName,T as formatServerDeliveryError,fa as getConnectSessionExpiryMs,C as getConnectStatusForTenant,ka as getConnectTokenExpiryMs,q as getHubConfig,ba as getManagedAccessToken,X as handleHubDeliveryGet,Y as handleHubDeliveryPost,_ as handleHubDeliveryRequest,Z as hubDeliveryToResponse,s as inferHubEnvironmentSlug,b as isLoopbackUrl,M as isServerDeliveryAckSuccessful,D as listHubProjectConnections,p as normalizeHubConfig,P as parseConnectLinkFromDeliveryBody,t as parseConnectSessionResponse,x as parseConnectStatusResponse,y as parseHubApiErrorBody,w as parseOAuthRefreshResponse,v as parsePermissionSessionResponse,u as parseProjectConnectionsResponse,L as parseServerDeliveryAckBody,R as parseSyncFromDeliveryBody,m as prepareClientBridgeDeliveryTransport,W as processManagedOAuthDelivery,A as registerHubWebhookTenantLink,c as resolveDeliveryTransport,z as resolveHubDeliveryUrl,r as resolveHubOAuthCallbackUrl,$ as respondToHubDelivery,aa as respondToHubDeliveryFromRequest,j as signBrowserDeliveryToken,ga as signConnectSessionToken,la as signConnectToken,I as signDeliveryEnvelope,qa as signPermissionToken,d as usesBrowserDelivery,e as validateProductionDeliveryUrl,k as verifyBrowserDeliveryToken,ha as verifyConnectSessionToken,ma as verifyConnectToken,J as verifyDeliveryEnvelope,ra as verifyPermissionToken,K as verifySignedTunnelDelivery};
|
|
@@ -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-
|
|
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-DcJhvFt7.js';
|
|
3
3
|
|
|
4
4
|
declare const CORSAIR_INTERNAL: unique symbol;
|
|
5
5
|
type CorsairInternalConfig = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthTypes } from './types-
|
|
2
|
-
import { W as WebhookTenantMatch } from './index-
|
|
1
|
+
import { A as AuthTypes } from './types-C24LhkXl.js';
|
|
2
|
+
import { W as WebhookTenantMatch } from './index-DcJhvFt7.js';
|
|
3
3
|
import { a as CorsairAccount } from './index-eydqYIn0.js';
|
|
4
4
|
import { CorsairDatabase } from './db.js';
|
|
5
5
|
|
|
@@ -233,6 +233,7 @@ type OAuthCallbackTunnelPayload = {
|
|
|
233
233
|
*/
|
|
234
234
|
plugin?: string;
|
|
235
235
|
tenantId?: string;
|
|
236
|
+
callbackParams?: Record<string, string>;
|
|
236
237
|
};
|
|
237
238
|
type OAuthTokensTunnelPayload = {
|
|
238
239
|
plugin: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ZodTypeAny } from 'zod';
|
|
2
2
|
import { CorsairDatabase, CorsairDatabaseInput } from './db.js';
|
|
3
3
|
import { CorsairPluginSchema, PluginEntityClients } from './orm.js';
|
|
4
|
-
import { A as AuthTypes, l as AllErrors, M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult, g as AllProviders } from './types-
|
|
4
|
+
import { A as AuthTypes, l as AllErrors, M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult, g as AllProviders } from './types-C24LhkXl.js';
|
|
5
5
|
import { C as CorsairPermission } from './index-eydqYIn0.js';
|
|
6
6
|
|
|
7
7
|
type HubEnvironmentSlug = 'development' | 'production';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { C as CorsairClientOptions, a as CorsairManagementClient } from './types-
|
|
2
|
-
export { b as CorsairClientError } from './types-
|
|
3
|
-
export { c as createCorsair } from './index-
|
|
4
|
-
import { e as CorsairSingleTenantClient, C as CorsairPlugin, d as CorsairTenantWrapper, m as CorsairClient, z as CorsairPermissionsNamespace, ag as BoundWebhookTree, am as RawWebhookRequest, al as CorsairWebhookTenantMatcher, ap as WebhookResponse } from './index-
|
|
5
|
-
export { ar as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions, K as ReadonlyForbiddenError, L as runReadonly } from './index-
|
|
6
|
-
import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-
|
|
7
|
-
export { A as AuthMissingError, g as PermissionRequiredError, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, p as firstString, f as formatDocSchemaShape, q as getHeader, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-
|
|
1
|
+
import { C as CorsairClientOptions, a as CorsairManagementClient } from './types-Dt339hBs.js';
|
|
2
|
+
export { b as CorsairClientError } from './types-Dt339hBs.js';
|
|
3
|
+
export { c as createCorsair } from './index-B_P6rcu8.js';
|
|
4
|
+
import { e as CorsairSingleTenantClient, C as CorsairPlugin, d as CorsairTenantWrapper, m as CorsairClient, z as CorsairPermissionsNamespace, ag as BoundWebhookTree, am as RawWebhookRequest, al as CorsairWebhookTenantMatcher, ap as WebhookResponse } from './index-DcJhvFt7.js';
|
|
5
|
+
export { ar as CorsairManageNamespace, b as CorsairManualConfig, a as CorsairPermissionsOptions, K as ReadonlyForbiddenError, L as runReadonly } from './index-DcJhvFt7.js';
|
|
6
|
+
import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-Dq3dd_Zs.js';
|
|
7
|
+
export { A as AuthMissingError, g as PermissionRequiredError, k as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, l as asRecord, h as collectPluginWebhookMatchers, n as decodePubSubData, p as firstString, f as formatDocSchemaShape, q as getHeader, m as matchWebhookPlugin, j as matchWebhookPluginAndTenant, t as readBodyRecord, r as resolveConnectLink, v as toExternalId } from './tenant-match-utils-Dq3dd_Zs.js';
|
|
8
8
|
export { SetupCorsairOptions, setupCorsair } from './setup.js';
|
|
9
|
-
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-
|
|
10
|
-
import { B as BaseProviders } from './types-
|
|
11
|
-
export { c as ConnectLink, a as ConnectionStatus, d as CreateConnectLinkInput, C as CreateTenantInput, M as ManagementOk, e as OAuthCallbackInput, O as OAuthCallbackResult, f as PermissionLookupInput, b as PermissionRecord, k as PluginConnectionState, P as PluginInfo, R as ResolvedConnectLink, T as Tenant } from './types-
|
|
9
|
+
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-CsNw9hYU.js';
|
|
10
|
+
import { B as BaseProviders } from './types-C24LhkXl.js';
|
|
11
|
+
export { c as ConnectLink, a as ConnectionStatus, d as CreateConnectLinkInput, C as CreateTenantInput, M as ManagementOk, e as OAuthCallbackInput, O as OAuthCallbackResult, f as PermissionLookupInput, b as PermissionRecord, k as PluginConnectionState, P as PluginInfo, R as ResolvedConnectLink, T as Tenant } from './types-C24LhkXl.js';
|
|
12
12
|
import './db.js';
|
|
13
13
|
import 'kysely';
|
|
14
14
|
import './index-eydqYIn0.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as B,b as J}from"./chunk-XLNT2UI2.js";import{Db as E,Eb as v,Fb as _,Gb as $,Hb as M,Ia as R,Ib as D,Jb as H,N as y,Nb as N,Ob as j,Pb as g,Qa as O,Qb as q,S as h,T as k,U as x,V as P,Xa as T,ja as b,ma as S,na as w,oa as I,ob as A,pb as L,qb as F,rb as W,vb as l,wb as c,xb as d,yb as m}from"./chunk-
|
|
1
|
+
import{a as B,b as J}from"./chunk-XLNT2UI2.js";import{Db as E,Eb as v,Fb as _,Gb as $,Hb as M,Ia as R,Ib as D,Jb as H,N as y,Nb as N,Ob as j,Pb as g,Qa as O,Qb as q,S as h,T as k,U as x,V as P,Xa as T,ja as b,ma as S,na as w,oa as I,ob as A,pb as L,qb as F,rb as W,vb as l,wb as c,xb as d,yb as m}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";function s(n){let t=n[g];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function Y(n,t){let r=c(s(n),t);return typeof r=="string"?r:Array.isArray(r)?r.join(`
|
|
2
2
|
`):Object.values(r).flat().join(`
|
|
3
3
|
`)}function z(n,t){return d(s(n),t)}function G(n,t){return l(s(n),t)}var K=Symbol.for("corsair:internal");function Q(n,t){let r=n;for(let e of t){if(!r||typeof r!="object")return null;r=r[e]}return typeof r=="function"?r:null}function C(n){return n[K]?.database}async function U(n,t){let r=new Date().toISOString(),e=await n.permissions.find_by_token(t);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<r){let o=C(n);return o&&await o.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let f=e.tenant_id??"default",a=(n.withTenant?n.withTenant(f):n)[e.plugin];if(!a?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let p=Q(a.api,e.endpoint.split("."));if(!p)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let o=typeof e.args=="string"?JSON.parse(e.args):e.args,i=await p(o);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:i}}catch(o){let i=o instanceof Error?o.message:String(o),u=C(n);return u&&await u.db.updateTable("corsair_permissions").set({status:"failed",error:i,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:i}}}export{T as AuthMissingError,B as CorsairClientError,S as PermissionRequiredError,w as ReadonlyForbiddenError,D as asRecord,_ as collectPluginWebhookMatchers,q as createCorsair,J as createCorsairClient,j as decodePubSubData,U as executePermission,N as firstString,m as formatDocSchemaShape,$ as getHeader,z as getSchema,G as getStructuredSchema,Y as listOperations,A as managementHandler,E as matchWebhookPlugin,v as matchWebhookPluginAndTenant,O as processCorsair,R as processWebhook,H as readBodyRecord,k as resolveAccountFromWebhookLink,b as resolveConnectLink,P as resolveTenantFromWebhookLink,x as resolveTenantIdFromWebhookLink,I as runReadonly,h as setWebhookTenantLink,y as setupCorsair,L as toExpressHandler,M as toExternalId,F as toHonoHandler,W as toNextJsHandler};
|
package/dist/oauth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as OAuthConfig } from './index-
|
|
1
|
+
import { O as OAuthConfig } from './index-DcJhvFt7.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import './db.js';
|
|
4
4
|
import 'kysely';
|
|
@@ -6,7 +6,7 @@ import './index-eydqYIn0.js';
|
|
|
6
6
|
import 'pg';
|
|
7
7
|
import 'postgres';
|
|
8
8
|
import './orm.js';
|
|
9
|
-
import './types-
|
|
9
|
+
import './types-C24LhkXl.js';
|
|
10
10
|
|
|
11
11
|
type OAuthState = {
|
|
12
12
|
plugin: string;
|
|
@@ -70,6 +70,7 @@ type ProcessOAuthCallbackOptions = {
|
|
|
70
70
|
/** Required when `trusted` is true. Ignored otherwise (state is decoded). */
|
|
71
71
|
plugin?: string;
|
|
72
72
|
tenantId?: string;
|
|
73
|
+
callbackParams?: Record<string, string>;
|
|
73
74
|
};
|
|
74
75
|
type ProcessOAuthCallbackResult = {
|
|
75
76
|
plugin: string;
|
package/dist/oauth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as h,P as a,Q as b,W as c,X as d,Y as e,Z as f,_ as g}from"./chunk-
|
|
1
|
+
import{$ as h,P as a,Q as b,W as c,X as d,Y as e,Z as f,_ as g}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.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{N as a,O as b}from"./chunk-
|
|
1
|
+
import{N as a,O as b}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aa as a,ba as b,ca as c,da as d}from"./chunk-
|
|
1
|
+
import{aa as a,ba as b,ca as c,da as d}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as buildConnectPluginManifest,a as buildConnectPluginManifestFromContext,d as ensureConnectAccountRows,c as ensureConnectAccountRowsFromContext};
|
package/dist/setup.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { a as CorsairInternalConfig } from './index-
|
|
1
|
+
import { a as CorsairInternalConfig } from './index-B_P6rcu8.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-
|
|
3
|
+
import { C as CorsairPlugin, e as CorsairSingleTenantClient, d as CorsairTenantWrapper } from './index-DcJhvFt7.js';
|
|
4
4
|
import 'kysely';
|
|
5
5
|
import './index-eydqYIn0.js';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import 'pg';
|
|
8
8
|
import 'postgres';
|
|
9
9
|
import './orm.js';
|
|
10
|
-
import './types-
|
|
10
|
+
import './types-C24LhkXl.js';
|
|
11
11
|
|
|
12
12
|
/** Plugin id → credential field → value (from CLI `field=value` pairs). */
|
|
13
13
|
type SetupCredentials = Record<string, Record<string, string>>;
|
package/dist/setup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as a,O as b}from"./chunk-
|
|
1
|
+
import{N as a,O as b}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{b as applySetupCredentials,a as setupCorsair};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Y as EndpointRiskLevel, C as CorsairPlugin, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, am as RawWebhookRequest, W as WebhookTenantMatch } from './index-
|
|
2
|
-
import { g as AllProviders } from './types-
|
|
1
|
+
import { Y as EndpointRiskLevel, C as CorsairPlugin, ak as CorsairWebhookMatcher, al as CorsairWebhookTenantMatcher, am as RawWebhookRequest, W as WebhookTenantMatch } from './index-DcJhvFt7.js';
|
|
2
|
+
import { g as AllProviders } from './types-C24LhkXl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Error thrown when an endpoint call is blocked pending user approval or by
|
package/dist/tunnel.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { B as BrowserDeliveryPayload, R as RunResultPayload, P as ProbeResultPayload } from './index-
|
|
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-
|
|
3
|
-
export { v as verifyBrowserDeliveryToken } from './browser-delivery-
|
|
4
|
-
import './types-
|
|
1
|
+
import { B as BrowserDeliveryPayload, R as RunResultPayload, P as ProbeResultPayload } from './index-CsNw9hYU.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-CsNw9hYU.js';
|
|
3
|
+
export { v as verifyBrowserDeliveryToken } from './browser-delivery-BJtn0HMO.js';
|
|
4
|
+
import './types-C24LhkXl.js';
|
|
5
5
|
import './index-eydqYIn0.js';
|
|
6
6
|
import 'zod';
|
|
7
|
-
import './index-
|
|
7
|
+
import './index-DcJhvFt7.js';
|
|
8
8
|
import './db.js';
|
|
9
9
|
import 'kysely';
|
|
10
10
|
import 'pg';
|
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,S as b,T as c,U as d,V as e,l as a}from"./chunk-
|
|
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,S as b,T as c,U as d,V as e,l as a}from"./chunk-IT5JH3MM.js";import"./chunk-WDF3YE27.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.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,4 +1,4 @@
|
|
|
1
|
-
import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-
|
|
1
|
+
import { M as ManagementOk, T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, f as PermissionLookupInput, b as PermissionRecord, d as CreateConnectLinkInput, c as ConnectLink, R as ResolvedConnectLink, e as OAuthCallbackInput, O as OAuthCallbackResult } from './types-C24LhkXl.js';
|
|
2
2
|
|
|
3
3
|
type CorsairClientOptions = {
|
|
4
4
|
/** Origin + base path of the mounted handler, e.g. 'https://api.example.com/api/corsair'. */
|