corsair 0.1.21 → 0.1.23
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 +11 -0
- package/dist/core/client/index.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -0
- package/dist/core/inspect/index.d.ts +49 -6
- package/dist/core/inspect/index.d.ts.map +1 -1
- package/dist/core/inspect/index.js +132 -5
- package/dist/core/permissions/index.d.ts +37 -0
- package/dist/core/permissions/index.d.ts.map +1 -1
- package/dist/core/permissions/index.js +50 -1
- package/dist/db/index.d.ts +12 -7
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +12 -2
- package/dist/permissions/index.d.ts +19 -22
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +87 -47
- package/dist/plugins/resend/webhooks/types.d.ts +2 -2
- package/dist/plugins/slack/webhooks/messages.d.ts.map +1 -1
- package/dist/plugins/slack/webhooks/messages.js +2 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import type { AuthTypes } from '../constants';
|
|
|
6
6
|
import type { BindEndpoints, EndpointTree } from '../endpoints';
|
|
7
7
|
import type { CorsairErrorHandler } from '../errors';
|
|
8
8
|
import type { CorsairInspectMethods } from '../inspect';
|
|
9
|
+
import type { CorsairPermissionsNamespace } from '../permissions';
|
|
9
10
|
import type { CorsairPlugin } from '../plugins';
|
|
10
11
|
import type { BindWebhooks, RawWebhookRequest, WebhookTree } from '../webhooks';
|
|
11
12
|
/**
|
|
@@ -102,6 +103,11 @@ export type CorsairTenantWrapper<Plugins extends readonly CorsairPlugin[]> = {
|
|
|
102
103
|
* Used to manage secrets shared across all tenants (e.g., OAuth2 client_id, client_secret).
|
|
103
104
|
*/
|
|
104
105
|
keys: InferAllIntegrationKeys<Plugins>;
|
|
106
|
+
/**
|
|
107
|
+
* Permission management namespace. Use this to query and transition permission records.
|
|
108
|
+
* Available at the root regardless of multi-tenancy setting.
|
|
109
|
+
*/
|
|
110
|
+
permissions: CorsairPermissionsNamespace;
|
|
105
111
|
} & CorsairInspectMethods;
|
|
106
112
|
/**
|
|
107
113
|
* Single-tenant client that includes both plugin APIs and integration-level keys.
|
|
@@ -112,6 +118,11 @@ export type CorsairSingleTenantClient<Plugins extends readonly CorsairPlugin[]>
|
|
|
112
118
|
* Used to manage secrets shared across all tenants (e.g., OAuth2 client_id, client_secret).
|
|
113
119
|
*/
|
|
114
120
|
keys: InferAllIntegrationKeys<Plugins>;
|
|
121
|
+
/**
|
|
122
|
+
* Permission management namespace. Use this to query and transition permission records.
|
|
123
|
+
* Available at the root regardless of multi-tenancy setting.
|
|
124
|
+
*/
|
|
125
|
+
permissions: CorsairPermissionsNamespace;
|
|
115
126
|
};
|
|
116
127
|
export type BuildCorsairClientOptions = {
|
|
117
128
|
database: CorsairDatabase | undefined;
|
|
@@ -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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"}
|
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, EnforcePermissionResult, } from './permissions';
|
|
41
|
+
export type { CorsairPermissionsNamespace, 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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createCorsairDatabase } from '../db/kysely/database';
|
|
|
2
2
|
import { createMissingConfigProxy } from './auth/errors';
|
|
3
3
|
import { buildCorsairClient, buildIntegrationKeys } from './client';
|
|
4
4
|
import { buildInspectMethods } from './inspect';
|
|
5
|
+
import { buildPermissionsNamespace } from './permissions';
|
|
5
6
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
7
|
// Internal access for CLI tooling
|
|
7
8
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -26,6 +27,7 @@ export function createCorsair(config) {
|
|
|
26
27
|
multiTenancy: !!config.multiTenancy,
|
|
27
28
|
approval: config.approval,
|
|
28
29
|
};
|
|
30
|
+
const permissions = buildPermissionsNamespace(resolvedDatabase);
|
|
29
31
|
if (config.multiTenancy) {
|
|
30
32
|
return Object.assign({
|
|
31
33
|
withTenant: (tenantId) => {
|
|
@@ -41,6 +43,7 @@ export function createCorsair(config) {
|
|
|
41
43
|
});
|
|
42
44
|
},
|
|
43
45
|
keys: integrationKeys,
|
|
46
|
+
permissions,
|
|
44
47
|
...buildInspectMethods(config.plugins),
|
|
45
48
|
}, { [CORSAIR_INTERNAL]: internalConfig });
|
|
46
49
|
}
|
|
@@ -53,6 +56,7 @@ export function createCorsair(config) {
|
|
|
53
56
|
});
|
|
54
57
|
return Object.assign({}, client, {
|
|
55
58
|
keys: integrationKeys,
|
|
59
|
+
permissions,
|
|
56
60
|
[CORSAIR_INTERNAL]: internalConfig,
|
|
57
61
|
});
|
|
58
62
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CorsairPlugin } from '../plugins';
|
|
2
|
+
type DbFieldType = 'string' | 'number' | 'boolean' | 'date';
|
|
2
3
|
export type EndpointSchemaResult = {
|
|
3
4
|
/** Human-readable description of what this endpoint does. */
|
|
4
5
|
description?: string;
|
|
@@ -34,6 +35,35 @@ export type WebhookSchemaResult = {
|
|
|
34
35
|
*/
|
|
35
36
|
availableWebhooks?: Record<string, string[]>;
|
|
36
37
|
};
|
|
38
|
+
export type DbSearchSchemaResult = {
|
|
39
|
+
/**
|
|
40
|
+
* What this entity type represents and how to search it.
|
|
41
|
+
* Pass `limit` and `offset` as numbers for pagination.
|
|
42
|
+
*/
|
|
43
|
+
description: string;
|
|
44
|
+
/**
|
|
45
|
+
* Filterable fields for the search() call.
|
|
46
|
+
* All active filters are AND-combined. Omit a field to skip filtering on it.
|
|
47
|
+
*
|
|
48
|
+
* Each operator shorthand: passing a raw value (string/number/boolean/Date) is
|
|
49
|
+
* equivalent to `{ equals: value }`.
|
|
50
|
+
*/
|
|
51
|
+
filters: {
|
|
52
|
+
/** Filter by the entity's external platform ID (e.g. a Slack channel ID). */
|
|
53
|
+
entity_id: {
|
|
54
|
+
type: 'string';
|
|
55
|
+
operators: string[];
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Filter by fields inside the entity's data payload.
|
|
59
|
+
* Only flat primitive fields are listed — nested objects are not filterable.
|
|
60
|
+
*/
|
|
61
|
+
data: Record<string, {
|
|
62
|
+
type: DbFieldType;
|
|
63
|
+
operators: string[];
|
|
64
|
+
}>;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
37
67
|
export type ListOperationsOptions = {
|
|
38
68
|
/**
|
|
39
69
|
* Filter to a specific plugin by its ID (e.g. 'slack', 'github').
|
|
@@ -42,24 +72,29 @@ export type ListOperationsOptions = {
|
|
|
42
72
|
*/
|
|
43
73
|
plugin?: string;
|
|
44
74
|
/**
|
|
45
|
-
* Whether to list API endpoints or
|
|
46
|
-
*
|
|
75
|
+
* Whether to list API endpoints, webhooks, or database entities.
|
|
76
|
+
* - 'api' (default) — lists callable API endpoint paths
|
|
77
|
+
* - 'webhooks' — lists receivable webhook event paths
|
|
78
|
+
* - 'db' — lists searchable database entity paths (one .search per entity type)
|
|
47
79
|
*/
|
|
48
|
-
type?: 'api' | 'webhooks';
|
|
80
|
+
type?: 'api' | 'webhooks' | 'db';
|
|
49
81
|
};
|
|
50
82
|
export type CorsairInspectMethods = {
|
|
51
83
|
/**
|
|
52
|
-
* Lists available operations (API endpoints or
|
|
84
|
+
* Lists available operations (API endpoints, webhooks, or database entities) for the configured plugins.
|
|
53
85
|
*
|
|
54
86
|
* - No options → all API endpoint paths across every plugin, keyed by plugin ID
|
|
55
87
|
* - `{ type: 'webhooks' }` → all webhook paths across every plugin, keyed by plugin ID
|
|
88
|
+
* - `{ type: 'db' }` → all searchable DB entity paths across every plugin, keyed by plugin ID
|
|
56
89
|
* - `{ plugin: 'slack' }` → Slack API endpoint paths as a flat array
|
|
57
90
|
* - `{ plugin: 'slack', type: 'webhooks' }` → Slack webhook paths as a flat array
|
|
91
|
+
* - `{ plugin: 'slack', type: 'db' }` → Slack DB entity search paths as a flat array
|
|
58
92
|
* - If the plugin is known but not configured, returns a plain string message.
|
|
59
93
|
* - If the plugin string is completely unrecognised, returns all API endpoints (same as no options).
|
|
60
94
|
*
|
|
61
95
|
* API paths use the format `plugin.api.group.method` (e.g. `slack.api.messages.post`).
|
|
62
96
|
* Webhook paths use the format `plugin.webhooks.group.event` (e.g. `slack.webhooks.messages.message`).
|
|
97
|
+
* DB paths use the format `plugin.db.entityType.search` (e.g. `slack.db.messages.search`).
|
|
63
98
|
* All paths can be passed directly to `get_schema()`.
|
|
64
99
|
*
|
|
65
100
|
* @example
|
|
@@ -72,15 +107,19 @@ export type CorsairInspectMethods = {
|
|
|
72
107
|
* corsair.list_operations({ plugin: 'slack', type: 'webhooks' })
|
|
73
108
|
* // ['slack.webhooks.messages.message', 'slack.webhooks.channels.created', ...]
|
|
74
109
|
*
|
|
110
|
+
* corsair.list_operations({ plugin: 'slack', type: 'db' })
|
|
111
|
+
* // ['slack.db.messages.search', 'slack.db.channels.search', 'slack.db.users.search', ...]
|
|
112
|
+
*
|
|
75
113
|
* corsair.list_operations({ plugin: 'unknown' })
|
|
76
114
|
* // "unknown isn't configured in the Corsair instance."
|
|
77
115
|
*/
|
|
78
116
|
list_operations(options?: ListOperationsOptions): Record<string, string[]> | string[] | string;
|
|
79
117
|
/**
|
|
80
|
-
* Returns schema and metadata for a specific API endpoint or
|
|
118
|
+
* Returns schema and metadata for a specific API endpoint, webhook, or database entity search.
|
|
81
119
|
* The path format determines which kind of schema is returned:
|
|
82
120
|
* - API path (`plugin.api.group.method`) → `EndpointSchemaResult`
|
|
83
121
|
* - Webhook path (`plugin.webhooks.group.event`) → `WebhookSchemaResult`
|
|
122
|
+
* - DB path (`plugin.db.entityType.search`) → `DbSearchSchemaResult`
|
|
84
123
|
*
|
|
85
124
|
* Casing is ignored — the path is lowercased before lookup.
|
|
86
125
|
* If the path is not found, returns an object with available paths for self-correction.
|
|
@@ -92,14 +131,18 @@ export type CorsairInspectMethods = {
|
|
|
92
131
|
* corsair.get_schema('slack.webhooks.messages.message')
|
|
93
132
|
* // { description: '...', usage: '...', payload: { ... }, response: { ... } }
|
|
94
133
|
*
|
|
134
|
+
* corsair.get_schema('slack.db.messages.search')
|
|
135
|
+
* // { description: '...', filters: { entity_id: { ... }, data: { text: { type: 'string', operators: [...] }, ... } } }
|
|
136
|
+
*
|
|
95
137
|
* corsair.get_schema('slack.api.invalid')
|
|
96
138
|
* // { availableMethods: { slack: ['slack.api.channels.list', ...], ... } }
|
|
97
139
|
*/
|
|
98
|
-
get_schema(path: string): EndpointSchemaResult | WebhookSchemaResult;
|
|
140
|
+
get_schema(path: string): EndpointSchemaResult | WebhookSchemaResult | DbSearchSchemaResult;
|
|
99
141
|
};
|
|
100
142
|
/**
|
|
101
143
|
* Creates the list_operations / get_schema functions bound to a specific plugin list.
|
|
102
144
|
* Used by both single-tenant and multi-tenant client builders.
|
|
103
145
|
*/
|
|
104
146
|
export declare function buildInspectMethods(plugins: readonly CorsairPlugin[]): CorsairInspectMethods;
|
|
147
|
+
export {};
|
|
105
148
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/inspect/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/inspect/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC;AA0FnE,KAAK,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAyF5D,MAAM,MAAM,oBAAoB,GAAG;IAClC,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;IAC7C,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAClC;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,OAAO,EAAE;QACR,6EAA6E;QAC7E,SAAS,EAAE;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,SAAS,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QACnD;;;WAGG;QACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,WAAW,CAAC;YAAC,SAAS,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;KACjE,CAAC;CACF,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,eAAe,CACd,OAAO,CAAC,EAAE,qBAAqB,GAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;IAChD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,UAAU,CACT,IAAI,EAAE,MAAM,GACV,oBAAoB,GAAG,mBAAmB,GAAG,oBAAoB,CAAC;CACrE,CAAC;AAqYF;;;GAGG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,SAAS,aAAa,EAAE,GAC/B,qBAAqB,CAWvB"}
|
|
@@ -75,6 +75,89 @@ function zodToJsonSchema(schema) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
78
|
+
// DB Entity Helpers
|
|
79
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
80
|
+
const STRING_OPERATORS = ['equals', 'contains', 'startsWith', 'endsWith', 'in'];
|
|
81
|
+
const NUMBER_OPERATORS = ['equals', 'gt', 'gte', 'lt', 'lte', 'in'];
|
|
82
|
+
const BOOLEAN_OPERATORS = ['equals'];
|
|
83
|
+
const DATE_OPERATORS = ['equals', 'before', 'after', 'between'];
|
|
84
|
+
/**
|
|
85
|
+
* Unwraps Optional/Nullable/Default/Effects wrappers to find the primitive leaf type.
|
|
86
|
+
* Returns null for complex types (objects, arrays, unions) that are not directly filterable.
|
|
87
|
+
*/
|
|
88
|
+
function getSchemaLeafType(schema) {
|
|
89
|
+
const def = schema._def;
|
|
90
|
+
const typeName = def.typeName;
|
|
91
|
+
switch (typeName) {
|
|
92
|
+
case 'ZodOptional':
|
|
93
|
+
case 'ZodNullable':
|
|
94
|
+
case 'ZodDefault':
|
|
95
|
+
return getSchemaLeafType(def.innerType);
|
|
96
|
+
case 'ZodEffects':
|
|
97
|
+
// Covers z.coerce.date() and other transforms
|
|
98
|
+
return getSchemaLeafType(def.schema);
|
|
99
|
+
case 'ZodString':
|
|
100
|
+
return 'string';
|
|
101
|
+
case 'ZodNumber':
|
|
102
|
+
return 'number';
|
|
103
|
+
case 'ZodBoolean':
|
|
104
|
+
return 'boolean';
|
|
105
|
+
case 'ZodDate':
|
|
106
|
+
return 'date';
|
|
107
|
+
default:
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Derives the filterable fields from a Zod object schema.
|
|
113
|
+
* Only flat primitive fields (string, number, boolean, date) are included.
|
|
114
|
+
* Nested objects and arrays are skipped — the ORM does not support filtering into them.
|
|
115
|
+
*/
|
|
116
|
+
function buildFilterableFields(schema) {
|
|
117
|
+
const def = schema._def;
|
|
118
|
+
const typeName = def.typeName;
|
|
119
|
+
if (typeName === 'ZodOptional' ||
|
|
120
|
+
typeName === 'ZodNullable' ||
|
|
121
|
+
typeName === 'ZodDefault') {
|
|
122
|
+
return buildFilterableFields(def.innerType);
|
|
123
|
+
}
|
|
124
|
+
if (typeName === 'ZodEffects') {
|
|
125
|
+
return buildFilterableFields(def.schema);
|
|
126
|
+
}
|
|
127
|
+
if (typeName !== 'ZodObject')
|
|
128
|
+
return {};
|
|
129
|
+
const shape = def.shape();
|
|
130
|
+
const result = {};
|
|
131
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
132
|
+
const leafType = getSchemaLeafType(fieldSchema);
|
|
133
|
+
if (leafType === 'string') {
|
|
134
|
+
result[key] = { type: 'string', operators: STRING_OPERATORS };
|
|
135
|
+
}
|
|
136
|
+
else if (leafType === 'number') {
|
|
137
|
+
result[key] = { type: 'number', operators: NUMBER_OPERATORS };
|
|
138
|
+
}
|
|
139
|
+
else if (leafType === 'boolean') {
|
|
140
|
+
result[key] = { type: 'boolean', operators: BOOLEAN_OPERATORS };
|
|
141
|
+
}
|
|
142
|
+
else if (leafType === 'date') {
|
|
143
|
+
result[key] = { type: 'date', operators: DATE_OPERATORS };
|
|
144
|
+
}
|
|
145
|
+
// Nested objects, arrays, unions — not filterable via ORM, omit them
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Case-insensitive lookup for an entity name in a schema's entities map.
|
|
151
|
+
* Entity names are camelCase (e.g. 'userGroups') but agent paths are lowercased.
|
|
152
|
+
*/
|
|
153
|
+
function findEntityCaseInsensitive(entities, lowercasedName) {
|
|
154
|
+
for (const [key, schema] of Object.entries(entities)) {
|
|
155
|
+
if (key.toLowerCase() === lowercasedName)
|
|
156
|
+
return [key, schema];
|
|
157
|
+
}
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
78
161
|
// Endpoint Tree Walker
|
|
79
162
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
80
163
|
function walkEndpointTree(tree, pathParts, result) {
|
|
@@ -222,13 +305,17 @@ function listOperations(plugins, options) {
|
|
|
222
305
|
walkWebhookTree(found.webhooks, [], paths);
|
|
223
306
|
return paths.map((path) => `${found.id}.webhooks.${path}`);
|
|
224
307
|
}
|
|
225
|
-
|
|
226
|
-
|
|
308
|
+
if (type === 'db') {
|
|
309
|
+
const entities = found.schema?.entities;
|
|
310
|
+
if (!entities)
|
|
227
311
|
return [];
|
|
228
|
-
|
|
229
|
-
walkEndpointTree(found.endpoints, [], paths);
|
|
230
|
-
return paths.map((path) => `${found.id}.api.${path.toLowerCase()}`);
|
|
312
|
+
return Object.keys(entities).map((entityName) => `${found.id}.db.${entityName}.search`);
|
|
231
313
|
}
|
|
314
|
+
if (!found.endpoints)
|
|
315
|
+
return [];
|
|
316
|
+
const paths = [];
|
|
317
|
+
walkEndpointTree(found.endpoints, [], paths);
|
|
318
|
+
return paths.map((path) => `${found.id}.api.${path.toLowerCase()}`);
|
|
232
319
|
}
|
|
233
320
|
const result = {};
|
|
234
321
|
if (type === 'webhooks') {
|
|
@@ -240,6 +327,14 @@ function listOperations(plugins, options) {
|
|
|
240
327
|
result[p.id] = paths.map((path) => `${p.id}.webhooks.${path}`);
|
|
241
328
|
}
|
|
242
329
|
}
|
|
330
|
+
else if (type === 'db') {
|
|
331
|
+
for (const p of plugins) {
|
|
332
|
+
const entities = p.schema?.entities;
|
|
333
|
+
if (!entities)
|
|
334
|
+
continue;
|
|
335
|
+
result[p.id] = Object.keys(entities).map((entityName) => `${p.id}.db.${entityName}.search`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
243
338
|
else {
|
|
244
339
|
for (const p of plugins) {
|
|
245
340
|
if (!p.endpoints)
|
|
@@ -274,6 +369,38 @@ function getSchema(plugins, path) {
|
|
|
274
369
|
const remainder = normalised.slice(dotIndex + 1);
|
|
275
370
|
const plugin = plugins.find((p) => p.id === pluginId);
|
|
276
371
|
if (plugin) {
|
|
372
|
+
// ── DB search path: plugin.db.entityType.search ────────────────────────
|
|
373
|
+
if (remainder.startsWith('db.')) {
|
|
374
|
+
const dbPath = remainder.slice(3); // strip 'db.'
|
|
375
|
+
const lastDot = dbPath.lastIndexOf('.');
|
|
376
|
+
if (lastDot !== -1) {
|
|
377
|
+
const entityNameLower = dbPath.slice(0, lastDot);
|
|
378
|
+
const method = dbPath.slice(lastDot + 1);
|
|
379
|
+
const entities = plugin.schema?.entities;
|
|
380
|
+
if (method === 'search' && entities) {
|
|
381
|
+
const entry = findEntityCaseInsensitive(entities, entityNameLower);
|
|
382
|
+
if (entry) {
|
|
383
|
+
const [entityName, entitySchema] = entry;
|
|
384
|
+
return {
|
|
385
|
+
description: `Search ${pluginId} ${entityName} stored in the local database. Returns an array of matching records. Pass limit and offset (numbers) for pagination.`,
|
|
386
|
+
filters: {
|
|
387
|
+
entity_id: {
|
|
388
|
+
type: 'string',
|
|
389
|
+
operators: STRING_OPERATORS,
|
|
390
|
+
},
|
|
391
|
+
data: buildFilterableFields(entitySchema),
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// Invalid db path — return available db operations for self-correction
|
|
398
|
+
return {
|
|
399
|
+
availableMethods: listOperations(plugins, {
|
|
400
|
+
type: 'db',
|
|
401
|
+
}),
|
|
402
|
+
};
|
|
403
|
+
}
|
|
277
404
|
// ── Webhook path: plugin.webhooks.group.event ──────────────────────────
|
|
278
405
|
if (remainder.startsWith('webhooks.')) {
|
|
279
406
|
const webhookPathNormalised = remainder.slice(9); // strip 'webhooks.'
|
|
@@ -1,9 +1,46 @@
|
|
|
1
|
+
import type { CorsairPermission } from '../../db';
|
|
1
2
|
import type { CorsairDatabase } from '../../db/kysely/database';
|
|
2
3
|
import type { EndpointMetaEntry, EndpointRiskLevel, PermissionMode, PermissionPolicy } from '../plugins';
|
|
3
4
|
/** Resolves the effective permission policy for an endpoint. The override (from permissions.overrides) takes precedence. */
|
|
4
5
|
export declare function evaluatePermission(riskLevel: EndpointRiskLevel, mode: PermissionMode, override?: PermissionPolicy): PermissionPolicy;
|
|
5
6
|
/** Parses a duration string ('30s', '10m', '1h', '2h30m', '1d') into milliseconds. */
|
|
6
7
|
export declare function parseDurationMs(duration: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* The `corsair.permissions` namespace available at the root of every corsair instance.
|
|
10
|
+
* Provides methods for querying and transitioning permission records.
|
|
11
|
+
*
|
|
12
|
+
* Status transitions exposed here are intentionally limited to safe, non-escalating states.
|
|
13
|
+
* Setting a record to 'approved' (which grants execution) is deliberately excluded —
|
|
14
|
+
* that must happen through the out-of-band review flow.
|
|
15
|
+
*/
|
|
16
|
+
export type CorsairPermissionsNamespace = {
|
|
17
|
+
/**
|
|
18
|
+
* Fetches a single permission record by its ID.
|
|
19
|
+
* Returns undefined if no record exists or if no database is configured.
|
|
20
|
+
*/
|
|
21
|
+
find_by_permission_id(id: string): Promise<CorsairPermission | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* Fetches a single permission record by its token.
|
|
24
|
+
* The token is the public-facing handle embedded in review URLs.
|
|
25
|
+
* Returns undefined if no record exists or if no database is configured.
|
|
26
|
+
*/
|
|
27
|
+
find_by_token(token: string): Promise<CorsairPermission | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Marks the permission as 'executing'. Call this when executePermission picks up
|
|
30
|
+
* an approved record and is about to run the endpoint.
|
|
31
|
+
*/
|
|
32
|
+
set_executing(id: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Marks the permission as 'completed'. Call this after the endpoint has finished
|
|
35
|
+
* executing successfully.
|
|
36
|
+
*/
|
|
37
|
+
set_completed(id: string): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Builds the `corsair.permissions` namespace for a given database instance.
|
|
41
|
+
* Returns no-op stubs when no database is configured.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildPermissionsNamespace(db: CorsairDatabase | undefined): CorsairPermissionsNamespace;
|
|
7
44
|
export type EnforcePermissionOptions = {
|
|
8
45
|
pluginId: string;
|
|
9
46
|
endpointPath: string;
|
|
@@ -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;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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/permissions/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAClD,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;;;;;;;GAOG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACzC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;IAC1E;;;;OAIG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;IACrE;;;OAGG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,yBAAyB,CACxC,EAAE,EAAE,eAAe,GAAG,SAAS,GAC7B,2BAA2B,CAmC7B;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,CAqGlC"}
|
|
@@ -42,6 +42,50 @@ export function parseDurationMs(duration) {
|
|
|
42
42
|
}
|
|
43
43
|
return total > 0 ? total : 10 * 60 * 1_000;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Builds the `corsair.permissions` namespace for a given database instance.
|
|
47
|
+
* Returns no-op stubs when no database is configured.
|
|
48
|
+
*/
|
|
49
|
+
export function buildPermissionsNamespace(db) {
|
|
50
|
+
return {
|
|
51
|
+
async find_by_permission_id(id) {
|
|
52
|
+
if (!db)
|
|
53
|
+
return undefined;
|
|
54
|
+
return db.db
|
|
55
|
+
.selectFrom('corsair_permissions')
|
|
56
|
+
.selectAll()
|
|
57
|
+
.where('id', '=', id)
|
|
58
|
+
.executeTakeFirst();
|
|
59
|
+
},
|
|
60
|
+
async find_by_token(token) {
|
|
61
|
+
if (!db)
|
|
62
|
+
return undefined;
|
|
63
|
+
return db.db
|
|
64
|
+
.selectFrom('corsair_permissions')
|
|
65
|
+
.selectAll()
|
|
66
|
+
.where('token', '=', token)
|
|
67
|
+
.executeTakeFirst();
|
|
68
|
+
},
|
|
69
|
+
async set_executing(id) {
|
|
70
|
+
if (!db)
|
|
71
|
+
return;
|
|
72
|
+
await db.db
|
|
73
|
+
.updateTable('corsair_permissions')
|
|
74
|
+
.set({ status: 'executing', updated_at: new Date() })
|
|
75
|
+
.where('id', '=', id)
|
|
76
|
+
.execute();
|
|
77
|
+
},
|
|
78
|
+
async set_completed(id) {
|
|
79
|
+
if (!db)
|
|
80
|
+
return;
|
|
81
|
+
await db.db
|
|
82
|
+
.updateTable('corsair_permissions')
|
|
83
|
+
.set({ status: 'completed', updated_at: new Date() })
|
|
84
|
+
.where('id', '=', id)
|
|
85
|
+
.execute();
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
45
89
|
/**
|
|
46
90
|
* Evaluates the permission policy and returns whether the action is allowed.
|
|
47
91
|
*
|
|
@@ -80,7 +124,7 @@ export async function enforcePermission(opts) {
|
|
|
80
124
|
.where('args', '=', argsJson)
|
|
81
125
|
.where('tenant_id', '=', tenantId)
|
|
82
126
|
.where('expires_at', '>', now)
|
|
83
|
-
.where('status', 'in', ['pending', 'approved'])
|
|
127
|
+
.where('status', 'in', ['pending', 'approved', 'executing'])
|
|
84
128
|
.orderBy('created_at', 'desc')
|
|
85
129
|
.limit(1)
|
|
86
130
|
.executeTakeFirst();
|
|
@@ -100,6 +144,11 @@ export async function enforcePermission(opts) {
|
|
|
100
144
|
},
|
|
101
145
|
};
|
|
102
146
|
}
|
|
147
|
+
if (existing.status === 'executing') {
|
|
148
|
+
// executePermission is actively running this — let the endpoint body proceed.
|
|
149
|
+
// Completion is handled by executePermission itself, not via onComplete here.
|
|
150
|
+
return { result: 'allow' };
|
|
151
|
+
}
|
|
103
152
|
// status === 'pending': already waiting for approval, don't create a duplicate
|
|
104
153
|
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
154
|
return { result: 'blocked' };
|
package/dist/db/index.d.ts
CHANGED
|
@@ -120,33 +120,37 @@ export declare const CorsairPermissionsSchema: z.ZodObject<{
|
|
|
120
120
|
* can scope the corsair instance correctly when executing the approved action.
|
|
121
121
|
* Defaults to 'default' for single-tenant instances.
|
|
122
122
|
*/
|
|
123
|
-
tenant_id: z.
|
|
123
|
+
tenant_id: z.ZodString;
|
|
124
124
|
/** Current state of the approval request */
|
|
125
|
-
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "completed", "denied", "expired"]>>;
|
|
125
|
+
status: z.ZodDefault<z.ZodEnum<["pending", "approved", "executing", "completed", "denied", "expired", "failed"]>>;
|
|
126
126
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
127
127
|
expires_at: z.ZodString;
|
|
128
|
+
/** Stringified error captured when status transitions to 'failed'. Null otherwise. */
|
|
129
|
+
error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
128
130
|
}, "strip", z.ZodTypeAny, {
|
|
129
131
|
id: string;
|
|
130
132
|
created_at: Date;
|
|
131
133
|
updated_at: Date;
|
|
132
|
-
status: "pending" | "completed" | "approved" | "denied" | "expired";
|
|
134
|
+
status: "pending" | "completed" | "failed" | "approved" | "executing" | "denied" | "expired";
|
|
135
|
+
tenant_id: string;
|
|
133
136
|
token: string;
|
|
134
137
|
plugin: string;
|
|
135
138
|
endpoint: string;
|
|
136
139
|
args: string;
|
|
137
140
|
expires_at: string;
|
|
138
|
-
|
|
141
|
+
error?: string | null | undefined;
|
|
139
142
|
}, {
|
|
140
143
|
id: string;
|
|
141
144
|
created_at: Date;
|
|
142
145
|
updated_at: Date;
|
|
146
|
+
tenant_id: string;
|
|
143
147
|
token: string;
|
|
144
148
|
plugin: string;
|
|
145
149
|
endpoint: string;
|
|
146
150
|
args: string;
|
|
147
151
|
expires_at: string;
|
|
148
|
-
status?: "pending" | "completed" | "approved" | "denied" | "expired" | undefined;
|
|
149
|
-
|
|
152
|
+
status?: "pending" | "completed" | "failed" | "approved" | "executing" | "denied" | "expired" | undefined;
|
|
153
|
+
error?: string | null | undefined;
|
|
150
154
|
}>;
|
|
151
155
|
export type CorsairPermission = z.infer<typeof CorsairPermissionsSchema>;
|
|
152
156
|
export type CorsairPermissionInsert = {
|
|
@@ -158,8 +162,9 @@ export type CorsairPermissionInsert = {
|
|
|
158
162
|
endpoint: string;
|
|
159
163
|
args: string;
|
|
160
164
|
tenant_id?: string;
|
|
161
|
-
status?: 'pending' | 'approved' | 'completed' | 'denied' | 'expired';
|
|
165
|
+
status?: 'pending' | 'approved' | 'executing' | 'completed' | 'denied' | 'expired' | 'failed';
|
|
162
166
|
expires_at: string;
|
|
167
|
+
error?: string | null;
|
|
163
168
|
};
|
|
164
169
|
export type CorsairTableName = 'corsair_integrations' | 'corsair_accounts' | 'corsair_entities' | 'corsair_events' | 'corsair_permissions' | (string & {});
|
|
165
170
|
export type CorsairTableRow = {
|
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;;;;OAIG;;IAEH,4CAA4C;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"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"}
|
package/dist/db/index.js
CHANGED
|
@@ -86,11 +86,21 @@ export const CorsairPermissionsSchema = z.object({
|
|
|
86
86
|
* can scope the corsair instance correctly when executing the approved action.
|
|
87
87
|
* Defaults to 'default' for single-tenant instances.
|
|
88
88
|
*/
|
|
89
|
-
tenant_id: z.string()
|
|
89
|
+
tenant_id: z.string(),
|
|
90
90
|
/** Current state of the approval request */
|
|
91
91
|
status: z
|
|
92
|
-
.enum([
|
|
92
|
+
.enum([
|
|
93
|
+
'pending',
|
|
94
|
+
'approved',
|
|
95
|
+
'executing',
|
|
96
|
+
'completed',
|
|
97
|
+
'denied',
|
|
98
|
+
'expired',
|
|
99
|
+
'failed',
|
|
100
|
+
])
|
|
93
101
|
.default('pending'),
|
|
94
102
|
/** ISO8601 timestamp — when this request becomes invalid */
|
|
95
103
|
expires_at: z.string(),
|
|
104
|
+
/** Stringified error captured when status transitions to 'failed'. Null otherwise. */
|
|
105
|
+
error: z.string().nullable().optional(),
|
|
96
106
|
});
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CorsairPermissionsNamespace } from '../core/permissions';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* The corsair instance type for permission execution.
|
|
4
|
+
* Must expose the `permissions` namespace and optionally a `withTenant` method.
|
|
5
|
+
* The withTenant return type is intentionally broad — we only need to index into it
|
|
6
|
+
* by plugin name, and we cast the result to PluginWithApi at the call site.
|
|
4
7
|
*/
|
|
5
|
-
type
|
|
6
|
-
|
|
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;
|
|
8
|
+
type CorsairInstance = {
|
|
9
|
+
permissions: CorsairPermissionsNamespace;
|
|
10
|
+
withTenant?: (tenantId: string) => Record<string, unknown>;
|
|
11
|
+
[key: string]: unknown;
|
|
14
12
|
};
|
|
15
13
|
export type PermissionExecuteResult = {
|
|
16
|
-
plugin
|
|
17
|
-
endpoint
|
|
18
|
-
result
|
|
14
|
+
plugin?: string;
|
|
15
|
+
endpoint?: string;
|
|
16
|
+
result?: unknown;
|
|
19
17
|
error?: string;
|
|
20
18
|
};
|
|
21
19
|
/**
|
|
@@ -29,19 +27,18 @@ export type PermissionExecuteResult = {
|
|
|
29
27
|
* involvement required.
|
|
30
28
|
*
|
|
31
29
|
* Lifecycle:
|
|
32
|
-
* 1. Fetches the permission record
|
|
33
|
-
* 2. Validates the record is
|
|
30
|
+
* 1. Fetches the permission record via corsair.permissions.find_by_permission_id
|
|
31
|
+
* 2. Validates the record is approved (human has signed off) and not expired
|
|
34
32
|
* 3. Resolves the tenant-scoped corsair instance (via withTenant if multi-tenant)
|
|
35
|
-
* 4. Sets status to '
|
|
33
|
+
* 4. Sets status to 'executing' via corsair.permissions.set_executing
|
|
36
34
|
* 5. Navigates corsair[plugin].api[...endpoint path] to find the bound function
|
|
37
35
|
* 6. Calls the function with the stored args (JSON-parsed)
|
|
38
|
-
* 7.
|
|
39
|
-
* 8. Returns the result, or an error object if the endpoint
|
|
36
|
+
* 7. Sets status to 'completed' via corsair.permissions.set_completed
|
|
37
|
+
* 8. Returns the result, or an error object if the endpoint gracefully exits
|
|
40
38
|
*
|
|
41
39
|
* @param corsair - The corsair instance (returned from createCorsair)
|
|
42
|
-
* @param
|
|
43
|
-
* @param permissionId - The ID of the corsair_permissions record to execute
|
|
40
|
+
* @param token - The token embedded in the review URL for the corsair_permissions record
|
|
44
41
|
*/
|
|
45
|
-
export declare function executePermission(corsair: CorsairInstance,
|
|
42
|
+
export declare function executePermission(corsair: CorsairInstance, token: string): Promise<PermissionExecuteResult>;
|
|
46
43
|
export {};
|
|
47
44
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAcvE;;;;;GAKG;AACH,KAAK,eAAe,GAAG;IACtB,WAAW,EAAE,2BAA2B,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA4CF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,uBAAuB,CAAC,CAoHlC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Internal symbol — mirrors the one exported from core/index.ts without importing it
|
|
2
|
+
// (avoids potential circular dependency) since Symbol.for() uses a global registry.
|
|
3
|
+
const CORSAIR_INTERNAL_SYMBOL = Symbol.for('corsair:internal');
|
|
1
4
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
5
|
// Helpers
|
|
3
6
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -16,6 +19,15 @@ function resolveEndpointFn(api, pathParts) {
|
|
|
16
19
|
? current
|
|
17
20
|
: null;
|
|
18
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves the internal database from a corsair instance via the CORSAIR_INTERNAL symbol.
|
|
24
|
+
* Used for terminal status transitions (expired, denied) that are not part of the
|
|
25
|
+
* public `corsair.permissions` API.
|
|
26
|
+
*/
|
|
27
|
+
function getInternalDb(corsair) {
|
|
28
|
+
const internal = corsair[CORSAIR_INTERNAL_SYMBOL];
|
|
29
|
+
return internal?.database;
|
|
30
|
+
}
|
|
19
31
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
32
|
// Main Function
|
|
21
33
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -30,77 +42,105 @@ function resolveEndpointFn(api, pathParts) {
|
|
|
30
42
|
* involvement required.
|
|
31
43
|
*
|
|
32
44
|
* Lifecycle:
|
|
33
|
-
* 1. Fetches the permission record
|
|
34
|
-
* 2. Validates the record is
|
|
45
|
+
* 1. Fetches the permission record via corsair.permissions.find_by_permission_id
|
|
46
|
+
* 2. Validates the record is approved (human has signed off) and not expired
|
|
35
47
|
* 3. Resolves the tenant-scoped corsair instance (via withTenant if multi-tenant)
|
|
36
|
-
* 4. Sets status to '
|
|
48
|
+
* 4. Sets status to 'executing' via corsair.permissions.set_executing
|
|
37
49
|
* 5. Navigates corsair[plugin].api[...endpoint path] to find the bound function
|
|
38
50
|
* 6. Calls the function with the stored args (JSON-parsed)
|
|
39
|
-
* 7.
|
|
40
|
-
* 8. Returns the result, or an error object if the endpoint
|
|
51
|
+
* 7. Sets status to 'completed' via corsair.permissions.set_completed
|
|
52
|
+
* 8. Returns the result, or an error object if the endpoint gracefully exits
|
|
41
53
|
*
|
|
42
54
|
* @param corsair - The corsair instance (returned from createCorsair)
|
|
43
|
-
* @param
|
|
44
|
-
* @param permissionId - The ID of the corsair_permissions record to execute
|
|
55
|
+
* @param token - The token embedded in the review URL for the corsair_permissions record
|
|
45
56
|
*/
|
|
46
|
-
export async function executePermission(corsair,
|
|
57
|
+
export async function executePermission(corsair, token) {
|
|
47
58
|
const now = new Date().toISOString();
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
throw new Error(`executePermission: permission '${permissionId}' not found.`);
|
|
59
|
+
const permission = await corsair.permissions.find_by_token(token);
|
|
60
|
+
if (!permission) {
|
|
61
|
+
console.error(`executePermission: no permission found for token.`);
|
|
62
|
+
return {
|
|
63
|
+
error: `executePermission: no permission found for token.`,
|
|
64
|
+
};
|
|
55
65
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
66
|
+
if (permission.status !== 'approved') {
|
|
67
|
+
console.error(`executePermission: permission '${permission.id}' is '${permission.status}', expected 'approved'.`);
|
|
68
|
+
return {
|
|
69
|
+
endpoint: permission.endpoint,
|
|
70
|
+
plugin: permission.plugin,
|
|
71
|
+
result: null,
|
|
72
|
+
error: `executePermission: permission '${permission.id}' is '${permission.status}', expected 'approved'.`,
|
|
73
|
+
};
|
|
58
74
|
}
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
if (permission.expires_at < now) {
|
|
76
|
+
const db = getInternalDb(corsair);
|
|
77
|
+
if (db) {
|
|
78
|
+
await db.db
|
|
79
|
+
.updateTable('corsair_permissions')
|
|
80
|
+
.set({ status: 'expired', updated_at: new Date() })
|
|
81
|
+
.where('id', '=', permission.id)
|
|
82
|
+
.execute();
|
|
83
|
+
}
|
|
84
|
+
console.error(`executePermission: permission '${permission.id}' has expired.`);
|
|
85
|
+
return {
|
|
86
|
+
error: `executePermission: permission '${permission.id}' has expired.`,
|
|
87
|
+
endpoint: permission.endpoint,
|
|
88
|
+
plugin: permission.plugin,
|
|
89
|
+
result: null,
|
|
90
|
+
};
|
|
66
91
|
}
|
|
67
92
|
// Resolve the tenant-scoped instance. The stored tenant_id ensures the correct
|
|
68
93
|
// plugin context is used for multi-tenant corsair instances.
|
|
69
|
-
const tenantId =
|
|
94
|
+
const tenantId = permission.tenant_id ?? 'default';
|
|
70
95
|
const scopedCorsair = corsair.withTenant
|
|
71
96
|
? corsair.withTenant(tenantId)
|
|
72
97
|
: corsair;
|
|
73
|
-
const pluginNamespace = scopedCorsair[
|
|
98
|
+
const pluginNamespace = scopedCorsair[permission.plugin];
|
|
74
99
|
if (!pluginNamespace?.api) {
|
|
75
|
-
|
|
100
|
+
console.error(`executePermission: plugin '${permission.plugin}' not found or has no API on this corsair instance.`);
|
|
101
|
+
return {
|
|
102
|
+
error: `executePermission: plugin '${permission.plugin}' not found or has no API on this corsair instance.`,
|
|
103
|
+
plugin: permission.plugin,
|
|
104
|
+
endpoint: permission.endpoint,
|
|
105
|
+
result: null,
|
|
106
|
+
};
|
|
76
107
|
}
|
|
77
|
-
const endpointFn = resolveEndpointFn(pluginNamespace.api,
|
|
108
|
+
const endpointFn = resolveEndpointFn(pluginNamespace.api, permission.endpoint.split('.'));
|
|
78
109
|
if (!endpointFn) {
|
|
79
|
-
|
|
110
|
+
console.error(`executePermission: endpoint '${permission.endpoint}' not found in plugin '${permission.plugin}'.`);
|
|
111
|
+
return {
|
|
112
|
+
endpoint: permission.endpoint,
|
|
113
|
+
plugin: permission.plugin,
|
|
114
|
+
result: null,
|
|
115
|
+
error: `executePermission: endpoint '${permission.endpoint}' not found in plugin '${permission.plugin}'.`,
|
|
116
|
+
};
|
|
80
117
|
}
|
|
81
|
-
// Mark as
|
|
82
|
-
//
|
|
83
|
-
await
|
|
84
|
-
.updateTable('corsair_permissions')
|
|
85
|
-
.set({ status: 'approved', updated_at: new Date() })
|
|
86
|
-
.where('id', '=', permissionId)
|
|
87
|
-
.execute();
|
|
118
|
+
// Mark as executing — the bound endpoint's enforcePermission recognises this status
|
|
119
|
+
// and allows the call through. Completion is set explicitly below after the endpoint returns.
|
|
120
|
+
await corsair.permissions.set_executing(permission.id);
|
|
88
121
|
try {
|
|
89
|
-
const
|
|
90
|
-
|
|
122
|
+
const parsedArgs = typeof permission.args === 'string'
|
|
123
|
+
? JSON.parse(permission.args)
|
|
124
|
+
: permission.args;
|
|
125
|
+
const result = await endpointFn(parsedArgs);
|
|
126
|
+
await corsair.permissions.set_completed(permission.id);
|
|
127
|
+
return { plugin: permission.plugin, endpoint: permission.endpoint, result };
|
|
91
128
|
}
|
|
92
129
|
catch (error) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
131
|
+
const db = getInternalDb(corsair);
|
|
132
|
+
if (db) {
|
|
133
|
+
await db.db
|
|
134
|
+
.updateTable('corsair_permissions')
|
|
135
|
+
.set({ status: 'failed', error: errorMessage, updated_at: new Date() })
|
|
136
|
+
.where('id', '=', permission.id)
|
|
137
|
+
.execute();
|
|
138
|
+
}
|
|
99
139
|
return {
|
|
100
|
-
plugin:
|
|
101
|
-
endpoint:
|
|
140
|
+
plugin: permission.plugin,
|
|
141
|
+
endpoint: permission.endpoint,
|
|
102
142
|
result: null,
|
|
103
|
-
error:
|
|
143
|
+
error: errorMessage,
|
|
104
144
|
};
|
|
105
145
|
}
|
|
106
146
|
}
|
|
@@ -47,8 +47,8 @@ export declare const ResendWebhookPayloadSchema: z.ZodObject<{
|
|
|
47
47
|
created_at: string;
|
|
48
48
|
name?: string | undefined;
|
|
49
49
|
status?: string | undefined;
|
|
50
|
-
link?: string | undefined;
|
|
51
50
|
error?: string | undefined;
|
|
51
|
+
link?: string | undefined;
|
|
52
52
|
subject?: string | undefined;
|
|
53
53
|
from?: string | undefined;
|
|
54
54
|
to?: string[] | undefined;
|
|
@@ -65,8 +65,8 @@ export declare const ResendWebhookPayloadSchema: z.ZodObject<{
|
|
|
65
65
|
created_at: string;
|
|
66
66
|
name?: string | undefined;
|
|
67
67
|
status?: string | undefined;
|
|
68
|
-
link?: string | undefined;
|
|
69
68
|
error?: string | undefined;
|
|
69
|
+
link?: string | undefined;
|
|
70
70
|
subject?: string | undefined;
|
|
71
71
|
from?: string | undefined;
|
|
72
72
|
to?: string[] | undefined;
|
|
@@ -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,CA4F5C,CAAC"}
|
|
@@ -43,7 +43,8 @@ export const message = {
|
|
|
43
43
|
});
|
|
44
44
|
corsairEntityId = entity?.id || '';
|
|
45
45
|
}
|
|
46
|
-
else if (!('subtype' in event) ||
|
|
46
|
+
else if (!('subtype' in event) ||
|
|
47
|
+
event.subtype !== 'message_deleted') {
|
|
47
48
|
// GenericMessageEvent, BotMessageEvent, FileShareMessageEvent, etc.
|
|
48
49
|
// Skip message_deleted — the message no longer exists and we don't
|
|
49
50
|
// want to create a spurious record keyed on the deletion-event timestamp.
|