corsair 0.1.103 → 0.1.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { B as BrowserDeliveryPayload } from './index-CXpDAEOf.js';
1
+ import { B as BrowserDeliveryPayload } from './index-CXNdPXR3.js';
2
2
 
3
3
  /**
4
4
  * Browser (client) delivery — hub redirects the user's browser to the app with `?d=<token>`.
@@ -0,0 +1,38 @@
1
+ import{a as Ur,b as de,c as Br,d as w,e as U,f as Lr,g as j,h as H,i as S,j as mn,k as Nr,l as $r,m as mt,n as jr,o as Wr}from"./chunk-BPFUYXOD.js";import{a as Fr}from"./chunk-IGGCNGU2.js";var hn=["agentql","algolia","ahrefs","airtable","amplitude","asana","bitwarden","bluesky","box","cal","calendly","cloudflare","confluence","cursor","datadog","deepseek","discord","dodopayments","dropbox","exa","figma","firecrawl","fireflies","gemini","github","gitlab","gmail","googlecalendar","googledocs","googledrive","googlemeet","googlesheets","grafana","hackernews","hubspot","insightoai","instagram","intercom","jira","linear","linkedin","mailchimp","monday","neon","notion","onedrive","openai","openweathermap","oura","outlook","pagerduty","perplexityai","posthog","razorpay","reddit","resend","sentry","sharepoint","slack","spotify","strava","stripe","supabase","tally","tavily","teams","telegram","todoist","trello","twilio","twitter","twitterapiio","typeform","vapi","xquik","youtube","zendesk","zohomail","zoom"],Kr={agentql:"AgentQL",algolia:"Algolia",ahrefs:"Ahrefs",airtable:"Airtable",amplitude:"Amplitude",asana:"Asana",bitwarden:"Bitwarden",bluesky:"Bluesky",box:"Box",cal:"Cal",calendly:"Calendly",cloudflare:"Cloudflare",confluence:"Confluence",cursor:"Cursor",datadog:"Datadog",deepseek:"DeepSeek",discord:"Discord",dodopayments:"Dodo Payments",dropbox:"Dropbox",exa:"Exa",figma:"Figma",firecrawl:"Firecrawl",fireflies:"Fireflies",gemini:"Gemini",github:"GitHub",gitlab:"GitLab",gmail:"Gmail",googlecalendar:"Google Calendar",googledocs:"Google Docs",googledrive:"Google Drive",googlemeet:"Google Meet",googlesheets:"Google Sheets",grafana:"Grafana",hackernews:"Hacker News",hubspot:"HubSpot",insightoai:"Insighto.ai",instagram:"Instagram",intercom:"Intercom",jira:"Jira",linear:"Linear",linkedin:"LinkedIn",mailchimp:"Mailchimp",monday:"Monday",neon:"Neon",notion:"Notion",onedrive:"OneDrive",openai:"OpenAI",openweathermap:"OpenWeatherMap",oura:"Oura",outlook:"Outlook",pagerduty:"PagerDuty",posthog:"PostHog",razorpay:"Razorpay",reddit:"Reddit",resend:"Resend",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",xquik:"XQuik",youtube:"YouTube",zendesk:"Zendesk",zohomail:"Zoho Mail",zoom:"Zoom",perplexityai:"Perplexity AI"};function pe(e){let n=Kr[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}import{randomUUID as Bi}from"crypto";var Di="corsair:client-bridge";function ht(e){return new URL(e).origin}function De(e){let n=JSON.stringify({type:Di,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(ht(e.hubOrigin));return`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><script>
2
+ (function () {
3
+ var message = ${n};
4
+ var targetOrigin = ${t};
5
+ if (window.parent && window.parent !== window) {
6
+ window.parent.postMessage(message, targetOrigin);
7
+ }
8
+ })();
9
+ </script></body></html>`}var Oi=new Set(["localhost","127.0.0.1","[::1]","::1"]);function bt(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Oi.has(n)}catch{return!1}}function ze(e){return e==="development"?"browser":"server"}function qr(e){return ze(e)==="browser"}function Zr(e){return bt(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as Ui}from"crypto";var Gr=new Set(["oauth.callback","oauth.tokens","webhook","permission.approve","permission.deny","auth.credentials","integration.credentials","connect.create_link","connections.sync"]),ge=60*1e3,Te=300*1e3;import{createHmac as Mi,randomBytes as Hi,timingSafeEqual as Fi}from"crypto";function oe(){return Hi(16).toString("base64url")}function Ve(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Mi("sha256",t).update(e).digest("base64url")}function Q(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=Ve(o,t);try{if(!Fi(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 bn(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=Ve(i,n);return`${i}.${s}`}function Ye(e,n,t){let r=Math.floor(Date.now()/1e3);return bn(e,n,r+Math.floor(t/1e3))}function Pe(e){return decodeURIComponent(e)}function kt(e){return encodeURIComponent(e)}function Jr(e){let n=e.trim();return n.length>0?n:null}function Oe(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function Me(e,n){if(!Jr(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??Ui(16).toString("base64url"),iat:t,exp:t+Math.floor(ge/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=Ve(o,n);return`${o}.${i}`}function fe(e,n){return Jr(n)?Q(e,n):null}function Li(e){let n=ht(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 Ct(e){let n=Me(Li(e),e.signingSecret);return Oe(e.deliveryUrl,n)}function zr(e){if(ze(e.environmentSlug)==="server")return{transport:"server"};if(!e.hubOrigin)throw new Error(`hubOrigin is required for development ${e.deliveryMode} delivery`);let t=Bi(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:Ct(r)}}var Qe="https://auth.corsair.dev";var ie=class extends Error{constructor(){super("Hub is not configured. Pass hub: { projectApiKey, signingSecret } to createCorsair()."),this.name="HubNotConfiguredError"}};function kn(e){let n=(e.apiUrl?.trim()||Qe).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(/\/$/,"")}}function Ni(e){return e.apiUrl.trim().length>0&&e.projectApiKey.trim().length>0&&e.signingSecret.trim().length>0}function M(e){let n=w(e).hub;if(!n||!Ni(n))throw new ie;return n}function Vr(e){return e.replace(/\/$/,"")}function Cn(e){return e.oauthCallbackUrl?Vr(e.oauthCallbackUrl.trim()):`${Vr(e.apiUrl)}/oauth/callback`}function He(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 x(e){return typeof e=="string"&&e.length>0}function $i(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function ji(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function wn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!x(n.connectUrl)||!x(n.token)||!x(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:x(n.environmentId)?n.environmentId:n.projectId};return x(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function vn(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(!x(r.tenantId)||!x(r.plugin)||!$i(r.status)||!ji(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:x(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function Tn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!x(n.approvalUrl)||!x(n.token)||!x(n.projectId)||!x(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 Pn(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(x(n.access_token))return{access_token:n.access_token,refresh_token:x(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:x(n.scope)?n.scope:void 0};throw new Error(x(n.error)?x(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Wi(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Ki(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;x(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 qi(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 Yr(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!x(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(!x(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=Ki(o.fields),a=Wi(o.missingRequiredFields),c=qi(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:x(o.providerName)?o.providerName:o.plugin,authKind:i,status:c,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function An(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}var Zi="3000",Gi="/api/corsair";function Ji(e){return e.replace(/\/$/,"")}function ye(e){let n=e?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(n){let r=/^https?:\/\//i.test(n)?n:`https://${n}`;return Ji(r)}return`http://localhost:${process.env.PORT?.trim()||Zi}${Gi}`}function Qr(e){return e.replace(/\/$/,"")}function wt(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return ye()}catch{return null}}function Xr(e){let n=wt(e);return n?{"x-corsair-delivery-url":n}:{}}async function eo(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 no(e,n,t){if(n===404&&t)return t;let r=An(e);return r||`Hub API returned HTTP ${n}`}async function W(e){let n=Qr(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...Xr(e.hub)},body:JSON.stringify(e.body)}),r=await eo(t);if(!t.ok)throw new Error(no(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function xn(e){let n=Qr(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...Xr(e.hub)}}),r=await eo(t);if(!t.ok)throw new Error(no(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as to,createDecipheriv as ro,randomBytes as In,scrypt as zi}from"crypto";import{promisify as Vi}from"util";var oo=Vi(zi),Sn="aes-256-gcm",io=12,Rn=16,Yi=16,Xe=32;function se(){return In(Xe).toString("base64")}async function ae(e,n){let t=In(Yi),r=await oo(n,t,Xe),o=In(io),i=to(Sn,r,o,{authTagLength:Rn}),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 q(e,n){let[t,r,o,i]=e.split(":");if(!t||!r||!o||!i)throw new Error("Invalid encrypted DEK format");let s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=Buffer.from(i,"base64"),u=await oo(n,s,Xe),p=ro(Sn,u,a,{authTagLength:Rn});return p.setAuthTag(c),Buffer.concat([p.update(l),p.final()]).toString("utf8")}function vt(e,n){let t=Buffer.from(n,"base64"),r=In(io),o=to(Sn,t,r,{authTagLength:Rn}),i=Buffer.concat([o.update(e,"utf8"),o.final()]),s=o.getAuthTag();return[r.toString("base64"),s.toString("base64"),i.toString("base64")].join(":")}function en(e,n){let[t,r,o]=e.split(":");if(!t||!r||!o)throw new Error("Invalid encrypted data format");let i=Buffer.from(n,"base64"),s=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),c=Buffer.from(o,"base64"),l=ro(Sn,i,s,{authTagLength:Rn});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function me(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=vt(o,n);return t}function ce(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=en(o,n);return t}function nn(e,n,t){let r=ce(e,n);return me(r,t)}function so(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 Tt=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};function E(e){let{authType:n,integrationName:t,kek:r,database:o,extraIntegrationFields:i=[]}=e,s=[...H[n].integration,...i],a=null,c={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:Tt(m.config),dek:m.dek??null},a},updateIntegration:async m=>{let h=await c.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,u=async()=>{if(l)return l;let m=await c.getIntegration();if(!m.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return l=await q(m.dek,r),l},p=async()=>{let m=await c.getIntegration(),h=await u(),b=m.config;return!b||Object.keys(b).length===0?{}:ce(b,h)},g=Promise.resolve(),d=m=>{let h=g.then(()=>y(m));return g=h.catch(()=>{}),h},y=async m=>{let h=await u(),b;try{b=await p()}catch(T){console.error(`[corsair] Failed to decrypt config for integration "${t}", starting fresh:`,T),b={}}let v={...b};for(let[T,A]of Object.entries(m))A===null?delete v[T]:v[T]=A;let O=me(v,h);await c.updateIntegration({config:O})};return{get_dek:u,issue_new_dek:async()=>{let m=await c.getIntegration(),h=se(),b={};if(m.dek){let O=await q(m.dek,r),T=m.config;T&&Object.keys(T).length>0&&(b=nn(T,O,h))}let v=await ae(h,r);return await c.updateIntegration({config:b,dek:v}),l=h,h},...so(p,d,s)}}function _(e){let{authType:n,integrationName:t,tenantId:r,kek:o,database:i,extraAccountFields:s=[],ensureProvisioned:a}=e,c=[...H[n].account,...s],l=null,u=null,p=async()=>{if(u)return u;let k=!1;for(;;){let C=await i.db.selectFrom("corsair_integrations").selectAll().where("name","=",t).executeTakeFirst();if(!C){if(!k&&a){k=!0,await a();continue}throw new Error(`Integration "${t}" not found. Make sure to create the integration first.`)}return u={id:C.id,config:Tt(C.config),dek:C.dek??null},u}},g={kek:o,integrationName:t,tenantId:r,getIntegration:p,getAccount:async()=>{if(l)return l;let k=!1;for(;;){let C=await p(),P=await i.db.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",r).where("integration_id","=",C.id).executeTakeFirst();if(!P){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:P.id,config:Tt(P.config),dek:P.dek??null},l}},updateAccount:async k=>{let C=await g.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","=",C.id).execute(),l=null}},d=null,y=null,f=async()=>{if(d)return d;let k=await g.getAccount();if(!k.dek)throw new Error(`No DEK found for account (tenant: "${r}", integration: "${t}"). Initialize the account first.`);return d=await q(k.dek,o),d},m=async()=>{if(y)return y;let k=await g.getIntegration();if(!k.dek)throw new Error(`No DEK found for integration "${t}". Initialize the integration first.`);return y=await q(k.dek,o),y},h=async()=>{let k=await g.getAccount(),C=await f(),P=k.config;return!P||Object.keys(P).length===0?{}:ce(P,C)},b=async()=>{let k=await g.getIntegration(),C=await m(),P=k.config;return!P||Object.keys(P).length===0?{}:ce(P,C)},v=Promise.resolve(),O=k=>{let C=v.then(()=>T(k));return v=C.catch(()=>{}),C},T=async k=>{let C=await f(),P;try{P=await h()}catch(I){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,I),P={}}let N={...P};for(let[I,$]of Object.entries(k))$===null?delete N[I]:N[I]=$;let te=me(N,C);await g.updateAccount({config:te})},A={get_dek:f,issue_new_dek:async()=>{let k=await g.getAccount(),C=se(),P={};if(k.dek){let te=await q(k.dek,o),I=k.config;I&&Object.keys(I).length>0&&(P=nn(I,te,C))}let N=await ae(C,o);return await g.updateAccount({config:P,dek:N}),d=C,C},...so(h,O,c)};return n==="oauth_2"&&(A.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}}),A}async function ao(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=se(),i=await ae(o,t);return await e.db.updateTable("corsair_integrations").set({dek:i,updated_at:new Date}).where("id","=",r.id).execute(),o}async function co(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=se(),a=await ae(s,r);return await e.db.updateTable("corsair_accounts").set({dek:a,updated_at:new Date}).where("id","=",i.id).execute(),s}var Qi=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function he(e){return Qi.has(e)}function Xi(e,n){return he(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function es(e){return!he(e)}function ns(e){switch(e){case"oauth_2":case"managed":return["access_token","refresh_token"];case"api_key":return["api_key"];case"bot_token":return["bot_token"]}}function ts(e,n){return ns(e).every(r=>n.find(i=>i.level==="account"&&i.name===r)?.configured??!1)}async function uo(e,n){if(!e)return!1;let t=j(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function rs(e,n){let r=e.authConfig?.[n]?.integration??[];return[...H[n].integration,...r]}function os(e,n){let r=e.authConfig?.[n]?.account??[];return[...H[n].account,...r]}function is(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:ts(n,t),fields:t,missingRequiredFields:r}}async function Ae(e,n,t){let r=S(n);if(!r||!e.database||!e.kek)return null;let o=t.trim()||"default",i=n.authConfig,s=i?.[r]?.integration??[],a=i?.[r]?.account??[],c=E({authType:r,integrationName:n.id,kek:e.kek,database:e.database,extraIntegrationFields:s}),l=_({authType:r,integrationName:n.id,tenantId:o,kek:e.kek,database:e.database,extraAccountFields:a}),u=rs(n,r),p=os(n,r),g=[];for(let d of u)g.push({name:d,level:"integration",required:Xi(r,d),configured:await uo(c,d)});for(let d of p)g.push({name:d,level:"account",required:es(d),configured:await uo(l,d)});return is(n.id,r,g)}async function tn(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 Ae(e,s,r);a&&i.push(a)}return i}function _n(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var lo=Symbol.for("corsair:internal"),po=new WeakMap;function ss(e){let n=po.get(e);return n||(n=new Map,po.set(e,n)),n}function as(e){return e.multiTenancy?{withTenant:()=>({}),[lo]:e}:{[lo]:e}}async function En(e,n){if(!e.database)return;let t=n.trim()||"default",r=ss(e),o=t,i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-ZXL3B2P6.js");await a(as(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import{ZodBoolean as us,ZodDate as ls,ZodEnum as ds,ZodNullable as ps,ZodNumber as gs,ZodObject as fs,ZodOptional as ys,ZodRecord as ms,ZodString as hs,ZodType as bs}from"zod";var cs={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:{}}}},Pt=cs;async function On(e,n){let t=[],r=n?.silent??!1,o=d=>{t.push(d),r||console.log(d)},i=d=>{t.push(d),r||console.warn(d)},s=n?.caller??"script",a=Br(e);if(!a)throw new Error("setupCorsair: invalid corsair instance");if(!a.database)throw new Error("setupCorsair: a database must be configured on the corsair instance");let c=Cs(e,a.plugins,n),l={...a,database:a.database},u=l.database.db;await Ts(u,i);let p=await Ps(u,l,c.tenantId,c.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Is(e,c,n.credentials,l,o,i);let g=await Rs(p,c,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let d=yo({plugins:a.plugins,database:u,kek:a.kek,multiTenancy:!0}).withTenant(c.tenantId);await _s(d,a.plugins,g,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
10
+ `)}function At(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...H[n][t],...r])}function ks(e,n){if(!e)return!1;for(let[t,r]of Object.entries(e)){let o=n.find(a=>a.id===t);if(!o)continue;let i=S(o);if(!i)continue;let s=At(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function Cs(e,n,t){let r=Lr(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&&ks(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 fo(e,n){return de(e)?n===0?!0:Object.values(e).every(t=>fo(t,n-1)):!1}function ws(e){return fo(e,4)}var vs={...jr};function Dn(e){if(e instanceof fs){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof bs?Dn(r):"unknown";return n}return e instanceof ps?`${Dn(e.unwrap())} | null`:e instanceof ys?`${Dn(e.unwrap())} | undefined`:e instanceof ds?e.options.join(" | "):e instanceof hs?"string":e instanceof gs?"number":e instanceof us?"boolean":e instanceof ls?"date":e instanceof ms?"jsonb":"unknown"}async function Ts(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(vs))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
11
+ Schema: ${JSON.stringify(Dn(i),null,2)}`)}async function Ps(e,n,t,r,o){let i=new Date,s=new Map;for(let a of n.plugins){let c=a.id,l=S(a),u=await e.selectFrom("corsair_integrations").selectAll().where("name","=",c).executeTakeFirst();if(!u){let f=crypto.randomUUID();await e.insertInto("corsair_integrations").values({id:f,name:c,config:{},created_at:i,updated_at:i}).execute(),u=await e.selectFrom("corsair_integrations").selectAll().where("id","=",f).executeTakeFirst(),o(`[corsair:setup] Created integration: ${c}`)}let p=l?a.authConfig?.[l]?.integration??[]:[],g=l?a.authConfig?.[l]?.account??[]:[],d=l&&u?E({authType:l,integrationName:c,kek:n.kek,database:n.database,extraIntegrationFields:p}):void 0;if(u&&!u.dek&&d&&(await d.issue_new_dek(),o(`[corsair:setup] Issued integration DEK: ${c}`)),!u||!l||!d)continue;let y;if(r){let f=await e.selectFrom("corsair_accounts").selectAll().where("tenant_id","=",t).where("integration_id","=",u.id).executeTakeFirst();if(!f){let m=crypto.randomUUID();await e.insertInto("corsair_accounts").values({id:m,tenant_id:t,integration_id:u.id,config:{},created_at:i,updated_at:i}).execute(),f=await e.selectFrom("corsair_accounts").selectAll().where("id","=",m).executeTakeFirst(),o(`[corsair:setup] Created account: ${c}`)}y=f&&_({authType:l,integrationName:c,tenantId:t,kek:n.kek,database:n.database,extraAccountFields:g}),f&&y&&!f.dek&&(await y.issue_new_dek(),o(`[corsair:setup] Issued account DEK: ${c}`))}s.set(c,{pluginId:c,authType:l,integration:d,account:y,integrationFields:[...H[l].integration,...p],accountFields:r?[...H[l].account,...g]:[]})}return s}function As(e){if(!de(e))return;let n=e.keys;return de(n)?n:void 0}function xs(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Is(e,n,t,r,o,i){let s=As(e),a=n.provisionAccounts?xs(e,n.tenantId):void 0;for(let[c,l]of Object.entries(t)){let u=r.plugins.find(h=>h.id===c);if(!u){i(`[corsair:setup] Unknown plugin '${c}' \u2014 skipping credentials.`);continue}let p=S(u);if(!p){i(`[corsair:setup] Plugin '${c}' has no auth type \u2014 skipping credentials.`);continue}let g=At(u,p,"integration"),d=At(u,p,"account"),y=s?.[c],f=a?.[c],m=de(f)?f.keys:void 0;for(let[h,b]of Object.entries(l))if(b){if(g.has(h)){if(n.multiTenant&&n.tenantIdProvided)throw new Error(`[corsair:setup] '${c}.${h}' 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 v=j(y,`set_${h}`);if(!v){i(`[corsair:setup] Cannot set integration field '${h}' for '${c}'.`);continue}await v(b),o(`[corsair:setup] Set ${c} integration.${h}`);continue}if(d.has(h)){if(n.multiTenant&&!n.tenantIdProvided)throw new Error(`setupCorsair: tenantId is required to set account-level credential '${c}.${h}' on a multi-tenant instance`);let v=j(m,`set_${h}`);if(!v){i(`[corsair:setup] Cannot set account field '${h}' for '${c}'.`);continue}await v(b),o(`[corsair:setup] Set ${c} account.${h} (tenant=${n.tenantId})`);continue}i(`[corsair:setup] Unknown credential field '${h}' for plugin '${c}'.`)}}}var go=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Ss(e,n,t,r,o,i,s,a,c){let l=[],u=[];for(let g of o){if(go.has(g))continue;let d=j(t,`get_${g}`);if(!d)continue;let y=null;try{let f=await d();y=typeof f=="string"?f:null}catch{}y||l.push(g)}if(r&&i.length>0)for(let g of i){if(go.has(g))continue;let d=j(r,`get_${g}`);if(!d)continue;let y=null;try{let f=await d();y=typeof f=="string"?f:null}catch{}y||u.push(g)}let p=l.length===0&&u.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 g=[...l,...u];if(c==="cli"){let d=g.map(y=>`${y}=VALUE`).join(" ");a(`[corsair:setup] '${e}' (${n}) needs credentials. Run:
12
+ corsair setup --${e} ${d}`)}else{let d=[`[corsair:setup] '${e}' (${n}) needs credentials. Call:`];for(let y of l)d.push(` await corsair.keys.${e}.set_${y}(value)`);for(let y of u){let f=s.provisionAccounts?s.tenantId==="default"?`corsair.${e}`:`corsair.withTenant(${JSON.stringify(s.tenantId)}).${e}`:`corsair.withTenant(<tenant>).${e}`;d.push(` await ${f}.keys.set_${y}(value)`)}a(d.join(`
13
+ `))}}return p}async function Rs(e,n,t,r){let o=new Set;for(let i of e.values())await Ss(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function _s(e,n,t,r,o){if(!ws(Pt)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=Pt,s=new Set(n.map(a=>a.id));for(let[a,c]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=de(e)?e[a]:void 0,u=de(l)?l.api:void 0;if(u)for(let[p,g]of Object.entries(c))for(let[d,y]of Object.entries(g)){r(`[corsair:setup] Backfilling ${a} \u203A ${p}.${d}...`);try{let f=de(u)?u[p]:void 0;await j(f,d)?.(y)}catch(f){o(`[corsair:setup] ${a} \u203A ${p}.${d} failed: `+(f instanceof Error?f.message:String(f)))}}}}async function mo(e){if(!w(e).database)throw new Error("A database must be configured to provision Corsair integrations");await On(e,{silent:!0})}async function xe(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await En(t,n)}var Es=Symbol.for("corsair:internal"),Ds=new Set(["access_token","refresh_token","expires_at","scope"]);function Os(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ms(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!he(t)&&!Ds.has(t)):n.filter(t=>!he(t))}function ho(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:!1}}function bo(e){return{[Es]:ho(e)}}async function Mn(e,n,t={}){let r=Cn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=ho(e),a=bo(e);for(let c of e.plugins){if(i&&!i.has(c.id))continue;let l=S(c);if(!l)continue;let u=Os(l),p=t.providerNameOverrides?.[c.id]??pe(c.id),g=await Ae(s,c,n),d=mn(c,l),y=Ms(l,d),f={plugin:c.id,providerName:p,authKind:u,alreadyConfigured:g?.connected??!1};if(y.length>0&&(f.credentialFields=y),u==="oauth"){let h=t.oauthModeOverrides?.[c.id]??(l==="managed"?"managed":"byo");if(f.oauthMode=h,!t.skipOAuthUrlGeneration&&h!=="managed")try{let b=await xt(a,c.id,{tenantId:n,redirectUri:r,hubConnect:!0});f.oauthUrl=b.url}catch(b){f.setupError=b instanceof Error?b.message:`Could not prepare OAuth for ${c.id}`}}o.push(f)}return o}async function wu(e,n,t={}){let r=w(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return Mn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function It(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await xe(bo(e),n)}async function vu(e,n){await xe(e,n)}async function ko(e,n){let t=He(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return t==="development"&&(r.deliveryUrl=ye({deliveryUrl:n.deliveryUrl})),W({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:wn})}async function St(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e};await It(t,n.tenantId);let r=await Mn(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 ko(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function Hn(e,n){let t=w(e),r=M(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r};await It(o,n.tenantId);let i=n.plugin?[n.plugin]:void 0,s=n.plugin&&n.oauthMode?{[n.plugin]:n.oauthMode}:void 0,a=n.plugin&&n.providerName?{[n.plugin]:n.providerName}:void 0,c=await Mn(o,n.tenantId,{pluginIds:i,oauthModeOverrides:s,providerNameOverrides:a});if(c.length===0)throw new Error(n.plugin?`Plugin '${n.plugin}' is not configured on this Corsair instance`:"No plugins are configured on this Corsair instance");return ko(r,{tenantId:n.tenantId,plugins:c,deliveryUrl:n.deliveryUrl})}function Co(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Hs(e,n){return n&&!n.has(e.id)?!1:S(e)!==null}async function wo(e,n,t={}){let r=w(e),o=n.trim()||"default",i=t.pluginIds?.length?new Set(t.pluginIds):null,s=await tn(r,o,{pluginIds:t.pluginIds}),a=new Map(s.map(l=>[l.plugin,l])),c=r.plugins.filter(l=>Hs(l,i)).map(l=>{let u=S(l),p=a.get(l.id);return p?{plugin:l.id,providerName:pe(l.id),authKind:Co(u),status:p.status,connected:p.connected,fields:p.fields.map(g=>({name:g.name,level:g.level,required:g.required,configured:g.configured})),missingRequiredFields:p.missingRequiredFields}:{plugin:l.id,providerName:pe(l.id),authKind:Co(u),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:c}}async function vo(e,n){let t=M(e);return xn({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:vn})}import*as rn from"crypto";function be(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Rt(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 Fe(e,n){let t=rn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var _t=600*1e3;function Fn(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=rn.createHmac("sha256",n).update(r).digest("base64url"),s=Buffer.from(o,"base64url"),a=Buffer.from(i,"base64url");return s.length!==a.length||!rn.timingSafeEqual(s,a)?null:Rt(r,{maxAgeMs:_t})}function Ue(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}import*as To from"querystring";function Ie(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}?${To.stringify(i)}`}var Z=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function Fs(e){let n=e.oauthConfig;if(!n)throw new Z("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Et(e,n){let t=w(e,()=>new Z("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new Z("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new Z("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=Fn(n,t.kek);if(!o)throw new Z("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=U(t,i,g=>new Z("plugin_not_found",g)),c=Fs(a),u=await E({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!u)throw new Z("client_id_not_configured",`client_id not configured for '${i}'`);let p=Ie({oauthConfig:c,clientId:u,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:c.providerName,oauthUrl:p,state:n}}import{randomBytes as Bs}from"crypto";import{v4 as Ls}from"uuid";async function Un(e,n){let t=He(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 t==="development"&&(r.deliveryUrl=ye({deliveryUrl:n.deliveryUrl})),W({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:Tn})}function Bn(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Dt="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 Mt(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Po(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Ot(e){return Bn(e)}async function Ht(e,n){if(Mt(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Po(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Un(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:Us(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function Us(e){try{return JSON.parse(e)}catch{return e}}async function Ln(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Ht(e,n);return{...n,approvalUrl:r}}async function Ft(e){let{permissionsOptions:n,manual:t,hub:r,permissionId:o,permissionToken:i,plugin:s,endpoint:a,args:c,tenantId:l,expiresAt:u,operationPath:p}=e;if(n?.formatAsyncMessage)return n.formatAsyncMessage({token:i,id:o,plugin:s,endpoint:a,args:c});let d=await Ht({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(c),tenant_id:l,expires_at:u});return Mt(t)?d?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:d}):Ot(d):Dt:r?d?Ot(d):`Action '${p}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Dt}var Ns={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 $s(e,n,t){return t!==void 0?t:Ns[n][e]}function Ut(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 xo(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 Ao(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 Io(e){let n=$s(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}'.`,`
14
+ Action: ${r}`,`
15
+ 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 y=e.db,f=a.id;return{result:"allow",onComplete:async()=>{await y.db.updateTable("corsair_permissions").set({status:"completed",updated_at:new Date}).where("id","=",f).execute()}}}return a.status==="executing"?{result:"allow"}:(console.log(`[corsair/${e.pluginId}] '${e.endpointPath}' blocked \u2014 approval already pending.`,`
16
+ Action: ${r}`,`
17
+ Permission ID: ${a.id}`,`
18
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ao(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let c=Ls(),l=Bs(32).toString("hex"),u=e.timeoutMs??600*1e3,p=new Date(Date.now()+u).toISOString();return await e.db.db.insertInto("corsair_permissions").values({id:c,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.`,`
19
+ Action: ${r}`,`
20
+ Permission ID: ${c}`,`
21
+ Permission token: ${l}`,`
22
+ Expires at: ${p}`,`
23
+ Use the token to approve or deny this request.`),(typeof e.approvalMode=="function"?e.approvalMode():e.approvalMode)==="synchronous"?Ao(e.db,c,u):{result:"blocked",reason:"pending",id:c,token:l,expiresAt:p}}var R=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 D(e,n){return new Response(JSON.stringify(n),{status:e,headers:{"content-type":"application/json"}})}function So(e){let n={error:e.code,message:e.message,...e.extra};return D(e.status,n)}function ke(e){return new R(404,"not_found",e)}function ue(e,n={}){return new R(400,"bad_request",e,n)}function Ro(e,n){return U(e,n,t=>ke(t))}async function _o(e,n){let t=e.options?.authType;if(!t||!n.database||!n.kek)return{configured:!1,missingFields:[]};let r=E({authType:t,integrationName:e.id,kek:n.kek,database:n.database}),o=H[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,u)=>s[u]==null),c;return t==="oauth_2"?c=!a.includes("client_id")&&!a.includes("client_secret"):c=a.length===0,{configured:c,missingFields:a}}async function Eo(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await _o(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 Nn(){return{ok:!0}}async function Be(e){return Promise.all(e.plugins.map(n=>Eo(n,e)))}async function $n(e,n){let t=Ro(e,n);return Eo(t,e)}async function js(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 Do(e,n){let t=await js(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Le(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 jn(e,n){if(!n)throw ue("Tenant id must be a non-empty string");return Do(e,n)}async function Wn(e,n){let t=n?.id?.trim();if(!t)throw ue("Tenant id is required",{missingFields:["id"]});return Do(e,t)}async function Kn(e,n){let t=n?.trim()||"default",r={},o=await tn(e,t);for(let i of o)r[i.plugin]=_n(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 Bt(e,n){if(!e.database)throw ke(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw ke(`Permission '${n}' not found`);return Ln(e,t)}function Ws(e){if(!e.oauthConfig)throw ue(`Plugin '${e.id}' has no oauthConfig`)}function Ks(e){if(!e.manual)throw new R(500,"connect_not_configured","createCorsair was not given manual config. Set { manual: { baseUrl, redirectUri } } to enable manual connect routes.");return e.manual}function Lt(e){let n=Ks(e);if(!n.baseUrl?.trim()||!n.redirectUri?.trim())throw new R(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 qs(e){let n=!!e.hub,t=Ue(e.manual);if(!n&&!t)throw new R(500,"connect_not_configured","createCorsair was not given connect config. Set hub: { ... } for Hub mode, or manual: { baseUrl, redirectUri } for manual connect.")}function Oo(e){if(!e.database||!e.kek)throw new R(500,"database_not_configured","A database and kek are required to issue connect links.")}async function Zs(e,n){let t=n?.plugin?.trim();if(!t)throw ue("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=Ro(e,t);Ws(o);let i=Lt(e);Oo(e);let s=await _o(o,e);if(!s.configured)throw new R(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=Fe(be(t,r),e.kek),c;try{c=new URL(i.baseUrl)}catch{throw new R(500,"connect_misconfigured","manual.baseUrl is not a valid URL. Set a full URL including protocol (e.g. https://app.example.com/connect).")}return c.searchParams.set("state",a),{connectUrl:c.toString(),expiresAt:new Date(Date.now()+_t).toISOString()}}async function Gs(e,n,t){Oo(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 Hn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function qn(e,n,t){return qs(n),n.hub?Gs(e,n,t):Zs(n,t)}async function Zn(e,n,t){if(n.hub&&!Ue(n.manual))throw new R(400,"hub_mode","resolve is not used with hub config. Redirect users to connectUrl from createLink.");let r=t?.trim();if(!r)throw ue("state is required",{missingFields:["state"]});Lt(n);try{return await Et(e,r)}catch(o){if(o instanceof Z)switch(o.code){case"invalid_state":throw ue("Invalid or expired state");case"client_id_not_configured":throw new R(400,"missing_credentials","OAuth client_id is not configured for this plugin",{missingFields:["client_id"]});case"no_redirect_uri":break}throw new R(500,"resolve_failed","Could not resolve connect link. Check server logs for details.")}}async function Gn(e,n,t){if(n.hub&&!Ue(n.manual))throw new R(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 ue("Missing required fields",{missingFields:i});let s=Lt(n),{processOAuthCallback:a}=await import("./oauth.js");try{return await a(e,{code:r,state:o,redirectUri:s.redirectUri})}catch(c){if(c instanceof Error&&c.name==="OAuthCallbackError")switch(c.code){case"invalid_state":throw ue("Invalid or expired state");case"credentials_not_configured":throw new R(400,"missing_credentials","OAuth client credentials are not configured for this plugin",{missingFields:["client_id","client_secret"]})}throw new R(502,"oauth_callback_failed","OAuth callback did not complete. Check server logs for details.")}}async function Nt(e,n){if(!e.database)throw ke("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw ke("Permission not found");return Ln(e,t)}async function Mo(e,n){return"id"in n?Bt(e,n.id):Nt(e,n.token)}import{createCipheriv as ea,createDecipheriv as wl,randomBytes as Bo,scryptSync as na}from"crypto";import{createHmac as $t,randomUUID as Js,timingSafeEqual as Fo}from"crypto";function Uo(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function Jn(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=$t("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":Js()}}}function jt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=Uo(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Te)return!1;let i=$t("sha256",n).update(e.body).digest("hex");try{return Fo(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function Ne(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=Uo(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)>Te)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=$t("sha256",n).update(e.body).digest("hex");try{if(!Fo(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 $e(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function zn(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function Vn(e){let n=e.sync?.encrypted;return typeof n!="string"||!n.trim()?null:{encrypted:n.trim()}}function on(e){let n=e.connectUrl?.trim();return n?{connectUrl:n,expiresAt:e.expiresAt}:null}function Wt(e){return on($e(e))}async function Kt(e){let n=await Xn({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=$e(n.body),r=zn({httpOk:n.ok,status:n.status,body:t}),o=on(t);if(!r||!o)throw new Error(Qn({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function Yn(e){return Vn($e(e))}function zs(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 Ho(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var Vs="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",Ys="Check the delivery URL configured for this environment.";function Qs(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})`}. ${Vs}`}function Xs(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${Ys}`}function sn(e,n){let t=zs(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 Qn(e){if(e.status===0)return e.ack.error?e.ack.error:e.body.startsWith("Could not reach")?e.body:sn(e.deliveryUrl,new Error(e.body||"Delivery request failed"));if(e.status===401||e.status===403)return Qs(e);if(e.status===404)return Xs(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}): ${Ho(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${Ho(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function Xn(e){let{body:n,headers:t}=Jn(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:sn(e.deliveryUrl,r)}}}var ta="aes-256-gcm",ra=12,oa=16,ia=16,sa=32;function aa(e,n){return na(e.trim(),n,sa)}function qt(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=Bo(ia),o=aa(t,r),i=Bo(ra),s=ea(ta,o,i,{authTagLength:oa}),a=JSON.stringify(e),c=Buffer.concat([s.update(a,"utf8"),s.final()]),l=s.getAuthTag();return[r.toString("base64"),i.toString("base64"),l.toString("base64"),c.toString("base64")].join(":")}var ca=["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 Zt(e){if(e instanceof Ur)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!ca.some(t=>n.includes(t))}function ua(e){if(!e)return[];let n=S(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!he(r)):[]}async function an(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to sync connections from the app");await On(e,{silent:!0});let[r,o]=await Promise.all([Le(t),Be(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=ua(t.plugins.find(c=>c.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 qt(i,n)}async function et(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},{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-L7VOSJF5.js"),{postHubConnectSession:i}=await import("./connect-EOKSLJEB.js"),s={plugins:n.plugins,database:n.database,kek:n.kek,hub:e};await o(s,t.tenantId);let a=await r(s,t.tenantId,{pluginIds:t.pluginIds});if(a.length===0)throw new Error("No connectable plugins found for this tenant");let c=a.find(l=>l.setupError);if(c)throw new Error(c.setupError??`Could not prepare connect link for ${c.plugin}`);return i(e,{tenantId:t.tenantId,plugins:a})}var X=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function nt(e,n){let t=w(e,()=>new X("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new X("no_database","Database not configured");let r=U(t,n.plugin,u=>new X("plugin_not_found",u)),o=S(r);if(!o)throw new X("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new X("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await xe(e,n.tenantId);let i=new Set(mn(r,o)),a=r.authConfig?.[o]?.account??[],c=_({authType:o,integrationName:n.plugin,tenantId:n.tenantId,kek:t.kek,database:t.database,extraAccountFields:a}),l=0;for(let[u,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(u))throw new X("invalid_credentials",`Unknown credential field '${u}' for plugin '${n.plugin}'`);let g=j(c,`set_${u}`);if(!g)throw new X("invalid_credentials",`Cannot set credential field '${u}' for plugin '${n.plugin}'`);await g(p.trim()),l+=1}if(l===0)throw new X("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var ee=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function Gt(e,n){let t=w(e,()=>new ee("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new ee("no_database","Database not configured");let r=U(t,n.plugin,u=>new ee("plugin_not_found",u)),o=S(r);if(!o)throw new ee("invalid_credentials",`Plugin '${r.id}' has no authType configured`);await mo(e);let i=new Set(Nr(r,o)),a=r.authConfig?.[o]?.integration??[],c=E({authType:o,integrationName:n.plugin,kek:t.kek,database:t.database,extraIntegrationFields:a}),l=0;for(let[u,p]of Object.entries(n.credentials)){if(!p.trim())continue;if(!i.has(u))throw new ee("invalid_credentials",`Unknown integration credential field '${u}' for plugin '${n.plugin}'`);let g=j(c,`set_${u}`);if(!g)throw new ee("invalid_credentials",`Cannot set integration field '${u}' for plugin '${n.plugin}'`);await g(p.trim()),l+=1}if(l===0)throw new ee("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var tt=new Map;function da(e){for(let[n,t]of tt)t<=e&&tt.delete(n)}function rt(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return da(r),tt.has(t)?{ok:!1,error:"Delivery request already consumed"}:(tt.set(t,r+n),{ok:!0})}async function ot(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 Lo=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function pa(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 ga(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 q(n.dek,e.kek),r=Lo(n.config),o={};Object.keys(r).length>0&&(o=ce(r,t)),o[e.link.linkType]=e.link.externalId;let i=me(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:c}=await pa({database:n,pluginId:r,tenantId:o}),l=!1;if(s){let u=_({authType:s,integrationName:r,tenantId:o,kek:t,database:n,extraAccountFields:a}),p=`set_${i.linkType}`,g=u[p];typeof g=="function"&&(await g(i.externalId),l=!0)}l||await ga({database:n,kek:t,accountId:c,link:i})}async function Jt(e){let{database:n,kek:t,pluginId:r,linkType:o,externalId:i}=e,s=await n.db.selectFrom("corsair_accounts as accounts").innerJoin("corsair_integrations as integrations","integrations.id","accounts.integration_id").selectAll("accounts").where("integrations.name","=",r).execute();for(let a of s)if(a.dek)try{let c=await q(a.dek,t),u=Lo(a.config)[o];if(!u)continue;if(en(u,c)===i)return a}catch{continue}return null}async function it(e){return(await Jt(e))?.tenant_id??null}async function No(e){return it({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}function $o(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function jo(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 W({hub:e,path:"/connections/report",body:$o(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function fa(e,n){try{let t=M(e);W({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof ie)return}}async function ya(e){if(!e.hub||!e.database||!e.kek)return;let n={database:e.database,kek:e.kek,plugins:e.plugins};if(!S(e.plugin))return;let r=e.tenantId?.trim()||"default",o=await Ae(n,e.plugin,r);o&&Ko(e.hub,jo({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function Wo(e,n){fa(e,n)}function Ko(e,n){W({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function cn(e){ya(e).catch(()=>{})}async function zt(e,n){let t=w(e);if(!S(n.plugin))return;let o=await Ae(t,n.plugin,n.tenantId);o&&Wo(e,jo({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}))}var Ce=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function Ke(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a}=n;if(!o.trim())throw new Ce("no_access_token","Managed OAuth delivery missing access_token");let c=w(e,()=>new Ce("invalid_corsair_instance","Invalid corsair instance"));if(!c.database)throw new Ce("no_database","No database configured on corsair instance");let l=U(c,t,p=>new Ce("plugin_not_found",p));await xe(e,r);let u=_({authType:"managed",integrationName:t,tenantId:r,kek:c.kek,database:c.database});await u.set_access_token(o),i&&await u.set_refresh_token(i),s&&await u.set_expires_at(String(Math.floor(Date.now()/1e3)+s)),a&&await u.set_scope(a);try{let p=await ot(c.plugins,t,{access_token:o,refresh_token:i,scope:a});if(p){try{let g=l.authConfig?.managed?.account??[];await je({database:c.database,kek:c.kek,pluginId:t,tenantId:r,link:p,authType:"managed",extraAccountFields:g})}catch(g){console.warn(`[corsair:managed-oauth] Failed to persist webhook tenant link for '${t}' tenant '${r}':`,g)}c.hub&&We(c.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 ma(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function qo(e,n,t=[]){for(let[r,o]of Object.entries(e))if(ma(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=qo(o,n,[...t,r]);if(i)return i}return null}function ha(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function ba(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 Zo(e,n,t,r,o){let i=ha(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=ba(i)||s);let c={headers:i,body:s,...r?{query:r}:{}},l=r?.tenantId||"default",u=e.withTenant?e.withTenant(l):e,p=o?.plugin,g=p?[p]:hn;for(let d of g){let y=u[d];if(!y||!y.webhooks||!p&&y.pluginWebhookMatcher&&!y.pluginWebhookMatcher(c))continue;let f=qo(y.webhooks,c);if(!f)continue;let m=f.path.join("."),h={payload:s,headers:i,rawBody:typeof t=="string"?t:JSON.stringify(t),...r?{query:r}:{}};try{let b=await f.webhook.handler(h),v=!!Object.keys(b.returnToSender||{})?.length;return{plugin:d,action:m,body:s,response:v?{...b?.returnToSender,success:!0}:{success:!0},...b.responseHeaders&&{responseHeaders:b.responseHeaders}}}catch(b){return console.error(`Error executing webhook handler for ${d}.${m}:`,b),{plugin:d,action:m,body:s,response:{success:!1,error:b instanceof Error?b.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}function Se(e){return e.deliveryMode==="auth.credentials"}function un(e){return e.deliveryMode==="connections.sync"}function st(e){return e.deliveryMode==="connect.create_link"}function ln(e){return e.deliveryMode==="permission.approve"||e.deliveryMode==="permission.deny"}function dn(e){return e.deliveryMode==="oauth.tokens"}function at(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Se(e)&&!un(e)&&!st(e)&&!ln(e)&&!dn(e)}async function ka(e,n){try{return{status:"ok",webhookResponse:{status:200,body:{status:"ok",sync:{encrypted:await an(e,n)}}}}}catch(t){return{status:"failed",retryable:Zt(t),error:t instanceof Error?t.message:"Connections sync delivery failed"}}}async function Ca(e,n){try{let t=await et(e,n);return{status:"ok",webhookResponse:{status:200,body:{status:"ok",connectUrl:t.connectUrl,expiresAt:t.expiresAt}}}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Connect link delivery failed"}}}function Vt(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 wa(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 it({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function va(e,n,t){let r=await wa(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await Zo(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 Ta(e,n){return await pn(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 Pa(e,n){return await Ke(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function Qt(e,n,t){let r=await Yt(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function Yt(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 Aa(e,n){try{return await nt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function xa(e,n){try{return await Gt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}async function Xt(e,n,t={}){let r=w(e),o=Vt(n.headers,"x-corsair-signature"),i=Vt(n.headers,"x-corsair-timestamp"),s=Vt(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let c=Ne({body:n.body,signatureHeader:o,timestampHeader:i,signingSecret:t.signingSecret});if(!c.ok)return{status:"failed",retryable:!1,error:c.error};if(!s?.trim())return{status:"failed",retryable:!1,error:"Missing tunnel nonce"};let l=rt(`nonce:${s.trim()}`,Te);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 va(e,r,a.payload);case"oauth.callback":return Ta(e,a.payload);case"oauth.tokens":return Pa(e,a.payload);case"permission.approve":return Yt(e,a.payload,"approved");case"permission.deny":return Yt(e,a.payload,"denied");case"auth.credentials":return Aa(e,a.payload);case"integration.credentials":return xa(e,a.payload);case"connect.create_link":return Ca(e,a.payload);case"connections.sync":{let c=t.signingSecret?.trim();return c?ka(e,c):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}default:return Ia(String(a.type))}}function Ia(e){return Gr.has(e)?{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}:{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}}var er=new Map;function Go(e){let n;try{n=M(e)}catch{return}let t=wt(n);t&&er.get(n.projectApiKey)!==t&&(er.set(n.projectApiKey,t),W({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{er.delete(n.projectApiKey)}))}var Sa=[".corsair.dev"];function Ra(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function _a(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Ra(n)?!0:Sa.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Jo(e){return!e||!_a(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 zo(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 nr(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 tr(e,n){let t=M(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=fe(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=rt(`browser:${i.jti}`,ge);if(!s.ok)return{type:"json",status:400,body:{error:s.error}};try{if(un(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 an(e,t.signingSecret);return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:De({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(st(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 c=await et(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:De({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:c.connectUrl,expiresAt:c.expiresAt}})}}if(Se(i))return i.hubSuccessUrl?i.credentials?(await nt(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:nr(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:nr(i.hubSuccessUrl,{error:"Credential delivery missing credentials"})}:{type:"json",status:400,body:{error:"Credential delivery missing hubSuccessUrl"}};if(ln(i)){if(!i.permissionToken)return{type:"json",status:400,body:{error:"Permission delivery missing permission token"}};await Qt(e,i.permissionToken,i.deliveryMode==="permission.approve"?"approved":"denied")}else if(dn(i)){if(!i.accessToken)return{type:"json",status:400,body:{error:"Managed OAuth delivery missing access_token"}};await Ke(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!at(i)||!i.code||!i.state||!i.redirectUri)return{type:"json",status:400,body:{error:"Invalid BYO OAuth delivery token"}};await pn(e,{code:i.code,state:i.state,redirectUri:i.redirectUri,trusted:!0,plugin:i.plugin,tenantId:i.tenantId})}}catch(a){let c=a instanceof Error?a.message:"Hub delivery failed";return un(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:De({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:st(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:De({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:Se(i)&&i.hubSuccessUrl?{type:"redirect",url:nr(i.hubSuccessUrl,{error:c})}:Se(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:De({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:{type:"json",status:400,body:{error:c}}}return{type:"redirect",url:i.hubSuccessUrl}}async function rr(e,n){let t=M(e),r=await Xt(e,n,{signingSecret:t.signingSecret});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 or(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 ir(e,n){return n.method==="GET"?tr(e,n.url):rr(e,{headers:n.headers,body:n.body??""})}async function sr(e,n){try{let t=await ir(e,n);return or(t)}catch(t){if(t instanceof ie)return Response.json({error:t.message},{status:503});throw t}}async function Re(e,n){Go(e);let t=n.method.toUpperCase(),r=Jo(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 sr(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return zo(o,r)}var ne=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 Vo=300;async function ar(e,n){let{keys:t,hub:r,plugin:o,tenantId:i}=e,s=n?.forceRefresh??!1,[a,c,l]=await Promise.all([t.get_access_token(),t.get_expires_at(),t.get_refresh_token()]);if(!a&&!l)throw new ne(o,"managed");let u=Math.floor(Date.now()/1e3);if(!s&&a&&c&&Number(c)>u+Vo)return{accessToken:a,expiresAt:Number(c),refreshed:!1};if(!l&&a&&!s){let d=c?Number(c):null;if(d===null||d>u+Vo)return{accessToken:a,expiresAt:d??u+3600,refreshed:!1}}let p=await Da(r,o,i),g=p.expires_in?u+p.expires_in:c?Number(c):u+3600;return await t.set_access_token(p.access_token),await t.set_expires_at(String(g)),p.refresh_token&&await t.set_refresh_token(p.refresh_token),p.scope&&await t.set_scope(p.scope),{accessToken:p.access_token,expiresAt:g,refreshed:!0}}function Ea(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function Da(e,n,t){try{return await W({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t},parseResponse:Pn})}catch(r){let o=r instanceof Error?r.message:"";throw Ea(o)?new ne(n,"managed"):r}}async function Yo(e,n){e._refreshAuth=async()=>(await ar(n,{forceRefresh:!0})).accessToken}function Qo(e){return{delivery:n=>Re(e,n),deliveryOptions:n=>Re(e,n)}}var Xo=1200*1e3;function cr(){return oe()}function ur(){return Xo}function lr(e,n){return Ye(e,n,Xo)}function dr(e,n){return Q(e,n)}function pr(e){return Pe(e)}var ei=600*1e3;function gr(){return oe()}function fr(){return ei}function yr(e,n){return Ye(e,n,ei)}function mr(e,n){return Q(e,n)}function hr(e){return kt(e)}function br(e){return Pe(e)}function kr(){return oe()}function Cr(e,n,t){return bn(e,n,Math.floor(t.getTime()/1e3))}function wr(e,n){return Q(e,n)}function vr(e){return Pe(e)}function ct(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.
24
+
25
+ To generate a KEK, run: openssl rand -base64 ${Xe}`)}})}async function Oa(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 ni(e){let{integrationId:n,accountId:t}=await Oa(e);return{integrationId:n,accountId:t}}function Tr(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function Ma(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await St(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins})).connectUrl}catch{return null}}async function Ha(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await St(n,{tenantId:e.tenantId,plugin:e.plugin,database:e.database,kek:e.kek,plugins:e.plugins});return e.manual?.onAuthMissing?e.manual.onAuthMissing({plugin:e.pluginId,connectUrl:r.connectUrl,state:r.token}):Tr(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 Ma({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins});return t?Tr(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function Fa(e,n,t){let r=Fe(be(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}):Tr(e,i)}async function ti(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&Ue(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?Fa(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?Ha({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}):e.error.message}var Ua=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function ri(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||Ua)(e,i)}function Ba(e){return typeof e=="function"}function Pr({endpoints:e,hooks:n,ctx:t,tree:r,pluginId:o,errorHandlers:i,currentPath:s=[],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:u,permissionsOptions:p,tenantId:g,manualConfig:d,hubConfig:y,plugin:f,kek:m,allPlugins:h}){for(let[b,v]of Object.entries(e)){let O=n?.[b];if(Ba(v)){let T=O,A=[...s,b].join("."),k=async(C={})=>{let P;if(c){let F=l?.[A],{result:yn,reason:V,onComplete:Je,token:re,id:ve,expiresAt:K}=await Io({pluginId:o,endpointPath:A,args:C,mode:c.mode,override:c.overrides?.[A],riskLevel:F?.riskLevel??"write",meta:F,db:u,timeoutMs:p?Ut(p.timeout):void 0,tenantId:g,approvalMode:p?.mode});if(yn==="blocked"){let Y;throw V==="denied"?Y=`Action '${A}' was denied by the user. Await further instructions before proceeding.`:V==="policy"?Y=`Action '${A}' is blocked by the permission policy. Update the corsair config to allow it.`:V==="timeout"?Y=`Action '${A}' timed out waiting for approval.`:re&&ve?Y=await Ft({permissionsOptions:p,manual:d,hub:y,permissionId:ve,permissionToken:re,plugin:o,endpoint:A,args:C,tenantId:g??"default",expiresAt:K??new Date(Date.now()+(p?Ut(p.timeout):600*1e3)).toISOString(),operationPath:A}):Y=`Action '${A}' requires user approval before it can run.`,new Error(Y)}P=Je}let N=async(F,yn,V)=>{try{return await v(yn,V)}catch(Je){if(Je instanceof Error){let re=await ri(Je,o,A,typeof V=="object"&&V!==null?V:{args:V},i);if(F<(re.maxRetries||0)){let ve=F+1;console.log(`Retrying (${ve} / ${re.maxRetries})...`);let K;if(re.headersRetryAfterMs)K=re.headersRetryAfterMs;else switch(re.retryStrategy){case"exponential_backoff":K=Math.pow(2,ve-1)*1e3;break;case"exponential_backoff_jitter":let Y=Math.pow(2,ve-1)*1e3,Ei=(Math.random()-.5)*1e3;K=Math.max(0,Y+Ei);break;case"linear_1s":K=1e3;break;case"linear_2s":K=2e3;break;case"linear_3s":K=3e3;break;case"linear_4s":K=4e3;break;default:K=1e3;break}await new Promise(Y=>setTimeout(Y,K)),await N(ve,yn,V),console.log(`[corsair:${o}:${A}] Retry strategy:`,re)}}throw Je}},te;try{te=a?await a(t,"endpoint"):void 0}catch(F){if(F instanceof ne)return f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!1}),ti({error:F,manual:d,hub:y,plugin:f,tenantId:g,database:u,kek:m,plugins:h});throw F}if(!T?.before&&!T?.after){let F=await N(0,{...t,key:te},C);return await P?.(),f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!0}),F}let I={...t,key:te},$=T.before?await T.before(I,C):{ctx:I,args:C,continue:!0,passToAfter:void 0};if($.continue===!1)return;let Ge=await N(0,$.ctx,$.args);return await T.after?.($.ctx,Ge,$.passToAfter),await P?.(),f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!0}),Ge};r[b]=k}else if(v&&typeof v=="object"){let T={};Pr({endpoints:v,hooks:O,ctx:t,tree:T,pluginId:o,errorHandlers:i,currentPath:[...s,b],keyBuilder:a,permissionsConfig:c,endpointMeta:l,database:u,permissionsOptions:p,tenantId:g,manualConfig:d,hubConfig:y,plugin:f,kek:m,allPlugins:h}),r[b]=T}}}function La(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Ar({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(La(s)){let c=a,l=async u=>{let p=(d,y)=>s.handler(d,y),g=o?await o(t,"webhook"):void 0;return!c?.before&&!c?.after?p({...t,key:g},u):(async()=>{let d={...t,key:g},y=c.before?await c.before(d,u):{ctx:d,args:u,continue:!0,passToAfter:void 0};if(y.continue===!1)return;let f=await p(y.ctx,y.args);return f?.success===!0&&await c.after?.(y.ctx,f,y.passToAfter),f})()};r[i]={match:s.match,handler:l}}else if(s&&typeof s=="object"){let c={};Ar({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:o}),r[i]=c}}}function Na(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 ni({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function $a(e,n,t,r,o){return e?mt(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 xr(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:c,internalConfig:l}=n,u=l&&t?()=>En(l,r??"default"):void 0,p={},g={};for(let d of e)p[d.id]={},g[d.id]={};for(let d of e){let y=d.schema,f=r??"default",m=Na(t,d.id,f,u);if(y?.entities){let I={};for(let[$,Ge]of Object.entries(y.entities)){let F=t?mt(t.db,m,$,y.version,Ge):$a(void 0,m,$,y.version,Ge);I[$]=F}g[d.id].db=I,p[d.id].db=I}let h=d.options,b=d.authConfig,v;if(t&&o&&h?.authType){let I=b?.[h.authType]?.account??[];v=_({authType:h.authType,integrationName:d.id,tenantId:f,kek:o,database:t,extraAccountFields:I,ensureProvisioned:u}),p[d.id].keys=v}let O={database:t,db:g[d.id]?.db??{},$getAccountId:m,...d.options?{options:d.options}:{},...v?{keys:v,authType:h?.authType}:{},tenantId:f,...c?{hub:c}:{}},T=d.endpoints??{},A=d.hooks,k={...i,...d.errorHandlers},C={},P=d.options?.permissions;Pr({endpoints:T,hooks:A,ctx:O,tree:C,pluginId:d.id,errorHandlers:k,currentPath:[],keyBuilder:d.keyBuilder,permissionsConfig:P,endpointMeta:d.endpointMeta,database:t,permissionsOptions:s,tenantId:r,manualConfig:a?{...a,oauthConfig:d.oauthConfig,kek:o,tenantId:f}:void 0,hubConfig:c,plugin:d,kek:o,allPlugins:e}),Object.keys(C).length>0&&(p[d.id].api=C),O.endpoints=C;let N=d.webhooks??{},te=d.webhookHooks;if(Object.keys(N).length>0){let I={};Ar({webhooks:N,hooks:te,ctx:O,webhooksTree:I,keyBuilder:d.keyBuilder}),p[d.id].webhooks=I,d.pluginWebhookMatcher&&(p[d.id].pluginWebhookMatcher=d.pluginWebhookMatcher),d.pluginTenantWebhookMatcher&&(p[d.id].pluginTenantWebhookMatcher=d.pluginTenantWebhookMatcher)}}return p}function oi(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??[],c=E({authType:i.authType,integrationName:o.id,kek:t,database:n,extraIntegrationFields:a});r[o.id]=c}}return r}var ja="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function ii(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] ${ja}`),t):n}var si=[{method:"GET",pattern:"/ok",handler:async()=>D(200,Nn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>D(200,await Le(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>D(201,await Wn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>D(200,await jn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>D(200,await Be(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>D(200,await $n(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>D(200,await Kn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>D(200,await Bt(e,n.id))},{method:"POST",pattern:"/permissions/lookup-by-token",handler:async({internal:e,body:n})=>{let t=n?.token?.trim();return t?D(200,await Nt(e,t)):D(400,{error:"bad_request",message:"token is required",missingFields:["token"]})}},{method:"POST",pattern:"/connect/links",handler:async({corsair:e,internal:n,body:t})=>D(200,await qn(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>D(200,await Zn(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>D(200,await Gn(e,n,t))}];(()=>{let e=new Set;for(let n of si){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Wa(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 Ka(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 qa(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 R(400,"invalid_json","Request body is not valid JSON")}}var Za="/api/corsair";function _e(e,n={}){let t=n.basePath??Za,r=w(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=Ka(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await Re(e,o);if(a!=="GET"&&a!=="POST")return D(405,{error:"method_not_allowed",message:`Method ${a} not allowed`});let c=Object.fromEntries(i.searchParams);for(let l of si){if(l.method!==a)continue;let u=Wa(l.pattern,s);if(!u)continue;let p=await qa(o);return await l.handler({corsair:e,internal:r,req:o,params:u,query:c,body:p})}throw ke(`No route for ${a} ${s}`)}catch(i){if(n.onError){let a=await n.onError(i,o);if(a)return a}if(i instanceof R)return So(i);let s=i instanceof Error?i.message:"Internal server error";return D(500,{error:"internal_error",message:s})}}}function Ga(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[c,l]of Object.entries(e.headers))if(l!=null)if(Array.isArray(l))for(let u of l)i.append(c,u);else i.set(c,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 Ja(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 ai(e,n){let t=_e(e,n);return async(r,o,i)=>{try{let s=await t(Ga(r));await Ja(o,s)}catch(s){i(s)}}}function ci(e,n){let t=_e(e,n);return r=>t(r.req.raw)}function ui(e,n){let t=_e(e,n);return{GET:t,POST:t,OPTIONS:t}}function li(e){let n={[gn]:e};return{ok:Nn,tenants:{list:()=>Le(e),create:t=>Wn(e,t),get:t=>jn(e,t)},plugins:{list:()=>Be(e),get:t=>$n(e,t)},connectionStatus:{get:t=>Kn(e,t?.tenantId)},permissions:{get:t=>Mo(e,t)},connect:{createLink:t=>qn(n,e,t),resolve:t=>Zn(n,e,t),oauthCallback:t=>Gn(n,e,t)}}}async function di(e,n,t,r,o="pending"){if(!e)return null;try{let i=$r(),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 za(e,n,t,r="pending"){try{let o=await e.$getAccountId();return di(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as gi from"https";import*as ut from"querystring";var Va=["expires_in","refresh_token_expires_in"];function pi(e){let n={...e};for(let t of Va){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function Ya(e){try{return pi(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=ut.parse(e);return!n.access_token&&!n.error?null:pi({...n})}function lt(e,n,t,r,o){let i=new URL(r.tokenUrl),s=r.tokenAuthMethod==="basic";return new Promise((a,c)=>{let l={code:e.trim(),redirect_uri:o,grant_type:"authorization_code"};s||(l.client_id=n,l.client_secret=t);let u=ut.stringify(l),p={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json","Content-Length":Buffer.byteLength(u).toString()};s&&(p.Authorization=`Basic ${Buffer.from(`${n}:${t}`).toString("base64")}`);let g=gi.request({hostname:i.hostname,...i.port?{port:Number(i.port)}:{},path:i.pathname+i.search,method:"POST",headers:p},d=>{let y="";d.on("data",f=>{y+=f}),d.on("end",()=>{if(d.statusCode!==200){c(new Error(`Token exchange failed (${d.statusCode}): ${y}`));return}let f=Ya(y);f?a(f):c(new Error(`Token endpoint returned non-JSON response: ${y}`))})});g.on("error",d=>c(new Error(`Request failed: ${d.message}`))),g.write(u),g.end()})}var fi=" ";function J(e){let n=e;return n._def??n.def??{}}function z(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 G(e){return e.innerType??e.schema??e.out??e.in}function mi(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 G(e)}}function hi(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function pt(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 bi(e,n){return e.description??n.description}function Qa(e){let n=e;for(;n;){let t=J(n),r=bi(n,t);if(r)return r;let o=z(t);if(Er(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=mi(t,o);continue}break}}function Er(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function B(e){let n=J(e),t=z(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=G(n);return r?B(r):"unknown"}case"ZodNullable":{let r=G(n);return`${r?B(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=G(n);return r?B(r):"unknown"}case"ZodArray":{let r=hi(n);if(!r)return"unknown[]";let o=J(r),i=z(o)==="ZodUnion",s=B(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=pt(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let c=z(J(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${B(a)}`}).join(", ")} }`}case"ZodUnion":return qe(n).map(r=>B(r)).join(" | ");case"ZodIntersection":return`${B(n.left)} & ${B(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=mi(n,t);return r?B(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function le(e){let n=J(e),t=z(n),r=bi(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=G(n),i=o?le(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=G(n),i=o?le(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=G(n);return o?{...le(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=hi(n);return{kind:"array",optional:!1,description:r,items:o?le(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=pt(e,n),i={};for(let[s,a]of Object.entries(o))i[s]=le(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=J(i);if(z(s)==="ZodObject")return{...le(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=G(n);return o?{...le(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function qg(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(u=>u.id===o);if(!s)return null;let a=i;a.startsWith("api.")&&(a=a.slice(4));let c=we(s.endpointMeta,a),l=we(s.endpointSchemas,a);return!c&&!l?null:{input:l?.input?le(l.input):null,output:l?.output?le(l.output):null,description:c?.description}}var Dr=["equals","contains","startsWith","endsWith","in"],Xa=["equals","gt","gte","lt","lte","in"],ec=["equals"],nc=["equals","before","after","between"];function ki(e){let n=J(e);switch(z(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=G(n);return r?ki(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Or(e){let n=J(e),t=z(n);if(Er(t)){let i=G(n);return i?Or(i):{}}if(t!=="ZodObject")return{};let r=pt(e,n),o={};for(let[i,s]of Object.entries(r)){let a=ki(s);a==="string"?o[i]={type:"string",operators:Dr}:a==="number"?o[i]={type:"number",operators:Xa}:a==="boolean"?o[i]={type:"boolean",operators:ec}:a==="date"&&(o[i]={type:"date",operators:nc})}return o}function Ci(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Sr(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"&&Sr(o,i,t)}}function Rr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function _r(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Rr(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&_r(o,i,t)}}function Mr(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 Rr(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Rr(s)){let a=Mr(s,r);if(a!==null)return[i,...a]}return null}function wi(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(`
26
+ `)}var tc=new Set(hn);function Ee(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 tc.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:Ee(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return _r(i.webhooks,[],a),a.map(c=>`${i.id}.webhooks.${c}`)}if(t==="db"){let a=i.schema?.entities;return a?Object.keys(a).map(c=>`${i.id}.db.${c}.search`):[]}if(!i.endpoints)return[];let s=[];return Sr(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=[];_r(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=[];Sr(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function we(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function rc(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 Ir(e,n){return typeof e=="string"?e:Array.isArray(e)?`${n}:
27
+ ${e.join(", ")}`:`${n}:
28
+ `+Object.entries(e).map(([t,r])=>` ${t}: ${r.join(", ")}`).join(`
29
+ `)}function Zg(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 u=i.slice(3),p=u.lastIndexOf(".");if(p!==-1){let g=u.slice(0,p),d=u.slice(p+1),y=s.schema?.entities;if(d==="search"&&y){let f=Ci(y,g);if(f){let[m,h]=f,b=Or(h),v=[`Search ${o} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Dr.join(", ")}]`];for(let[O,T]of Object.entries(b))v.push(` ${O}?: ${T.type} [${T.operators.join(", ")}]`);return v.push("}"),v.join(`
30
+ `)}}}return Ir(Ee(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let u=i.slice(9);if(s.webhooks){let p=Mr(s.webhooks,u.split("."));if(p!==null){let g=p.join("."),d=we(s.webhookSchemas,g.toLowerCase()),y=d?.response?B(d.response):null,f=[];return d?.description&&f.push(d.description),d?.payload&&f.push(`payload ${dt(Ze(d.payload))}`),y&&f.push(`response: ${y}`),f.push(`usage:
31
+ ${wi(o,p)}`),f.join(`
32
+
33
+ `)}}return Ir(Ee(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let c=we(s.endpointMeta,a),l=we(s.endpointSchemas,a);if(c||l){let u=[],p=[c?.riskLevel?`[${c.riskLevel}]`:"",c?.irreversible?"[irreversible]":""].filter(Boolean).join(" "),g=[c?.description,p].filter(Boolean).join(" ");return g&&u.push(g),l?.input&&u.push(`input ${dt(Ze(l.input))}`),l?.output&&u.push(`output ${dt(Ze(l.output))}`),u.join(`
34
+
35
+ `)}}}return Ir(Ee(e),"Path not found. Available operations")}function yi(e){let n=e;for(;;){let t=J(n),r=z(t);if(Er(r)){let o=G(t);if(!o)return n;n=o;continue}return n}}function Ze(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=yi(e),t=J(n);if(z(t)==="ZodObject"){let o=pt(n,t),i=[];for(let[s,a]of Object.entries(o)){let c=J(a),l=z(c),u=l==="ZodOptional"||l==="ZodNullable",p=yi(a),g=Qa(a);i.push({key:s,optional:u,type:B(p),...g!==void 0?{description:g}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:B(n)}}function dt(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=fi.repeat(n+1),r=fi.repeat(n);return`{
36
+ ${e.fields.map(i=>{let s=i.optional?`${i.key}?`:i.key,a=i.description?` // ${i.description}`:"";return`${t}${s}: ${i.type}${a}`}).join(`
37
+ `)}
38
+ ${r}}`}return"unknown"}function oc(e,n){let t=Ee(e,{plugin:n,type:"api"});if(typeof t=="string")return{ok:!1,error:t};if(!Array.isArray(t))return{ok:!1,error:"list_operations did not return a path array \u2014 pass a configured plugin id."};let r=e.find(u=>u.id===n);if(!r)return{ok:!1,error:`Plugin "${n}" is not configured on this instance.`};let o=[];for(let u of t){let{shortPath:p,lookupKey:g}=rc(u,n),d=we(r.endpointMeta,g),y=we(r.endpointSchemas,g);!d&&!y||o.push({path:u,shortPath:p,description:d?.description,riskLevel:d?.riskLevel,irreversible:d?.irreversible,input:Ze(y?.input),output:Ze(y?.output)})}o.sort((u,p)=>u.path.localeCompare(p.path));let i=[],s=Ee(e,{plugin:n,type:"webhooks"});if(Array.isArray(s)&&r.webhooks)for(let u of s){let g=u.toLowerCase().slice(n.length+1),d=g.startsWith(".")?g.slice(1):g;if(!d.startsWith("webhooks."))continue;let y=d.slice(9),f=Mr(r.webhooks,y.split("."));if(f===null)continue;let m=f.join("."),h=we(r.webhookSchemas,m.toLowerCase()),b=h?.response?B(h.response):void 0;i.push({path:u,description:h?.description,payload:Ze(h?.payload),responseType:b,usageExample:wi(n,f)})}i.sort((u,p)=>u.path.localeCompare(p.path));let a=[],c=Ee(e,{plugin:n,type:"db"}),l=r.schema?.entities;if(Array.isArray(c)&&l)for(let u of c){let g=u.toLowerCase().slice(n.length+1),d=g.startsWith(".")?g.slice(1):g;if(!d.startsWith("db."))continue;let y=d.slice(3),f=y.lastIndexOf(".");if(f===-1)continue;let m=y.slice(0,f);if(y.slice(f+1)!=="search")continue;let b=Ci(l,m);if(!b)continue;let[v,O]=b,T=Or(O),A=Object.entries(T).map(([k,C])=>({field:k,type:C.type,operators:C.operators}));a.push({path:u,entityName:v,filters:[{field:"entity_id",type:"string",operators:Dr},...A]})}return a.sort((u,p)=>u.path.localeCompare(p.path)),{ok:!0,data:{pluginId:n,api:o,webhooks:i,db:a}}}import{randomUUID as vi}from"crypto";async function ic(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=vi(),o=vi(),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 sc}from"crypto";var gt="https://graph.microsoft.com/v1.0",Hr=2e4,ac=60;async function cc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let c=await fetch(`${gt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Hr)});if(c.ok){let{value:l}=await c.json(),u=(l??[]).filter(p=>p.notificationUrl===n.webhookUrl);await Promise.all(u.map(p=>fetch(`${gt}/subscriptions/${p.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Hr)}).catch(()=>{})))}}catch{}let o=sc(),i=new Date(Date.now()+ac*6e4).toISOString(),s=await fetch(`${gt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Hr),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 Ti(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function uc(e,n){let t=Ti(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 lc(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function Pi(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function Ai(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 fn(e){return!e||typeof e!="object"||Array.isArray(e)?null:e}function dc(e){return fn(e.body)}function xi(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return ft(Array.isArray(r)?r:[r])}function Ii(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=ft(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=xi({query:e.query},"validationToken");if(r)return r;let o=["x-forwarded-uri","x-original-uri","x-rewrite-url","x-envoy-original-path","referer"];for(let c of o){let l=n[c],u=Array.isArray(l)?l[0]:l;if(!(!u||typeof u!="string"))try{let g=(u.startsWith("http")?new URL(u):new URL(`https://example.invalid${u.startsWith("/")?u:`/${u}`}`)).searchParams.get("validationToken");if(g?.trim())return g.trim()}catch{continue}}let i=e.payload!==void 0?e.payload:e.body!==void 0?e.body:void 0,s=fn(typeof i=="string"?(()=>{try{return JSON.parse(i)}catch{return i}})():i);return ft([s?.validationToken])??null}function pc(e){if(Ii(e))return!0;let n=fn(e.body??e.payload);return Pi(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function ft(e){for(let n of e){let t=Ai(n);if(t)return t}}function gc(e){let t=fn(e.message)?.data;if(typeof t!="string")return null;try{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}catch{return null}}var gn=Symbol.for("corsair:internal");function yo(e){let n=e.database?Fr(e.database):void 0,t=n&&e.kek?oi(e.plugins,n,e.kek):ct(!!n,!!e.kek),r=ii(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?kn(e.hub):void 0},i=xo(n),s=li(o);if(e.multiTenancy)return Object.assign({withTenant:c=>{if(!c)throw new Error("corsair.withTenant(tenantId): tenantId must be a non-empty string");let l=xr(e.plugins,{database:n,tenantId:c,kek:e.kek,rootErrorHandlers:e.errorHandlers,permissionsOptions:r,manualConfig:e.manual,hubConfig:o.hub,internalConfig:o});return Object.assign(l,{[gn]:o})},keys:t,permissions:i,manage:s},{[gn]:o});let a=xr(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,[gn]:o})}async function Si(e,n){try{return await xn({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function yt(e,n,t,r){if(!n.subscribe)return;let o=M(e),i=await Si(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await zt(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var L=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Ri(e){let n=e.oauthConfig;if(!n)throw new L("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function fc(e,n,t,r){let o=Wr(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=se(),c=await ae(a,r);await o.accounts.create({tenant_id:t,integration_id:i.id,config:{},dek:c})}async function xt(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=w(e,()=>new L("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=U(s,n,g=>new L("plugin_not_found",g)),c=Ri(a),u=await E({authType:"oauth_2",integrationName:n,kek:s.kek,database:s.database}).get_client_id();if(!u)throw new Error(`client_id not configured for '${n}'`);if(i){let g=new URL(Ie({oauthConfig:c,clientId:u,redirectUri:o,state:""}));return g.searchParams.delete("state"),{url:g.toString(),state:""}}let p=Fe(be(n,r),s.kek);return{url:Ie({oauthConfig:c,clientId:u,redirectUri:o,state:p}),state:p}}async function pn(e,n){let{code:t,state:r,redirectUri:o}=n,i=w(e,()=>new L("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new L("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let f=Fn(r,i.kek);if(!f)throw new L("invalid_state","Invalid or tampered state parameter");s=f.plugin,a=f.tenantId}if(!i.database)throw new L("no_database","No database configured on corsair instance");let c=U(i,s,f=>new L("plugin_not_found",f)),l=Ri(c),u=E({authType:"oauth_2",integrationName:s,kek:i.kek,database:i.database}),p=await u.get_client_id(),g=await u.get_client_secret();if(!p||!g)throw new L("credentials_not_configured",`Credentials not configured for '${s}'`);await fc(i.database,s,a,i.kek);let d=await lt(t,p,g,l,o);if(!d.access_token)throw new L("no_access_token",`No access_token returned from ${l.providerName}`);let y=_({authType:"oauth_2",integrationName:s,tenantId:a,kek:i.kek,database:i.database,extraAccountFields:[...c.authConfig?.oauth_2?.account??[]]});await y.set_access_token(d.access_token),d.refresh_token&&await y.set_refresh_token(d.refresh_token),d.expires_in&&await y.set_expires_at(String(Math.floor(Date.now()/1e3)+d.expires_in));try{let f=await ot(i.plugins,s,d);if(f){try{let m=c.authConfig?.oauth_2?.account??[];await je({database:i.database,kek:i.kek,pluginId:s,tenantId:a,link:f,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:f,authType:"oauth_2"})}}catch(f){console.warn(`[corsair:oauth] Failed to resolve webhook tenant link for '${s}' tenant '${a}':`,f)}if(c.subscribe)try{await yt(e,c,a,y)}catch(f){console.warn(`[corsair:oauth] BYO subscribe failed for '${s}' tenant '${a}':`,f)}return{plugin:s,tenantId:a}}async function yc(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??yt,i=[],s=[];if(!t.database)return{renewed:i,failed:s};for(let a of r){let c=t.plugins.find(u=>u.id===a.integrationName);if(!c?.subscribe)continue;let l=`${c.id}/${a.tenantId}`;try{let u=_({authType:"oauth_2",integrationName:c.id,tenantId:a.tenantId,kek:t.kek,database:t.database,extraAccountFields:[...c.authConfig?.oauth_2?.account??[]]}),p=c.keyBuilder;if(p){let g=Object.create(u,{get_expires_at:{value:async()=>"0"}});await p({authType:"oauth_2",keys:g},"endpoint")}await o(n,c,a.tenantId,u),i.push(l)}catch(u){console.warn(`[corsair:renewal] re-subscribe failed for '${l}':`,u),s.push(l)}}return{renewed:i,failed:s}}async function _i(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 yc({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function mc(e,n={}){let t=!1,r=()=>{t||(t=!0,_i(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)}export{Kr as a,pe as b,bt as c,ze as d,qr as e,Zr as f,ge as g,Te as h,oe as i,Oe as j,Me as k,fe as l,Ct as m,zr as n,Qe as o,ie as p,kn as q,M as r,Cn as s,He as t,wn as u,vn as v,Tn as w,Pn as x,Yr as y,An as z,ye as A,se as B,ae as C,q as D,vt as E,en as F,me as G,ce as H,nn as I,E as J,_ as K,ao as L,co as M,be as N,Rt as O,We as P,je as Q,Jt as R,it as S,No as T,Ie as U,L as V,xt as W,pn as X,_i as Y,mc as Z,On as _,Is as $,Mn as aa,wu as ba,It as ca,vu as da,ko as ea,St as fa,Hn as ga,wo as ha,vo as ia,Et as ja,Un as ka,Bn as la,Jn as ma,jt as na,Ne as oa,$e as pa,zn as qa,Vn as ra,on as sa,Wt as ta,Kt as ua,Yn as va,sn as wa,Qn as xa,Xn as ya,Ce as za,Ke as Aa,Zo as Ba,Se as Ca,ln as Da,dn as Ea,at as Fa,Qt as Ga,Xt as Ha,tr as Ia,rr as Ja,or as Ka,ir as La,sr as Ma,Re as Na,ne as Oa,ar as Pa,Yo as Qa,Qo as Ra,cr as Sa,ur as Ta,lr as Ua,dr as Va,pr as Wa,gr as Xa,fr as Ya,yr as Za,mr as _a,hr as $a,br as ab,kr as bb,Cr as cb,wr as db,vr as eb,_e as fb,ai as gb,ci as hb,ui as ib,di as jb,za as kb,lt as lb,qg as mb,Ee as nb,Zg as ob,dt as pb,oc as qb,ic as rb,gt as sb,cc as tb,Ti as ub,uc as vb,lc as wb,Pi as xb,Ai as yb,fn as zb,dc as Ab,xi as Bb,Ii as Cb,pc as Db,ft as Eb,gc as Fb,gn as Gb,yo as Hb};
@@ -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-FOY4YYJo.js';
2
- export { f as PermissionLookupInput } from '../../types-FOY4YYJo.js';
3
- import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-Br272VqS.js';
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-1nBbBn-U.js';
2
+ export { f as PermissionLookupInput } from '../../types-1nBbBn-U.js';
3
+ import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-DvDEtIUw.js';
4
4
  import '../../index-eydqYIn0.js';
5
5
  import 'zod';
6
6
 
@@ -0,0 +1 @@
1
+ import{ea as a,fa as b,ga as c}from"./chunk-2FHSN2ZY.js";import"./chunk-BPFUYXOD.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-WqJfKVqn.js';
1
+ export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-DePcixJK.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-DKIQbeNM.js';
4
- export { f as AccountFieldNames, i as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, g as BaseKeyManager, D as BeforeHookResult, l as BindEndpoints, a1 as BindWebhooks, $ as Bivariant, m as BoundEndpointFn, n as BoundEndpointTree, a2 as BoundWebhook, a3 as BoundWebhookTree, k as CorsairClient, o as CorsairContext, p as CorsairEndpoint, r as CorsairErrorHandler, c as CorsairIntegration, F as CorsairKeyBuilder, G as CorsairKeyBuilderBase, a4 as CorsairOAuthWebhookTenantLinkResolver, x as CorsairPermissionsNamespace, C as CorsairPlugin, J as CorsairPluginContext, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a5 as CorsairWebhook, a6 as CorsairWebhookHandler, a7 as CorsairWebhookMatcher, a8 as CorsairWebhookTenantMatcher, K as EndpointHooks, L as EndpointMetaEntry, E as EndpointPathsOf, M as EndpointRiskLevel, q as EndpointTree, y as EnforcePermissionOptions, z as EnforcePermissionResult, s as ErrorContext, t as ErrorHandler, u as ErrorHandlerAndMatchFunction, v as ErrorMatcher, h as IntegrationFieldNames, N as KeyBuilderContext, O as OAuth2IntegrationCredentials, Q as OAuthConfig, S as PermissionMode, U as PermissionPolicy, P as PluginAuthConfig, V as PluginEndpointMeta, W as PluginPermissionsConfig, a9 as RawWebhookRequest, X as RequiredPluginEndpointMeta, Y as RequiredPluginEndpointSchemas, Z as RequiredPluginWebhookSchemas, R as RetryStrategies, w as RetryStrategy, T as TokenResponse, a0 as UnionToIntersection, _ as WebhookHooks, aa as WebhookPathsOf, ab as WebhookRequest, ac as WebhookResponse, ad as WebhookTenantMatch, ae as WebhookTree, j as exchangeCodeForTokens } from './index-DKIQbeNM.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, P as PluginDocsIntrospection, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, n as extractMicrosoftGraphValidationToken, o as firstString, f as formatDocSchemaShape, p as getHeader, i as introspectPluginForDocs, q as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, t as readQueryParam, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-C5Jn0opu.js';
6
- import { A as AuthTypes } from './types-FOY4YYJo.js';
7
- export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-FOY4YYJo.js';
3
+ import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-Zg8W-Gnw.js';
4
+ export { g as AccountFieldNames, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, G as BeforeHookResult, n as BindEndpoints, a4 as BindWebhooks, a2 as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, a5 as BoundWebhook, a6 as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, J as CorsairKeyBuilder, K as CorsairKeyBuilderBase, a7 as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, L as CorsairPluginContext, M as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, a8 as CorsairWebhook, a9 as CorsairWebhookHandler, aa as CorsairWebhookMatcher, ab as CorsairWebhookTenantMatcher, N as EndpointHooks, Q as EndpointMetaEntry, E as EndpointPathsOf, S 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, U as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, V as PermissionMode, X as PermissionPolicy, P as PluginAuthConfig, Y as PluginEndpointMeta, Z as PluginPermissionsConfig, ac as RawWebhookRequest, _ as RequiredPluginEndpointMeta, $ as RequiredPluginEndpointSchemas, a0 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, T as TokenResponse, a3 as UnionToIntersection, a1 as WebhookHooks, ad as WebhookPathsOf, ae as WebhookRequest, af as WebhookResponse, W as WebhookTenantMatch, ag as WebhookTree, l as exchangeCodeForTokens } from './index-Zg8W-Gnw.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, P as PluginDocsIntrospection, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, n as extractMicrosoftGraphValidationToken, o as firstString, f as formatDocSchemaShape, p as getHeader, i as introspectPluginForDocs, q as isMicrosoftGraphValidationHandshake, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, t as readQueryParam, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-VaW1D4fv.js';
6
+ import { A as AuthTypes } from './types-1nBbBn-U.js';
7
+ export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-1nBbBn-U.js';
8
8
  import 'kysely';
9
9
  import './index-eydqYIn0.js';
10
10
  import 'zod';
@@ -154,4 +154,49 @@ declare function initializeIntegrationDEK(database: CorsairDatabase, integration
154
154
  */
155
155
  declare function initializeAccountDEK(database: CorsairDatabase, integrationName: string, tenantId: string, kek: string): Promise<string>;
156
156
 
157
- export { AccountKeyManagerFor, AuthTypes, type EventLoggingContext, IntegrationKeyManagerFor, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, reEncryptConfig };
157
+ /** Minimal shape we need from the account key manager (ctx.keys). */
158
+ type SubscribeCtx$1 = {
159
+ keys: {
160
+ get_access_token: () => Promise<string | null | undefined>;
161
+ };
162
+ };
163
+ /**
164
+ * Shared BYO subscribe for Google channel-watch providers (Calendar, Drive):
165
+ * only the watch endpoint (and any extra body fields) differ. Opens a
166
+ * notification channel pointed at the Hub URL and returns the routing link
167
+ * (our generated channel id, echoed back in X-Goog-Channel-ID) + the channel
168
+ * token Hub verifies via X-Goog-Channel-Token. No app-side verify, so nothing
169
+ * is persisted locally.
170
+ * No stale-channel cleanup: Google exposes no channel list API, so prior
171
+ * channels can't be enumerated — they lapse at their TTL (expect brief
172
+ * invalid-token noise after reconnects). Default TTLs are accepted;
173
+ * oauth/renewal.ts re-arms before expiry.
174
+ */
175
+ declare function googleChannelSubscribe(ctx: SubscribeCtx$1, input: {
176
+ webhookUrl: string;
177
+ watchUrl: string;
178
+ body?: Record<string, unknown>;
179
+ }): Promise<CorsairPluginSubscribeResult | null>;
180
+
181
+ declare const MS_GRAPH_API_BASE = "https://graph.microsoft.com/v1.0";
182
+ /** Minimal shape we need from the account key manager (ctx.keys). */
183
+ type SubscribeCtx = {
184
+ keys: {
185
+ get_access_token: () => Promise<string | null | undefined>;
186
+ set_webhook_signature: (value: string) => Promise<void>;
187
+ };
188
+ };
189
+ /**
190
+ * Shared BYO subscribe for every MS Graph plugin: only `resource` and
191
+ * `changeType` differ per provider. Arms the Graph subscription and returns
192
+ * the routing link (subscription_id) + verification secret (clientState) for
193
+ * Hub to store. Token is freshly exchanged at connect time, so no refresh
194
+ * dance here.
195
+ */
196
+ declare function msGraphSubscribe(ctx: SubscribeCtx, input: {
197
+ webhookUrl: string;
198
+ resource: string;
199
+ changeType: string;
200
+ }): Promise<CorsairPluginSubscribeResult | null>;
201
+
202
+ export { AccountKeyManagerFor, AuthTypes, CorsairPluginSubscribeResult, type EventLoggingContext, IntegrationKeyManagerFor, MS_GRAPH_API_BASE, createAccountKeyManager, createIntegrationKeyManager, decryptConfig, decryptDEK, decryptWithDEK, encryptConfig, encryptDEK, encryptWithDEK, generateDEK, googleChannelSubscribe, initializeAccountDEK, initializeIntegrationDEK, logEvent, logEventFromContext, msGraphSubscribe, reEncryptConfig };
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{A as o,Ha as q,X as p,a,b,cb as r,db as s,eb as t,ib as u,jb as v,kb as w,lb as x,mb as y,nb as z,ob as A,p as d,pb as B,q as e,qb as C,r as f,rb as D,s as g,sb as E,t as h,tb as F,u as i,ub as G,v as j,vb as H,w as k,wb as I,x as l,xb as J,y as m,z as n}from"./chunk-3ELEU4KA.js";import{h as c}from"./chunk-BPFUYXOD.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{q as AuthMissingError,c as BASE_AUTH_FIELDS,I as CORSAIR_INTERNAL,a as ProviderDisplayNames,B as asRecord,y as collectPluginWebhookMatchers,m as createAccountKeyManager,J as createCorsair,l as createIntegrationKeyManager,H as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,t as exchangeCodeForTokens,E as extractMicrosoftGraphValidationToken,G as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,z as getHeader,o as initializeAccountDEK,n as initializeIntegrationDEK,v as introspectPluginForDocs,F as isMicrosoftGraphValidationHandshake,r as logEvent,s as logEventFromContext,w as matchWebhookPlugin,x as matchWebhookPluginAndTenant,k as reEncryptConfig,C as readBodyRecord,D as readQueryParam,p as resolveConnectLink,A as toExternalId};
1
+ import{Ab as F,B as d,Bb as G,C as e,Cb as H,D as f,Db as I,E as g,Eb as J,F as h,Fb as K,G as i,Gb as L,H as j,Hb as M,I as k,J as l,K as m,L as n,M as o,Oa as q,a,b,ja as p,jb as r,kb as s,lb as t,pb as u,qb as v,rb as w,sb as x,tb as y,ub as z,vb as A,wb as B,xb as C,yb as D,zb as E}from"./chunk-2FHSN2ZY.js";import{h as c}from"./chunk-BPFUYXOD.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{q as AuthMissingError,c as BASE_AUTH_FIELDS,L as CORSAIR_INTERNAL,x as MS_GRAPH_API_BASE,a as ProviderDisplayNames,E as asRecord,B as collectPluginWebhookMatchers,m as createAccountKeyManager,M as createCorsair,l as createIntegrationKeyManager,K as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,t as exchangeCodeForTokens,H as extractMicrosoftGraphValidationToken,J as firstString,u as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,C as getHeader,w as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,v as introspectPluginForDocs,I as isMicrosoftGraphValidationHandshake,r as logEvent,s as logEventFromContext,z as matchWebhookPlugin,A as matchWebhookPluginAndTenant,y as msGraphSubscribe,k as reEncryptConfig,F as readBodyRecord,G as readQueryParam,p as resolveConnectLink,D as toExternalId};
package/dist/hub.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { A as AuthTypes } from './types-FOY4YYJo.js';
2
- export { i as formatProviderDisplayName } from './types-FOY4YYJo.js';
3
- import { ag as HubOAuthMode, ah as HubConnectSessionResult, ai as HubPermissionSessionResult, H as HubConfig, aj as HubConfigInput, ak as HubConnectSessionInput, al as HubListProjectConnectionsInput, A as AccountKeyManagerFor, am as HubPermissionSessionInput } from './index-DKIQbeNM.js';
4
- export { an as DEFAULT_HUB_API_URL, ao as HubEnvironmentSlug } from './index-DKIQbeNM.js';
5
- import { g as TunnelType, c as ProcessCorsairRequest, h as WebhookTenantLink } from './index-CXpDAEOf.js';
6
- export { i as BROWSER_DELIVERY_TTL_MS, j as BrowserDeliveryMode, B as BrowserDeliveryPayload, S as SIGNED_TUNNEL_REPLAY_WINDOW_MS, f as TunnelEnvelope } from './index-CXpDAEOf.js';
7
- export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-DE71IK5C.js';
1
+ import { A as AuthTypes } from './types-1nBbBn-U.js';
2
+ export { i as formatProviderDisplayName } from './types-1nBbBn-U.js';
3
+ import { ai as HubOAuthMode, aj as HubConnectSessionResult, ak as HubPermissionSessionResult, H as HubConfig, al as HubConfigInput, am as HubConnectSessionInput, an as HubListProjectConnectionsInput, A as AccountKeyManagerFor, ao as HubPermissionSessionInput } from './index-Zg8W-Gnw.js';
4
+ export { ap as DEFAULT_HUB_API_URL, aq as HubEnvironmentSlug } from './index-Zg8W-Gnw.js';
5
+ import { g as TunnelType, c as ProcessCorsairRequest, h as WebhookTenantLink } from './index-CXNdPXR3.js';
6
+ export { i as BROWSER_DELIVERY_TTL_MS, j as BrowserDeliveryMode, B as BrowserDeliveryPayload, S as SIGNED_TUNNEL_REPLAY_WINDOW_MS, f as TunnelEnvelope } from './index-CXNdPXR3.js';
7
+ export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-DEaQVGsf.js';
8
8
  import './index-eydqYIn0.js';
9
9
  import 'zod';
10
10
  import './db.js';
@@ -13,6 +13,57 @@ import 'pg';
13
13
  import 'postgres';
14
14
  import './orm.js';
15
15
 
16
+ type HubEnvironmentSlug = 'development' | 'production';
17
+ type DeliveryTransport = 'browser' | 'server';
18
+ declare function isLoopbackUrl(url: string): boolean;
19
+ declare function resolveDeliveryTransport(slug: HubEnvironmentSlug): DeliveryTransport;
20
+ declare function usesBrowserDelivery(slug: HubEnvironmentSlug): boolean;
21
+ declare function validateProductionDeliveryUrl(deliveryUrl: string): string | null;
22
+
23
+ type ClientBridgeDeliverySpec = {
24
+ deliveryMode: 'connections.sync';
25
+ deliveryUrl: string;
26
+ projectId: string;
27
+ signingSecret: string;
28
+ hubOrigin: string;
29
+ requestId: string;
30
+ } | {
31
+ deliveryMode: 'connect.create_link';
32
+ deliveryUrl: string;
33
+ projectId: string;
34
+ signingSecret: string;
35
+ hubOrigin: string;
36
+ requestId: string;
37
+ tenantId: string;
38
+ plugins: string[];
39
+ };
40
+ type ClientBridgeTransportResult = {
41
+ transport: 'server';
42
+ } | {
43
+ transport: 'browser';
44
+ deliveryUrl: string;
45
+ requestId: string;
46
+ };
47
+ declare function buildClientBridgeBrowserDeliveryUrl(spec: ClientBridgeDeliverySpec): string;
48
+ type PrepareClientBridgeDeliveryTransportInput = {
49
+ deliveryMode: 'connections.sync';
50
+ deliveryUrl: string;
51
+ projectId: string;
52
+ signingSecret: string;
53
+ hubOrigin?: string;
54
+ environmentSlug: HubEnvironmentSlug;
55
+ } | {
56
+ deliveryMode: 'connect.create_link';
57
+ deliveryUrl: string;
58
+ projectId: string;
59
+ signingSecret: string;
60
+ hubOrigin?: string;
61
+ environmentSlug: HubEnvironmentSlug;
62
+ tenantId: string;
63
+ plugins: string[];
64
+ };
65
+ declare function prepareClientBridgeDeliveryTransport(spec: PrepareClientBridgeDeliveryTransportInput): ClientBridgeTransportResult;
66
+
16
67
  type ConnectAuthKind = 'oauth' | 'api_key' | 'bot_token';
17
68
  type ConnectPluginManifestEntry = {
18
69
  plugin: string;
@@ -84,13 +135,6 @@ declare function parseOAuthRefreshResponse(payload: unknown): HubOAuthRefreshRes
84
135
  declare function parseConnectStatusResponse(payload: unknown): ConnectStatusResponse;
85
136
  declare function parseHubApiErrorBody(payload: unknown): string | null;
86
137
 
87
- type HubEnvironmentSlug = 'development' | 'production';
88
- type DeliveryTransport = 'browser' | 'server';
89
- declare function isLoopbackUrl(url: string): boolean;
90
- declare function resolveDeliveryTransport(slug: HubEnvironmentSlug): DeliveryTransport;
91
- declare function usesBrowserDelivery(slug: HubEnvironmentSlug): boolean;
92
- declare function validateProductionDeliveryUrl(deliveryUrl: string): string | null;
93
-
94
138
  declare class HubNotConfiguredError extends Error {
95
139
  constructor();
96
140
  }
@@ -111,6 +155,11 @@ declare function inferHubEnvironmentSlug(apiKey: string): 'development' | 'produ
111
155
  */
112
156
  declare function createHubConnectSession(corsair: unknown, input: HubConnectSessionInput): Promise<HubConnectSessionResult>;
113
157
 
158
+ type ConnectCreateLinkDeliveryResult = {
159
+ connectUrl: string;
160
+ expiresAt?: string;
161
+ };
162
+
114
163
  declare function getConnectStatusForTenant(corsair: unknown, tenantId: string, options?: {
115
164
  pluginIds?: string[];
116
165
  }): Promise<ConnectStatusResponse>;
@@ -236,6 +285,21 @@ declare function isServerDeliveryAckSuccessful(input: {
236
285
  declare function extractSyncFromDeliveryAck(body: ServerDeliveryAckBody): {
237
286
  encrypted: string;
238
287
  } | null;
288
+ declare function extractConnectLinkFromDeliveryAck(body: ServerDeliveryAckBody): ConnectCreateLinkDeliveryResult | null;
289
+ /**
290
+ * Parses connect link payload from a raw delivery HTTP body.
291
+ */
292
+ declare function parseConnectLinkFromDeliveryBody(body: string): ConnectCreateLinkDeliveryResult | null;
293
+ /**
294
+ * POSTs a connect.create_link envelope to the app's delivery URL.
295
+ */
296
+ declare function deliverConnectCreateLink(input: {
297
+ deliveryUrl: string;
298
+ projectId: string;
299
+ signingSecret: string;
300
+ tenantId: string;
301
+ plugins: string[];
302
+ }): Promise<ConnectCreateLinkDeliveryResult>;
239
303
  /**
240
304
  * Parses sync payload from a raw delivery HTTP body using the standard ack contract.
241
305
  */
@@ -513,4 +577,4 @@ declare function decodePermissionTokenFromPath(encoded: string): string;
513
577
  */
514
578
  declare function createSignedTokenJti(): string;
515
579
 
516
- export { type ConnectAuthFieldStatus, type ConnectAuthKind, type ConnectAuthStatusLevel, type ConnectPluginManifestEntry, type ConnectSessionTokenPayload, type ConnectStatusPluginEntry, type ConnectStatusResponse, type ConnectTokenPayload, type CreateConnectSessionRequestBody, type CreatePermissionSessionRequestBody, type FormatServerDeliveryErrorInput, HubConfig, HubConfigInput, HubConnectSessionInput, HubConnectSessionResult, type HubDeliveryRequest, type HubDeliveryResult, HubListProjectConnectionsInput, HubNotConfiguredError, HubOAuthMode, type HubOAuthRefreshResponse, HubPermissionSessionInput, HubPermissionSessionResult, type HubProjectConnection, type ManagedAccessTokenResult, type ManagedAuthContext, ManagedOAuthDeliveryError, type PermissionTokenPayload, type ProcessManagedOAuthDeliveryOptions, type ProcessManagedOAuthDeliveryResult, type ServerDeliveryAckBody, type SignedDeliveryHeaders, type SignedEnvelopeDeliveryResult, TunnelType, attachManagedRefreshAuth, createConnectSessionJti, createConnectTokenJti, createHubConnectSession, createHubPermissionSession, createHubRouteHandlers, createPermissionSessionJti, createSignedTokenJti, decodeConnectSessionTokenFromPath, decodeConnectTokenFromPath, decodePermissionTokenFromPath, deliverSignedEnvelope, describeDeliveryNetworkError, encodeConnectTokenForPath, extractSyncFromDeliveryAck, formatHubApprovalMessage, formatServerDeliveryError, getConnectSessionExpiryMs, getConnectStatusForTenant, getConnectTokenExpiryMs, getHubConfig, getManagedAccessToken, handleHubDeliveryGet, handleHubDeliveryPost, handleHubDeliveryRequest, hubDeliveryToResponse, inferHubEnvironmentSlug, isLoopbackUrl, isServerDeliveryAckSuccessful, listHubProjectConnections, normalizeHubConfig, parseConnectSessionResponse, parseConnectStatusResponse, parseHubApiErrorBody, parseOAuthRefreshResponse, parsePermissionSessionResponse, parseProjectConnectionsResponse, parseServerDeliveryAckBody, parseSyncFromDeliveryBody, processManagedOAuthDelivery, registerHubWebhookTenantLink, resolveDeliveryTransport, resolveHubDeliveryUrl, resolveHubOAuthCallbackUrl, respondToHubDelivery, respondToHubDeliveryFromRequest, signConnectSessionToken, signConnectToken, signDeliveryEnvelope, signPermissionToken, usesBrowserDelivery, validateProductionDeliveryUrl, verifyConnectSessionToken, verifyConnectToken, verifyDeliveryEnvelope, verifyPermissionToken, verifySignedTunnelDelivery };
580
+ export { type ClientBridgeDeliverySpec, type ClientBridgeTransportResult, type ConnectAuthFieldStatus, type ConnectAuthKind, type ConnectAuthStatusLevel, type ConnectCreateLinkDeliveryResult, type ConnectPluginManifestEntry, type ConnectSessionTokenPayload, type ConnectStatusPluginEntry, type ConnectStatusResponse, type ConnectTokenPayload, type CreateConnectSessionRequestBody, type CreatePermissionSessionRequestBody, type FormatServerDeliveryErrorInput, HubConfig, HubConfigInput, HubConnectSessionInput, HubConnectSessionResult, type HubDeliveryRequest, type HubDeliveryResult, HubListProjectConnectionsInput, HubNotConfiguredError, HubOAuthMode, type HubOAuthRefreshResponse, HubPermissionSessionInput, HubPermissionSessionResult, type HubProjectConnection, type ManagedAccessTokenResult, type ManagedAuthContext, ManagedOAuthDeliveryError, type PermissionTokenPayload, type PrepareClientBridgeDeliveryTransportInput, type ProcessManagedOAuthDeliveryOptions, type ProcessManagedOAuthDeliveryResult, type ServerDeliveryAckBody, type SignedDeliveryHeaders, type SignedEnvelopeDeliveryResult, TunnelType, attachManagedRefreshAuth, buildClientBridgeBrowserDeliveryUrl, createConnectSessionJti, createConnectTokenJti, createHubConnectSession, createHubPermissionSession, createHubRouteHandlers, createPermissionSessionJti, createSignedTokenJti, decodeConnectSessionTokenFromPath, decodeConnectTokenFromPath, decodePermissionTokenFromPath, deliverConnectCreateLink, deliverSignedEnvelope, describeDeliveryNetworkError, encodeConnectTokenForPath, extractConnectLinkFromDeliveryAck, extractSyncFromDeliveryAck, formatHubApprovalMessage, formatServerDeliveryError, getConnectSessionExpiryMs, getConnectStatusForTenant, getConnectTokenExpiryMs, getHubConfig, getManagedAccessToken, handleHubDeliveryGet, handleHubDeliveryPost, handleHubDeliveryRequest, hubDeliveryToResponse, inferHubEnvironmentSlug, isLoopbackUrl, isServerDeliveryAckSuccessful, listHubProjectConnections, normalizeHubConfig, parseConnectLinkFromDeliveryBody, parseConnectSessionResponse, parseConnectStatusResponse, parseHubApiErrorBody, parseOAuthRefreshResponse, parsePermissionSessionResponse, parseProjectConnectionsResponse, parseServerDeliveryAckBody, parseSyncFromDeliveryBody, prepareClientBridgeDeliveryTransport, processManagedOAuthDelivery, registerHubWebhookTenantLink, resolveDeliveryTransport, resolveHubDeliveryUrl, resolveHubOAuthCallbackUrl, respondToHubDelivery, respondToHubDeliveryFromRequest, signConnectSessionToken, signConnectToken, signDeliveryEnvelope, signPermissionToken, usesBrowserDelivery, validateProductionDeliveryUrl, verifyConnectSessionToken, verifyConnectToken, verifyDeliveryEnvelope, verifyPermissionToken, verifySignedTunnelDelivery };