@skillsmith/core 0.1.2 → 0.2.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analysis/CodebaseAnalyzer.d.ts +4 -134
- package/dist/src/analysis/CodebaseAnalyzer.d.ts.map +1 -1
- package/dist/src/analysis/CodebaseAnalyzer.js +7 -315
- package/dist/src/analysis/CodebaseAnalyzer.js.map +1 -1
- package/dist/src/analysis/framework-detector.d.ts +47 -0
- package/dist/src/analysis/framework-detector.d.ts.map +1 -0
- package/dist/src/analysis/framework-detector.js +151 -0
- package/dist/src/analysis/framework-detector.js.map +1 -0
- package/dist/src/analysis/index.d.ts +6 -1
- package/dist/src/analysis/index.d.ts.map +1 -1
- package/dist/src/analysis/index.js +10 -1
- package/dist/src/analysis/index.js.map +1 -1
- package/dist/src/analysis/parsers.d.ts +43 -0
- package/dist/src/analysis/parsers.d.ts.map +1 -0
- package/dist/src/analysis/parsers.js +219 -0
- package/dist/src/analysis/parsers.js.map +1 -0
- package/dist/src/analysis/types.d.ts +138 -0
- package/dist/src/analysis/types.d.ts.map +1 -0
- package/dist/src/analysis/types.js +25 -0
- package/dist/src/analysis/types.js.map +1 -0
- package/dist/src/analytics/AnalyticsRepository.d.ts.map +1 -1
- package/dist/src/analytics/AnalyticsRepository.js +4 -4
- package/dist/src/analytics/AnalyticsRepository.js.map +1 -1
- package/dist/src/api/cache.d.ts +108 -0
- package/dist/src/api/cache.d.ts.map +1 -0
- package/dist/src/api/cache.js +216 -0
- package/dist/src/api/cache.js.map +1 -0
- package/dist/src/api/client.d.ts +152 -0
- package/dist/src/api/client.d.ts.map +1 -0
- package/dist/src/api/client.js +221 -0
- package/dist/src/api/client.js.map +1 -0
- package/dist/src/api/index.d.ts +10 -0
- package/dist/src/api/index.d.ts.map +1 -0
- package/dist/src/api/index.js +10 -0
- package/dist/src/api/index.js.map +1 -0
- package/dist/src/benchmarks/BenchmarkRunner.d.ts +6 -175
- package/dist/src/benchmarks/BenchmarkRunner.d.ts.map +1 -1
- package/dist/src/benchmarks/BenchmarkRunner.js +6 -123
- package/dist/src/benchmarks/BenchmarkRunner.js.map +1 -1
- package/dist/src/benchmarks/MemoryProfiler.d.ts +4 -262
- package/dist/src/benchmarks/MemoryProfiler.d.ts.map +1 -1
- package/dist/src/benchmarks/MemoryProfiler.js +4 -400
- package/dist/src/benchmarks/MemoryProfiler.js.map +1 -1
- package/dist/src/benchmarks/comparator.d.ts +38 -0
- package/dist/src/benchmarks/comparator.d.ts.map +1 -0
- package/dist/src/benchmarks/comparator.js +81 -0
- package/dist/src/benchmarks/comparator.js.map +1 -0
- package/dist/src/benchmarks/formatters.d.ts +30 -0
- package/dist/src/benchmarks/formatters.d.ts.map +1 -0
- package/dist/src/benchmarks/formatters.js +88 -0
- package/dist/src/benchmarks/formatters.js.map +1 -0
- package/dist/src/benchmarks/index.d.ts +5 -1
- package/dist/src/benchmarks/index.d.ts.map +1 -1
- package/dist/src/benchmarks/index.js +9 -2
- package/dist/src/benchmarks/index.js.map +1 -1
- package/dist/src/benchmarks/memory/MemoryProfiler.d.ts +165 -0
- package/dist/src/benchmarks/memory/MemoryProfiler.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/MemoryProfiler.js +312 -0
- package/dist/src/benchmarks/memory/MemoryProfiler.js.map +1 -0
- package/dist/src/benchmarks/memory/baseline-manager.d.ts +64 -0
- package/dist/src/benchmarks/memory/baseline-manager.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/baseline-manager.js +95 -0
- package/dist/src/benchmarks/memory/baseline-manager.js.map +1 -0
- package/dist/src/benchmarks/memory/index.d.ts +12 -0
- package/dist/src/benchmarks/memory/index.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/index.js +12 -0
- package/dist/src/benchmarks/memory/index.js.map +1 -0
- package/dist/src/benchmarks/memory/leak-detector.d.ts +23 -0
- package/dist/src/benchmarks/memory/leak-detector.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/leak-detector.js +46 -0
- package/dist/src/benchmarks/memory/leak-detector.js.map +1 -0
- package/dist/src/benchmarks/memory/regression-detector.d.ts +17 -0
- package/dist/src/benchmarks/memory/regression-detector.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/regression-detector.js +56 -0
- package/dist/src/benchmarks/memory/regression-detector.js.map +1 -0
- package/dist/src/benchmarks/memory/types.d.ts +111 -0
- package/dist/src/benchmarks/memory/types.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/types.js +7 -0
- package/dist/src/benchmarks/memory/types.js.map +1 -0
- package/dist/src/benchmarks/memory/utils.d.ts +17 -0
- package/dist/src/benchmarks/memory/utils.d.ts.map +1 -0
- package/dist/src/benchmarks/memory/utils.js +29 -0
- package/dist/src/benchmarks/memory/utils.js.map +1 -0
- package/dist/src/benchmarks/types.d.ts +175 -0
- package/dist/src/benchmarks/types.d.ts.map +1 -0
- package/dist/src/benchmarks/types.js +20 -0
- package/dist/src/benchmarks/types.js.map +1 -0
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/repositories/QuarantineRepository.d.ts +4 -251
- package/dist/src/repositories/QuarantineRepository.d.ts.map +1 -1
- package/dist/src/repositories/QuarantineRepository.js +4 -441
- package/dist/src/repositories/QuarantineRepository.js.map +1 -1
- package/dist/src/repositories/quarantine/QuarantineRepository.d.ts +168 -0
- package/dist/src/repositories/quarantine/QuarantineRepository.d.ts.map +1 -0
- package/dist/src/repositories/quarantine/QuarantineRepository.js +341 -0
- package/dist/src/repositories/quarantine/QuarantineRepository.js.map +1 -0
- package/dist/src/repositories/quarantine/index.d.ts +10 -0
- package/dist/src/repositories/quarantine/index.d.ts.map +1 -0
- package/dist/src/repositories/quarantine/index.js +10 -0
- package/dist/src/repositories/quarantine/index.js.map +1 -0
- package/dist/src/repositories/quarantine/queries.d.ts +58 -0
- package/dist/src/repositories/quarantine/queries.d.ts.map +1 -0
- package/dist/src/repositories/quarantine/queries.js +88 -0
- package/dist/src/repositories/quarantine/queries.js.map +1 -0
- package/dist/src/repositories/quarantine/query-builder.d.ts +44 -0
- package/dist/src/repositories/quarantine/query-builder.d.ts.map +1 -0
- package/dist/src/repositories/quarantine/query-builder.js +87 -0
- package/dist/src/repositories/quarantine/query-builder.js.map +1 -0
- package/dist/src/repositories/quarantine/types.d.ts +155 -0
- package/dist/src/repositories/quarantine/types.d.ts.map +1 -0
- package/dist/src/repositories/quarantine/types.js +13 -0
- package/dist/src/repositories/quarantine/types.js.map +1 -0
- package/dist/src/scripts/__tests__/scan-imported-skills.test.d.ts +1 -0
- package/dist/src/scripts/__tests__/scan-imported-skills.test.d.ts.map +1 -1
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js +7 -43
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
- package/dist/src/scripts/github-import/checkpoint.d.ts +21 -0
- package/dist/src/scripts/github-import/checkpoint.d.ts.map +1 -0
- package/dist/src/scripts/github-import/checkpoint.js +52 -0
- package/dist/src/scripts/github-import/checkpoint.js.map +1 -0
- package/dist/src/scripts/github-import/deduplication.d.ts +15 -0
- package/dist/src/scripts/github-import/deduplication.d.ts.map +1 -0
- package/dist/src/scripts/github-import/deduplication.js +33 -0
- package/dist/src/scripts/github-import/deduplication.js.map +1 -0
- package/dist/src/scripts/github-import/github-client.d.ts +29 -0
- package/dist/src/scripts/github-import/github-client.d.ts.map +1 -0
- package/dist/src/scripts/github-import/github-client.js +184 -0
- package/dist/src/scripts/github-import/github-client.js.map +1 -0
- package/dist/src/scripts/github-import/index.d.ts +29 -0
- package/dist/src/scripts/github-import/index.d.ts.map +1 -0
- package/dist/src/scripts/github-import/index.js +198 -0
- package/dist/src/scripts/github-import/index.js.map +1 -0
- package/dist/src/scripts/github-import/output.d.ts +12 -0
- package/dist/src/scripts/github-import/output.d.ts.map +1 -0
- package/dist/src/scripts/github-import/output.js +34 -0
- package/dist/src/scripts/github-import/output.js.map +1 -0
- package/dist/src/scripts/github-import/types.d.ts +108 -0
- package/dist/src/scripts/github-import/types.d.ts.map +1 -0
- package/dist/src/scripts/github-import/types.js +44 -0
- package/dist/src/scripts/github-import/types.js.map +1 -0
- package/dist/src/scripts/github-import/utils.d.ts +13 -0
- package/dist/src/scripts/github-import/utils.d.ts.map +1 -0
- package/dist/src/scripts/github-import/utils.js +28 -0
- package/dist/src/scripts/github-import/utils.js.map +1 -0
- package/dist/src/scripts/import-github-skills.d.ts +3 -12
- package/dist/src/scripts/import-github-skills.d.ts.map +1 -1
- package/dist/src/scripts/import-github-skills.js +18 -398
- package/dist/src/scripts/import-github-skills.js.map +1 -1
- package/dist/src/scripts/scan-imported-skills.d.ts +7 -7
- package/dist/src/scripts/scan-imported-skills.d.ts.map +1 -1
- package/dist/src/scripts/scan-imported-skills.js +8 -397
- package/dist/src/scripts/scan-imported-skills.js.map +1 -1
- package/dist/src/scripts/skill-scanner/categorizer.d.ts +43 -0
- package/dist/src/scripts/skill-scanner/categorizer.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/categorizer.js +61 -0
- package/dist/src/scripts/skill-scanner/categorizer.js.map +1 -0
- package/dist/src/scripts/skill-scanner/file-scanner.d.ts +43 -0
- package/dist/src/scripts/skill-scanner/file-scanner.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/file-scanner.js +90 -0
- package/dist/src/scripts/skill-scanner/file-scanner.js.map +1 -0
- package/dist/src/scripts/skill-scanner/index.d.ts +22 -0
- package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/index.js +43 -0
- package/dist/src/scripts/skill-scanner/index.js.map +1 -0
- package/dist/src/scripts/skill-scanner/logger.d.ts +59 -0
- package/dist/src/scripts/skill-scanner/logger.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/logger.js +104 -0
- package/dist/src/scripts/skill-scanner/logger.js.map +1 -0
- package/dist/src/scripts/skill-scanner/reporter.d.ts +56 -0
- package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/reporter.js +166 -0
- package/dist/src/scripts/skill-scanner/reporter.js.map +1 -0
- package/dist/src/scripts/skill-scanner/scanner.d.ts +44 -0
- package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/scanner.js +140 -0
- package/dist/src/scripts/skill-scanner/scanner.js.map +1 -0
- package/dist/src/scripts/skill-scanner/trust-scorer.d.ts +59 -0
- package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/trust-scorer.js +62 -0
- package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -0
- package/dist/src/scripts/skill-scanner/types.d.ts +98 -0
- package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/types.js +7 -0
- package/dist/src/scripts/skill-scanner/types.js.map +1 -0
- package/dist/src/scripts/validate-skills.d.ts +3 -172
- package/dist/src/scripts/validate-skills.d.ts.map +1 -1
- package/dist/src/scripts/validate-skills.js +6 -519
- package/dist/src/scripts/validate-skills.js.map +1 -1
- package/dist/src/scripts/validation/deduplication.d.ts +23 -0
- package/dist/src/scripts/validation/deduplication.d.ts.map +1 -0
- package/dist/src/scripts/validation/deduplication.js +127 -0
- package/dist/src/scripts/validation/deduplication.js.map +1 -0
- package/dist/src/scripts/validation/field-validators.d.ts +9 -0
- package/dist/src/scripts/validation/field-validators.d.ts.map +1 -0
- package/dist/src/scripts/validation/field-validators.js +135 -0
- package/dist/src/scripts/validation/field-validators.js.map +1 -0
- package/dist/src/scripts/validation/index.d.ts +29 -0
- package/dist/src/scripts/validation/index.d.ts.map +1 -0
- package/dist/src/scripts/validation/index.js +84 -0
- package/dist/src/scripts/validation/index.js.map +1 -0
- package/dist/src/scripts/validation/normalizers.d.ts +29 -0
- package/dist/src/scripts/validation/normalizers.d.ts.map +1 -0
- package/dist/src/scripts/validation/normalizers.js +79 -0
- package/dist/src/scripts/validation/normalizers.js.map +1 -0
- package/dist/src/scripts/validation/pipeline.d.ts +13 -0
- package/dist/src/scripts/validation/pipeline.d.ts.map +1 -0
- package/dist/src/scripts/validation/pipeline.js +126 -0
- package/dist/src/scripts/validation/pipeline.js.map +1 -0
- package/dist/src/scripts/validation/types.d.ts +128 -0
- package/dist/src/scripts/validation/types.d.ts.map +1 -0
- package/dist/src/scripts/validation/types.js +43 -0
- package/dist/src/scripts/validation/types.js.map +1 -0
- package/dist/src/security/index.d.ts +5 -4
- package/dist/src/security/index.d.ts.map +1 -1
- package/dist/src/security/index.js +8 -2
- package/dist/src/security/index.js.map +1 -1
- package/dist/src/security/rate-limiter/RateLimiter.d.ts +86 -0
- package/dist/src/security/rate-limiter/RateLimiter.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/RateLimiter.js +260 -0
- package/dist/src/security/rate-limiter/RateLimiter.js.map +1 -0
- package/dist/src/security/rate-limiter/constants.d.ts +15 -0
- package/dist/src/security/rate-limiter/constants.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/constants.js +15 -0
- package/dist/src/security/rate-limiter/constants.js.map +1 -0
- package/dist/src/security/rate-limiter/errors.d.ts +22 -0
- package/dist/src/security/rate-limiter/errors.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/errors.js +32 -0
- package/dist/src/security/rate-limiter/errors.js.map +1 -0
- package/dist/src/security/rate-limiter/index.d.ts +12 -0
- package/dist/src/security/rate-limiter/index.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/index.js +16 -0
- package/dist/src/security/rate-limiter/index.js.map +1 -0
- package/dist/src/security/rate-limiter/metrics-manager.d.ts +55 -0
- package/dist/src/security/rate-limiter/metrics-manager.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/metrics-manager.js +144 -0
- package/dist/src/security/rate-limiter/metrics-manager.js.map +1 -0
- package/dist/src/security/rate-limiter/presets.d.ts +52 -0
- package/dist/src/security/rate-limiter/presets.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/presets.js +53 -0
- package/dist/src/security/rate-limiter/presets.js.map +1 -0
- package/dist/src/security/rate-limiter/queue-manager.d.ts +59 -0
- package/dist/src/security/rate-limiter/queue-manager.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/queue-manager.js +189 -0
- package/dist/src/security/rate-limiter/queue-manager.js.map +1 -0
- package/dist/src/security/rate-limiter/storage.d.ts +34 -0
- package/dist/src/security/rate-limiter/storage.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/storage.js +80 -0
- package/dist/src/security/rate-limiter/storage.js.map +1 -0
- package/dist/src/security/rate-limiter/token-bucket.d.ts +44 -0
- package/dist/src/security/rate-limiter/token-bucket.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/token-bucket.js +99 -0
- package/dist/src/security/rate-limiter/token-bucket.js.map +1 -0
- package/dist/src/security/rate-limiter/types.d.ts +104 -0
- package/dist/src/security/rate-limiter/types.d.ts.map +1 -0
- package/dist/src/security/rate-limiter/types.js +7 -0
- package/dist/src/security/rate-limiter/types.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts +94 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.js +403 -0
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -0
- package/dist/src/security/scanner/index.d.ts +11 -0
- package/dist/src/security/scanner/index.d.ts.map +1 -0
- package/dist/src/security/scanner/index.js +14 -0
- package/dist/src/security/scanner/index.js.map +1 -0
- package/dist/src/security/scanner/patterns.d.ts +14 -0
- package/dist/src/security/scanner/patterns.d.ts.map +1 -0
- package/dist/src/security/scanner/patterns.js +147 -0
- package/dist/src/security/scanner/patterns.js.map +1 -0
- package/dist/src/security/scanner/regex-utils.d.ts +33 -0
- package/dist/src/security/scanner/regex-utils.d.ts.map +1 -0
- package/dist/src/security/scanner/regex-utils.js +41 -0
- package/dist/src/security/scanner/regex-utils.js.map +1 -0
- package/dist/src/security/scanner/types.d.ts +63 -0
- package/dist/src/security/scanner/types.d.ts.map +1 -0
- package/dist/src/security/scanner/types.js +7 -0
- package/dist/src/security/scanner/types.js.map +1 -0
- package/dist/src/security/scanner/weights.d.ts +15 -0
- package/dist/src/security/scanner/weights.d.ts.map +1 -0
- package/dist/src/security/scanner/weights.js +28 -0
- package/dist/src/security/scanner/weights.js.map +1 -0
- package/dist/src/session/SessionHealthMonitor.d.ts +5 -168
- package/dist/src/session/SessionHealthMonitor.d.ts.map +1 -1
- package/dist/src/session/SessionHealthMonitor.js +22 -91
- package/dist/src/session/SessionHealthMonitor.js.map +1 -1
- package/dist/src/session/health-checks.d.ts +37 -0
- package/dist/src/session/health-checks.d.ts.map +1 -0
- package/dist/src/session/health-checks.js +64 -0
- package/dist/src/session/health-checks.js.map +1 -0
- package/dist/src/session/health-types.d.ts +78 -0
- package/dist/src/session/health-types.d.ts.map +1 -0
- package/dist/src/session/health-types.js +16 -0
- package/dist/src/session/health-types.js.map +1 -0
- package/dist/src/session/index.d.ts +5 -1
- package/dist/src/session/index.d.ts.map +1 -1
- package/dist/src/session/index.js +9 -0
- package/dist/src/session/index.js.map +1 -1
- package/dist/src/session/metrics-collector.d.ts +23 -0
- package/dist/src/session/metrics-collector.d.ts.map +1 -0
- package/dist/src/session/metrics-collector.js +44 -0
- package/dist/src/session/metrics-collector.js.map +1 -0
- package/dist/src/session/typed-event-emitter.d.ts +70 -0
- package/dist/src/session/typed-event-emitter.d.ts.map +1 -0
- package/dist/src/session/typed-event-emitter.js +79 -0
- package/dist/src/session/typed-event-emitter.js.map +1 -0
- package/dist/src/sources/BaseSourceAdapter.d.ts +1 -1
- package/dist/src/sources/BaseSourceAdapter.d.ts.map +1 -1
- package/dist/src/sources/BaseSourceAdapter.js +2 -2
- package/dist/src/sources/BaseSourceAdapter.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +1 -0
- package/dist/src/telemetry/index.d.ts.map +1 -1
- package/dist/src/telemetry/index.js +2 -0
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/posthog.d.ts +125 -0
- package/dist/src/telemetry/posthog.d.ts.map +1 -0
- package/dist/src/telemetry/posthog.js +198 -0
- package/dist/src/telemetry/posthog.js.map +1 -0
- package/dist/tests/RateLimiter.test.js +4 -4
- package/dist/tests/RateLimiter.test.js.map +1 -1
- package/dist/tests/e2e/security/security.e2e.test.js +3 -3
- package/dist/tests/e2e/security/security.e2e.test.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Presets - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Pre-configured rate limit settings for common use cases.
|
|
5
|
+
*/
|
|
6
|
+
import type { RateLimitStorage } from './types.js';
|
|
7
|
+
import { RateLimiter } from './RateLimiter.js';
|
|
8
|
+
/**
|
|
9
|
+
* Preset rate limit configurations
|
|
10
|
+
*/
|
|
11
|
+
export declare const RATE_LIMIT_PRESETS: {
|
|
12
|
+
/** Very strict: 10 requests per minute, fail-closed for high security */
|
|
13
|
+
readonly STRICT: {
|
|
14
|
+
readonly maxTokens: 10;
|
|
15
|
+
readonly refillRate: number;
|
|
16
|
+
readonly windowMs: 60000;
|
|
17
|
+
readonly failMode: "closed";
|
|
18
|
+
};
|
|
19
|
+
/** Standard: 30 requests per minute (default for adapters) */
|
|
20
|
+
readonly STANDARD: {
|
|
21
|
+
readonly maxTokens: 30;
|
|
22
|
+
readonly refillRate: number;
|
|
23
|
+
readonly windowMs: 60000;
|
|
24
|
+
readonly failMode: "open";
|
|
25
|
+
};
|
|
26
|
+
/** Relaxed: 60 requests per minute */
|
|
27
|
+
readonly RELAXED: {
|
|
28
|
+
readonly maxTokens: 60;
|
|
29
|
+
readonly refillRate: number;
|
|
30
|
+
readonly windowMs: 60000;
|
|
31
|
+
readonly failMode: "open";
|
|
32
|
+
};
|
|
33
|
+
/** Generous: 120 requests per minute */
|
|
34
|
+
readonly GENEROUS: {
|
|
35
|
+
readonly maxTokens: 120;
|
|
36
|
+
readonly refillRate: number;
|
|
37
|
+
readonly windowMs: 60000;
|
|
38
|
+
readonly failMode: "open";
|
|
39
|
+
};
|
|
40
|
+
/** High throughput: 300 requests per minute */
|
|
41
|
+
readonly HIGH_THROUGHPUT: {
|
|
42
|
+
readonly maxTokens: 300;
|
|
43
|
+
readonly refillRate: number;
|
|
44
|
+
readonly windowMs: 60000;
|
|
45
|
+
readonly failMode: "open";
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Create a rate limiter from a preset
|
|
50
|
+
*/
|
|
51
|
+
export declare function createRateLimiterFromPreset(preset: keyof typeof RATE_LIMIT_PRESETS, storage?: RateLimitStorage): RateLimiter;
|
|
52
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../../src/security/rate-limiter/presets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B,yEAAyE;;;;;;;IAOzE,8DAA8D;;;;;;;IAO9D,sCAAsC;;;;;;;IAOtC,wCAAwC;;;;;;;IAOxC,+CAA+C;;;;;;;CAOvC,CAAA;AAEV;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,OAAO,kBAAkB,EACvC,OAAO,CAAC,EAAE,gBAAgB,GACzB,WAAW,CAEb"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Presets - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Pre-configured rate limit settings for common use cases.
|
|
5
|
+
*/
|
|
6
|
+
import { RateLimiter } from './RateLimiter.js';
|
|
7
|
+
/**
|
|
8
|
+
* Preset rate limit configurations
|
|
9
|
+
*/
|
|
10
|
+
export const RATE_LIMIT_PRESETS = {
|
|
11
|
+
/** Very strict: 10 requests per minute, fail-closed for high security */
|
|
12
|
+
STRICT: {
|
|
13
|
+
maxTokens: 10,
|
|
14
|
+
refillRate: 10 / 60, // 0.167 tokens/sec
|
|
15
|
+
windowMs: 60000,
|
|
16
|
+
failMode: 'closed',
|
|
17
|
+
},
|
|
18
|
+
/** Standard: 30 requests per minute (default for adapters) */
|
|
19
|
+
STANDARD: {
|
|
20
|
+
maxTokens: 30,
|
|
21
|
+
refillRate: 30 / 60, // 0.5 tokens/sec
|
|
22
|
+
windowMs: 60000,
|
|
23
|
+
failMode: 'open',
|
|
24
|
+
},
|
|
25
|
+
/** Relaxed: 60 requests per minute */
|
|
26
|
+
RELAXED: {
|
|
27
|
+
maxTokens: 60,
|
|
28
|
+
refillRate: 60 / 60, // 1 token/sec
|
|
29
|
+
windowMs: 60000,
|
|
30
|
+
failMode: 'open',
|
|
31
|
+
},
|
|
32
|
+
/** Generous: 120 requests per minute */
|
|
33
|
+
GENEROUS: {
|
|
34
|
+
maxTokens: 120,
|
|
35
|
+
refillRate: 120 / 60, // 2 tokens/sec
|
|
36
|
+
windowMs: 60000,
|
|
37
|
+
failMode: 'open',
|
|
38
|
+
},
|
|
39
|
+
/** High throughput: 300 requests per minute */
|
|
40
|
+
HIGH_THROUGHPUT: {
|
|
41
|
+
maxTokens: 300,
|
|
42
|
+
refillRate: 300 / 60, // 5 tokens/sec
|
|
43
|
+
windowMs: 60000,
|
|
44
|
+
failMode: 'open',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Create a rate limiter from a preset
|
|
49
|
+
*/
|
|
50
|
+
export function createRateLimiterFromPreset(preset, storage) {
|
|
51
|
+
return new RateLimiter(RATE_LIMIT_PRESETS[preset], storage);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../../src/security/rate-limiter/presets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,yEAAyE;IACzE,MAAM,EAAE;QACN,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,mBAAmB;QACxC,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,QAAiB;KAC5B;IACD,8DAA8D;IAC9D,QAAQ,EAAE;QACR,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,iBAAiB;QACtC,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAe;KAC1B;IACD,sCAAsC;IACtC,OAAO,EAAE;QACP,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,cAAc;QACnC,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAe;KAC1B;IACD,wCAAwC;IACxC,QAAQ,EAAE;QACR,SAAS,EAAE,GAAG;QACd,UAAU,EAAE,GAAG,GAAG,EAAE,EAAE,eAAe;QACrC,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAe;KAC1B;IACD,+CAA+C;IAC/C,eAAe,EAAE;QACf,SAAS,EAAE,GAAG;QACd,UAAU,EAAE,GAAG,GAAG,EAAE,EAAE,eAAe;QACrC,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,MAAe;KAC1B;CACO,CAAA;AAEV;;GAEG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAuC,EACvC,OAA0B;IAE1B,OAAO,IAAI,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limit Queue Manager - SMI-1013, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Queue management for rate limiting with request waiting.
|
|
5
|
+
*/
|
|
6
|
+
import type { RateLimitResult } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for the queue manager
|
|
9
|
+
*/
|
|
10
|
+
export interface QueueManagerConfig {
|
|
11
|
+
maxQueueSize: number;
|
|
12
|
+
queueTimeoutMs: number;
|
|
13
|
+
debug: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Manages request queues for rate limiting
|
|
17
|
+
*/
|
|
18
|
+
export declare class QueueManager {
|
|
19
|
+
private readonly queues;
|
|
20
|
+
private processorInterval;
|
|
21
|
+
private isProcessing;
|
|
22
|
+
private readonly config;
|
|
23
|
+
private readonly log;
|
|
24
|
+
constructor(config: QueueManagerConfig, log?: {
|
|
25
|
+
debug: (msg: string, data?: Record<string, unknown>) => void;
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Start the queue processor
|
|
29
|
+
*/
|
|
30
|
+
startProcessor(tryConsumeToken: (key: string, cost: number) => Promise<RateLimitResult>, onSuccess: (key: string, allowed: boolean) => void): void;
|
|
31
|
+
/**
|
|
32
|
+
* Stop the queue processor
|
|
33
|
+
*/
|
|
34
|
+
stopProcessor(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Process all queues and release waiting requests when tokens become available
|
|
37
|
+
*/
|
|
38
|
+
private processQueues;
|
|
39
|
+
/**
|
|
40
|
+
* Queue a request and wait for a token
|
|
41
|
+
*/
|
|
42
|
+
queueRequest(key: string, cost: number, onMetricsUpdate: (allowed: boolean) => void): Promise<RateLimitResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Get queue status for a key
|
|
45
|
+
*/
|
|
46
|
+
getStatus(key?: string): {
|
|
47
|
+
totalQueued: number;
|
|
48
|
+
queues: Map<string, number>;
|
|
49
|
+
} | number;
|
|
50
|
+
/**
|
|
51
|
+
* Clear queue for a key
|
|
52
|
+
*/
|
|
53
|
+
clear(key?: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Dispose of resources
|
|
56
|
+
*/
|
|
57
|
+
dispose(): void;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=queue-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-manager.d.ts","sourceRoot":"","sources":["../../../../src/security/rate-limiter/queue-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,YAAY,CAAA;AAIhE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkE;gBAGpF,MAAM,EAAE,kBAAkB,EAC1B,GAAG,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;KAAE;IAMxE;;OAEG;IACH,cAAc,CACZ,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,EACxE,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GACjD,IAAI;IAOP;;OAEG;IACH,aAAa,IAAI,IAAI;IAOrB;;OAEG;YACW,aAAa;IAqD3B;;OAEG;IACG,YAAY,CAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAC1C,OAAO,CAAC,eAAe,CAAC;IA2D3B;;OAEG;IACH,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,MAAM;IActF;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAqBzB;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limit Queue Manager - SMI-1013, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Queue management for rate limiting with request waiting.
|
|
5
|
+
*/
|
|
6
|
+
import { randomUUID } from 'crypto';
|
|
7
|
+
import { RateLimitQueueTimeoutError, RateLimitQueueFullError } from './errors.js';
|
|
8
|
+
import { MAX_UNIQUE_KEYS } from './constants.js';
|
|
9
|
+
/**
|
|
10
|
+
* Manages request queues for rate limiting
|
|
11
|
+
*/
|
|
12
|
+
export class QueueManager {
|
|
13
|
+
queues = new Map();
|
|
14
|
+
processorInterval = null;
|
|
15
|
+
isProcessing = false;
|
|
16
|
+
config;
|
|
17
|
+
log;
|
|
18
|
+
constructor(config, log) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
this.log = log || { debug: () => { } };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Start the queue processor
|
|
24
|
+
*/
|
|
25
|
+
startProcessor(tryConsumeToken, onSuccess) {
|
|
26
|
+
// Check queue every 100ms
|
|
27
|
+
this.processorInterval = setInterval(() => {
|
|
28
|
+
this.processQueues(tryConsumeToken, onSuccess);
|
|
29
|
+
}, 100);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stop the queue processor
|
|
33
|
+
*/
|
|
34
|
+
stopProcessor() {
|
|
35
|
+
if (this.processorInterval) {
|
|
36
|
+
clearInterval(this.processorInterval);
|
|
37
|
+
this.processorInterval = null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Process all queues and release waiting requests when tokens become available
|
|
42
|
+
*/
|
|
43
|
+
async processQueues(tryConsumeToken, onSuccess) {
|
|
44
|
+
// Prevent concurrent queue processing
|
|
45
|
+
if (this.isProcessing) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.isProcessing = true;
|
|
49
|
+
try {
|
|
50
|
+
for (const [key, queue] of this.queues.entries()) {
|
|
51
|
+
if (queue.length === 0) {
|
|
52
|
+
// Clean up empty queues to prevent memory leak
|
|
53
|
+
this.queues.delete(key);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Try to process the first request in the queue
|
|
57
|
+
const request = queue[0];
|
|
58
|
+
const result = await tryConsumeToken(key, request.cost);
|
|
59
|
+
if (result.allowed) {
|
|
60
|
+
// Remove from queue by ID (not by position for safety)
|
|
61
|
+
const index = queue.findIndex((r) => r.id === request.id);
|
|
62
|
+
if (index !== -1) {
|
|
63
|
+
queue.splice(index, 1);
|
|
64
|
+
}
|
|
65
|
+
// Clear timeout
|
|
66
|
+
clearTimeout(request.timeoutHandle);
|
|
67
|
+
// Resolve with queue info
|
|
68
|
+
const queueWaitMs = Date.now() - request.queuedAt;
|
|
69
|
+
onSuccess(key, true);
|
|
70
|
+
request.resolve({
|
|
71
|
+
...result,
|
|
72
|
+
queued: true,
|
|
73
|
+
queueWaitMs,
|
|
74
|
+
});
|
|
75
|
+
if (this.config.debug) {
|
|
76
|
+
this.log.debug(`Queue request released for ${key}`, {
|
|
77
|
+
requestId: request.id,
|
|
78
|
+
queueWaitMs,
|
|
79
|
+
remaining: result.remaining,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
this.isProcessing = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Queue a request and wait for a token
|
|
91
|
+
*/
|
|
92
|
+
async queueRequest(key, cost, onMetricsUpdate) {
|
|
93
|
+
// Check queue size
|
|
94
|
+
const queue = this.queues.get(key) || [];
|
|
95
|
+
if (queue.length >= this.config.maxQueueSize) {
|
|
96
|
+
onMetricsUpdate(false);
|
|
97
|
+
throw new RateLimitQueueFullError(key, this.config.maxQueueSize);
|
|
98
|
+
}
|
|
99
|
+
// Check if adding new queue would exceed max unique keys
|
|
100
|
+
if (!this.queues.has(key) && this.queues.size >= MAX_UNIQUE_KEYS) {
|
|
101
|
+
onMetricsUpdate(false);
|
|
102
|
+
throw new RateLimitQueueFullError(key, this.config.maxQueueSize);
|
|
103
|
+
}
|
|
104
|
+
// Queue the request
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
// Use UUID for unique identification (not timestamp which can collide)
|
|
107
|
+
const requestId = randomUUID();
|
|
108
|
+
const queuedAt = Date.now();
|
|
109
|
+
// Set up timeout
|
|
110
|
+
const timeoutHandle = setTimeout(() => {
|
|
111
|
+
// Remove from queue by unique ID
|
|
112
|
+
const currentQueue = this.queues.get(key) || [];
|
|
113
|
+
const index = currentQueue.findIndex((r) => r.id === requestId);
|
|
114
|
+
if (index !== -1) {
|
|
115
|
+
currentQueue.splice(index, 1);
|
|
116
|
+
}
|
|
117
|
+
onMetricsUpdate(false);
|
|
118
|
+
reject(new RateLimitQueueTimeoutError(key, this.config.queueTimeoutMs));
|
|
119
|
+
}, this.config.queueTimeoutMs);
|
|
120
|
+
const request = {
|
|
121
|
+
id: requestId,
|
|
122
|
+
resolve,
|
|
123
|
+
reject,
|
|
124
|
+
cost,
|
|
125
|
+
queuedAt,
|
|
126
|
+
timeoutHandle,
|
|
127
|
+
};
|
|
128
|
+
// Add to queue
|
|
129
|
+
if (!this.queues.has(key)) {
|
|
130
|
+
this.queues.set(key, []);
|
|
131
|
+
}
|
|
132
|
+
this.queues.get(key).push(request);
|
|
133
|
+
if (this.config.debug) {
|
|
134
|
+
this.log.debug(`Request queued for ${key}`, {
|
|
135
|
+
requestId,
|
|
136
|
+
queueSize: this.queues.get(key).length,
|
|
137
|
+
cost,
|
|
138
|
+
timeoutMs: this.config.queueTimeoutMs,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get queue status for a key
|
|
145
|
+
*/
|
|
146
|
+
getStatus(key) {
|
|
147
|
+
if (key) {
|
|
148
|
+
return this.queues.get(key)?.length ?? 0;
|
|
149
|
+
}
|
|
150
|
+
const queues = new Map();
|
|
151
|
+
let totalQueued = 0;
|
|
152
|
+
for (const [k, q] of this.queues.entries()) {
|
|
153
|
+
queues.set(k, q.length);
|
|
154
|
+
totalQueued += q.length;
|
|
155
|
+
}
|
|
156
|
+
return { totalQueued, queues };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Clear queue for a key
|
|
160
|
+
*/
|
|
161
|
+
clear(key) {
|
|
162
|
+
const clearQueueForKey = (k) => {
|
|
163
|
+
const queue = this.queues.get(k);
|
|
164
|
+
if (queue) {
|
|
165
|
+
for (const request of queue) {
|
|
166
|
+
clearTimeout(request.timeoutHandle);
|
|
167
|
+
request.reject(new RateLimitQueueTimeoutError(k, 0));
|
|
168
|
+
}
|
|
169
|
+
this.queues.delete(k);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
if (key) {
|
|
173
|
+
clearQueueForKey(key);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
for (const k of this.queues.keys()) {
|
|
177
|
+
clearQueueForKey(k);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Dispose of resources
|
|
183
|
+
*/
|
|
184
|
+
dispose() {
|
|
185
|
+
this.stopProcessor();
|
|
186
|
+
this.clear();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=queue-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-manager.js","sourceRoot":"","sources":["../../../../src/security/rate-limiter/queue-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Storage - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Storage implementations for rate limiting.
|
|
5
|
+
*/
|
|
6
|
+
import type { RateLimitStorage, TokenBucket } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* In-memory storage implementation
|
|
9
|
+
*/
|
|
10
|
+
export declare class InMemoryRateLimitStorage implements RateLimitStorage {
|
|
11
|
+
private store;
|
|
12
|
+
private cleanupInterval;
|
|
13
|
+
constructor(cleanupIntervalMs?: number);
|
|
14
|
+
get(key: string): Promise<TokenBucket | null>;
|
|
15
|
+
set(key: string, value: TokenBucket, ttlMs: number): Promise<void>;
|
|
16
|
+
delete(key: string): Promise<void>;
|
|
17
|
+
clear(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Clean up expired entries
|
|
20
|
+
*/
|
|
21
|
+
private cleanup;
|
|
22
|
+
/**
|
|
23
|
+
* Dispose of resources
|
|
24
|
+
*/
|
|
25
|
+
dispose(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Get storage stats (for testing/monitoring)
|
|
28
|
+
*/
|
|
29
|
+
getStats(): {
|
|
30
|
+
size: number;
|
|
31
|
+
keys: string[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/security/rate-limiter/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAI/D;;GAEG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,KAAK,CAAgE;IAC7E,OAAO,CAAC,eAAe,CAA8B;gBAEzC,iBAAiB,SAAQ;IAO/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAa7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,OAAO,CAAC,OAAO;IAiBf;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;CAM7C"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Storage - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Storage implementations for rate limiting.
|
|
5
|
+
*/
|
|
6
|
+
import { createLogger } from '../../utils/logger.js';
|
|
7
|
+
const log = createLogger('RateLimiter');
|
|
8
|
+
/**
|
|
9
|
+
* In-memory storage implementation
|
|
10
|
+
*/
|
|
11
|
+
export class InMemoryRateLimitStorage {
|
|
12
|
+
store = new Map();
|
|
13
|
+
cleanupInterval = null;
|
|
14
|
+
constructor(cleanupIntervalMs = 60000) {
|
|
15
|
+
// Periodic cleanup of expired entries
|
|
16
|
+
this.cleanupInterval = setInterval(() => {
|
|
17
|
+
this.cleanup();
|
|
18
|
+
}, cleanupIntervalMs);
|
|
19
|
+
}
|
|
20
|
+
async get(key) {
|
|
21
|
+
const entry = this.store.get(key);
|
|
22
|
+
if (!entry)
|
|
23
|
+
return null;
|
|
24
|
+
// Check expiration
|
|
25
|
+
if (Date.now() > entry.expiresAt) {
|
|
26
|
+
this.store.delete(key);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return entry.bucket;
|
|
30
|
+
}
|
|
31
|
+
async set(key, value, ttlMs) {
|
|
32
|
+
this.store.set(key, {
|
|
33
|
+
bucket: value,
|
|
34
|
+
expiresAt: Date.now() + ttlMs,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async delete(key) {
|
|
38
|
+
this.store.delete(key);
|
|
39
|
+
}
|
|
40
|
+
async clear() {
|
|
41
|
+
this.store.clear();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Clean up expired entries
|
|
45
|
+
*/
|
|
46
|
+
cleanup() {
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
let cleaned = 0;
|
|
49
|
+
// Use Array.from to avoid downlevelIteration requirement
|
|
50
|
+
Array.from(this.store.entries()).forEach(([key, entry]) => {
|
|
51
|
+
if (now > entry.expiresAt) {
|
|
52
|
+
this.store.delete(key);
|
|
53
|
+
cleaned++;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (cleaned > 0) {
|
|
57
|
+
log.debug(`Cleaned up ${cleaned} expired rate limit entries`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Dispose of resources
|
|
62
|
+
*/
|
|
63
|
+
dispose() {
|
|
64
|
+
if (this.cleanupInterval) {
|
|
65
|
+
clearInterval(this.cleanupInterval);
|
|
66
|
+
this.cleanupInterval = null;
|
|
67
|
+
}
|
|
68
|
+
this.store.clear();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get storage stats (for testing/monitoring)
|
|
72
|
+
*/
|
|
73
|
+
getStats() {
|
|
74
|
+
return {
|
|
75
|
+
size: this.store.size,
|
|
76
|
+
keys: Array.from(this.store.keys()),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/security/rate-limiter/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGpD,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,CAAC,CAAA;AAEvC;;GAEG;AACH,MAAM,OAAO,wBAAwB;IAC3B,KAAK,GAAG,IAAI,GAAG,EAAsD,CAAA;IACrE,eAAe,GAA0B,IAAI,CAAA;IAErD,YAAY,iBAAiB,GAAG,KAAK;QACnC,sCAAsC;QACtC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC,EAAE,iBAAiB,CAAC,CAAA;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAEvB,mBAAmB;QACnB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACtB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,KAAK,CAAC,MAAM,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAkB,EAAE,KAAa;QACtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC9B,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED;;OAEG;IACK,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,OAAO,GAAG,CAAC,CAAA;QAEf,yDAAyD;QACzD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACxD,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBACtB,OAAO,EAAE,CAAA;YACX,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,GAAG,CAAC,KAAK,CAAC,cAAc,OAAO,6BAA6B,CAAC,CAAA;QAC/D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;YACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC7B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SACpC,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Bucket Core Logic - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Core token bucket algorithm implementation for rate limiting.
|
|
5
|
+
*/
|
|
6
|
+
import type { TokenBucket, RateLimitResult, RateLimitStorage } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for token bucket operations
|
|
9
|
+
*/
|
|
10
|
+
export interface TokenBucketConfig {
|
|
11
|
+
maxTokens: number;
|
|
12
|
+
refillRate: number;
|
|
13
|
+
windowMs: number;
|
|
14
|
+
keyPrefix: string;
|
|
15
|
+
failMode: 'open' | 'closed';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Try to consume tokens from a bucket (internal helper)
|
|
19
|
+
*
|
|
20
|
+
* @param storage - Storage for token buckets
|
|
21
|
+
* @param config - Token bucket configuration
|
|
22
|
+
* @param key - Rate limit key
|
|
23
|
+
* @param cost - Number of tokens to consume
|
|
24
|
+
* @returns Rate limit result
|
|
25
|
+
*/
|
|
26
|
+
export declare function tryConsumeToken(storage: RateLimitStorage, config: TokenBucketConfig, key: string, cost: number): Promise<RateLimitResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Get the current state of a token bucket
|
|
29
|
+
*
|
|
30
|
+
* @param storage - Storage for token buckets
|
|
31
|
+
* @param keyPrefix - Key prefix for storage
|
|
32
|
+
* @param key - Rate limit key
|
|
33
|
+
* @returns Current bucket state or null
|
|
34
|
+
*/
|
|
35
|
+
export declare function getTokenBucketState(storage: RateLimitStorage, keyPrefix: string, key: string): Promise<TokenBucket | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Reset a token bucket
|
|
38
|
+
*
|
|
39
|
+
* @param storage - Storage for token buckets
|
|
40
|
+
* @param keyPrefix - Key prefix for storage
|
|
41
|
+
* @param key - Rate limit key
|
|
42
|
+
*/
|
|
43
|
+
export declare function resetTokenBucket(storage: RateLimitStorage, keyPrefix: string, key: string): Promise<void>;
|
|
44
|
+
//# sourceMappingURL=token-bucket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-bucket.d.ts","sourceRoot":"","sources":["../../../../src/security/rate-limiter/token-bucket.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAEhF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAA;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,eAAe,CAAC,CAkE1B;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAG7B;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Bucket Core Logic - SMI-730, SMI-1189
|
|
3
|
+
*
|
|
4
|
+
* Core token bucket algorithm implementation for rate limiting.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Try to consume tokens from a bucket (internal helper)
|
|
8
|
+
*
|
|
9
|
+
* @param storage - Storage for token buckets
|
|
10
|
+
* @param config - Token bucket configuration
|
|
11
|
+
* @param key - Rate limit key
|
|
12
|
+
* @param cost - Number of tokens to consume
|
|
13
|
+
* @returns Rate limit result
|
|
14
|
+
*/
|
|
15
|
+
export async function tryConsumeToken(storage, config, key, cost) {
|
|
16
|
+
const storageKey = `${config.keyPrefix}:${key}`;
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
try {
|
|
19
|
+
let bucket = await storage.get(storageKey);
|
|
20
|
+
if (!bucket) {
|
|
21
|
+
bucket = {
|
|
22
|
+
tokens: config.maxTokens,
|
|
23
|
+
lastRefill: now,
|
|
24
|
+
firstRequest: now,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Refill tokens based on elapsed time
|
|
28
|
+
const elapsedMs = now - bucket.lastRefill;
|
|
29
|
+
const elapsedSeconds = elapsedMs / 1000;
|
|
30
|
+
const tokensToAdd = elapsedSeconds * config.refillRate;
|
|
31
|
+
if (tokensToAdd > 0) {
|
|
32
|
+
bucket.tokens = Math.min(config.maxTokens, bucket.tokens + tokensToAdd);
|
|
33
|
+
bucket.lastRefill = now;
|
|
34
|
+
}
|
|
35
|
+
// Check if we have enough tokens
|
|
36
|
+
const allowed = bucket.tokens >= cost;
|
|
37
|
+
if (allowed) {
|
|
38
|
+
bucket.tokens -= cost;
|
|
39
|
+
await storage.set(storageKey, bucket, config.windowMs);
|
|
40
|
+
return {
|
|
41
|
+
allowed: true,
|
|
42
|
+
remaining: Math.floor(bucket.tokens),
|
|
43
|
+
limit: config.maxTokens,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const tokensNeeded = cost - bucket.tokens;
|
|
48
|
+
const retryAfterMs = Math.ceil((tokensNeeded / config.refillRate) * 1000);
|
|
49
|
+
const resetAt = new Date(now + retryAfterMs).toISOString();
|
|
50
|
+
return {
|
|
51
|
+
allowed: false,
|
|
52
|
+
remaining: Math.floor(bucket.tokens),
|
|
53
|
+
limit: config.maxTokens,
|
|
54
|
+
retryAfterMs,
|
|
55
|
+
resetAt,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// On error, return based on fail mode
|
|
61
|
+
if (config.failMode === 'closed') {
|
|
62
|
+
return {
|
|
63
|
+
allowed: false,
|
|
64
|
+
remaining: 0,
|
|
65
|
+
limit: config.maxTokens,
|
|
66
|
+
retryAfterMs: config.windowMs,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
allowed: true,
|
|
71
|
+
remaining: config.maxTokens,
|
|
72
|
+
limit: config.maxTokens,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get the current state of a token bucket
|
|
78
|
+
*
|
|
79
|
+
* @param storage - Storage for token buckets
|
|
80
|
+
* @param keyPrefix - Key prefix for storage
|
|
81
|
+
* @param key - Rate limit key
|
|
82
|
+
* @returns Current bucket state or null
|
|
83
|
+
*/
|
|
84
|
+
export async function getTokenBucketState(storage, keyPrefix, key) {
|
|
85
|
+
const storageKey = `${keyPrefix}:${key}`;
|
|
86
|
+
return await storage.get(storageKey);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Reset a token bucket
|
|
90
|
+
*
|
|
91
|
+
* @param storage - Storage for token buckets
|
|
92
|
+
* @param keyPrefix - Key prefix for storage
|
|
93
|
+
* @param key - Rate limit key
|
|
94
|
+
*/
|
|
95
|
+
export async function resetTokenBucket(storage, keyPrefix, key) {
|
|
96
|
+
const storageKey = `${keyPrefix}:${key}`;
|
|
97
|
+
await storage.delete(storageKey);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=token-bucket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-bucket.js","sourceRoot":"","sources":["../../../../src/security/rate-limiter/token-bucket.ts"],"names":[],"mappings":"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"}
|