corsair 0.1.103 → 0.1.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-delivery-DE71IK5C.d.ts → browser-delivery-ARqe7lph.d.ts} +1 -1
- package/dist/chunk-6WGGD3SS.js +38 -0
- package/dist/client/react/index.d.ts +3 -3
- package/dist/connect-A2OXYDLE.js +1 -0
- package/dist/core.d.ts +52 -7
- package/dist/core.js +1 -1
- package/dist/hub.d.ts +79 -15
- package/dist/hub.js +1 -1
- package/dist/{index-CXpDAEOf.d.ts → index-CdzrawUJ.d.ts} +5 -7
- package/dist/{index-WqJfKVqn.d.ts → index-D7aqzKjb.d.ts} +1 -1
- package/dist/{index-DKIQbeNM.d.ts → index-DwegPGYj.d.ts} +54 -2
- package/dist/index.d.ts +19 -10
- package/dist/index.js +2 -2
- package/dist/oauth.d.ts +23 -3
- package/dist/oauth.js +1 -1
- package/dist/{setup-OYRFEDUS.js → setup-W2M2D2FG.js} +1 -1
- package/dist/setup-introspect-YZWWCD2B.js +1 -0
- package/dist/setup.d.ts +3 -3
- package/dist/setup.js +1 -1
- package/dist/{tenant-match-utils-C5Jn0opu.d.ts → tenant-match-utils-f49OxmPU.d.ts} +2 -2
- package/dist/tunnel.d.ts +5 -5
- package/dist/tunnel.js +1 -1
- package/dist/{types-FOY4YYJo.d.ts → types-1nBbBn-U.d.ts} +6 -2
- package/dist/{types-Br272VqS.d.ts → types-DvDEtIUw.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3ELEU4KA.js +0 -38
- package/dist/connect-YUGW4GB5.js +0 -1
- package/dist/setup-introspect-P674L2XG.js +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import{a as Nr,b as pe,c as $r,d as w,e as F,f as jr,g as N,h as H,i as S,j as hn,k as Wr,l as Kr,m as bt,n as qr,o as Zr}from"./chunk-BPFUYXOD.js";import{a as Lr}from"./chunk-IGGCNGU2.js";var bn=["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"],Gr={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 ge(e){let n=Gr[e];return n||e.charAt(0).toUpperCase()+e.slice(1)}import{randomUUID as Wi}from"crypto";var Ui="corsair:client-bridge";function kt(e){return new URL(e).origin}function Oe(e){let n=JSON.stringify({type:Ui,requestId:e.requestId,ok:e.ok,body:e.body??null,error:e.error??null}),t=JSON.stringify(kt(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 Bi=new Set(["localhost","127.0.0.1","[::1]","::1"]);function Ct(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Bi.has(n)}catch{return!1}}function ze(e){return e==="development"?"browser":"server"}function Jr(e){return ze(e)==="browser"}function zr(e){return Ct(e)?"Production delivery URL must be a public URL, not localhost":null}import{randomBytes as ji}from"crypto";var Vr=new Set(["oauth.callback","oauth.tokens","webhook","permission.approve","permission.deny","auth.credentials","integration.credentials","connect.create_link","connections.sync"]),fe=60*1e3,Pe=300*1e3;import{createHmac as Li,randomBytes as Ni,timingSafeEqual as $i}from"crypto";function oe(){return Ni(16).toString("base64url")}function Ve(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required");return Li("sha256",t).update(e).digest("base64url")}function Y(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(!$i(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 kn(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 kn(e,n,r+Math.floor(t/1e3))}function Ae(e){return decodeURIComponent(e)}function wt(e){return encodeURIComponent(e)}function Yr(e){let n=e.trim();return n.length>0?n:null}function Me(e,n){let t=new URL(e);return t.searchParams.set("d",n),t.toString()}function He(e,n){if(!Yr(n))throw new Error("Signing secret is required for browser delivery tokens");let t=Math.floor(Date.now()/1e3),r={...e,jti:e.jti??ji(16).toString("base64url"),iat:t,exp:t+Math.floor(fe/1e3)},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=Ve(o,n);return`${o}.${i}`}function ye(e,n){return Yr(n)?Y(e,n):null}function Ki(e){let n=kt(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 vt(e){let n=He(Ki(e),e.signingSecret);return Me(e.deliveryUrl,n)}function Qr(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=Wi(),r={...e,hubOrigin:e.hubOrigin,requestId:t};return{transport:"browser",requestId:t,deliveryUrl:vt(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 Cn(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 qi(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||!qi(n))throw new ie;return n}function Xr(e){return e.replace(/\/$/,"")}function wn(e){return e.oauthCallbackUrl?Xr(e.oauthCallbackUrl.trim()):`${Xr(e.apiUrl)}/oauth/callback`}function Fe(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 I(e){return typeof e=="string"&&e.length>0}function Zi(e){return e==="ready"||e==="partial"||e==="not_started"||e==="missing_integration"}function Gi(e){return e==="oauth_2"||e==="api_key"||e==="bot_token"||e==="managed"}function vn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty connect session");let n=e;if(!I(n.connectUrl)||!I(n.token)||!I(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:I(n.environmentId)?n.environmentId:n.projectId};return I(n.expiresAt)&&(t.expiresAt=n.expiresAt),t}function Tn(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(!I(r.tenantId)||!I(r.plugin)||!Zi(r.status)||!Gi(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:I(r.reportedAt)?r.reportedAt:new Date().toISOString()})}return n}function Pn(e){if(!e||typeof e!="object")throw new Error("Hub API returned an empty permission session");let n=e;if(!I(n.approvalUrl)||!I(n.token)||!I(n.projectId)||!I(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 An(e){if(!e||typeof e!="object")throw new Error("Hub token refresh returned an empty response");let n=e;if(I(n.access_token))return{access_token:n.access_token,refresh_token:I(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:I(n.scope)?n.scope:void 0};throw new Error(I(n.error)?I(n.error_description)?n.error_description:n.error:"Hub token refresh returned no access_token")}function Ji(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function zi(e){if(!Array.isArray(e))return[];let n=[];for(let t of e){if(!t||typeof t!="object")continue;let r=t;I(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 Vi(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 eo(e){if(!e||typeof e!="object")throw new Error("Connect status response was empty");let n=e;if(!I(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(!I(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=zi(o.fields),a=Ji(o.missingRequiredFields),c=Vi(o.status,o.connected,s,a);t.push({plugin:o.plugin,providerName:I(o.providerName)?o.providerName:o.plugin,authKind:i,status:c,connected:o.connected,fields:s,missingRequiredFields:a})}return{tenantId:n.tenantId,plugins:t}}function xn(e){if(!e||typeof e!="object")return null;let n=e;return n.error??n.message??null}var Yi="3000",Qi="/api/corsair";function Xi(e){return e.replace(/\/$/,"")}function me(e){let n=e?.deliveryUrl?.trim()||process.env.CORSAIR_DELIVERY_URL?.trim();if(n){let r=/^https?:\/\//i.test(n)?n:`https://${n}`;return Xi(r)}return`http://localhost:${process.env.PORT?.trim()||Yi}${Qi}`}function no(e){return e.replace(/\/$/,"")}function Tt(e){if(!e.projectApiKey.startsWith("ck_dev_"))return null;try{return me()}catch{return null}}function to(e){let n=Tt(e);return n?{"x-corsair-delivery-url":n}:{}}async function ro(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 oo(e,n,t){if(n===404&&t)return t;let r=xn(e);return r||`Hub API returned HTTP ${n}`}async function $(e){let n=no(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.hub.projectApiKey}`,...to(e.hub)},body:JSON.stringify(e.body)}),r=await ro(t);if(!t.ok)throw new Error(oo(r,t.status,e.notFoundMessage));return e.parseResponse(r)}async function In(e){let n=no(e.hub.apiUrl),t=await fetch(`${n}${e.path}`,{method:"GET",headers:{authorization:`Bearer ${e.hub.projectApiKey}`,...to(e.hub)}}),r=await ro(t);if(!t.ok)throw new Error(oo(r,t.status,e.notFoundMessage));return e.parseResponse(r)}import{createCipheriv as io,createDecipheriv as so,randomBytes as Sn,scrypt as es}from"crypto";import{promisify as ns}from"util";var ao=ns(es),Rn="aes-256-gcm",co=12,_n=16,ts=16,Xe=32;function se(){return Sn(Xe).toString("base64")}async function ae(e,n){let t=Sn(ts),r=await ao(n,t,Xe),o=Sn(co),i=io(Rn,r,o,{authTagLength:_n}),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 K(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 ao(n,s,Xe),p=so(Rn,u,a,{authTagLength:_n});return p.setAuthTag(c),Buffer.concat([p.update(l),p.final()]).toString("utf8")}function Pt(e,n){let t=Buffer.from(n,"base64"),r=Sn(co),o=io(Rn,t,r,{authTagLength:_n}),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=so(Rn,i,s,{authTagLength:_n});return l.setAuthTag(a),Buffer.concat([l.update(c),l.final()]).toString("utf8")}function he(e,n){let t={};for(let[r,o]of Object.entries(e))t[r]=Pt(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 he(r,t)}function uo(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 At=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:At(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 K(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=he(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 K(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},...uo(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:At(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:At(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 K(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 K(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(x){console.error(`[corsair] Failed to decrypt config for account (tenant: "${r}", integration: "${t}"), starting fresh:`,x),P={}}let L={...P};for(let[x,te]of Object.entries(k))te===null?delete L[x]:L[x]=te;let ne=he(L,C);await g.updateAccount({config:ne})},A={get_dek:f,issue_new_dek:async()=>{let k=await g.getAccount(),C=se(),P={};if(k.dek){let ne=await K(k.dek,o),x=k.config;x&&Object.keys(x).length>0&&(P=nn(x,ne,C))}let L=await ae(C,o);return await g.updateAccount({config:P,dek:L}),d=C,C},...uo(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 lo(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 po(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 rs=new Set(["webhook_signature","expires_at","scope","redirect_url"]);function be(e){return rs.has(e)}function os(e,n){return be(n)?!1:e==="oauth_2"?n==="client_id"||n==="client_secret":!0}function is(e){return!be(e)}function ss(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 as(e,n){return ss(e).every(r=>n.find(i=>i.level==="account"&&i.name===r)?.configured??!1)}async function go(e,n){if(!e)return!1;let t=N(e,`get_${n}`);if(!t)return!1;try{let r=await t();return typeof r=="string"&&r.length>0}catch{return!1}}function cs(e,n){let r=e.authConfig?.[n]?.integration??[];return[...H[n].integration,...r]}function us(e,n){let r=e.authConfig?.[n]?.account??[];return[...H[n].account,...r]}function ls(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:as(n,t),fields:t,missingRequiredFields:r}}async function xe(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=cs(n,r),p=us(n,r),g=[];for(let d of u)g.push({name:d,level:"integration",required:os(r,d),configured:await go(c,d)});for(let d of p)g.push({name:d,level:"account",required:is(d),configured:await go(l,d)});return ls(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 xe(e,s,r);a&&i.push(a)}return i}function En(e){return e.connected?"connected":e.status==="missing_integration"?"missing_credentials":"not_connected"}var fo=Symbol.for("corsair:internal"),yo=new WeakMap;function ds(e){let n=yo.get(e);return n||(n=new Map,yo.set(e,n)),n}function ps(e){return e.multiTenancy?{withTenant:()=>({}),[fo]:e}:{[fo]:e}}async function Dn(e,n){if(!e.database)return;let t=n.trim()||"default",r=ds(e),o=t,i=r.get(o);if(i){await i;return}let s=(async()=>{let{setupCorsair:a}=await import("./setup-W2M2D2FG.js");await a(ps(e),{tenantId:e.multiTenancy?t:void 0,silent:!0})})().finally(()=>{r.delete(o)});r.set(o,s),await s}import{ZodBoolean as fs,ZodDate as ys,ZodEnum as ms,ZodNullable as hs,ZodNumber as bs,ZodObject as ks,ZodOptional as Cs,ZodRecord as ws,ZodString as vs,ZodType as Ts}from"zod";var gs={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:{}}}},xt=gs;async function Mn(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=$r(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=As(e,a.plugins,n),l={...a,database:a.database},u=l.database.db;await Ss(u,i);let p=await Rs(u,l,c.tenantId,c.provisionAccounts,o);n?.credentials&&Object.keys(n.credentials).length>0&&await Ds(e,c,n.credentials,l,o,i);let g=await Ms(p,c,o,s);if(n?.backfill){o("[corsair:setup] Starting backfill...");let d=bo({plugins:a.plugins,database:u,kek:a.kek,multiTenancy:!0}).withTenant(c.tenantId);await Hs(d,a.plugins,g,o,i),o("[corsair:setup] Backfill complete.")}return t.join(`
|
|
10
|
+
`)}function It(e,n,t){let r=t==="integration"?e.authConfig?.[n]?.integration??[]:e.authConfig?.[n]?.account??[];return new Set([...H[n][t],...r])}function Ps(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=It(o,i,"account");for(let a of Object.keys(r))if(s.has(a))return!0}return!1}function As(e,n,t){let r=jr(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&&Ps(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 ho(e,n){return pe(e)?n===0?!0:Object.values(e).every(t=>ho(t,n-1)):!1}function xs(e){return ho(e,4)}var Is={...qr};function On(e){if(e instanceof ks){let n={};for(let[t,r]of Object.entries(e.shape))n[t]=r instanceof Ts?On(r):"unknown";return n}return e instanceof hs?`${On(e.unwrap())} | null`:e instanceof Cs?`${On(e.unwrap())} | undefined`:e instanceof ms?e.options.join(" | "):e instanceof vs?"string":e instanceof bs?"number":e instanceof fs?"boolean":e instanceof ys?"date":e instanceof ws?"jsonb":"unknown"}async function Ss(e,n){let t=await e.introspection.getTables(),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(Is))r.has(o)||n(`[corsair:setup] Table "${o}" does not exist. Run your database migrations before calling setupCorsair.
|
|
11
|
+
Schema: ${JSON.stringify(On(i),null,2)}`)}async function Rs(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 _s(e){if(!pe(e))return;let n=e.keys;return pe(n)?n:void 0}function Es(e,n){return"withTenant"in e&&typeof e.withTenant=="function"?e.withTenant(n):e}async function Ds(e,n,t,r,o,i){let s=_s(e),a=n.provisionAccounts?Es(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=It(u,p,"integration"),d=It(u,p,"account"),y=s?.[c],f=a?.[c],m=pe(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=N(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=N(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 mo=new Set(["webhook_signature","expires_at","scope","redirect_url"]);async function Os(e,n,t,r,o,i,s,a,c){let l=[],u=[];for(let g of o){if(mo.has(g))continue;let d=N(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(mo.has(g))continue;let d=N(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 Ms(e,n,t,r){let o=new Set;for(let i of e.values())await Os(i.pluginId,i.authType,i.integration,i.account,i.integrationFields,i.accountFields,n,t,r)&&o.add(i.pluginId);return o}async function Hs(e,n,t,r,o){if(!xs(xt)){o("[corsair:setup] Backfill config is invalid - skipping backfill.");return}let i=xt,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=pe(e)?e[a]:void 0,u=pe(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=pe(u)?u[p]:void 0;await N(f,d)?.(y)}catch(f){o(`[corsair:setup] ${a} \u203A ${p}.${d} failed: `+(f instanceof Error?f.message:String(f)))}}}}async function ko(e){if(!w(e).database)throw new Error("A database must be configured to provision Corsair integrations");await Mn(e,{silent:!0})}async function Ie(e,n){let t=w(e);if(!t.database)throw new Error("A database must be configured to provision Corsair for connect");await Dn(t,n)}var Fs=Symbol.for("corsair:internal"),Us=new Set(["access_token","refresh_token","expires_at","scope"]);function Bs(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ls(e,n){return e==="oauth_2"||e==="managed"?n.filter(t=>!be(t)&&!Us.has(t)):n.filter(t=>!be(t))}function Co(e){return{plugins:e.plugins,database:e.database,kek:e.kek,multiTenancy:!1}}function wo(e){return{[Fs]:Co(e)}}async function Hn(e,n,t={}){let r=wn(e.hub),o=[],i=t.pluginIds?new Set(t.pluginIds):null,s=Co(e),a=wo(e);for(let c of e.plugins){if(i&&!i.has(c.id))continue;let l=S(c);if(!l)continue;let u=Bs(l),p=t.providerNameOverrides?.[c.id]??ge(c.id),g=await xe(s,c,n),d=hn(c,l),y=Ls(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 St(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 Su(e,n,t={}){let r=w(e),o=r.hub;if(!o)throw new Error("Hub is not configured");return Hn({plugins:r.plugins,database:r.database,kek:r.kek,hub:o},n,t)}async function Rt(e,n){if(!e.database)throw new Error("A database must be configured to provision Corsair for connect");await Ie(wo(e),n)}async function Ru(e,n){await Ie(e,n)}async function vo(e,n){let t=Fe(e.projectApiKey),r={tenantId:n.tenantId,plugins:n.plugins};return t==="development"&&(r.deliveryUrl=me({deliveryUrl:n.deliveryUrl})),$({hub:e,path:"/connect/sessions",notFoundMessage:"Hub REST API not found at /connect/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:vn})}async function _t(e,n){let t={plugins:n.plugins,database:n.database,kek:n.kek,hub:e};await Rt(t,n.tenantId);let r=await Hn(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 vo(e,{tenantId:n.tenantId,plugins:r,deliveryUrl:n.deliveryUrl})}async function Fn(e,n){let t=w(e),r=M(e),o={plugins:t.plugins,database:t.database,kek:t.kek,hub:r};await Rt(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 Hn(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 vo(r,{tenantId:n.tenantId,plugins:c,deliveryUrl:n.deliveryUrl})}function To(e){return e==="oauth_2"||e==="managed"?"oauth":e==="bot_token"?"bot_token":"api_key"}function Ns(e,n){return n&&!n.has(e.id)?!1:S(e)!==null}async function Po(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=>Ns(l,i)).map(l=>{let u=S(l),p=a.get(l.id);return p?{plugin:l.id,providerName:ge(l.id),authKind:To(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:ge(l.id),authKind:To(u),status:"not_started",connected:!1,fields:[],missingRequiredFields:[]}});return{tenantId:o,plugins:c}}async function Ao(e,n){let t=M(e);return In({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:Tn})}import*as rn from"crypto";function ke(e,n){return Buffer.from(JSON.stringify({plugin:e,tenantId:n,iat:Date.now()})).toString("base64url")}function Et(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 Ue(e,n){let t=rn.createHmac("sha256",n).update(e).digest("base64url");return`${e}.${t}`}var Dt=600*1e3;function Un(e,n){let t=e.lastIndexOf(".");if(t===-1)return null;let r=e.slice(0,t),o=e.slice(t+1),i=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:Et(r,{maxAgeMs:Dt})}function Be(e){return!!(e?.baseUrl?.trim()&&e?.redirectUri?.trim())}import*as xo from"querystring";function Se(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}?${xo.stringify(i)}`}var q=class extends Error{code;constructor(n,t){super(t),this.name="ConnectError",this.code=n}};function $s(e){let n=e.oauthConfig;if(!n)throw new q("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function Ot(e,n){let t=w(e,()=>new q("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new q("no_database","No database configured on corsair instance");let r=t.manual?.redirectUri;if(!r)throw new q("no_redirect_uri","No redirectUri configured. Set manual.redirectUri in createCorsair().");let o=Un(n,t.kek);if(!o)throw new q("invalid_state","Invalid or tampered state parameter");let{plugin:i,tenantId:s}=o,a=F(t,i,g=>new q("plugin_not_found",g)),c=$s(a),u=await E({authType:"oauth_2",integrationName:i,kek:t.kek,database:t.database}).get_client_id();if(!u)throw new q("client_id_not_configured",`client_id not configured for '${i}'`);let p=Se({oauthConfig:c,clientId:u,redirectUri:r,state:n});return{plugin:i,tenantId:s,providerName:c.providerName,oauthUrl:p,state:n}}import{AsyncLocalStorage as Ws}from"async_hooks";import{randomBytes as Ks}from"crypto";import{v4 as qs}from"uuid";async function Bn(e,n){let t=Fe(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=me({deliveryUrl:n.deliveryUrl})),$({hub:e,path:"/permission/sessions",notFoundMessage:"Hub REST API not found at /permission/sessions. Check HUB_API_URL and ensure the Hub API is deployed.",body:r,parseResponse:Pn})}function Ln(e){return`Approval required. Visit ${e} to approve or deny, then tell the agent to retry this action.`}var Mt="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 Ft(e){return e?e.approvalBaseUrl!==void 0||e.onApprovalRequired!==void 0:!1}function Io(e,n){return`${e.replace(/\/+$/,"")}/${n}`}function Ht(e){return Ln(e)}async function Ut(e,n){if(Ft(e.manual)){let r=e.manual?.approvalBaseUrl?.trim();return r?Io(r,n.token):null}let t=e.hub;if(!t)return null;try{return(await Bn(t,{permissionId:n.id,permissionToken:n.token,plugin:n.plugin,endpoint:n.endpoint,args:js(n.args),tenantId:n.tenant_id,expiresAt:n.expires_at})).approvalUrl}catch{return null}}function js(e){try{return JSON.parse(e)}catch{return e}}async function Nn(e,n){if(!(n.status==="pending"||n.status==="approved"))return{...n,approvalUrl:null};let r=await Ut(e,n);return{...n,approvalUrl:r}}async function Bt(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 Ut({manual:t,hub:r},{id:o,token:i,plugin:s,endpoint:a,args:JSON.stringify(c),tenant_id:l,expires_at:u});return Ft(t)?d?t?.onApprovalRequired?t.onApprovalRequired({approvalUrl:d}):Ht(d):Mt:r?d?Ht(d):`Action '${p}' requires user approval before it can run. Could not create approval link. Check hub configuration and server logs.`:Mt}var Ro=new Ws,$n=class extends Error{endpointPath;riskLevel;constructor(n,t){super(`Action '${n}' is a '${t}' operation and is forbidden in readonly mode. Only read operations are permitted \u2014 rewrite the script to avoid write/destructive actions.`),this.name="ReadonlyForbiddenError",this.endpointPath=n,this.riskLevel=t}};function Zs(e){return Ro.run(!0,e)}function _o(){return Ro.getStore()===!0}function Lt(e,n){if(_o()&&n!=="read")throw new $n(e,n)}var Gs={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 Js(e,n,t){return t!==void 0?t:Gs[n][e]}function Nt(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 Eo(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 So(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 Do(e){let n=Js(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"?So(e.db,a.id,e.timeoutMs??600*1e3):{result:"blocked",reason:"pending",id:a.id,token:a.token,expiresAt:a.expires_at})}let c=qs(),l=Ks(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"?So(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 Oo(e){let n={error:e.code,message:e.message,...e.extra};return D(e.status,n)}function Ce(e){return new R(404,"not_found",e)}function ue(e,n={}){return new R(400,"bad_request",e,n)}function Mo(e,n){return F(e,n,t=>Ce(t))}async function Ho(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 Fo(e,n){let t=e.options?.authType??null,r=e.oauthConfig,{configured:o,missingFields:i}=await Ho(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 jn(){return{ok:!0}}async function Le(e){return Promise.all(e.plugins.map(n=>Fo(n,e)))}async function Wn(e,n){let t=Mo(e,n);return Fo(t,e)}async function zs(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 Uo(e,n){let t=await zs(e,n),r=t.filter(o=>o.hasCredentials).map(o=>o.integrationName);return{id:n,accounts:t,connectedPlugins:r}}async function Ne(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 Kn(e,n){if(!n)throw ue("Tenant id must be a non-empty string");return Uo(e,n)}async function qn(e,n){let t=n?.id?.trim();if(!t)throw ue("Tenant id is required",{missingFields:["id"]});return Uo(e,t)}async function Zn(e,n){let t=n?.trim()||"default",r={},o=await tn(e,t);for(let i of o)r[i.plugin]=En(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 $t(e,n){if(!e.database)throw Ce(`Permission '${n}' not found`);let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("id","=",n).executeTakeFirst();if(!t)throw Ce(`Permission '${n}' not found`);return Nn(e,t)}function Vs(e){if(!e.oauthConfig)throw ue(`Plugin '${e.id}' has no oauthConfig`)}function Ys(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 jt(e){let n=Ys(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=Be(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 Bo(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 Xs(e,n){let t=n?.plugin?.trim();if(!t)throw ue("Plugin id is required",{missingFields:["plugin"]});let r=n.tenantId?.trim()||"default",o=Mo(e,t);Vs(o);let i=jt(e);Bo(e);let s=await Ho(o,e);if(!s.configured)throw new R(400,"missing_credentials",`Plugin '${t}' is missing OAuth client credentials`,{missingFields:s.missingFields});let a=Ue(ke(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()+Dt).toISOString()}}async function ea(e,n,t){Bo(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 Fn(e,o);return{connectUrl:a.connectUrl,expiresAt:a.expiresAt}}async function Gn(e,n,t){return Qs(n),n.hub?ea(e,n,t):Xs(n,t)}async function Jn(e,n,t){if(n.hub&&!Be(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"]});jt(n);try{return await Ot(e,r)}catch(o){if(o instanceof q)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 zn(e,n,t){if(n.hub&&!Be(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=jt(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 Wt(e,n){if(!e.database)throw Ce("Permission not found");let t=await e.database.db.selectFrom("corsair_permissions").selectAll().where("token","=",n).executeTakeFirst();if(!t)throw Ce("Permission not found");return Nn(e,t)}async function Lo(e,n){return"id"in n?$t(e,n.id):Wt(e,n.token)}import{createCipheriv as aa,createDecipheriv as Rl,randomBytes as Wo,scryptSync as ca}from"crypto";import{createHmac as Kt,randomUUID as na,timingSafeEqual as $o}from"crypto";function jo(e){if(e)return e.startsWith("sha256=")?e.slice(7):e}function Vn(e){let n=JSON.stringify({type:e.type,payload:e.payload}),t=Math.floor(Date.now()/1e3).toString(),r=Kt("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":na()}}}function qt(e){let n=e.signingSecret.trim();if(!n)return!1;let t=jo(e.signatureHeader);if(!t)return!1;let r=Number(e.timestampHeader);if(!Number.isFinite(r)||Math.abs(Date.now()-r*1e3)>Pe)return!1;let i=Kt("sha256",n).update(e.body).digest("hex");try{return $o(Buffer.from(i,"utf8"),Buffer.from(t,"utf8"))}catch{return!1}}function $e(e){let n=e.signingSecret.trim();if(!n)return{ok:!1,error:"Tunnel signing secret is required"};let t=jo(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)>Pe)return{ok:!1,error:"Tunnel request timestamp is outside the allowed window"};let i=Kt("sha256",n).update(e.body).digest("hex");try{if(!$o(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 je(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function Yn(e){return e.httpOk&&(e.status===204||e.body.status==="ok"||e.body.ok===!0)}function Qn(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 Zt(e){return on(je(e))}async function Gt(e){let n=await nt({deliveryUrl:e.deliveryUrl,projectId:e.projectId,signingSecret:e.signingSecret,type:"connect.create_link",payload:{tenantId:e.tenantId,plugins:e.plugins}}),t=je(n.body),r=Yn({httpOk:n.ok,status:n.status,body:t}),o=on(t);if(!r||!o)throw new Error(et({deliveryUrl:e.deliveryUrl,status:n.status,body:n.body,ack:t}));return o}function Xn(e){return Qn(je(e))}function ta(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 No(e,n=200){let t=e.trim();return t.length<=n?t:`${t.slice(0,n)}\u2026`}var ra="Verify hub.signingSecret in your app matches the signing secret shown in Hub project settings.",oa="Check the delivery URL configured for this environment.";function ia(e){return`${e.ack.error?`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`:`App rejected the signed delivery (HTTP ${e.status} from ${e.deliveryUrl})`}. ${ra}`}function sa(e){return`${e.ack.error?`${e.ack.error} (HTTP 404 from ${e.deliveryUrl})`:`Delivery endpoint not found at ${e.deliveryUrl} (HTTP 404)`}. ${oa}`}function sn(e,n){let t=ta(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 et(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 ia(e);if(e.status===404)return sa(e);if(e.ack.error)return`${e.ack.error} (HTTP ${e.status} from ${e.deliveryUrl})`;if(e.status>=500){let t=e.body.trim();return t?`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl}): ${No(t)}`:`App failed while processing the delivery (HTTP ${e.status} from ${e.deliveryUrl})`}let n=e.body.trim();return n?`${No(n)} (HTTP ${e.status} from ${e.deliveryUrl})`:`Delivery failed with HTTP ${e.status} from ${e.deliveryUrl}`}async function nt(e){let{body:n,headers:t}=Vn(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 ua="aes-256-gcm",la=12,da=16,pa=16,ga=32;function fa(e,n){return ca(e.trim(),n,ga)}function Jt(e,n){let t=n.trim();if(!t)throw new Error("Signing secret is required to encrypt sync manifest");let r=Wo(pa),o=fa(t,r),i=Wo(la),s=aa(ua,o,i,{authTagLength:da}),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 ya=["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 Nr)return!1;if(!(e instanceof Error))return!0;let n=e.message.toLowerCase();return!ya.some(t=>n.includes(t))}function ma(e){if(!e)return[];let n=S(e);return n?(e.authConfig?.[n]?.integration??[]).filter(r=>!be(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 Mn(e,{silent:!0});let[r,o]=await Promise.all([Ne(t),Le(t)]),i={tenants:r.map(s=>({id:s.id})),plugins:o.map(s=>{let a=ma(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 Jt(i,n)}async function tt(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 ha(o.hub,{plugins:o.plugins,database:o.database,kek:o.kek},{tenantId:t,pluginIds:r});return{connectUrl:i.connectUrl,expiresAt:i.expiresAt}}async function ha(e,n,t){let{buildConnectPluginManifestFromContext:r,ensureConnectAccountRowsFromContext:o}=await import("./setup-introspect-YZWWCD2B.js"),{postHubConnectSession:i}=await import("./connect-A2OXYDLE.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 Q=class extends Error{code;constructor(n,t){super(t),this.name="AuthCredentialsDeliveryError",this.code=n}};async function rt(e,n){let t=w(e,()=>new Q("invalid_corsair_instance","Invalid corsair instance"));if(!t.database)throw new Q("no_database","Database not configured");let r=F(t,n.plugin,u=>new Q("plugin_not_found",u)),o=S(r);if(!o)throw new Q("invalid_credentials",`Plugin '${r.id}' has no authType configured`);if(o==="oauth_2"||o==="managed")throw new Q("invalid_credentials","OAuth plugins must be connected via sign-in, not credentials delivery");await Ie(e,n.tenantId);let i=new Set(hn(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 Q("invalid_credentials",`Unknown credential field '${u}' for plugin '${n.plugin}'`);let g=N(c,`set_${u}`);if(!g)throw new Q("invalid_credentials",`Cannot set credential field '${u}' for plugin '${n.plugin}'`);await g(p.trim()),l+=1}if(l===0)throw new Q("invalid_credentials","Provide at least one credential field to save");return{plugin:n.plugin,tenantId:n.tenantId}}var X=class extends Error{code;constructor(n,t){super(t),this.name="IntegrationCredentialsDeliveryError",this.code=n}};async function Vt(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=F(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`);await ko(e);let i=new Set(Wr(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 X("invalid_credentials",`Unknown integration credential field '${u}' for plugin '${n.plugin}'`);let g=N(c,`set_${u}`);if(!g)throw new X("invalid_credentials",`Cannot set integration field '${u}' for plugin '${n.plugin}'`);await g(p.trim()),l+=1}if(l===0)throw new X("invalid_credentials","Provide at least one integration credential field to save");return{plugin:n.plugin}}var ot=new Map;function ba(e){for(let[n,t]of ot)t<=e&&ot.delete(n)}function it(e,n){let t=e.trim();if(!t)return{ok:!1,error:"Delivery replay key is required"};let r=Date.now();return ba(r),ot.has(t)?{ok:!1,error:"Delivery request already consumed"}:(ot.set(t,r+n),{ok:!0})}async function st(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 Ko=e=>{if(!e)return{};if(typeof e=="string")try{return JSON.parse(e)}catch{return{}}return e};async function ka(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 Ca(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 K(n.dek,e.kek),r=Ko(n.config),o={};Object.keys(r).length>0&&(o=ce(r,t)),o[e.link.linkType]=e.link.externalId;let i=he(o,t);await e.database.db.updateTable("corsair_accounts").set({config:i,updated_at:new Date}).where("id","=",n.id).execute()}async function We(e){let{database:n,kek:t,pluginId:r,tenantId:o,link:i,authType:s,extraAccountFields:a=[]}=e,{accountId:c}=await ka({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 Ca({database:n,kek:t,accountId:c,link:i})}async function Yt(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 K(a.dek,t),u=Ko(a.config)[o];if(!u)continue;if(en(u,c)===i)return a}catch{continue}return null}async function at(e){return(await Yt(e))?.tenant_id??null}async function qo(e){return at({database:e.database,kek:e.kek,pluginId:e.pluginId,linkType:e.match.linkType,externalId:e.match.externalId})}function Zo(e){return{tenantId:e.tenantId,plugin:e.plugin,authType:e.authType??"oauth_2",status:"ready",connected:!0,verified:!0,webhookLink:e.link}}function Go(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 Ke(e,n){await $({hub:e,path:"/connections/report",body:Zo(n),parseResponse:()=>({ok:!0})}).catch(()=>{})}function wa(e,n){try{let t=M(e);$({hub:t,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}catch(t){if(t instanceof ie)return}}async function va(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 xe(n,e.plugin,r);o&&zo(e.hub,Go({tenantId:r,plugin:e.plugin.id,authType:o.authType,status:o.status,connected:o.connected,verified:e.verified??o.connected,missingFields:o.missingRequiredFields}))}function Jo(e,n){wa(e,n)}function zo(e,n){$({hub:e,path:"/connections/report",body:n,parseResponse:()=>({ok:!0})}).catch(()=>{})}function cn(e){va(e).catch(()=>{})}async function Qt(e,n){let t=w(e);if(!S(n.plugin))return;let o=await xe(t,n.plugin,n.tenantId);o&&Jo(e,Go({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 we=class extends Error{code;constructor(n,t){super(t),this.name="ManagedOAuthDeliveryError",this.code=n}};async function qe(e,n){let{plugin:t,tenantId:r,accessToken:o,refreshToken:i,expiresIn:s,scope:a}=n;if(!o.trim())throw new we("no_access_token","Managed OAuth delivery missing access_token");let c=w(e,()=>new we("invalid_corsair_instance","Invalid corsair instance"));if(!c.database)throw new we("no_database","No database configured on corsair instance");let l=F(c,t,p=>new we("plugin_not_found",p));await Ie(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 st(c.plugins,t,{access_token:o,refresh_token:i,scope:a});if(p){try{let g=l.authConfig?.managed?.account??[];await We({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&&Ke(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 Ta(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Vo(e,n,t=[]){for(let[r,o]of Object.entries(e))if(Ta(o)){if(o.match(n))return{webhook:o,path:[...t,r]}}else if(o&&typeof o=="object"){let i=Vo(o,n,[...t,r]);if(i)return i}return null}function Pa(e){let n={};for(let[t,r]of Object.entries(e))n[t.toLowerCase()]=Array.isArray(r)?r[0]:r;return n}function Aa(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 Yo(e,n,t,r,o){let i=Pa(n),s=typeof t=="string"?JSON.parse(t):t;(!s||typeof s=="object"&&Object.keys(s).length===0)&&i["x-goog-resource-uri"]&&(s=Aa(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]:bn;for(let d of g){let y=u[d];if(!y||!y.webhooks||!p&&y.pluginWebhookMatcher&&!y.pluginWebhookMatcher(c))continue;let f=Vo(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 Re(e){return e.deliveryMode==="auth.credentials"}function un(e){return e.deliveryMode==="connections.sync"}function ct(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 ut(e){return e.deliveryMode==="oauth.callback"||e.deliveryMode===void 0&&!Re(e)&&!un(e)&&!ct(e)&&!ln(e)&&!dn(e)}async function xa(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 Ia(e,n){try{let t=await tt(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 Xt(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 Sa(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 at({database:n.database,kek:n.kek,pluginId:t.plugin,linkType:t.linkType,externalId:t.externalId})??void 0)}async function Ra(e,n,t){let r=await Sa(e,n,t),o={...t.query??{},...r?{tenantId:r}:{}},i=await Yo(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 _a(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 Ea(e,n){return await qe(e,{plugin:n.plugin,tenantId:n.tenantId,accessToken:n.accessToken,refreshToken:n.refreshToken,expiresIn:n.expiresIn,scope:n.scope}),{status:"ok"}}async function nr(e,n,t){let r=await er(e,{token:n},t);if(r.status!=="ok")throw new Error(r.error??"Permission decision failed")}async function er(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 Da(e,n){try{return await rt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Credential delivery failed"}}}async function Oa(e,n){try{return await Vt(e,n),{status:"ok"}}catch(t){return{status:"failed",retryable:!1,error:t instanceof Error?t.message:"Integration credential delivery failed"}}}async function tr(e,n,t={}){let r=w(e),o=Xt(n.headers,"x-corsair-signature"),i=Xt(n.headers,"x-corsair-timestamp"),s=Xt(n.headers,"x-corsair-nonce");if(t.signingSecret?.trim()){let c=$e({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=it(`nonce:${s.trim()}`,Pe);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 Ra(e,r,a.payload);case"oauth.callback":return _a(e,a.payload);case"oauth.tokens":return Ea(e,a.payload);case"permission.approve":return er(e,a.payload,"approved");case"permission.deny":return er(e,a.payload,"denied");case"auth.credentials":return Da(e,a.payload);case"integration.credentials":return Oa(e,a.payload);case"connect.create_link":return Ia(e,a.payload);case"connections.sync":{let c=t.signingSecret?.trim();return c?xa(e,c):{status:"failed",retryable:!1,error:"Tunnel signing secret is required for connections.sync"}}default:return Ma(String(a.type))}}function Ma(e){return Vr.has(e)?{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}:{status:"failed",retryable:!1,error:`Unsupported tunnel type: ${e}`}}var rr=new Map;function Qo(e){let n;try{n=M(e)}catch{return}let t=Tt(n);t&&rr.get(n.projectApiKey)!==t&&(rr.set(n.projectApiKey,t),$({hub:n,path:"/apps/announce",body:{deliveryUrl:t},parseResponse:()=>({ok:!0})}).catch(()=>{rr.delete(n.projectApiKey)}))}var Ha=[".corsair.dev"];function Fa(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}function Ua(e){try{let{hostname:n,protocol:t}=new URL(e);return t!=="http:"&&t!=="https:"?!1:Fa(n)?!0:Ha.some(r=>n===r.slice(1)||n.endsWith(r))}catch{return!1}}function Xo(e){return!e||!Ua(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 ei(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 or(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 ir(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=ye(o,t.signingSecret);if(!i)return{type:"json",status:400,body:{error:"Invalid or expired delivery token"}};let s=it(`browser:${i.jti}`,fe);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:Oe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",sync:{encrypted:a}}})}}if(ct(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 tt(e,{tenantId:i.tenantId,plugins:a});return{type:"text",status:200,headers:{"Content-Type":"text/html; charset=utf-8"},body:Oe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!0,body:{status:"ok",connectUrl:c.connectUrl,expiresAt:c.expiresAt}})}}if(Re(i))return i.hubSuccessUrl?i.credentials?(await rt(e,{plugin:i.plugin,tenantId:i.tenantId,credentials:i.credentials}),{type:"redirect",url:or(i.hubSuccessUrl,{connectedPlugin:i.plugin})}):{type:"redirect",url:or(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 nr(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 qe(e,{plugin:i.plugin,tenantId:i.tenantId,accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,scope:i.scope})}else{if(!ut(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:Oe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:ct(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Oe({hubOrigin:i.hubOrigin,requestId:i.requestId,ok:!1,error:c})}:Re(i)&&i.hubSuccessUrl?{type:"redirect",url:or(i.hubSuccessUrl,{error:c})}:Re(i)&&i.hubOrigin&&i.requestId?{type:"text",status:400,headers:{"Content-Type":"text/html; charset=utf-8"},body:Oe({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 sr(e,n){let t=M(e),r=await tr(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 ar(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 cr(e,n){return n.method==="GET"?ir(e,n.url):sr(e,{headers:n.headers,body:n.body??""})}async function ur(e,n){try{let t=await cr(e,n);return ar(t)}catch(t){if(t instanceof ie)return Response.json({error:t.message},{status:503});throw t}}async function _e(e,n){Qo(e);let t=n.method.toUpperCase(),r=Xo(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 ur(e,{method:t,url:n.url,headers:n.headers,body:t==="POST"?await n.text():void 0});return ei(o,r)}var ee=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 ni=300;async function lr(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 ee(o,"managed");let u=Math.floor(Date.now()/1e3);if(!s&&a&&c&&Number(c)>u+ni)return{accessToken:a,expiresAt:Number(c),refreshed:!1};if(!l&&a&&!s){let d=c?Number(c):null;if(d===null||d>u+ni)return{accessToken:a,expiresAt:d??u+3600,refreshed:!1}}let p=await La(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 Ba(e){return e.includes("Managed OAuth connection not found")||e.includes("Managed OAuth connection has no tokens")}async function La(e,n,t){try{return await $({hub:e,path:"/oauth/refresh",body:{plugin:n,tenantId:t},parseResponse:An})}catch(r){let o=r instanceof Error?r.message:"";throw Ba(o)?new ee(n,"managed"):r}}async function ti(e,n){e._refreshAuth=async()=>(await lr(n,{forceRefresh:!0})).accessToken}function ri(e){return{delivery:n=>_e(e,n),deliveryOptions:n=>_e(e,n)}}var oi=1200*1e3;function dr(){return oe()}function pr(){return oi}function gr(e,n){return Ye(e,n,oi)}function fr(e,n){return Y(e,n)}function yr(e){return Ae(e)}var ii=600*1e3;function mr(){return oe()}function hr(){return ii}function br(e,n){return Ye(e,n,ii)}function kr(e,n){return Y(e,n)}function Cr(e){return wt(e)}function wr(e){return Ae(e)}function vr(){return oe()}function Tr(e,n,t){return kn(e,n,Math.floor(t.getTime()/1e3))}function Pr(e,n){return Y(e,n)}function Ar(e){return Ae(e)}function lt(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 Na(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 si(e){let{integrationId:n,accountId:t}=await Na(e);return{integrationId:n,accountId:t}}function xr(e,n){return`[auth-missing:${e}] Authentication required. Direct the user to connect their account: ${n}`}async function $a(e,n){let t=e.hub;if(!t||!n.database||!n.kek)return null;try{return(await _t(t,{tenantId:n.tenantId,plugin:n.plugin,database:n.database,kek:n.kek,plugins:n.plugins})).connectUrl}catch{return null}}async function ja(e){let n=e.hub;if(n&&e.database&&e.kek)try{let r=await _t(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}):xr(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 $a({manual:e.manual,hub:e.hub},{plugin:e.plugin,tenantId:e.tenantId,database:e.database,kek:e.kek,plugins:e.plugins});return t?xr(e.pluginId,t):`[auth-missing:${e.pluginId}:${e.authType}]`}function Wa(e,n,t){let r=Ue(ke(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}):xr(e,i)}async function ai(e){let n=e.tenantId??"default",t=e.error.pluginId;return e.manual&&Be(e.manual)&&e.manual.oauthConfig&&e.manual.kek&&e.error.authType==="oauth_2"?Wa(t,{...e.manual,baseUrl:e.manual.baseUrl,kek:e.manual.kek},e.tenantId):e.hub&&e.plugin&&e.kek&&e.database&&e.plugins?ja({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 Ka=async(e,n)=>(console.error(`[corsair:${n.pluginId}:${n.operation}]`,{error:e.message,input:n.input}),{maxRetries:0});async function ci(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||Ka)(e,i)}function qa(e){return typeof e=="function"}function Ir({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(qa(v)){let T=O,A=[...s,b].join("."),k=async(C={})=>{let P=l?.[A];Lt(A,P?.riskLevel??"write");let L;if(c){let j=P,{result:mn,reason:z,onComplete:Je,token:re,id:Te,expiresAt:W}=await Do({pluginId:o,endpointPath:A,args:C,mode:c.mode,override:c.overrides?.[A],riskLevel:j?.riskLevel??"write",meta:j,db:u,timeoutMs:p?Nt(p.timeout):void 0,tenantId:g,approvalMode:p?.mode});if(mn==="blocked"){let V;throw z==="denied"?V=`Action '${A}' was denied by the user. Await further instructions before proceeding.`:z==="policy"?V=`Action '${A}' is blocked by the permission policy. Update the corsair config to allow it.`:z==="timeout"?V=`Action '${A}' timed out waiting for approval.`:re&&Te?V=await Bt({permissionsOptions:p,manual:d,hub:y,permissionId:Te,permissionToken:re,plugin:o,endpoint:A,args:C,tenantId:g??"default",expiresAt:W??new Date(Date.now()+(p?Nt(p.timeout):600*1e3)).toISOString(),operationPath:A}):V=`Action '${A}' requires user approval before it can run.`,new Error(V)}L=Je}let ne=async(j,mn,z)=>{try{return await v(mn,z)}catch(Je){if(Je instanceof Error){let re=await ci(Je,o,A,typeof z=="object"&&z!==null?z:{args:z},i);if(j<(re.maxRetries||0)){let Te=j+1;console.log(`Retrying (${Te} / ${re.maxRetries})...`);let W;if(re.headersRetryAfterMs)W=re.headersRetryAfterMs;else switch(re.retryStrategy){case"exponential_backoff":W=Math.pow(2,Te-1)*1e3;break;case"exponential_backoff_jitter":let V=Math.pow(2,Te-1)*1e3,Fi=(Math.random()-.5)*1e3;W=Math.max(0,V+Fi);break;case"linear_1s":W=1e3;break;case"linear_2s":W=2e3;break;case"linear_3s":W=3e3;break;case"linear_4s":W=4e3;break;default:W=1e3;break}await new Promise(V=>setTimeout(V,W)),await ne(Te,mn,z),console.log(`[corsair:${o}:${A}] Retry strategy:`,re)}}throw Je}},x;try{x=a?await a(t,"endpoint"):void 0}catch(j){if(j instanceof ee)return f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!1}),ai({error:j,manual:d,hub:y,plugin:f,tenantId:g,database:u,kek:m,plugins:h});throw j}if(!T?.before&&!T?.after){let j=await ne(0,{...t,key:x},C);return await L?.(),f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!0}),j}let te={...t,key:x},de=T.before?await T.before(te,C):{ctx:te,args:C,continue:!0,passToAfter:void 0};if(de.continue===!1)return;let yn=await ne(0,de.ctx,de.args);return await T.after?.(de.ctx,yn,de.passToAfter),await L?.(),f&&y&&cn({hub:y,database:u,kek:m,plugins:h??[],plugin:f,tenantId:g,verified:!0}),yn};r[b]=k}else if(v&&typeof v=="object"){let T={};Ir({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 Za(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Sr({webhooks:e,hooks:n,ctx:t,webhooksTree:r,keyBuilder:o}){for(let[i,s]of Object.entries(e)){let a=n?.[i];if(Za(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={};Sr({webhooks:s,hooks:a,ctx:t,webhooksTree:c,keyBuilder:o}),r[i]=c}}}function Ga(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 si({database:e,integrationName:n,tenantId:t,ensureProvisioned:r});return o=i,o}}function Ja(e,n,t,r,o){return e?bt(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 Rr(e,n){let{database:t,tenantId:r,kek:o,rootErrorHandlers:i,permissionsOptions:s,manualConfig:a,hubConfig:c,internalConfig:l}=n,u=l&&t?()=>Dn(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=Ga(t,d.id,f,u);if(y?.entities){let x={};for(let[te,de]of Object.entries(y.entities)){let yn=t?bt(t.db,m,te,y.version,de):Ja(void 0,m,te,y.version,de);x[te]=yn}g[d.id].db=x,p[d.id].db=x}let h=d.options,b=d.authConfig,v;if(t&&o&&h?.authType){let x=b?.[h.authType]?.account??[];v=_({authType:h.authType,integrationName:d.id,tenantId:f,kek:o,database:t,extraAccountFields:x,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;Ir({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 L=d.webhooks??{},ne=d.webhookHooks;if(Object.keys(L).length>0){let x={};Sr({webhooks:L,hooks:ne,ctx:O,webhooksTree:x,keyBuilder:d.keyBuilder}),p[d.id].webhooks=x,d.pluginWebhookMatcher&&(p[d.id].pluginWebhookMatcher=d.pluginWebhookMatcher),d.pluginTenantWebhookMatcher&&(p[d.id].pluginTenantWebhookMatcher=d.pluginTenantWebhookMatcher)}}return p}function ui(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 za="createCorsair({ approval: ... }) is deprecated. Rename to permissions: { timeout, onTimeout, mode }.";function li(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] ${za}`),t):n}var di=[{method:"GET",pattern:"/ok",handler:async()=>D(200,jn())},{method:"GET",pattern:"/tenants",handler:async({internal:e})=>D(200,await Ne(e))},{method:"POST",pattern:"/tenants",handler:async({internal:e,body:n})=>D(201,await qn(e,n))},{method:"GET",pattern:"/tenants/:id",handler:async({internal:e,params:n})=>D(200,await Kn(e,n.id))},{method:"GET",pattern:"/plugins",handler:async({internal:e})=>D(200,await Le(e))},{method:"GET",pattern:"/plugins/:id",handler:async({internal:e,params:n})=>D(200,await Wn(e,n.id))},{method:"GET",pattern:"/connection-status",handler:async({internal:e,query:n})=>D(200,await Zn(e,n.tenantId))},{method:"GET",pattern:"/permissions/:id",handler:async({internal:e,params:n})=>D(200,await $t(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 Wt(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 Gn(e,n,t))},{method:"GET",pattern:"/connect/resolve",handler:async({corsair:e,internal:n,query:t})=>D(200,await Jn(e,n,t.state??""))},{method:"POST",pattern:"/connect/oauth/callback",handler:async({corsair:e,internal:n,body:t})=>D(200,await zn(e,n,t))}];(()=>{let e=new Set;for(let n of di){let t=`${n.method} ${n.pattern}`;if(e.has(t))throw new Error(`Duplicate management route registered: ${t}`);e.add(t)}})();function Va(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 Ya(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 Xa="/api/corsair";function Ee(e,n={}){let t=n.basePath??Xa,r=w(e,()=>new Error("managementHandler: invalid corsair instance (missing internal config)"));return async o=>{try{let i=new URL(o.url),s=Ya(i.pathname,t),a=o.method.toUpperCase();if(a==="OPTIONS"||s==="/"||s==="")return await _e(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 di){if(l.method!==a)continue;let u=Va(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 Ce(`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 Oo(i);let s=i instanceof Error?i.message:"Internal server error";return D(500,{error:"internal_error",message:s})}}}function ec(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 nc(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 pi(e,n){let t=Ee(e,n);return async(r,o,i)=>{try{let s=await t(ec(r));await nc(o,s)}catch(s){i(s)}}}function gi(e,n){let t=Ee(e,n);return r=>t(r.req.raw)}function fi(e,n){let t=Ee(e,n);return{GET:t,POST:t,OPTIONS:t}}function yi(e){let n={[gn]:e};return{ok:jn,tenants:{list:()=>Ne(e),create:t=>qn(e,t),get:t=>Kn(e,t)},plugins:{list:()=>Le(e),get:t=>Wn(e,t)},connectionStatus:{get:t=>Zn(e,t?.tenantId)},permissions:{get:t=>Lo(e,t)},connect:{createLink:t=>Gn(n,e,t),resolve:t=>Jn(n,e,t),oauthCallback:t=>zn(n,e,t)}}}async function mi(e,n,t,r,o="pending"){if(!e)return null;try{let i=Kr(),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 tc(e,n,t,r="pending"){try{let o=await e.$getAccountId();return mi(e.database,o,n,t,r)}catch(o){return console.warn("Failed to log event:",o),null}}import*as bi from"https";import*as dt from"querystring";var rc=["expires_in","refresh_token_expires_in"];function hi(e){let n={...e};for(let t of rc){let r=e[t];if(typeof r=="string"){let o=Number(r);n[t]=Number.isFinite(o)?o:void 0}}return n}function oc(e){try{return hi(JSON.parse(e))}catch{}if(!e.includes("="))return null;let n=dt.parse(e);return!n.access_token&&!n.error?null:hi({...n})}function pt(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=dt.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=bi.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=oc(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 ki=" ";function G(e){let n=e;return n._def??n.def??{}}function J(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 Z(e){return e.innerType??e.schema??e.out??e.in}function wi(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 Z(e)}}function vi(e){let n=e.type;return e.element??(typeof n=="string"?void 0:n)}function ft(e,n){let t=n.shape??e.shape;return typeof t=="function"?t():t}function Ze(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 Ti(e,n){return e.description??n.description}function ic(e){let n=e;for(;n;){let t=G(n),r=Ti(n,t);if(r)return r;let o=J(t);if(Mr(o)||o==="ZodPipe"||o==="ZodEffects"||o==="ZodTransform"){n=wi(t,o);continue}break}}function Mr(e){return e==="ZodOptional"||e==="ZodNullable"||e==="ZodDefault"||e==="ZodCatch"}function U(e){let n=G(e),t=J(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??Ze(n)[0]??"unknown");case"ZodEnum":return Ze(n).map(r=>String(r)).join(" | ");case"ZodOptional":{let r=Z(n);return r?U(r):"unknown"}case"ZodNullable":{let r=Z(n);return`${r?U(r):"unknown"} | null`}case"ZodDefault":case"ZodCatch":{let r=Z(n);return r?U(r):"unknown"}case"ZodArray":{let r=vi(n);if(!r)return"unknown[]";let o=G(r),i=J(o)==="ZodUnion",s=U(r);return`${i?`(${s})`:s}[]`}case"ZodRecord":return"{}";case"ZodObject":{let r=ft(e,n),o=Object.entries(r);return o.length===0?"{}":`{ ${o.map(([s,a])=>{let c=J(G(a));return`${c==="ZodOptional"||c==="ZodNullable"?s+"?":s}: ${U(a)}`}).join(", ")} }`}case"ZodUnion":return Ze(n).map(r=>U(r)).join(" | ");case"ZodIntersection":return`${U(n.left)} & ${U(n.right)}`;case"ZodPipe":case"ZodTransform":case"ZodEffects":{let r=wi(n,t);return r?U(r):"unknown"}default:return(t??"unknown").replace("Zod","").toLowerCase()}}function le(e){let n=G(e),t=J(n),r=Ti(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??Ze(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=Ze(n).map(i=>String(i));return{kind:"string",optional:!1,description:r,enum:o}}case"ZodOptional":{let o=Z(n),i=o?le(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodNullable":{let o=Z(n),i=o?le(o):{kind:"unknown",optional:!1};return{...i,optional:!0,description:r??i.description}}case"ZodDefault":case"ZodCatch":{let o=Z(n);return o?{...le(o),description:r}:{kind:"unknown",optional:!1,description:r}}case"ZodArray":{let o=vi(n);return{kind:"array",optional:!1,description:r,items:o?le(o):{kind:"unknown",optional:!1}}}case"ZodObject":{let o=ft(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=Ze(n);for(let i of o){let s=G(i);if(J(s)==="ZodObject")return{...le(i),description:r}}return{kind:"unknown",optional:!1,description:r}}case"ZodIntersection":case"ZodPipe":case"ZodTransform":case"ZodEffects":{let o=Z(n);return o?{...le(o),description:r}:{kind:"unknown",optional:!1,description:r}}default:return{kind:"unknown",optional:!1,description:r}}}function Xg(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=ve(s.endpointMeta,a),l=ve(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 Hr=["equals","contains","startsWith","endsWith","in"],sc=["equals","gt","gte","lt","lte","in"],ac=["equals"],cc=["equals","before","after","between"];function Pi(e){let n=G(e);switch(J(n)){case"ZodOptional":case"ZodNullable":case"ZodDefault":case"ZodCatch":{let r=Z(n);return r?Pi(r):null}case"ZodString":return"string";case"ZodNumber":return"number";case"ZodBoolean":return"boolean";case"ZodDate":return"date";default:return null}}function Fr(e){let n=G(e),t=J(n);if(Mr(t)){let i=Z(n);return i?Fr(i):{}}if(t!=="ZodObject")return{};let r=ft(e,n),o={};for(let[i,s]of Object.entries(r)){let a=Pi(s);a==="string"?o[i]={type:"string",operators:Hr}:a==="number"?o[i]={type:"number",operators:sc}:a==="boolean"?o[i]={type:"boolean",operators:ac}:a==="date"&&(o[i]={type:"date",operators:cc})}return o}function Ai(e,n){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return[t,r]}function Er(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"&&Er(o,i,t)}}function Dr(e){return e!==null&&typeof e=="object"&&"match"in e&&"handler"in e&&typeof e.match=="function"&&typeof e.handler=="function"}function Or(e,n,t){for(let[r,o]of Object.entries(e)){let i=[...n,r];Dr(o)?t.push(i.join(".")):o!==null&&typeof o=="object"&&Or(o,i,t)}}function Ur(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 Dr(s)?[i]:null;if(s!==null&&typeof s=="object"&&!Dr(s)){let a=Ur(s,r);if(a!==null)return[i,...a]}return null}function xi(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 uc=new Set(bn);function De(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 uc.has(r)?`This plugin (${r}) is not configured. Please add it to the Corsair instance to see its associated methods.`:De(e);if(t==="webhooks"){if(!i.webhooks)return[];let a=[];return Or(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 Er(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=[];Or(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=[];Er(i.endpoints,[],s),o[i.id]=s.map(a=>`${i.id}.api.${a}`)}return o}function ve(e,n){if(e){for(let[t,r]of Object.entries(e))if(t.toLowerCase()===n)return r}}function lc(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 _r(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 ef(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=Ai(y,g);if(f){let[m,h]=f,b=Fr(h),v=[`Search ${o} ${m} stored in the local database.`,"Pass limit and offset as numbers for pagination.","","filters {",` entity_id: string [${Hr.join(", ")}]`];for(let[O,T]of Object.entries(b))v.push(` ${O}?: ${T.type} [${T.operators.join(", ")}]`);return v.push("}"),v.join(`
|
|
30
|
+
`)}}}return _r(De(e,{type:"db"}),"Path not found. Available db operations")}if(i.startsWith("webhooks.")){let u=i.slice(9);if(s.webhooks){let p=Ur(s.webhooks,u.split("."));if(p!==null){let g=p.join("."),d=ve(s.webhookSchemas,g.toLowerCase()),y=d?.response?U(d.response):null,f=[];return d?.description&&f.push(d.description),d?.payload&&f.push(`payload ${gt(Ge(d.payload))}`),y&&f.push(`response: ${y}`),f.push(`usage:
|
|
31
|
+
${xi(o,p)}`),f.join(`
|
|
32
|
+
|
|
33
|
+
`)}}return _r(De(e,{type:"webhooks"}),"Path not found. Available webhooks")}let a=i;a.startsWith("api.")&&(a=a.slice(4));let c=ve(s.endpointMeta,a),l=ve(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 ${gt(Ge(l.input))}`),l?.output&&u.push(`output ${gt(Ge(l.output))}`),u.join(`
|
|
34
|
+
|
|
35
|
+
`)}}}return _r(De(e),"Path not found. Available operations")}function Ci(e){let n=e;for(;;){let t=G(n),r=J(t);if(Mr(r)){let o=Z(t);if(!o)return n;n=o;continue}return n}}function Ge(e){if(e===void 0)return{kind:"inline",type:"unknown"};let n=Ci(e),t=G(n);if(J(t)==="ZodObject"){let o=ft(n,t),i=[];for(let[s,a]of Object.entries(o)){let c=G(a),l=J(c),u=l==="ZodOptional"||l==="ZodNullable",p=Ci(a),g=ic(a);i.push({key:s,optional:u,type:U(p),...g!==void 0?{description:g}:{}})}return{kind:"object",fields:i}}return{kind:"inline",type:U(n)}}function gt(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=ki.repeat(n+1),r=ki.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 dc(e,n){let t=De(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}=lc(u,n),d=ve(r.endpointMeta,g),y=ve(r.endpointSchemas,g);!d&&!y||o.push({path:u,shortPath:p,description:d?.description,riskLevel:d?.riskLevel,irreversible:d?.irreversible,input:Ge(y?.input),output:Ge(y?.output)})}o.sort((u,p)=>u.path.localeCompare(p.path));let i=[],s=De(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=Ur(r.webhooks,y.split("."));if(f===null)continue;let m=f.join("."),h=ve(r.webhookSchemas,m.toLowerCase()),b=h?.response?U(h.response):void 0;i.push({path:u,description:h?.description,payload:Ge(h?.payload),responseType:b,usageExample:xi(n,f)})}i.sort((u,p)=>u.path.localeCompare(p.path));let a=[],c=De(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=Ai(l,m);if(!b)continue;let[v,O]=b,T=Fr(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:Hr},...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 Ii}from"crypto";async function pc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r=Ii(),o=Ii(),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 gc}from"crypto";var yt="https://graph.microsoft.com/v1.0",Br=2e4,fc=60;async function yc(e,n){let t=await e.keys.get_access_token();if(!t)return null;let r={authorization:`Bearer ${t}`};try{let c=await fetch(`${yt}/subscriptions`,{headers:r,signal:AbortSignal.timeout(Br)});if(c.ok){let{value:l}=await c.json(),u=(l??[]).filter(p=>p.notificationUrl===n.webhookUrl);await Promise.all(u.map(p=>fetch(`${yt}/subscriptions/${p.id}`,{method:"DELETE",headers:r,signal:AbortSignal.timeout(Br)}).catch(()=>{})))}}catch{}let o=gc(),i=new Date(Date.now()+fc*6e4).toISOString(),s=await fetch(`${yt}/subscriptions`,{method:"POST",headers:{...r,"content-type":"application/json"},signal:AbortSignal.timeout(Br),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 Si(e,n){for(let[t,r]of Object.entries(e))if(r?.pluginWebhookMatcher&&r.pluginWebhookMatcher(n))return t;return null}function mc(e,n){let t=Si(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 hc(e){let n={};for(let t of e)!t.pluginWebhookMatcher&&!t.pluginTenantWebhookMatcher||(n[t.id]={pluginWebhookMatcher:t.pluginWebhookMatcher,pluginTenantWebhookMatcher:t.pluginTenantWebhookMatcher});return n}function Ri(e,n){let t=n.toLowerCase(),r=e[t]??e[n];return Array.isArray(r)?r[0]:typeof r=="string"?r:void 0}function _i(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 bc(e){return fn(e.body)}function Ei(e,n){let t=e.query;if(!t)return;let r=t[n]??t[n.toLowerCase()];return mt(Array.isArray(r)?r:[r])}function Di(e){let n=e.headers??{},t=[n.validationtoken,n.validationToken,n["validation-token"],n["ms-validation-token"]];for(let c of t){let l=mt(Array.isArray(c)?c:[c]);if(l)return decodeURIComponent(l)}let r=Ei({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 mt([s?.validationToken])??null}function kc(e){if(Di(e))return!0;let n=fn(e.body??e.payload);return Ri(e.headers??{},"content-type")?.includes("text/plain")?!n||Object.keys(n).length===0:!1}function mt(e){for(let n of e){let t=_i(n);if(t)return t}}function Cc(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 bo(e){let n=e.database?Lr(e.database):void 0,t=n&&e.kek?ui(e.plugins,n,e.kek):lt(!!n,!!e.kek),r=li(e),o={plugins:e.plugins,database:n,kek:e.kek,multiTenancy:!!e.multiTenancy,permissions:r,manual:e.manual,hub:e.hub?Cn(e.hub):void 0},i=Eo(n),s=yi(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=Rr(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=Rr(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 Oi(e,n){try{return await In({hub:e,path:`/webhooks/endpoint?plugin=${encodeURIComponent(n)}`,parseResponse:t=>t?.url??null})}catch{return null}}async function ht(e,n,t,r){if(!n.subscribe)return;let o=M(e),i=await Oi(o,n.id);if(!i)return;let s=await n.subscribe({keys:r},{webhookUrl:i});s&&await Qt(e,{plugin:n,tenantId:t,verified:!0,webhookLink:s.webhookLink,webhookSecret:s.webhookSecret})}var B=class extends Error{code;constructor(n,t){super(t),this.name="OAuthCallbackError",this.code=n}};function Mi(e){let n=e.oauthConfig;if(!n)throw new B("plugin_has_no_oauth_config",`Plugin '${e.id}' has no oauthConfig`);return n}async function wc(e,n,t,r){let o=Zr(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 St(e,n,t){let{tenantId:r,redirectUri:o,hubConnect:i=!1}=t,s=w(e,()=>new B("invalid_corsair_instance","Invalid corsair instance"));if(!s.database)throw new Error("No database configured on corsair instance");let a=F(s,n,g=>new B("plugin_not_found",g)),c=Mi(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(Se({oauthConfig:c,clientId:u,redirectUri:o,state:""}));return g.searchParams.delete("state"),{url:g.toString(),state:""}}let p=Ue(ke(n,r),s.kek);return{url:Se({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 B("invalid_corsair_instance","Invalid corsair instance")),s,a;if(n.trusted){if(!n.plugin||!n.tenantId)throw new B("invalid_state","trusted callback requires plugin and tenantId");s=n.plugin,a=n.tenantId}else{let f=Un(r,i.kek);if(!f)throw new B("invalid_state","Invalid or tampered state parameter");s=f.plugin,a=f.tenantId}if(!i.database)throw new B("no_database","No database configured on corsair instance");let c=F(i,s,f=>new B("plugin_not_found",f)),l=Mi(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 B("credentials_not_configured",`Credentials not configured for '${s}'`);await wc(i.database,s,a,i.kek);let d=await pt(t,p,g,l,o);if(!d.access_token)throw new B("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 st(i.plugins,s,d);if(f){try{let m=c.authConfig?.oauth_2?.account??[];await We({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&&Ke(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 ht(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 vc(e){let{corsair:n,internal:t,rows:r}=e,o=e.subscribeAndReport??ht,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 Hi(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 vc({corsair:e,internal:n,rows:t.filter(r=>!!r.tenantId)})}function Tc(e,n={}){let t=!1,r=()=>{t||(t=!0,Hi(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{Gr as a,ge as b,Ct as c,ze as d,Jr as e,zr as f,fe as g,Pe as h,oe as i,Me as j,He as k,ye as l,vt as m,Qr as n,Qe as o,ie as p,Cn as q,M as r,wn as s,Fe as t,vn as u,Tn as v,Pn as w,An as x,eo as y,xn as z,me as A,se as B,ae as C,K as D,Pt as E,en as F,he as G,ce as H,nn as I,E as J,_ as K,lo as L,po as M,ke as N,Et as O,Ke as P,We as Q,Yt as R,at as S,qo as T,Se as U,B as V,St as W,pn as X,Hi as Y,Tc as Z,Mn as _,Ds as $,Hn as aa,Su as ba,Rt as ca,Ru as da,vo as ea,_t as fa,Fn as ga,Po as ha,Ao as ia,Ot as ja,Bn as ka,Ln as la,$n as ma,Zs as na,_o as oa,Lt as pa,Vn as qa,qt as ra,$e as sa,je as ta,Yn as ua,Qn as va,on as wa,Zt as xa,Gt as ya,Xn as za,sn as Aa,et as Ba,nt as Ca,we as Da,qe as Ea,Yo as Fa,Re as Ga,ln as Ha,dn as Ia,ut as Ja,nr as Ka,tr as La,ir as Ma,sr as Na,ar as Oa,cr as Pa,ur as Qa,_e as Ra,ee as Sa,lr as Ta,ti as Ua,ri as Va,dr as Wa,pr as Xa,gr as Ya,fr as Za,yr as _a,mr as $a,hr as ab,br as bb,kr as cb,Cr as db,wr as eb,vr as fb,Tr as gb,Pr as hb,Ar as ib,Ee as jb,pi as kb,gi as lb,fi as mb,mi as nb,tc as ob,pt as pb,Xg as qb,De as rb,ef as sb,gt as tb,dc as ub,pc as vb,yt as wb,yc as xb,Si as yb,mc as zb,hc as Ab,Ri as Bb,_i as Cb,fn as Db,bc as Eb,Ei as Fb,Di as Gb,kc as Hb,mt as Ib,Cc as Jb,gn as Kb,bo as Lb};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-
|
|
2
|
-
export { f as PermissionLookupInput } from '../../types-
|
|
3
|
-
import { C as CorsairClientOptions, a as CorsairManagementClient } from '../../types-
|
|
1
|
+
import { T as Tenant, C as CreateTenantInput, P as PluginInfo, a as ConnectionStatus, b as PermissionRecord, c as ConnectLink, d as CreateConnectLinkInput, O as OAuthCallbackResult, e as OAuthCallbackInput } from '../../types-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-6WGGD3SS.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-
|
|
1
|
+
export { C as CORSAIR_INTERNAL, a as CorsairInternalConfig, c as createCorsair } from './index-D7aqzKjb.js';
|
|
2
2
|
import { CorsairDatabase } from './db.js';
|
|
3
|
-
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor } from './index-
|
|
4
|
-
export {
|
|
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-
|
|
6
|
-
import { A as AuthTypes } from './types-
|
|
7
|
-
export { g as AllProviders, B as BaseProviders, h as PickAuth, j as ProviderDisplayNames, i as formatProviderDisplayName } from './types-
|
|
3
|
+
import { A as AccountKeyManagerFor, I as IntegrationKeyManagerFor, f as CorsairPluginSubscribeResult } from './index-DwegPGYj.js';
|
|
4
|
+
export { g as AccountFieldNames, k as BASE_AUTH_FIELDS, B as BaseAuthFieldConfig, h as BaseKeyManager, M as BeforeHookResult, n as BindEndpoints, a8 as BindWebhooks, a6 as Bivariant, o as BoundEndpointFn, p as BoundEndpointTree, a9 as BoundWebhook, aa as BoundWebhookTree, m as CorsairClient, q as CorsairContext, r as CorsairEndpoint, t as CorsairErrorHandler, c as CorsairIntegration, N as CorsairKeyBuilder, Q as CorsairKeyBuilderBase, ab as CorsairOAuthWebhookTenantLinkResolver, z as CorsairPermissionsNamespace, C as CorsairPlugin, S as CorsairPluginContext, U as CorsairPluginSubscribe, e as CorsairSingleTenantClient, d as CorsairTenantWrapper, ac as CorsairWebhook, ad as CorsairWebhookHandler, ae as CorsairWebhookMatcher, af as CorsairWebhookTenantMatcher, V as EndpointHooks, X as EndpointMetaEntry, E as EndpointPathsOf, Y as EndpointRiskLevel, s as EndpointTree, D as EnforcePermissionOptions, F as EnforcePermissionResult, u as ErrorContext, v as ErrorHandler, w as ErrorHandlerAndMatchFunction, x as ErrorMatcher, i as IntegrationFieldNames, Z as KeyBuilderContext, j as OAuth2IntegrationCredentials, O as OAuthConfig, _ as PermissionMode, $ as PermissionPolicy, P as PluginAuthConfig, a0 as PluginEndpointMeta, a1 as PluginPermissionsConfig, ag as RawWebhookRequest, K as ReadonlyForbiddenError, a2 as RequiredPluginEndpointMeta, a3 as RequiredPluginEndpointSchemas, a4 as RequiredPluginWebhookSchemas, R as RetryStrategies, y as RetryStrategy, T as TokenResponse, a7 as UnionToIntersection, a5 as WebhookHooks, ah as WebhookPathsOf, ai as WebhookRequest, aj as WebhookResponse, W as WebhookTenantMatch, ak as WebhookTree, G as assertReadonlyAllowed, l as exchangeCodeForTokens, J as isReadonlyScopeActive, L as runReadonly } from './index-DwegPGYj.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-f49OxmPU.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
|
-
|
|
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{
|
|
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,Ib as N,J as l,Jb as O,K as m,Kb as P,L as n,Lb as Q,M as o,Sa as u,a,b,ja as p,ma as q,na as r,nb as v,oa as s,ob as w,pa as t,pb 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-6WGGD3SS.js";import{h as c}from"./chunk-BPFUYXOD.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{u as AuthMissingError,c as BASE_AUTH_FIELDS,P as CORSAIR_INTERNAL,B as MS_GRAPH_API_BASE,a as ProviderDisplayNames,q as ReadonlyForbiddenError,I as asRecord,t as assertReadonlyAllowed,F as collectPluginWebhookMatchers,m as createAccountKeyManager,Q as createCorsair,l as createIntegrationKeyManager,O as decodePubSubData,j as decryptConfig,f as decryptDEK,h as decryptWithDEK,i as encryptConfig,e as encryptDEK,g as encryptWithDEK,x as exchangeCodeForTokens,L as extractMicrosoftGraphValidationToken,N as firstString,y as formatDocSchemaShape,b as formatProviderDisplayName,d as generateDEK,G as getHeader,A as googleChannelSubscribe,o as initializeAccountDEK,n as initializeIntegrationDEK,z as introspectPluginForDocs,M as isMicrosoftGraphValidationHandshake,s as isReadonlyScopeActive,v as logEvent,w as logEventFromContext,D as matchWebhookPlugin,E as matchWebhookPluginAndTenant,C as msGraphSubscribe,k as reEncryptConfig,J as readBodyRecord,K as readQueryParam,p as resolveConnectLink,r as runReadonly,H as toExternalId};
|
package/dist/hub.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { A as AuthTypes } from './types-
|
|
2
|
-
export { i as formatProviderDisplayName } from './types-
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
5
|
-
import { g as TunnelType, c as ProcessCorsairRequest, h as WebhookTenantLink } from './index-
|
|
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-
|
|
7
|
-
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-
|
|
1
|
+
import { A as AuthTypes } from './types-1nBbBn-U.js';
|
|
2
|
+
export { i as formatProviderDisplayName } from './types-1nBbBn-U.js';
|
|
3
|
+
import { am as HubOAuthMode, an as HubConnectSessionResult, ao as HubPermissionSessionResult, H as HubConfig, ap as HubConfigInput, aq as HubConnectSessionInput, ar as HubListProjectConnectionsInput, A as AccountKeyManagerFor, as as HubPermissionSessionInput } from './index-DwegPGYj.js';
|
|
4
|
+
export { at as DEFAULT_HUB_API_URL, au as HubEnvironmentSlug } from './index-DwegPGYj.js';
|
|
5
|
+
import { g as TunnelType, c as ProcessCorsairRequest, h as WebhookTenantLink } from './index-CdzrawUJ.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-CdzrawUJ.js';
|
|
7
|
+
export { b as buildBrowserDeliveryRedirectUrl, s as signBrowserDeliveryToken, v as verifyBrowserDeliveryToken } from './browser-delivery-ARqe7lph.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 };
|