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.
@@ -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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"}
@@ -160,6 +160,7 @@ export function buildCorsairClient(plugins, options) {
160
160
  endpointMeta: plugin.endpointMeta,
161
161
  database,
162
162
  approvalConfig,
163
+ tenantId,
163
164
  });
164
165
  if (Object.keys(boundTree).length > 0) {
165
166
  apiUnsafe[plugin.id].api = boundTree;
@@ -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,GACd,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;CACpE,GAAG,IAAI,CAwJP"}
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
- return call(0, { ...ctx, key }, args);
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
  }
@@ -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';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
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,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGvF,YAAY,EACX,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,YAAY,GACZ,MAAM,WAAW,CAAC;AAGnB,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9D,YAAY,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,eAAe,EACf,WAAW,GACX,MAAM,YAAY,CAAC"}
@@ -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
- * - `'allow'` → returns 'allow', caller proceeds normally
24
- * - `'deny'` logs a blocked message, returns 'blocked'
25
- * - `'require_approval'` creates a `corsair_permissions` record, logs the token, returns 'blocked'
26
- * (falls back to deny if no database is configured)
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<'allow' | 'blocked'>;
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;CACnB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,wBAAwB,GAC5B,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAkD9B"}
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
- * - `'allow'` → returns 'allow', caller proceeds normally
49
- * - `'deny'` logs a blocked message, returns 'blocked'
50
- * - `'require_approval'` creates a `corsair_permissions` record, logs the token, returns 'blocked'
51
- * (falls back to deny if no database is configured)
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
- // require_approval: create a pending record and log the token
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
- // unknown args serialized to JSON; available for inspection or re-execution
80
- args: JSON.stringify(opts.args),
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
  }
@@ -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
- /** Agent session ID from the orchestrator (NanoClaw / OpenClaw) — used to resume the agent */
119
- session_id: z.ZodOptional<z.ZodString>;
120
- /** URL to POST to when the action is approved or denied, to resume the agent */
121
- callback_url: z.ZodOptional<z.ZodString>;
122
- /** Full public review page URL (ngrok URL + path + token query param) */
123
- review_url: z.ZodOptional<z.ZodString>;
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
- session_id?: string | undefined;
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
- session_id?: string | undefined;
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
- session_id?: string;
165
- callback_url?: string;
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 & {});
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../db/index.ts"],"names":[],"mappings":"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"}
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
- /** Agent session ID from the orchestrator (NanoClaw / OpenClaw) — used to resume the agent */
85
- session_id: z.string().optional(),
86
- /** URL to POST to when the action is approved or denied, to resume the agent */
87
- callback_url: z.string().optional(),
88
- /** Full public review page URL (ngrok URL + path + token query param) */
89
- review_url: z.string().optional(),
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';
@@ -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;AAI5C,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"}
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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" | "verified" | "error" | "not_started" | "scheduled" | "ready";
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,CAwD5C,CAAC"}
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 && event.ts) {
23
+ if (ctx.db.messages) {
24
24
  try {
25
- const entity = await ctx.db.messages.upsertByEntityId(event.ts, {
26
- ...event,
27
- id: event.ts,
28
- authorId: 'user' in event ? event.user : undefined,
29
- createdAt: event.ts
30
- ? new Date(parseFloat(event.ts) * 1000)
31
- : new Date(),
32
- });
33
- corsairEntityId = entity?.id || '';
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsair",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",