corsair 0.1.76 → 0.1.78

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.
@@ -0,0 +1,53 @@
1
+ type TunnelType = 'oauth.callback' | 'oauth.tokens' | 'webhook' | 'permission.approve' | 'permission.deny' | 'auth.credentials' | 'run';
2
+ type TunnelEnvelope<TPayload = unknown> = {
3
+ type: TunnelType;
4
+ payload: TPayload;
5
+ };
6
+ type TunnelAck = {
7
+ status: 'ok' | 'failed';
8
+ retryable?: boolean;
9
+ error?: string;
10
+ webhookResponse?: {
11
+ status?: number;
12
+ body?: unknown;
13
+ headers?: Record<string, string>;
14
+ };
15
+ };
16
+ type WebhookTunnelPayload = {
17
+ headers: Record<string, string>;
18
+ body: string;
19
+ bodyBase64?: string;
20
+ bodyEncoding?: string;
21
+ query?: Record<string, string | string[] | undefined>;
22
+ plugin?: string;
23
+ linkType?: string;
24
+ externalId?: string;
25
+ tenantId?: string;
26
+ };
27
+ type OAuthCallbackTunnelPayload = {
28
+ code: string;
29
+ state: string;
30
+ redirectUri: string;
31
+ };
32
+ type OAuthTokensTunnelPayload = {
33
+ plugin: string;
34
+ tenantId: string;
35
+ accessToken: string;
36
+ refreshToken?: string;
37
+ expiresIn?: number;
38
+ scope?: string;
39
+ };
40
+ type ProcessCorsairRequest = {
41
+ headers: Headers | Record<string, string | string[] | undefined>;
42
+ body: string;
43
+ };
44
+ declare function applyPermissionDecision(corsair: unknown, token: string, decision: 'approved' | 'denied'): Promise<void>;
45
+ type ProcessCorsairOptions = {
46
+ /** HMAC signing secret shared with the tunnel relay. Required unless allowUnsignedTunnel is true. */
47
+ signingSecret?: string;
48
+ /** Local development only. Skips signature verification when signingSecret is omitted. */
49
+ allowUnsignedTunnel?: boolean;
50
+ };
51
+ declare function processCorsair(corsair: unknown, request: ProcessCorsairRequest, options?: ProcessCorsairOptions): Promise<TunnelAck>;
52
+
53
+ export { type OAuthCallbackTunnelPayload as O, type ProcessCorsairOptions as P, type TunnelAck as T, type WebhookTunnelPayload as W, applyPermissionDecision as a, type OAuthTokensTunnelPayload as b, type ProcessCorsairRequest as c, type TunnelEnvelope as d, type TunnelType as e, processCorsair as p };
@@ -0,0 +1,55 @@
1
+ import { CorsairDatabase } from './db.js';
2
+ import { H as HubConfig } from './types-B1We8TTP.js';
3
+ import { C as CorsairPlugin, a as CorsairIntegration, b as CorsairTenantWrapper, c as CorsairSingleTenantClient } from './index-BHyMcpwm.js';
4
+
5
+ declare const CORSAIR_INTERNAL: unique symbol;
6
+ type CorsairInternalConfig = {
7
+ plugins: readonly CorsairPlugin[];
8
+ database: CorsairDatabase | undefined;
9
+ kek: string;
10
+ multiTenancy: boolean;
11
+ approval?: {
12
+ timeout: string;
13
+ onTimeout: 'deny' | 'approve';
14
+ mode?: 'synchronous' | 'asynchronous' | (() => 'synchronous' | 'asynchronous');
15
+ /** Called when a permission is blocked in async mode. Return the message surfaced to the LLM. */
16
+ formatAsyncMessage?: (opts: {
17
+ token: string;
18
+ id: string;
19
+ plugin: string;
20
+ endpoint: string;
21
+ args: unknown;
22
+ }) => string;
23
+ };
24
+ connect?: {
25
+ baseUrl: string;
26
+ redirectUri: string;
27
+ onAuthMissing?: (opts: {
28
+ plugin: string;
29
+ connectUrl: string;
30
+ state: string;
31
+ }) => string;
32
+ };
33
+ hub?: HubConfig;
34
+ };
35
+ /**
36
+ * Creates a Corsair integration with multi-tenancy enabled.
37
+ * Returns a wrapper with a `withTenant()` method to scope operations to specific tenants,
38
+ * and a `keys` property for integration-level key management.
39
+ * @param config - Configuration with plugins, database, and multiTenancy: true
40
+ * @returns A tenant wrapper with `withTenant(tenantId)` method and integration-level `keys`
41
+ */
42
+ declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
43
+ multiTenancy: true;
44
+ }): CorsairTenantWrapper<Plugins>;
45
+ /**
46
+ * Creates a Corsair integration without multi-tenancy.
47
+ * Returns a direct client instance with both plugin APIs and integration-level keys.
48
+ * @param config - Configuration with plugins and optional database
49
+ * @returns A Corsair client instance with plugin APIs and integration-level `keys`
50
+ */
51
+ declare function createCorsair<const Plugins extends readonly CorsairPlugin[]>(config: CorsairIntegration<Plugins> & {
52
+ multiTenancy?: false | undefined;
53
+ }): CorsairSingleTenantClient<Plugins>;
54
+
55
+ export { CORSAIR_INTERNAL as C, type CorsairInternalConfig as a, createCorsair as c };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,15 @@
1
- import { ae as ManagementOk, af as Tenant, ag as CreateTenantInput, ah as PluginInfo, ai as ConnectionStatus, aj as PermissionRecord, k as CorsairSingleTenantClient, C as CorsairPlugin, l as CorsairTenantWrapper, j as CorsairClient, G as CorsairPermissionsNamespace, a5 as BoundWebhookTree, a9 as RawWebhookRequest, n as BaseProviders, ac as WebhookResponse } from './index-DSVPkmM-.js';
2
- export { ak as CorsairManageNamespace, al as PluginConnectionState, d as createCorsair } from './index-DSVPkmM-.js';
3
- import { F as FormFieldSchema, L as ListOperationsOptions } from './index-BnkJ_TYy.js';
4
- export { A as AuthMissingError, R as ResolveConnectLinkResult, f as formatDocSchemaShape, r as resolveConnectLink } from './index-BnkJ_TYy.js';
1
+ import { a1 as ManagementOk, a2 as Tenant, a3 as CreateTenantInput, a4 as PluginInfo, a5 as ConnectionStatus, a6 as PermissionRecord, a7 as CreateConnectLinkInput, a8 as ConnectLink, a9 as ResolvedConnectLink, aa as OAuthCallbackInput, ab as OAuthCallbackResult, c as CorsairSingleTenantClient, C as CorsairPlugin, b as CorsairTenantWrapper, d as CorsairClient, q as CorsairPermissionsNamespace, N as BoundWebhookTree, Y as RawWebhookRequest, X as CorsairWebhookTenantMatcher, $ as WebhookResponse } from './index-BHyMcpwm.js';
2
+ export { ac as CorsairManageNamespace, ad as PluginConnectionState } from './index-BHyMcpwm.js';
3
+ export { c as createCorsair } from './index-mZfhN-6e.js';
4
+ import { F as FormFieldSchema, L as ListOperationsOptions } from './tenant-match-utils-DXoUP9o9.js';
5
+ export { A as AuthMissingError, j as PluginWebhookMatchers, R as ResolveConnectLinkResult, W as WebhookPluginTenantMatch, k as asRecord, g as collectPluginWebhookMatchers, l as decodePubSubData, o as firstString, f as formatDocSchemaShape, p as getHeader, m as matchWebhookPlugin, h as matchWebhookPluginAndTenant, s as readBodyRecord, r as resolveConnectLink, u as toExternalId } from './tenant-match-utils-DXoUP9o9.js';
5
6
  export { SetupCorsairOptions, setupCorsair } from './setup.js';
7
+ export { O as OAuthCallbackTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, p as processCorsair } from './index-aVkEGoHG.js';
8
+ import { g as BaseProviders } from './types-B1We8TTP.js';
9
+ export { R as ResolveAccountFromWebhookLinkInput, W as WebhookTenantLink, r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-UNTSO7K7.js';
10
+ import 'zod';
6
11
  import './db.js';
7
12
  import 'kysely';
8
- import 'zod';
9
13
  import 'pg';
10
14
  import 'postgres';
11
15
  import './orm.js';
@@ -75,6 +79,11 @@ type CorsairManagementClient = {
75
79
  get: (id: string) => Promise<PermissionRecord>;
76
80
  getByToken: (token: string) => Promise<PermissionRecord>;
77
81
  };
82
+ connect: {
83
+ createLink: (input: CreateConnectLinkInput) => Promise<ConnectLink>;
84
+ resolve: (state: string) => Promise<ResolvedConnectLink>;
85
+ oauthCallback: (input: OAuthCallbackInput) => Promise<OAuthCallbackResult>;
86
+ };
78
87
  };
79
88
  declare class CorsairClientError extends Error {
80
89
  readonly status: number;
@@ -207,6 +216,8 @@ type PluginWithWebhooks = {
207
216
  webhooks?: BoundWebhookTree;
208
217
  /** Plugin-level matcher to quickly check if a webhook is for this plugin */
209
218
  pluginWebhookMatcher?: (request: RawWebhookRequest) => boolean;
219
+ /** Extracts the external tenant lookup key for this plugin's webhook */
220
+ pluginTenantWebhookMatcher?: CorsairWebhookTenantMatcher;
210
221
  };
211
222
  /**
212
223
  * The corsair instance type - a record of plugin namespaces.
@@ -245,4 +256,4 @@ declare function processWebhook(corsair: CorsairInstance, headers: WebhookHeader
245
256
  [x: string]: string | string[] | undefined;
246
257
  }): Promise<WebhookFilterResult>;
247
258
 
248
- export { type AnyCorsairInstance, ConnectionStatus, CorsairClientError, type CorsairClientOptions, type CorsairManagementClient, CreateTenantInput, type ExpressHandler, FormFieldSchema, type HonoHandler, ListOperationsOptions, type ManagementHandlerOptions, ManagementOk, type PermissionExecuteResult, PermissionRecord, PluginInfo, Tenant, createCorsairClient, executePermission, getSchema, getStructuredSchema, listOperations, managementHandler, processWebhook, toExpressHandler, toHonoHandler, toNextJsHandler };
259
+ export { type AnyCorsairInstance, ConnectLink, ConnectionStatus, CorsairClientError, type CorsairClientOptions, type CorsairManagementClient, CreateConnectLinkInput, CreateTenantInput, type ExpressHandler, FormFieldSchema, type HonoHandler, ListOperationsOptions, type ManagementHandlerOptions, ManagementOk, OAuthCallbackInput, OAuthCallbackResult, type PermissionExecuteResult, PermissionRecord, PluginInfo, ResolvedConnectLink, Tenant, createCorsairClient, executePermission, getSchema, getStructuredSchema, listOperations, managementHandler, processWebhook, toExpressHandler, toHonoHandler, toNextJsHandler };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{a as H}from"./chunk-UPIMTWVI.js";import{A as k,B as C,C as b,D as w,E as x,G as P,H as j,a as W,s as E,t as $,u as B,v as M,z as A}from"./chunk-LIZVHWQK.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";var l=class extends Error{status;code;extra;constructor(t,r,e,s={}){super(e),this.name="CorsairClientError",this.status=t,this.code=r,this.extra=s}};function _(n){return n.endsWith("/")?n.slice(0,-1):n}async function R(n){let t={};try{t=await n.json()}catch{}let r=typeof t.error=="string"?t.error:"request_failed",e=typeof t.message=="string"?t.message:`Request failed (${n.status})`,{error:s,message:i,...o}=t;return new l(n.status,r,e,o)}function F(n){let t=_(n.baseURL),r=n.fetch??globalThis.fetch.bind(globalThis);async function e(o,u){let a=u&&Object.keys(u).length?`?${new URLSearchParams(u).toString()}`:"",c=await r(`${t}${o}${a}`,{method:"GET"});if(!c.ok)throw await R(c);return await c.json()}async function s(o,u){let a=await r(`${t}${o}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(u)});if(!a.ok)throw await R(a);return await a.json()}let i=encodeURIComponent;return{ok:()=>e("/ok"),tenants:{list:()=>e("/tenants"),create:o=>s("/tenants",o),get:o=>e(`/tenants/${i(o)}`)},plugins:{list:()=>e("/plugins"),get:o=>e(`/plugins/${i(o)}`)},connectionStatus:{get:o=>{let u={};return o?.tenantId&&(u.tenantId=o.tenantId),e("/connection-status",u)}},permissions:{get:o=>e(`/permissions/${i(o)}`),getByToken:o=>s("/permissions/lookup-by-token",{token:o})}}}function y(n){let t=n[P];if(!t)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return t.plugins}function L(n,t){let r=b(y(n),t);return typeof r=="string"?r:Array.isArray(r)?r.join(`
2
- `):Object.values(r).flat().join(`
3
- `)}function N(n,t){return w(y(n),t)}function v(n,t){return C(y(n),t)}var D=Symbol.for("corsair:internal");function q(n,t){let r=n;for(let e of t){if(!r||typeof r!="object")return null;r=r[e]}return typeof r=="function"?r:null}function S(n){return n[D]?.database}async function J(n,t){let r=new Date().toISOString(),e=await n.permissions.find_by_token(t);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<r){let a=S(n);return a&&await a.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let s=e.tenant_id??"default",o=(n.withTenant?n.withTenant(s):n)[e.plugin];if(!o?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let u=q(o.api,e.endpoint.split("."));if(!u)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let a=typeof e.args=="string"?JSON.parse(e.args):e.args,c=await u(a);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:c}}catch(a){let c=a instanceof Error?a.message:String(a),g=S(n);return g&&await g.db.updateTable("corsair_permissions").set({status:"failed",error:c,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:c}}}function U(n){return n!==null&&typeof n=="object"&&"match"in n&&"handler"in n&&typeof n.match=="function"&&typeof n.handler=="function"}function I(n,t,r=[]){for(let[e,s]of Object.entries(n))if(U(s)){if(s.match(t))return{webhook:s,path:[...r,e]}}else if(s&&typeof s=="object"){let i=I(s,t,[...r,e]);if(i)return i}return null}function z(n){let t={};for(let[r,e]of Object.entries(n))t[r.toLowerCase()]=Array.isArray(e)?e[0]:e;return t}function G(n){let t=n["x-goog-resource-uri"],r=n["x-goog-channel-id"];if(!t||!r)return null;let e={resourceId:n["x-goog-resource-id"]||"",resourceState:n["x-goog-resource-state"]||"",resourceUri:t,channelId:r,channelExpiration:n["x-goog-channel-expiration"]||""};return t.includes("/drive/")&&(e.kind="drive#change"),{message:{data:Buffer.from(JSON.stringify(e)).toString("base64"),messageId:n["x-goog-message-number"]||""}}}async function Y(n,t,r,e){let s=z(t),i=typeof r=="string"?JSON.parse(r):r;(!i||typeof i=="object"&&Object.keys(i).length===0)&&s["x-goog-resource-uri"]&&(i=G(s)||i);let u={headers:s,body:i},a=e?.tenantId||"default",c=n.withTenant?n.withTenant(a):n,g=k;for(let m of g){let d=c[m];if(!d||!d.webhooks||d.pluginWebhookMatcher&&!d.pluginWebhookMatcher(u))continue;let f=I(d.webhooks,u);if(!f)continue;let h=f.path.join("."),T={payload:i,headers:s,rawBody:typeof r=="string"?r:JSON.stringify(r)};try{let p=await f.webhook.handler(T),O=!!Object.keys(p.returnToSender||{})?.length;return{plugin:m,action:h,body:i,response:O?{...p?.returnToSender,success:!0}:{success:!0},...p.responseHeaders&&{responseHeaders:p.responseHeaders}}}catch(p){return console.error(`Error executing webhook handler for ${m}.${h}:`,p),{plugin:m,action:h,body:i,response:{success:!1,error:p instanceof Error?p.message:"Unknown error"}}}}return{plugin:null,action:null,body:null}}export{W as AuthMissingError,l as CorsairClientError,j as createCorsair,F as createCorsairClient,J as executePermission,x as formatDocSchemaShape,N as getSchema,v as getStructuredSchema,L as listOperations,E as managementHandler,Y as processWebhook,A as resolveConnectLink,H as setupCorsair,$ as toExpressHandler,B as toHonoHandler,M as toNextJsHandler};
1
+ import{a as B}from"./chunk-KLJBBN2T.js";import{$ as T,Aa as D,Ba as H,Ca as k,Da as j,P as w,U as I,da as S,ea as O,fa as L,ga as A,ha as v,la as d,ma as g,na as C,oa as f,qa as $,ra as E,sa as M,ta as W,ua as F,va as _,w as P,wa as N,x,y as b,z as R}from"./chunk-J6HIPZAR.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";var c=class extends Error{status;code;extra;constructor(r,o,e,a={}){super(e),this.name="CorsairClientError",this.status=r,this.code=o,this.extra=a}};function J(n){return n.endsWith("/")?n.slice(0,-1):n}async function y(n){let r={};try{r=await n.json()}catch{}let o=typeof r.error=="string"?r.error:"request_failed",e=typeof r.message=="string"?r.message:`Request failed (${n.status})`,{error:a,message:u,...t}=r;return new c(n.status,o,e,t)}function U(n){let r=J(n.baseURL),o=n.fetch??globalThis.fetch.bind(globalThis);async function e(t,s){let i=s&&Object.keys(s).length?`?${new URLSearchParams(s).toString()}`:"",p=await o(`${r}${t}${i}`,{method:"GET"});if(!p.ok)throw await y(p);return await p.json()}async function a(t,s){let i=await o(`${r}${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw await y(i);return await i.json()}let u=encodeURIComponent;return{ok:()=>e("/ok"),tenants:{list:()=>e("/tenants"),create:t=>a("/tenants",t),get:t=>e(`/tenants/${u(t)}`)},plugins:{list:()=>e("/plugins"),get:t=>e(`/plugins/${u(t)}`)},connectionStatus:{get:t=>{let s={};return t?.tenantId&&(s.tenantId=t.tenantId),e("/connection-status",s)}},permissions:{get:t=>e(`/permissions/${u(t)}`),getByToken:t=>a("/permissions/lookup-by-token",{token:t})},connect:{createLink:t=>a("/connect/links",t),resolve:t=>e("/connect/resolve",{state:t}),oauthCallback:t=>a("/connect/oauth/callback",t)}}}function l(n){let r=n[k];if(!r)throw new Error("listOperations / getSchema: invalid corsair instance. Pass the value returned by createCorsair() or corsair.withTenant().");return r.plugins}function q(n,r){let o=g(l(n),r);return typeof o=="string"?o:Array.isArray(o)?o.join(`
2
+ `):Object.values(o).flat().join(`
3
+ `)}function G(n,r){return C(l(n),r)}function Y(n,r){return d(l(n),r)}var z=Symbol.for("corsair:internal");function K(n,r){let o=n;for(let e of r){if(!o||typeof o!="object")return null;o=o[e]}return typeof o=="function"?o:null}function h(n){return n[z]?.database}async function Q(n,r){let o=new Date().toISOString(),e=await n.permissions.find_by_token(r);if(!e)return console.error("executePermission: no permission found for token."),{error:"executePermission: no permission found for token."};if(e.status!=="approved")return console.error(`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: permission '${e.id}' is '${e.status}', expected 'approved'.`};if(e.expires_at<o){let i=h(n);return i&&await i.db.updateTable("corsair_permissions").set({status:"expired",updated_at:new Date}).where("id","=",e.id).execute(),console.error(`executePermission: permission '${e.id}' has expired.`),{error:`executePermission: permission '${e.id}' has expired.`,endpoint:e.endpoint,plugin:e.plugin,result:null}}let a=e.tenant_id??"default",t=(n.withTenant?n.withTenant(a):n)[e.plugin];if(!t?.api)return console.error(`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`),{error:`executePermission: plugin '${e.plugin}' not found or has no API on this corsair instance.`,plugin:e.plugin,endpoint:e.endpoint,result:null};let s=K(t.api,e.endpoint.split("."));if(!s)return console.error(`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`),{endpoint:e.endpoint,plugin:e.plugin,result:null,error:`executePermission: endpoint '${e.endpoint}' not found in plugin '${e.plugin}'.`};await n.permissions.set_executing(e.id);try{let i=typeof e.args=="string"?JSON.parse(e.args):e.args,p=await s(i);return await n.permissions.set_completed(e.id),{plugin:e.plugin,endpoint:e.endpoint,result:p}}catch(i){let p=i instanceof Error?i.message:String(i),m=h(n);return m&&await m.db.updateTable("corsair_permissions").set({status:"failed",error:p,updated_at:new Date}).where("id","=",e.id).execute(),{plugin:e.plugin,endpoint:e.endpoint,result:null,error:p}}}export{T as AuthMissingError,c as CorsairClientError,_ as asRecord,M as collectPluginWebhookMatchers,j as createCorsair,U as createCorsairClient,H as decodePubSubData,Q as executePermission,D as firstString,f as formatDocSchemaShape,W as getHeader,G as getSchema,Y as getStructuredSchema,q as listOperations,O as managementHandler,$ as matchWebhookPlugin,E as matchWebhookPluginAndTenant,I as processCorsair,w as processWebhook,N as readBodyRecord,x as resolveAccountFromWebhookLink,S as resolveConnectLink,R as resolveTenantFromWebhookLink,b as resolveTenantIdFromWebhookLink,P as setWebhookTenantLink,B as setupCorsair,L as toExpressHandler,F as toExternalId,A as toHonoHandler,v as toNextJsHandler};
package/dist/oauth.d.ts CHANGED
@@ -8,6 +8,11 @@ declare function decodeOAuthState(state: string, { maxAgeMs }?: {
8
8
  maxAgeMs?: number;
9
9
  }): OAuthState | null;
10
10
 
11
+ type OAuthCallbackErrorCode = 'invalid_corsair_instance' | 'no_database' | 'invalid_state' | 'plugin_not_found' | 'plugin_has_no_oauth_config' | 'credentials_not_configured' | 'no_access_token';
12
+ declare class OAuthCallbackError extends Error {
13
+ readonly code: OAuthCallbackErrorCode;
14
+ constructor(code: OAuthCallbackErrorCode, message: string);
15
+ }
11
16
  type GenerateOAuthUrlOptions = {
12
17
  tenantId: string;
13
18
  redirectUri: string;
@@ -50,4 +55,4 @@ type ProcessOAuthCallbackResult = {
50
55
  */
51
56
  declare function processOAuthCallback(corsair: unknown, options: ProcessOAuthCallbackOptions): Promise<ProcessOAuthCallbackResult>;
52
57
 
53
- export { type GenerateOAuthUrlOptions, type GenerateOAuthUrlResult, type ProcessOAuthCallbackOptions, type ProcessOAuthCallbackResult, decodeOAuthState, encodeOAuthState, generateOAuthUrl, processOAuthCallback };
58
+ export { type GenerateOAuthUrlOptions, type GenerateOAuthUrlResult, OAuthCallbackError, type OAuthCallbackErrorCode, type ProcessOAuthCallbackOptions, type ProcessOAuthCallbackResult, decodeOAuthState, encodeOAuthState, generateOAuthUrl, processOAuthCallback };
package/dist/oauth.js CHANGED
@@ -1 +1 @@
1
- import{G as x,b as C,c as O,k as p,l as m,o as f,p as _,q as A,r as y,y as b}from"./chunk-LIZVHWQK.js";import{b as P}from"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";import*as E from"querystring";function I(n){let e=n[x];if(!e)throw new Error("Invalid corsair instance");return e}function U(n,e){let o=n.plugins.find(a=>a.id===e);if(!o)throw new Error(`Plugin '${e}' not found`);return o}function N(n){let e=n.oauthConfig;if(!e)throw new Error(`Plugin '${n.id}' has no oauthConfig`);return e}async function R(n,e,o,a){let i=P(n),t=await i.integrations.findByName(e);if(!t)throw new Error(`Integration '${e}' not found. Run setupCorsair first.`);if(await i.accounts.findOne({tenant_id:o,integration_id:t.id}))return;let r=C(),s=await O(r,a);await i.accounts.create({tenant_id:o,integration_id:t.id,config:{},dek:s})}async function S(n,e,o){let{tenantId:a,redirectUri:i}=o,t=I(n);if(!t.database)throw new Error("No database configured on corsair instance");let u=U(t,e),r=N(u),d=await p({authType:"oauth_2",integrationName:e,kek:t.kek,database:t.database}).get_client_id();if(!d)throw new Error(`client_id not configured for '${e}'`);let g=A(f(e,a),t.kek),l={...r.authParams,client_id:d,redirect_uri:i,response_type:"code",scope:r.scopes.join(" "),state:g};return{url:`${r.authUrl}?${E.stringify(l)}`,state:g}}async function K(n,e){let{code:o,state:a,redirectUri:i}=e,t=I(n),u=y(a,t.kek);if(!u)throw new Error("Invalid or tampered state parameter");let{plugin:r,tenantId:s}=u;if(!t.database)throw new Error("No database configured on corsair instance");let d=U(t,r),g=N(d),l=p({authType:"oauth_2",integrationName:r,kek:t.kek,database:t.database}),k=await l.get_client_id(),w=await l.get_client_secret();if(!k||!w)throw new Error(`Credentials not configured for '${r}'`);await R(t.database,r,s,t.kek);let c=await b(o,k,w,g,i);if(!c.access_token)throw new Error(`No access_token returned from ${g.providerName}`);let h=m({authType:"oauth_2",integrationName:r,tenantId:s,kek:t.kek,database:t.database});return await h.set_access_token(c.access_token),c.refresh_token&&await h.set_refresh_token(c.refresh_token),c.expires_in&&await h.set_expires_at(String(Math.floor(Date.now()/1e3)+c.expires_in)),{plugin:r,tenantId:s}}export{_ as decodeOAuthState,f as encodeOAuthState,S as generateOAuthUrl,K as processOAuthCallback};
1
+ import{A as c,B as d,C as e,h as a,i as b}from"./chunk-J6HIPZAR.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{c as OAuthCallbackError,b as decodeOAuthState,a as encodeOAuthState,d as generateOAuthUrl,e as processOAuthCallback};
package/dist/orm.js CHANGED
@@ -1 +1 @@
1
- import"./chunk-N2XRSSRL.js";import{b as o,c as e,d as n,e as s}from"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import{a as r,b as t,c as i,d as a}from"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
1
+ import"./chunk-N2XRSSRL.js";import{d as o,e,f as n,g as s}from"./chunk-3X6WVI5I.js";import{b as r,c as t,d as i,e as a}from"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{t as CorsairAccountsSchema,i as CorsairEntitiesSchema,a as CorsairEventsSchema,r as CorsairIntegrationsSchema,o as createCorsairOrm,e as createPluginOrm,s as createPluginOrmFactory,n as createTenantScopedOrm};
package/dist/setup.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { C as CorsairPlugin, k as CorsairSingleTenantClient, l as CorsairTenantWrapper, c as CorsairInternalConfig } from './index-DSVPkmM-.js';
1
+ import { a as CorsairInternalConfig } from './index-mZfhN-6e.js';
2
2
  import { CorsairDatabase } from './db.js';
3
- import 'zod';
4
- import './orm.js';
3
+ import { C as CorsairPlugin, c as CorsairSingleTenantClient, b as CorsairTenantWrapper } from './index-BHyMcpwm.js';
4
+ import './types-B1We8TTP.js';
5
5
  import 'kysely';
6
+ import 'zod';
6
7
  import 'pg';
7
8
  import 'postgres';
9
+ import './orm.js';
8
10
 
9
11
  /** Plugin id → credential field → value (from CLI `field=value` pairs). */
10
12
  type SetupCredentials = Record<string, Record<string, string>>;
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{a as o,b as r}from"./chunk-UPIMTWVI.js";import"./chunk-LIZVHWQK.js";import"./chunk-UBM25HVI.js";import"./chunk-OZHME3EO.js";import"./chunk-3USHGH6P.js";import"./chunk-FL4GOHVN.js";import"./chunk-QAIKSQAD.js";export{r as applySetupCredentials,o as setupCorsair};
1
+ import{a as o,b as r}from"./chunk-KLJBBN2T.js";import"./chunk-J6HIPZAR.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{r as applySetupCredentials,o as setupCorsair};
@@ -0,0 +1,43 @@
1
+ import { A as AuthTypes } from './types-B1We8TTP.js';
2
+ import { W as WebhookTenantMatch } from './index-BHyMcpwm.js';
3
+ import { CorsairDatabase, CorsairAccount } from './db.js';
4
+
5
+ type WebhookTenantLink = WebhookTenantMatch;
6
+ declare function setWebhookTenantLink(options: {
7
+ database: CorsairDatabase;
8
+ kek: string;
9
+ pluginId: string;
10
+ tenantId: string;
11
+ link: WebhookTenantLink;
12
+ authType?: AuthTypes;
13
+ extraAccountFields?: readonly string[];
14
+ }): Promise<void>;
15
+ type ResolveAccountFromWebhookLinkInput = {
16
+ database: CorsairDatabase;
17
+ kek: string;
18
+ pluginId: string;
19
+ linkType: string;
20
+ externalId: string;
21
+ };
22
+ /**
23
+ * Resolves the matching corsair_accounts row for a webhook tenant link.
24
+ *
25
+ * Runs one SQL query scoped to the plugin, then decrypts only the requested
26
+ * link field per account using the account DEK and KEK.
27
+ */
28
+ declare function resolveAccountFromWebhookLink(options: ResolveAccountFromWebhookLinkInput): Promise<CorsairAccount | null>;
29
+ declare function resolveTenantIdFromWebhookLink(options: {
30
+ database: CorsairDatabase;
31
+ kek: string;
32
+ pluginId: string;
33
+ linkType: string;
34
+ externalId: string;
35
+ }): Promise<string | null>;
36
+ declare function resolveTenantFromWebhookLink(options: {
37
+ database: CorsairDatabase;
38
+ kek: string;
39
+ pluginId: string;
40
+ match: WebhookTenantMatch;
41
+ }): Promise<string | null>;
42
+
43
+ export { type ResolveAccountFromWebhookLinkInput as R, type WebhookTenantLink as W, resolveTenantFromWebhookLink as a, resolveTenantIdFromWebhookLink as b, resolveAccountFromWebhookLink as r, setWebhookTenantLink as s };
@@ -1,4 +1,5 @@
1
- import { E as EndpointRiskLevel, C as CorsairPlugin } from './index-DSVPkmM-.js';
1
+ import { z as EndpointRiskLevel, C as CorsairPlugin, V as CorsairWebhookMatcher, X as CorsairWebhookTenantMatcher, Y as RawWebhookRequest, W as WebhookTenantMatch } from './index-BHyMcpwm.js';
2
+ import { f as AllProviders } from './types-B1We8TTP.js';
2
3
 
3
4
  /**
4
5
  * Error thrown when a plugin endpoint is called but the required auth credentials
@@ -184,4 +185,43 @@ declare function formatDocSchemaShape(shape: DocSchemaShape | undefined, depth?:
184
185
  */
185
186
  declare function introspectPluginForDocs(plugins: readonly CorsairPlugin[], pluginId: string): IntrospectPluginForDocsResult;
186
187
 
187
- export { AuthMissingError as A, type DocSchemaFieldRow as D, type EndpointSchemaResult as E, type FormFieldSchema as F, type IntrospectPluginForDocsResult as I, type ListOperationsOptions as L, type PluginDocsIntrospection as P, type ResolveConnectLinkResult as R, type DocSchemaShape as a, type DocsApiEndpoint as b, type DocsDbEntity as c, type DocsDbFilterField as d, type DocsWebhook as e, formatDocSchemaShape as f, introspectPluginForDocs as i, resolveConnectLink as r };
188
+ type PluginWebhookMatchers = {
189
+ pluginWebhookMatcher?: CorsairWebhookMatcher;
190
+ pluginTenantWebhookMatcher?: CorsairWebhookTenantMatcher;
191
+ };
192
+ type WebhookPluginTenantMatch = {
193
+ plugin: AllProviders | (string & {});
194
+ tenantMatch: WebhookTenantMatch;
195
+ };
196
+ /**
197
+ * Identifies which plugin an incoming webhook belongs to.
198
+ */
199
+ declare function matchWebhookPlugin(plugins: Record<string, PluginWebhookMatchers | undefined>, request: RawWebhookRequest): string | null;
200
+ /**
201
+ * Runs plugin identification, then extracts the tenant lookup key for that plugin.
202
+ */
203
+ declare function matchWebhookPluginAndTenant(plugins: Record<string, PluginWebhookMatchers | undefined>, request: RawWebhookRequest): WebhookPluginTenantMatch | null;
204
+ /**
205
+ * Collects plugin-level webhook matchers from a corsair plugin list.
206
+ */
207
+ declare function collectPluginWebhookMatchers(plugins: readonly CorsairPlugin[]): Record<string, PluginWebhookMatchers>;
208
+
209
+ declare function getHeader(headers: Record<string, string | string[] | undefined>, name: string): string | undefined;
210
+ declare function toExternalId(value: unknown): string | undefined;
211
+ declare function asRecord(value: unknown): Record<string, unknown> | null;
212
+ declare function readBodyRecord(request: RawWebhookRequest): Record<string, unknown> | null;
213
+ declare function readQueryParam(request: {
214
+ query?: Record<string, string | string[] | undefined>;
215
+ }, name: string): string | undefined;
216
+ type MicrosoftGraphValidationRequest = {
217
+ headers?: Record<string, string | string[] | undefined>;
218
+ body?: unknown;
219
+ payload?: unknown;
220
+ query?: Record<string, string | string[] | undefined>;
221
+ };
222
+ declare function extractMicrosoftGraphValidationToken(request: MicrosoftGraphValidationRequest): string | null;
223
+ declare function isMicrosoftGraphValidationHandshake(request: MicrosoftGraphValidationRequest): boolean;
224
+ declare function firstString(values: unknown[]): string | undefined;
225
+ declare function decodePubSubData(body: Record<string, unknown>): unknown;
226
+
227
+ export { AuthMissingError as A, type DocSchemaFieldRow as D, type EndpointSchemaResult as E, type FormFieldSchema as F, type IntrospectPluginForDocsResult as I, type ListOperationsOptions as L, type PluginDocsIntrospection as P, type ResolveConnectLinkResult as R, type WebhookPluginTenantMatch as W, type DocSchemaShape as a, type DocsApiEndpoint as b, type DocsDbEntity as c, type DocsDbFilterField as d, type DocsWebhook as e, formatDocSchemaShape as f, collectPluginWebhookMatchers as g, matchWebhookPluginAndTenant as h, introspectPluginForDocs as i, type PluginWebhookMatchers as j, asRecord as k, decodePubSubData as l, matchWebhookPlugin as m, extractMicrosoftGraphValidationToken as n, firstString as o, getHeader as p, isMicrosoftGraphValidationHandshake as q, resolveConnectLink as r, readBodyRecord as s, readQueryParam as t, toExternalId as u };
@@ -0,0 +1,35 @@
1
+ export { O as OAuthCallbackTunnelPayload, b as OAuthTokensTunnelPayload, P as ProcessCorsairOptions, c as ProcessCorsairRequest, T as TunnelAck, d as TunnelEnvelope, e as TunnelType, W as WebhookTunnelPayload, a as applyPermissionDecision, p as processCorsair } from './index-aVkEGoHG.js';
2
+ export { r as resolveAccountFromWebhookLink, a as resolveTenantFromWebhookLink, b as resolveTenantIdFromWebhookLink, s as setWebhookTenantLink } from './tenant-links-UNTSO7K7.js';
3
+ import './types-B1We8TTP.js';
4
+ import './index-BHyMcpwm.js';
5
+ import 'zod';
6
+ import './db.js';
7
+ import 'kysely';
8
+ import 'pg';
9
+ import 'postgres';
10
+ import './orm.js';
11
+
12
+ type BrowserDeliveryPayload = {
13
+ jti: string;
14
+ connectJti: string;
15
+ projectId: string;
16
+ plugin: string;
17
+ tenantId: string;
18
+ hubSuccessUrl: string;
19
+ exp: number;
20
+ iat: number;
21
+ deliveryMode?: 'oauth.callback' | 'oauth.tokens' | 'permission.approve' | 'permission.deny';
22
+ code?: string;
23
+ state?: string;
24
+ redirectUri?: string;
25
+ accessToken?: string;
26
+ refreshToken?: string;
27
+ expiresIn?: number;
28
+ scope?: string;
29
+ permissionToken?: string;
30
+ };
31
+ declare function isPermissionBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
32
+ declare function isManagedBrowserDelivery(payload: BrowserDeliveryPayload): boolean;
33
+ declare function verifyBrowserDeliveryToken(token: string, signingSecret: string): BrowserDeliveryPayload | null;
34
+
35
+ export { type BrowserDeliveryPayload, isManagedBrowserDelivery, isPermissionBrowserDelivery, verifyBrowserDeliveryToken };
package/dist/tunnel.js ADDED
@@ -0,0 +1 @@
1
+ import{Q as e,R as f,S as g,T as h,U as i,w as a,x as b,y as c,z as d}from"./chunk-J6HIPZAR.js";import"./chunk-3X6WVI5I.js";import"./chunk-IGGCNGU2.js";import"./chunk-QAIKSQAD.js";export{h as applyPermissionDecision,f as isManagedBrowserDelivery,e as isPermissionBrowserDelivery,i as processCorsair,b as resolveAccountFromWebhookLink,d as resolveTenantFromWebhookLink,c as resolveTenantIdFromWebhookLink,a as setWebhookTenantLink,g as verifyBrowserDeliveryToken};