corsair 0.1.18 → 0.1.20
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/core/client/index.d.ts.map +1 -1
- package/dist/core/client/index.js +1 -0
- package/dist/core/endpoints/bind.d.ts +3 -1
- package/dist/core/endpoints/bind.d.ts.map +1 -1
- package/dist/core/endpoints/bind.js +24 -19
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/permissions/index.d.ts +22 -5
- package/dist/core/permissions/index.d.ts.map +1 -1
- package/dist/core/permissions/index.js +52 -10
- package/dist/db/index.d.ts +13 -19
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +7 -7
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/permissions/index.d.ts +47 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +106 -0
- package/dist/plugins/resend/endpoints/index.d.ts +1 -1
- package/dist/plugins/resend/endpoints/types.d.ts +6 -6
- package/dist/plugins/resend/index.d.ts +4 -4
- package/dist/plugins/resend/schema/database.d.ts +2 -2
- package/dist/plugins/resend/schema/index.d.ts +2 -2
- package/dist/plugins/slack/webhooks/messages.d.ts.map +1 -1
- package/dist/plugins/slack/webhooks/messages.js +29 -10
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/client/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ export declare function isEndpoint(value: unknown): value is Function;
|
|
|
19
19
|
* @param currentPath - The current path for tracking nested endpoint operations
|
|
20
20
|
* @param keyBuilder - Optional async callback to generate a key from the plugin context
|
|
21
21
|
*/
|
|
22
|
-
export declare function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId, errorHandlers, currentPath, keyBuilder, permissionsConfig, endpointMeta, database, approvalConfig, }: {
|
|
22
|
+
export declare function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId, errorHandlers, currentPath, keyBuilder, permissionsConfig, endpointMeta, database, approvalConfig, tenantId, }: {
|
|
23
23
|
endpoints: Record<string, unknown>;
|
|
24
24
|
hooks: Record<string, unknown> | undefined;
|
|
25
25
|
ctx: Record<string, unknown>;
|
|
@@ -42,5 +42,7 @@ export declare function bindEndpointsRecursively({ endpoints, hooks, ctx, tree,
|
|
|
42
42
|
timeout: string;
|
|
43
43
|
onTimeout: 'deny' | 'approve';
|
|
44
44
|
};
|
|
45
|
+
/** Tenant ID for multi-tenant instances. Forwarded to the permission record so executePermission can scope correctly. */
|
|
46
|
+
tenantId?: string;
|
|
45
47
|
}): void;
|
|
46
48
|
//# sourceMappingURL=bind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../../core/endpoints/bind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,KAAK,EACX,qBAAqB,EAErB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAMpB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,SAAS,EACT,KAAK,EACL,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,WAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,cAAc,
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../../core/endpoints/bind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,KAAK,EACX,qBAAqB,EAErB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAMpB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACxC,SAAS,EACT,KAAK,EACL,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,WAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,QAAQ,GACR,EAAE;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,mBAAmB,CAAC;IACnC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,mGAAmG;IACnG,iBAAiB,CAAC,EAAE;QACnB,IAAI,EAAE,cAAc,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KAC7C,CAAC;IACF,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,qEAAqE;IACrE,cAAc,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACpE,yHAAyH;IACzH,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CA6JP"}
|
|
@@ -23,7 +23,7 @@ export function isEndpoint(value) {
|
|
|
23
23
|
* @param currentPath - The current path for tracking nested endpoint operations
|
|
24
24
|
* @param keyBuilder - Optional async callback to generate a key from the plugin context
|
|
25
25
|
*/
|
|
26
|
-
export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId, errorHandlers, currentPath = [], keyBuilder, permissionsConfig, endpointMeta, database, approvalConfig, }) {
|
|
26
|
+
export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId, errorHandlers, currentPath = [], keyBuilder, permissionsConfig, endpointMeta, database, approvalConfig, tenantId, }) {
|
|
27
27
|
for (const [key, value] of Object.entries(endpoints)) {
|
|
28
28
|
// we have to retype this now because it's nested webhooks
|
|
29
29
|
const nodeHooks = hooks?.[key];
|
|
@@ -33,9 +33,10 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
33
33
|
const operationPath = [...currentPath, key].join('.');
|
|
34
34
|
const boundFn = async (args) => {
|
|
35
35
|
// ── Permission guard ────────────────────────────────────────────────────────────────
|
|
36
|
+
let onPermissionComplete;
|
|
36
37
|
if (permissionsConfig) {
|
|
37
38
|
const meta = endpointMeta?.[operationPath];
|
|
38
|
-
const permResult = await enforcePermission({
|
|
39
|
+
const { result: permResult, onComplete } = await enforcePermission({
|
|
39
40
|
pluginId,
|
|
40
41
|
endpointPath: operationPath,
|
|
41
42
|
args,
|
|
@@ -48,9 +49,11 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
48
49
|
timeoutMs: approvalConfig
|
|
49
50
|
? parseDurationMs(approvalConfig.timeout)
|
|
50
51
|
: undefined,
|
|
52
|
+
tenantId,
|
|
51
53
|
});
|
|
52
54
|
if (permResult === 'blocked')
|
|
53
55
|
return null;
|
|
56
|
+
onPermissionComplete = onComplete;
|
|
54
57
|
}
|
|
55
58
|
const call = async (attemptNumber, callCtx, callArgs) => {
|
|
56
59
|
try {
|
|
@@ -105,24 +108,25 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
105
108
|
};
|
|
106
109
|
const key = keyBuilder ? await keyBuilder(ctx, 'endpoint') : undefined;
|
|
107
110
|
if (!endpointHooks?.before && !endpointHooks?.after) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return (async () => {
|
|
111
|
-
const ctxWithKey = { ...ctx, key };
|
|
112
|
-
const beforeResult = endpointHooks.before
|
|
113
|
-
? await endpointHooks.before(ctxWithKey, args)
|
|
114
|
-
: {
|
|
115
|
-
ctx: ctxWithKey,
|
|
116
|
-
args,
|
|
117
|
-
continue: true,
|
|
118
|
-
passToAfter: undefined,
|
|
119
|
-
};
|
|
120
|
-
if (beforeResult.continue === false)
|
|
121
|
-
return;
|
|
122
|
-
const res = await call(0, beforeResult.ctx, beforeResult.args);
|
|
123
|
-
await endpointHooks.after?.(beforeResult.ctx, res, beforeResult.passToAfter);
|
|
111
|
+
const res = await call(0, { ...ctx, key }, args);
|
|
112
|
+
await onPermissionComplete?.();
|
|
124
113
|
return res;
|
|
125
|
-
}
|
|
114
|
+
}
|
|
115
|
+
const ctxWithKey = { ...ctx, key };
|
|
116
|
+
const beforeResult = endpointHooks.before
|
|
117
|
+
? await endpointHooks.before(ctxWithKey, args)
|
|
118
|
+
: {
|
|
119
|
+
ctx: ctxWithKey,
|
|
120
|
+
args,
|
|
121
|
+
continue: true,
|
|
122
|
+
passToAfter: undefined,
|
|
123
|
+
};
|
|
124
|
+
if (beforeResult.continue === false)
|
|
125
|
+
return;
|
|
126
|
+
const res = await call(0, beforeResult.ctx, beforeResult.args);
|
|
127
|
+
await endpointHooks.after?.(beforeResult.ctx, res, beforeResult.passToAfter);
|
|
128
|
+
await onPermissionComplete?.();
|
|
129
|
+
return res;
|
|
126
130
|
};
|
|
127
131
|
tree[key] = boundFn;
|
|
128
132
|
}
|
|
@@ -142,6 +146,7 @@ export function bindEndpointsRecursively({ endpoints, hooks, ctx, tree, pluginId
|
|
|
142
146
|
endpointMeta,
|
|
143
147
|
database,
|
|
144
148
|
approvalConfig,
|
|
149
|
+
tenantId,
|
|
145
150
|
});
|
|
146
151
|
tree[key] = nestedTree;
|
|
147
152
|
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export type { AllProviders, AuthTypes, BaseProviders } from './constants';
|
|
|
38
38
|
export type { BindEndpoints, BoundEndpointFn, BoundEndpointTree, CorsairContext, CorsairEndpoint, EndpointPathsOf, EndpointTree, } from './endpoints';
|
|
39
39
|
export type { CorsairErrorHandler, ErrorContext, ErrorHandler, ErrorHandlerAndMatchFunction, ErrorMatcher, RetryStrategies, RetryStrategy, } from './errors';
|
|
40
40
|
export type { CorsairInspectMethods, EndpointSchemaResult } from './inspect';
|
|
41
|
-
export type { EnforcePermissionOptions } from './permissions';
|
|
41
|
+
export type { EnforcePermissionOptions, EnforcePermissionResult } from './permissions';
|
|
42
42
|
export type { BeforeHookResult, CorsairIntegration, CorsairKeyBuilder, CorsairKeyBuilderBase, CorsairPlugin, CorsairPluginContext, EndpointHooks, EndpointMetaEntry, EndpointRiskLevel, KeyBuilderContext, PermissionMode, PermissionPolicy, PluginEndpointMeta, PluginPermissionsConfig, RequiredPluginEndpointMeta, RequiredPluginEndpointSchemas, RequiredPluginWebhookSchemas, WebhookHooks, } from './plugins';
|
|
43
43
|
export type { Bivariant, UnionToIntersection } from './utils';
|
|
44
44
|
export type { BindWebhooks, BoundWebhook, BoundWebhookTree, CorsairWebhook, CorsairWebhookHandler, CorsairWebhookMatcher, RawWebhookRequest, WebhookPathsOf, WebhookRequest, WebhookResponse, WebhookTree, } from './webhooks';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGhF,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAMnE,eAAO,MAAM,gBAAgB,eAAiC,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IACnC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,QAAQ,EAAE,eAAe,GAAG,SAAS,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;KAC9B,CAAC;CACF,CAAC;AAMF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,aAAa,EAAE,EAC3E,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,GAC1D,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAEjC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,aAAa,EAAE,EAC3E,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAAE,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;CAAE,GACxE,yBAAyB,CAAC,OAAO,CAAC,CAAC;AA6EtC,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,GAChB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACN,gBAAgB,EAChB,uBAAuB,EACvB,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,GACf,MAAM,QAAQ,CAAC;AAEhB,YAAY,EACX,aAAa,EACb,yBAAyB,EACzB,oBAAoB,GACpB,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1E,YAAY,EACX,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,aAAa,CAAC;AAErB,YAAY,EACX,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,4BAA4B,EAC5B,YAAY,EACZ,eAAe,EACf,aAAa,GACb,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC7E,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,14 +16,31 @@ export type EnforcePermissionOptions = {
|
|
|
16
16
|
/** Required to create an approval record. Without a DB, 'require_approval' falls back to deny. */
|
|
17
17
|
db?: CorsairDatabase;
|
|
18
18
|
timeoutMs?: number;
|
|
19
|
+
/** Tenant ID for multi-tenant instances. Stored on the record so executePermission can scope correctly. Defaults to 'default'. */
|
|
20
|
+
tenantId?: string;
|
|
21
|
+
};
|
|
22
|
+
export type EnforcePermissionResult = {
|
|
23
|
+
result: 'allow' | 'blocked';
|
|
24
|
+
/**
|
|
25
|
+
* Called by the endpoint binding layer after the endpoint executes successfully.
|
|
26
|
+
* Marks the permission record as 'completed' (single-use approval consumed).
|
|
27
|
+
* Only present when an 'approved' record was found and the call is allowed through.
|
|
28
|
+
*/
|
|
29
|
+
onComplete?: () => Promise<void>;
|
|
19
30
|
};
|
|
20
31
|
/**
|
|
21
32
|
* Evaluates the permission policy and returns whether the action is allowed.
|
|
22
33
|
*
|
|
23
|
-
*
|
|
24
|
-
* - `'
|
|
25
|
-
* - `'
|
|
26
|
-
*
|
|
34
|
+
* Lifecycle:
|
|
35
|
+
* - `'allow'` → policy permits, caller proceeds normally
|
|
36
|
+
* - `'deny'` → blocked by policy mode; no DB record created
|
|
37
|
+
* - `'require_approval'` → checks for an existing matching permission record first:
|
|
38
|
+
* - `pending` (not expired) → already waiting for approval, returns 'blocked'
|
|
39
|
+
* - `approved` (not expired) → approved and ready; returns 'allow' + onComplete callback
|
|
40
|
+
* that marks the record 'completed' after the endpoint runs
|
|
41
|
+
* - otherwise → creates a new 'pending' record, returns 'blocked'
|
|
42
|
+
*
|
|
43
|
+
* Falls back to deny if no database is configured.
|
|
27
44
|
*/
|
|
28
|
-
export declare function enforcePermission(opts: EnforcePermissionOptions): Promise<
|
|
45
|
+
export declare function enforcePermission(opts: EnforcePermissionOptions): Promise<EnforcePermissionResult>;
|
|
29
46
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAgBpB,4HAA4H;AAC5H,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,cAAc,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAGlB;AAMD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsBxD;AAMD,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,kGAAkG;IAClG,EAAE,CAAC,EAAE,eAAe,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAgBpB,4HAA4H;AAC5H,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,cAAc,EACpB,QAAQ,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAGlB;AAMD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsBxD;AAMD,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,kGAAkG;IAClG,EAAE,CAAC,EAAE,eAAe,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kIAAkI;IAClI,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,wBAAwB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CA+FlC"}
|
|
@@ -45,24 +45,66 @@ export function parseDurationMs(duration) {
|
|
|
45
45
|
/**
|
|
46
46
|
* Evaluates the permission policy and returns whether the action is allowed.
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
* - `'
|
|
50
|
-
* - `'
|
|
51
|
-
*
|
|
48
|
+
* Lifecycle:
|
|
49
|
+
* - `'allow'` → policy permits, caller proceeds normally
|
|
50
|
+
* - `'deny'` → blocked by policy mode; no DB record created
|
|
51
|
+
* - `'require_approval'` → checks for an existing matching permission record first:
|
|
52
|
+
* - `pending` (not expired) → already waiting for approval, returns 'blocked'
|
|
53
|
+
* - `approved` (not expired) → approved and ready; returns 'allow' + onComplete callback
|
|
54
|
+
* that marks the record 'completed' after the endpoint runs
|
|
55
|
+
* - otherwise → creates a new 'pending' record, returns 'blocked'
|
|
56
|
+
*
|
|
57
|
+
* Falls back to deny if no database is configured.
|
|
52
58
|
*/
|
|
53
59
|
export async function enforcePermission(opts) {
|
|
54
60
|
const policy = evaluatePermission(opts.riskLevel, opts.mode, opts.override);
|
|
55
61
|
if (policy === 'allow')
|
|
56
|
-
return 'allow';
|
|
62
|
+
return { result: 'allow' };
|
|
57
63
|
const irreversibleNote = opts.meta?.irreversible ? ' (irreversible)' : '';
|
|
58
64
|
const description = opts.meta?.description
|
|
59
65
|
? `${opts.meta.description}${irreversibleNote}`
|
|
60
66
|
: `${opts.pluginId}.${opts.endpointPath}${irreversibleNote}`;
|
|
61
67
|
if (policy === 'deny' || !opts.db) {
|
|
62
68
|
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — denied by permission mode '${opts.mode}'.`, `\n Action: ${description}`, `\n To allow this, update the permission mode or add an override in your corsair config.`);
|
|
63
|
-
return 'blocked';
|
|
69
|
+
return { result: 'blocked' };
|
|
70
|
+
}
|
|
71
|
+
const argsJson = JSON.stringify(opts.args);
|
|
72
|
+
const now = new Date().toISOString();
|
|
73
|
+
const tenantId = opts.tenantId ?? 'default';
|
|
74
|
+
// Check for an existing, non-expired permission record for this plugin + endpoint + args + tenant
|
|
75
|
+
const existing = await opts.db.db
|
|
76
|
+
.selectFrom('corsair_permissions')
|
|
77
|
+
.selectAll()
|
|
78
|
+
.where('plugin', '=', opts.pluginId)
|
|
79
|
+
.where('endpoint', '=', opts.endpointPath)
|
|
80
|
+
.where('args', '=', argsJson)
|
|
81
|
+
.where('tenant_id', '=', tenantId)
|
|
82
|
+
.where('expires_at', '>', now)
|
|
83
|
+
.where('status', 'in', ['pending', 'approved'])
|
|
84
|
+
.orderBy('created_at', 'desc')
|
|
85
|
+
.limit(1)
|
|
86
|
+
.executeTakeFirst();
|
|
87
|
+
if (existing) {
|
|
88
|
+
if (existing.status === 'approved') {
|
|
89
|
+
// Single-use: let the call through; onComplete will mark it 'completed'
|
|
90
|
+
const db = opts.db;
|
|
91
|
+
const permissionId = existing.id;
|
|
92
|
+
return {
|
|
93
|
+
result: 'allow',
|
|
94
|
+
onComplete: async () => {
|
|
95
|
+
await db.db
|
|
96
|
+
.updateTable('corsair_permissions')
|
|
97
|
+
.set({ status: 'completed', updated_at: new Date() })
|
|
98
|
+
.where('id', '=', permissionId)
|
|
99
|
+
.execute();
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// status === 'pending': already waiting for approval, don't create a duplicate
|
|
104
|
+
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — approval already pending.`, `\n Action: ${description}`, `\n Permission ID: ${existing.id}`, `\n Use the token to approve or deny this request.`);
|
|
105
|
+
return { result: 'blocked' };
|
|
64
106
|
}
|
|
65
|
-
//
|
|
107
|
+
// No existing actionable record — create a new pending approval request
|
|
66
108
|
const id = uuidv4();
|
|
67
109
|
const token = randomBytes(32).toString('hex');
|
|
68
110
|
const timeoutMs = opts.timeoutMs ?? 10 * 60 * 1_000;
|
|
@@ -76,12 +118,12 @@ export async function enforcePermission(opts) {
|
|
|
76
118
|
token,
|
|
77
119
|
plugin: opts.pluginId,
|
|
78
120
|
endpoint: opts.endpointPath,
|
|
79
|
-
|
|
80
|
-
|
|
121
|
+
args: argsJson,
|
|
122
|
+
tenant_id: tenantId,
|
|
81
123
|
status: 'pending',
|
|
82
124
|
expires_at: expiresAt,
|
|
83
125
|
})
|
|
84
126
|
.execute();
|
|
85
127
|
console.log(`[corsair/${opts.pluginId}] '${opts.endpointPath}' blocked — approval required.`, `\n Action: ${description}`, `\n Permission ID: ${id}`, `\n Permission token: ${token}`, `\n Expires at: ${expiresAt}`, `\n Use the token to approve or deny this request.`);
|
|
86
|
-
return 'blocked';
|
|
128
|
+
return { result: 'blocked' };
|
|
87
129
|
}
|
package/dist/db/index.d.ts
CHANGED
|
@@ -115,29 +115,27 @@ export declare const CorsairPermissionsSchema: z.ZodObject<{
|
|
|
115
115
|
endpoint: z.ZodString;
|
|
116
116
|
/** JSON-encoded args that will be forwarded to the endpoint upon approval */
|
|
117
117
|
args: z.ZodString;
|
|
118
|
-
/**
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Tenant ID for multi-tenant corsair instances. Stored so executePermission
|
|
120
|
+
* can scope the corsair instance correctly when executing the approved action.
|
|
121
|
+
* Defaults to 'default' for single-tenant instances.
|
|
122
|
+
*/
|
|
123
|
+
tenant_id: z.ZodOptional<z.ZodString>;
|
|
124
124
|
/** Current state of the approval request */
|
|
125
|
-
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "denied", "expired"]>>;
|
|
125
|
+
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "completed", "denied", "expired"]>>;
|
|
126
126
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
127
127
|
expires_at: z.ZodString;
|
|
128
128
|
}, "strip", z.ZodTypeAny, {
|
|
129
129
|
id: string;
|
|
130
130
|
created_at: Date;
|
|
131
131
|
updated_at: Date;
|
|
132
|
-
status: "pending" | "approved" | "denied" | "expired";
|
|
132
|
+
status: "pending" | "completed" | "approved" | "denied" | "expired";
|
|
133
133
|
token: string;
|
|
134
134
|
plugin: string;
|
|
135
135
|
endpoint: string;
|
|
136
136
|
args: string;
|
|
137
137
|
expires_at: string;
|
|
138
|
-
|
|
139
|
-
callback_url?: string | undefined;
|
|
140
|
-
review_url?: string | undefined;
|
|
138
|
+
tenant_id?: string | undefined;
|
|
141
139
|
}, {
|
|
142
140
|
id: string;
|
|
143
141
|
created_at: Date;
|
|
@@ -147,10 +145,8 @@ export declare const CorsairPermissionsSchema: z.ZodObject<{
|
|
|
147
145
|
endpoint: string;
|
|
148
146
|
args: string;
|
|
149
147
|
expires_at: string;
|
|
150
|
-
status?: "pending" | "approved" | "denied" | "expired" | undefined;
|
|
151
|
-
|
|
152
|
-
callback_url?: string | undefined;
|
|
153
|
-
review_url?: string | undefined;
|
|
148
|
+
status?: "pending" | "completed" | "approved" | "denied" | "expired" | undefined;
|
|
149
|
+
tenant_id?: string | undefined;
|
|
154
150
|
}>;
|
|
155
151
|
export type CorsairPermission = z.infer<typeof CorsairPermissionsSchema>;
|
|
156
152
|
export type CorsairPermissionInsert = {
|
|
@@ -161,10 +157,8 @@ export type CorsairPermissionInsert = {
|
|
|
161
157
|
plugin: string;
|
|
162
158
|
endpoint: string;
|
|
163
159
|
args: string;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
review_url?: string;
|
|
167
|
-
status?: 'pending' | 'approved' | 'denied' | 'expired';
|
|
160
|
+
tenant_id?: string;
|
|
161
|
+
status?: 'pending' | 'approved' | 'completed' | 'denied' | 'expired';
|
|
168
162
|
expires_at: string;
|
|
169
163
|
};
|
|
170
164
|
export type CorsairTableName = 'corsair_integrations' | 'corsair_accounts' | 'corsair_entities' | 'corsair_events' | 'corsair_permissions' | (string & {});
|
package/dist/db/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;EAYpC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM3E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAehC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMnE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBhC,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMlE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAgB9B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAM/D,eAAO,MAAM,wBAAwB;;;;IAKpC,uFAAuF;;IAEvF,uCAAuC;;IAEvC,6DAA6D;;IAE7D,6EAA6E;;IAE7E
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"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"}
|
package/dist/db/index.js
CHANGED
|
@@ -81,15 +81,15 @@ export const CorsairPermissionsSchema = z.object({
|
|
|
81
81
|
endpoint: z.string(),
|
|
82
82
|
/** JSON-encoded args that will be forwarded to the endpoint upon approval */
|
|
83
83
|
args: z.string(),
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Tenant ID for multi-tenant corsair instances. Stored so executePermission
|
|
86
|
+
* can scope the corsair instance correctly when executing the approved action.
|
|
87
|
+
* Defaults to 'default' for single-tenant instances.
|
|
88
|
+
*/
|
|
89
|
+
tenant_id: z.string().optional(),
|
|
90
90
|
/** Current state of the approval request */
|
|
91
91
|
status: z
|
|
92
|
-
.enum(['pending', 'approved', 'denied', 'expired'])
|
|
92
|
+
.enum(['pending', 'approved', 'completed', 'denied', 'expired'])
|
|
93
93
|
.default('pending'),
|
|
94
94
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
95
95
|
expires_at: z.string(),
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { createCorsair } from './core';
|
|
2
2
|
export { processWebhook } from './webhooks';
|
|
3
|
+
export { executePermission } from './permissions';
|
|
4
|
+
export type { PermissionExecuteResult } from './permissions';
|
|
3
5
|
export { discord } from './plugins/discord';
|
|
4
6
|
export { github } from './plugins/github';
|
|
5
7
|
export { gmail } from './plugins/gmail';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAI7D,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// main function exports
|
|
2
2
|
export { createCorsair } from './core';
|
|
3
3
|
export { processWebhook } from './webhooks';
|
|
4
|
+
export { executePermission } from './permissions';
|
|
4
5
|
// plugin function exports
|
|
5
6
|
export { discord } from './plugins/discord';
|
|
6
7
|
export { github } from './plugins/github';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CorsairDatabase } from '../db/kysely/database';
|
|
2
|
+
/**
|
|
3
|
+
* A plugin namespace on the corsair instance that may have API endpoints.
|
|
4
|
+
*/
|
|
5
|
+
type PluginWithApi = {
|
|
6
|
+
api?: Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The corsair instance type for permission execution — a record of plugin namespaces.
|
|
10
|
+
* Mirrors the duck-typed shape used by processWebhook.
|
|
11
|
+
*/
|
|
12
|
+
type CorsairInstance = Record<string, PluginWithApi | undefined> & {
|
|
13
|
+
withTenant?: (tenantId: string) => CorsairInstance;
|
|
14
|
+
};
|
|
15
|
+
export type PermissionExecuteResult = {
|
|
16
|
+
plugin: string;
|
|
17
|
+
endpoint: string;
|
|
18
|
+
result: unknown;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Deterministically executes a pending permission request by directly calling
|
|
23
|
+
* the bound endpoint with the frozen args stored in the approval record.
|
|
24
|
+
*
|
|
25
|
+
* This is the approval-side counterpart to processWebhook. Instead of resuming
|
|
26
|
+
* the LLM to re-derive the action, this function looks up the pending permission
|
|
27
|
+
* record, navigates corsair[plugin].api[...endpoint path] to find the bound
|
|
28
|
+
* function, and calls it with the exact args that were stored — no LLM
|
|
29
|
+
* involvement required.
|
|
30
|
+
*
|
|
31
|
+
* Lifecycle:
|
|
32
|
+
* 1. Fetches the permission record from corsair_permissions
|
|
33
|
+
* 2. Validates the record is pending and not expired
|
|
34
|
+
* 3. Resolves the tenant-scoped corsair instance (via withTenant if multi-tenant)
|
|
35
|
+
* 4. Sets status to 'approved' so the bound endpoint's permission guard allows it through
|
|
36
|
+
* 5. Navigates corsair[plugin].api[...endpoint path] to find the bound function
|
|
37
|
+
* 6. Calls the function with the stored args (JSON-parsed)
|
|
38
|
+
* 7. The bound function's internal onComplete callback marks the record 'completed'
|
|
39
|
+
* 8. Returns the result, or an error object if the endpoint throws
|
|
40
|
+
*
|
|
41
|
+
* @param corsair - The corsair instance (returned from createCorsair)
|
|
42
|
+
* @param db - The corsair database instance
|
|
43
|
+
* @param permissionId - The ID of the corsair_permissions record to execute
|
|
44
|
+
*/
|
|
45
|
+
export declare function executePermission(corsair: CorsairInstance, db: CorsairDatabase, permissionId: string): Promise<PermissionExecuteResult>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAM7D;;GAEG;AACH,KAAK,aAAa,GAAG;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC,GAAG;IAClE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA4BF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,eAAe,EACnB,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC,CAiFlC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Helpers
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Traverses a bound API tree by dot-notation path parts and returns the
|
|
6
|
+
* endpoint function, or null if the path does not resolve to a function.
|
|
7
|
+
*/
|
|
8
|
+
function resolveEndpointFn(api, pathParts) {
|
|
9
|
+
let current = api;
|
|
10
|
+
for (const part of pathParts) {
|
|
11
|
+
if (!current || typeof current !== 'object')
|
|
12
|
+
return null;
|
|
13
|
+
current = current[part];
|
|
14
|
+
}
|
|
15
|
+
return typeof current === 'function'
|
|
16
|
+
? current
|
|
17
|
+
: null;
|
|
18
|
+
}
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// Main Function
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Deterministically executes a pending permission request by directly calling
|
|
24
|
+
* the bound endpoint with the frozen args stored in the approval record.
|
|
25
|
+
*
|
|
26
|
+
* This is the approval-side counterpart to processWebhook. Instead of resuming
|
|
27
|
+
* the LLM to re-derive the action, this function looks up the pending permission
|
|
28
|
+
* record, navigates corsair[plugin].api[...endpoint path] to find the bound
|
|
29
|
+
* function, and calls it with the exact args that were stored — no LLM
|
|
30
|
+
* involvement required.
|
|
31
|
+
*
|
|
32
|
+
* Lifecycle:
|
|
33
|
+
* 1. Fetches the permission record from corsair_permissions
|
|
34
|
+
* 2. Validates the record is pending and not expired
|
|
35
|
+
* 3. Resolves the tenant-scoped corsair instance (via withTenant if multi-tenant)
|
|
36
|
+
* 4. Sets status to 'approved' so the bound endpoint's permission guard allows it through
|
|
37
|
+
* 5. Navigates corsair[plugin].api[...endpoint path] to find the bound function
|
|
38
|
+
* 6. Calls the function with the stored args (JSON-parsed)
|
|
39
|
+
* 7. The bound function's internal onComplete callback marks the record 'completed'
|
|
40
|
+
* 8. Returns the result, or an error object if the endpoint throws
|
|
41
|
+
*
|
|
42
|
+
* @param corsair - The corsair instance (returned from createCorsair)
|
|
43
|
+
* @param db - The corsair database instance
|
|
44
|
+
* @param permissionId - The ID of the corsair_permissions record to execute
|
|
45
|
+
*/
|
|
46
|
+
export async function executePermission(corsair, db, permissionId) {
|
|
47
|
+
const now = new Date().toISOString();
|
|
48
|
+
const perm = await db.db
|
|
49
|
+
.selectFrom('corsair_permissions')
|
|
50
|
+
.selectAll()
|
|
51
|
+
.where('id', '=', permissionId)
|
|
52
|
+
.executeTakeFirst();
|
|
53
|
+
if (!perm) {
|
|
54
|
+
throw new Error(`executePermission: permission '${permissionId}' not found.`);
|
|
55
|
+
}
|
|
56
|
+
if (perm.status !== 'pending') {
|
|
57
|
+
throw new Error(`executePermission: permission '${permissionId}' is '${perm.status}', expected 'pending'.`);
|
|
58
|
+
}
|
|
59
|
+
if (perm.expires_at < now) {
|
|
60
|
+
await db.db
|
|
61
|
+
.updateTable('corsair_permissions')
|
|
62
|
+
.set({ status: 'expired', updated_at: new Date() })
|
|
63
|
+
.where('id', '=', permissionId)
|
|
64
|
+
.execute();
|
|
65
|
+
throw new Error(`executePermission: permission '${permissionId}' has expired.`);
|
|
66
|
+
}
|
|
67
|
+
// Resolve the tenant-scoped instance. The stored tenant_id ensures the correct
|
|
68
|
+
// plugin context is used for multi-tenant corsair instances.
|
|
69
|
+
const tenantId = perm.tenant_id ?? 'default';
|
|
70
|
+
const scopedCorsair = corsair.withTenant
|
|
71
|
+
? corsair.withTenant(tenantId)
|
|
72
|
+
: corsair;
|
|
73
|
+
const pluginNamespace = scopedCorsair[perm.plugin];
|
|
74
|
+
if (!pluginNamespace?.api) {
|
|
75
|
+
throw new Error(`executePermission: plugin '${perm.plugin}' not found or has no API on this corsair instance.`);
|
|
76
|
+
}
|
|
77
|
+
const endpointFn = resolveEndpointFn(pluginNamespace.api, perm.endpoint.split('.'));
|
|
78
|
+
if (!endpointFn) {
|
|
79
|
+
throw new Error(`executePermission: endpoint '${perm.endpoint}' not found in plugin '${perm.plugin}'.`);
|
|
80
|
+
}
|
|
81
|
+
// Mark as approved — the bound function's enforcePermission will find this record,
|
|
82
|
+
// allow the call through, then its onComplete callback marks it 'completed'.
|
|
83
|
+
await db.db
|
|
84
|
+
.updateTable('corsair_permissions')
|
|
85
|
+
.set({ status: 'approved', updated_at: new Date() })
|
|
86
|
+
.where('id', '=', permissionId)
|
|
87
|
+
.execute();
|
|
88
|
+
try {
|
|
89
|
+
const result = await endpointFn(JSON.parse(perm.args));
|
|
90
|
+
return { plugin: perm.plugin, endpoint: perm.endpoint, result };
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
// Reset to a terminal state so the approval cannot be silently retried.
|
|
94
|
+
await db.db
|
|
95
|
+
.updateTable('corsair_permissions')
|
|
96
|
+
.set({ status: 'denied', updated_at: new Date() })
|
|
97
|
+
.where('id', '=', permissionId)
|
|
98
|
+
.execute();
|
|
99
|
+
return {
|
|
100
|
+
plugin: perm.plugin,
|
|
101
|
+
endpoint: perm.endpoint,
|
|
102
|
+
result: null,
|
|
103
|
+
error: error instanceof Error ? error.message : String(error),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -70,7 +70,7 @@ export declare const Domains: {
|
|
|
70
70
|
data: {
|
|
71
71
|
id: string;
|
|
72
72
|
name: string;
|
|
73
|
-
status: "validation" | "pending" | "failed" | "
|
|
73
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
74
74
|
created_at?: Date | null | undefined;
|
|
75
75
|
region?: string | undefined;
|
|
76
76
|
}[];
|
|
@@ -162,13 +162,13 @@ declare const DomainSchema: z.ZodObject<{
|
|
|
162
162
|
}, "strip", z.ZodTypeAny, {
|
|
163
163
|
id: string;
|
|
164
164
|
name: string;
|
|
165
|
-
status: "validation" | "pending" | "failed" | "
|
|
165
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
166
166
|
created_at?: Date | null | undefined;
|
|
167
167
|
region?: string | undefined;
|
|
168
168
|
}, {
|
|
169
169
|
id: string;
|
|
170
170
|
name: string;
|
|
171
|
-
status: "validation" | "pending" | "failed" | "
|
|
171
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
172
172
|
created_at?: Date | null | undefined;
|
|
173
173
|
region?: string | undefined;
|
|
174
174
|
}>;
|
|
@@ -284,13 +284,13 @@ export declare const ResendEndpointOutputSchemas: {
|
|
|
284
284
|
}, "strip", z.ZodTypeAny, {
|
|
285
285
|
id: string;
|
|
286
286
|
name: string;
|
|
287
|
-
status: "validation" | "pending" | "failed" | "
|
|
287
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
288
288
|
created_at?: Date | null | undefined;
|
|
289
289
|
region?: string | undefined;
|
|
290
290
|
}, {
|
|
291
291
|
id: string;
|
|
292
292
|
name: string;
|
|
293
|
-
status: "validation" | "pending" | "failed" | "
|
|
293
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
294
294
|
created_at?: Date | null | undefined;
|
|
295
295
|
region?: string | undefined;
|
|
296
296
|
}>, "many">;
|
|
@@ -298,7 +298,7 @@ export declare const ResendEndpointOutputSchemas: {
|
|
|
298
298
|
data: {
|
|
299
299
|
id: string;
|
|
300
300
|
name: string;
|
|
301
|
-
status: "validation" | "pending" | "failed" | "
|
|
301
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
302
302
|
created_at?: Date | null | undefined;
|
|
303
303
|
region?: string | undefined;
|
|
304
304
|
}[];
|
|
@@ -306,7 +306,7 @@ export declare const ResendEndpointOutputSchemas: {
|
|
|
306
306
|
data: {
|
|
307
307
|
id: string;
|
|
308
308
|
name: string;
|
|
309
|
-
status: "validation" | "pending" | "failed" | "
|
|
309
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
310
310
|
created_at?: Date | null | undefined;
|
|
311
311
|
region?: string | undefined;
|
|
312
312
|
}[];
|
|
@@ -298,13 +298,13 @@ export declare const resendEndpointSchemas: {
|
|
|
298
298
|
}, "strip", import("zod").ZodTypeAny, {
|
|
299
299
|
id: string;
|
|
300
300
|
name: string;
|
|
301
|
-
status: "validation" | "pending" | "failed" | "
|
|
301
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
302
302
|
created_at?: Date | null | undefined;
|
|
303
303
|
region?: string | undefined;
|
|
304
304
|
}, {
|
|
305
305
|
id: string;
|
|
306
306
|
name: string;
|
|
307
|
-
status: "validation" | "pending" | "failed" | "
|
|
307
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
308
308
|
created_at?: Date | null | undefined;
|
|
309
309
|
region?: string | undefined;
|
|
310
310
|
}>, "many">;
|
|
@@ -312,7 +312,7 @@ export declare const resendEndpointSchemas: {
|
|
|
312
312
|
data: {
|
|
313
313
|
id: string;
|
|
314
314
|
name: string;
|
|
315
|
-
status: "validation" | "pending" | "failed" | "
|
|
315
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
316
316
|
created_at?: Date | null | undefined;
|
|
317
317
|
region?: string | undefined;
|
|
318
318
|
}[];
|
|
@@ -320,7 +320,7 @@ export declare const resendEndpointSchemas: {
|
|
|
320
320
|
data: {
|
|
321
321
|
id: string;
|
|
322
322
|
name: string;
|
|
323
|
-
status: "validation" | "pending" | "failed" | "
|
|
323
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
324
324
|
created_at?: Date | null | undefined;
|
|
325
325
|
region?: string | undefined;
|
|
326
326
|
}[];
|
|
@@ -27,13 +27,13 @@ export declare const ResendDomain: z.ZodObject<{
|
|
|
27
27
|
}, "strip", z.ZodTypeAny, {
|
|
28
28
|
id: string;
|
|
29
29
|
name: string;
|
|
30
|
-
status: "validation" | "pending" | "failed" | "
|
|
30
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
31
31
|
created_at?: Date | null | undefined;
|
|
32
32
|
region?: string | undefined;
|
|
33
33
|
}, {
|
|
34
34
|
id: string;
|
|
35
35
|
name: string;
|
|
36
|
-
status: "validation" | "pending" | "failed" | "
|
|
36
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
37
37
|
created_at?: Date | null | undefined;
|
|
38
38
|
region?: string | undefined;
|
|
39
39
|
}>;
|
|
@@ -29,13 +29,13 @@ export declare const ResendSchema: {
|
|
|
29
29
|
}, "strip", import("zod").ZodTypeAny, {
|
|
30
30
|
id: string;
|
|
31
31
|
name: string;
|
|
32
|
-
status: "validation" | "pending" | "failed" | "
|
|
32
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
33
33
|
created_at?: Date | null | undefined;
|
|
34
34
|
region?: string | undefined;
|
|
35
35
|
}, {
|
|
36
36
|
id: string;
|
|
37
37
|
name: string;
|
|
38
|
-
status: "validation" | "pending" | "failed" | "
|
|
38
|
+
status: "validation" | "pending" | "failed" | "error" | "verified" | "not_started" | "scheduled" | "ready";
|
|
39
39
|
created_at?: Date | null | undefined;
|
|
40
40
|
region?: string | undefined;
|
|
41
41
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../plugins/slack/webhooks/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAGxC,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../plugins/slack/webhooks/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAGxC,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC,SAAS,CAyE5C,CAAC"}
|
|
@@ -20,17 +20,36 @@ export const message = {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
let corsairEntityId = '';
|
|
23
|
-
if (ctx.db.messages
|
|
23
|
+
if (ctx.db.messages) {
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
if ('subtype' in event && event.subtype === 'message_changed' && 'message' in event) {
|
|
26
|
+
// For message_changed events, event.ts is the change-event timestamp (always new).
|
|
27
|
+
// The original message lives at event.message, with event.message.ts as the stable ID.
|
|
28
|
+
const updated = event.message;
|
|
29
|
+
const messageTs = 'ts' in updated ? updated.ts : undefined;
|
|
30
|
+
if (messageTs) {
|
|
31
|
+
const entity = await ctx.db.messages.upsertByEntityId(messageTs, {
|
|
32
|
+
...updated,
|
|
33
|
+
id: messageTs,
|
|
34
|
+
authorId: 'user' in updated ? updated.user : undefined,
|
|
35
|
+
createdAt: new Date(parseFloat(messageTs) * 1000),
|
|
36
|
+
});
|
|
37
|
+
corsairEntityId = entity?.id || '';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (!('subtype' in event) || event.subtype !== 'message_deleted') {
|
|
41
|
+
// Skip message_deleted events — the message no longer exists and we don't
|
|
42
|
+
// want to create a spurious record keyed on the deletion-event timestamp.
|
|
43
|
+
if (event.ts) {
|
|
44
|
+
const entity = await ctx.db.messages.upsertByEntityId(event.ts, {
|
|
45
|
+
...event,
|
|
46
|
+
id: event.ts,
|
|
47
|
+
authorId: 'user' in event ? event.user : undefined,
|
|
48
|
+
createdAt: new Date(parseFloat(event.ts) * 1000),
|
|
49
|
+
});
|
|
50
|
+
corsairEntityId = entity?.id || '';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
34
53
|
}
|
|
35
54
|
catch (error) {
|
|
36
55
|
console.warn('Failed to save message to database:', error);
|