@frontmcp/plugin-approval 1.8.1 → 1.8.2
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/approval.identity.d.ts +3 -5
- package/approval.identity.d.ts.map +1 -1
- package/esm/index.mjs +2 -3
- package/esm/package.json +4 -4
- package/index.js +20 -21
- package/package.json +4 -4
package/approval.identity.d.ts
CHANGED
|
@@ -10,14 +10,12 @@ export interface ApprovalIdentity {
|
|
|
10
10
|
/** Key for user-scoped approvals, when the call has an authenticated principal. */
|
|
11
11
|
userId: string | undefined;
|
|
12
12
|
}
|
|
13
|
-
type ApprovalCallerContext = Pick<FrontMcpContext, '
|
|
13
|
+
type ApprovalCallerContext = Pick<FrontMcpContext, 'verifiedSessionId' | 'authInfo'>;
|
|
14
14
|
/**
|
|
15
15
|
* The session and user that a call's approvals are read from and granted to.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* call is keyed by its authenticated principal instead, and a call with neither a session nor
|
|
20
|
-
* a principal gets a key of its own that no other call can match.
|
|
17
|
+
* Only a verified session keys session approvals; a stateless call (shared or per-request session
|
|
18
|
+
* id) is keyed by its principal, and a call with neither gets a key no other call can match.
|
|
21
19
|
*/
|
|
22
20
|
export declare function resolveApprovalIdentity(ctx: ApprovalCallerContext | undefined): ApprovalIdentity;
|
|
23
21
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.identity.d.ts","sourceRoot":"","sources":["../src/approval.identity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"approval.identity.d.ts","sourceRoot":"","sources":["../src/approval.identity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,KAAK,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,GAAG,UAAU,CAAC,CAAC;AAMrF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,qBAAqB,GAAG,SAAS,GAAG,gBAAgB,CAWhG"}
|
package/esm/index.mjs
CHANGED
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
} from "@frontmcp/sdk";
|
|
27
27
|
|
|
28
28
|
// plugins/plugin-approval/src/approval.identity.ts
|
|
29
|
-
import { STATELESS_SESSION_ID } from "@frontmcp/sdk";
|
|
30
29
|
import { randomUUID } from "@frontmcp/utils";
|
|
31
30
|
function nonEmptyString(value) {
|
|
32
31
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -34,8 +33,8 @@ function nonEmptyString(value) {
|
|
|
34
33
|
function resolveApprovalIdentity(ctx) {
|
|
35
34
|
const extra = ctx?.authInfo?.extra;
|
|
36
35
|
const userId = nonEmptyString(extra?.["userId"]) ?? nonEmptyString(extra?.["sub"]) ?? nonEmptyString(ctx?.authInfo?.clientId);
|
|
37
|
-
const sessionId = nonEmptyString(ctx?.
|
|
38
|
-
if (sessionId
|
|
36
|
+
const sessionId = nonEmptyString(ctx?.verifiedSessionId);
|
|
37
|
+
if (sessionId) {
|
|
39
38
|
return { sessionId, userId };
|
|
40
39
|
}
|
|
41
40
|
return { sessionId: userId ? `stateless-user:${userId}` : `unidentified:${randomUUID()}`, userId };
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-approval",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "Approval plugin for FrontMCP - tool authorization workflow with PKCE webhook security",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@frontmcp/sdk": "1.8.
|
|
53
|
-
"@frontmcp/utils": "1.8.
|
|
52
|
+
"@frontmcp/sdk": "1.8.2",
|
|
53
|
+
"@frontmcp/utils": "1.8.2",
|
|
54
54
|
"ioredis": "^5.8.0",
|
|
55
55
|
"reflect-metadata": "^0.2.2"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@frontmcp/lazy-zod": "1.8.
|
|
58
|
+
"@frontmcp/lazy-zod": "1.8.2",
|
|
59
59
|
"@vercel/kv": "^2.0.0 || ^3.0.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
package/index.js
CHANGED
|
@@ -76,10 +76,9 @@ __export(index_exports, {
|
|
|
76
76
|
module.exports = __toCommonJS(index_exports);
|
|
77
77
|
|
|
78
78
|
// plugins/plugin-approval/src/approval.plugin.ts
|
|
79
|
-
var
|
|
79
|
+
var import_sdk5 = require("@frontmcp/sdk");
|
|
80
80
|
|
|
81
81
|
// plugins/plugin-approval/src/approval.identity.ts
|
|
82
|
-
var import_sdk = require("@frontmcp/sdk");
|
|
83
82
|
var import_utils = require("@frontmcp/utils");
|
|
84
83
|
function nonEmptyString(value) {
|
|
85
84
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -87,8 +86,8 @@ function nonEmptyString(value) {
|
|
|
87
86
|
function resolveApprovalIdentity(ctx) {
|
|
88
87
|
const extra = ctx?.authInfo?.extra;
|
|
89
88
|
const userId = nonEmptyString(extra?.["userId"]) ?? nonEmptyString(extra?.["sub"]) ?? nonEmptyString(ctx?.authInfo?.clientId);
|
|
90
|
-
const sessionId = nonEmptyString(ctx?.
|
|
91
|
-
if (sessionId
|
|
89
|
+
const sessionId = nonEmptyString(ctx?.verifiedSessionId);
|
|
90
|
+
if (sessionId) {
|
|
92
91
|
return { sessionId, userId };
|
|
93
92
|
}
|
|
94
93
|
return { sessionId: userId ? `stateless-user:${userId}` : `unidentified:${(0, import_utils.randomUUID)()}`, userId };
|
|
@@ -106,7 +105,7 @@ var ChallengeServiceToken = /* @__PURE__ */ Symbol.for(
|
|
|
106
105
|
);
|
|
107
106
|
|
|
108
107
|
// plugins/plugin-approval/src/hooks/approval-check.hook.ts
|
|
109
|
-
var
|
|
108
|
+
var import_sdk = require("@frontmcp/sdk");
|
|
110
109
|
|
|
111
110
|
// plugins/plugin-approval/src/approval/types.ts
|
|
112
111
|
var ApprovalScope = /* @__PURE__ */ ((ApprovalScope2) => {
|
|
@@ -473,7 +472,7 @@ var ChallengeValidationError = class extends ApprovalError {
|
|
|
473
472
|
|
|
474
473
|
// plugins/plugin-approval/src/hooks/approval-check.hook.ts
|
|
475
474
|
var passedApprovalStores = /* @__PURE__ */ new WeakMap();
|
|
476
|
-
var ApprovalCheckPlugin = class extends
|
|
475
|
+
var ApprovalCheckPlugin = class extends import_sdk.DynamicPlugin {
|
|
477
476
|
async checkApproval(flowCtx) {
|
|
478
477
|
const { tool, toolContext } = flowCtx.state;
|
|
479
478
|
if (!tool || !toolContext) return;
|
|
@@ -579,17 +578,17 @@ var ApprovalCheckPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
579
578
|
}
|
|
580
579
|
};
|
|
581
580
|
__decorateClass([
|
|
582
|
-
|
|
581
|
+
import_sdk.ToolHook.Will("execute", { priority: 100 })
|
|
583
582
|
], ApprovalCheckPlugin.prototype, "checkApproval", 1);
|
|
584
583
|
ApprovalCheckPlugin = __decorateClass([
|
|
585
|
-
(0,
|
|
584
|
+
(0, import_sdk.Plugin)({
|
|
586
585
|
name: "approval:check",
|
|
587
586
|
description: "Checks tool approval state before execution"
|
|
588
587
|
})
|
|
589
588
|
], ApprovalCheckPlugin);
|
|
590
589
|
|
|
591
590
|
// plugins/plugin-approval/src/services/approval.service.ts
|
|
592
|
-
var
|
|
591
|
+
var import_sdk2 = require("@frontmcp/sdk");
|
|
593
592
|
var ApprovalService = class {
|
|
594
593
|
constructor(store, sessionId, userId) {
|
|
595
594
|
this.store = store;
|
|
@@ -731,10 +730,10 @@ var ApprovalService = class {
|
|
|
731
730
|
}
|
|
732
731
|
};
|
|
733
732
|
ApprovalService = __decorateClass([
|
|
734
|
-
(0,
|
|
733
|
+
(0, import_sdk2.Provider)({
|
|
735
734
|
name: "provider:approval:service",
|
|
736
735
|
description: "Service for managing tool approvals",
|
|
737
|
-
scope:
|
|
736
|
+
scope: import_sdk2.ProviderScope.CONTEXT
|
|
738
737
|
})
|
|
739
738
|
], ApprovalService);
|
|
740
739
|
function createApprovalService(store, sessionId, userId) {
|
|
@@ -742,7 +741,7 @@ function createApprovalService(store, sessionId, userId) {
|
|
|
742
741
|
}
|
|
743
742
|
|
|
744
743
|
// plugins/plugin-approval/src/services/challenge.service.ts
|
|
745
|
-
var
|
|
744
|
+
var import_sdk3 = require("@frontmcp/sdk");
|
|
746
745
|
var import_utils2 = require("@frontmcp/utils");
|
|
747
746
|
var ChallengeService = class {
|
|
748
747
|
storage;
|
|
@@ -876,10 +875,10 @@ var ChallengeService = class {
|
|
|
876
875
|
}
|
|
877
876
|
};
|
|
878
877
|
ChallengeService = __decorateClass([
|
|
879
|
-
(0,
|
|
878
|
+
(0, import_sdk3.Provider)({
|
|
880
879
|
name: "provider:approval:challenge-service",
|
|
881
880
|
description: "PKCE challenge service for webhook approval flows",
|
|
882
|
-
scope:
|
|
881
|
+
scope: import_sdk3.ProviderScope.GLOBAL
|
|
883
882
|
})
|
|
884
883
|
], ChallengeService);
|
|
885
884
|
function generatePkcePairFromVerifier(codeVerifier) {
|
|
@@ -897,7 +896,7 @@ function createMemoryChallengeService(options = {}) {
|
|
|
897
896
|
}
|
|
898
897
|
|
|
899
898
|
// plugins/plugin-approval/src/stores/approval-storage.store.ts
|
|
900
|
-
var
|
|
899
|
+
var import_sdk4 = require("@frontmcp/sdk");
|
|
901
900
|
var import_utils3 = require("@frontmcp/utils");
|
|
902
901
|
function escapePattern(str) {
|
|
903
902
|
return str.replace(/[*?[\]\\]/g, "\\$&");
|
|
@@ -1146,10 +1145,10 @@ var ApprovalStorageStore = class {
|
|
|
1146
1145
|
}
|
|
1147
1146
|
};
|
|
1148
1147
|
ApprovalStorageStore = __decorateClass([
|
|
1149
|
-
(0,
|
|
1148
|
+
(0, import_sdk4.Provider)({
|
|
1150
1149
|
name: "provider:approval:store:storage",
|
|
1151
1150
|
description: "Storage-backed approval store (supports Memory, Redis, Vercel KV, Upstash)",
|
|
1152
|
-
scope:
|
|
1151
|
+
scope: import_sdk4.ProviderScope.GLOBAL
|
|
1153
1152
|
})
|
|
1154
1153
|
], ApprovalStorageStore);
|
|
1155
1154
|
function createApprovalMemoryStore(options = {}) {
|
|
@@ -1161,7 +1160,7 @@ function createApprovalMemoryStore(options = {}) {
|
|
|
1161
1160
|
}
|
|
1162
1161
|
|
|
1163
1162
|
// plugins/plugin-approval/src/approval.plugin.ts
|
|
1164
|
-
var ApprovalPlugin = class extends
|
|
1163
|
+
var ApprovalPlugin = class extends import_sdk5.DynamicPlugin {
|
|
1165
1164
|
options;
|
|
1166
1165
|
constructor(options = {}) {
|
|
1167
1166
|
super();
|
|
@@ -1222,8 +1221,8 @@ __publicField(ApprovalPlugin, "dynamicProviders", (options) => {
|
|
|
1222
1221
|
providers.push({
|
|
1223
1222
|
name: "approval:service",
|
|
1224
1223
|
provide: ApprovalServiceToken,
|
|
1225
|
-
scope:
|
|
1226
|
-
inject: () => [ApprovalStoreToken,
|
|
1224
|
+
scope: import_sdk5.ProviderScope.CONTEXT,
|
|
1225
|
+
inject: () => [ApprovalStoreToken, import_sdk5.FRONTMCP_CONTEXT],
|
|
1227
1226
|
useFactory: (store, ctx) => {
|
|
1228
1227
|
const { sessionId, userId } = resolveApprovalIdentity(ctx);
|
|
1229
1228
|
return createApprovalService(store, sessionId, userId);
|
|
@@ -1232,7 +1231,7 @@ __publicField(ApprovalPlugin, "dynamicProviders", (options) => {
|
|
|
1232
1231
|
return providers;
|
|
1233
1232
|
});
|
|
1234
1233
|
ApprovalPlugin = __decorateClass([
|
|
1235
|
-
(0,
|
|
1234
|
+
(0, import_sdk5.Plugin)({
|
|
1236
1235
|
name: "approval",
|
|
1237
1236
|
description: "Tool authorization workflow with PKCE webhook security",
|
|
1238
1237
|
plugins: [ApprovalCheckPlugin],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-approval",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "Approval plugin for FrontMCP - tool authorization workflow with PKCE webhook security",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@frontmcp/sdk": "1.8.
|
|
53
|
-
"@frontmcp/utils": "1.8.
|
|
52
|
+
"@frontmcp/sdk": "1.8.2",
|
|
53
|
+
"@frontmcp/utils": "1.8.2",
|
|
54
54
|
"ioredis": "^5.8.0",
|
|
55
55
|
"reflect-metadata": "^0.2.2"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@frontmcp/lazy-zod": "1.8.
|
|
58
|
+
"@frontmcp/lazy-zod": "1.8.2",
|
|
59
59
|
"@vercel/kv": "^2.0.0 || ^3.0.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|