@skillsmith/core 0.5.3 → 0.5.4
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/CHANGELOG.md +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/activation/ActivationManager.d.ts +7 -0
- package/dist/src/activation/ActivationManager.d.ts.map +1 -1
- package/dist/src/activation/ActivationManager.js +13 -4
- package/dist/src/activation/ActivationManager.js.map +1 -1
- package/dist/src/analysis/adapters/python.d.ts +16 -11
- package/dist/src/analysis/adapters/python.d.ts.map +1 -1
- package/dist/src/analysis/adapters/python.js +46 -61
- package/dist/src/analysis/adapters/python.js.map +1 -1
- package/dist/src/analysis/router.test.d.ts +2 -0
- package/dist/src/analysis/router.test.d.ts.map +1 -0
- package/dist/src/analysis/router.test.js +411 -0
- package/dist/src/analysis/router.test.js.map +1 -0
- package/dist/src/analysis/tree-sitter/manager.d.ts.map +1 -1
- package/dist/src/analysis/tree-sitter/manager.js +12 -5
- package/dist/src/analysis/tree-sitter/manager.js.map +1 -1
- package/dist/src/analysis/tree-sitter/pythonExtractor.d.ts +45 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.js +264 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.js.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.test.d.ts +12 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.test.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.test.js +74 -0
- package/dist/src/analysis/tree-sitter/pythonExtractor.test.js.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts +93 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.d.ts +22 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js +229 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.js +287 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.js.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.test.d.ts +17 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.test.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.test.js +142 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.test.js.map +1 -0
- package/dist/src/analysis/tree-sitter/queries/python.d.ts +43 -0
- package/dist/src/analysis/tree-sitter/queries/python.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/queries/python.js +88 -0
- package/dist/src/analysis/tree-sitter/queries/python.js.map +1 -0
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.d.ts +13 -0
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.d.ts.map +1 -0
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js +174 -0
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js.map +1 -0
- package/dist/src/analytics/ROIDashboardService.csv.d.ts +11 -0
- package/dist/src/analytics/ROIDashboardService.csv.d.ts.map +1 -0
- package/dist/src/analytics/ROIDashboardService.csv.js +43 -0
- package/dist/src/analytics/ROIDashboardService.csv.js.map +1 -0
- package/dist/src/analytics/ROIDashboardService.d.ts +64 -3
- package/dist/src/analytics/ROIDashboardService.d.ts.map +1 -1
- package/dist/src/analytics/ROIDashboardService.js +116 -45
- package/dist/src/analytics/ROIDashboardService.js.map +1 -1
- package/dist/src/api/schemas.d.ts +70 -319
- package/dist/src/api/schemas.d.ts.map +1 -1
- package/dist/src/benchmarks/incrementalParseBenchmark.d.ts +18 -0
- package/dist/src/benchmarks/incrementalParseBenchmark.d.ts.map +1 -0
- package/dist/src/benchmarks/incrementalParseBenchmark.js +121 -0
- package/dist/src/benchmarks/incrementalParseBenchmark.js.map +1 -0
- package/dist/src/billing/GDPRComplianceService.test.d.ts +2 -0
- package/dist/src/billing/GDPRComplianceService.test.d.ts.map +1 -0
- package/dist/src/billing/GDPRComplianceService.test.js +405 -0
- package/dist/src/billing/GDPRComplianceService.test.js.map +1 -0
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/SkillParser.coverage.test.d.ts +10 -0
- package/dist/src/indexer/SkillParser.coverage.test.d.ts.map +1 -0
- package/dist/src/indexer/SkillParser.coverage.test.js +76 -0
- package/dist/src/indexer/SkillParser.coverage.test.js.map +1 -0
- package/dist/src/indexer/SkillParser.test.d.ts +2 -0
- package/dist/src/indexer/SkillParser.test.d.ts.map +1 -0
- package/dist/src/indexer/SkillParser.test.js +375 -0
- package/dist/src/indexer/SkillParser.test.js.map +1 -0
- package/dist/src/scripts/validation/types.d.ts +14 -24
- package/dist/src/scripts/validation/types.d.ts.map +1 -1
- package/dist/src/services/skill-config-schema.d.ts +4 -36
- package/dist/src/services/skill-config-schema.d.ts.map +1 -1
- package/dist/src/sources/LocalFilesystemAdapter.d.ts +104 -10
- package/dist/src/sources/LocalFilesystemAdapter.d.ts.map +1 -1
- package/dist/src/sources/LocalFilesystemAdapter.helpers.d.ts +92 -0
- package/dist/src/sources/LocalFilesystemAdapter.helpers.d.ts.map +1 -0
- package/dist/src/sources/LocalFilesystemAdapter.helpers.js +157 -0
- package/dist/src/sources/LocalFilesystemAdapter.helpers.js.map +1 -0
- package/dist/src/sources/LocalFilesystemAdapter.js +218 -159
- package/dist/src/sources/LocalFilesystemAdapter.js.map +1 -1
- package/dist/src/sources/LocalFilesystemAdapter.scan.d.ts +78 -0
- package/dist/src/sources/LocalFilesystemAdapter.scan.d.ts.map +1 -0
- package/dist/src/sources/LocalFilesystemAdapter.scan.js +118 -0
- package/dist/src/sources/LocalFilesystemAdapter.scan.js.map +1 -0
- package/dist/src/sources/index.d.ts +1 -1
- package/dist/src/sources/index.d.ts.map +1 -1
- package/dist/src/sources/index.js.map +1 -1
- package/dist/src/sources/types.d.ts +28 -0
- package/dist/src/sources/types.d.ts.map +1 -1
- package/dist/src/telemetry/tracer-imports.d.ts +13 -0
- package/dist/src/telemetry/tracer-imports.d.ts.map +1 -0
- package/dist/src/telemetry/tracer-imports.js +26 -0
- package/dist/src/telemetry/tracer-imports.js.map +1 -0
- package/dist/src/telemetry/tracer.d.ts.map +1 -1
- package/dist/src/telemetry/tracer.js +18 -21
- package/dist/src/telemetry/tracer.js.map +1 -1
- package/dist/src/utils/rate-limit.d.ts +39 -0
- package/dist/src/utils/rate-limit.d.ts.map +1 -0
- package/dist/src/utils/rate-limit.js +48 -0
- package/dist/src/utils/rate-limit.js.map +1 -0
- package/dist/src/utils/rate-limit.test.d.ts +11 -0
- package/dist/src/utils/rate-limit.test.d.ts.map +1 -0
- package/dist/src/utils/rate-limit.test.js +86 -0
- package/dist/src/utils/rate-limit.test.js.map +1 -0
- package/dist/src/webhooks/WebhookDeadLetterRepository.d.ts +178 -0
- package/dist/src/webhooks/WebhookDeadLetterRepository.d.ts.map +1 -0
- package/dist/src/webhooks/WebhookDeadLetterRepository.js +196 -0
- package/dist/src/webhooks/WebhookDeadLetterRepository.js.map +1 -0
- package/dist/src/webhooks/WebhookQueue.d.ts +1 -0
- package/dist/src/webhooks/WebhookQueue.d.ts.map +1 -1
- package/dist/src/webhooks/WebhookQueue.js +19 -0
- package/dist/src/webhooks/WebhookQueue.js.map +1 -1
- package/dist/src/webhooks/WebhookQueue.types.d.ts +11 -0
- package/dist/src/webhooks/WebhookQueue.types.d.ts.map +1 -1
- package/dist/src/webhooks/index.d.ts +1 -0
- package/dist/src/webhooks/index.d.ts.map +1 -1
- package/dist/src/webhooks/index.js +2 -0
- package/dist/src/webhooks/index.js.map +1 -1
- package/dist/src/webhooks/webhook-schemas.d.ts +117 -1212
- package/dist/src/webhooks/webhook-schemas.d.ts.map +1 -1
- package/dist/tests/ActivationManager.test.d.ts +13 -0
- package/dist/tests/ActivationManager.test.d.ts.map +1 -0
- package/dist/tests/ActivationManager.test.js +218 -0
- package/dist/tests/ActivationManager.test.js.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.coverage.test.d.ts +13 -0
- package/dist/tests/LocalFilesystemAdapter.coverage.test.d.ts.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.coverage.test.js +314 -0
- package/dist/tests/LocalFilesystemAdapter.coverage.test.js.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.security.test.d.ts +18 -0
- package/dist/tests/LocalFilesystemAdapter.security.test.d.ts.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.security.test.js +344 -0
- package/dist/tests/LocalFilesystemAdapter.security.test.js.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.test.d.ts +12 -0
- package/dist/tests/LocalFilesystemAdapter.test.d.ts.map +1 -0
- package/dist/tests/LocalFilesystemAdapter.test.js +301 -0
- package/dist/tests/LocalFilesystemAdapter.test.js.map +1 -0
- package/dist/tests/ROIDashboardService.coverage.test.d.ts +9 -0
- package/dist/tests/ROIDashboardService.coverage.test.d.ts.map +1 -0
- package/dist/tests/ROIDashboardService.coverage.test.js +118 -0
- package/dist/tests/ROIDashboardService.coverage.test.js.map +1 -0
- package/dist/tests/ROIDashboardService.test.js +87 -0
- package/dist/tests/ROIDashboardService.test.js.map +1 -1
- package/dist/tests/ScraperAdapters.gitlab-coverage.test.d.ts +14 -0
- package/dist/tests/ScraperAdapters.gitlab-coverage.test.d.ts.map +1 -0
- package/dist/tests/ScraperAdapters.gitlab-coverage.test.js +169 -0
- package/dist/tests/ScraperAdapters.gitlab-coverage.test.js.map +1 -0
- package/dist/tests/ScraperAdapters.test.d.ts +5 -1
- package/dist/tests/ScraperAdapters.test.d.ts.map +1 -1
- package/dist/tests/ScraperAdapters.test.js +6 -336
- package/dist/tests/ScraperAdapters.test.js.map +1 -1
- package/dist/tests/WebhookDeadLetterRepository.test.d.ts +2 -0
- package/dist/tests/WebhookDeadLetterRepository.test.d.ts.map +1 -0
- package/dist/tests/WebhookDeadLetterRepository.test.js +333 -0
- package/dist/tests/WebhookDeadLetterRepository.test.js.map +1 -0
- package/dist/tests/WebhookHandler.test.js +93 -1
- package/dist/tests/WebhookHandler.test.js.map +1 -1
- package/dist/tests/WebhookQueue.coverage.test.d.ts +19 -0
- package/dist/tests/WebhookQueue.coverage.test.d.ts.map +1 -0
- package/dist/tests/WebhookQueue.coverage.test.js +190 -0
- package/dist/tests/WebhookQueue.coverage.test.js.map +1 -0
- package/dist/tests/billing/GDPRCompliance.test.d.ts +2 -2
- package/dist/tests/billing/GDPRCompliance.test.js +221 -36
- package/dist/tests/billing/GDPRCompliance.test.js.map +1 -1
- package/dist/tests/telemetry.test.js +126 -0
- package/dist/tests/telemetry.test.js.map +1 -1
- package/dist/tests/webhooks/WebhookDeadLetterRepository.test.d.ts +10 -0
- package/dist/tests/webhooks/WebhookDeadLetterRepository.test.d.ts.map +1 -0
- package/dist/tests/webhooks/WebhookDeadLetterRepository.test.js +109 -0
- package/dist/tests/webhooks/WebhookDeadLetterRepository.test.js.map +1 -0
- package/package.json +8 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalFilesystemAdapter scan loop (SMI-4287, SMI-4319)
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `LocalFilesystemAdapter.ts` to keep the main adapter file
|
|
5
|
+
* under the 500-line governance ceiling. Pure function of its inputs — no
|
|
6
|
+
* shared instance state other than the `warnings` sink.
|
|
7
|
+
*
|
|
8
|
+
* SMI-4319: tracks visited directory realpaths in a per-scan `Set<string>`
|
|
9
|
+
* so mutually-recursive symlinks (A→B, B→A) are detected and skipped with a
|
|
10
|
+
* `loop` warning. Each `scanDirectoryRecursive` invocation checks the set
|
|
11
|
+
* BEFORE recursing; the set is keyed on the raw realpath (no
|
|
12
|
+
* `normaliseForFs`) so legitimate case-sensitive distinctions are preserved.
|
|
13
|
+
* Loop detection runs regardless of `allowSymlinksOutsideRoot` — loops are a
|
|
14
|
+
* correctness issue (infinite work), not a security issue.
|
|
15
|
+
*/
|
|
16
|
+
import { join, relative, dirname } from 'path';
|
|
17
|
+
import { safeFs, resolveSafeRealpath } from './LocalFilesystemAdapter.helpers.js';
|
|
18
|
+
/**
|
|
19
|
+
* File names that identify a skill definition.
|
|
20
|
+
*/
|
|
21
|
+
export const SKILL_FILE_NAMES = ['SKILL.md', 'skill.md'];
|
|
22
|
+
/**
|
|
23
|
+
* Recursively scan `dirPath` for `SKILL.md` files, populating
|
|
24
|
+
* `options.discovered` and `options.warnings` in place.
|
|
25
|
+
*
|
|
26
|
+
* SMI-4287: all filesystem access routes through `safeFs`. Per-entry errors
|
|
27
|
+
* are recorded on `warnings` and the scan continues for siblings.
|
|
28
|
+
*
|
|
29
|
+
* SMI-4319: before descending, realpath `dirPath` and check
|
|
30
|
+
* `options.visitedRealpaths` for a prior visit. On hit, push a `loop` warning
|
|
31
|
+
* and return — prevents A↔B / self-loop directory symlinks from wasting
|
|
32
|
+
* `maxDepth` traversals and surfacing the same SKILL.md under multiple
|
|
33
|
+
* lexical paths. Realpath errors (permission, ENOENT, ELOOP on the dir
|
|
34
|
+
* itself) are recorded and the subtree is skipped.
|
|
35
|
+
*/
|
|
36
|
+
export async function scanDirectoryRecursive(dirPath, depth, options) {
|
|
37
|
+
if (depth > options.maxDepth)
|
|
38
|
+
return;
|
|
39
|
+
// SMI-4319: loop detection runs before readdir so we short-circuit on a
|
|
40
|
+
// repeat directory even if the prior visit populated `discovered`.
|
|
41
|
+
const realDirResult = await safeFs.realpath(dirPath);
|
|
42
|
+
if (!realDirResult.ok) {
|
|
43
|
+
options.warnings.push(realDirResult.error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const realDir = realDirResult.value;
|
|
47
|
+
if (options.visitedRealpaths.has(realDir)) {
|
|
48
|
+
options.warnings.push({
|
|
49
|
+
code: 'loop',
|
|
50
|
+
path: dirPath,
|
|
51
|
+
message: `Symlink loop detected: ${dirPath} resolves to already-visited ${realDir}`,
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
options.visitedRealpaths.add(realDir);
|
|
56
|
+
const dirResult = await safeFs.readdir(dirPath);
|
|
57
|
+
if (!dirResult.ok) {
|
|
58
|
+
if (dirResult.error.code === 'permission') {
|
|
59
|
+
options.log.debug(`Skipping ${dirPath}: ${dirResult.error.message}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
options.log.warn(`Error scanning directory ${dirPath}: ${dirResult.error.message}`);
|
|
63
|
+
}
|
|
64
|
+
options.warnings.push(dirResult.error);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const entry of dirResult.value) {
|
|
68
|
+
const fullPath = join(dirPath, entry.name);
|
|
69
|
+
if (options.isExcluded(entry.name))
|
|
70
|
+
continue;
|
|
71
|
+
let isDirectory = entry.isDirectory();
|
|
72
|
+
let isFile = entry.isFile();
|
|
73
|
+
if (entry.isSymbolicLink()) {
|
|
74
|
+
if (!options.followSymlinks)
|
|
75
|
+
continue;
|
|
76
|
+
const resolvedResult = await resolveSafeRealpath(fullPath, options.rootDir, {
|
|
77
|
+
allowSymlinksOutsideRoot: options.allowSymlinksOutsideRoot,
|
|
78
|
+
});
|
|
79
|
+
if (!resolvedResult.ok) {
|
|
80
|
+
options.warnings.push(resolvedResult.error);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const statResult = await safeFs.stat(fullPath);
|
|
84
|
+
if (!statResult.ok) {
|
|
85
|
+
// ENOENT on a symlink = broken link; quietly skip (pre-existing
|
|
86
|
+
// behaviour). Other errors (loop, permission) are recorded.
|
|
87
|
+
if (statResult.error.code !== 'not-found') {
|
|
88
|
+
options.warnings.push(statResult.error);
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
isDirectory = statResult.value.isDirectory();
|
|
93
|
+
isFile = statResult.value.isFile();
|
|
94
|
+
}
|
|
95
|
+
if (isFile && SKILL_FILE_NAMES.includes(entry.name)) {
|
|
96
|
+
const statResult = await safeFs.stat(fullPath);
|
|
97
|
+
if (!statResult.ok) {
|
|
98
|
+
options.warnings.push(statResult.error);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const stats = statResult.value;
|
|
102
|
+
options.discovered.push({
|
|
103
|
+
path: fullPath,
|
|
104
|
+
relativePath: relative(options.rootDir, fullPath),
|
|
105
|
+
directory: dirname(fullPath),
|
|
106
|
+
stats: {
|
|
107
|
+
size: stats.size,
|
|
108
|
+
mtime: stats.mtime,
|
|
109
|
+
ctime: stats.ctime,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (isDirectory) {
|
|
114
|
+
await scanDirectoryRecursive(fullPath, depth + 1, options);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=LocalFilesystemAdapter.scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalFilesystemAdapter.scan.js","sourceRoot":"","sources":["../../../src/sources/LocalFilesystemAdapter.scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*
|
|
33
33
|
* @module sources
|
|
34
34
|
*/
|
|
35
|
-
export type { SourceType, SourceConfig, RateLimitConfig, SourceAuthConfig, SourceLocation, SourceRepository, SkillContent, SourceSearchOptions, SourceSearchResult, SkillIndexResult, BatchIndexResult, SourceHealth, } from './types.js';
|
|
35
|
+
export type { SourceType, SourceConfig, RateLimitConfig, SourceAuthConfig, SourceLocation, SourceRepository, SkillContent, SourceSearchOptions, SourceSearchResult, SkillIndexResult, BatchIndexResult, SourceHealth, AdapterError, } from './types.js';
|
|
36
36
|
export { type ISourceAdapter, isSourceAdapter } from './ISourceAdapter.js';
|
|
37
37
|
export { BaseSourceAdapter, type ExtendedSourceConfig } from './BaseSourceAdapter.js';
|
|
38
38
|
export { GitHubSourceAdapter, createGitHubAdapter } from './GitHubSourceAdapter.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,YAAY,EACV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG1E,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAGrF,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAGnF,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,aAAa,GACnB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,YAAY,EACV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG1E,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAGrF,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAGnF,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,aAAa,GACnB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAmBH,aAAa;AACb,OAAO,EAAuB,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1E,aAAa;AACb,OAAO,EAAE,iBAAiB,EAA6B,MAAM,wBAAwB,CAAA;AAErF,2BAA2B;AAC3B,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEnF,6BAA6B;AAC7B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GAGpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAE7B,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GAEpB,MAAM,0BAA0B,CAAA;AAEjC,WAAW;AACX,OAAO,EACL,qBAAqB,EACrB,eAAe,GAGhB,MAAM,4BAA4B,CAAA;AAEnC,UAAU;AACV,OAAO,EACL,aAAa,GAKd,MAAM,oBAAoB,CAAA;AAE3B,6BAA6B;AAC7B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,GAElB,MAAM,aAAa,CAAA"}
|
|
@@ -131,6 +131,28 @@ export interface SourceSearchOptions {
|
|
|
131
131
|
/** Additional filters */
|
|
132
132
|
filters?: Record<string, unknown>;
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Non-fatal adapter error surfaced to the caller via SourceSearchResult.warnings
|
|
136
|
+
*
|
|
137
|
+
* SMI-4287: Introduced to let adapters continue scanning after permission /
|
|
138
|
+
* symlink / loop failures on individual paths instead of throwing.
|
|
139
|
+
*
|
|
140
|
+
* - `permission` — EACCES or EPERM reading a path
|
|
141
|
+
* - `not-found` — ENOENT on a path that should exist (e.g. broken symlink)
|
|
142
|
+
* - `io` — Other filesystem errors (EIO, EMFILE, etc.)
|
|
143
|
+
* - `loop` — ELOOP from circular symlinks
|
|
144
|
+
* - `symlink-escape` — Symlink resolved outside the adapter's root directory
|
|
145
|
+
*/
|
|
146
|
+
export interface AdapterError {
|
|
147
|
+
/** Machine-readable error category */
|
|
148
|
+
code: 'permission' | 'not-found' | 'io' | 'loop' | 'symlink-escape';
|
|
149
|
+
/** Path (or best-effort identifier) that triggered the error */
|
|
150
|
+
path: string;
|
|
151
|
+
/** Human-readable message */
|
|
152
|
+
message: string;
|
|
153
|
+
/** Underlying error for debugging (not serialised) */
|
|
154
|
+
cause?: unknown;
|
|
155
|
+
}
|
|
134
156
|
/**
|
|
135
157
|
* Result of a search operation
|
|
136
158
|
*/
|
|
@@ -143,6 +165,12 @@ export interface SourceSearchResult {
|
|
|
143
165
|
hasMore: boolean;
|
|
144
166
|
/** Cursor for next page (if applicable) */
|
|
145
167
|
nextCursor?: string;
|
|
168
|
+
/**
|
|
169
|
+
* Non-fatal errors encountered during the scan (SMI-4287).
|
|
170
|
+
* Adapters surface `AdapterError` entries here instead of throwing, so the
|
|
171
|
+
* caller can continue processing successful results.
|
|
172
|
+
*/
|
|
173
|
+
warnings?: AdapterError[];
|
|
146
174
|
}
|
|
147
175
|
/**
|
|
148
176
|
* Result of indexing a single skill
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sources/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sources/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4250: Extracted dynamic import + instrumentation registry for tracer.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so tests can `vi.mock` the import surface without
|
|
5
|
+
* having to mock all of tracer.ts. The class registry encodes which OTel
|
|
6
|
+
* instrumentation packages tracer.ts attempts to load on init; each entry
|
|
7
|
+
* is optional at runtime and silently skipped if the package isn't installed
|
|
8
|
+
* (e.g. `instrumentation-aws-sdk` only loads when `@skillsmith/enterprise`
|
|
9
|
+
* is present in the consuming install).
|
|
10
|
+
*/
|
|
11
|
+
export declare function dynamicImport(moduleName: string): Promise<unknown>;
|
|
12
|
+
export declare const INSTRUMENTATION_PACKAGES: ReadonlyArray<readonly [string, string]>;
|
|
13
|
+
//# sourceMappingURL=tracer-imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer-imports.d.ts","sourceRoot":"","sources":["../../../src/telemetry/tracer-imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAED,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAKpE,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4250: Extracted dynamic import + instrumentation registry for tracer.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so tests can `vi.mock` the import surface without
|
|
5
|
+
* having to mock all of tracer.ts. The class registry encodes which OTel
|
|
6
|
+
* instrumentation packages tracer.ts attempts to load on init; each entry
|
|
7
|
+
* is optional at runtime and silently skipped if the package isn't installed
|
|
8
|
+
* (e.g. `instrumentation-aws-sdk` only loads when `@skillsmith/enterprise`
|
|
9
|
+
* is present in the consuming install).
|
|
10
|
+
*/
|
|
11
|
+
export async function dynamicImport(moduleName) {
|
|
12
|
+
try {
|
|
13
|
+
const importFn = new Function('m', 'return import(m)');
|
|
14
|
+
return await importFn(moduleName);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export const INSTRUMENTATION_PACKAGES = [
|
|
21
|
+
['@opentelemetry/instrumentation-http', 'HttpInstrumentation'],
|
|
22
|
+
['@opentelemetry/instrumentation-undici', 'UndiciInstrumentation'],
|
|
23
|
+
['@opentelemetry/instrumentation-runtime-node', 'RuntimeNodeInstrumentation'],
|
|
24
|
+
['@opentelemetry/instrumentation-aws-sdk', 'AwsInstrumentation'],
|
|
25
|
+
];
|
|
26
|
+
//# sourceMappingURL=tracer-imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer-imports.js","sourceRoot":"","sources":["../../../src/telemetry/tracer-imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAoC,CAAA;QACzF,OAAO,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAA6C;IAChF,CAAC,qCAAqC,EAAE,qBAAqB,CAAC;IAC9D,CAAC,uCAAuC,EAAE,uBAAuB,CAAC;IAClE,CAAC,6CAA6C,EAAE,4BAA4B,CAAC;IAC7E,CAAC,wCAAwC,EAAE,oBAAoB,CAAC;CACxD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/telemetry/tracer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,IAAI,EACJ,MAAM,EACN,WAAW,EACX,OAAO,EACP,WAAW,EACX,0BAA0B,GAC3B,MAAM,mBAAmB,CAAA;AAG1B,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EAKZ,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/telemetry/tracer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,IAAI,EACJ,MAAM,EACN,WAAW,EACX,OAAO,EACP,WAAW,EACX,0BAA0B,GAC3B,MAAM,mBAAmB,CAAA;AAG1B,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EAKZ,MAAM,mBAAmB,CAAA;AAgC1B;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAAqE;gBAE5E,MAAM,GAAE,YAAiB;IAwB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmFjC,SAAS,IAAI,OAAO;IAIpB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW;IAMrD,QAAQ,CAAC,CAAC,EACd,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACrC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC;IAeb,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC;IAerF,cAAc,IAAI,WAAW;IAQvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAQhC;AAKD,wBAAgB,SAAS,IAAI,gBAAgB,CAG5C;AAED,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAKxF;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAKrD;AAED,wBAAgB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,IACrB,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EACjE,QAAQ,OAAO,EACf,aAAa,MAAM,EACnB,YAAY,uBAAuB,CAAC,CAAC,CAAC,KACrC,uBAAuB,CAAC,CAAC,CAAC,CAkB9B"}
|
|
@@ -8,21 +8,13 @@
|
|
|
8
8
|
* @see span-utils.ts for span wrapper classes
|
|
9
9
|
*/
|
|
10
10
|
import { NoOpSpanWrapper, ActiveSpanWrapper } from './span-utils.js';
|
|
11
|
+
import { dynamicImport, INSTRUMENTATION_PACKAGES } from './tracer-imports.js';
|
|
11
12
|
// Lazy import to avoid loading OTEL if not needed
|
|
12
13
|
let api = null;
|
|
13
14
|
let sdk = null;
|
|
14
15
|
let resources = null;
|
|
15
16
|
let semanticConventions = null;
|
|
16
17
|
let otelAvailable = null;
|
|
17
|
-
async function dynamicImport(moduleName) {
|
|
18
|
-
try {
|
|
19
|
-
const importFn = new Function('m', 'return import(m)');
|
|
20
|
-
return await importFn(moduleName);
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
18
|
async function checkOTelAvailability() {
|
|
27
19
|
if (otelAvailable !== null)
|
|
28
20
|
return otelAvailable;
|
|
@@ -113,20 +105,25 @@ export class SkillsmithTracer {
|
|
|
113
105
|
[otelSemConv['ATTR_SERVICE_VERSION'] ?? 'service.version']: '0.1.0',
|
|
114
106
|
});
|
|
115
107
|
if (this.config.autoInstrument) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
108
|
+
// SMI-4250: explicit per-package instrumentation registration replaces
|
|
109
|
+
// the @opentelemetry/auto-instrumentations-node bundle (which transitively
|
|
110
|
+
// pinned @opentelemetry/core@2.5.0 across ~40 packages and blocked otel
|
|
111
|
+
// upgrades). Each entry is optional at runtime: aws-sdk only loads when
|
|
112
|
+
// @skillsmith/enterprise is in the consuming install. Registry lives in
|
|
113
|
+
// tracer-imports.ts so tests can mock the import surface.
|
|
114
|
+
const instrumentations = [];
|
|
115
|
+
for (const [pkgName, exportName] of INSTRUMENTATION_PACKAGES) {
|
|
116
|
+
const mod = (await dynamicImport(pkgName));
|
|
117
|
+
if (mod && typeof mod[exportName] === 'function') {
|
|
118
|
+
const InstrumentationClass = mod[exportName];
|
|
119
|
+
instrumentations.push(new InstrumentationClass());
|
|
120
|
+
}
|
|
121
|
+
else if (process.env.OTEL_LOG_LEVEL === 'debug') {
|
|
122
|
+
console.debug(`[Skillsmith Telemetry] Instrumentation ${pkgName} not installed; skipping.`);
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
if (instrumentations.length > 0) {
|
|
126
|
+
sdkConfig.instrumentations = instrumentations;
|
|
130
127
|
}
|
|
131
128
|
}
|
|
132
129
|
const NodeSDK = otelSdk.NodeSDK;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../../src/telemetry/tracer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0BH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../../src/telemetry/tracer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Utility (SMI-4316)
|
|
3
|
+
*
|
|
4
|
+
* Token-bucket style rate limiter intended for gating log output. First N
|
|
5
|
+
* events per window fire unconditionally; after that, one-in-`SAMPLE_EVERY`
|
|
6
|
+
* is allowed through. Windows reset automatically once `WINDOW_MS` elapses
|
|
7
|
+
* since the first event in the window.
|
|
8
|
+
*
|
|
9
|
+
* Keyed: callers pass a stable string key (e.g. file path or error
|
|
10
|
+
* signature). Different keys are isolated — a flood on key A does not
|
|
11
|
+
* starve key B.
|
|
12
|
+
*
|
|
13
|
+
* Intended for observability, not security-sensitive throttling.
|
|
14
|
+
*/
|
|
15
|
+
type Key = string;
|
|
16
|
+
/** Window length for a single bucket (1 hour). */
|
|
17
|
+
export declare const WINDOW_MS: number;
|
|
18
|
+
/** First N events per window always pass through. */
|
|
19
|
+
export declare const FIRST_N = 5;
|
|
20
|
+
/** After the first N, every Nth subsequent event passes through. */
|
|
21
|
+
export declare const SAMPLE_EVERY = 100;
|
|
22
|
+
/**
|
|
23
|
+
* Return `true` if the event for `key` should be allowed through
|
|
24
|
+
* (logged / processed), or `false` if it is suppressed by the limiter.
|
|
25
|
+
*
|
|
26
|
+
* The first `FIRST_N` events in a window always return `true`. After that,
|
|
27
|
+
* one-in-`SAMPLE_EVERY` events return `true` until the window rolls over.
|
|
28
|
+
*
|
|
29
|
+
* @param key - Stable grouping key (per-file, per-error, etc.)
|
|
30
|
+
* @param now - Optional timestamp override for tests (defaults to Date.now()).
|
|
31
|
+
*/
|
|
32
|
+
export declare function rateLimited(key: Key, now?: number): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Reset all buckets. Intended for tests; callers in production should not
|
|
35
|
+
* need this.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resetRateLimiter(): void;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/utils/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,KAAK,GAAG,GAAG,MAAM,CAAA;AASjB,kDAAkD;AAClD,eAAO,MAAM,SAAS,QAAiB,CAAA;AAEvC,qDAAqD;AACrD,eAAO,MAAM,OAAO,IAAI,CAAA;AAExB,oEAAoE;AACpE,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CASvE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Utility (SMI-4316)
|
|
3
|
+
*
|
|
4
|
+
* Token-bucket style rate limiter intended for gating log output. First N
|
|
5
|
+
* events per window fire unconditionally; after that, one-in-`SAMPLE_EVERY`
|
|
6
|
+
* is allowed through. Windows reset automatically once `WINDOW_MS` elapses
|
|
7
|
+
* since the first event in the window.
|
|
8
|
+
*
|
|
9
|
+
* Keyed: callers pass a stable string key (e.g. file path or error
|
|
10
|
+
* signature). Different keys are isolated — a flood on key A does not
|
|
11
|
+
* starve key B.
|
|
12
|
+
*
|
|
13
|
+
* Intended for observability, not security-sensitive throttling.
|
|
14
|
+
*/
|
|
15
|
+
const BUCKETS = new Map();
|
|
16
|
+
/** Window length for a single bucket (1 hour). */
|
|
17
|
+
export const WINDOW_MS = 60 * 60 * 1000;
|
|
18
|
+
/** First N events per window always pass through. */
|
|
19
|
+
export const FIRST_N = 5;
|
|
20
|
+
/** After the first N, every Nth subsequent event passes through. */
|
|
21
|
+
export const SAMPLE_EVERY = 100;
|
|
22
|
+
/**
|
|
23
|
+
* Return `true` if the event for `key` should be allowed through
|
|
24
|
+
* (logged / processed), or `false` if it is suppressed by the limiter.
|
|
25
|
+
*
|
|
26
|
+
* The first `FIRST_N` events in a window always return `true`. After that,
|
|
27
|
+
* one-in-`SAMPLE_EVERY` events return `true` until the window rolls over.
|
|
28
|
+
*
|
|
29
|
+
* @param key - Stable grouping key (per-file, per-error, etc.)
|
|
30
|
+
* @param now - Optional timestamp override for tests (defaults to Date.now()).
|
|
31
|
+
*/
|
|
32
|
+
export function rateLimited(key, now = Date.now()) {
|
|
33
|
+
const existing = BUCKETS.get(key);
|
|
34
|
+
const bucket = existing && now - existing.windowStart <= WINDOW_MS ? existing : { count: 0, windowStart: now };
|
|
35
|
+
bucket.count += 1;
|
|
36
|
+
BUCKETS.set(key, bucket);
|
|
37
|
+
if (bucket.count <= FIRST_N)
|
|
38
|
+
return true;
|
|
39
|
+
return (bucket.count - FIRST_N) % SAMPLE_EVERY === 1;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Reset all buckets. Intended for tests; callers in production should not
|
|
43
|
+
* need this.
|
|
44
|
+
*/
|
|
45
|
+
export function resetRateLimiter() {
|
|
46
|
+
BUCKETS.clear();
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../../src/utils/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAA;AAE3C,kDAAkD;AAClD,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEvC,qDAAqD;AACrD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAA;AAExB,oEAAoE;AACpE,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;AAE/B;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,MAAM,GACV,QAAQ,IAAI,GAAG,GAAG,QAAQ,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAA;IACjG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAA;IACjB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAExB,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO;QAAE,OAAO,IAAI,CAAA;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,YAAY,KAAK,CAAC,CAAA;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,KAAK,EAAE,CAAA;AACjB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4316: rateLimited() unit tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* 1. First-N events (<= FIRST_N) always return true.
|
|
6
|
+
* 2. Sampled-after-N events follow the 1-in-SAMPLE_EVERY cadence.
|
|
7
|
+
* 3. Per-key isolation (one key's flood does not starve another key).
|
|
8
|
+
* 4. Window rollover when `now` advances beyond WINDOW_MS.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=rate-limit.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.test.d.ts","sourceRoot":"","sources":["../../../src/utils/rate-limit.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4316: rateLimited() unit tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* 1. First-N events (<= FIRST_N) always return true.
|
|
6
|
+
* 2. Sampled-after-N events follow the 1-in-SAMPLE_EVERY cadence.
|
|
7
|
+
* 3. Per-key isolation (one key's flood does not starve another key).
|
|
8
|
+
* 4. Window rollover when `now` advances beyond WINDOW_MS.
|
|
9
|
+
*/
|
|
10
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
11
|
+
import { FIRST_N, SAMPLE_EVERY, WINDOW_MS, rateLimited, resetRateLimiter } from './rate-limit.js';
|
|
12
|
+
describe('rateLimited', () => {
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
resetRateLimiter();
|
|
15
|
+
});
|
|
16
|
+
it('allows the first FIRST_N calls for a key', () => {
|
|
17
|
+
const results = [];
|
|
18
|
+
for (let i = 0; i < FIRST_N; i += 1) {
|
|
19
|
+
results.push(rateLimited('k1'));
|
|
20
|
+
}
|
|
21
|
+
expect(results.every((r) => r === true)).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('after FIRST_N, allows one-in-SAMPLE_EVERY', () => {
|
|
24
|
+
// Burn the first N allowed events.
|
|
25
|
+
for (let i = 0; i < FIRST_N; i += 1)
|
|
26
|
+
rateLimited('k2');
|
|
27
|
+
// Next 2 * SAMPLE_EVERY events should produce exactly 2 allowed.
|
|
28
|
+
let allowed = 0;
|
|
29
|
+
for (let i = 0; i < 2 * SAMPLE_EVERY; i += 1) {
|
|
30
|
+
if (rateLimited('k2'))
|
|
31
|
+
allowed += 1;
|
|
32
|
+
}
|
|
33
|
+
expect(allowed).toBe(2);
|
|
34
|
+
});
|
|
35
|
+
it('matches the plan count: 5 firsts + 200 sampled = 7 total allowed', () => {
|
|
36
|
+
// Mirrors the acceptance test described in the plan.
|
|
37
|
+
let allowed = 0;
|
|
38
|
+
for (let i = 0; i < FIRST_N; i += 1) {
|
|
39
|
+
if (rateLimited('k3'))
|
|
40
|
+
allowed += 1;
|
|
41
|
+
}
|
|
42
|
+
for (let i = 0; i < 200; i += 1) {
|
|
43
|
+
if (rateLimited('k3'))
|
|
44
|
+
allowed += 1;
|
|
45
|
+
}
|
|
46
|
+
expect(allowed).toBe(FIRST_N + 2);
|
|
47
|
+
});
|
|
48
|
+
it('isolates per-key: flooding one key does not starve another', () => {
|
|
49
|
+
// Flood key A well past FIRST_N.
|
|
50
|
+
for (let i = 0; i < FIRST_N * 3; i += 1)
|
|
51
|
+
rateLimited('A');
|
|
52
|
+
// Key B still gets its full FIRST_N window.
|
|
53
|
+
let bAllowed = 0;
|
|
54
|
+
for (let i = 0; i < FIRST_N; i += 1) {
|
|
55
|
+
if (rateLimited('B'))
|
|
56
|
+
bAllowed += 1;
|
|
57
|
+
}
|
|
58
|
+
expect(bAllowed).toBe(FIRST_N);
|
|
59
|
+
});
|
|
60
|
+
it('resets the bucket when the window elapses', () => {
|
|
61
|
+
const t0 = 1_000_000;
|
|
62
|
+
// Exhaust first window at t0.
|
|
63
|
+
for (let i = 0; i < FIRST_N; i += 1)
|
|
64
|
+
rateLimited('win', t0);
|
|
65
|
+
// Next event at t0 is the first sampled hit (count-FIRST_N === 1),
|
|
66
|
+
// so it passes. Step past that so the next is definitely suppressed.
|
|
67
|
+
rateLimited('win', t0);
|
|
68
|
+
expect(rateLimited('win', t0)).toBe(false);
|
|
69
|
+
// Advance past WINDOW_MS — the next call starts a fresh bucket and
|
|
70
|
+
// returns true as count-1.
|
|
71
|
+
const t1 = t0 + WINDOW_MS + 1;
|
|
72
|
+
expect(rateLimited('win', t1)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('suppresses events after FIRST_N + 1 that are not on the sampled boundary', () => {
|
|
75
|
+
const t = 5_000;
|
|
76
|
+
// First N pass.
|
|
77
|
+
for (let i = 0; i < FIRST_N; i += 1) {
|
|
78
|
+
expect(rateLimited('same-now', t)).toBe(true);
|
|
79
|
+
}
|
|
80
|
+
// FIRST_N + 1: first sampled hit, (count - FIRST_N) % SAMPLE_EVERY === 1 → true.
|
|
81
|
+
expect(rateLimited('same-now', t)).toBe(true);
|
|
82
|
+
// FIRST_N + 2: (count - FIRST_N) % SAMPLE_EVERY === 2 → false.
|
|
83
|
+
expect(rateLimited('same-now', t)).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=rate-limit.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.test.js","sourceRoot":"","sources":["../../../src/utils/rate-limit.test.ts"],"names":[],"mappings":"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"}
|