@frontmcp/testing 1.3.0 → 1.4.1

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.
@@ -2841,7 +2841,7 @@ var ProgressCollector = class {
2841
2841
  };
2842
2842
 
2843
2843
  // libs/testing/src/auth/token-factory.ts
2844
- import { SignJWT, generateKeyPair, exportJWK } from "jose";
2844
+ import { exportJWK, generateKeyPair, SignJWT } from "jose";
2845
2845
  var TestTokenFactory = class {
2846
2846
  issuer;
2847
2847
  audience;
@@ -2849,15 +2849,39 @@ var TestTokenFactory = class {
2849
2849
  publicKey = null;
2850
2850
  jwk = null;
2851
2851
  keyId;
2852
+ /** HS256 shared secret (gateway mode). Null → RS256 + JWKS (default). */
2853
+ hmacSecret;
2852
2854
  constructor(options = {}) {
2853
2855
  this.issuer = options.issuer ?? "https://test.frontmcp.local";
2854
2856
  this.audience = options.audience ?? "frontmcp-test";
2855
2857
  this.keyId = `test-key-${Date.now()}`;
2858
+ this.hmacSecret = options.hmacSecret ? new TextEncoder().encode(options.hmacSecret) : null;
2859
+ }
2860
+ /** True when this factory signs HS256 with a shared secret (gateway mode). */
2861
+ get isHmac() {
2862
+ return this.hmacSecret !== null;
2863
+ }
2864
+ /** The JWS `alg` this factory signs with. */
2865
+ get alg() {
2866
+ return this.isHmac ? "HS256" : "RS256";
2867
+ }
2868
+ /**
2869
+ * The signing key: the shared HMAC secret in gateway mode, otherwise the
2870
+ * generated RSA private key (lazily created via ensureKeys()).
2871
+ */
2872
+ signingKey() {
2873
+ if (this.hmacSecret) return this.hmacSecret;
2874
+ if (!this.privateKey) {
2875
+ throw new Error("Private key not initialized");
2876
+ }
2877
+ return this.privateKey;
2856
2878
  }
2857
2879
  /**
2858
- * Initialize the key pair (called automatically on first use)
2880
+ * Initialize the key pair (called automatically on first use). No-op in HS256
2881
+ * mode — there is no asymmetric keypair, just the shared secret.
2859
2882
  */
2860
2883
  async ensureKeys() {
2884
+ if (this.isHmac) return;
2861
2885
  if (this.privateKey && this.publicKey) return;
2862
2886
  const { publicKey, privateKey } = await generateKeyPair("RS256", {
2863
2887
  extractable: true
@@ -2885,10 +2909,8 @@ var TestTokenFactory = class {
2885
2909
  scope: options.scopes?.join(" "),
2886
2910
  ...options.claims
2887
2911
  };
2888
- if (!this.privateKey) {
2889
- throw new Error("Private key not initialized");
2890
- }
2891
- const token = await new SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2912
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2913
+ const token = await new SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
2892
2914
  return token;
2893
2915
  }
2894
2916
  /**
@@ -2947,10 +2969,8 @@ var TestTokenFactory = class {
2947
2969
  exp: now - 3600
2948
2970
  // Expired 1 hour ago
2949
2971
  };
2950
- if (!this.privateKey) {
2951
- throw new Error("Private key not initialized");
2952
- }
2953
- const token = await new SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2972
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2973
+ const token = await new SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
2954
2974
  return token;
2955
2975
  }
2956
2976
  /**
@@ -2958,7 +2978,8 @@ var TestTokenFactory = class {
2958
2978
  */
2959
2979
  createTokenWithInvalidSignature(options) {
2960
2980
  const now = Math.floor(Date.now() / 1e3);
2961
- const header = Buffer.from(JSON.stringify({ alg: "RS256", kid: this.keyId })).toString("base64url");
2981
+ const headerObj = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2982
+ const header = Buffer.from(JSON.stringify(headerObj)).toString("base64url");
2962
2983
  const payload = Buffer.from(
2963
2984
  JSON.stringify({
2964
2985
  iss: this.issuer,
@@ -2972,9 +2993,15 @@ var TestTokenFactory = class {
2972
2993
  return `${header}.${payload}.${signature}`;
2973
2994
  }
2974
2995
  /**
2975
- * Get the public JWKS for verifying tokens
2996
+ * Get the public JWKS for verifying tokens.
2997
+ *
2998
+ * Only meaningful in RS256 mode — HS256 (gateway) tokens are verified against
2999
+ * the shared secret, not a published public key, so there is no JWKS to serve.
2976
3000
  */
2977
3001
  async getPublicJwks() {
3002
+ if (this.isHmac) {
3003
+ throw new Error("getPublicJwks() is not available in HS256 mode (gateway tokens use a shared secret)");
3004
+ }
2978
3005
  await this.ensureKeys();
2979
3006
  if (!this.jwk) {
2980
3007
  throw new Error("JWK not initialized");
@@ -3036,6 +3063,7 @@ var E2E_PORT_RANGES = {
3036
3063
  "demo-e2e-orchestrated": { start: 50100, size: 10 },
3037
3064
  "demo-e2e-transparent": { start: 50110, size: 10 },
3038
3065
  "demo-e2e-cimd": { start: 50120, size: 10 },
3066
+ "demo-e2e-remote-proxy": { start: 50130, size: 10 },
3039
3067
  // Feature E2E tests (50200-50299)
3040
3068
  "demo-e2e-skills": { start: 50200, size: 10 },
3041
3069
  "demo-e2e-remote": { start: 50210, size: 10 },
package/fixtures/index.js CHANGED
@@ -31,6 +31,190 @@ module.exports = __toCommonJS(fixtures_exports);
31
31
  // libs/testing/src/fixtures/test-fixture.ts
32
32
  var import_globals = require("@jest/globals");
33
33
 
34
+ // libs/testing/src/auth/token-factory.ts
35
+ var import_jose = require("jose");
36
+ var TestTokenFactory = class {
37
+ issuer;
38
+ audience;
39
+ privateKey = null;
40
+ publicKey = null;
41
+ jwk = null;
42
+ keyId;
43
+ /** HS256 shared secret (gateway mode). Null → RS256 + JWKS (default). */
44
+ hmacSecret;
45
+ constructor(options = {}) {
46
+ this.issuer = options.issuer ?? "https://test.frontmcp.local";
47
+ this.audience = options.audience ?? "frontmcp-test";
48
+ this.keyId = `test-key-${Date.now()}`;
49
+ this.hmacSecret = options.hmacSecret ? new TextEncoder().encode(options.hmacSecret) : null;
50
+ }
51
+ /** True when this factory signs HS256 with a shared secret (gateway mode). */
52
+ get isHmac() {
53
+ return this.hmacSecret !== null;
54
+ }
55
+ /** The JWS `alg` this factory signs with. */
56
+ get alg() {
57
+ return this.isHmac ? "HS256" : "RS256";
58
+ }
59
+ /**
60
+ * The signing key: the shared HMAC secret in gateway mode, otherwise the
61
+ * generated RSA private key (lazily created via ensureKeys()).
62
+ */
63
+ signingKey() {
64
+ if (this.hmacSecret) return this.hmacSecret;
65
+ if (!this.privateKey) {
66
+ throw new Error("Private key not initialized");
67
+ }
68
+ return this.privateKey;
69
+ }
70
+ /**
71
+ * Initialize the key pair (called automatically on first use). No-op in HS256
72
+ * mode — there is no asymmetric keypair, just the shared secret.
73
+ */
74
+ async ensureKeys() {
75
+ if (this.isHmac) return;
76
+ if (this.privateKey && this.publicKey) return;
77
+ const { publicKey, privateKey } = await (0, import_jose.generateKeyPair)("RS256", {
78
+ extractable: true
79
+ });
80
+ this.privateKey = privateKey;
81
+ this.publicKey = publicKey;
82
+ this.jwk = await (0, import_jose.exportJWK)(publicKey);
83
+ this.jwk.kid = this.keyId;
84
+ this.jwk.use = "sig";
85
+ this.jwk.alg = "RS256";
86
+ }
87
+ /**
88
+ * Create a JWT token with the specified claims
89
+ */
90
+ async createTestToken(options) {
91
+ await this.ensureKeys();
92
+ const now = Math.floor(Date.now() / 1e3);
93
+ const exp = options.exp ?? 3600;
94
+ const payload = {
95
+ iss: options.iss ?? this.issuer,
96
+ sub: options.sub,
97
+ aud: options.aud ?? this.audience,
98
+ iat: now,
99
+ exp: now + exp,
100
+ scope: options.scopes?.join(" "),
101
+ ...options.claims
102
+ };
103
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
104
+ const token = await new import_jose.SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
105
+ return token;
106
+ }
107
+ /**
108
+ * Create an admin token with full access
109
+ */
110
+ async createAdminToken(sub = "admin-001") {
111
+ return this.createTestToken({
112
+ sub,
113
+ scopes: ["admin:*", "read", "write", "delete"],
114
+ claims: {
115
+ email: "admin@test.local",
116
+ name: "Test Admin",
117
+ role: "admin"
118
+ }
119
+ });
120
+ }
121
+ /**
122
+ * Create a regular user token
123
+ */
124
+ async createUserToken(sub = "user-001", scopes = ["read", "write"]) {
125
+ return this.createTestToken({
126
+ sub,
127
+ scopes,
128
+ claims: {
129
+ email: "user@test.local",
130
+ name: "Test User",
131
+ role: "user"
132
+ }
133
+ });
134
+ }
135
+ /**
136
+ * Create an anonymous user token
137
+ */
138
+ async createAnonymousToken() {
139
+ return this.createTestToken({
140
+ sub: `anon:${Date.now()}`,
141
+ scopes: ["anonymous"],
142
+ claims: {
143
+ name: "Anonymous",
144
+ role: "anonymous"
145
+ }
146
+ });
147
+ }
148
+ /**
149
+ * Create an expired token (for testing token expiration)
150
+ */
151
+ async createExpiredToken(options) {
152
+ await this.ensureKeys();
153
+ const now = Math.floor(Date.now() / 1e3);
154
+ const payload = {
155
+ iss: this.issuer,
156
+ sub: options.sub,
157
+ aud: this.audience,
158
+ iat: now - 7200,
159
+ // 2 hours ago
160
+ exp: now - 3600
161
+ // Expired 1 hour ago
162
+ };
163
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
164
+ const token = await new import_jose.SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
165
+ return token;
166
+ }
167
+ /**
168
+ * Create a token with an invalid signature (for testing signature validation)
169
+ */
170
+ createTokenWithInvalidSignature(options) {
171
+ const now = Math.floor(Date.now() / 1e3);
172
+ const headerObj = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
173
+ const header = Buffer.from(JSON.stringify(headerObj)).toString("base64url");
174
+ const payload = Buffer.from(
175
+ JSON.stringify({
176
+ iss: this.issuer,
177
+ sub: options.sub,
178
+ aud: this.audience,
179
+ iat: now,
180
+ exp: now + 3600
181
+ })
182
+ ).toString("base64url");
183
+ const signature = Buffer.from("invalid-signature-" + Date.now()).toString("base64url");
184
+ return `${header}.${payload}.${signature}`;
185
+ }
186
+ /**
187
+ * Get the public JWKS for verifying tokens.
188
+ *
189
+ * Only meaningful in RS256 mode — HS256 (gateway) tokens are verified against
190
+ * the shared secret, not a published public key, so there is no JWKS to serve.
191
+ */
192
+ async getPublicJwks() {
193
+ if (this.isHmac) {
194
+ throw new Error("getPublicJwks() is not available in HS256 mode (gateway tokens use a shared secret)");
195
+ }
196
+ await this.ensureKeys();
197
+ if (!this.jwk) {
198
+ throw new Error("JWK not initialized");
199
+ }
200
+ return {
201
+ keys: [this.jwk]
202
+ };
203
+ }
204
+ /**
205
+ * Get the issuer URL
206
+ */
207
+ getIssuer() {
208
+ return this.issuer;
209
+ }
210
+ /**
211
+ * Get the audience
212
+ */
213
+ getAudience() {
214
+ return this.audience;
215
+ }
216
+ };
217
+
34
218
  // libs/testing/src/platform/platform-client-info.ts
35
219
  var MCP_APPS_EXTENSION_KEY = "io.modelcontextprotocol/ui";
36
220
  function getPlatformClientInfo(platform) {
@@ -2101,163 +2285,6 @@ var ProgressCollector = class {
2101
2285
  }
2102
2286
  };
2103
2287
 
2104
- // libs/testing/src/auth/token-factory.ts
2105
- var import_jose = require("jose");
2106
- var TestTokenFactory = class {
2107
- issuer;
2108
- audience;
2109
- privateKey = null;
2110
- publicKey = null;
2111
- jwk = null;
2112
- keyId;
2113
- constructor(options = {}) {
2114
- this.issuer = options.issuer ?? "https://test.frontmcp.local";
2115
- this.audience = options.audience ?? "frontmcp-test";
2116
- this.keyId = `test-key-${Date.now()}`;
2117
- }
2118
- /**
2119
- * Initialize the key pair (called automatically on first use)
2120
- */
2121
- async ensureKeys() {
2122
- if (this.privateKey && this.publicKey) return;
2123
- const { publicKey, privateKey } = await (0, import_jose.generateKeyPair)("RS256", {
2124
- extractable: true
2125
- });
2126
- this.privateKey = privateKey;
2127
- this.publicKey = publicKey;
2128
- this.jwk = await (0, import_jose.exportJWK)(publicKey);
2129
- this.jwk.kid = this.keyId;
2130
- this.jwk.use = "sig";
2131
- this.jwk.alg = "RS256";
2132
- }
2133
- /**
2134
- * Create a JWT token with the specified claims
2135
- */
2136
- async createTestToken(options) {
2137
- await this.ensureKeys();
2138
- const now = Math.floor(Date.now() / 1e3);
2139
- const exp = options.exp ?? 3600;
2140
- const payload = {
2141
- iss: options.iss ?? this.issuer,
2142
- sub: options.sub,
2143
- aud: options.aud ?? this.audience,
2144
- iat: now,
2145
- exp: now + exp,
2146
- scope: options.scopes?.join(" "),
2147
- ...options.claims
2148
- };
2149
- if (!this.privateKey) {
2150
- throw new Error("Private key not initialized");
2151
- }
2152
- const token = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2153
- return token;
2154
- }
2155
- /**
2156
- * Create an admin token with full access
2157
- */
2158
- async createAdminToken(sub = "admin-001") {
2159
- return this.createTestToken({
2160
- sub,
2161
- scopes: ["admin:*", "read", "write", "delete"],
2162
- claims: {
2163
- email: "admin@test.local",
2164
- name: "Test Admin",
2165
- role: "admin"
2166
- }
2167
- });
2168
- }
2169
- /**
2170
- * Create a regular user token
2171
- */
2172
- async createUserToken(sub = "user-001", scopes = ["read", "write"]) {
2173
- return this.createTestToken({
2174
- sub,
2175
- scopes,
2176
- claims: {
2177
- email: "user@test.local",
2178
- name: "Test User",
2179
- role: "user"
2180
- }
2181
- });
2182
- }
2183
- /**
2184
- * Create an anonymous user token
2185
- */
2186
- async createAnonymousToken() {
2187
- return this.createTestToken({
2188
- sub: `anon:${Date.now()}`,
2189
- scopes: ["anonymous"],
2190
- claims: {
2191
- name: "Anonymous",
2192
- role: "anonymous"
2193
- }
2194
- });
2195
- }
2196
- /**
2197
- * Create an expired token (for testing token expiration)
2198
- */
2199
- async createExpiredToken(options) {
2200
- await this.ensureKeys();
2201
- const now = Math.floor(Date.now() / 1e3);
2202
- const payload = {
2203
- iss: this.issuer,
2204
- sub: options.sub,
2205
- aud: this.audience,
2206
- iat: now - 7200,
2207
- // 2 hours ago
2208
- exp: now - 3600
2209
- // Expired 1 hour ago
2210
- };
2211
- if (!this.privateKey) {
2212
- throw new Error("Private key not initialized");
2213
- }
2214
- const token = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2215
- return token;
2216
- }
2217
- /**
2218
- * Create a token with an invalid signature (for testing signature validation)
2219
- */
2220
- createTokenWithInvalidSignature(options) {
2221
- const now = Math.floor(Date.now() / 1e3);
2222
- const header = Buffer.from(JSON.stringify({ alg: "RS256", kid: this.keyId })).toString("base64url");
2223
- const payload = Buffer.from(
2224
- JSON.stringify({
2225
- iss: this.issuer,
2226
- sub: options.sub,
2227
- aud: this.audience,
2228
- iat: now,
2229
- exp: now + 3600
2230
- })
2231
- ).toString("base64url");
2232
- const signature = Buffer.from("invalid-signature-" + Date.now()).toString("base64url");
2233
- return `${header}.${payload}.${signature}`;
2234
- }
2235
- /**
2236
- * Get the public JWKS for verifying tokens
2237
- */
2238
- async getPublicJwks() {
2239
- await this.ensureKeys();
2240
- if (!this.jwk) {
2241
- throw new Error("JWK not initialized");
2242
- }
2243
- return {
2244
- keys: [this.jwk]
2245
- };
2246
- }
2247
- /**
2248
- * Get the issuer URL
2249
- */
2250
- getIssuer() {
2251
- return this.issuer;
2252
- }
2253
- /**
2254
- * Get the audience
2255
- */
2256
- getAudience() {
2257
- return this.audience;
2258
- }
2259
- };
2260
-
2261
2288
  // libs/testing/src/server/test-server.ts
2262
2289
  var import_child_process = require("child_process");
2263
2290
  var import_utils = require("@frontmcp/utils");
@@ -2297,6 +2324,7 @@ var E2E_PORT_RANGES = {
2297
2324
  "demo-e2e-orchestrated": { start: 50100, size: 10 },
2298
2325
  "demo-e2e-transparent": { start: 50110, size: 10 },
2299
2326
  "demo-e2e-cimd": { start: 50120, size: 10 },
2327
+ "demo-e2e-remote-proxy": { start: 50130, size: 10 },
2300
2328
  // Feature E2E tests (50200-50299)
2301
2329
  "demo-e2e-skills": { start: 50200, size: 10 },
2302
2330
  "demo-e2e-remote": { start: 50210, size: 10 },
@@ -2971,7 +2999,8 @@ var tokenFactory = null;
2971
2999
  var serverStartedByUs = false;
2972
3000
  async function initializeSharedResources() {
2973
3001
  if (!tokenFactory) {
2974
- tokenFactory = new TestTokenFactory();
3002
+ const sharedSecret = currentConfig.env?.["JWT_SECRET"];
3003
+ tokenFactory = new TestTokenFactory(sharedSecret ? { hmacSecret: sharedSecret } : {});
2975
3004
  }
2976
3005
  if (!serverInstance) {
2977
3006
  if (currentConfig.baseUrl) {
@@ -1 +1 @@
1
- {"version":3,"file":"test-fixture.d.ts","sourceRoot":"","sources":["../../src/fixtures/test-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAwBH,OAAO,KAAK,EAEV,YAAY,EAIZ,gBAAgB,EAEjB,MAAM,iBAAiB,CAAC;AAsBzB;;GAEG;AACH,iBAAe,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqDxD;AAED;;GAEG;AACH,iBAAe,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA6BzD;AAED;;;;GAIG;AACH,iBAAe,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB5F;AAED;;GAEG;AACH,iBAAe,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQrD;AAmMD,QAAA,MAAM,IAAI,EAAuB,gBAAgB,CAAC;AAqBlD,OAAO,EAAE,IAAI,EAAE,CAAC;AAGhB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,CAAC"}
1
+ {"version":3,"file":"test-fixture.d.ts","sourceRoot":"","sources":["../../src/fixtures/test-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH,OAAO,KAAK,EAIV,YAAY,EAGZ,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AA+BzB;;GAEG;AACH,iBAAe,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6DxD;AAED;;GAEG;AACH,iBAAe,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA6BzD;AAED;;;;GAIG;AACH,iBAAe,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB5F;AAED;;GAEG;AACH,iBAAe,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQrD;AAmMD,QAAA,MAAM,IAAI,EAAuB,gBAAgB,CAAC;AAqBlD,OAAO,EAAE,IAAI,EAAE,CAAC;AAGhB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,CAAC"}
package/index.d.ts CHANGED
@@ -73,6 +73,6 @@ export type { TestPlatformType, PlatformMetaNamespace, TestClientInfo } from './
73
73
  export { getPlatformMetaNamespace, getPlatformMimeType, isOpenAIPlatform, isExtAppsPlatform, isUiPlatform, getToolsListMetaPrefixes, getToolCallMetaPrefixes, getForbiddenMetaPrefixes, getPlatformClientInfo, buildUserAgent, getPlatformUserAgent, PLATFORM_DETECTION_PATTERNS, } from './platform';
74
74
  export { BASIC_UI_TOOL_CONFIG, FULL_UI_TOOL_CONFIG, basicUIToolInputSchema, basicUIToolOutputSchema, fullUIToolInputSchema, fullUIToolOutputSchema, generateBasicUIToolOutput, generateFullUIToolOutput, EXPECTED_OPENAI_TOOLS_LIST_META_KEYS, EXPECTED_OPENAI_TOOL_CALL_META_KEYS, EXPECTED_EXTAPPS_TOOLS_LIST_META_KEYS, EXPECTED_EXTAPPS_TOOL_CALL_META_KEYS, EXPECTED_GENERIC_TOOLS_LIST_META_KEYS, EXPECTED_GENERIC_TOOL_CALL_META_KEYS, } from './example-tools';
75
75
  export { perfTest, MetricsCollector, isGcAvailable, forceGc, forceFullGc, formatBytes, formatMicroseconds, formatDuration, LeakDetector, assertNoLeak, createLeakDetector, createPerfFixtures, PerfFixturesImpl, getGlobalMeasurements, clearGlobalMeasurements, BaselineStore, parseBaselineFromComment, formatBaselineAsComment, getBaselineStore, RegressionDetector, summarizeRegressions, getRegressionDetector, ReportGenerator, saveReports, createReportGenerator, } from './perf';
76
- export { McpClient, McpStdioClientTransport } from './raw-client';
76
+ export { McpClient, McpStdioClientTransport, isTcpPortListening } from './raw-client';
77
77
  export type { MemoryMetrics, CpuMetrics, PerfSnapshot, PerfMeasurement, PerfIssue, PerfThresholds, LeakDetectionOptions, LeakDetectionResult, MetricBaseline, TestBaseline, PerfBaseline, RegressionConfig, MetricRegression, RegressionResult, PerfTestSummary, ProjectSummary, PerfReport, PerfFixtures, PerfTestFixtures, PerfTestConfig, PerfTestFn, PerfTestWithFixtures, } from './perf';
78
78
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAMH,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,SAAS,GACV,MAAM,gCAAgC,CAAC;AAMxC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACrG,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAMhF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM9E,OAAO,EACL,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,OAAO,EACP,cAAc,EACd,WAAW,GACZ,MAAM,6BAA6B,CAAC;AAMrC,OAAO,EACL,eAAe,EACf,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAMxB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,MAAM,EAEN,cAAc,EACd,eAAe,GAChB,MAAM,gCAAgC,CAAC;AAMxC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,YAAY,EACV,UAAU,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,MAAM,EACN,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMlC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzG,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,UAAU,EACV,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAMvB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErD,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAMhD,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1F,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,YAAY,CAAC;AAMpB,OAAO,EAEL,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EAEtB,yBAAyB,EACzB,wBAAwB,EAExB,oCAAoC,EACpC,mCAAmC,EACnC,qCAAqC,EACrC,oCAAoC,EACpC,qCAAqC,EACrC,oCAAoC,GACrC,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAEL,QAAQ,EAGR,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,cAAc,EAGd,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAGlB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EAGvB,aAAa,EACb,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAGhB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EAGrB,eAAe,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,QAAQ,CAAC;AAMhB,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEtF,YAAY,EAEV,aAAa,EACb,UAAU,EACV,YAAY,EAGZ,eAAe,EACf,SAAS,EACT,cAAc,EAGd,oBAAoB,EACpB,mBAAmB,EAGnB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAGhB,eAAe,EACf,cAAc,EACd,UAAU,EAGV,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,oBAAoB,GACrB,MAAM,QAAQ,CAAC"}
package/index.js CHANGED
@@ -111,6 +111,7 @@ __export(index_exports, {
111
111
  isGcAvailable: () => isGcAvailable,
112
112
  isOpenAIPlatform: () => isOpenAIPlatform,
113
113
  isSuccessful: () => isSuccessful,
114
+ isTcpPortListening: () => isTcpPortListening,
114
115
  isUiPlatform: () => isUiPlatform,
115
116
  mcpMatchers: () => mcpMatchers,
116
117
  mockResponse: () => mockResponse,
@@ -2285,15 +2286,39 @@ var TestTokenFactory = class {
2285
2286
  publicKey = null;
2286
2287
  jwk = null;
2287
2288
  keyId;
2289
+ /** HS256 shared secret (gateway mode). Null → RS256 + JWKS (default). */
2290
+ hmacSecret;
2288
2291
  constructor(options = {}) {
2289
2292
  this.issuer = options.issuer ?? "https://test.frontmcp.local";
2290
2293
  this.audience = options.audience ?? "frontmcp-test";
2291
2294
  this.keyId = `test-key-${Date.now()}`;
2295
+ this.hmacSecret = options.hmacSecret ? new TextEncoder().encode(options.hmacSecret) : null;
2296
+ }
2297
+ /** True when this factory signs HS256 with a shared secret (gateway mode). */
2298
+ get isHmac() {
2299
+ return this.hmacSecret !== null;
2300
+ }
2301
+ /** The JWS `alg` this factory signs with. */
2302
+ get alg() {
2303
+ return this.isHmac ? "HS256" : "RS256";
2292
2304
  }
2293
2305
  /**
2294
- * Initialize the key pair (called automatically on first use)
2306
+ * The signing key: the shared HMAC secret in gateway mode, otherwise the
2307
+ * generated RSA private key (lazily created via ensureKeys()).
2308
+ */
2309
+ signingKey() {
2310
+ if (this.hmacSecret) return this.hmacSecret;
2311
+ if (!this.privateKey) {
2312
+ throw new Error("Private key not initialized");
2313
+ }
2314
+ return this.privateKey;
2315
+ }
2316
+ /**
2317
+ * Initialize the key pair (called automatically on first use). No-op in HS256
2318
+ * mode — there is no asymmetric keypair, just the shared secret.
2295
2319
  */
2296
2320
  async ensureKeys() {
2321
+ if (this.isHmac) return;
2297
2322
  if (this.privateKey && this.publicKey) return;
2298
2323
  const { publicKey, privateKey } = await (0, import_jose.generateKeyPair)("RS256", {
2299
2324
  extractable: true
@@ -2321,10 +2346,8 @@ var TestTokenFactory = class {
2321
2346
  scope: options.scopes?.join(" "),
2322
2347
  ...options.claims
2323
2348
  };
2324
- if (!this.privateKey) {
2325
- throw new Error("Private key not initialized");
2326
- }
2327
- const token = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2349
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2350
+ const token = await new import_jose.SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
2328
2351
  return token;
2329
2352
  }
2330
2353
  /**
@@ -2383,10 +2406,8 @@ var TestTokenFactory = class {
2383
2406
  exp: now - 3600
2384
2407
  // Expired 1 hour ago
2385
2408
  };
2386
- if (!this.privateKey) {
2387
- throw new Error("Private key not initialized");
2388
- }
2389
- const token = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256", kid: this.keyId }).sign(this.privateKey);
2409
+ const header = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2410
+ const token = await new import_jose.SignJWT(payload).setProtectedHeader(header).sign(this.signingKey());
2390
2411
  return token;
2391
2412
  }
2392
2413
  /**
@@ -2394,7 +2415,8 @@ var TestTokenFactory = class {
2394
2415
  */
2395
2416
  createTokenWithInvalidSignature(options) {
2396
2417
  const now = Math.floor(Date.now() / 1e3);
2397
- const header = Buffer.from(JSON.stringify({ alg: "RS256", kid: this.keyId })).toString("base64url");
2418
+ const headerObj = this.isHmac ? { alg: this.alg, typ: "JWT" } : { alg: this.alg, kid: this.keyId };
2419
+ const header = Buffer.from(JSON.stringify(headerObj)).toString("base64url");
2398
2420
  const payload = Buffer.from(
2399
2421
  JSON.stringify({
2400
2422
  iss: this.issuer,
@@ -2408,9 +2430,15 @@ var TestTokenFactory = class {
2408
2430
  return `${header}.${payload}.${signature}`;
2409
2431
  }
2410
2432
  /**
2411
- * Get the public JWKS for verifying tokens
2433
+ * Get the public JWKS for verifying tokens.
2434
+ *
2435
+ * Only meaningful in RS256 mode — HS256 (gateway) tokens are verified against
2436
+ * the shared secret, not a published public key, so there is no JWKS to serve.
2412
2437
  */
2413
2438
  async getPublicJwks() {
2439
+ if (this.isHmac) {
2440
+ throw new Error("getPublicJwks() is not available in HS256 mode (gateway tokens use a shared secret)");
2441
+ }
2414
2442
  await this.ensureKeys();
2415
2443
  if (!this.jwk) {
2416
2444
  throw new Error("JWK not initialized");
@@ -4006,6 +4034,7 @@ var E2E_PORT_RANGES = {
4006
4034
  "demo-e2e-orchestrated": { start: 50100, size: 10 },
4007
4035
  "demo-e2e-transparent": { start: 50110, size: 10 },
4008
4036
  "demo-e2e-cimd": { start: 50120, size: 10 },
4037
+ "demo-e2e-remote-proxy": { start: 50130, size: 10 },
4009
4038
  // Feature E2E tests (50200-50299)
4010
4039
  "demo-e2e-skills": { start: 50200, size: 10 },
4011
4040
  "demo-e2e-remote": { start: 50210, size: 10 },
@@ -4846,7 +4875,8 @@ var tokenFactory = null;
4846
4875
  var serverStartedByUs = false;
4847
4876
  async function initializeSharedResources() {
4848
4877
  if (!tokenFactory) {
4849
- tokenFactory = new TestTokenFactory();
4878
+ const sharedSecret = currentConfig.env?.["JWT_SECRET"];
4879
+ tokenFactory = new TestTokenFactory(sharedSecret ? { hmacSecret: sharedSecret } : {});
4850
4880
  }
4851
4881
  if (!serverInstance) {
4852
4882
  if (currentConfig.baseUrl) {
@@ -8092,6 +8122,26 @@ function createReportGenerator() {
8092
8122
  // libs/testing/src/raw-client/index.ts
8093
8123
  var import_protocol = require("@frontmcp/protocol");
8094
8124
  var import_protocol2 = require("@frontmcp/protocol");
8125
+
8126
+ // libs/testing/src/raw-client/port-probe.ts
8127
+ var import_node_net = __toESM(require("node:net"));
8128
+ function isTcpPortListening(port, host = "127.0.0.1", timeoutMs = 1500) {
8129
+ return new Promise((resolve) => {
8130
+ const socket = import_node_net.default.connect({ port, host });
8131
+ socket.unref();
8132
+ socket.setTimeout(timeoutMs);
8133
+ let settled = false;
8134
+ const finish = (listening) => {
8135
+ if (settled) return;
8136
+ settled = true;
8137
+ socket.destroy();
8138
+ resolve(listening);
8139
+ };
8140
+ socket.once("connect", () => finish(true));
8141
+ socket.once("error", () => finish(false));
8142
+ socket.once("timeout", () => finish(false));
8143
+ });
8144
+ }
8095
8145
  // Annotate the CommonJS export names for ESM import in node:
8096
8146
  0 && (module.exports = {
8097
8147
  AssertionError,
@@ -8175,6 +8225,7 @@ var import_protocol2 = require("@frontmcp/protocol");
8175
8225
  isGcAvailable,
8176
8226
  isOpenAIPlatform,
8177
8227
  isSuccessful,
8228
+ isTcpPortListening,
8178
8229
  isUiPlatform,
8179
8230
  mcpMatchers,
8180
8231
  mockResponse,