@mcp-abap-adt/header-validator 0.1.8 → 0.3.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.
@@ -16,7 +16,9 @@ exports.validateAuthHeaders = validateAuthHeaders;
16
16
  exports.validateProxyHeaders = validateProxyHeaders;
17
17
  exports.isProxyRequest = isProxyRequest;
18
18
  exports.isMcpServerRequest = isMcpServerRequest;
19
- const interfaces_1 = require("@mcp-abap-adt/interfaces");
19
+ const interfaces_auth_1 = require("@mcp-abap-adt/interfaces-auth");
20
+ const interfaces_auth_sap_1 = require("@mcp-abap-adt/interfaces-auth-sap");
21
+ const interfaces_network_1 = require("@mcp-abap-adt/interfaces-network");
20
22
  /**
21
23
  * Extract header value (handles array values)
22
24
  * Node.js normalizes headers to lowercase, but check both cases for safety
@@ -55,47 +57,48 @@ function isValidUrl(url) {
55
57
  */
56
58
  function validateSapDestinationAuth(headers) {
57
59
  // Check both lowercase and original case (Node.js normalizes to lowercase, but check both for safety)
58
- const destinationRaw = headers[interfaces_1.HEADER_SAP_DESTINATION_SERVICE.toLowerCase()] || headers[interfaces_1.HEADER_SAP_DESTINATION_SERVICE];
60
+ const destinationRaw = headers[interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE.toLowerCase()] ||
61
+ headers[interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE];
59
62
  if (!destinationRaw) {
60
63
  return null;
61
64
  }
62
- const destination = getHeaderValue(headers, interfaces_1.HEADER_SAP_DESTINATION_SERVICE);
65
+ const destination = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE);
63
66
  const errors = [];
64
67
  const warnings = [];
65
68
  // Validate destination name (check if empty after trim)
66
69
  if (!destination || destination.length === 0) {
67
- errors.push(`${interfaces_1.HEADER_SAP_DESTINATION_SERVICE} header is empty`);
70
+ errors.push(`${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE} header is empty`);
68
71
  return {
69
- priority: interfaces_1.AuthMethodPriority.NONE,
70
- authType: interfaces_1.AUTH_TYPE_JWT, // SAP destination always uses JWT
72
+ priority: interfaces_auth_sap_1.AuthMethodPriority.NONE,
73
+ authType: interfaces_auth_1.AUTH_TYPE_JWT, // SAP destination always uses JWT
71
74
  sapUrl: '', // URL will be loaded from destination
72
75
  errors,
73
76
  warnings,
74
77
  };
75
78
  }
76
79
  // Extract optional SAP client
77
- const sapClient = getHeaderValue(headers, interfaces_1.HEADER_SAP_CLIENT);
80
+ const sapClient = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_CLIENT);
78
81
  // Optional: x-sap-login and x-sap-password (for cloud systems)
79
- const username = getHeaderValue(headers, interfaces_1.HEADER_SAP_LOGIN);
80
- const password = getHeaderValue(headers, interfaces_1.HEADER_SAP_PASSWORD);
82
+ const username = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_LOGIN);
83
+ const password = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_PASSWORD);
81
84
  // Warning if x-sap-url is provided (URL comes from destination, not header)
82
- const sapUrl = getHeaderValue(headers, interfaces_1.HEADER_SAP_URL);
85
+ const sapUrl = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_URL);
83
86
  if (sapUrl) {
84
- warnings.push(`${interfaces_1.HEADER_SAP_URL} is ignored when ${interfaces_1.HEADER_SAP_DESTINATION_SERVICE} is present (URL is loaded from destination service key or .env file)`);
87
+ warnings.push(`${interfaces_network_1.HEADER_SAP_URL} is ignored when ${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE} is present (URL is loaded from destination service key or .env file)`);
85
88
  }
86
89
  // Warning if direct JWT token is also provided (destination takes priority)
87
- const jwtToken = getHeaderValue(headers, interfaces_1.HEADER_SAP_JWT_TOKEN);
90
+ const jwtToken = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_JWT_TOKEN);
88
91
  if (jwtToken) {
89
- warnings.push(`${interfaces_1.HEADER_SAP_JWT_TOKEN} is ignored when ${interfaces_1.HEADER_SAP_DESTINATION_SERVICE} is present (destination-based auth takes priority)`);
92
+ warnings.push(`${interfaces_network_1.HEADER_SAP_JWT_TOKEN} is ignored when ${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE} is present (destination-based auth takes priority)`);
90
93
  }
91
94
  // Warning if auth-type is provided (not needed for x-sap-destination)
92
- const authType = getHeaderValue(headers, interfaces_1.HEADER_SAP_AUTH_TYPE);
95
+ const authType = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_AUTH_TYPE);
93
96
  if (authType) {
94
- warnings.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} is ignored when ${interfaces_1.HEADER_SAP_DESTINATION_SERVICE} is present (always uses JWT)`);
97
+ warnings.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} is ignored when ${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE} is present (always uses JWT)`);
95
98
  }
96
99
  return {
97
- priority: interfaces_1.AuthMethodPriority.SAP_DESTINATION,
98
- authType: interfaces_1.AUTH_TYPE_JWT, // Always JWT for x-sap-destination
100
+ priority: interfaces_auth_sap_1.AuthMethodPriority.SAP_DESTINATION,
101
+ authType: interfaces_auth_1.AUTH_TYPE_JWT, // Always JWT for x-sap-destination
99
102
  sapUrl: '', // URL will be loaded from destination (service key or .env)
100
103
  sapClient,
101
104
  destination,
@@ -113,19 +116,20 @@ function validateSapDestinationAuth(headers) {
113
116
  */
114
117
  function validateMcpDestinationAuth(headers, sapUrl) {
115
118
  // Check both lowercase and original case (Node.js normalizes to lowercase, but check both for safety)
116
- const destinationRaw = headers[interfaces_1.HEADER_MCP_DESTINATION.toLowerCase()] || headers[interfaces_1.HEADER_MCP_DESTINATION];
119
+ const destinationRaw = headers[interfaces_network_1.HEADER_MCP_DESTINATION.toLowerCase()] ||
120
+ headers[interfaces_network_1.HEADER_MCP_DESTINATION];
117
121
  if (!destinationRaw) {
118
122
  return null;
119
123
  }
120
- const destination = getHeaderValue(headers, interfaces_1.HEADER_MCP_DESTINATION);
124
+ const destination = getHeaderValue(headers, interfaces_network_1.HEADER_MCP_DESTINATION);
121
125
  const errors = [];
122
126
  const warnings = [];
123
127
  // Validate destination name (check if empty after trim)
124
128
  if (!destination || destination.length === 0) {
125
- errors.push(`${interfaces_1.HEADER_MCP_DESTINATION} header is empty`);
129
+ errors.push(`${interfaces_network_1.HEADER_MCP_DESTINATION} header is empty`);
126
130
  return {
127
- priority: interfaces_1.AuthMethodPriority.NONE,
128
- authType: interfaces_1.AUTH_TYPE_JWT, // MCP destination always uses JWT
131
+ priority: interfaces_auth_sap_1.AuthMethodPriority.NONE,
132
+ authType: interfaces_auth_1.AUTH_TYPE_JWT, // MCP destination always uses JWT
129
133
  sapUrl: '', // URL will be loaded from destination
130
134
  errors,
131
135
  warnings,
@@ -133,23 +137,23 @@ function validateMcpDestinationAuth(headers, sapUrl) {
133
137
  }
134
138
  // Warning if x-sap-url is provided (URL comes from destination, not header)
135
139
  if (sapUrl) {
136
- warnings.push(`${interfaces_1.HEADER_SAP_URL} is ignored when ${interfaces_1.HEADER_MCP_DESTINATION} is present (URL is loaded from destination service key or .env file)`);
140
+ warnings.push(`${interfaces_network_1.HEADER_SAP_URL} is ignored when ${interfaces_network_1.HEADER_MCP_DESTINATION} is present (URL is loaded from destination service key or .env file)`);
137
141
  }
138
142
  // Warning if x-sap-auth-type is provided (not needed for x-mcp-destination)
139
- const authType = getHeaderValue(headers, interfaces_1.HEADER_SAP_AUTH_TYPE);
143
+ const authType = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_AUTH_TYPE);
140
144
  if (authType) {
141
- warnings.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} is ignored when ${interfaces_1.HEADER_MCP_DESTINATION} is present (always uses JWT)`);
145
+ warnings.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} is ignored when ${interfaces_network_1.HEADER_MCP_DESTINATION} is present (always uses JWT)`);
142
146
  }
143
147
  // Extract optional SAP client
144
- const sapClient = getHeaderValue(headers, interfaces_1.HEADER_SAP_CLIENT);
148
+ const sapClient = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_CLIENT);
145
149
  // Warning if direct JWT token is also provided (destination takes priority)
146
- const jwtToken = getHeaderValue(headers, interfaces_1.HEADER_SAP_JWT_TOKEN);
150
+ const jwtToken = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_JWT_TOKEN);
147
151
  if (jwtToken) {
148
- warnings.push(`${interfaces_1.HEADER_SAP_JWT_TOKEN} is ignored when ${interfaces_1.HEADER_MCP_DESTINATION} is present (destination-based auth takes priority)`);
152
+ warnings.push(`${interfaces_network_1.HEADER_SAP_JWT_TOKEN} is ignored when ${interfaces_network_1.HEADER_MCP_DESTINATION} is present (destination-based auth takes priority)`);
149
153
  }
150
154
  return {
151
- priority: interfaces_1.AuthMethodPriority.MCP_DESTINATION,
152
- authType: interfaces_1.AUTH_TYPE_JWT, // Always JWT for x-mcp-destination
155
+ priority: interfaces_auth_sap_1.AuthMethodPriority.MCP_DESTINATION,
156
+ authType: interfaces_auth_1.AUTH_TYPE_JWT, // Always JWT for x-mcp-destination
153
157
  sapUrl: '', // URL will be loaded from destination (service key or .env)
154
158
  sapClient,
155
159
  destination,
@@ -165,10 +169,10 @@ function validateMcpDestinationAuth(headers, sapUrl) {
165
169
  * and only used for token refresh - they are a separate set of headers.
166
170
  */
167
171
  function validateDirectJwtAuth(headers, sapUrl, authType) {
168
- if (authType !== interfaces_1.AUTH_TYPE_JWT && authType !== interfaces_1.AUTH_TYPE_XSUAA) {
172
+ if (authType !== interfaces_auth_1.AUTH_TYPE_JWT && authType !== interfaces_auth_sap_1.AUTH_TYPE_XSUAA) {
169
173
  return null;
170
174
  }
171
- const jwtToken = getHeaderValue(headers, interfaces_1.HEADER_SAP_JWT_TOKEN);
175
+ const jwtToken = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_JWT_TOKEN);
172
176
  if (!jwtToken) {
173
177
  return null;
174
178
  }
@@ -176,25 +180,28 @@ function validateDirectJwtAuth(headers, sapUrl, authType) {
176
180
  const warnings = [];
177
181
  // Validate JWT token format (basic check - should start with eyJ)
178
182
  if (jwtToken.length < 10) {
179
- errors.push(`${interfaces_1.HEADER_SAP_JWT_TOKEN} appears to be invalid (too short)`);
183
+ errors.push(`${interfaces_network_1.HEADER_SAP_JWT_TOKEN} appears to be invalid (too short)`);
180
184
  }
181
185
  // Extract optional refresh token
182
- const refreshToken = getHeaderValue(headers, interfaces_1.HEADER_SAP_REFRESH_TOKEN);
186
+ const refreshToken = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_REFRESH_TOKEN);
183
187
  // Extract optional UAA config (for token refresh only - separate set of headers)
184
188
  // These are optional and don't affect authorization validation
185
- const uaaUrl = getHeaderValue(headers, interfaces_1.HEADER_SAP_UAA_URL) || getHeaderValue(headers, interfaces_1.HEADER_UAA_URL);
186
- const uaaClientId = getHeaderValue(headers, interfaces_1.HEADER_SAP_UAA_CLIENT_ID) || getHeaderValue(headers, interfaces_1.HEADER_UAA_CLIENT_ID);
187
- const uaaClientSecret = getHeaderValue(headers, interfaces_1.HEADER_SAP_UAA_CLIENT_SECRET) || getHeaderValue(headers, interfaces_1.HEADER_UAA_CLIENT_SECRET);
189
+ const uaaUrl = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_UAA_URL) ||
190
+ getHeaderValue(headers, interfaces_network_1.HEADER_UAA_URL);
191
+ const uaaClientId = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_UAA_CLIENT_ID) ||
192
+ getHeaderValue(headers, interfaces_network_1.HEADER_UAA_CLIENT_ID);
193
+ const uaaClientSecret = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_UAA_CLIENT_SECRET) ||
194
+ getHeaderValue(headers, interfaces_network_1.HEADER_UAA_CLIENT_SECRET);
188
195
  // Validate UAA config completeness if any UAA header is present
189
196
  if (uaaUrl || uaaClientId || uaaClientSecret) {
190
197
  if (!uaaUrl || !uaaClientId || !uaaClientSecret) {
191
- warnings.push(`UAA headers (${interfaces_1.HEADER_SAP_UAA_URL}, ${interfaces_1.HEADER_SAP_UAA_CLIENT_ID}, ${interfaces_1.HEADER_SAP_UAA_CLIENT_SECRET}) should be provided together for token refresh`);
198
+ warnings.push(`UAA headers (${interfaces_network_1.HEADER_SAP_UAA_URL}, ${interfaces_network_1.HEADER_SAP_UAA_CLIENT_ID}, ${interfaces_network_1.HEADER_SAP_UAA_CLIENT_SECRET}) should be provided together for token refresh`);
192
199
  }
193
200
  }
194
201
  // Extract optional SAP client
195
- const sapClient = getHeaderValue(headers, interfaces_1.HEADER_SAP_CLIENT);
202
+ const sapClient = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_CLIENT);
196
203
  return {
197
- priority: interfaces_1.AuthMethodPriority.DIRECT_JWT,
204
+ priority: interfaces_auth_sap_1.AuthMethodPriority.DIRECT_JWT,
198
205
  authType,
199
206
  sapUrl,
200
207
  sapClient,
@@ -211,29 +218,29 @@ function validateDirectJwtAuth(headers, sapUrl, authType) {
211
218
  * Validate basic authentication (lowest priority)
212
219
  */
213
220
  function validateBasicAuth(headers, sapUrl, authType) {
214
- if (authType !== interfaces_1.AUTH_TYPE_BASIC) {
221
+ if (authType !== interfaces_auth_1.AUTH_TYPE_BASIC) {
215
222
  return null;
216
223
  }
217
- const usernameRaw = headers[interfaces_1.HEADER_SAP_LOGIN.toLowerCase()] || headers[interfaces_1.HEADER_SAP_LOGIN];
218
- const passwordRaw = headers[interfaces_1.HEADER_SAP_PASSWORD.toLowerCase()] || headers[interfaces_1.HEADER_SAP_PASSWORD];
224
+ const usernameRaw = headers[interfaces_network_1.HEADER_SAP_LOGIN.toLowerCase()] || headers[interfaces_network_1.HEADER_SAP_LOGIN];
225
+ const passwordRaw = headers[interfaces_network_1.HEADER_SAP_PASSWORD.toLowerCase()] || headers[interfaces_network_1.HEADER_SAP_PASSWORD];
219
226
  if (!usernameRaw || !passwordRaw) {
220
227
  return null;
221
228
  }
222
- const username = getHeaderValue(headers, interfaces_1.HEADER_SAP_LOGIN);
223
- const password = getHeaderValue(headers, interfaces_1.HEADER_SAP_PASSWORD);
229
+ const username = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_LOGIN);
230
+ const password = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_PASSWORD);
224
231
  const errors = [];
225
232
  const warnings = [];
226
233
  // Validate username and password (check if empty after trim)
227
234
  if (!username || username.length === 0) {
228
- errors.push(`${interfaces_1.HEADER_SAP_LOGIN} header is empty`);
235
+ errors.push(`${interfaces_network_1.HEADER_SAP_LOGIN} header is empty`);
229
236
  }
230
237
  if (!password || password.length === 0) {
231
- errors.push(`${interfaces_1.HEADER_SAP_PASSWORD} header is empty`);
238
+ errors.push(`${interfaces_network_1.HEADER_SAP_PASSWORD} header is empty`);
232
239
  }
233
240
  // Return config with errors if validation failed
234
241
  if (errors.length > 0) {
235
242
  return {
236
- priority: interfaces_1.AuthMethodPriority.NONE,
243
+ priority: interfaces_auth_sap_1.AuthMethodPriority.NONE,
237
244
  authType,
238
245
  sapUrl,
239
246
  errors,
@@ -241,7 +248,7 @@ function validateBasicAuth(headers, sapUrl, authType) {
241
248
  };
242
249
  }
243
250
  return {
244
- priority: interfaces_1.AuthMethodPriority.BASIC,
251
+ priority: interfaces_auth_sap_1.AuthMethodPriority.BASIC,
245
252
  authType,
246
253
  sapUrl,
247
254
  username,
@@ -289,7 +296,7 @@ function validateAuthHeaders(headers) {
289
296
  }
290
297
  }
291
298
  // Check for MCP destination (doesn't require x-sap-url, URL comes from destination)
292
- const sapUrl = getHeaderValue(headers, interfaces_1.HEADER_SAP_URL);
299
+ const sapUrl = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_URL);
293
300
  const mcpDestinationConfig = validateMcpDestinationAuth(headers, sapUrl);
294
301
  if (mcpDestinationConfig) {
295
302
  // MCP destination found - URL comes from destination, not header
@@ -321,7 +328,7 @@ function validateAuthHeaders(headers) {
321
328
  }
322
329
  // Validate URL format
323
330
  if (!isValidUrl(sapUrl)) {
324
- errors.push(`${interfaces_1.HEADER_SAP_URL} is not a valid URL: ${sapUrl}`);
331
+ errors.push(`${interfaces_network_1.HEADER_SAP_URL} is not a valid URL: ${sapUrl}`);
325
332
  return {
326
333
  isValid: false,
327
334
  errors,
@@ -332,29 +339,33 @@ function validateAuthHeaders(headers) {
332
339
  const configs = [];
333
340
  // Check if basic auth headers are present (x-sap-login, x-sap-password)
334
341
  // These should come together with x-sap-auth-type: basic
335
- const hasSapLogin = !!getHeaderValue(headers, interfaces_1.HEADER_SAP_LOGIN);
336
- const hasSapPassword = !!getHeaderValue(headers, interfaces_1.HEADER_SAP_PASSWORD);
342
+ const hasSapLogin = !!getHeaderValue(headers, interfaces_network_1.HEADER_SAP_LOGIN);
343
+ const hasSapPassword = !!getHeaderValue(headers, interfaces_network_1.HEADER_SAP_PASSWORD);
337
344
  const hasBasicAuthHeaders = hasSapLogin || hasSapPassword;
338
345
  if (hasBasicAuthHeaders && (!hasSapLogin || !hasSapPassword)) {
339
- errors.push(`${interfaces_1.HEADER_SAP_LOGIN} and ${interfaces_1.HEADER_SAP_PASSWORD} must be provided together`);
346
+ errors.push(`${interfaces_network_1.HEADER_SAP_LOGIN} and ${interfaces_network_1.HEADER_SAP_PASSWORD} must be provided together`);
340
347
  }
341
348
  // 3. Other auth methods require x-sap-auth-type
342
- const sapAuthType = getHeaderValue(headers, interfaces_1.HEADER_SAP_AUTH_TYPE);
349
+ const sapAuthType = getHeaderValue(headers, interfaces_network_1.HEADER_SAP_AUTH_TYPE);
343
350
  if (sapAuthType) {
344
351
  // Validate auth type
345
- const validAuthTypes = [interfaces_1.AUTH_TYPE_JWT, interfaces_1.AUTH_TYPE_XSUAA, interfaces_1.AUTH_TYPE_BASIC];
352
+ const validAuthTypes = [
353
+ interfaces_auth_1.AUTH_TYPE_JWT,
354
+ interfaces_auth_sap_1.AUTH_TYPE_XSUAA,
355
+ interfaces_auth_1.AUTH_TYPE_BASIC,
356
+ ];
346
357
  const authType = sapAuthType.toLowerCase();
347
358
  if (!validAuthTypes.includes(authType)) {
348
- errors.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} must be one of: ${validAuthTypes.join(', ')}, got: ${sapAuthType}`);
359
+ errors.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} must be one of: ${validAuthTypes.join(', ')}, got: ${sapAuthType}`);
349
360
  }
350
361
  else {
351
362
  // Check if basic auth headers are present but auth-type is not basic
352
- if (hasBasicAuthHeaders && authType !== interfaces_1.AUTH_TYPE_BASIC) {
353
- warnings.push(`${interfaces_1.HEADER_SAP_LOGIN} and ${interfaces_1.HEADER_SAP_PASSWORD} are present but ${interfaces_1.HEADER_SAP_AUTH_TYPE} is not "${interfaces_1.AUTH_TYPE_BASIC}"`);
363
+ if (hasBasicAuthHeaders && authType !== interfaces_auth_1.AUTH_TYPE_BASIC) {
364
+ warnings.push(`${interfaces_network_1.HEADER_SAP_LOGIN} and ${interfaces_network_1.HEADER_SAP_PASSWORD} are present but ${interfaces_network_1.HEADER_SAP_AUTH_TYPE} is not "${interfaces_auth_1.AUTH_TYPE_BASIC}"`);
354
365
  }
355
366
  // Check if auth-type is basic but headers are missing
356
- if (authType === interfaces_1.AUTH_TYPE_BASIC && !hasBasicAuthHeaders) {
357
- errors.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} is "${interfaces_1.AUTH_TYPE_BASIC}" but ${interfaces_1.HEADER_SAP_LOGIN} and ${interfaces_1.HEADER_SAP_PASSWORD} are missing`);
367
+ if (authType === interfaces_auth_1.AUTH_TYPE_BASIC && !hasBasicAuthHeaders) {
368
+ errors.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} is "${interfaces_auth_1.AUTH_TYPE_BASIC}" but ${interfaces_network_1.HEADER_SAP_LOGIN} and ${interfaces_network_1.HEADER_SAP_PASSWORD} are missing`);
358
369
  }
359
370
  // Only validate direct JWT and basic auth if MCP destination is not present
360
371
  // (MCP destination already handled above)
@@ -376,22 +387,22 @@ function validateAuthHeaders(headers) {
376
387
  // No auth-type provided
377
388
  // If basic auth headers are present, auth-type must be basic
378
389
  if (hasBasicAuthHeaders) {
379
- errors.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} must be "${interfaces_1.AUTH_TYPE_BASIC}" when ${interfaces_1.HEADER_SAP_LOGIN} and ${interfaces_1.HEADER_SAP_PASSWORD} are present`);
390
+ errors.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} must be "${interfaces_auth_1.AUTH_TYPE_BASIC}" when ${interfaces_network_1.HEADER_SAP_LOGIN} and ${interfaces_network_1.HEADER_SAP_PASSWORD} are present`);
380
391
  }
381
392
  else if (!mcpDestinationConfig && !sapDestinationConfig) {
382
393
  // No auth-type and no destination - error
383
- errors.push(`${interfaces_1.HEADER_SAP_AUTH_TYPE} header is required when ${interfaces_1.HEADER_SAP_DESTINATION_SERVICE} and ${interfaces_1.HEADER_MCP_DESTINATION} are not present`);
394
+ errors.push(`${interfaces_network_1.HEADER_SAP_AUTH_TYPE} header is required when ${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE} and ${interfaces_network_1.HEADER_MCP_DESTINATION} are not present`);
384
395
  }
385
396
  }
386
397
  // No valid authentication method found
387
398
  if (configs.length === 0) {
388
399
  if (sapAuthType) {
389
400
  const authType = sapAuthType.toLowerCase();
390
- if (authType === interfaces_1.AUTH_TYPE_JWT || authType === interfaces_1.AUTH_TYPE_XSUAA) {
391
- errors.push(`JWT authentication requires either ${interfaces_1.HEADER_SAP_DESTINATION_SERVICE}, ${interfaces_1.HEADER_MCP_DESTINATION}, or ${interfaces_1.HEADER_SAP_JWT_TOKEN} header`);
401
+ if (authType === interfaces_auth_1.AUTH_TYPE_JWT || authType === interfaces_auth_sap_1.AUTH_TYPE_XSUAA) {
402
+ errors.push(`JWT authentication requires either ${interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE}, ${interfaces_network_1.HEADER_MCP_DESTINATION}, or ${interfaces_network_1.HEADER_SAP_JWT_TOKEN} header`);
392
403
  }
393
- else if (authType === interfaces_1.AUTH_TYPE_BASIC) {
394
- errors.push(`Basic authentication requires ${interfaces_1.HEADER_SAP_LOGIN} and ${interfaces_1.HEADER_SAP_PASSWORD} headers`);
404
+ else if (authType === interfaces_auth_1.AUTH_TYPE_BASIC) {
405
+ errors.push(`Basic authentication requires ${interfaces_network_1.HEADER_SAP_LOGIN} and ${interfaces_network_1.HEADER_SAP_PASSWORD} headers`);
395
406
  }
396
407
  }
397
408
  else {
@@ -410,9 +421,9 @@ function validateAuthHeaders(headers) {
410
421
  // Select highest priority configuration
411
422
  const selectedConfig = configs.reduce((prev, current) => current.priority > prev.priority ? current : prev);
412
423
  // Check for conflicts (multiple auth methods with same priority shouldn't happen, but check anyway)
413
- const samePriorityConfigs = configs.filter(c => c.priority === selectedConfig.priority);
424
+ const samePriorityConfigs = configs.filter((c) => c.priority === selectedConfig.priority);
414
425
  if (samePriorityConfigs.length > 1) {
415
- warnings.push(`Multiple authentication methods with same priority detected, using: ${interfaces_1.AuthMethodPriority[selectedConfig.priority]}`);
426
+ warnings.push(`Multiple authentication methods with same priority detected, using: ${interfaces_auth_sap_1.AuthMethodPriority[selectedConfig.priority]}`);
416
427
  }
417
428
  // Merge errors and warnings
418
429
  const allErrors = [...errors, ...selectedConfig.errors];
@@ -448,29 +459,31 @@ function validateProxyHeaders(headers) {
448
459
  warnings: [],
449
460
  };
450
461
  }
451
- const btpDestination = getHeaderValue(headers, interfaces_1.HEADER_BTP_DESTINATION);
452
- const mcpDestination = getHeaderValue(headers, interfaces_1.HEADER_MCP_DESTINATION);
453
- const mcpUrl = getHeaderValue(headers, interfaces_1.HEADER_MCP_URL);
462
+ const btpDestination = getHeaderValue(headers, interfaces_network_1.HEADER_BTP_DESTINATION);
463
+ const mcpDestination = getHeaderValue(headers, interfaces_network_1.HEADER_MCP_DESTINATION);
464
+ const mcpUrl = getHeaderValue(headers, interfaces_network_1.HEADER_MCP_URL);
454
465
  const hasBtpDestination = !!btpDestination;
455
466
  const hasMcpDestination = !!mcpDestination;
456
467
  const hasMcpUrl = !!mcpUrl;
457
468
  // Validate destination names if present
458
- if (hasBtpDestination && (!btpDestination || btpDestination.trim().length === 0)) {
459
- errors.push(`${interfaces_1.HEADER_BTP_DESTINATION} header is empty`);
469
+ if (hasBtpDestination &&
470
+ (!btpDestination || btpDestination.trim().length === 0)) {
471
+ errors.push(`${interfaces_network_1.HEADER_BTP_DESTINATION} header is empty`);
460
472
  }
461
- if (hasMcpDestination && (!mcpDestination || mcpDestination.trim().length === 0)) {
462
- errors.push(`${interfaces_1.HEADER_MCP_DESTINATION} header is empty`);
473
+ if (hasMcpDestination &&
474
+ (!mcpDestination || mcpDestination.trim().length === 0)) {
475
+ errors.push(`${interfaces_network_1.HEADER_MCP_DESTINATION} header is empty`);
463
476
  }
464
477
  // Validate mcpUrl format if present
465
- if (hasMcpUrl) {
478
+ if (hasMcpUrl && mcpUrl) {
466
479
  if (!isValidUrl(mcpUrl)) {
467
- errors.push(`${interfaces_1.HEADER_MCP_URL} is not a valid URL: ${mcpUrl}`);
480
+ errors.push(`${interfaces_network_1.HEADER_MCP_URL} is not a valid URL: ${mcpUrl}`);
468
481
  }
469
482
  }
470
483
  // At least one proxy header should be present for proxy routing
471
484
  const hasAnyProxyHeader = hasBtpDestination || hasMcpDestination || hasMcpUrl;
472
485
  if (!hasAnyProxyHeader) {
473
- warnings.push(`No proxy headers found (${interfaces_1.HEADER_BTP_DESTINATION}, ${interfaces_1.HEADER_MCP_DESTINATION}, or ${interfaces_1.HEADER_MCP_URL})`);
486
+ warnings.push(`No proxy headers found (${interfaces_network_1.HEADER_BTP_DESTINATION}, ${interfaces_network_1.HEADER_MCP_DESTINATION}, or ${interfaces_network_1.HEADER_MCP_URL})`);
474
487
  }
475
488
  return {
476
489
  isValid: errors.length === 0,
@@ -497,7 +510,9 @@ function isProxyRequest(headers) {
497
510
  return false;
498
511
  }
499
512
  const validation = validateProxyHeaders(headers);
500
- return validation.hasBtpDestination || validation.hasMcpDestination || validation.hasMcpUrl;
513
+ return (validation.hasBtpDestination ||
514
+ validation.hasMcpDestination ||
515
+ validation.hasMcpUrl);
501
516
  }
502
517
  /**
503
518
  * Check if headers indicate an MCP server request (not proxy)
@@ -514,13 +529,13 @@ function isMcpServerRequest(headers) {
514
529
  return false;
515
530
  }
516
531
  // Check for MCP authentication headers
517
- const hasSapDestination = !!getHeaderValue(headers, interfaces_1.HEADER_SAP_DESTINATION_SERVICE);
518
- const hasMcpDestination = !!getHeaderValue(headers, interfaces_1.HEADER_MCP_DESTINATION);
519
- const hasSapUrl = !!getHeaderValue(headers, interfaces_1.HEADER_SAP_URL);
520
- const hasSapJwtToken = !!getHeaderValue(headers, interfaces_1.HEADER_SAP_JWT_TOKEN);
532
+ const hasSapDestination = !!getHeaderValue(headers, interfaces_network_1.HEADER_SAP_DESTINATION_SERVICE);
533
+ const hasMcpDestination = !!getHeaderValue(headers, interfaces_network_1.HEADER_MCP_DESTINATION);
534
+ const hasSapUrl = !!getHeaderValue(headers, interfaces_network_1.HEADER_SAP_URL);
535
+ const hasSapJwtToken = !!getHeaderValue(headers, interfaces_network_1.HEADER_SAP_JWT_TOKEN);
521
536
  // Check for proxy-specific headers
522
- const hasBtpDestination = !!getHeaderValue(headers, interfaces_1.HEADER_BTP_DESTINATION);
523
- const hasMcpUrl = !!getHeaderValue(headers, interfaces_1.HEADER_MCP_URL);
537
+ const hasBtpDestination = !!getHeaderValue(headers, interfaces_network_1.HEADER_BTP_DESTINATION);
538
+ const hasMcpUrl = !!getHeaderValue(headers, interfaces_network_1.HEADER_MCP_URL);
524
539
  // MCP server request has MCP auth headers but no proxy headers
525
540
  const hasMcpAuthHeaders = hasSapDestination || hasMcpDestination || hasSapUrl || hasSapJwtToken;
526
541
  const hasProxyHeaders = hasBtpDestination || hasMcpUrl;
package/dist/index.d.ts CHANGED
@@ -3,5 +3,5 @@
3
3
  *
4
4
  * Validates and prioritizes authentication headers for MCP ABAP ADT servers
5
5
  */
6
- export { validateAuthHeaders, validateProxyHeaders, isProxyRequest, isMcpServerRequest, type ProxyHeaderValidationResult, } from './headerValidator';
6
+ export { isMcpServerRequest, isProxyRequest, type ProxyHeaderValidationResult, validateAuthHeaders, validateProxyHeaders, } from './headerValidator';
7
7
  export * from './types';
package/dist/index.js CHANGED
@@ -19,10 +19,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.isMcpServerRequest = exports.isProxyRequest = exports.validateProxyHeaders = exports.validateAuthHeaders = void 0;
22
+ exports.validateProxyHeaders = exports.validateAuthHeaders = exports.isProxyRequest = exports.isMcpServerRequest = void 0;
23
23
  var headerValidator_1 = require("./headerValidator");
24
+ Object.defineProperty(exports, "isMcpServerRequest", { enumerable: true, get: function () { return headerValidator_1.isMcpServerRequest; } });
25
+ Object.defineProperty(exports, "isProxyRequest", { enumerable: true, get: function () { return headerValidator_1.isProxyRequest; } });
24
26
  Object.defineProperty(exports, "validateAuthHeaders", { enumerable: true, get: function () { return headerValidator_1.validateAuthHeaders; } });
25
27
  Object.defineProperty(exports, "validateProxyHeaders", { enumerable: true, get: function () { return headerValidator_1.validateProxyHeaders; } });
26
- Object.defineProperty(exports, "isProxyRequest", { enumerable: true, get: function () { return headerValidator_1.isProxyRequest; } });
27
- Object.defineProperty(exports, "isMcpServerRequest", { enumerable: true, get: function () { return headerValidator_1.isMcpServerRequest; } });
28
28
  __exportStar(require("./types"), exports);
package/dist/types.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Types for header validator
3
3
  */
4
- import type { AuthType } from '@mcp-abap-adt/interfaces';
5
- import { AuthMethodPriority, type IValidatedAuthConfig, type IHeaderValidationResult } from '@mcp-abap-adt/interfaces';
4
+ import type { AuthType, IHeaderValidationResult, IValidatedAuthConfig } from '@mcp-abap-adt/interfaces-auth-sap';
5
+ import { AuthMethodPriority } from '@mcp-abap-adt/interfaces-auth-sap';
6
6
  export type { AuthType };
7
7
  export { AuthMethodPriority };
8
8
  export type ValidatedAuthConfig = IValidatedAuthConfig;
package/dist/types.js CHANGED
@@ -4,5 +4,5 @@
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AuthMethodPriority = void 0;
7
- const interfaces_1 = require("@mcp-abap-adt/interfaces");
8
- Object.defineProperty(exports, "AuthMethodPriority", { enumerable: true, get: function () { return interfaces_1.AuthMethodPriority; } });
7
+ const interfaces_auth_sap_1 = require("@mcp-abap-adt/interfaces-auth-sap");
8
+ Object.defineProperty(exports, "AuthMethodPriority", { enumerable: true, get: function () { return interfaces_auth_sap_1.AuthMethodPriority; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/header-validator",
3
- "version": "0.1.8",
3
+ "version": "0.3.1",
4
4
  "description": "Header validator for MCP ABAP ADT - validates and prioritizes authentication headers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,8 @@
8
8
  "dist",
9
9
  "README.md",
10
10
  "CHANGELOG.md",
11
- "LICENSE"
11
+ "LICENSE",
12
+ "COPYING"
12
13
  ],
13
14
  "keywords": [
14
15
  "abap",
@@ -21,7 +22,7 @@
21
22
  "abap-adt"
22
23
  ],
23
24
  "author": "Oleksii Kyslytsia <oleksij.kyslytsja@gmail.com>",
24
- "license": "MIT",
25
+ "license": "LGPL-3.0-only",
25
26
  "homepage": "https://github.com/fr0ster/mcp-abap-adt-header-validator#readme",
26
27
  "bugs": {
27
28
  "url": "https://github.com/fr0ster/mcp-abap-adt-header-validator/issues"
@@ -34,8 +35,12 @@
34
35
  "access": "public"
35
36
  },
36
37
  "scripts": {
38
+ "chrono": "./tools/version-stats.sh",
37
39
  "clean": "rm -rf dist tsconfig.tsbuildinfo",
38
- "build": "npm run clean --silent && npx tsc -p tsconfig.json",
40
+ "lint": "npx biome check --write src",
41
+ "lint:check": "npx biome check src",
42
+ "format": "npx biome format --write src",
43
+ "build": "npm run --silent clean && npx biome check src --diagnostic-level=error && npx tsc -p tsconfig.json",
39
44
  "build:fast": "npx tsc -p tsconfig.json",
40
45
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
41
46
  "test:check": "npx tsc --noEmit",
@@ -45,9 +50,12 @@
45
50
  "node": ">=18.0.0"
46
51
  },
47
52
  "dependencies": {
48
- "@mcp-abap-adt/interfaces": "^0.1.16"
53
+ "@mcp-abap-adt/interfaces-auth": "^2.0.1",
54
+ "@mcp-abap-adt/interfaces-auth-sap": "^1.0.1",
55
+ "@mcp-abap-adt/interfaces-network": "^2.0.0"
49
56
  },
50
57
  "devDependencies": {
58
+ "@biomejs/biome": "^2.3.10",
51
59
  "@types/jest": "^30.0.0",
52
60
  "@types/node": "^24.2.1",
53
61
  "jest": "^30.2.0",