@arcis/node 1.3.0 → 1.4.0

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.
Files changed (118) hide show
  1. package/dist/core/{index.d.mts → constants.d.ts} +21 -70
  2. package/dist/core/constants.d.ts.map +1 -0
  3. package/dist/core/errors.d.ts +53 -0
  4. package/dist/core/errors.d.ts.map +1 -0
  5. package/dist/core/index.d.ts +6 -168
  6. package/dist/core/index.d.ts.map +1 -0
  7. package/dist/{types-BOkx5YJc.d.mts → core/types.d.ts} +27 -30
  8. package/dist/core/types.d.ts.map +1 -0
  9. package/dist/index.d.ts +71 -166
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +57 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +56 -3
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/logging/index.d.ts +4 -36
  16. package/dist/logging/index.d.ts.map +1 -0
  17. package/dist/logging/{index.d.mts → redactor.d.ts} +5 -9
  18. package/dist/logging/redactor.d.ts.map +1 -0
  19. package/dist/middleware/bot-detection.d.ts +86 -0
  20. package/dist/middleware/bot-detection.d.ts.map +1 -0
  21. package/dist/middleware/cookies.d.ts +48 -0
  22. package/dist/middleware/cookies.d.ts.map +1 -0
  23. package/dist/middleware/cors.d.ts +65 -0
  24. package/dist/middleware/cors.d.ts.map +1 -0
  25. package/dist/middleware/csrf.d.ts +109 -0
  26. package/dist/middleware/csrf.d.ts.map +1 -0
  27. package/dist/middleware/error-handler.d.ts +43 -0
  28. package/dist/middleware/error-handler.d.ts.map +1 -0
  29. package/dist/middleware/headers.d.ts +29 -0
  30. package/dist/middleware/headers.d.ts.map +1 -0
  31. package/dist/middleware/hpp.d.ts +56 -0
  32. package/dist/middleware/hpp.d.ts.map +1 -0
  33. package/dist/middleware/index.d.ts +16 -3
  34. package/dist/middleware/index.d.ts.map +1 -0
  35. package/dist/middleware/index.js +6 -1
  36. package/dist/middleware/index.js.map +1 -1
  37. package/dist/middleware/index.mjs +6 -1
  38. package/dist/middleware/index.mjs.map +1 -1
  39. package/dist/middleware/main.d.ts +40 -0
  40. package/dist/middleware/main.d.ts.map +1 -0
  41. package/dist/middleware/rate-limit-sliding.d.ts +46 -0
  42. package/dist/middleware/rate-limit-sliding.d.ts.map +1 -0
  43. package/dist/middleware/rate-limit-token.d.ts +51 -0
  44. package/dist/middleware/rate-limit-token.d.ts.map +1 -0
  45. package/dist/middleware/rate-limit.d.ts +34 -0
  46. package/dist/middleware/rate-limit.d.ts.map +1 -0
  47. package/dist/sanitizers/command.d.ts +28 -0
  48. package/dist/sanitizers/command.d.ts.map +1 -0
  49. package/dist/sanitizers/encode.d.ts +46 -0
  50. package/dist/sanitizers/encode.d.ts.map +1 -0
  51. package/dist/sanitizers/headers.d.ts +46 -0
  52. package/dist/sanitizers/headers.d.ts.map +1 -0
  53. package/dist/sanitizers/index.d.ts +17 -22
  54. package/dist/sanitizers/index.d.ts.map +1 -0
  55. package/dist/sanitizers/jsonp.d.ts +34 -0
  56. package/dist/sanitizers/jsonp.d.ts.map +1 -0
  57. package/dist/sanitizers/nosql.d.ts +31 -0
  58. package/dist/sanitizers/nosql.d.ts.map +1 -0
  59. package/dist/sanitizers/path.d.ts +28 -0
  60. package/dist/sanitizers/path.d.ts.map +1 -0
  61. package/dist/sanitizers/pii.d.ts +80 -0
  62. package/dist/sanitizers/pii.d.ts.map +1 -0
  63. package/dist/sanitizers/prototype.d.ts +34 -0
  64. package/dist/sanitizers/prototype.d.ts.map +1 -0
  65. package/dist/sanitizers/sanitize.d.ts +51 -0
  66. package/dist/sanitizers/sanitize.d.ts.map +1 -0
  67. package/dist/sanitizers/sql.d.ts +28 -0
  68. package/dist/sanitizers/sql.d.ts.map +1 -0
  69. package/dist/sanitizers/ssti.d.ts +20 -0
  70. package/dist/sanitizers/ssti.d.ts.map +1 -0
  71. package/dist/sanitizers/utils.d.ts +19 -0
  72. package/dist/sanitizers/utils.d.ts.map +1 -0
  73. package/dist/sanitizers/xss.d.ts +35 -0
  74. package/dist/sanitizers/xss.d.ts.map +1 -0
  75. package/dist/sanitizers/xxe.d.ts +20 -0
  76. package/dist/sanitizers/xxe.d.ts.map +1 -0
  77. package/dist/stores/index.d.ts +6 -104
  78. package/dist/stores/index.d.ts.map +1 -0
  79. package/dist/stores/memory.d.ts +35 -0
  80. package/dist/stores/memory.d.ts.map +1 -0
  81. package/dist/stores/{index.d.mts → redis.d.ts} +6 -45
  82. package/dist/stores/redis.d.ts.map +1 -0
  83. package/dist/utils/duration.d.ts +34 -0
  84. package/dist/utils/duration.d.ts.map +1 -0
  85. package/dist/utils/fingerprint.d.ts +64 -0
  86. package/dist/utils/fingerprint.d.ts.map +1 -0
  87. package/dist/utils/index.d.ts +10 -0
  88. package/dist/utils/index.d.ts.map +1 -0
  89. package/dist/utils/index.js +188 -0
  90. package/dist/utils/index.js.map +1 -0
  91. package/dist/utils/index.mjs +182 -0
  92. package/dist/utils/index.mjs.map +1 -0
  93. package/dist/utils/ip.d.ts +70 -0
  94. package/dist/utils/ip.d.ts.map +1 -0
  95. package/dist/validation/email.d.ts +82 -0
  96. package/dist/validation/email.d.ts.map +1 -0
  97. package/dist/validation/file.d.ts +90 -0
  98. package/dist/validation/file.d.ts.map +1 -0
  99. package/dist/validation/index.d.ts +10 -3
  100. package/dist/validation/index.d.ts.map +1 -0
  101. package/dist/validation/redirect.d.ts +64 -0
  102. package/dist/validation/redirect.d.ts.map +1 -0
  103. package/dist/validation/schema.d.ts +36 -0
  104. package/dist/validation/schema.d.ts.map +1 -0
  105. package/dist/validation/url.d.ts +65 -0
  106. package/dist/validation/url.d.ts.map +1 -0
  107. package/package.json +8 -6
  108. package/dist/encode-CrQCGlBq.d.mts +0 -484
  109. package/dist/encode-jl9sOwmA.d.ts +0 -484
  110. package/dist/index-BAhgn9V2.d.ts +0 -532
  111. package/dist/index-BGNKspqH.d.ts +0 -340
  112. package/dist/index-Cd02z-0j.d.mts +0 -340
  113. package/dist/index-DgJtWMSj.d.mts +0 -532
  114. package/dist/index.d.mts +0 -175
  115. package/dist/middleware/index.d.mts +0 -3
  116. package/dist/sanitizers/index.d.mts +0 -24
  117. package/dist/types-BOkx5YJc.d.ts +0 -279
  118. package/dist/validation/index.d.mts +0 -3
@@ -1,532 +0,0 @@
1
- import { b as ArcisOptions, o as ArcisMiddlewareStack, A as ArcisFunction, e as RateLimitOptions, h as RateLimiterMiddleware, H as HeaderOptions, E as ErrorHandlerOptions } from './types-BOkx5YJc.mjs';
2
- import { RequestHandler, Request, Response, NextFunction } from 'express';
3
-
4
- /**
5
- * @module @arcis/node/middleware/main
6
- * Main arcis() middleware factory
7
- */
8
-
9
- /**
10
- * Create Arcis middleware with all protections enabled.
11
- *
12
- * @param options - Configuration options
13
- * @returns Array of Express middleware
14
- *
15
- * @example
16
- * // Full protection (recommended)
17
- * app.use(arcis());
18
- *
19
- * @example
20
- * // Custom configuration
21
- * app.use(arcis({
22
- * rateLimit: { max: 50 },
23
- * headers: { frameOptions: 'SAMEORIGIN' }
24
- * }));
25
- *
26
- * @example
27
- * // Disable specific features
28
- * app.use(arcis({
29
- * rateLimit: false,
30
- * sanitize: { sql: false }
31
- * }));
32
- *
33
- * @example
34
- * // Cleanup on shutdown
35
- * const middleware = arcis();
36
- * app.use(middleware);
37
- * process.on('SIGTERM', () => middleware.close());
38
- */
39
- declare function arcis(options?: ArcisOptions): ArcisMiddlewareStack;
40
- declare const arcisWithMethods: ArcisFunction;
41
-
42
- /**
43
- * @module @arcis/node/middleware/rate-limit
44
- * Rate limiting middleware
45
- */
46
-
47
- /**
48
- * Create Express middleware for rate limiting.
49
- *
50
- * @param options - Rate limit configuration
51
- * @returns Express middleware with cleanup method
52
- *
53
- * @example
54
- * app.use(createRateLimiter({ max: 100, windowMs: 60000 }));
55
- *
56
- * @example
57
- * // Skip rate limiting for certain routes
58
- * app.use(createRateLimiter({
59
- * max: 50,
60
- * skip: (req) => req.path === '/health'
61
- * }));
62
- *
63
- * @example
64
- * // Cleanup on shutdown
65
- * const limiter = createRateLimiter();
66
- * app.use(limiter);
67
- * process.on('SIGTERM', () => limiter.close());
68
- */
69
- declare function createRateLimiter(options?: RateLimitOptions): RateLimiterMiddleware;
70
- /**
71
- * Alias for createRateLimiter
72
- * @see createRateLimiter
73
- */
74
- declare const rateLimit: typeof createRateLimiter;
75
-
76
- /**
77
- * @module @arcis/node/middleware/rate-limit-sliding
78
- * Sliding window rate limiting middleware.
79
- *
80
- * More accurate than fixed window — uses a weighted sum of the previous
81
- * and current window to approximate a true sliding window.
82
- *
83
- * Algorithm:
84
- * weight = (windowMs - elapsed) / windowMs
85
- * count = (prevWindow * weight) + currentWindow
86
- * allow = count < limit
87
- *
88
- * @example
89
- * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));
90
- */
91
-
92
- interface SlidingWindowOptions {
93
- /** Maximum requests per window. Default: 100 */
94
- max?: number;
95
- /** Window size in ms or duration string. Default: '1m' */
96
- window?: string | number;
97
- /** Error message when limit exceeded */
98
- message?: string;
99
- /** HTTP status code for rate limited responses. Default: 429 */
100
- statusCode?: number;
101
- /** Function to generate rate limit key from request */
102
- keyGenerator?: (req: Request) => string;
103
- /** Function to skip rate limiting for certain requests */
104
- skip?: (req: Request) => boolean;
105
- }
106
- interface SlidingWindowMiddleware extends RequestHandler {
107
- close: () => void;
108
- }
109
- /**
110
- * Create sliding window rate limiter middleware.
111
- *
112
- * @example
113
- * // 100 requests per 15 minutes
114
- * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));
115
- *
116
- * @example
117
- * // Strict API limit
118
- * app.use('/api', createSlidingWindowLimiter({ max: 30, window: '1m' }));
119
- */
120
- declare function createSlidingWindowLimiter(options?: SlidingWindowOptions): SlidingWindowMiddleware;
121
-
122
- /**
123
- * @module @arcis/node/middleware/rate-limit-token
124
- * Token bucket rate limiting middleware.
125
- *
126
- * Allows burst traffic while enforcing an average rate.
127
- * Tokens refill at a steady rate. Each request costs 1 token.
128
- *
129
- * Algorithm:
130
- * tokens = min(capacity, tokens + elapsed * refillRate)
131
- * if tokens >= cost: allow, subtract cost
132
- * else: deny
133
- *
134
- * @example
135
- * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));
136
- */
137
-
138
- interface TokenBucketOptions {
139
- /** Maximum tokens (burst size). Default: 100 */
140
- capacity?: number;
141
- /** Tokens added per second. Default: 10 */
142
- refillRate?: number;
143
- /** Tokens consumed per request. Default: 1 */
144
- cost?: number;
145
- /** Error message when limit exceeded */
146
- message?: string;
147
- /** HTTP status code for rate limited responses. Default: 429 */
148
- statusCode?: number;
149
- /** Function to generate rate limit key from request */
150
- keyGenerator?: (req: Request) => string;
151
- /** Function to skip rate limiting for certain requests */
152
- skip?: (req: Request) => boolean;
153
- }
154
- interface TokenBucketMiddleware extends RequestHandler {
155
- close: () => void;
156
- }
157
- /**
158
- * Create token bucket rate limiter middleware.
159
- *
160
- * @example
161
- * // Allow bursts of 50, sustained rate of 10/sec
162
- * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));
163
- *
164
- * @example
165
- * // Strict API: 5 requests burst, 1/sec sustained
166
- * app.use('/api/expensive', createTokenBucketLimiter({
167
- * capacity: 5,
168
- * refillRate: 1,
169
- * }));
170
- */
171
- declare function createTokenBucketLimiter(options?: TokenBucketOptions): TokenBucketMiddleware;
172
-
173
- /**
174
- * @module @arcis/node/middleware/headers
175
- * Security headers middleware
176
- */
177
-
178
- /**
179
- * Create Express middleware for security headers.
180
- * Sets CSP, HSTS, X-Frame-Options, and other security headers.
181
- *
182
- * @param options - Header configuration
183
- * @returns Express middleware
184
- *
185
- * @example
186
- * app.use(createHeaders());
187
- *
188
- * @example
189
- * app.use(createHeaders({
190
- * frameOptions: 'SAMEORIGIN',
191
- * contentSecurityPolicy: "default-src 'self'"
192
- * }));
193
- */
194
- declare function createHeaders(options?: HeaderOptions): RequestHandler;
195
- /**
196
- * Alias for createHeaders
197
- * @see createHeaders
198
- */
199
- declare const securityHeaders: typeof createHeaders;
200
-
201
- /**
202
- * @module @arcis/node/middleware/error-handler
203
- * Production-safe error handler middleware
204
- */
205
-
206
- /**
207
- * Create Express error handler that hides sensitive details in production.
208
- *
209
- * Prevents information leakage by:
210
- * - Hiding stack traces in production
211
- * - Hiding error messages unless explicitly exposed
212
- * - Scrubbing database errors, connection strings, and internal IPs
213
- *
214
- * @param options - Error handler configuration (or boolean for isDev)
215
- * @returns Express error handling middleware
216
- *
217
- * @example
218
- * // Production mode (default) - hides error details
219
- * app.use(errorHandler());
220
- *
221
- * @example
222
- * // Development mode - shows error details and stack traces
223
- * app.use(errorHandler({ isDev: true }));
224
- *
225
- * @example
226
- * // With custom logger
227
- * app.use(errorHandler({
228
- * isDev: false,
229
- * logger: arcis.logger()
230
- * }));
231
- */
232
- declare function errorHandler(options?: ErrorHandlerOptions | boolean): (err: Error, req: Request, res: Response, next: NextFunction) => void;
233
- /**
234
- * Alias for errorHandler
235
- * @see errorHandler
236
- */
237
- declare const createErrorHandler: typeof errorHandler;
238
-
239
- /**
240
- * @module @arcis/node/middleware/cors
241
- * Safe CORS middleware with secure defaults
242
- */
243
-
244
- /** CORS configuration options */
245
- interface CorsOptions {
246
- /**
247
- * Allowed origins. Can be:
248
- * - A string: exact match (e.g., 'https://example.com')
249
- * - An array: whitelist of allowed origins
250
- * - A RegExp: pattern match (use with care)
251
- * - A function: custom validation `(origin) => boolean`
252
- * - `true`: reflect the request origin (DANGEROUS — only for dev)
253
- *
254
- * Default: none (no origin allowed). You must explicitly set this.
255
- */
256
- origin: string | string[] | RegExp | ((origin: string) => boolean) | true;
257
- /** Allowed HTTP methods. Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'] */
258
- methods?: string[];
259
- /** Allowed headers. Default: ['Content-Type', 'Authorization'] */
260
- allowedHeaders?: string[];
261
- /** Headers exposed to the browser. Default: [] */
262
- exposedHeaders?: string[];
263
- /** Allow credentials (cookies, authorization headers). Default: false */
264
- credentials?: boolean;
265
- /** Preflight cache duration in seconds. Default: 600 (10 minutes) */
266
- maxAge?: number;
267
- /** Respond to preflight with 204 (no content). Default: true */
268
- preflightContinue?: boolean;
269
- }
270
- /**
271
- * Create safe CORS middleware.
272
- *
273
- * Unlike permissive CORS libraries, this enforces secure defaults:
274
- * - No wildcard `*` when credentials are enabled
275
- * - `null` origin is always blocked
276
- * - `Vary: Origin` is always set for proper caching
277
- * - You must explicitly configure allowed origins
278
- *
279
- * @param options - CORS configuration
280
- * @returns Express middleware
281
- *
282
- * @example
283
- * // Allow a single origin
284
- * app.use(safeCors({ origin: 'https://myapp.com' }));
285
- *
286
- * @example
287
- * // Allow multiple origins with credentials
288
- * app.use(safeCors({
289
- * origin: ['https://myapp.com', 'https://admin.myapp.com'],
290
- * credentials: true,
291
- * }));
292
- *
293
- * @example
294
- * // Development: allow all (NOT for production)
295
- * app.use(safeCors({ origin: true }));
296
- */
297
- declare function safeCors(options: CorsOptions): RequestHandler;
298
- /**
299
- * Alias for safeCors
300
- * @see safeCors
301
- */
302
- declare const createCors: typeof safeCors;
303
-
304
- /**
305
- * @module @arcis/node/middleware/cookies
306
- * Secure cookie defaults middleware
307
- */
308
-
309
- /** Cookie security configuration */
310
- interface SecureCookieOptions {
311
- /** Force HttpOnly on all cookies. Default: true */
312
- httpOnly?: boolean;
313
- /** Force Secure flag (HTTPS only). Default: true in production, false in dev */
314
- secure?: boolean;
315
- /** SameSite attribute. Default: 'Lax' */
316
- sameSite?: 'Strict' | 'Lax' | 'None' | false;
317
- /** Override Path attribute. Default: undefined (keep original) */
318
- path?: string;
319
- }
320
- /**
321
- * Enforce secure defaults on a Set-Cookie header value.
322
- */
323
- declare function enforceSecureCookie(cookieStr: string, options: Required<Omit<SecureCookieOptions, 'path'>> & {
324
- path?: string;
325
- }): string;
326
- /**
327
- * Create middleware that enforces secure cookie defaults.
328
- *
329
- * Intercepts Set-Cookie headers and adds missing security attributes:
330
- * - HttpOnly: prevents JavaScript access (XSS cookie theft)
331
- * - Secure: cookies only sent over HTTPS
332
- * - SameSite: CSRF protection
333
- *
334
- * @param options - Cookie security configuration
335
- * @returns Express middleware
336
- *
337
- * @example
338
- * // Enforce defaults on all cookies
339
- * app.use(secureCookieDefaults());
340
- *
341
- * @example
342
- * // Strict SameSite for sensitive apps
343
- * app.use(secureCookieDefaults({ sameSite: 'Strict' }));
344
- */
345
- declare function secureCookieDefaults(options?: SecureCookieOptions): RequestHandler;
346
- /**
347
- * Alias for secureCookieDefaults
348
- * @see secureCookieDefaults
349
- */
350
- declare const createSecureCookies: typeof secureCookieDefaults;
351
-
352
- /**
353
- * @module @arcis/node/middleware/bot-detection
354
- * Local-only bot detection using User-Agent and behavioral signals.
355
- *
356
- * Categorizes requests into bot types and allows/denies based on config.
357
- * No cloud calls — everything runs locally.
358
- *
359
- * @example
360
- * // Block automated tools, allow search engines
361
- * app.use(botProtection({
362
- * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],
363
- * deny: ['AUTOMATED', 'SCRAPER'],
364
- * }));
365
- */
366
-
367
- type BotCategory = 'SEARCH_ENGINE' | 'SOCIAL' | 'MONITORING' | 'AI_CRAWLER' | 'SCRAPER' | 'AUTOMATED' | 'UNKNOWN' | 'HUMAN';
368
- interface BotDetectionResult {
369
- /** Whether the request appears to be from a bot */
370
- isBot: boolean;
371
- /** Bot category */
372
- category: BotCategory;
373
- /** Matched bot name (e.g. 'Googlebot', 'curl') or null */
374
- name: string | null;
375
- /** Confidence score: 0-1 */
376
- confidence: number;
377
- /** Behavioral signals detected */
378
- signals: string[];
379
- }
380
- interface BotProtectionOptions {
381
- /** Categories to explicitly allow. Default: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'] */
382
- allow?: BotCategory[];
383
- /** Categories to explicitly deny. Default: ['AUTOMATED'] */
384
- deny?: BotCategory[];
385
- /** Action for categories not in allow or deny. Default: 'allow' */
386
- defaultAction?: 'allow' | 'deny';
387
- /** HTTP status code for denied bots. Default: 403 */
388
- statusCode?: number;
389
- /** Error message for denied bots */
390
- message?: string;
391
- /** Enable behavioral signal detection. Default: true */
392
- detectBehavior?: boolean;
393
- /** Custom handler called on detection (instead of default deny response) */
394
- onDetected?: (req: Request, res: Response, result: BotDetectionResult) => void;
395
- }
396
- /**
397
- * Detect what kind of bot (if any) is making the request.
398
- *
399
- * @param req - HTTP request object
400
- * @returns Detection result with category, name, confidence, and signals
401
- *
402
- * @example
403
- * const result = detectBot(req);
404
- * if (result.isBot && result.category === 'AUTOMATED') {
405
- * // Block automated tools
406
- * }
407
- */
408
- declare function detectBot(req: Request): BotDetectionResult;
409
- /**
410
- * Create Express middleware for bot protection.
411
- *
412
- * @example
413
- * // Block automated tools and scrapers
414
- * app.use(botProtection({
415
- * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],
416
- * deny: ['AUTOMATED', 'SCRAPER'],
417
- * }));
418
- *
419
- * @example
420
- * // Block everything except search engines
421
- * app.use(botProtection({
422
- * allow: ['SEARCH_ENGINE'],
423
- * defaultAction: 'deny',
424
- * }));
425
- *
426
- * @example
427
- * // Custom handler
428
- * app.use(botProtection({
429
- * deny: ['AUTOMATED'],
430
- * onDetected: (req, res, result) => {
431
- * console.log(`Bot blocked: ${result.name} (${result.category})`);
432
- * res.status(403).json({ error: 'Bots not allowed' });
433
- * },
434
- * }));
435
- */
436
- declare function botProtection(options?: BotProtectionOptions): RequestHandler;
437
-
438
- /**
439
- * @module @arcis/node/middleware/csrf
440
- * CSRF (Cross-Site Request Forgery) protection middleware
441
- *
442
- * Implements the double-submit cookie pattern:
443
- * 1. Server sets a CSRF token in a cookie
444
- * 2. Client must send the same token in a header or form field
445
- * 3. Middleware rejects requests where cookie token !== header/field token
446
- *
447
- * This works because an attacker's cross-origin form submission will include
448
- * the cookie automatically, but cannot read it (same-origin policy) to set
449
- * the matching header.
450
- */
451
-
452
- /** CSRF protection configuration */
453
- interface CsrfOptions {
454
- /** Cookie name for the CSRF token. Default: '_csrf' */
455
- cookieName?: string;
456
- /** Header name to check for the token. Default: 'x-csrf-token' */
457
- headerName?: string;
458
- /** Form field name to check for the token. Default: '_csrf' */
459
- fieldName?: string;
460
- /** Token byte length (hex-encoded = 2x chars). Default: 32 */
461
- tokenLength?: number;
462
- /** HTTP methods to protect. Default: ['POST', 'PUT', 'PATCH', 'DELETE'] */
463
- protectedMethods?: string[];
464
- /** Paths to exclude from CSRF checks (e.g., webhook endpoints) */
465
- excludePaths?: string[];
466
- /** Cookie options */
467
- cookie?: {
468
- /** Cookie path. Default: '/' */
469
- path?: string;
470
- /** HttpOnly — set false so client JS can read it for headers. Default: false */
471
- httpOnly?: boolean;
472
- /** Secure flag (HTTPS only). Default: true in production */
473
- secure?: boolean;
474
- /** SameSite attribute. Default: 'Lax' */
475
- sameSite?: 'Strict' | 'Lax' | 'None';
476
- /** Cookie domain */
477
- domain?: string;
478
- };
479
- /** Custom error handler when CSRF validation fails */
480
- onError?: (req: Request, res: Response, next: NextFunction) => void;
481
- }
482
- /**
483
- * Generate a cryptographically random CSRF token.
484
- *
485
- * @param length - Byte length (output is hex, so 2x chars). Default: 32
486
- * @returns Hex-encoded random token
487
- *
488
- * @example
489
- * const token = generateCsrfToken(); // 64 hex chars
490
- */
491
- declare function generateCsrfToken(length?: number): string;
492
- /**
493
- * Validate that two CSRF tokens match using constant-time comparison.
494
- *
495
- * @param cookieToken - Token from the cookie
496
- * @param requestToken - Token from the header or form field
497
- * @returns true if tokens match
498
- */
499
- declare function validateCsrfToken(cookieToken: string, requestToken: string): boolean;
500
- /**
501
- * Create CSRF protection middleware using double-submit cookie pattern.
502
- *
503
- * For safe methods (GET, HEAD, OPTIONS), sets a CSRF token cookie if not present.
504
- * For unsafe methods (POST, PUT, PATCH, DELETE), validates the token.
505
- *
506
- * @param options - CSRF configuration
507
- * @returns Express middleware
508
- *
509
- * @example
510
- * // Basic usage
511
- * app.use(csrfProtection());
512
- *
513
- * @example
514
- * // Exclude webhook paths
515
- * app.use(csrfProtection({
516
- * excludePaths: ['/api/webhooks/stripe', '/api/webhooks/github']
517
- * }));
518
- *
519
- * @example
520
- * // Client-side: read cookie + set header
521
- * const token = document.cookie.match(/_csrf=([^;]+)/)?.[1];
522
- * fetch('/api/data', {
523
- * method: 'POST',
524
- * headers: { 'X-CSRF-Token': token },
525
- * credentials: 'same-origin'
526
- * });
527
- */
528
- declare function csrfProtection(options?: CsrfOptions): RequestHandler;
529
- /** Alias for csrfProtection */
530
- declare const createCsrf: typeof csrfProtection;
531
-
532
- export { validateCsrfToken as A, type BotCategory as B, type CorsOptions as C, type SecureCookieOptions as S, type TokenBucketMiddleware as T, type BotDetectionResult as a, type BotProtectionOptions as b, type CsrfOptions as c, type SlidingWindowMiddleware as d, type SlidingWindowOptions as e, type TokenBucketOptions as f, arcis as g, arcisWithMethods as h, botProtection as i, createCors as j, createCsrf as k, createErrorHandler as l, createHeaders as m, createRateLimiter as n, createSecureCookies as o, createSlidingWindowLimiter as p, createTokenBucketLimiter as q, csrfProtection as r, detectBot as s, enforceSecureCookie as t, errorHandler as u, generateCsrfToken as v, rateLimit as w, safeCors as x, secureCookieDefaults as y, securityHeaders as z };
package/dist/index.d.mts DELETED
@@ -1,175 +0,0 @@
1
- export { B as BotCategory, a as BotDetectionResult, b as BotProtectionOptions, C as CorsOptions, c as CsrfOptions, S as SecureCookieOptions, d as SlidingWindowMiddleware, e as SlidingWindowOptions, T as TokenBucketMiddleware, f as TokenBucketOptions, g as arcis, h as arcisFunction, i as botProtection, j as createCors, k as createCsrf, l as createErrorHandler, m as createHeaders, n as createRateLimiter, o as createSecureCookies, p as createSlidingWindowLimiter, q as createTokenBucketLimiter, r as csrfProtection, h as default, s as detectBot, t as enforceSecureCookie, u as errorHandler, v as generateCsrfToken, w as rateLimit, x as safeCors, y as secureCookieDefaults, z as securityHeaders, A as validateCsrfToken } from './index-DgJtWMSj.mjs';
2
- export { P as PiiMatch, K as PiiRedactOptions, L as PiiScanOptions, M as PiiType, c as createSanitizer, d as detectCommandInjection, a as detectHeaderInjection, b as detectJsonpInjection, e as detectNoSqlInjection, f as detectPathTraversal, g as detectPii, h as detectPrototypePollution, i as detectSql, j as detectSsti, k as detectXss, l as detectXxe, m as encodeForAttribute, n as encodeForCss, o as encodeForHtml, p as encodeForJs, q as encodeForUrl, t as isDangerousNoSqlKey, u as isDangerousProtoKey, v as redactObjectPii, w as redactPii, x as sanitizeCommand, y as sanitizeHeaderValue, z as sanitizeHeaders, A as sanitizeJsonpCallback, B as sanitizeObject, C as sanitizePath, D as sanitizeSql, E as sanitizeSsti, F as sanitizeString, G as sanitizeXss, H as sanitizeXxe, I as scanObjectPii, J as scanPii } from './encode-CrQCGlBq.mjs';
3
- export { E as EmailValidationOptions, a as EmailValidationResult, F as FileInput, V as ValidateFileOptions, b as ValidateFileResult, c as ValidateRedirectOptions, d as ValidateRedirectResult, e as ValidateUrlOptions, f as ValidateUrlResult, g as createValidator, i as isDangerousExtension, h as isRedirectSafe, j as isUrlSafe, k as isValidEmailSyntax, s as sanitizeFilename, v as validate, l as validateEmail, m as validateFile, n as validateRedirect, o as validateUrl, p as verifyEmailMx } from './index-Cd02z-0j.mjs';
4
- import { IncomingMessage } from 'http';
5
- export { createRedactor, createSafeLogger, safeLog } from './logging/index.mjs';
6
- export { MemoryStore, RedisClientLike, RedisStore, RedisStoreOptions, createRedisStore } from './stores/index.mjs';
7
- export { A as ArcisFunction, a as ArcisMiddleware, b as ArcisOptions, E as ErrorHandlerOptions, F as FieldValidator, H as HeaderOptions, c as HstsOptions, d as HttpError, L as LogOptions, R as RateLimitEntry, e as RateLimitOptions, f as RateLimitResult, g as RateLimitStore, h as RateLimiterMiddleware, S as SafeLogger, i as SanitizeOptions, j as SanitizeResult, T as ThreatInfo, k as ThreatType, V as ValidationConfig, l as ValidationError, m as ValidationResult, n as ValidationSchema } from './types-BOkx5YJc.mjs';
8
- export { ArcisError, ArcisValidationError, BLOCKED, ERRORS, HEADERS, INPUT, InputTooLargeError, RATE_LIMIT, REDACTION, RateLimitError, SanitizationError, SecurityThreatError, VALIDATION } from './core/index.mjs';
9
- import 'express';
10
-
11
- /**
12
- * @module @arcis/node/utils/duration
13
- * Parse human-readable duration strings into milliseconds.
14
- *
15
- * Supports: ms, s, m, h, d
16
- *
17
- * @example
18
- * parseDuration('5m') // 300000
19
- * parseDuration('2h') // 7200000
20
- * parseDuration(60000) // 60000 (passthrough)
21
- * parseDuration('500ms') // 500
22
- */
23
- /**
24
- * Parse a duration string or number into milliseconds.
25
- *
26
- * @param value - Duration string (e.g. "5m", "2h", "30s") or number (ms)
27
- * @returns Duration in milliseconds
28
- * @throws {Error} If the value is not a valid duration
29
- *
30
- * @example
31
- * parseDuration('15m') // 900000
32
- * parseDuration('1d') // 86400000
33
- * parseDuration('500ms') // 500
34
- * parseDuration(60000) // 60000
35
- */
36
- declare function parseDuration(value: string | number): number;
37
- /**
38
- * Format milliseconds into a human-readable duration string.
39
- *
40
- * @param ms - Duration in milliseconds
41
- * @returns Human-readable string (e.g. "5m", "2h 30m")
42
- */
43
- declare function formatDuration(ms: number): string;
44
-
45
- /**
46
- * @module @arcis/node/utils/ip
47
- * Platform-aware client IP detection.
48
- *
49
- * Prevents IP spoofing by reading platform-specific headers
50
- * instead of blindly trusting X-Forwarded-For.
51
- *
52
- * @example
53
- * // Auto-detect platform from environment
54
- * const ip = detectClientIp(req);
55
- *
56
- * // Explicit platform
57
- * const ip = detectClientIp(req, { platform: 'cloudflare' });
58
- */
59
-
60
- type Platform = 'auto' | 'cloudflare' | 'vercel' | 'flyio' | 'render' | 'firebase' | 'aws-alb' | 'generic';
61
- interface DetectIpOptions {
62
- /** Platform to use for header selection. Default: 'auto' */
63
- platform?: Platform;
64
- /** Number of trusted proxies (for X-Forwarded-For parsing). Default: 1 */
65
- trustedProxyCount?: number;
66
- }
67
- interface RequestLike$1 {
68
- headers: Record<string, string | string[] | undefined>;
69
- socket?: {
70
- remoteAddress?: string;
71
- };
72
- connection?: {
73
- remoteAddress?: string;
74
- };
75
- ip?: string;
76
- }
77
- /**
78
- * Detect the real client IP address from a request.
79
- *
80
- * Uses platform-specific headers when available to prevent IP spoofing.
81
- * Falls back to X-Forwarded-For (parsed from the right) and then
82
- * the socket remote address.
83
- *
84
- * @param req - HTTP request object (Express, raw http, etc.)
85
- * @param options - Detection options
86
- * @returns Client IP address, or 'unknown' if unresolvable
87
- *
88
- * @example
89
- * // Auto-detect platform
90
- * app.use((req, res, next) => {
91
- * const clientIp = detectClientIp(req);
92
- * console.log('Client IP:', clientIp);
93
- * next();
94
- * });
95
- *
96
- * @example
97
- * // Behind Cloudflare
98
- * const ip = detectClientIp(req, { platform: 'cloudflare' });
99
- *
100
- * @example
101
- * // Behind 2 proxies (e.g. CDN + load balancer)
102
- * const ip = detectClientIp(req, { trustedProxyCount: 2 });
103
- */
104
- declare function detectClientIp(req: RequestLike$1 | IncomingMessage, options?: DetectIpOptions): string;
105
- /**
106
- * Check if an IP address is a private/internal address.
107
- *
108
- * Detects: loopback, private ranges (RFC 1918), link-local, IPv6 equivalents.
109
- */
110
- declare function isPrivateIp(ip: string): boolean;
111
-
112
- /**
113
- * @module @arcis/node/utils/fingerprint
114
- * Deterministic request fingerprinting via SHA-256.
115
- *
116
- * Generates a stable hash from request characteristics for
117
- * rate limiting keys, abuse detection, and analytics.
118
- *
119
- * @example
120
- * const fp = await fingerprint(req);
121
- * // "a3f2b8c1d4e5..."
122
- */
123
-
124
- interface FingerprintOptions {
125
- /** Include IP address in fingerprint. Default: true */
126
- ip?: boolean;
127
- /** Include User-Agent header. Default: true */
128
- userAgent?: boolean;
129
- /** Include Accept header. Default: true */
130
- accept?: boolean;
131
- /** Include Accept-Language header. Default: true */
132
- acceptLanguage?: boolean;
133
- /** Include Accept-Encoding header. Default: true */
134
- acceptEncoding?: boolean;
135
- /** Additional custom components to include */
136
- custom?: string[];
137
- /** IP detection options */
138
- ipOptions?: DetectIpOptions;
139
- }
140
- interface RequestLike {
141
- headers: Record<string, string | string[] | undefined>;
142
- socket?: {
143
- remoteAddress?: string;
144
- };
145
- connection?: {
146
- remoteAddress?: string;
147
- };
148
- ip?: string;
149
- }
150
- /**
151
- * Generate a deterministic fingerprint for a request.
152
- *
153
- * Creates a SHA-256 hash from configurable request components.
154
- * The fingerprint is stable across requests from the same client
155
- * (same IP, browser, language settings).
156
- *
157
- * @param req - HTTP request object
158
- * @param options - Fingerprint configuration
159
- * @returns Hex-encoded SHA-256 hash (64 characters)
160
- *
161
- * @example
162
- * // Default fingerprint (IP + UA + Accept headers)
163
- * const fp = fingerprint(req);
164
- *
165
- * @example
166
- * // IP-only fingerprint (for simple rate limiting)
167
- * const fp = fingerprint(req, { userAgent: false, accept: false, acceptLanguage: false, acceptEncoding: false });
168
- *
169
- * @example
170
- * // With custom components
171
- * const fp = fingerprint(req, { custom: [req.body?.userId] });
172
- */
173
- declare function fingerprint(req: RequestLike, options?: FingerprintOptions): string;
174
-
175
- export { type DetectIpOptions, type FingerprintOptions, type Platform, detectClientIp, fingerprint, formatDuration, isPrivateIp, parseDuration };