claude-flow-novice 2.15.3 → 2.15.5

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 (473) hide show
  1. package/.claude/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  2. package/.claude/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  3. package/.claude/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  4. package/.claude/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  5. package/.claude/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  6. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  7. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  8. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  9. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  10. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  11. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  12. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  13. package/.claude/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  14. package/.claude/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  15. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  16. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  17. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  18. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  19. package/.claude/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  20. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  21. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  22. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  23. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  24. package/.claude/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  25. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  26. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  27. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  28. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  29. package/.claude/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  30. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  31. package/.claude/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  32. package/.claude/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  33. package/.claude/commands/cfn-loop-cli.md +29 -6
  34. package/.claude/commands/switch-api.md +31 -10
  35. package/.claude/hooks/cfn-lint-sql-injection.sh +61 -0
  36. package/.claude/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  37. package/.claude/hooks/cfn-pre-edit-security-warning.sh +40 -0
  38. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  39. package/.claude/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  40. package/.claude/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  41. package/.claude/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  42. package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  43. package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  44. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  45. package/.claude/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  46. package/.claude/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  47. package/.claude/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  48. package/.claude/skills/cfn-redis-coordination/agent-log.sh +4 -0
  49. package/.claude/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  50. package/.claude/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  51. package/.claude/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  52. package/.claude/skills/cfn-redis-coordination/get-context.sh +33 -0
  53. package/.claude/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  54. package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  55. package/.claude/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  56. package/.claude/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  57. package/.claude/skills/cfn-redis-coordination/report-completion.sh +24 -31
  58. package/.claude/skills/cfn-redis-coordination/store-context.sh +4 -0
  59. package/.claude/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  60. package/.claude/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  61. package/.claude/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  62. package/.claude/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  63. package/.claude/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  64. package/README.md +116 -475
  65. package/claude-assets/agents/cfn-dev-team/README.md +103 -0
  66. package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +1 -1
  67. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +77 -15
  68. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +355 -6
  69. package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +82 -1
  70. package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +82 -1
  71. package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +77 -15
  72. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +99 -12
  73. package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +1 -1
  74. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +97 -0
  75. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +20 -1
  76. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +97 -0
  77. package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +110 -13
  78. package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +106 -15
  79. package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +115 -11
  80. package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +94 -7
  81. package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +87 -9
  82. package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +85 -7
  83. package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +160 -28
  84. package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +101 -19
  85. package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +108 -14
  86. package/claude-assets/agents/cfn-dev-team/reviewers/{reviewer.md → code-reviewer.md} +95 -8
  87. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +107 -7
  88. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +98 -7
  89. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +95 -7
  90. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +136 -9
  91. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +108 -1
  92. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +107 -13
  93. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +737 -0
  94. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
  95. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +828 -0
  96. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +106 -7
  97. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +77 -0
  98. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +684 -0
  99. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +110 -1
  100. package/claude-assets/agents/cfn-dev-team/testers/tester.md +94 -7
  101. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +1 -3
  102. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +87 -13
  103. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +103 -7
  104. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -3
  105. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +94 -7
  106. package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +46 -0
  107. package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
  108. package/claude-assets/cfn-extras/skills/advanced-features/cfn-agent-swap/recommend-swap.sh +59 -59
  109. package/claude-assets/cfn-extras/skills/analytics/cfn-improvement-recommender/recommend-improvements.sh +91 -91
  110. package/claude-assets/cfn-extras/skills/analytics/cfn-pattern-extraction/extract-patterns.sh +79 -79
  111. package/claude-assets/cfn-extras/skills/analytics/cfn-retrospective-report/generate-report.sh +100 -100
  112. package/claude-assets/cfn-extras/skills/analytics/cfn-telemetry/start-telemetry.sh +110 -110
  113. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/add-bullet.sh +145 -145
  114. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/log-merge.sh +67 -67
  115. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/monitor-injection-performance.sh +137 -137
  116. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/optimize-injection-pipeline.sh +168 -168
  117. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/query-reflections.sh +35 -35
  118. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/store-reflection.sh +45 -45
  119. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/track-ab-test.sh +41 -41
  120. package/claude-assets/cfn-extras/skills/deprecated/cfn-ace-system/update-reflection.sh +41 -41
  121. package/claude-assets/cfn-extras/skills/deprecated/cfn-cli-setup/validate-cli-environment.sh +191 -191
  122. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/create-campaign.sh +231 -231
  123. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/get-campaign-performance.sh +190 -190
  124. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/pause-campaign.sh +142 -142
  125. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/set-budget.sh +181 -181
  126. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-ad-campaigns/operations/update-bid-strategy.sh +133 -133
  127. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/get-conversation-history.sh +121 -121
  128. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/qualify-lead.sh +156 -156
  129. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/schedule-demo.sh +181 -181
  130. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/send-message.sh +137 -137
  131. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-chatbot-conversations/operations/transfer-to-human.sh +179 -179
  132. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/create-campaign.sh +183 -183
  133. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/get-delivery-status.sh +139 -139
  134. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/opt-out.sh +150 -150
  135. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/schedule-campaign.sh +187 -187
  136. package/claude-assets/cfn-extras/skills/marketing/cfn-marketing-sms-campaigns/operations/send-sms.sh +181 -181
  137. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/test-web-portal-skill.sh +50 -50
  138. package/claude-assets/cfn-extras/skills/ui-portal/cfn-web-portal/validate-deployment.sh +84 -84
  139. package/claude-assets/cfn-extras/skills/utility/cfn-environment-sanitization/sanitize-environment.sh +243 -243
  140. package/claude-assets/commands/cfn-loop-cli.md +29 -6
  141. package/claude-assets/commands/switch-api.md +31 -10
  142. package/claude-assets/hooks/cfn-lint-sql-injection.sh +61 -0
  143. package/claude-assets/hooks/cfn-post-edit-cfn-retrospective.sh +33 -2
  144. package/claude-assets/hooks/cfn-pre-edit-security-warning.sh +40 -0
  145. package/claude-assets/hooks/detect-hardcoded-credentials.sh +212 -0
  146. package/claude-assets/skills/SKILL_TEMPLATE.md +774 -0
  147. package/claude-assets/skills/agent-lifecycle/execute-lifecycle-hook.sh +84 -113
  148. package/claude-assets/skills/agent-lifecycle/simple-audit.sh +33 -6
  149. package/claude-assets/skills/agent-template-generator/SKILL.md +440 -0
  150. package/claude-assets/skills/agent-template-generator/generate-agent.sh +405 -0
  151. package/claude-assets/skills/agent-validation-linter/SKILL.md +589 -0
  152. package/claude-assets/skills/agent-validation-linter/lint-agents.sh +271 -0
  153. package/claude-assets/skills/bootstrap/bash-fundamentals.md +786 -0
  154. package/claude-assets/skills/bootstrap/database-connection.md +464 -0
  155. package/claude-assets/skills/bootstrap/error-handling.md +580 -0
  156. package/claude-assets/skills/bootstrap/file-operations.md +699 -0
  157. package/claude-assets/skills/bootstrap/skill-loader.md +616 -0
  158. package/claude-assets/skills/bootstrap/sqlite-params.sh +287 -0
  159. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh +22 -24
  160. package/claude-assets/skills/cfn-automatic-memory-persistence/test-memory-persistence.sh +17 -16
  161. package/claude-assets/skills/cfn-deployment/SKILL.md +293 -0
  162. package/claude-assets/skills/cfn-deployment/execute.sh +21 -0
  163. package/claude-assets/skills/cfn-docker-agent-spawning/SKILL.md +28 -4
  164. package/claude-assets/skills/cfn-docker-agent-spawning/spawn-agent.sh +3 -1
  165. package/claude-assets/skills/cfn-docker-loop-orchestration/orchestrate.sh +224 -20
  166. package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +38 -0
  167. package/claude-assets/skills/cfn-error-batching-strategy/lib/core-functions.sh +47 -47
  168. package/claude-assets/skills/cfn-file-operations/SKILL.md +290 -0
  169. package/claude-assets/skills/cfn-file-operations/execute.sh +129 -0
  170. package/claude-assets/skills/cfn-file-operations/lib/atomic-write.sh +294 -0
  171. package/claude-assets/skills/cfn-file-operations/lib/lock.sh +361 -0
  172. package/claude-assets/skills/cfn-file-operations/test.sh +369 -0
  173. package/claude-assets/skills/cfn-log-operations/SKILL.md +308 -0
  174. package/claude-assets/skills/cfn-log-operations/execute.sh +420 -0
  175. package/claude-assets/skills/cfn-log-operations/lib/rotate.sh +406 -0
  176. package/claude-assets/skills/cfn-log-operations/lib/search.sh +448 -0
  177. package/claude-assets/skills/cfn-log-operations/test.sh +394 -0
  178. package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +550 -46
  179. package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +277 -0
  180. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +238 -29
  181. package/claude-assets/skills/cfn-loop-orchestration/security_utils.sh +24 -0
  182. package/claude-assets/skills/cfn-loop-orchestration/test-iteration-context-injection.sh +366 -0
  183. package/claude-assets/skills/cfn-parameterized-queries/SKILL.md +339 -0
  184. package/claude-assets/skills/cfn-playbook/query-playbook.sh +19 -15
  185. package/claude-assets/skills/cfn-playbook/update-playbook.sh +25 -14
  186. package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +44 -0
  187. package/claude-assets/skills/cfn-promotion/SKILL.md +305 -0
  188. package/claude-assets/skills/cfn-redis-coordination/CENTRALIZED_REDIS_WRAPPER.md +319 -0
  189. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh +4 -0
  190. package/claude-assets/skills/cfn-redis-coordination/agent-log.sh.bak +124 -0
  191. package/claude-assets/skills/cfn-redis-coordination/agent-recovery.sh +2 -2
  192. package/claude-assets/skills/cfn-redis-coordination/collect-confidence-scores.sh +30 -0
  193. package/claude-assets/skills/cfn-redis-coordination/get-context.sh +33 -0
  194. package/claude-assets/skills/cfn-redis-coordination/get-success-criteria.sh +54 -0
  195. package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +6 -2
  196. package/claude-assets/skills/cfn-redis-coordination/redis-cli-wrapper.sh +24 -3
  197. package/claude-assets/skills/cfn-redis-coordination/redis-functions.sh +34 -0
  198. package/claude-assets/skills/cfn-redis-coordination/report-completion.sh +24 -31
  199. package/claude-assets/skills/cfn-redis-coordination/store-context.sh +4 -0
  200. package/claude-assets/skills/cfn-redis-coordination/store-success-criteria.sh +85 -0
  201. package/claude-assets/skills/cfn-redis-coordination/update-all-scripts.sh +67 -0
  202. package/claude-assets/skills/cfn-skill-loader/SKILL.md +466 -0
  203. package/claude-assets/skills/cfn-skill-loader/execute.sh +344 -0
  204. package/claude-assets/skills/cfn-sqlite-memory/ttl-cleanup.sh +17 -25
  205. package/claude-assets/skills/cfn-task-audit/get-audit-data.sh +42 -21
  206. package/claude-assets/skills/cfn-task-audit/store-task-audit.sh +17 -10
  207. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh +17 -14
  208. package/claude-assets/skills/cfn-test-runner/detect-regressions.sh.backup-1763392821 +55 -0
  209. package/claude-assets/skills/cfn-test-runner/store-benchmarks.sh +17 -19
  210. package/claude-assets/skills/cfn-transparency-middleware/test-e2e.sh +15 -0
  211. package/claude-assets/skills/cfn-transparency-middleware/tests/input-validation.sh +15 -0
  212. package/claude-assets/skills/cfn-utilities/SKILL.md +237 -0
  213. package/claude-assets/skills/cfn-utilities/execute.sh +32 -0
  214. package/claude-assets/skills/cfn-utilities/lib/errors.sh +56 -0
  215. package/claude-assets/skills/cfn-utilities/lib/file-ops.sh +164 -0
  216. package/claude-assets/skills/cfn-utilities/lib/logging.sh +77 -0
  217. package/claude-assets/skills/cfn-utilities/lib/retry.sh +127 -0
  218. package/claude-assets/skills/cfn-utilities/test.sh +317 -0
  219. package/claude-assets/skills/integration/agent-handoff.sh +62 -64
  220. package/claude-assets/skills/json-validation/SKILL.md +431 -0
  221. package/claude-assets/skills/json-validation/test-validate-success-criteria.sh +421 -0
  222. package/claude-assets/skills/json-validation/validate-success-criteria.sh +197 -0
  223. package/claude-assets/skills/redis-coordination/validate-parameters.sh +34 -0
  224. package/claude-assets/skills/workflow-codification/DEPLOY_QUICK_REFERENCE.md +106 -0
  225. package/claude-assets/skills/workflow-codification/PROPAGATE_UPDATE_QUICK_REFERENCE.md +366 -0
  226. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh +481 -0
  227. package/claude-assets/skills/workflow-codification/deploy-approved-skill.sh.backup-1763392820 +512 -0
  228. package/claude-assets/skills/workflow-codification/lib/security-utils.sh +204 -0
  229. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh +648 -0
  230. package/claude-assets/skills/workflow-codification/propagate-skill-update.sh.backup-1763392820 +664 -0
  231. package/claude-assets/skills/workflow-codification/test-integration.sh +15 -0
  232. package/claude-assets/skills/workflow-codification/test-metadata-update.sh +350 -0
  233. package/claude-assets/skills/workflow-codification/track-cost-savings.sh +55 -14
  234. package/claude-assets/skills/workflow-codification/track-cost-savings.sh.backup-1763392821 +445 -0
  235. package/claude-assets/skills/workflow-codification/track-edge-case.sh +27 -60
  236. package/claude-assets/skills/workflow-codification/workflow-codification.db +0 -0
  237. package/dist/ace/ace-curator.js +10 -2
  238. package/dist/ace/ace-curator.js.map +1 -1
  239. package/dist/ace/ace-generator.js +4 -0
  240. package/dist/ace/ace-generator.js.map +1 -1
  241. package/dist/ace/ace-reflector.js +1 -1
  242. package/dist/ace/ace-reflector.js.map +1 -1
  243. package/dist/ace/context-injection.js +24 -2
  244. package/dist/ace/context-injection.js.map +1 -1
  245. package/dist/agents/task-agent-integration.js +1 -1
  246. package/dist/agents/task-agent-integration.js.map +1 -1
  247. package/dist/api/health-endpoints.js +390 -0
  248. package/dist/api/health-endpoints.js.map +1 -0
  249. package/dist/cli/agent-executor.js +4 -1
  250. package/dist/cli/agent-executor.js.map +1 -1
  251. package/dist/cli/agent-prompt-builder.js +89 -1
  252. package/dist/cli/agent-prompt-builder.js.map +1 -1
  253. package/dist/cli/agent-spawn.js +130 -37
  254. package/dist/cli/agent-spawn.js.map +1 -1
  255. package/dist/cli/config-manager.js +109 -91
  256. package/dist/cli/config-manager.js.map +1 -1
  257. package/dist/cli/conversation-fork-cleanup.js +201 -0
  258. package/dist/cli/conversation-fork-cleanup.js.map +1 -0
  259. package/dist/cli/conversation-fork.js +16 -3
  260. package/dist/cli/conversation-fork.js.map +1 -1
  261. package/dist/cli/skill-cache-validator.js +412 -0
  262. package/dist/cli/skill-cache-validator.js.map +1 -0
  263. package/dist/cli/skill-cli.js +991 -0
  264. package/dist/cli/skill-cli.js.map +1 -0
  265. package/dist/cli/skill-execution-logger.js +284 -0
  266. package/dist/cli/skill-execution-logger.js.map +1 -0
  267. package/dist/cli/skill-loader.js +457 -0
  268. package/dist/cli/skill-loader.js.map +1 -0
  269. package/dist/coordination/event-bus.js +2 -2
  270. package/dist/coordination/event-bus.js.map +1 -1
  271. package/dist/coordination/fleet-manager.js +1 -1
  272. package/dist/coordination/fleet-manager.js.map +1 -1
  273. package/dist/coordination/index.js +23 -9
  274. package/dist/coordination/index.js.map +1 -1
  275. package/dist/coordination/types/fleet-manager.types.js.map +1 -1
  276. package/dist/db/migration-manager.js +483 -0
  277. package/dist/db/migration-manager.js.map +1 -0
  278. package/dist/db/skills-query.js +535 -0
  279. package/dist/db/skills-query.js.map +1 -0
  280. package/dist/integration/DatabaseHandoff.js +1 -1
  281. package/dist/integration/DatabaseHandoff.js.map +1 -1
  282. package/dist/jobs/edge-case-analyzer.js +367 -0
  283. package/dist/jobs/edge-case-analyzer.js.map +1 -0
  284. package/dist/jobs/promotion-sla-enforcer.js +288 -0
  285. package/dist/jobs/promotion-sla-enforcer.js.map +1 -0
  286. package/dist/lib/agent-output-parser.js.map +1 -1
  287. package/dist/lib/agent-output-validator.js.map +1 -1
  288. package/dist/lib/agent-workspace.js +281 -0
  289. package/dist/lib/agent-workspace.js.map +1 -0
  290. package/dist/lib/atomic-file-writer.js +377 -0
  291. package/dist/lib/atomic-file-writer.js.map +1 -0
  292. package/dist/lib/backup-manager.js +779 -0
  293. package/dist/lib/backup-manager.js.map +1 -0
  294. package/dist/lib/checkpoint-manager.js +837 -0
  295. package/dist/lib/checkpoint-manager.js.map +1 -0
  296. package/dist/lib/circuit-breaker.js +340 -0
  297. package/dist/lib/circuit-breaker.js.map +1 -0
  298. package/dist/lib/completion-signal-handler.js +243 -0
  299. package/dist/lib/completion-signal-handler.js.map +1 -0
  300. package/dist/lib/config-manager.js +312 -0
  301. package/dist/lib/config-manager.js.map +1 -0
  302. package/dist/lib/config-migrator.js +386 -0
  303. package/dist/lib/config-migrator.js.map +1 -0
  304. package/dist/lib/config-validator.js.map +1 -1
  305. package/dist/lib/correlation-cache.js +311 -0
  306. package/dist/lib/correlation-cache.js.map +1 -0
  307. package/dist/lib/correlation.js +263 -0
  308. package/dist/lib/correlation.js.map +1 -0
  309. package/dist/lib/database-service/connection-pool-manager.js +520 -0
  310. package/dist/lib/database-service/connection-pool-manager.js.map +1 -0
  311. package/dist/lib/database-service/correlation.js +329 -0
  312. package/dist/lib/database-service/correlation.js.map +1 -0
  313. package/dist/lib/database-service/errors.js +120 -0
  314. package/dist/lib/database-service/errors.js.map +1 -0
  315. package/dist/lib/database-service/index.js +168 -0
  316. package/dist/lib/database-service/index.js.map +1 -0
  317. package/dist/lib/database-service/postgres-adapter.js +526 -0
  318. package/dist/lib/database-service/postgres-adapter.js.map +1 -0
  319. package/dist/lib/database-service/redis-adapter.js +360 -0
  320. package/dist/lib/database-service/redis-adapter.js.map +1 -0
  321. package/dist/lib/database-service/sqlite-adapter.js +544 -0
  322. package/dist/lib/database-service/sqlite-adapter.js.map +1 -0
  323. package/dist/lib/database-service/transaction-manager.js +773 -0
  324. package/dist/lib/database-service/transaction-manager.js.map +1 -0
  325. package/dist/lib/database-service/types.js +23 -0
  326. package/dist/lib/database-service/types.js.map +1 -0
  327. package/dist/lib/deadlock-resolver.js +292 -0
  328. package/dist/lib/deadlock-resolver.js.map +1 -0
  329. package/dist/lib/distributed-lock.js +451 -0
  330. package/dist/lib/distributed-lock.js.map +1 -0
  331. package/dist/lib/edge-case-deduplicator.js +227 -0
  332. package/dist/lib/edge-case-deduplicator.js.map +1 -0
  333. package/dist/lib/encryption-manager.js +322 -0
  334. package/dist/lib/encryption-manager.js.map +1 -0
  335. package/dist/lib/error-aggregator.js +234 -0
  336. package/dist/lib/error-aggregator.js.map +1 -0
  337. package/dist/lib/errors.js +287 -0
  338. package/dist/lib/errors.js.map +1 -0
  339. package/dist/lib/file-lock-manager.js +578 -0
  340. package/dist/lib/file-lock-manager.js.map +1 -0
  341. package/dist/lib/file-operations.js +367 -0
  342. package/dist/lib/file-operations.js.map +1 -0
  343. package/dist/lib/idempotent-write.js +237 -0
  344. package/dist/lib/idempotent-write.js.map +1 -0
  345. package/dist/lib/integration-schema-validator.js +522 -0
  346. package/dist/lib/integration-schema-validator.js.map +1 -0
  347. package/dist/lib/lock-health-monitor.js +298 -0
  348. package/dist/lib/lock-health-monitor.js.map +1 -0
  349. package/dist/lib/log-shipper.js +422 -0
  350. package/dist/lib/log-shipper.js.map +1 -0
  351. package/dist/lib/logging.js +146 -0
  352. package/dist/lib/logging.js.map +1 -0
  353. package/dist/lib/message-deduplicator.js +439 -0
  354. package/dist/lib/message-deduplicator.js.map +1 -0
  355. package/dist/lib/multi-system-query.js +604 -0
  356. package/dist/lib/multi-system-query.js.map +1 -0
  357. package/dist/lib/orphan-detector.js +332 -0
  358. package/dist/lib/orphan-detector.js.map +1 -0
  359. package/dist/lib/password-generator.js +166 -0
  360. package/dist/lib/password-generator.js.map +1 -0
  361. package/dist/lib/path-validator.js +429 -0
  362. package/dist/lib/path-validator.js.map +1 -0
  363. package/dist/lib/query-translator.js +905 -0
  364. package/dist/lib/query-translator.js.map +1 -0
  365. package/dist/lib/queue-recovery.js +469 -0
  366. package/dist/lib/queue-recovery.js.map +1 -0
  367. package/dist/lib/redis-queue-manager.js +512 -0
  368. package/dist/lib/redis-queue-manager.js.map +1 -0
  369. package/dist/lib/reflection-archiver.js +272 -0
  370. package/dist/lib/reflection-archiver.js.map +1 -0
  371. package/dist/lib/retry-manager.js +453 -0
  372. package/dist/lib/retry-manager.js.map +1 -0
  373. package/dist/lib/retry.js +262 -0
  374. package/dist/lib/retry.js.map +1 -0
  375. package/dist/lib/schema-transform.js +695 -0
  376. package/dist/lib/schema-transform.js.map +1 -0
  377. package/dist/lib/schema-validator.js +491 -0
  378. package/dist/lib/schema-validator.js.map +1 -0
  379. package/dist/lib/skill-cache.js +297 -0
  380. package/dist/lib/skill-cache.js.map +1 -0
  381. package/dist/lib/skill-content-manager.js +337 -0
  382. package/dist/lib/skill-content-manager.js.map +1 -0
  383. package/dist/lib/skill-frontmatter-parser.js +237 -0
  384. package/dist/lib/skill-frontmatter-parser.js.map +1 -0
  385. package/dist/lib/skill-git-integration.js +275 -0
  386. package/dist/lib/skill-git-integration.js.map +1 -0
  387. package/dist/lib/skill-markdown-validator.js +396 -0
  388. package/dist/lib/skill-markdown-validator.js.map +1 -0
  389. package/dist/lib/skill-output-parser.js +312 -0
  390. package/dist/lib/skill-output-parser.js.map +1 -0
  391. package/dist/lib/unified-query-api.js +467 -0
  392. package/dist/lib/unified-query-api.js.map +1 -0
  393. package/dist/middleware/auth-middleware.js +350 -0
  394. package/dist/middleware/auth-middleware.js.map +1 -0
  395. package/dist/middleware/schema-validation.js +347 -0
  396. package/dist/middleware/schema-validation.js.map +1 -0
  397. package/dist/providers/anthropic-provider.js +1 -1
  398. package/dist/providers/anthropic-provider.js.map +1 -1
  399. package/dist/providers/provider-factory.js +2 -2
  400. package/dist/providers/provider-factory.js.map +1 -1
  401. package/dist/services/edge-case-analyzer.js +321 -0
  402. package/dist/services/edge-case-analyzer.js.map +1 -0
  403. package/dist/services/edge-case-deduplicator.js +266 -0
  404. package/dist/services/edge-case-deduplicator.js.map +1 -0
  405. package/dist/services/edge-case-detector.js +337 -0
  406. package/dist/services/edge-case-detector.js.map +1 -0
  407. package/dist/services/edge-case-tracker.js +547 -0
  408. package/dist/services/edge-case-tracker.js.map +1 -0
  409. package/dist/services/health-check-system.js +586 -0
  410. package/dist/services/health-check-system.js.map +1 -0
  411. package/dist/services/metrics-logger.js +412 -0
  412. package/dist/services/metrics-logger.js.map +1 -0
  413. package/dist/services/patch-generator.js +378 -0
  414. package/dist/services/patch-generator.js.map +1 -0
  415. package/dist/services/patch-validator.js +337 -0
  416. package/dist/services/patch-validator.js.map +1 -0
  417. package/dist/services/performance-monitor.js +811 -0
  418. package/dist/services/performance-monitor.js.map +1 -0
  419. package/dist/services/promotion-pipeline.js +918 -0
  420. package/dist/services/promotion-pipeline.js.map +1 -0
  421. package/dist/services/promotion-validator.js +394 -0
  422. package/dist/services/promotion-validator.js.map +1 -0
  423. package/dist/services/reflection-logger.js +388 -0
  424. package/dist/services/reflection-logger.js.map +1 -0
  425. package/dist/services/skill-deployment.js +472 -0
  426. package/dist/services/skill-deployment.js.map +1 -0
  427. package/dist/services/skill-loader.js +427 -0
  428. package/dist/services/skill-loader.js.map +1 -0
  429. package/dist/services/skill-promotion.js +372 -0
  430. package/dist/services/skill-promotion.js.map +1 -0
  431. package/dist/services/skill-validator.js +454 -0
  432. package/dist/services/skill-validator.js.map +1 -0
  433. package/dist/services/skill-versioning.js +244 -0
  434. package/dist/services/skill-versioning.js.map +1 -0
  435. package/dist/services/workspace-supervisor.js +597 -0
  436. package/dist/services/workspace-supervisor.js.map +1 -0
  437. package/dist/types/edge-case.js +45 -0
  438. package/dist/types/edge-case.js.map +1 -0
  439. package/docs/BUG_19_MEMORY_LEAK_TASK_MODE.md +405 -0
  440. package/docs/MEMORY_CLEANUP_GUIDE.md +358 -0
  441. package/docs/MEMORY_LEAK_FIX_SUMMARY.md +322 -0
  442. package/docs/REDIS_CLEANUP_EXECUTIVE_SUMMARY.md +319 -0
  443. package/docs/REDIS_CLEANUP_VERIFICATION_REPORT.md +574 -0
  444. package/package.json +35 -4
  445. package/readme/README.md +53 -5
  446. package/scripts/backup-cleanup.sh +627 -0
  447. package/scripts/cleanup-workspaces.sh +412 -0
  448. package/scripts/cleanup-yaml-configs.sh +141 -0
  449. package/scripts/deploy-approved-skills.sh +263 -0
  450. package/scripts/health-check.sh +447 -0
  451. package/scripts/log-aggregator.sh +554 -0
  452. package/scripts/log-monitor.sh +629 -0
  453. package/scripts/manage-agent-workspaces.sh +434 -0
  454. package/scripts/migrate-schema.sh +533 -0
  455. package/scripts/promote-staged-skills.sh +423 -0
  456. package/scripts/verify-no-secrets.sh +88 -35
  457. package/scripts/verify-redis-cleanup.sh +173 -0
  458. package/tests/README.md +84 -0
  459. package/tests/test-memory-leak-task-mode.sh +435 -0
  460. package/.claude/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  461. package/.claude/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  462. package/.claude/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  463. package/.claude/skills/agent-lifecycle/SKILL.md +0 -60
  464. package/.claude/skills/agent-lifecycle/execute-lifecycle-hook.sh +0 -573
  465. package/.claude/skills/agent-lifecycle/simple-audit.sh +0 -31
  466. package/.claude/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  467. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
  468. package/README.md.backup_before_replace +0 -781
  469. package/claude-assets/cfn-extras/agents/deprecated-coordinators/adaptive-coordinator.md.backup +0 -161
  470. package/claude-assets/cfn-extras/agents/deprecated-coordinators/blocking-coordinator-example.md.backup +0 -728
  471. package/claude-assets/cfn-extras/agents/deprecated-coordinators/mesh-coordinator.md.backup +0 -131
  472. package/claude-assets/skills/cfn-agent-spawning/spawn-agent.sh.backup +0 -273
  473. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh.backup +0 -949
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Edge Case Deduplicator
3
+ *
4
+ * Handles deduplication of edge cases using SHA-256 signatures.
5
+ * Normalizes context to detect similar errors with different IDs, timestamps, or numbers.
6
+ */ import * as crypto from 'crypto';
7
+ export class EdgeCaseDeduplicator {
8
+ /**
9
+ * Generate SHA-256 signature for edge case deduplication
10
+ *
11
+ * Signature is based on:
12
+ * - Type
13
+ * - Category
14
+ * - Normalized error message
15
+ * - Normalized stack trace
16
+ *
17
+ * @param edgeCase Edge case input
18
+ * @returns SHA-256 signature (64 hex characters)
19
+ */ generateSignature(edgeCase) {
20
+ const normalizedContext = this.normalizeContext(edgeCase.context);
21
+ const signatureData = {
22
+ type: edgeCase.type,
23
+ category: edgeCase.category,
24
+ context: normalizedContext
25
+ };
26
+ const signatureString = JSON.stringify(signatureData);
27
+ const hash = crypto.createHash('sha256');
28
+ hash.update(signatureString);
29
+ return hash.digest('hex');
30
+ }
31
+ /**
32
+ * Normalize context for deduplication
33
+ *
34
+ * Replaces variable data with placeholders:
35
+ * - Dates/timestamps → {date}
36
+ * - IDs (hex, alphanumeric) → {id}
37
+ * - Numbers → {number}
38
+ * - File paths → normalized paths
39
+ * - Line numbers in stack traces → {line}
40
+ *
41
+ * @param context Edge case context object
42
+ * @returns Normalized JSON string
43
+ */ normalizeContext(context) {
44
+ const normalized = this.deepNormalize(context);
45
+ return JSON.stringify(normalized, null, 0);
46
+ }
47
+ /**
48
+ * Normalize stack trace for deduplication
49
+ *
50
+ * Removes:
51
+ * - Line numbers
52
+ * - Column numbers
53
+ * - Absolute file paths (keep relative paths)
54
+ * - Memory addresses
55
+ *
56
+ * @param stackTrace Stack trace string
57
+ * @returns Normalized stack trace
58
+ */ normalizeStackTrace(stackTrace) {
59
+ let normalized = stackTrace;
60
+ // Normalize line and column numbers: ":42:10" → ":{line}:{col}"
61
+ normalized = normalized.replace(/:(\d+):(\d+)/g, ':{line}:{col}');
62
+ // Normalize single line numbers: ":42)" → ":{line})"
63
+ normalized = normalized.replace(/:(\d+)\)/g, ':{line})');
64
+ // Normalize absolute paths to relative
65
+ // /app/src/file.js → src/file.js
66
+ // /home/user/project/file.js → file.js
67
+ normalized = normalized.replace(/\/[a-zA-Z0-9_\-\/]+\//g, (match)=>{
68
+ // Keep only the last 2 path segments
69
+ const segments = match.split('/').filter((s)=>s.length > 0);
70
+ return segments.slice(-2).join('/') + '/';
71
+ });
72
+ // Normalize memory addresses: 0x7f1234567890 → {addr}
73
+ normalized = normalized.replace(/0x[0-9a-f]+/gi, '{addr}');
74
+ return normalized;
75
+ }
76
+ /**
77
+ * Deep normalize an object or string
78
+ *
79
+ * Recursively processes objects and arrays,
80
+ * normalizing strings at leaf nodes.
81
+ */ deepNormalize(value) {
82
+ if (typeof value === 'string') {
83
+ return this.normalizeString(value);
84
+ }
85
+ if (Array.isArray(value)) {
86
+ return value.map((item)=>this.deepNormalize(item));
87
+ }
88
+ if (typeof value === 'object' && value !== null) {
89
+ const normalized = {};
90
+ // Special handling for error objects
91
+ if (value.message !== undefined) {
92
+ normalized.message = this.normalizeString(value.message);
93
+ }
94
+ if (value.stack !== undefined) {
95
+ normalized.stack = this.normalizeStackTrace(value.stack);
96
+ }
97
+ // Normalize other properties
98
+ for (const key of Object.keys(value)){
99
+ if (key !== 'message' && key !== 'stack') {
100
+ normalized[key] = this.deepNormalize(value[key]);
101
+ }
102
+ }
103
+ // Sort keys for consistent hashing
104
+ const sorted = {};
105
+ Object.keys(normalized).sort().forEach((key)=>{
106
+ sorted[key] = normalized[key];
107
+ });
108
+ return sorted;
109
+ }
110
+ // Numbers, booleans, null stay as-is for non-string normalization
111
+ // but we track them as {number} etc. in strings
112
+ return value;
113
+ }
114
+ /**
115
+ * Normalize a string by replacing variable data with placeholders
116
+ */ normalizeString(str) {
117
+ let normalized = str;
118
+ // Normalize ISO 8601 dates/timestamps
119
+ // 2025-11-16T13:00:00Z → {date}
120
+ // 2025-11-16T13:00:00.123Z → {date}
121
+ // 2025-11-16 13:00:00 → {date}
122
+ normalized = normalized.replace(/\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z?/g, '{date}');
123
+ // Normalize standalone dates
124
+ // 2025-11-16 → {date}
125
+ normalized = normalized.replace(/\d{4}-\d{2}-\d{2}/g, '{date}');
126
+ // Normalize Unix timestamps (10 digits)
127
+ // 1700000000 → {timestamp}
128
+ normalized = normalized.replace(/\b\d{10}\b/g, '{timestamp}');
129
+ // Normalize UUIDs
130
+ // 550e8400-e29b-41d4-a716-446655440000 → {uuid}
131
+ normalized = normalized.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '{uuid}');
132
+ // Normalize hex IDs (8+ hex characters)
133
+ // abc123def456 → {id}
134
+ normalized = normalized.replace(/\b[a-f0-9]{8,}\b/gi, '{id}');
135
+ // Normalize task/agent IDs with prefixes
136
+ // task-abc123, agent-xyz789, cfn-cli-1234567 → {id}
137
+ normalized = normalized.replace(/(?:task|agent|cfn|job|run|session)-[a-z0-9\-]+/gi, '{id}');
138
+ // Normalize user/resource IDs in paths
139
+ // /api/users/12345 → /api/users/{id}
140
+ // /tasks/abc123/status → /tasks/{id}/status
141
+ normalized = normalized.replace(/\/([a-z0-9\-]+)(?=\/|$)/gi, (match, id)=>{
142
+ // Only replace if it looks like an ID (contains numbers or is hex)
143
+ if (/\d/.test(id) || /^[a-f0-9]+$/i.test(id)) {
144
+ return '/{id}';
145
+ }
146
+ return match;
147
+ });
148
+ // Normalize standalone numbers
149
+ // "Error 500", "timeout after 5000ms", "user 12345" → "Error {number}", etc.
150
+ normalized = normalized.replace(/\b\d+\b/g, '{number}');
151
+ // Normalize memory addresses
152
+ // 0x7f1234567890 → {addr}
153
+ normalized = normalized.replace(/0x[0-9a-f]+/gi, '{addr}');
154
+ // Normalize file paths with line numbers
155
+ // /app/file.js:42 → /app/file.js:{line}
156
+ normalized = normalized.replace(/:(\d+)(?::(\d+))?/g, ':{line}');
157
+ return normalized;
158
+ }
159
+ /**
160
+ * Check if two edge cases are similar based on their signatures
161
+ *
162
+ * @param signature1 First signature
163
+ * @param signature2 Second signature
164
+ * @returns True if signatures match
165
+ */ areSimilar(signature1, signature2) {
166
+ return signature1 === signature2;
167
+ }
168
+ /**
169
+ * Calculate similarity score between two contexts (for fuzzy matching)
170
+ *
171
+ * This is for future enhancement - currently we use exact signature matching.
172
+ * Could be used for "similar but not identical" edge case detection.
173
+ *
174
+ * @param context1 First context
175
+ * @param context2 Second context
176
+ * @returns Similarity score (0.0 to 1.0)
177
+ */ calculateSimilarity(context1, context2) {
178
+ const norm1 = this.normalizeContext(context1);
179
+ const norm2 = this.normalizeContext(context2);
180
+ // Simple Jaccard similarity on normalized strings
181
+ const set1 = new Set(norm1.split(/\s+/));
182
+ const set2 = new Set(norm2.split(/\s+/));
183
+ const intersection = new Set(Array.from(set1).filter((x)=>set2.has(x)));
184
+ const union = new Set([
185
+ ...Array.from(set1),
186
+ ...Array.from(set2)
187
+ ]);
188
+ return intersection.size / union.size;
189
+ }
190
+ /**
191
+ * Extract common pattern from multiple edge cases
192
+ *
193
+ * For future pattern detection feature.
194
+ *
195
+ * @param edgeCases Array of edge case inputs
196
+ * @returns Common pattern descriptor
197
+ */ extractPattern(edgeCases) {
198
+ // Future implementation: extract common error patterns
199
+ // For now, return basic statistics
200
+ const types = new Map();
201
+ const categories = new Map();
202
+ for (const edgeCase of edgeCases){
203
+ types.set(edgeCase.type, (types.get(edgeCase.type) || 0) + 1);
204
+ categories.set(edgeCase.category, (categories.get(edgeCase.category) || 0) + 1);
205
+ }
206
+ return {
207
+ commonType: this.findMostCommon(types),
208
+ commonCategory: this.findMostCommon(categories),
209
+ totalCases: edgeCases.length
210
+ };
211
+ }
212
+ /**
213
+ * Find most common value in a map
214
+ */ findMostCommon(map) {
215
+ let maxCount = 0;
216
+ let maxKey = null;
217
+ for (const [key, count] of Array.from(map.entries())){
218
+ if (count > maxCount) {
219
+ maxCount = count;
220
+ maxKey = key;
221
+ }
222
+ }
223
+ return maxKey;
224
+ }
225
+ }
226
+
227
+ //# sourceMappingURL=edge-case-deduplicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/edge-case-deduplicator.ts"],"sourcesContent":["/**\r\n * Edge Case Deduplicator\r\n *\r\n * Handles deduplication of edge cases using SHA-256 signatures.\r\n * Normalizes context to detect similar errors with different IDs, timestamps, or numbers.\r\n */\r\n\r\nimport * as crypto from 'crypto';\r\nimport { EdgeCaseInput, EdgeCaseType } from '../types/edge-case.js';\r\n\r\nexport class EdgeCaseDeduplicator {\r\n /**\r\n * Generate SHA-256 signature for edge case deduplication\r\n *\r\n * Signature is based on:\r\n * - Type\r\n * - Category\r\n * - Normalized error message\r\n * - Normalized stack trace\r\n *\r\n * @param edgeCase Edge case input\r\n * @returns SHA-256 signature (64 hex characters)\r\n */\r\n public generateSignature(edgeCase: EdgeCaseInput): string {\r\n const normalizedContext = this.normalizeContext(edgeCase.context);\r\n\r\n const signatureData = {\r\n type: edgeCase.type,\r\n category: edgeCase.category,\r\n context: normalizedContext\r\n };\r\n\r\n const signatureString = JSON.stringify(signatureData);\r\n const hash = crypto.createHash('sha256');\r\n hash.update(signatureString);\r\n\r\n return hash.digest('hex');\r\n }\r\n\r\n /**\r\n * Normalize context for deduplication\r\n *\r\n * Replaces variable data with placeholders:\r\n * - Dates/timestamps → {date}\r\n * - IDs (hex, alphanumeric) → {id}\r\n * - Numbers → {number}\r\n * - File paths → normalized paths\r\n * - Line numbers in stack traces → {line}\r\n *\r\n * @param context Edge case context object\r\n * @returns Normalized JSON string\r\n */\r\n public normalizeContext(context: any): string {\r\n const normalized = this.deepNormalize(context);\r\n return JSON.stringify(normalized, null, 0);\r\n }\r\n\r\n /**\r\n * Normalize stack trace for deduplication\r\n *\r\n * Removes:\r\n * - Line numbers\r\n * - Column numbers\r\n * - Absolute file paths (keep relative paths)\r\n * - Memory addresses\r\n *\r\n * @param stackTrace Stack trace string\r\n * @returns Normalized stack trace\r\n */\r\n public normalizeStackTrace(stackTrace: string): string {\r\n let normalized = stackTrace;\r\n\r\n // Normalize line and column numbers: \":42:10\" → \":{line}:{col}\"\r\n normalized = normalized.replace(/:(\\d+):(\\d+)/g, ':{line}:{col}');\r\n\r\n // Normalize single line numbers: \":42)\" → \":{line})\"\r\n normalized = normalized.replace(/:(\\d+)\\)/g, ':{line})');\r\n\r\n // Normalize absolute paths to relative\r\n // /app/src/file.js → src/file.js\r\n // /home/user/project/file.js → file.js\r\n normalized = normalized.replace(/\\/[a-zA-Z0-9_\\-\\/]+\\//g, (match) => {\r\n // Keep only the last 2 path segments\r\n const segments = match.split('/').filter(s => s.length > 0);\r\n return segments.slice(-2).join('/') + '/';\r\n });\r\n\r\n // Normalize memory addresses: 0x7f1234567890 → {addr}\r\n normalized = normalized.replace(/0x[0-9a-f]+/gi, '{addr}');\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * Deep normalize an object or string\r\n *\r\n * Recursively processes objects and arrays,\r\n * normalizing strings at leaf nodes.\r\n */\r\n private deepNormalize(value: any): any {\r\n if (typeof value === 'string') {\r\n return this.normalizeString(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value.map(item => this.deepNormalize(item));\r\n }\r\n\r\n if (typeof value === 'object' && value !== null) {\r\n const normalized: any = {};\r\n\r\n // Special handling for error objects\r\n if (value.message !== undefined) {\r\n normalized.message = this.normalizeString(value.message);\r\n }\r\n\r\n if (value.stack !== undefined) {\r\n normalized.stack = this.normalizeStackTrace(value.stack);\r\n }\r\n\r\n // Normalize other properties\r\n for (const key of Object.keys(value)) {\r\n if (key !== 'message' && key !== 'stack') {\r\n normalized[key] = this.deepNormalize(value[key]);\r\n }\r\n }\r\n\r\n // Sort keys for consistent hashing\r\n const sorted: any = {};\r\n Object.keys(normalized).sort().forEach(key => {\r\n sorted[key] = normalized[key];\r\n });\r\n\r\n return sorted;\r\n }\r\n\r\n // Numbers, booleans, null stay as-is for non-string normalization\r\n // but we track them as {number} etc. in strings\r\n return value;\r\n }\r\n\r\n /**\r\n * Normalize a string by replacing variable data with placeholders\r\n */\r\n private normalizeString(str: string): string {\r\n let normalized = str;\r\n\r\n // Normalize ISO 8601 dates/timestamps\r\n // 2025-11-16T13:00:00Z → {date}\r\n // 2025-11-16T13:00:00.123Z → {date}\r\n // 2025-11-16 13:00:00 → {date}\r\n normalized = normalized.replace(/\\d{4}-\\d{2}-\\d{2}[T\\s]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z?/g, '{date}');\r\n\r\n // Normalize standalone dates\r\n // 2025-11-16 → {date}\r\n normalized = normalized.replace(/\\d{4}-\\d{2}-\\d{2}/g, '{date}');\r\n\r\n // Normalize Unix timestamps (10 digits)\r\n // 1700000000 → {timestamp}\r\n normalized = normalized.replace(/\\b\\d{10}\\b/g, '{timestamp}');\r\n\r\n // Normalize UUIDs\r\n // 550e8400-e29b-41d4-a716-446655440000 → {uuid}\r\n normalized = normalized.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '{uuid}');\r\n\r\n // Normalize hex IDs (8+ hex characters)\r\n // abc123def456 → {id}\r\n normalized = normalized.replace(/\\b[a-f0-9]{8,}\\b/gi, '{id}');\r\n\r\n // Normalize task/agent IDs with prefixes\r\n // task-abc123, agent-xyz789, cfn-cli-1234567 → {id}\r\n normalized = normalized.replace(/(?:task|agent|cfn|job|run|session)-[a-z0-9\\-]+/gi, '{id}');\r\n\r\n // Normalize user/resource IDs in paths\r\n // /api/users/12345 → /api/users/{id}\r\n // /tasks/abc123/status → /tasks/{id}/status\r\n normalized = normalized.replace(/\\/([a-z0-9\\-]+)(?=\\/|$)/gi, (match, id) => {\r\n // Only replace if it looks like an ID (contains numbers or is hex)\r\n if (/\\d/.test(id) || /^[a-f0-9]+$/i.test(id)) {\r\n return '/{id}';\r\n }\r\n return match;\r\n });\r\n\r\n // Normalize standalone numbers\r\n // \"Error 500\", \"timeout after 5000ms\", \"user 12345\" → \"Error {number}\", etc.\r\n normalized = normalized.replace(/\\b\\d+\\b/g, '{number}');\r\n\r\n // Normalize memory addresses\r\n // 0x7f1234567890 → {addr}\r\n normalized = normalized.replace(/0x[0-9a-f]+/gi, '{addr}');\r\n\r\n // Normalize file paths with line numbers\r\n // /app/file.js:42 → /app/file.js:{line}\r\n normalized = normalized.replace(/:(\\d+)(?::(\\d+))?/g, ':{line}');\r\n\r\n return normalized;\r\n }\r\n\r\n /**\r\n * Check if two edge cases are similar based on their signatures\r\n *\r\n * @param signature1 First signature\r\n * @param signature2 Second signature\r\n * @returns True if signatures match\r\n */\r\n public areSimilar(signature1: string, signature2: string): boolean {\r\n return signature1 === signature2;\r\n }\r\n\r\n /**\r\n * Calculate similarity score between two contexts (for fuzzy matching)\r\n *\r\n * This is for future enhancement - currently we use exact signature matching.\r\n * Could be used for \"similar but not identical\" edge case detection.\r\n *\r\n * @param context1 First context\r\n * @param context2 Second context\r\n * @returns Similarity score (0.0 to 1.0)\r\n */\r\n public calculateSimilarity(context1: any, context2: any): number {\r\n const norm1 = this.normalizeContext(context1);\r\n const norm2 = this.normalizeContext(context2);\r\n\r\n // Simple Jaccard similarity on normalized strings\r\n const set1 = new Set(norm1.split(/\\s+/));\r\n const set2 = new Set(norm2.split(/\\s+/));\r\n\r\n const intersection = new Set(Array.from(set1).filter(x => set2.has(x)));\r\n const union = new Set([...Array.from(set1), ...Array.from(set2)]);\r\n\r\n return intersection.size / union.size;\r\n }\r\n\r\n /**\r\n * Extract common pattern from multiple edge cases\r\n *\r\n * For future pattern detection feature.\r\n *\r\n * @param edgeCases Array of edge case inputs\r\n * @returns Common pattern descriptor\r\n */\r\n public extractPattern(edgeCases: EdgeCaseInput[]): any {\r\n // Future implementation: extract common error patterns\r\n // For now, return basic statistics\r\n\r\n const types = new Map<EdgeCaseType, number>();\r\n const categories = new Map<string, number>();\r\n\r\n for (const edgeCase of edgeCases) {\r\n types.set(edgeCase.type, (types.get(edgeCase.type) || 0) + 1);\r\n categories.set(edgeCase.category, (categories.get(edgeCase.category) || 0) + 1);\r\n }\r\n\r\n return {\r\n commonType: this.findMostCommon(types),\r\n commonCategory: this.findMostCommon(categories),\r\n totalCases: edgeCases.length\r\n };\r\n }\r\n\r\n /**\r\n * Find most common value in a map\r\n */\r\n private findMostCommon<K>(map: Map<K, number>): K | null {\r\n let maxCount = 0;\r\n let maxKey: K | null = null;\r\n\r\n for (const [key, count] of Array.from(map.entries())) {\r\n if (count > maxCount) {\r\n maxCount = count;\r\n maxKey = key;\r\n }\r\n }\r\n\r\n return maxKey;\r\n }\r\n}\r\n"],"names":["crypto","EdgeCaseDeduplicator","generateSignature","edgeCase","normalizedContext","normalizeContext","context","signatureData","type","category","signatureString","JSON","stringify","hash","createHash","update","digest","normalized","deepNormalize","normalizeStackTrace","stackTrace","replace","match","segments","split","filter","s","length","slice","join","value","normalizeString","Array","isArray","map","item","message","undefined","stack","key","Object","keys","sorted","sort","forEach","str","id","test","areSimilar","signature1","signature2","calculateSimilarity","context1","context2","norm1","norm2","set1","Set","set2","intersection","from","x","has","union","size","extractPattern","edgeCases","types","Map","categories","set","get","commonType","findMostCommon","commonCategory","totalCases","maxCount","maxKey","count","entries"],"mappings":"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"}
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Backup Encryption Manager
3
+ *
4
+ * Implements AES-256-GCM encryption for backup files with:
5
+ * - Secure key management via environment variables
6
+ * - Unique IV generation for each backup
7
+ * - HMAC-SHA256 integrity verification
8
+ * - Key rotation support
9
+ * - Backward compatibility detection
10
+ * - Encryption metadata tracking
11
+ *
12
+ * CVSS Mitigation: Addresses CVSS 7.2 (high severity) vulnerability
13
+ * by encrypting sensitive backup data at rest.
14
+ *
15
+ * Security Requirements:
16
+ * - BACKUP_ENCRYPTION_KEY: 32-byte hex encoded AES-256 key (env var)
17
+ * - BACKUP_ENCRYPTION_ENABLED: Set to 'true' to enable encryption (env var)
18
+ * - IV: Cryptographically random, unique per backup
19
+ * - Auth Tag: GCM authentication tag for integrity verification
20
+ * - HMAC: SHA-256 for additional integrity verification
21
+ *
22
+ * Usage:
23
+ * const encryptionManager = new EncryptionManager();
24
+ * const encrypted = await encryptionManager.encrypt(buffer, backupId);
25
+ * const decrypted = await encryptionManager.decrypt(encrypted, backupId);
26
+ * const verified = encryptionManager.verifyIntegrity(encrypted);
27
+ */ import * as crypto from 'crypto';
28
+ import { createLogger } from './logging.js';
29
+ import { createError, ErrorCode } from './errors.js';
30
+ const logger = createLogger('encryption-manager');
31
+ /**
32
+ * Backup Encryption Manager
33
+ *
34
+ * Implements AES-256-GCM encryption with integrity verification
35
+ */ export class EncryptionManager {
36
+ enabled;
37
+ masterKey = null;
38
+ keyVersion;
39
+ ALGORITHM = 'aes-256-gcm';
40
+ IV_LENGTH = 16;
41
+ AUTH_TAG_LENGTH = 16;
42
+ KEY_LENGTH = 32;
43
+ HMAC_ALGORITHM = 'sha256';
44
+ constructor(config = {}){
45
+ // Check if encryption is enabled
46
+ this.enabled = config.enabled !== undefined ? config.enabled : this.isEncryptionEnabled();
47
+ // Load and validate master key
48
+ if (this.enabled) {
49
+ const keyHex = config.masterKey || process.env.BACKUP_ENCRYPTION_KEY;
50
+ if (!keyHex) {
51
+ throw createError(ErrorCode.VALIDATION_FAILED, 'BACKUP_ENCRYPTION_KEY environment variable is required when encryption is enabled', {
52
+ enabledVia: 'BACKUP_ENCRYPTION_ENABLED env var'
53
+ });
54
+ }
55
+ try {
56
+ this.masterKey = Buffer.from(keyHex, 'hex');
57
+ if (this.masterKey.length !== this.KEY_LENGTH) {
58
+ throw createError(ErrorCode.VALIDATION_FAILED, `Master key must be exactly ${this.KEY_LENGTH} bytes (${this.KEY_LENGTH * 2} hex characters)`, {
59
+ providedLength: this.masterKey.length,
60
+ expectedLength: this.KEY_LENGTH
61
+ });
62
+ }
63
+ logger.info('Encryption manager initialized with AES-256-GCM', {
64
+ enabled: true,
65
+ algorithm: this.ALGORITHM,
66
+ keyLength: this.KEY_LENGTH,
67
+ ivLength: this.IV_LENGTH,
68
+ authTagLength: this.AUTH_TAG_LENGTH
69
+ });
70
+ } catch (error) {
71
+ if (error instanceof Error && 'code' in error) {
72
+ throw error;
73
+ }
74
+ throw createError(ErrorCode.VALIDATION_FAILED, 'Failed to parse BACKUP_ENCRYPTION_KEY. Must be valid hex-encoded 32-byte key.', {
75
+ error: error instanceof Error ? error.message : String(error)
76
+ });
77
+ }
78
+ } else {
79
+ logger.info('Encryption manager initialized with encryption disabled', {
80
+ enabled: false,
81
+ enablementRequired: 'Set BACKUP_ENCRYPTION_ENABLED=true and provide BACKUP_ENCRYPTION_KEY to enable encryption'
82
+ });
83
+ }
84
+ this.keyVersion = config.keyVersion || 'v1';
85
+ }
86
+ /**
87
+ * Check if encryption is enabled
88
+ */ isEnabled() {
89
+ return this.enabled;
90
+ }
91
+ /**
92
+ * Encrypt backup data
93
+ *
94
+ * @param data - Data to encrypt
95
+ * @param backupId - Backup identifier (for logging/tracking)
96
+ * @returns Encrypted backup with metadata
97
+ * @throws Error if encryption is disabled or encryption fails
98
+ */ async encrypt(data, backupId) {
99
+ if (!this.enabled || !this.masterKey) {
100
+ throw createError(ErrorCode.VALIDATION_FAILED, 'Encryption is not enabled. Enable BACKUP_ENCRYPTION_ENABLED and provide BACKUP_ENCRYPTION_KEY.', {
101
+ backupId
102
+ });
103
+ }
104
+ try {
105
+ // Generate cryptographically random IV
106
+ const iv = crypto.randomBytes(this.IV_LENGTH);
107
+ // Create cipher
108
+ const cipher = crypto.createCipheriv(this.ALGORITHM, this.masterKey, iv);
109
+ // Encrypt data
110
+ let encryptedData = cipher.update(data);
111
+ encryptedData = Buffer.concat([
112
+ encryptedData,
113
+ cipher.final()
114
+ ]);
115
+ // Get authentication tag
116
+ const authTag = cipher.getAuthTag();
117
+ // Calculate HMAC for additional integrity verification
118
+ const hmac = crypto.createHmac(this.HMAC_ALGORITHM, this.masterKey).update(Buffer.concat([
119
+ iv,
120
+ encryptedData,
121
+ authTag
122
+ ])).digest();
123
+ // Create metadata
124
+ const metadata = {
125
+ algorithm: 'AES-256-GCM',
126
+ iv: iv.toString('hex'),
127
+ authTag: authTag.toString('hex'),
128
+ hmac: hmac.toString('hex'),
129
+ encryptedAt: new Date().toISOString(),
130
+ keyVersion: this.keyVersion
131
+ };
132
+ logger.debug('Backup encrypted successfully', {
133
+ backupId,
134
+ algorithm: this.ALGORITHM,
135
+ dataSize: data.length,
136
+ encryptedSize: encryptedData.length,
137
+ ivLength: iv.length,
138
+ authTagLength: authTag.length
139
+ });
140
+ return {
141
+ data: encryptedData,
142
+ metadata
143
+ };
144
+ } catch (error) {
145
+ logger.error('Backup encryption failed', error instanceof Error ? error : undefined, {
146
+ backupId
147
+ });
148
+ throw createError(ErrorCode.INTERNAL_ERROR, 'Backup encryption failed', {
149
+ backupId,
150
+ error: error instanceof Error ? error.message : String(error)
151
+ });
152
+ }
153
+ }
154
+ /**
155
+ * Decrypt backup data
156
+ *
157
+ * @param encrypted - Encrypted backup
158
+ * @param backupId - Backup identifier (for logging/tracking)
159
+ * @returns Decryption result with data and integrity verification
160
+ * @throws Error if decryption fails or integrity verification fails
161
+ */ async decrypt(encrypted, backupId) {
162
+ if (!this.enabled || !this.masterKey) {
163
+ throw createError(ErrorCode.VALIDATION_FAILED, 'Encryption is not enabled. Enable BACKUP_ENCRYPTION_ENABLED and provide BACKUP_ENCRYPTION_KEY.', {
164
+ backupId
165
+ });
166
+ }
167
+ try {
168
+ // Verify HMAC first
169
+ const iv = Buffer.from(encrypted.metadata.iv, 'hex');
170
+ const authTag = Buffer.from(encrypted.metadata.authTag, 'hex');
171
+ const expectedHmac = encrypted.metadata.hmac;
172
+ const calculatedHmac = crypto.createHmac(this.HMAC_ALGORITHM, this.masterKey).update(Buffer.concat([
173
+ iv,
174
+ encrypted.data,
175
+ authTag
176
+ ])).digest().toString('hex');
177
+ const integrityVerified = calculatedHmac === expectedHmac;
178
+ if (!integrityVerified) {
179
+ logger.warn('HMAC verification failed during decryption', {
180
+ backupId,
181
+ expectedHmac,
182
+ calculatedHmac
183
+ });
184
+ }
185
+ // Decrypt data
186
+ const decipher = crypto.createDecipheriv(this.ALGORITHM, this.masterKey, iv);
187
+ decipher.setAuthTag(authTag);
188
+ let decryptedData = decipher.update(encrypted.data);
189
+ decryptedData = Buffer.concat([
190
+ decryptedData,
191
+ decipher.final()
192
+ ]);
193
+ logger.debug('Backup decrypted successfully', {
194
+ backupId,
195
+ algorithm: this.ALGORITHM,
196
+ encryptedSize: encrypted.data.length,
197
+ decryptedSize: decryptedData.length,
198
+ integrityVerified
199
+ });
200
+ return {
201
+ data: decryptedData,
202
+ integrityVerified,
203
+ metadata: encrypted.metadata
204
+ };
205
+ } catch (error) {
206
+ logger.error('Backup decryption failed', error instanceof Error ? error : undefined, {
207
+ backupId
208
+ });
209
+ throw createError(ErrorCode.INTERNAL_ERROR, 'Backup decryption failed. Backup may be corrupted or key may be incorrect.', {
210
+ backupId,
211
+ error: error instanceof Error ? error.message : String(error)
212
+ });
213
+ }
214
+ }
215
+ /**
216
+ * Verify backup integrity without decryption
217
+ *
218
+ * @param encrypted - Encrypted backup
219
+ * @param backupId - Backup identifier (for logging)
220
+ * @returns Whether integrity verification passed
221
+ */ verifyIntegrity(encrypted, backupId) {
222
+ if (!this.masterKey) {
223
+ logger.error('Cannot verify integrity without master key', {
224
+ backupId
225
+ });
226
+ return false;
227
+ }
228
+ try {
229
+ const iv = Buffer.from(encrypted.metadata.iv, 'hex');
230
+ const authTag = Buffer.from(encrypted.metadata.authTag, 'hex');
231
+ const expectedHmac = encrypted.metadata.hmac;
232
+ const calculatedHmac = crypto.createHmac(this.HMAC_ALGORITHM, this.masterKey).update(Buffer.concat([
233
+ iv,
234
+ encrypted.data,
235
+ authTag
236
+ ])).digest().toString('hex');
237
+ const verified = calculatedHmac === expectedHmac;
238
+ if (!verified) {
239
+ logger.warn('Integrity verification failed', {
240
+ backupId
241
+ });
242
+ }
243
+ return verified;
244
+ } catch (error) {
245
+ logger.error('Integrity verification error', error instanceof Error ? error : undefined, {
246
+ backupId
247
+ });
248
+ return false;
249
+ }
250
+ }
251
+ /**
252
+ * Detect if a backup file is encrypted
253
+ *
254
+ * Useful for backward compatibility - detects if backup is encrypted
255
+ *
256
+ * @param data - File data
257
+ * @returns Whether the data appears to be encrypted
258
+ */ static isEncrypted(data) {
259
+ // Encrypted data with metadata should have a specific structure
260
+ // For now, we can check if the data is valid JSON metadata (simple heuristic)
261
+ try {
262
+ // Try to detect our encryption format
263
+ // This is a simple heuristic - encrypted data won't be valid text/JSON
264
+ if (data.length < 100) {
265
+ return false;
266
+ }
267
+ // Try to parse as JSON at the end for metadata
268
+ const str = data.toString('utf8', Math.max(0, data.length - 500));
269
+ const match = str.match(/"algorithm"\s*:\s*"AES-256-GCM"/);
270
+ return match !== null;
271
+ } catch {
272
+ return false;
273
+ }
274
+ }
275
+ /**
276
+ * Generate a new encryption key
277
+ *
278
+ * Useful for key rotation
279
+ *
280
+ * @returns 32-byte hex-encoded AES-256 key
281
+ */ static generateKey() {
282
+ return crypto.randomBytes(32).toString('hex');
283
+ }
284
+ /**
285
+ * Export encryption metadata as JSON
286
+ *
287
+ * Useful for storing metadata separately from encrypted data
288
+ *
289
+ * @param encrypted - Encrypted backup
290
+ * @returns JSON stringified metadata
291
+ */ static exportMetadata(encrypted) {
292
+ return JSON.stringify(encrypted.metadata, null, 2);
293
+ }
294
+ /**
295
+ * Import encryption metadata from JSON
296
+ *
297
+ * @param metadataJson - JSON stringified metadata
298
+ * @returns Parsed encryption metadata
299
+ */ static importMetadata(metadataJson) {
300
+ return JSON.parse(metadataJson);
301
+ }
302
+ // ============================================================================
303
+ // Private Helper Methods
304
+ // ============================================================================
305
+ isEncryptionEnabled() {
306
+ const enabled = process.env.BACKUP_ENCRYPTION_ENABLED?.toLowerCase() === 'true';
307
+ return enabled;
308
+ }
309
+ }
310
+ /**
311
+ * Singleton instance
312
+ */ let defaultManager = null;
313
+ /**
314
+ * Get the default encryption manager instance
315
+ */ export function getEncryptionManager(config) {
316
+ if (!defaultManager) {
317
+ defaultManager = new EncryptionManager(config);
318
+ }
319
+ return defaultManager;
320
+ }
321
+
322
+ //# sourceMappingURL=encryption-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/encryption-manager.ts"],"sourcesContent":["/**\r\n * Backup Encryption Manager\r\n *\r\n * Implements AES-256-GCM encryption for backup files with:\r\n * - Secure key management via environment variables\r\n * - Unique IV generation for each backup\r\n * - HMAC-SHA256 integrity verification\r\n * - Key rotation support\r\n * - Backward compatibility detection\r\n * - Encryption metadata tracking\r\n *\r\n * CVSS Mitigation: Addresses CVSS 7.2 (high severity) vulnerability\r\n * by encrypting sensitive backup data at rest.\r\n *\r\n * Security Requirements:\r\n * - BACKUP_ENCRYPTION_KEY: 32-byte hex encoded AES-256 key (env var)\r\n * - BACKUP_ENCRYPTION_ENABLED: Set to 'true' to enable encryption (env var)\r\n * - IV: Cryptographically random, unique per backup\r\n * - Auth Tag: GCM authentication tag for integrity verification\r\n * - HMAC: SHA-256 for additional integrity verification\r\n *\r\n * Usage:\r\n * const encryptionManager = new EncryptionManager();\r\n * const encrypted = await encryptionManager.encrypt(buffer, backupId);\r\n * const decrypted = await encryptionManager.decrypt(encrypted, backupId);\r\n * const verified = encryptionManager.verifyIntegrity(encrypted);\r\n */\r\n\r\nimport * as crypto from 'crypto';\r\nimport { createLogger } from './logging.js';\r\nimport { createError, ErrorCode } from './errors.js';\r\n\r\nconst logger = createLogger('encryption-manager');\r\n\r\n/**\r\n * Encryption metadata stored with encrypted backup\r\n */\r\nexport interface EncryptionMetadata {\r\n /** Encryption algorithm identifier */\r\n algorithm: 'AES-256-GCM';\r\n /** Initialization Vector (hex encoded) */\r\n iv: string;\r\n /** GCM Authentication Tag (hex encoded) */\r\n authTag: string;\r\n /** HMAC verification tag (hex encoded) */\r\n hmac: string;\r\n /** When encryption was applied */\r\n encryptedAt: string;\r\n /** Master key version/ID for key rotation support */\r\n keyVersion: string;\r\n}\r\n\r\n/**\r\n * Encrypted backup payload\r\n */\r\nexport interface EncryptedBackup {\r\n /** Encrypted file content */\r\n data: Buffer;\r\n /** Encryption metadata */\r\n metadata: EncryptionMetadata;\r\n}\r\n\r\n/**\r\n * Decryption result\r\n */\r\nexport interface DecryptionResult {\r\n /** Decrypted content */\r\n data: Buffer;\r\n /** Whether integrity verification passed */\r\n integrityVerified: boolean;\r\n /** Metadata about the encryption */\r\n metadata: EncryptionMetadata;\r\n}\r\n\r\n/**\r\n * Encryption Manager Configuration\r\n */\r\nexport interface EncryptionConfig {\r\n /** Enable encryption (default: from BACKUP_ENCRYPTION_ENABLED env var) */\r\n enabled?: boolean;\r\n /** Master encryption key (32-byte hex, from BACKUP_ENCRYPTION_KEY env var) */\r\n masterKey?: string;\r\n /** Key version ID for rotation tracking (default: 'v1') */\r\n keyVersion?: string;\r\n}\r\n\r\n/**\r\n * Backup Encryption Manager\r\n *\r\n * Implements AES-256-GCM encryption with integrity verification\r\n */\r\nexport class EncryptionManager {\r\n private enabled: boolean;\r\n private masterKey: Buffer | null = null;\r\n private keyVersion: string;\r\n private readonly ALGORITHM = 'aes-256-gcm';\r\n private readonly IV_LENGTH = 16; // 128 bits\r\n private readonly AUTH_TAG_LENGTH = 16; // 128 bits\r\n private readonly KEY_LENGTH = 32; // 256 bits\r\n private readonly HMAC_ALGORITHM = 'sha256';\r\n\r\n constructor(config: EncryptionConfig = {}) {\r\n // Check if encryption is enabled\r\n this.enabled = config.enabled !== undefined ? config.enabled : this.isEncryptionEnabled();\r\n\r\n // Load and validate master key\r\n if (this.enabled) {\r\n const keyHex = config.masterKey || process.env.BACKUP_ENCRYPTION_KEY;\r\n\r\n if (!keyHex) {\r\n throw createError(\r\n ErrorCode.VALIDATION_FAILED,\r\n 'BACKUP_ENCRYPTION_KEY environment variable is required when encryption is enabled',\r\n { enabledVia: 'BACKUP_ENCRYPTION_ENABLED env var' }\r\n );\r\n }\r\n\r\n try {\r\n this.masterKey = Buffer.from(keyHex, 'hex');\r\n\r\n if (this.masterKey.length !== this.KEY_LENGTH) {\r\n throw createError(\r\n ErrorCode.VALIDATION_FAILED,\r\n `Master key must be exactly ${this.KEY_LENGTH} bytes (${this.KEY_LENGTH * 2} hex characters)`,\r\n { providedLength: this.masterKey.length, expectedLength: this.KEY_LENGTH }\r\n );\r\n }\r\n\r\n logger.info('Encryption manager initialized with AES-256-GCM', {\r\n enabled: true,\r\n algorithm: this.ALGORITHM,\r\n keyLength: this.KEY_LENGTH,\r\n ivLength: this.IV_LENGTH,\r\n authTagLength: this.AUTH_TAG_LENGTH,\r\n });\r\n } catch (error) {\r\n if (error instanceof Error && 'code' in error) {\r\n throw error;\r\n }\r\n\r\n throw createError(\r\n ErrorCode.VALIDATION_FAILED,\r\n 'Failed to parse BACKUP_ENCRYPTION_KEY. Must be valid hex-encoded 32-byte key.',\r\n { error: error instanceof Error ? error.message : String(error) }\r\n );\r\n }\r\n } else {\r\n logger.info('Encryption manager initialized with encryption disabled', {\r\n enabled: false,\r\n enablementRequired:\r\n 'Set BACKUP_ENCRYPTION_ENABLED=true and provide BACKUP_ENCRYPTION_KEY to enable encryption',\r\n });\r\n }\r\n\r\n this.keyVersion = config.keyVersion || 'v1';\r\n }\r\n\r\n /**\r\n * Check if encryption is enabled\r\n */\r\n isEnabled(): boolean {\r\n return this.enabled;\r\n }\r\n\r\n /**\r\n * Encrypt backup data\r\n *\r\n * @param data - Data to encrypt\r\n * @param backupId - Backup identifier (for logging/tracking)\r\n * @returns Encrypted backup with metadata\r\n * @throws Error if encryption is disabled or encryption fails\r\n */\r\n async encrypt(data: Buffer, backupId: string): Promise<EncryptedBackup> {\r\n if (!this.enabled || !this.masterKey) {\r\n throw createError(\r\n ErrorCode.VALIDATION_FAILED,\r\n 'Encryption is not enabled. Enable BACKUP_ENCRYPTION_ENABLED and provide BACKUP_ENCRYPTION_KEY.',\r\n { backupId }\r\n );\r\n }\r\n\r\n try {\r\n // Generate cryptographically random IV\r\n const iv = crypto.randomBytes(this.IV_LENGTH);\r\n\r\n // Create cipher\r\n const cipher = crypto.createCipheriv(this.ALGORITHM, this.masterKey, iv);\r\n\r\n // Encrypt data\r\n let encryptedData = cipher.update(data);\r\n encryptedData = Buffer.concat([encryptedData, cipher.final()]);\r\n\r\n // Get authentication tag\r\n const authTag = cipher.getAuthTag();\r\n\r\n // Calculate HMAC for additional integrity verification\r\n const hmac = crypto\r\n .createHmac(this.HMAC_ALGORITHM, this.masterKey)\r\n .update(Buffer.concat([iv, encryptedData, authTag]))\r\n .digest();\r\n\r\n // Create metadata\r\n const metadata: EncryptionMetadata = {\r\n algorithm: 'AES-256-GCM',\r\n iv: iv.toString('hex'),\r\n authTag: authTag.toString('hex'),\r\n hmac: hmac.toString('hex'),\r\n encryptedAt: new Date().toISOString(),\r\n keyVersion: this.keyVersion,\r\n };\r\n\r\n logger.debug('Backup encrypted successfully', {\r\n backupId,\r\n algorithm: this.ALGORITHM,\r\n dataSize: data.length,\r\n encryptedSize: encryptedData.length,\r\n ivLength: iv.length,\r\n authTagLength: authTag.length,\r\n });\r\n\r\n return {\r\n data: encryptedData,\r\n metadata,\r\n };\r\n } catch (error) {\r\n logger.error(\r\n 'Backup encryption failed',\r\n error instanceof Error ? error : undefined,\r\n { backupId }\r\n );\r\n\r\n throw createError(\r\n ErrorCode.INTERNAL_ERROR,\r\n 'Backup encryption failed',\r\n {\r\n backupId,\r\n error: error instanceof Error ? error.message : String(error),\r\n }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Decrypt backup data\r\n *\r\n * @param encrypted - Encrypted backup\r\n * @param backupId - Backup identifier (for logging/tracking)\r\n * @returns Decryption result with data and integrity verification\r\n * @throws Error if decryption fails or integrity verification fails\r\n */\r\n async decrypt(encrypted: EncryptedBackup, backupId: string): Promise<DecryptionResult> {\r\n if (!this.enabled || !this.masterKey) {\r\n throw createError(\r\n ErrorCode.VALIDATION_FAILED,\r\n 'Encryption is not enabled. Enable BACKUP_ENCRYPTION_ENABLED and provide BACKUP_ENCRYPTION_KEY.',\r\n { backupId }\r\n );\r\n }\r\n\r\n try {\r\n // Verify HMAC first\r\n const iv = Buffer.from(encrypted.metadata.iv, 'hex');\r\n const authTag = Buffer.from(encrypted.metadata.authTag, 'hex');\r\n const expectedHmac = encrypted.metadata.hmac;\r\n\r\n const calculatedHmac = crypto\r\n .createHmac(this.HMAC_ALGORITHM, this.masterKey)\r\n .update(Buffer.concat([iv, encrypted.data, authTag]))\r\n .digest()\r\n .toString('hex');\r\n\r\n const integrityVerified = calculatedHmac === expectedHmac;\r\n\r\n if (!integrityVerified) {\r\n logger.warn('HMAC verification failed during decryption', {\r\n backupId,\r\n expectedHmac,\r\n calculatedHmac,\r\n });\r\n }\r\n\r\n // Decrypt data\r\n const decipher = crypto.createDecipheriv(this.ALGORITHM, this.masterKey, iv);\r\n decipher.setAuthTag(authTag);\r\n\r\n let decryptedData = decipher.update(encrypted.data);\r\n decryptedData = Buffer.concat([decryptedData, decipher.final()]);\r\n\r\n logger.debug('Backup decrypted successfully', {\r\n backupId,\r\n algorithm: this.ALGORITHM,\r\n encryptedSize: encrypted.data.length,\r\n decryptedSize: decryptedData.length,\r\n integrityVerified,\r\n });\r\n\r\n return {\r\n data: decryptedData,\r\n integrityVerified,\r\n metadata: encrypted.metadata,\r\n };\r\n } catch (error) {\r\n logger.error(\r\n 'Backup decryption failed',\r\n error instanceof Error ? error : undefined,\r\n { backupId }\r\n );\r\n\r\n throw createError(\r\n ErrorCode.INTERNAL_ERROR,\r\n 'Backup decryption failed. Backup may be corrupted or key may be incorrect.',\r\n {\r\n backupId,\r\n error: error instanceof Error ? error.message : String(error),\r\n }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Verify backup integrity without decryption\r\n *\r\n * @param encrypted - Encrypted backup\r\n * @param backupId - Backup identifier (for logging)\r\n * @returns Whether integrity verification passed\r\n */\r\n verifyIntegrity(encrypted: EncryptedBackup, backupId?: string): boolean {\r\n if (!this.masterKey) {\r\n logger.error('Cannot verify integrity without master key', { backupId });\r\n return false;\r\n }\r\n\r\n try {\r\n const iv = Buffer.from(encrypted.metadata.iv, 'hex');\r\n const authTag = Buffer.from(encrypted.metadata.authTag, 'hex');\r\n const expectedHmac = encrypted.metadata.hmac;\r\n\r\n const calculatedHmac = crypto\r\n .createHmac(this.HMAC_ALGORITHM, this.masterKey)\r\n .update(Buffer.concat([iv, encrypted.data, authTag]))\r\n .digest()\r\n .toString('hex');\r\n\r\n const verified = calculatedHmac === expectedHmac;\r\n\r\n if (!verified) {\r\n logger.warn('Integrity verification failed', { backupId });\r\n }\r\n\r\n return verified;\r\n } catch (error) {\r\n logger.error('Integrity verification error', error instanceof Error ? error : undefined, {\r\n backupId,\r\n });\r\n\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Detect if a backup file is encrypted\r\n *\r\n * Useful for backward compatibility - detects if backup is encrypted\r\n *\r\n * @param data - File data\r\n * @returns Whether the data appears to be encrypted\r\n */\r\n static isEncrypted(data: Buffer): boolean {\r\n // Encrypted data with metadata should have a specific structure\r\n // For now, we can check if the data is valid JSON metadata (simple heuristic)\r\n try {\r\n // Try to detect our encryption format\r\n // This is a simple heuristic - encrypted data won't be valid text/JSON\r\n if (data.length < 100) {\r\n return false;\r\n }\r\n\r\n // Try to parse as JSON at the end for metadata\r\n const str = data.toString('utf8', Math.max(0, data.length - 500));\r\n const match = str.match(/\"algorithm\"\\s*:\\s*\"AES-256-GCM\"/);\r\n\r\n return match !== null;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Generate a new encryption key\r\n *\r\n * Useful for key rotation\r\n *\r\n * @returns 32-byte hex-encoded AES-256 key\r\n */\r\n static generateKey(): string {\r\n return crypto.randomBytes(32).toString('hex');\r\n }\r\n\r\n /**\r\n * Export encryption metadata as JSON\r\n *\r\n * Useful for storing metadata separately from encrypted data\r\n *\r\n * @param encrypted - Encrypted backup\r\n * @returns JSON stringified metadata\r\n */\r\n static exportMetadata(encrypted: EncryptedBackup): string {\r\n return JSON.stringify(encrypted.metadata, null, 2);\r\n }\r\n\r\n /**\r\n * Import encryption metadata from JSON\r\n *\r\n * @param metadataJson - JSON stringified metadata\r\n * @returns Parsed encryption metadata\r\n */\r\n static importMetadata(metadataJson: string): EncryptionMetadata {\r\n return JSON.parse(metadataJson) as EncryptionMetadata;\r\n }\r\n\r\n // ============================================================================\r\n // Private Helper Methods\r\n // ============================================================================\r\n\r\n private isEncryptionEnabled(): boolean {\r\n const enabled = process.env.BACKUP_ENCRYPTION_ENABLED?.toLowerCase() === 'true';\r\n return enabled;\r\n }\r\n}\r\n\r\n/**\r\n * Singleton instance\r\n */\r\nlet defaultManager: EncryptionManager | null = null;\r\n\r\n/**\r\n * Get the default encryption manager instance\r\n */\r\nexport function getEncryptionManager(config?: EncryptionConfig): EncryptionManager {\r\n if (!defaultManager) {\r\n defaultManager = new EncryptionManager(config);\r\n }\r\n return defaultManager;\r\n}\r\n"],"names":["crypto","createLogger","createError","ErrorCode","logger","EncryptionManager","enabled","masterKey","keyVersion","ALGORITHM","IV_LENGTH","AUTH_TAG_LENGTH","KEY_LENGTH","HMAC_ALGORITHM","config","undefined","isEncryptionEnabled","keyHex","process","env","BACKUP_ENCRYPTION_KEY","VALIDATION_FAILED","enabledVia","Buffer","from","length","providedLength","expectedLength","info","algorithm","keyLength","ivLength","authTagLength","error","Error","message","String","enablementRequired","isEnabled","encrypt","data","backupId","iv","randomBytes","cipher","createCipheriv","encryptedData","update","concat","final","authTag","getAuthTag","hmac","createHmac","digest","metadata","toString","encryptedAt","Date","toISOString","debug","dataSize","encryptedSize","INTERNAL_ERROR","decrypt","encrypted","expectedHmac","calculatedHmac","integrityVerified","warn","decipher","createDecipheriv","setAuthTag","decryptedData","decryptedSize","verifyIntegrity","verified","isEncrypted","str","Math","max","match","generateKey","exportMetadata","JSON","stringify","importMetadata","metadataJson","parse","BACKUP_ENCRYPTION_ENABLED","toLowerCase","defaultManager","getEncryptionManager"],"mappings":"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"}