logicstamp-context 0.2.6 → 0.3.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 (63) hide show
  1. package/LLM_CONTEXT.md +2 -2
  2. package/README.md +79 -36
  3. package/dist/cli/commands/context.d.ts.map +1 -1
  4. package/dist/cli/commands/context.js +36 -10
  5. package/dist/cli/commands/context.js.map +1 -1
  6. package/dist/cli/commands/ignore.d.ts +16 -0
  7. package/dist/cli/commands/ignore.d.ts.map +1 -0
  8. package/dist/cli/commands/ignore.js +61 -0
  9. package/dist/cli/commands/ignore.js.map +1 -0
  10. package/dist/cli/commands/init.d.ts +4 -0
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +83 -9
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/security.d.ts +37 -0
  15. package/dist/cli/commands/security.d.ts.map +1 -0
  16. package/dist/cli/commands/security.js +304 -0
  17. package/dist/cli/commands/security.js.map +1 -0
  18. package/dist/cli/handlers/ignoreHandler.d.ts +5 -0
  19. package/dist/cli/handlers/ignoreHandler.d.ts.map +1 -0
  20. package/dist/cli/handlers/ignoreHandler.js +23 -0
  21. package/dist/cli/handlers/ignoreHandler.js.map +1 -0
  22. package/dist/cli/handlers/securityHandler.d.ts +5 -0
  23. package/dist/cli/handlers/securityHandler.d.ts.map +1 -0
  24. package/dist/cli/handlers/securityHandler.js +41 -0
  25. package/dist/cli/handlers/securityHandler.js.map +1 -0
  26. package/dist/cli/parser/argumentParser.d.ts +9 -0
  27. package/dist/cli/parser/argumentParser.d.ts.map +1 -1
  28. package/dist/cli/parser/argumentParser.js +50 -0
  29. package/dist/cli/parser/argumentParser.js.map +1 -1
  30. package/dist/cli/parser/helpText.d.ts +3 -0
  31. package/dist/cli/parser/helpText.d.ts.map +1 -1
  32. package/dist/cli/parser/helpText.js +492 -348
  33. package/dist/cli/parser/helpText.js.map +1 -1
  34. package/dist/cli/stamp.js +61 -1
  35. package/dist/cli/stamp.js.map +1 -1
  36. package/dist/core/pack/builder.d.ts.map +1 -1
  37. package/dist/core/pack/builder.js +25 -5
  38. package/dist/core/pack/builder.js.map +1 -1
  39. package/dist/core/pack/loader.d.ts +14 -0
  40. package/dist/core/pack/loader.d.ts.map +1 -1
  41. package/dist/core/pack/loader.js +86 -2
  42. package/dist/core/pack/loader.js.map +1 -1
  43. package/dist/core/pack.d.ts.map +1 -1
  44. package/dist/core/pack.js +15 -2
  45. package/dist/core/pack.js.map +1 -1
  46. package/dist/utils/codeSanitizer.d.ts +24 -0
  47. package/dist/utils/codeSanitizer.d.ts.map +1 -0
  48. package/dist/utils/codeSanitizer.js +234 -0
  49. package/dist/utils/codeSanitizer.js.map +1 -0
  50. package/dist/utils/gitignore.d.ts +30 -2
  51. package/dist/utils/gitignore.d.ts.map +1 -1
  52. package/dist/utils/gitignore.js +132 -20
  53. package/dist/utils/gitignore.js.map +1 -1
  54. package/dist/utils/secretDetector.d.ts +21 -0
  55. package/dist/utils/secretDetector.d.ts.map +1 -0
  56. package/dist/utils/secretDetector.js +145 -0
  57. package/dist/utils/secretDetector.js.map +1 -0
  58. package/dist/utils/stampignore.d.ts +49 -0
  59. package/dist/utils/stampignore.d.ts.map +1 -0
  60. package/dist/utils/stampignore.js +211 -0
  61. package/dist/utils/stampignore.js.map +1 -0
  62. package/package.json +1 -1
  63. package/schema/logicstamp.context.schema.json +1 -1
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Code sanitization utilities
3
+ * Replaces secret values in code with "PRIVATE_DATA" based on security report
4
+ */
5
+ import { resolve, isAbsolute, normalize } from 'node:path';
6
+ import { readFile } from 'node:fs/promises';
7
+ /**
8
+ * Load security report from file
9
+ */
10
+ export async function loadSecurityReport(projectRoot) {
11
+ try {
12
+ const reportPath = resolve(projectRoot, 'stamp_security_report.json');
13
+ const content = await readFile(reportPath, 'utf8');
14
+ return JSON.parse(content);
15
+ }
16
+ catch (error) {
17
+ // Report doesn't exist or can't be read - that's okay
18
+ return null;
19
+ }
20
+ }
21
+ /**
22
+ * Normalize a path for comparison (handles Windows case-insensitivity)
23
+ * Converts to lowercase on Windows and normalizes separators
24
+ */
25
+ function normalizePathForComparison(path) {
26
+ const normalized = normalize(resolve(path));
27
+ // On Windows, paths are case-insensitive, so lowercase for comparison
28
+ // Also normalize separators to forward slashes for consistency
29
+ if (process.platform === 'win32') {
30
+ return normalized.toLowerCase().replace(/\\/g, '/');
31
+ }
32
+ return normalized.replace(/\\/g, '/');
33
+ }
34
+ /**
35
+ * Get secret matches for a specific file
36
+ */
37
+ function getSecretMatchesForFile(report, filePath, projectRoot) {
38
+ // Try to match file path - handle both absolute and relative paths
39
+ const absoluteFilePath = isAbsolute(filePath) ? filePath : resolve(projectRoot, filePath);
40
+ const normalizedTargetPath = normalizePathForComparison(absoluteFilePath);
41
+ // Also normalize project roots for comparison
42
+ const normalizedReportRoot = normalizePathForComparison(report.projectRoot);
43
+ const normalizedCurrentRoot = normalizePathForComparison(projectRoot);
44
+ return report.matches.filter(match => {
45
+ // Normalize match file path - try multiple strategies
46
+ let matchFilePath;
47
+ if (isAbsolute(match.file)) {
48
+ // Match file is already absolute
49
+ matchFilePath = match.file;
50
+ }
51
+ else {
52
+ // Match file is relative - try resolving from report's projectRoot first
53
+ matchFilePath = resolve(report.projectRoot, match.file);
54
+ }
55
+ const normalizedMatchPath = normalizePathForComparison(matchFilePath);
56
+ // Direct path match
57
+ if (normalizedMatchPath === normalizedTargetPath) {
58
+ return true;
59
+ }
60
+ // If project roots differ, try resolving relative to current projectRoot
61
+ if (normalizedReportRoot !== normalizedCurrentRoot && !isAbsolute(match.file)) {
62
+ // Try resolving the match file relative to current projectRoot
63
+ const alternativePath = resolve(projectRoot, match.file);
64
+ const normalizedAlternative = normalizePathForComparison(alternativePath);
65
+ if (normalizedAlternative === normalizedTargetPath) {
66
+ return true;
67
+ }
68
+ // Try making both paths relative to their respective roots and comparing
69
+ // This handles cases where the file structure is the same but roots differ
70
+ try {
71
+ const relativeFromReport = match.file.replace(/^\.\//, '');
72
+ const relativeFromCurrent = filePath.replace(/^\.\//, '');
73
+ if (normalizePathForComparison(relativeFromReport) === normalizePathForComparison(relativeFromCurrent)) {
74
+ return true;
75
+ }
76
+ }
77
+ catch {
78
+ // Ignore errors in relative path comparison
79
+ }
80
+ }
81
+ return false;
82
+ });
83
+ }
84
+ /**
85
+ * Sanitize a line of code by replacing secret values with "PRIVATE_DATA"
86
+ * Uses the match information to accurately identify and replace the secret value
87
+ */
88
+ function sanitizeLine(line, matches) {
89
+ if (matches.length === 0) {
90
+ return line;
91
+ }
92
+ let sanitized = line;
93
+ // Sort matches by column (right to left) to avoid offset issues when replacing
94
+ const sortedMatches = [...matches].sort((a, b) => b.column - a.column);
95
+ for (const match of sortedMatches) {
96
+ // Extract the secret value from the snippet
97
+ // The snippet typically shows: "context = 'SECRET_VALUE' context"
98
+ // We need to extract the actual secret value
99
+ // For database URLs: postgres://user:password@host (check this FIRST before quoted value matching)
100
+ // Database URLs are often in quotes, so we need to handle them specially
101
+ if (match.type === 'Database URL with Credentials') {
102
+ // Extract the password from the URL pattern: protocol://user:password@host
103
+ const dbUrlMatch = match.snippet.match(/((?:postgres|mysql|mongodb):\/\/[^:]+:)([^@]+)(@)/i);
104
+ if (dbUrlMatch) {
105
+ const password = dbUrlMatch[2];
106
+ // Also try to find the full URL in the line to replace just the password part
107
+ const fullUrlMatch = sanitized.match(/(['"`])((?:postgres|mysql|mongodb):\/\/[^:]+:)([^@]+)(@[^'"`]+)\1/i);
108
+ if (fullUrlMatch) {
109
+ const quote = fullUrlMatch[1];
110
+ const prefix = fullUrlMatch[2];
111
+ const passwordPart = fullUrlMatch[3];
112
+ const suffix = fullUrlMatch[4];
113
+ // Replace the URL with password sanitized
114
+ sanitized = sanitized.replace(fullUrlMatch[0], `${quote}${prefix}PRIVATE_DATA${suffix}${quote}`);
115
+ }
116
+ else if (sanitized.includes(password)) {
117
+ // Fallback: just replace the password if we can't match the full URL
118
+ sanitized = sanitized.replace(password, 'PRIVATE_DATA');
119
+ }
120
+ }
121
+ continue;
122
+ }
123
+ // Try to extract quoted values: 'value', "value", or `value`
124
+ // Handle cases where snippet has extra context (leading/trailing spaces, etc.)
125
+ const quotedValueMatch = match.snippet.match(/[=:]\s*(['"`])([^'"`]+)\1/);
126
+ if (quotedValueMatch) {
127
+ const quote = quotedValueMatch[1];
128
+ const secretValue = quotedValueMatch[2];
129
+ // Replace the secret value in the line, preserving quotes
130
+ // The secretValue might be in the line even if the snippet has different context
131
+ if (secretValue && secretValue.length > 0) {
132
+ const escapedValue = secretValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
133
+ // Try to find and replace the quoted value in the line
134
+ // Match: quote + secretValue + quote (with word boundaries to avoid partial matches)
135
+ const quotePattern = new RegExp(`${quote}${escapedValue}${quote}`, 'g');
136
+ // Check if pattern matches (don't use test() as it modifies lastIndex)
137
+ if (quotePattern.exec(sanitized) !== null) {
138
+ // Reset regex lastIndex before replace
139
+ quotePattern.lastIndex = 0;
140
+ sanitized = sanitized.replace(quotePattern, `${quote}PRIVATE_DATA${quote}`);
141
+ }
142
+ else if (sanitized.includes(secretValue)) {
143
+ // Fallback: if exact quote match fails, try to replace the value itself
144
+ // This handles cases where quotes might differ or context is different
145
+ sanitized = sanitized.replace(new RegExp(escapedValue, 'g'), 'PRIVATE_DATA');
146
+ }
147
+ }
148
+ continue;
149
+ }
150
+ // Try to extract unquoted values after = or :
151
+ const unquotedValueMatch = match.snippet.match(/[=:]\s+([a-zA-Z0-9_\-]{16,})/);
152
+ if (unquotedValueMatch) {
153
+ const secretValue = unquotedValueMatch[1];
154
+ if (sanitized.includes(secretValue)) {
155
+ const escapedValue = secretValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
156
+ sanitized = sanitized.replace(new RegExp(`\\b${escapedValue}\\b`, 'g'), 'PRIVATE_DATA');
157
+ }
158
+ continue;
159
+ }
160
+ // For private keys, replace the entire key block
161
+ if (match.type === 'Private Key' && sanitized.includes('BEGIN')) {
162
+ // Find the private key block and replace content between BEGIN and END
163
+ sanitized = sanitized.replace(/(-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----)[\s\S]*?(-----END\s+(?:RSA\s+)?PRIVATE\s+KEY-----)/g, '$1\nPRIVATE_DATA\n$2');
164
+ continue;
165
+ }
166
+ // Fallback: try to find and replace long alphanumeric strings that match the pattern
167
+ // This is less precise but catches edge cases
168
+ const longStringMatch = match.snippet.match(/([a-zA-Z0-9_\-]{20,})/);
169
+ if (longStringMatch) {
170
+ const potentialSecret = longStringMatch[1];
171
+ // Only replace if it's not already been replaced and it's a reasonable length
172
+ if (potentialSecret.length >= 16 && sanitized.includes(potentialSecret) && !sanitized.includes('PRIVATE_DATA')) {
173
+ const escaped = potentialSecret.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
174
+ sanitized = sanitized.replace(new RegExp(escaped, 'g'), 'PRIVATE_DATA');
175
+ }
176
+ }
177
+ }
178
+ return sanitized;
179
+ }
180
+ /**
181
+ * Sanitize code by replacing secret values with "PRIVATE_DATA"
182
+ * Uses security report to identify which lines contain secrets
183
+ */
184
+ export function sanitizeCode(code, filePath, report, projectRoot) {
185
+ if (!report || report.matches.length === 0) {
186
+ return {
187
+ sanitized: code,
188
+ secretsReplaced: false,
189
+ filePath,
190
+ matchCount: 0,
191
+ };
192
+ }
193
+ // Get secret matches for this specific file
194
+ const fileMatches = getSecretMatchesForFile(report, filePath, projectRoot);
195
+ if (fileMatches.length === 0) {
196
+ // No matches for this file - return code unchanged
197
+ return {
198
+ sanitized: code,
199
+ secretsReplaced: false,
200
+ filePath,
201
+ matchCount: 0,
202
+ };
203
+ }
204
+ // Group matches by line number
205
+ const matchesByLine = new Map();
206
+ for (const match of fileMatches) {
207
+ if (!matchesByLine.has(match.line)) {
208
+ matchesByLine.set(match.line, []);
209
+ }
210
+ matchesByLine.get(match.line).push(match);
211
+ }
212
+ // Sanitize each line that has secrets
213
+ const lines = code.split('\n');
214
+ let secretsReplaced = false;
215
+ const sanitizedLines = lines.map((line, index) => {
216
+ const lineNumber = index + 1; // Line numbers are 1-based
217
+ const lineMatches = matchesByLine.get(lineNumber);
218
+ if (lineMatches && lineMatches.length > 0) {
219
+ const sanitized = sanitizeLine(line, lineMatches);
220
+ if (sanitized !== line) {
221
+ secretsReplaced = true;
222
+ }
223
+ return sanitized;
224
+ }
225
+ return line;
226
+ });
227
+ return {
228
+ sanitized: sanitizedLines.join('\n'),
229
+ secretsReplaced,
230
+ filePath,
231
+ matchCount: fileMatches.length,
232
+ };
233
+ }
234
+ //# sourceMappingURL=codeSanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeSanitizer.js","sourceRoot":"","sources":["../../src/utils/codeSanitizer.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * Utilities for managing .gitignore files
3
3
  */
4
4
  /**
5
- * Patterns that should be added to .gitignore for LogicStamp context files
5
+ * Patterns that should be added to .gitignore for LogicStamp context & security files
6
6
  */
7
7
  export declare const LOGICSTAMP_GITIGNORE_PATTERNS: string[];
8
8
  /**
@@ -17,12 +17,27 @@ export declare function readGitignore(targetDir: string): Promise<string>;
17
17
  * Check if a pattern exists in .gitignore content
18
18
  */
19
19
  export declare function hasPattern(content: string, pattern: string): boolean;
20
+ /**
21
+ * Check if .gitignore has the LogicStamp block header comment
22
+ */
23
+ export declare function hasLogicStampBlock(content: string): boolean;
20
24
  /**
21
25
  * Check if .gitignore has LogicStamp patterns
26
+ * This is a legacy function for backward compatibility - checks for key patterns
22
27
  */
23
28
  export declare function hasLogicStampPatterns(content: string): boolean;
24
29
  /**
25
- * Add LogicStamp patterns to .gitignore content
30
+ * Get which LogicStamp patterns are missing from .gitignore content
31
+ */
32
+ export declare function getMissingPatterns(content: string): string[];
33
+ /**
34
+ * Add LogicStamp patterns to .gitignore content (idempotent patch mode)
35
+ *
36
+ * Behavior:
37
+ * - If LogicStamp block exists: append only missing patterns to the block
38
+ * - If LogicStamp block doesn't exist: add full block at the end
39
+ * - Never duplicates patterns
40
+ * - Preserves user's manual additions
26
41
  */
27
42
  export declare function addLogicStampPatterns(content: string): string;
28
43
  /**
@@ -32,11 +47,24 @@ export declare function writeGitignore(targetDir: string, content: string): Prom
32
47
  /**
33
48
  * Add LogicStamp patterns to .gitignore file
34
49
  * Creates .gitignore if it doesn't exist
50
+ * Uses idempotent patch mode - only adds missing patterns if block exists
35
51
  */
36
52
  export declare function ensureGitignorePatterns(targetDir: string): Promise<{
37
53
  added: boolean;
38
54
  created: boolean;
39
55
  }>;
56
+ /**
57
+ * Ensure a specific pattern is in .gitignore
58
+ * Adds the pattern if it doesn't exist, preserves existing content
59
+ *
60
+ * @param targetDir - Project root directory
61
+ * @param pattern - Pattern to ensure (relative to project root, e.g., "reports/security.json")
62
+ * @returns Result indicating if pattern was added and if .gitignore was created
63
+ */
64
+ export declare function ensurePatternInGitignore(targetDir: string, pattern: string): Promise<{
65
+ added: boolean;
66
+ created: boolean;
67
+ }>;
40
68
  /**
41
69
  * Smart .gitignore management with config-based behavior (no prompting)
42
70
  *
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,eAAO,MAAM,6BAA6B,UAOzC,CAAC;AAEF;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOzE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ9D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0B7D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BtF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAY9G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBpF"}
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,eAAO,MAAM,6BAA6B,UAQzC,CAAC;AAEF;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOzE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ9D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAI5D;AA+CD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkD7D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BtF;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAiB9G;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA+B/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBpF"}
@@ -6,15 +6,16 @@ import { join } from 'node:path';
6
6
  import { readConfig } from './config.js';
7
7
  import { debugError } from './debug.js';
8
8
  /**
9
- * Patterns that should be added to .gitignore for LogicStamp context files
9
+ * Patterns that should be added to .gitignore for LogicStamp context & security files
10
10
  */
11
11
  export const LOGICSTAMP_GITIGNORE_PATTERNS = [
12
- '# LogicStamp context files',
12
+ '# LogicStamp context & security files',
13
13
  'context.json',
14
14
  'context_*.json',
15
15
  '*.uif.json',
16
16
  'logicstamp.manifest.json',
17
17
  '.logicstamp/',
18
+ 'stamp_security_report.json',
18
19
  ];
19
20
  /**
20
21
  * Check if .gitignore exists in the given directory
@@ -44,11 +45,18 @@ export async function readGitignore(targetDir) {
44
45
  * Check if a pattern exists in .gitignore content
45
46
  */
46
47
  export function hasPattern(content, pattern) {
47
- const lines = content.split('\n').map(line => line.trim());
48
+ const lines = content.split(/\r?\n/).map(line => line.trim());
48
49
  return lines.includes(pattern);
49
50
  }
51
+ /**
52
+ * Check if .gitignore has the LogicStamp block header comment
53
+ */
54
+ export function hasLogicStampBlock(content) {
55
+ return hasPattern(content, '# LogicStamp context & security files');
56
+ }
50
57
  /**
51
58
  * Check if .gitignore has LogicStamp patterns
59
+ * This is a legacy function for backward compatibility - checks for key patterns
52
60
  */
53
61
  export function hasLogicStampPatterns(content) {
54
62
  // Check for the key patterns (ignore the comment line)
@@ -59,26 +67,94 @@ export function hasLogicStampPatterns(content) {
59
67
  (hasPattern(content, 'context_*.json') || hasPattern(content, 'context_main.json'));
60
68
  }
61
69
  /**
62
- * Add LogicStamp patterns to .gitignore content
70
+ * Get which LogicStamp patterns are missing from .gitignore content
63
71
  */
64
- export function addLogicStampPatterns(content) {
65
- const lines = content.split('\n');
66
- // Check which patterns are missing
67
- const missingPatterns = LOGICSTAMP_GITIGNORE_PATTERNS.filter(pattern => {
68
- if (pattern.startsWith('#'))
69
- return false; // Always add the comment
72
+ export function getMissingPatterns(content) {
73
+ return LOGICSTAMP_GITIGNORE_PATTERNS.filter(pattern => {
70
74
  return !hasPattern(content, pattern);
71
75
  });
72
- if (missingPatterns.length === 0 && hasPattern(content, '# LogicStamp context files')) {
73
- return content; // All patterns already exist
76
+ }
77
+ /**
78
+ * Find the insertion point for LogicStamp patterns in .gitignore content
79
+ * Returns the index where the LogicStamp block starts, or -1 if not found
80
+ */
81
+ function findLogicStampBlockIndex(lines) {
82
+ const headerIndex = lines.findIndex(line => line.trim() === '# LogicStamp context & security files');
83
+ return headerIndex;
84
+ }
85
+ /**
86
+ * Find the insertion point for missing LogicStamp patterns
87
+ * Returns the index after the last existing LogicStamp pattern in the block
88
+ */
89
+ function findLogicStampInsertionPoint(lines, startIndex) {
90
+ // Known LogicStamp patterns (excluding the header comment)
91
+ const knownPatterns = new Set(LOGICSTAMP_GITIGNORE_PATTERNS.filter(p => !p.startsWith('#')).map(p => p.trim()));
92
+ let lastPatternIndex = startIndex; // Start after the header comment
93
+ // Find the last LogicStamp pattern in the block
94
+ for (let i = startIndex + 1; i < lines.length; i++) {
95
+ const trimmed = lines[i].trim();
96
+ // If we hit a blank line, stop here (insert before the blank line)
97
+ if (trimmed === '') {
98
+ return i;
99
+ }
100
+ // If we hit a non-LogicStamp pattern (not a comment, not a known pattern), stop here
101
+ if (!trimmed.startsWith('#') && !knownPatterns.has(trimmed)) {
102
+ return i;
103
+ }
104
+ // If this is a LogicStamp pattern (comment or known pattern), update lastPatternIndex
105
+ if (trimmed.startsWith('#') || knownPatterns.has(trimmed)) {
106
+ lastPatternIndex = i + 1; // Insert after this line
107
+ }
74
108
  }
75
- // Add a blank line before the section if content exists and doesn't end with blank line
76
- let newContent = content;
77
- if (newContent.length > 0 && !newContent.endsWith('\n\n') && !newContent.endsWith('\n')) {
78
- newContent += '\n';
109
+ // Block extends to end of file - insert at the end
110
+ return lastPatternIndex;
111
+ }
112
+ /**
113
+ * Add LogicStamp patterns to .gitignore content (idempotent patch mode)
114
+ *
115
+ * Behavior:
116
+ * - If LogicStamp block exists: append only missing patterns to the block
117
+ * - If LogicStamp block doesn't exist: add full block at the end
118
+ * - Never duplicates patterns
119
+ * - Preserves user's manual additions
120
+ */
121
+ export function addLogicStampPatterns(content) {
122
+ const lines = content.split(/\r?\n/);
123
+ const hasBlock = hasLogicStampBlock(content);
124
+ const missingPatterns = getMissingPatterns(content);
125
+ // If block exists and all patterns are present, return unchanged
126
+ if (hasBlock && missingPatterns.length === 0) {
127
+ return content;
79
128
  }
80
- if (newContent.length > 0 && !newContent.endsWith('\n\n')) {
81
- newContent += '\n';
129
+ // If block exists but patterns are missing, append only missing ones
130
+ if (hasBlock && missingPatterns.length > 0) {
131
+ const blockStartIndex = findLogicStampBlockIndex(lines);
132
+ const insertIndex = findLogicStampInsertionPoint(lines, blockStartIndex);
133
+ // Insert missing patterns right after the last existing LogicStamp pattern
134
+ const newLines = [...lines];
135
+ const patternsToAdd = missingPatterns.map(p => p.trim());
136
+ // Insert patterns at the insertion point
137
+ newLines.splice(insertIndex, 0, ...patternsToAdd);
138
+ // Preserve original line ending style
139
+ const lineEnding = content.includes('\r\n') ? '\r\n' : '\n';
140
+ return newLines.join(lineEnding) + (content.endsWith(lineEnding) ? '' : lineEnding);
141
+ }
142
+ // Block doesn't exist - add full block at the end
143
+ let newContent = content;
144
+ // Add blank lines before the section if content exists
145
+ if (newContent.length > 0) {
146
+ // Normalize line endings and ensure we end with at least one newline
147
+ const normalized = newContent.replace(/\r\n/g, '\n');
148
+ if (!normalized.endsWith('\n')) {
149
+ newContent = normalized + '\n';
150
+ }
151
+ else {
152
+ newContent = normalized;
153
+ }
154
+ // Add one more blank line if content doesn't already end with one
155
+ if (!newContent.endsWith('\n\n')) {
156
+ newContent += '\n';
157
+ }
82
158
  }
83
159
  // Add all LogicStamp patterns as a group
84
160
  newContent += LOGICSTAMP_GITIGNORE_PATTERNS.join('\n') + '\n';
@@ -120,14 +196,50 @@ export async function writeGitignore(targetDir, content) {
120
196
  /**
121
197
  * Add LogicStamp patterns to .gitignore file
122
198
  * Creates .gitignore if it doesn't exist
199
+ * Uses idempotent patch mode - only adds missing patterns if block exists
123
200
  */
124
201
  export async function ensureGitignorePatterns(targetDir) {
125
202
  const exists = await gitignoreExists(targetDir);
126
203
  const content = await readGitignore(targetDir);
127
- if (hasLogicStampPatterns(content)) {
204
+ // Use smart patch mode - will append only missing patterns if block exists
205
+ const newContent = addLogicStampPatterns(content);
206
+ // Check if content actually changed
207
+ const contentChanged = content !== newContent;
208
+ if (!contentChanged) {
128
209
  return { added: false, created: false };
129
210
  }
130
- const newContent = addLogicStampPatterns(content);
211
+ await writeGitignore(targetDir, newContent);
212
+ return { added: true, created: !exists };
213
+ }
214
+ /**
215
+ * Ensure a specific pattern is in .gitignore
216
+ * Adds the pattern if it doesn't exist, preserves existing content
217
+ *
218
+ * @param targetDir - Project root directory
219
+ * @param pattern - Pattern to ensure (relative to project root, e.g., "reports/security.json")
220
+ * @returns Result indicating if pattern was added and if .gitignore was created
221
+ */
222
+ export async function ensurePatternInGitignore(targetDir, pattern) {
223
+ const exists = await gitignoreExists(targetDir);
224
+ const content = await readGitignore(targetDir);
225
+ // Normalize pattern (forward slashes, no leading slash)
226
+ const normalizedPattern = pattern.replace(/\\/g, '/').replace(/^\//, '').trim();
227
+ // Check if pattern already exists
228
+ if (hasPattern(content, normalizedPattern)) {
229
+ return { added: false, created: false };
230
+ }
231
+ // Add pattern to .gitignore
232
+ let newContent = content;
233
+ // Ensure content ends with newline
234
+ if (newContent.length > 0 && !newContent.endsWith('\n')) {
235
+ newContent += '\n';
236
+ }
237
+ // Add blank line before pattern if content exists
238
+ if (newContent.length > 0 && !newContent.endsWith('\n\n')) {
239
+ newContent += '\n';
240
+ }
241
+ // Add pattern
242
+ newContent += normalizedPattern + '\n';
131
243
  await writeGitignore(targetDir, newContent);
132
244
  return { added: true, created: !exists };
133
245
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,uCAAuC;IACvC,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,0BAA0B;IAC1B,cAAc;IACd,4BAA4B;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,OAAe;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,UAAU,CAAC,OAAO,EAAE,uCAAuC,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,uDAAuD;IACvD,MAAM,QAAQ,GAAG,6BAA6B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAE/E,4CAA4C;IAC5C,+EAA+E;IAC/E,OAAO,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC;QACnC,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,6BAA6B,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACpD,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,wBAAwB,CAAC,KAAe;IAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,uCAAuC,CAAC,CAAC;IACrG,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAS,4BAA4B,CAAC,KAAe,EAAE,UAAkB;IACvE,2DAA2D;IAC3D,MAAM,aAAa,GAAG,IAAI,GAAG,CAC3B,6BAA6B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CACjF,CAAC;IAEF,IAAI,gBAAgB,GAAG,UAAU,CAAC,CAAC,iCAAiC;IAEpE,gDAAgD;IAChD,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhC,mEAAmE;QACnE,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,qFAAqF;QACrF,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5D,OAAO,CAAC,CAAC;QACX,CAAC;QAED,sFAAsF;QACtF,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1D,gBAAgB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,yBAAyB;QACrD,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEpD,iEAAiE;IACjE,IAAI,QAAQ,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,qEAAqE;IACrE,IAAI,QAAQ,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,4BAA4B,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAEzE,2EAA2E;QAC3E,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC5B,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzD,yCAAyC;QACzC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC;QAElD,sCAAsC;QACtC,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5D,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACtF,CAAC;IAED,kDAAkD;IAClD,IAAI,UAAU,GAAG,OAAO,CAAC;IAEzB,uDAAuD;IACvD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,qEAAqE;QACrE,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,UAAU,CAAC;QAC1B,CAAC;QAED,kEAAkE;QAClE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,UAAU,IAAI,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,UAAU,IAAI,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE9D,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,SAAiB,EAAE,OAAe;IACrE,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAA8B,CAAC;QAC3C,UAAU,CAAC,WAAW,EAAE,gBAAgB,EAAE;YACxC,aAAa;YACb,SAAS;YACT,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;SACf,CAAC,CAAC;QAEH,IAAI,WAAmB,CAAC;QACxB,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ;gBACX,WAAW,GAAG,oCAAoC,aAAa,GAAG,CAAC;gBACnE,MAAM;YACR,KAAK,QAAQ;gBACX,WAAW,GAAG,kCAAkC,aAAa,GAAG,CAAC;gBACjE,MAAM;YACR,KAAK,QAAQ;gBACX,WAAW,GAAG,2CAA2C,aAAa,GAAG,CAAC;gBAC1E,MAAM;YACR;gBACE,WAAW,GAAG,oCAAoC,aAAa,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;QACvF,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,SAAiB;IAC7D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAE/C,2EAA2E;IAC3E,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAElD,oCAAoC;IACpC,MAAM,cAAc,GAAG,OAAO,KAAK,UAAU,CAAC;IAE9C,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,cAAc,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAE5C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,SAAiB,EACjB,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAE/C,wDAAwD;IACxD,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEhF,kCAAkC;IAClC,IAAI,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,4BAA4B;IAC5B,IAAI,UAAU,GAAG,OAAO,CAAC;IAEzB,mCAAmC;IACnC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,UAAU,IAAI,IAAI,CAAC;IACrB,CAAC;IAED,kDAAkD;IAClD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1D,UAAU,IAAI,IAAI,CAAC;IACrB,CAAC;IAED,cAAc;IACd,UAAU,IAAI,iBAAiB,GAAG,IAAI,CAAC;IAEvC,MAAM,cAAc,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAE5C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,UAAuC,EAAE;IAEzC,8CAA8C;IAC9C,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1E,CAAC;IAED,kCAAkC;IAClC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3E,CAAC;IAED,oCAAoC;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;IAE3C,6DAA6D;IAC7D,6DAA6D;IAC7D,IAAI,MAAM,CAAC,mBAAmB,KAAK,OAAO,EAAE,CAAC;QAC3C,yEAAyE;QACzE,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,SAAS,CAAC,CAAC;QACxD,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAED,uDAAuD;IACvD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Simple secret detection utilities
3
+ * Detects common patterns for API keys, tokens, passwords, etc.
4
+ */
5
+ export interface SecretMatch {
6
+ file: string;
7
+ line: number;
8
+ column: number;
9
+ type: string;
10
+ snippet: string;
11
+ severity: 'high' | 'medium' | 'low';
12
+ }
13
+ /**
14
+ * Scan a file for secrets
15
+ */
16
+ export declare function scanFileForSecrets(filePath: string, content: string): SecretMatch[];
17
+ /**
18
+ * Filter out false positives (common patterns that look like secrets but aren't)
19
+ */
20
+ export declare function filterFalsePositives(matches: SecretMatch[]): SecretMatch[];
21
+ //# sourceMappingURL=secretDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretDetector.d.ts","sourceRoot":"","sources":["../../src/utils/secretDetector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACrC;AAyFD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,WAAW,EAAE,CAmCf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAyB1E"}