@panguard-ai/scan-core 0.1.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 (69) hide show
  1. package/dist/__tests__/atr-engine.test.d.ts +2 -0
  2. package/dist/__tests__/atr-engine.test.d.ts.map +1 -0
  3. package/dist/__tests__/atr-engine.test.js +360 -0
  4. package/dist/__tests__/atr-engine.test.js.map +1 -0
  5. package/dist/__tests__/context-signals.test.d.ts +2 -0
  6. package/dist/__tests__/context-signals.test.d.ts.map +1 -0
  7. package/dist/__tests__/context-signals.test.js +373 -0
  8. package/dist/__tests__/context-signals.test.js.map +1 -0
  9. package/dist/__tests__/hash-utils.test.d.ts +2 -0
  10. package/dist/__tests__/hash-utils.test.d.ts.map +1 -0
  11. package/dist/__tests__/hash-utils.test.js +89 -0
  12. package/dist/__tests__/hash-utils.test.js.map +1 -0
  13. package/dist/__tests__/manifest-parser.test.d.ts +2 -0
  14. package/dist/__tests__/manifest-parser.test.d.ts.map +1 -0
  15. package/dist/__tests__/manifest-parser.test.js +246 -0
  16. package/dist/__tests__/manifest-parser.test.js.map +1 -0
  17. package/dist/__tests__/risk-scorer.test.d.ts +2 -0
  18. package/dist/__tests__/risk-scorer.test.d.ts.map +1 -0
  19. package/dist/__tests__/risk-scorer.test.js +189 -0
  20. package/dist/__tests__/risk-scorer.test.js.map +1 -0
  21. package/dist/__tests__/scanner.test.d.ts +2 -0
  22. package/dist/__tests__/scanner.test.d.ts.map +1 -0
  23. package/dist/__tests__/scanner.test.js +442 -0
  24. package/dist/__tests__/scanner.test.js.map +1 -0
  25. package/dist/atr-engine.d.ts +31 -0
  26. package/dist/atr-engine.d.ts.map +1 -0
  27. package/dist/atr-engine.js +149 -0
  28. package/dist/atr-engine.js.map +1 -0
  29. package/dist/context-signals.d.ts +33 -0
  30. package/dist/context-signals.d.ts.map +1 -0
  31. package/dist/context-signals.js +162 -0
  32. package/dist/context-signals.js.map +1 -0
  33. package/dist/hash-utils.d.ts +20 -0
  34. package/dist/hash-utils.d.ts.map +1 -0
  35. package/dist/hash-utils.js +28 -0
  36. package/dist/hash-utils.js.map +1 -0
  37. package/dist/index.d.ts +17 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +17 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/instruction-patterns.d.ts +18 -0
  42. package/dist/instruction-patterns.d.ts.map +1 -0
  43. package/dist/instruction-patterns.js +291 -0
  44. package/dist/instruction-patterns.js.map +1 -0
  45. package/dist/manifest-parser.d.ts +19 -0
  46. package/dist/manifest-parser.d.ts.map +1 -0
  47. package/dist/manifest-parser.js +73 -0
  48. package/dist/manifest-parser.js.map +1 -0
  49. package/dist/markdown-utils.d.ts +16 -0
  50. package/dist/markdown-utils.d.ts.map +1 -0
  51. package/dist/markdown-utils.js +41 -0
  52. package/dist/markdown-utils.js.map +1 -0
  53. package/dist/risk-scorer.d.ts +21 -0
  54. package/dist/risk-scorer.d.ts.map +1 -0
  55. package/dist/risk-scorer.js +63 -0
  56. package/dist/risk-scorer.js.map +1 -0
  57. package/dist/scanner.d.ts +24 -0
  58. package/dist/scanner.d.ts.map +1 -0
  59. package/dist/scanner.js +131 -0
  60. package/dist/scanner.js.map +1 -0
  61. package/dist/secret-detection.d.ts +16 -0
  62. package/dist/secret-detection.d.ts.map +1 -0
  63. package/dist/secret-detection.js +42 -0
  64. package/dist/secret-detection.js.map +1 -0
  65. package/dist/types.d.ts +106 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +8 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +47 -0
@@ -0,0 +1,246 @@
1
+ // @ts-nocheck
2
+ import { describe, it, expect } from 'vitest';
3
+ import { parseManifestFromString, parseSkillName } from '../manifest-parser.js';
4
+ // ---------------------------------------------------------------------------
5
+ // parseManifestFromString
6
+ // ---------------------------------------------------------------------------
7
+ describe('parseManifestFromString', () => {
8
+ describe('valid frontmatter', () => {
9
+ it('parses name and description from frontmatter', () => {
10
+ const content = [
11
+ '---',
12
+ 'name: my-skill',
13
+ 'description: A test skill',
14
+ '---',
15
+ 'Do the thing.',
16
+ ].join('\n');
17
+ const manifest = parseManifestFromString(content);
18
+ expect(manifest.name).toBe('my-skill');
19
+ expect(manifest.description).toBe('A test skill');
20
+ });
21
+ it('extracts instructions as the content after frontmatter', () => {
22
+ const content = [
23
+ '---',
24
+ 'name: my-skill',
25
+ 'description: A test skill',
26
+ '---',
27
+ 'Do the thing.',
28
+ 'Second line.',
29
+ ].join('\n');
30
+ const manifest = parseManifestFromString(content);
31
+ expect(manifest.instructions).toContain('Do the thing.');
32
+ expect(manifest.instructions).toContain('Second line.');
33
+ });
34
+ it('parses optional license field', () => {
35
+ const content = [
36
+ '---',
37
+ 'name: my-skill',
38
+ 'description: desc',
39
+ 'license: MIT',
40
+ '---',
41
+ 'instructions',
42
+ ].join('\n');
43
+ const manifest = parseManifestFromString(content);
44
+ expect(manifest.license).toBe('MIT');
45
+ });
46
+ it('parses optional homepage field', () => {
47
+ const content = [
48
+ '---',
49
+ 'name: my-skill',
50
+ 'description: desc',
51
+ 'homepage: https://example.com',
52
+ '---',
53
+ 'instructions',
54
+ ].join('\n');
55
+ const manifest = parseManifestFromString(content);
56
+ expect(manifest.homepage).toBe('https://example.com');
57
+ });
58
+ it('parses user-invocable boolean', () => {
59
+ const content = [
60
+ '---',
61
+ 'name: my-skill',
62
+ 'description: desc',
63
+ 'user-invocable: true',
64
+ '---',
65
+ 'instructions',
66
+ ].join('\n');
67
+ const manifest = parseManifestFromString(content);
68
+ expect(manifest.userInvocable).toBe(true);
69
+ });
70
+ it('parses allowed-tools list', () => {
71
+ const content = [
72
+ '---',
73
+ 'name: my-skill',
74
+ 'description: desc',
75
+ 'allowed-tools:',
76
+ ' - Bash',
77
+ ' - Read',
78
+ '---',
79
+ 'instructions',
80
+ ].join('\n');
81
+ const manifest = parseManifestFromString(content);
82
+ expect(manifest['allowed-tools']).toEqual(['Bash', 'Read']);
83
+ });
84
+ });
85
+ describe('metadata extraction', () => {
86
+ it('extracts version from metadata object', () => {
87
+ const content = [
88
+ '---',
89
+ 'name: my-skill',
90
+ 'description: desc',
91
+ 'metadata:',
92
+ ' version: "1.2.3"',
93
+ '---',
94
+ 'instructions',
95
+ ].join('\n');
96
+ const manifest = parseManifestFromString(content);
97
+ expect(manifest.metadata?.version).toBe('1.2.3');
98
+ });
99
+ it('extracts tags from metadata object', () => {
100
+ const content = [
101
+ '---',
102
+ 'name: my-skill',
103
+ 'description: desc',
104
+ 'metadata:',
105
+ ' tags:',
106
+ ' - security',
107
+ ' - ai',
108
+ '---',
109
+ 'instructions',
110
+ ].join('\n');
111
+ const manifest = parseManifestFromString(content);
112
+ expect(manifest.metadata?.tags).toEqual(['security', 'ai']);
113
+ });
114
+ it('parses metadata when provided as a JSON string', () => {
115
+ const metaJson = JSON.stringify({ version: '2.0.0', tags: ['test'] });
116
+ const content = [
117
+ '---',
118
+ 'name: my-skill',
119
+ 'description: desc',
120
+ `metadata: '${metaJson}'`,
121
+ '---',
122
+ 'instructions',
123
+ ].join('\n');
124
+ const manifest = parseManifestFromString(content);
125
+ expect(manifest.metadata?.version).toBe('2.0.0');
126
+ });
127
+ it('silently ignores invalid JSON string in metadata', () => {
128
+ const content = [
129
+ '---',
130
+ 'name: my-skill',
131
+ 'description: desc',
132
+ 'metadata: "not valid json {"',
133
+ '---',
134
+ 'instructions',
135
+ ].join('\n');
136
+ const manifest = parseManifestFromString(content);
137
+ expect(manifest.metadata).toBeUndefined();
138
+ });
139
+ });
140
+ describe('no frontmatter', () => {
141
+ it('treats entire content as instructions when no frontmatter present', () => {
142
+ const content = 'Just raw instructions without any frontmatter.';
143
+ const manifest = parseManifestFromString(content);
144
+ expect(manifest.instructions).toBe(content);
145
+ });
146
+ it('uses fallbackName when no frontmatter', () => {
147
+ const content = 'Raw instructions.';
148
+ const manifest = parseManifestFromString(content, 'fallback-name');
149
+ expect(manifest.name).toBe('fallback-name');
150
+ });
151
+ it('uses "unknown" as default fallback name', () => {
152
+ const content = 'Raw instructions.';
153
+ const manifest = parseManifestFromString(content);
154
+ expect(manifest.name).toBe('unknown');
155
+ });
156
+ it('returns empty description when no frontmatter', () => {
157
+ const content = 'Raw instructions.';
158
+ const manifest = parseManifestFromString(content);
159
+ expect(manifest.description).toBe('');
160
+ });
161
+ it('handles empty string content', () => {
162
+ const manifest = parseManifestFromString('');
163
+ expect(manifest.name).toBe('unknown');
164
+ expect(manifest.instructions).toBe('');
165
+ });
166
+ });
167
+ describe('invalid YAML frontmatter', () => {
168
+ it('returns fallback manifest for invalid YAML', () => {
169
+ // YAML that is structurally invalid within the frontmatter block
170
+ const content = [
171
+ '---',
172
+ 'name: [unclosed bracket',
173
+ 'description: test',
174
+ '---',
175
+ 'instructions here',
176
+ ].join('\n');
177
+ const manifest = parseManifestFromString(content, 'fallback');
178
+ // Should fall back gracefully - either parse successfully or use fallback
179
+ expect(manifest.name).toBeDefined();
180
+ expect(typeof manifest.name).toBe('string');
181
+ });
182
+ it('uses fallbackName on YAML parse failure', () => {
183
+ // Deeply malformed YAML that triggers a parse exception
184
+ const badYaml = 'key: :\n - invalid: : nested\n bad: [unclosed';
185
+ const content = `---\n${badYaml}\n---\ninstructions`;
186
+ const manifest = parseManifestFromString(content, 'my-fallback');
187
+ // Either parses or falls back - name must be a string
188
+ expect(typeof manifest.name).toBe('string');
189
+ });
190
+ });
191
+ describe('edge cases', () => {
192
+ it('uses fallbackName when frontmatter has no name field', () => {
193
+ const content = [
194
+ '---',
195
+ 'description: no name here',
196
+ '---',
197
+ 'instructions',
198
+ ].join('\n');
199
+ const manifest = parseManifestFromString(content, 'injected-name');
200
+ expect(manifest.name).toBe('injected-name');
201
+ });
202
+ it('handles frontmatter with CRLF line endings', () => {
203
+ const content = '---\r\nname: crlf-skill\r\ndescription: desc\r\n---\r\ninstructions';
204
+ const manifest = parseManifestFromString(content);
205
+ expect(manifest.name).toBe('crlf-skill');
206
+ });
207
+ it('instructions are empty string when nothing follows frontmatter', () => {
208
+ const content = ['---', 'name: my-skill', 'description: desc', '---'].join('\n');
209
+ const manifest = parseManifestFromString(content);
210
+ // instructions should be empty or whitespace - just not throw
211
+ expect(typeof manifest.instructions).toBe('string');
212
+ });
213
+ });
214
+ });
215
+ // ---------------------------------------------------------------------------
216
+ // parseSkillName
217
+ // ---------------------------------------------------------------------------
218
+ describe('parseSkillName', () => {
219
+ it('extracts name from raw content with frontmatter', () => {
220
+ const content = ['---', 'name: extracted-skill', 'description: test', '---', 'body'].join('\n');
221
+ expect(parseSkillName(content)).toBe('extracted-skill');
222
+ });
223
+ it('returns null when no frontmatter present', () => {
224
+ const content = 'Just raw content without frontmatter.';
225
+ expect(parseSkillName(content)).toBeNull();
226
+ });
227
+ it('returns null when frontmatter has no name field', () => {
228
+ const content = ['---', 'description: no name', '---', 'body'].join('\n');
229
+ expect(parseSkillName(content)).toBeNull();
230
+ });
231
+ it('trims whitespace from the extracted name', () => {
232
+ const content = ['---', 'name: my-skill ', '---', 'body'].join('\n');
233
+ // The regex captures everything after "name: " so trailing space may or may not be trimmed
234
+ // The implementation does .trim() so we expect clean value
235
+ const name = parseSkillName(content);
236
+ expect(name).toBe('my-skill');
237
+ });
238
+ it('handles names with hyphens and dots', () => {
239
+ const content = ['---', 'name: my.complex-skill.v2', '---', 'body'].join('\n');
240
+ expect(parseSkillName(content)).toBe('my.complex-skill.v2');
241
+ });
242
+ it('returns null for empty string', () => {
243
+ expect(parseSkillName('')).toBeNull();
244
+ });
245
+ });
246
+ //# sourceMappingURL=manifest-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-parser.test.js","sourceRoot":"","sources":["../../src/__tests__/manifest-parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=risk-scorer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-scorer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/risk-scorer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,189 @@
1
+ // @ts-nocheck
2
+ import { describe, it, expect } from 'vitest';
3
+ import { calculateRiskScore } from '../risk-scorer.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Helpers
6
+ // ---------------------------------------------------------------------------
7
+ function makeFinding(id, severity, overrides = {}) {
8
+ return {
9
+ id,
10
+ title: `Finding ${id}`,
11
+ description: `Description for ${id}`,
12
+ severity,
13
+ category: 'prompt-injection',
14
+ ...overrides,
15
+ };
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // Tests
19
+ // ---------------------------------------------------------------------------
20
+ describe('calculateRiskScore', () => {
21
+ describe('empty findings', () => {
22
+ it('returns score 0 and level LOW for empty array', () => {
23
+ const { score, level } = calculateRiskScore([]);
24
+ expect(score).toBe(0);
25
+ expect(level).toBe('LOW');
26
+ });
27
+ it('returns score 0 and level LOW when called with no arguments', () => {
28
+ // contextMultiplier defaults to 1.0
29
+ const { score, level } = calculateRiskScore([]);
30
+ expect(score).toBe(0);
31
+ expect(level).toBe('LOW');
32
+ });
33
+ it('returns score 0 with contextMultiplier applied to empty set', () => {
34
+ const { score } = calculateRiskScore([], 2.0);
35
+ expect(score).toBe(0);
36
+ });
37
+ });
38
+ describe('severity weights', () => {
39
+ it('single info finding = score 0', () => {
40
+ const { score, level } = calculateRiskScore([makeFinding('f1', 'info')]);
41
+ expect(score).toBe(0);
42
+ expect(level).toBe('LOW');
43
+ });
44
+ it('single low finding = score 1', () => {
45
+ const { score } = calculateRiskScore([makeFinding('f1', 'low')]);
46
+ expect(score).toBe(1);
47
+ });
48
+ it('single medium finding = score 5', () => {
49
+ const { score } = calculateRiskScore([makeFinding('f1', 'medium')]);
50
+ expect(score).toBe(5);
51
+ });
52
+ it('single high finding = score 15, level MEDIUM', () => {
53
+ const { score, level } = calculateRiskScore([makeFinding('f1', 'high')]);
54
+ expect(score).toBe(15);
55
+ expect(level).toBe('MEDIUM');
56
+ });
57
+ it('single critical finding with contextMultiplier 1.0 = score 25, level CRITICAL', () => {
58
+ // Logic: score >= 25 && hasCritical && !weakened => CRITICAL
59
+ const { score, level } = calculateRiskScore([makeFinding('f1', 'critical')], 1.0);
60
+ expect(score).toBe(25);
61
+ expect(level).toBe('CRITICAL');
62
+ });
63
+ });
64
+ describe('deduplication by finding ID', () => {
65
+ it('deduplicates findings with the same ID, keeping the highest severity', () => {
66
+ const findings = [
67
+ makeFinding('dup-id', 'low'),
68
+ makeFinding('dup-id', 'critical'),
69
+ makeFinding('dup-id', 'medium'),
70
+ ];
71
+ const { score } = calculateRiskScore(findings);
72
+ // Only critical (weight 25) should count
73
+ expect(score).toBe(25);
74
+ });
75
+ it('deduplicates correctly when highest severity appears first', () => {
76
+ const findings = [
77
+ makeFinding('dup-id', 'critical'),
78
+ makeFinding('dup-id', 'low'),
79
+ ];
80
+ const { score } = calculateRiskScore(findings);
81
+ expect(score).toBe(25);
82
+ });
83
+ it('keeps distinct IDs separate', () => {
84
+ const findings = [
85
+ makeFinding('id-a', 'critical'), // 25
86
+ makeFinding('id-b', 'high'), // 15
87
+ ];
88
+ const { score } = calculateRiskScore(findings);
89
+ expect(score).toBe(40);
90
+ });
91
+ it('info duplicates do not inflate score', () => {
92
+ const findings = [
93
+ makeFinding('same', 'info'),
94
+ makeFinding('same', 'info'),
95
+ makeFinding('same', 'info'),
96
+ ];
97
+ const { score } = calculateRiskScore(findings);
98
+ expect(score).toBe(0);
99
+ });
100
+ });
101
+ describe('contextMultiplier > 1 boosts score', () => {
102
+ it('multiplier 2.0 doubles the raw score', () => {
103
+ const findings = [makeFinding('f1', 'high')]; // raw = 15
104
+ const { score } = calculateRiskScore(findings, 2.0);
105
+ expect(score).toBe(30);
106
+ });
107
+ it('multiplier 1.5 rounds correctly', () => {
108
+ const findings = [makeFinding('f1', 'medium')]; // raw = 5, * 1.5 = 7.5 → rounds to 8
109
+ const { score } = calculateRiskScore(findings, 1.5);
110
+ expect(score).toBe(8);
111
+ });
112
+ it('multiplier boosts push score into CRITICAL territory', () => {
113
+ // 2 high findings = 30, * 2.5 = 75 >= 70 => CRITICAL
114
+ const findings = [makeFinding('f1', 'high'), makeFinding('f2', 'high')];
115
+ const { level } = calculateRiskScore(findings, 2.5);
116
+ expect(level).toBe('CRITICAL');
117
+ });
118
+ });
119
+ describe('contextMultiplier < 0.6 weakens critical override', () => {
120
+ it('critical finding with multiplier 0.5 yields MEDIUM (not HIGH)', () => {
121
+ const findings = [makeFinding('f1', 'critical')]; // raw = 25, * 0.5 = 12 (< 15 threshold for MEDIUM via score)
122
+ const { level } = calculateRiskScore(findings, 0.5);
123
+ // weakenedCriticalOverride = true (0.5 < 0.6), so critical forces MEDIUM only
124
+ expect(level).toBe('MEDIUM');
125
+ });
126
+ it('critical finding with multiplier exactly 0.6 still yields HIGH', () => {
127
+ // 0.6 is NOT < 0.6, so weakenedCriticalOverride = false
128
+ const findings = [makeFinding('f1', 'critical')];
129
+ const { level } = calculateRiskScore(findings, 0.6);
130
+ // score = round(25 * 0.6) = 15, hasCritical=true, not weakened
131
+ // 15 < 40, not >=40; hasCritical && !weakened => HIGH
132
+ expect(level).toBe('HIGH');
133
+ });
134
+ it('critical finding with multiplier 0.3 (below 0.6) yields MEDIUM', () => {
135
+ const findings = [makeFinding('f1', 'critical')];
136
+ const { level } = calculateRiskScore(findings, 0.3);
137
+ expect(level).toBe('MEDIUM');
138
+ });
139
+ });
140
+ describe('score cap at 100', () => {
141
+ it('many critical findings are capped at 100', () => {
142
+ const findings = Array.from({ length: 20 }, (_, i) => makeFinding(`f${i}`, 'critical'));
143
+ const { score } = calculateRiskScore(findings, 1.0);
144
+ expect(score).toBe(100);
145
+ });
146
+ it('multiplier cannot push score above 100', () => {
147
+ const findings = [
148
+ makeFinding('f1', 'critical'),
149
+ makeFinding('f2', 'critical'),
150
+ makeFinding('f3', 'critical'),
151
+ ];
152
+ const { score } = calculateRiskScore(findings, 2.5);
153
+ expect(score).toBe(100);
154
+ });
155
+ });
156
+ describe('risk level boundaries', () => {
157
+ it('score exactly 70 yields CRITICAL', () => {
158
+ // 14 high findings (no dedup because different IDs) = 14*15=210, *0.5 = 105 => cap 100... different approach
159
+ // Use medium findings: need score >= 70 via multiplier
160
+ // 14 medium findings = 70 raw => CRITICAL
161
+ const findings = Array.from({ length: 14 }, (_, i) => makeFinding(`f${i}`, 'medium'));
162
+ const { score, level } = calculateRiskScore(findings, 1.0);
163
+ expect(score).toBe(70);
164
+ expect(level).toBe('CRITICAL');
165
+ });
166
+ it('score 40 with no critical = HIGH', () => {
167
+ // 8 medium = 40
168
+ const findings = Array.from({ length: 8 }, (_, i) => makeFinding(`f${i}`, 'medium'));
169
+ const { score, level } = calculateRiskScore(findings, 1.0);
170
+ expect(score).toBe(40);
171
+ expect(level).toBe('HIGH');
172
+ });
173
+ it('score 15 with no critical = MEDIUM', () => {
174
+ // 3 medium = 15
175
+ const findings = Array.from({ length: 3 }, (_, i) => makeFinding(`f${i}`, 'medium'));
176
+ const { score, level } = calculateRiskScore(findings, 1.0);
177
+ expect(score).toBe(15);
178
+ expect(level).toBe('MEDIUM');
179
+ });
180
+ it('score below 15 with no critical = LOW', () => {
181
+ // 2 medium = 10
182
+ const findings = Array.from({ length: 2 }, (_, i) => makeFinding(`f${i}`, 'medium'));
183
+ const { score, level } = calculateRiskScore(findings, 1.0);
184
+ expect(score).toBe(10);
185
+ expect(level).toBe('LOW');
186
+ });
187
+ });
188
+ });
189
+ //# sourceMappingURL=risk-scorer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-scorer.test.js","sourceRoot":"","sources":["../../src/__tests__/risk-scorer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scanner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scanner.test.ts"],"names":[],"mappings":""}