mcp-code-context 2.2.0 → 2.3.1

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 (128) hide show
  1. package/.io/RULES.md +12 -0
  2. package/CHANGELOG.md +88 -1
  3. package/README.md +27 -0
  4. package/RELEASE_NOTES_v2.3.0.md +228 -0
  5. package/RELEASE_NOTES_v2.3.1.md +110 -0
  6. package/dist/src/ast/writers/safeRename.d.ts +14 -0
  7. package/dist/src/ast/writers/safeRename.js +258 -0
  8. package/dist/src/ast/writers/safeRename.js.map +1 -0
  9. package/dist/src/ast/writers/symbolWriter.d.ts +2 -0
  10. package/dist/src/ast/writers/symbolWriter.js +9 -14
  11. package/dist/src/ast/writers/symbolWriter.js.map +1 -1
  12. package/dist/src/cache/astCache.d.ts +33 -0
  13. package/dist/src/cache/astCache.js +113 -0
  14. package/dist/src/cache/astCache.js.map +1 -0
  15. package/dist/src/handlers/readHandlers.d.ts +70 -0
  16. package/dist/src/handlers/readHandlers.js +431 -0
  17. package/dist/src/handlers/readHandlers.js.map +1 -0
  18. package/dist/src/handlers/utilHandlers.d.ts +31 -0
  19. package/dist/src/handlers/utilHandlers.js +69 -0
  20. package/dist/src/handlers/utilHandlers.js.map +1 -0
  21. package/dist/src/handlers/writeHandlers.d.ts +57 -0
  22. package/dist/src/handlers/writeHandlers.js +475 -0
  23. package/dist/src/handlers/writeHandlers.js.map +1 -0
  24. package/dist/src/index.d.ts +6 -143
  25. package/dist/src/index.js +77 -1091
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/utils/arrayUtils.d.ts +12 -0
  28. package/dist/src/utils/arrayUtils.js +27 -0
  29. package/dist/src/utils/arrayUtils.js.map +1 -0
  30. package/dist/src/utils/constants.d.ts +46 -0
  31. package/dist/src/utils/constants.js +112 -0
  32. package/dist/src/utils/constants.js.map +1 -0
  33. package/dist/src/utils/ignoreManager.d.ts +8 -0
  34. package/dist/src/utils/ignoreManager.js +49 -0
  35. package/dist/src/utils/ignoreManager.js.map +1 -1
  36. package/dist/src/utils/normalization.d.ts +49 -0
  37. package/dist/src/utils/normalization.js +173 -0
  38. package/dist/src/utils/normalization.js.map +1 -0
  39. package/dist/src/utils/projectRoot.d.ts +12 -5
  40. package/dist/src/utils/projectRoot.js +22 -20
  41. package/dist/src/utils/projectRoot.js.map +1 -1
  42. package/dist/src/utils/secureValidation.d.ts +15 -0
  43. package/dist/src/utils/secureValidation.js +41 -0
  44. package/dist/src/utils/secureValidation.js.map +1 -0
  45. package/dist/src/utils/transactionManager.d.ts +45 -0
  46. package/dist/src/utils/transactionManager.js +102 -0
  47. package/dist/src/utils/transactionManager.js.map +1 -0
  48. package/dist/src/utils/validation.d.ts +87 -0
  49. package/dist/src/utils/validation.js +231 -0
  50. package/dist/src/utils/validation.js.map +1 -0
  51. package/docs/ARCHITECTURE.md +300 -0
  52. package/docs/architecture/ADR-001-modular-handlers.md +119 -0
  53. package/package.json +5 -5
  54. package/AGENT_INSTRUCTIONS.md +0 -135
  55. package/DEPLOYMENT_INSTRUCTIONS.md +0 -110
  56. package/MEJORAS_PROPUESTAS.md +0 -324
  57. package/dist/src/tests/test-confirmation-flow.d.ts +0 -1
  58. package/dist/src/tests/test-confirmation-flow.js +0 -43
  59. package/dist/src/tests/test-confirmation-flow.js.map +0 -1
  60. package/dist/tests/debug-replace.d.ts +0 -1
  61. package/dist/tests/debug-replace.js +0 -17
  62. package/dist/tests/debug-replace.js.map +0 -1
  63. package/dist/tests/test-backup-system.d.ts +0 -7
  64. package/dist/tests/test-backup-system.js +0 -152
  65. package/dist/tests/test-backup-system.js.map +0 -1
  66. package/dist/tests/test-confirmation-flow.d.ts +0 -1
  67. package/dist/tests/test-confirmation-flow.js +0 -43
  68. package/dist/tests/test-confirmation-flow.js.map +0 -1
  69. package/dist/tests/test-dart.d.ts +0 -1
  70. package/dist/tests/test-dart.js +0 -242
  71. package/dist/tests/test-dart.js.map +0 -1
  72. package/dist/tests/test-new-tools.d.ts +0 -4
  73. package/dist/tests/test-new-tools.js +0 -147
  74. package/dist/tests/test-new-tools.js.map +0 -1
  75. package/dist/tests/test-php-ast.d.ts +0 -1
  76. package/dist/tests/test-php-ast.js +0 -152
  77. package/dist/tests/test-php-ast.js.map +0 -1
  78. package/dist/tests/test-php.d.ts +0 -1
  79. package/dist/tests/test-php.js +0 -234
  80. package/dist/tests/test-php.js.map +0 -1
  81. package/dist/tests/test-smoke.d.ts +0 -5
  82. package/dist/tests/test-smoke.js +0 -83
  83. package/dist/tests/test-smoke.js.map +0 -1
  84. package/dist/tests/writers/test-crlf-handling.d.ts +0 -4
  85. package/dist/tests/writers/test-crlf-handling.js +0 -73
  86. package/dist/tests/writers/test-crlf-handling.js.map +0 -1
  87. package/dist/tests/writers/test-write-smoke.d.ts +0 -9
  88. package/dist/tests/writers/test-write-smoke.js +0 -346
  89. package/dist/tests/writers/test-write-smoke.js.map +0 -1
  90. package/src/ast/dartCompressor.ts +0 -1013
  91. package/src/ast/phpCompressor.ts +0 -814
  92. package/src/ast/semanticCompressor.ts +0 -808
  93. package/src/ast/writers/dartWriter.ts +0 -648
  94. package/src/ast/writers/phpWriter.ts +0 -508
  95. package/src/ast/writers/pyWriter.ts +0 -446
  96. package/src/ast/writers/symbolWriter.ts +0 -277
  97. package/src/ast/writers/tsWriter.ts +0 -418
  98. package/src/index.ts +0 -1784
  99. package/src/tools/readFileLines.ts +0 -104
  100. package/src/tools/searchCodePattern.ts +0 -129
  101. package/src/utils/backupManager.ts +0 -141
  102. package/src/utils/confirmationCache.ts +0 -61
  103. package/src/utils/diffEngine.ts +0 -223
  104. package/src/utils/fuzzyMatch.ts +0 -86
  105. package/src/utils/ignoreManager.ts +0 -144
  106. package/src/utils/projectRoot.ts +0 -44
  107. package/tests/test-backup-system.ts +0 -174
  108. package/tests/test-confirmation-flow.ts +0 -49
  109. package/tests/test-dart.d.ts +0 -1
  110. package/tests/test-dart.js +0 -209
  111. package/tests/test-dart.js.map +0 -1
  112. package/tests/test-dart.ts +0 -265
  113. package/tests/test-new-tools.ts +0 -165
  114. package/tests/test-php-ast.d.ts +0 -1
  115. package/tests/test-php-ast.js +0 -152
  116. package/tests/test-php-ast.js.map +0 -1
  117. package/tests/test-php-ast.ts +0 -155
  118. package/tests/test-php.d.ts +0 -1
  119. package/tests/test-php.js +0 -234
  120. package/tests/test-php.js.map +0 -1
  121. package/tests/test-php.ts +0 -261
  122. package/tests/test-smoke.d.ts +0 -5
  123. package/tests/test-smoke.js +0 -83
  124. package/tests/test-smoke.js.map +0 -1
  125. package/tests/test-smoke.ts +0 -93
  126. package/tests/writers/test-crlf-handling.ts +0 -100
  127. package/tests/writers/test-write-smoke.ts +0 -568
  128. package/tsconfig.json +0 -19
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalization.js","sourceRoot":"","sources":["../../../src/utils/normalization.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,17 @@
1
1
  /**
2
- * projectRoot.ts — Project Root Discovery Utility
3
- *
4
- * Finds the root directory of a project by looking for common markers.
2
+ * Secure Project Root Detection
3
+ * Ensures all file operations are contained within project boundaries
5
4
  */
6
5
  /**
7
- * Find the project root by walking up from a file path.
8
- * Returns undefined if no root marker is found.
6
+ * Find project root by walking up from a file path
7
+ * Returns undefined if no root marker found
9
8
  */
10
9
  export declare function findProjectRoot(filePath: string): string | undefined;
10
+ /**
11
+ * Validate that a file path is within project boundaries
12
+ * MANDATORY for all write operations
13
+ */
14
+ export declare function enforceProjectBoundary(filePath: string, projectRoot: string): {
15
+ valid: boolean;
16
+ error?: string;
17
+ };
@@ -1,28 +1,13 @@
1
1
  /**
2
- * projectRoot.ts — Project Root Discovery Utility
3
- *
4
- * Finds the root directory of a project by looking for common markers.
2
+ * Secure Project Root Detection
3
+ * Ensures all file operations are contained within project boundaries
5
4
  */
6
5
  import * as fs from "node:fs";
7
6
  import * as path from "node:path";
8
- const ROOT_MARKERS = [
9
- "package.json",
10
- ".git",
11
- "pyproject.toml",
12
- "setup.py",
13
- "Cargo.toml",
14
- "go.mod",
15
- "pom.xml",
16
- "build.gradle",
17
- "CMakeLists.txt",
18
- ".gitignore",
19
- "Gemfile",
20
- "composer.json",
21
- "pubspec.yaml",
22
- ];
7
+ const ROOT_MARKERS = ["package.json", ".git", "pubspec.yaml", "pyproject.toml", "Cargo.toml"];
23
8
  /**
24
- * Find the project root by walking up from a file path.
25
- * Returns undefined if no root marker is found.
9
+ * Find project root by walking up from a file path
10
+ * Returns undefined if no root marker found
26
11
  */
27
12
  export function findProjectRoot(filePath) {
28
13
  let current = path.dirname(path.resolve(filePath));
@@ -37,4 +22,21 @@ export function findProjectRoot(filePath) {
37
22
  }
38
23
  return undefined;
39
24
  }
25
+ /**
26
+ * Validate that a file path is within project boundaries
27
+ * MANDATORY for all write operations
28
+ */
29
+ export function enforceProjectBoundary(filePath, projectRoot) {
30
+ const normalized = path.resolve(filePath);
31
+ const normalizedRoot = path.resolve(projectRoot);
32
+ const relative = path.relative(normalizedRoot, normalized);
33
+ // If relative path starts with .., it's outside the project root
34
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
35
+ return {
36
+ valid: false,
37
+ error: `Security: Path outside project root. File: ${normalized}, Root: ${normalizedRoot}`
38
+ };
39
+ }
40
+ return { valid: true };
41
+ }
40
42
  //# sourceMappingURL=projectRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../../src/utils/projectRoot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG;IACnB,cAAc;IACd,MAAM;IACN,gBAAgB;IAChB,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,SAAS;IACT,eAAe;IACf,cAAc;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;IAEtC,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC9C,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../../src/utils/projectRoot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAE9F;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;IAEtC,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC9C,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,WAAmB;IAEnB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAE3D,iEAAiE;IACjE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,8CAA8C,UAAU,WAAW,cAAc,EAAE;SAC3F,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Secure validation helper for write operations
3
+ * Enforces project boundary checks
4
+ */
5
+ export interface SecureValidationResult {
6
+ valid: boolean;
7
+ resolvedPath?: string;
8
+ projectRoot?: string;
9
+ error?: string;
10
+ }
11
+ /**
12
+ * Validate file path with mandatory project boundary enforcement
13
+ * Use this for ALL write operations
14
+ */
15
+ export declare function validateFilePathSecure(filePath: string): SecureValidationResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Secure validation helper for write operations
3
+ * Enforces project boundary checks
4
+ */
5
+ import { validateFilePath } from "./validation.js";
6
+ import { findProjectRoot, enforceProjectBoundary } from "./projectRoot.js";
7
+ /**
8
+ * Validate file path with mandatory project boundary enforcement
9
+ * Use this for ALL write operations
10
+ */
11
+ export function validateFilePathSecure(filePath) {
12
+ const validation = validateFilePath(filePath);
13
+ if (!validation.valid) {
14
+ return {
15
+ valid: false,
16
+ error: validation.error
17
+ };
18
+ }
19
+ const resolvedPath = validation.normalizedPath;
20
+ // SECURITY: Enforce project boundary for write operations
21
+ const projectRoot = findProjectRoot(resolvedPath);
22
+ if (!projectRoot) {
23
+ return {
24
+ valid: false,
25
+ error: "Cannot determine project root. Ensure file is within a valid project."
26
+ };
27
+ }
28
+ const boundaryCheck = enforceProjectBoundary(resolvedPath, projectRoot);
29
+ if (!boundaryCheck.valid) {
30
+ return {
31
+ valid: false,
32
+ error: boundaryCheck.error
33
+ };
34
+ }
35
+ return {
36
+ valid: true,
37
+ resolvedPath,
38
+ projectRoot
39
+ };
40
+ }
41
+ //# sourceMappingURL=secureValidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secureValidation.js","sourceRoot":"","sources":["../../../src/utils/secureValidation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAS3E;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,UAAU,CAAC,KAAK;SACxB,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,cAAe,CAAC;IAEhD,0DAA0D;IAC1D,MAAM,WAAW,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,uEAAuE;SAC/E,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,sBAAsB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACxE,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,aAAa,CAAC,KAAK;SAC3B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,YAAY;QACZ,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Transaction Manager - Atomic Multi-File Operations
3
+ * Ensures all-or-nothing writes with automatic rollback on failure
4
+ */
5
+ export interface FileChange {
6
+ filePath: string;
7
+ newContent: string;
8
+ }
9
+ export declare class TransactionManager {
10
+ private staging;
11
+ private backedUpFiles;
12
+ /**
13
+ * Stage a file change for commit
14
+ */
15
+ stage(filePath: string, newContent: string): void;
16
+ /**
17
+ * Stage multiple file changes
18
+ */
19
+ stageMultiple(changes: FileChange[]): void;
20
+ /**
21
+ * Commit all staged changes atomically
22
+ * Creates backups first, then writes all files
23
+ * Rolls back automatically on any failure
24
+ */
25
+ commit(): Promise<{
26
+ success: boolean;
27
+ error?: string;
28
+ }>;
29
+ /**
30
+ * Rollback all changes by restoring from backups
31
+ */
32
+ rollback(): Promise<void>;
33
+ /**
34
+ * Clear staging area and backup tracking
35
+ */
36
+ clear(): void;
37
+ /**
38
+ * Get number of staged changes
39
+ */
40
+ get stagedCount(): number;
41
+ /**
42
+ * Get list of staged file paths
43
+ */
44
+ getStagedFiles(): string[];
45
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Transaction Manager - Atomic Multi-File Operations
3
+ * Ensures all-or-nothing writes with automatic rollback on failure
4
+ */
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import { createBackup, restoreBackup } from "./backupManager.js";
8
+ export class TransactionManager {
9
+ staging = new Map();
10
+ backedUpFiles = new Set();
11
+ /**
12
+ * Stage a file change for commit
13
+ */
14
+ stage(filePath, newContent) {
15
+ const resolved = path.resolve(filePath);
16
+ this.staging.set(resolved, newContent);
17
+ }
18
+ /**
19
+ * Stage multiple file changes
20
+ */
21
+ stageMultiple(changes) {
22
+ for (const change of changes) {
23
+ this.stage(change.filePath, change.newContent);
24
+ }
25
+ }
26
+ /**
27
+ * Commit all staged changes atomically
28
+ * Creates backups first, then writes all files
29
+ * Rolls back automatically on any failure
30
+ */
31
+ async commit() {
32
+ if (this.staging.size === 0) {
33
+ return { success: true };
34
+ }
35
+ // Phase 1: Create backups
36
+ try {
37
+ for (const [filePath] of this.staging) {
38
+ createBackup(filePath);
39
+ this.backedUpFiles.add(filePath);
40
+ }
41
+ }
42
+ catch (error) {
43
+ await this.rollback();
44
+ return {
45
+ success: false,
46
+ error: `Backup failed: ${error instanceof Error ? error.message : String(error)}`
47
+ };
48
+ }
49
+ // Phase 2: Write all files
50
+ try {
51
+ for (const [filePath, content] of this.staging) {
52
+ await fs.promises.writeFile(filePath, content, "utf-8");
53
+ }
54
+ }
55
+ catch (error) {
56
+ await this.rollback();
57
+ return {
58
+ success: false,
59
+ error: `Write failed: ${error instanceof Error ? error.message : String(error)}`
60
+ };
61
+ }
62
+ // Phase 3: Validate (optional syntax check could go here)
63
+ // For now, we trust the write succeeded
64
+ this.clear();
65
+ return { success: true };
66
+ }
67
+ /**
68
+ * Rollback all changes by restoring from backups
69
+ */
70
+ async rollback() {
71
+ for (const filePath of this.backedUpFiles) {
72
+ try {
73
+ restoreBackup(filePath);
74
+ }
75
+ catch (error) {
76
+ // Log but continue rolling back other files
77
+ console.error(`Failed to restore ${filePath}:`, error);
78
+ }
79
+ }
80
+ this.clear();
81
+ }
82
+ /**
83
+ * Clear staging area and backup tracking
84
+ */
85
+ clear() {
86
+ this.staging.clear();
87
+ this.backedUpFiles.clear();
88
+ }
89
+ /**
90
+ * Get number of staged changes
91
+ */
92
+ get stagedCount() {
93
+ return this.staging.size;
94
+ }
95
+ /**
96
+ * Get list of staged file paths
97
+ */
98
+ getStagedFiles() {
99
+ return Array.from(this.staging.keys());
100
+ }
101
+ }
102
+ //# sourceMappingURL=transactionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionManager.js","sourceRoot":"","sources":["../../../src/utils/transactionManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * validation.ts — Input Validation & Security
3
+ *
4
+ * Centralized validation logic to prevent security vulnerabilities:
5
+ * - Path traversal attacks
6
+ * - ReDoS (Regular Expression Denial of Service)
7
+ * - Injection attacks
8
+ * - Resource exhaustion
9
+ */
10
+ export interface PathValidationResult {
11
+ valid: boolean;
12
+ error?: string;
13
+ normalizedPath?: string;
14
+ }
15
+ /**
16
+ * Validate that a file path is safe and within allowed boundaries.
17
+ * Prevents path traversal attacks and access to sensitive system files.
18
+ *
19
+ * @param filePath - The path to validate
20
+ * @param projectRoot - Optional project root to enforce containment
21
+ */
22
+ export declare function validateFilePath(filePath: string, projectRoot?: string): PathValidationResult;
23
+ /**
24
+ * Validate that a directory path is safe for operations.
25
+ */
26
+ export declare function validateDirectoryPath(dirPath: string, projectRoot?: string): PathValidationResult;
27
+ export interface SymbolValidationResult {
28
+ valid: boolean;
29
+ error?: string;
30
+ }
31
+ /**
32
+ * Validate a symbol name to prevent ReDoS and injection attacks.
33
+ *
34
+ * @param symbolName - The symbol name to validate
35
+ */
36
+ export declare function validateSymbolName(symbolName: string): SymbolValidationResult;
37
+ export interface RegexValidationResult {
38
+ valid: boolean;
39
+ error?: string;
40
+ safeRegex?: RegExp;
41
+ }
42
+ /**
43
+ * Validate and sanitize a regex pattern to prevent ReDoS attacks.
44
+ *
45
+ * @param pattern - The regex pattern to validate
46
+ * @param flags - Optional regex flags
47
+ */
48
+ export declare function validateRegexPattern(pattern: string, flags?: string): RegexValidationResult;
49
+ /**
50
+ * Create a safe regex with timeout protection.
51
+ * Uses a simple timeout mechanism to prevent long-running regex operations.
52
+ *
53
+ * @param pattern - The regex pattern
54
+ * @param flags - Optional regex flags
55
+ * @param timeoutMs - Timeout in milliseconds (default: 1000ms)
56
+ */
57
+ export declare function createSafeRegex(pattern: string, flags?: string, timeoutMs?: number): RegExp;
58
+ export interface FileSizeValidationResult {
59
+ valid: boolean;
60
+ error?: string;
61
+ size?: number;
62
+ }
63
+ /**
64
+ * Validate that a file is not too large to process safely.
65
+ *
66
+ * @param filePath - Path to the file
67
+ */
68
+ export declare function validateFileSize(filePath: string): FileSizeValidationResult;
69
+ /**
70
+ * Check if file content contains null bytes (likely binary).
71
+ */
72
+ export declare function isBinaryContent(content: string): boolean;
73
+ /**
74
+ * Validate that file content is safe to process.
75
+ */
76
+ export declare function validateFileContent(content: string): SymbolValidationResult;
77
+ /**
78
+ * Validate multiple file paths at once.
79
+ * Returns only valid paths and collects errors.
80
+ */
81
+ export declare function validateFilePaths(filePaths: string[], projectRoot?: string): {
82
+ validPaths: string[];
83
+ errors: Array<{
84
+ path: string;
85
+ error: string;
86
+ }>;
87
+ };
@@ -0,0 +1,231 @@
1
+ /**
2
+ * validation.ts — Input Validation & Security
3
+ *
4
+ * Centralized validation logic to prevent security vulnerabilities:
5
+ * - Path traversal attacks
6
+ * - ReDoS (Regular Expression Denial of Service)
7
+ * - Injection attacks
8
+ * - Resource exhaustion
9
+ */
10
+ import * as path from "node:path";
11
+ import * as fs from "node:fs";
12
+ import { MAX_SYMBOL_NAME_LENGTH, MAX_REGEX_PATTERN_LENGTH, MAX_FILE_SIZE_BYTES, DANGEROUS_PATTERN_REGEX, } from "./constants.js";
13
+ /**
14
+ * Validate that a file path is safe and within allowed boundaries.
15
+ * Prevents path traversal attacks and access to sensitive system files.
16
+ *
17
+ * @param filePath - The path to validate
18
+ * @param projectRoot - Optional project root to enforce containment
19
+ */
20
+ export function validateFilePath(filePath, projectRoot) {
21
+ // Normalize the path to resolve .. and . segments
22
+ const normalized = path.resolve(filePath);
23
+ // Check for dangerous patterns
24
+ if (DANGEROUS_PATTERN_REGEX.test(normalized)) {
25
+ return {
26
+ valid: false,
27
+ error: `Path contains dangerous pattern: ${normalized}`,
28
+ };
29
+ }
30
+ // If project root is provided, ensure path is within it
31
+ if (projectRoot) {
32
+ const normalizedRoot = path.resolve(projectRoot);
33
+ const relative = path.relative(normalizedRoot, normalized);
34
+ // If relative path starts with .., it's outside the project root
35
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
36
+ return {
37
+ valid: false,
38
+ error: `Path is outside project root: ${normalized}`,
39
+ };
40
+ }
41
+ }
42
+ // Check if path exists
43
+ if (!fs.existsSync(normalized)) {
44
+ return {
45
+ valid: false,
46
+ error: `Path does not exist: ${normalized}`,
47
+ };
48
+ }
49
+ return {
50
+ valid: true,
51
+ normalizedPath: normalized,
52
+ };
53
+ }
54
+ /**
55
+ * Validate that a directory path is safe for operations.
56
+ */
57
+ export function validateDirectoryPath(dirPath, projectRoot) {
58
+ const result = validateFilePath(dirPath, projectRoot);
59
+ if (!result.valid)
60
+ return result;
61
+ // Ensure it's actually a directory
62
+ const stat = fs.statSync(result.normalizedPath);
63
+ if (!stat.isDirectory()) {
64
+ return {
65
+ valid: false,
66
+ error: `Path is not a directory: ${result.normalizedPath}`,
67
+ };
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Validate a symbol name to prevent ReDoS and injection attacks.
73
+ *
74
+ * @param symbolName - The symbol name to validate
75
+ */
76
+ export function validateSymbolName(symbolName) {
77
+ // Check length to prevent ReDoS in fuzzy matching
78
+ if (symbolName.length > MAX_SYMBOL_NAME_LENGTH) {
79
+ return {
80
+ valid: false,
81
+ error: `Symbol name too long (max ${MAX_SYMBOL_NAME_LENGTH} characters)`,
82
+ };
83
+ }
84
+ // Check for null bytes (can cause issues in C-based parsers)
85
+ if (symbolName.includes("\0")) {
86
+ return {
87
+ valid: false,
88
+ error: "Symbol name contains null byte",
89
+ };
90
+ }
91
+ // Ensure it's a valid identifier (basic check)
92
+ // Allows Unicode letters, digits, underscore, dollar sign
93
+ if (!/^[\p{L}\p{N}_$]+$/u.test(symbolName)) {
94
+ return {
95
+ valid: false,
96
+ error: "Symbol name contains invalid characters",
97
+ };
98
+ }
99
+ return { valid: true };
100
+ }
101
+ /**
102
+ * Validate and sanitize a regex pattern to prevent ReDoS attacks.
103
+ *
104
+ * @param pattern - The regex pattern to validate
105
+ * @param flags - Optional regex flags
106
+ */
107
+ export function validateRegexPattern(pattern, flags) {
108
+ // Check length
109
+ if (pattern.length > MAX_REGEX_PATTERN_LENGTH) {
110
+ return {
111
+ valid: false,
112
+ error: `Regex pattern too long (max ${MAX_REGEX_PATTERN_LENGTH} characters)`,
113
+ };
114
+ }
115
+ // Check for catastrophic backtracking patterns
116
+ // These are common ReDoS patterns
117
+ const dangerousPatterns = [
118
+ /(\w+\*)+/, // Nested quantifiers
119
+ /(\w+)+/, // Repeated groups
120
+ /(\w*)*/, // Nested stars
121
+ /(\w+\|)+/, // Alternation with quantifiers
122
+ ];
123
+ for (const dangerous of dangerousPatterns) {
124
+ if (dangerous.test(pattern)) {
125
+ return {
126
+ valid: false,
127
+ error: "Regex pattern may cause catastrophic backtracking (ReDoS)",
128
+ };
129
+ }
130
+ }
131
+ // Try to compile the regex
132
+ try {
133
+ const regex = new RegExp(pattern, flags);
134
+ return {
135
+ valid: true,
136
+ safeRegex: regex,
137
+ };
138
+ }
139
+ catch (error) {
140
+ return {
141
+ valid: false,
142
+ error: `Invalid regex pattern: ${error instanceof Error ? error.message : String(error)}`,
143
+ };
144
+ }
145
+ }
146
+ /**
147
+ * Create a safe regex with timeout protection.
148
+ * Uses a simple timeout mechanism to prevent long-running regex operations.
149
+ *
150
+ * @param pattern - The regex pattern
151
+ * @param flags - Optional regex flags
152
+ * @param timeoutMs - Timeout in milliseconds (default: 1000ms)
153
+ */
154
+ export function createSafeRegex(pattern, flags, timeoutMs = 1000) {
155
+ const validation = validateRegexPattern(pattern, flags);
156
+ if (!validation.valid) {
157
+ throw new Error(validation.error);
158
+ }
159
+ // Return the validated regex
160
+ // Note: JavaScript doesn't have built-in regex timeout,
161
+ // so we rely on validation to prevent ReDoS
162
+ return validation.safeRegex;
163
+ }
164
+ /**
165
+ * Validate that a file is not too large to process safely.
166
+ *
167
+ * @param filePath - Path to the file
168
+ */
169
+ export function validateFileSize(filePath) {
170
+ try {
171
+ const stat = fs.statSync(filePath);
172
+ const size = stat.size;
173
+ if (size > MAX_FILE_SIZE_BYTES) {
174
+ return {
175
+ valid: false,
176
+ error: `File too large: ${(size / 1024 / 1024).toFixed(2)}MB (max ${MAX_FILE_SIZE_BYTES / 1024 / 1024}MB)`,
177
+ size,
178
+ };
179
+ }
180
+ return {
181
+ valid: true,
182
+ size,
183
+ };
184
+ }
185
+ catch (error) {
186
+ return {
187
+ valid: false,
188
+ error: `Failed to check file size: ${error instanceof Error ? error.message : String(error)}`,
189
+ };
190
+ }
191
+ }
192
+ // ─── Content Validation ─────────────────────────────────────────────
193
+ /**
194
+ * Check if file content contains null bytes (likely binary).
195
+ */
196
+ export function isBinaryContent(content) {
197
+ return content.includes("\0");
198
+ }
199
+ /**
200
+ * Validate that file content is safe to process.
201
+ */
202
+ export function validateFileContent(content) {
203
+ // Check for null bytes
204
+ if (isBinaryContent(content)) {
205
+ return {
206
+ valid: false,
207
+ error: "File appears to be binary (contains null bytes)",
208
+ };
209
+ }
210
+ return { valid: true };
211
+ }
212
+ // ─── Batch Validation ───────────────────────────────────────────────
213
+ /**
214
+ * Validate multiple file paths at once.
215
+ * Returns only valid paths and collects errors.
216
+ */
217
+ export function validateFilePaths(filePaths, projectRoot) {
218
+ const validPaths = [];
219
+ const errors = [];
220
+ for (const filePath of filePaths) {
221
+ const result = validateFilePath(filePath, projectRoot);
222
+ if (result.valid) {
223
+ validPaths.push(result.normalizedPath);
224
+ }
225
+ else {
226
+ errors.push({ path: filePath, error: result.error });
227
+ }
228
+ }
229
+ return { validPaths, errors };
230
+ }
231
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/utils/validation.ts"],"names":[],"mappings":"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"}