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,905 @@
1
+ /**
2
+ * Query Translator - SECURITY HARDENED
3
+ *
4
+ * Translates between SQL queries and Redis commands for cross-backend compatibility.
5
+ * Includes query optimization and backend recommendation logic.
6
+ *
7
+ * SECURITY ENHANCEMENTS (CVE-2024-SQL-INJECTION):
8
+ * - Input validation with whitelisting for identifiers (table/column names)
9
+ * - Parameterized queries for ALL database values
10
+ * - Comprehensive SQL injection prevention
11
+ * - Strict identifier validation against allowed patterns
12
+ * - Error handling using StandardError
13
+ *
14
+ * Part of Phase 2, Task P2-3.1: Unified Query API
15
+ *
16
+ * Features:
17
+ * - SQL to Redis translation with security validation
18
+ * - Redis to SQL translation with parameterization
19
+ * - Query optimization
20
+ * - Backend recommendation based on query patterns
21
+ * - Performance monitoring (<50ms translation time)
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const translator = new QueryTranslator({
26
+ * allowedTables: ['tasks', 'users', 'projects'],
27
+ * allowedFields: { tasks: ['id', 'name', 'status', 'description'] }
28
+ * });
29
+ *
30
+ * // Translate SQL to Redis (fully parameterized)
31
+ * const redisCmd = translator.translateSQLToRedis(
32
+ * 'SELECT * FROM tasks WHERE id = ?',
33
+ * ['task-123']
34
+ * );
35
+ *
36
+ * // Translate Redis to SQL (fully parameterized)
37
+ * const sqlQuery = translator.translateRedisToSQL({
38
+ * command: 'HGETALL',
39
+ * key: 'task:123'
40
+ * });
41
+ * ```
42
+ */ import { BackendType } from './unified-query-api.js';
43
+ import { StandardError, ErrorCode } from './errors.js';
44
+ /**
45
+ * SQL query parser - SECURITY HARDENED
46
+ */ let SQLParser = class SQLParser {
47
+ allowedTables;
48
+ allowedFields;
49
+ strictMode;
50
+ constructor(allowedTables, allowedFields, strictMode = true){
51
+ this.allowedTables = new Set(allowedTables || []);
52
+ this.allowedFields = new Map();
53
+ if (allowedFields) {
54
+ for (const [table, fields] of Object.entries(allowedFields)){
55
+ this.allowedFields.set(table.toLowerCase(), new Set(fields.map((f)=>f.toLowerCase())));
56
+ }
57
+ }
58
+ this.strictMode = strictMode;
59
+ }
60
+ /**
61
+ * Validate SQL identifier (table/column name)
62
+ * Pattern: alphanumeric, underscore, starts with letter or underscore
63
+ */ validateIdentifier(identifier, type) {
64
+ if (!identifier || typeof identifier !== 'string') {
65
+ return {
66
+ valid: false,
67
+ error: `Invalid ${type} name: must be a non-empty string`
68
+ };
69
+ }
70
+ // Remove surrounding whitespace
71
+ const trimmed = identifier.trim();
72
+ // Check pattern: must start with letter or underscore, contain only alphanumeric and underscore
73
+ const identifierPattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
74
+ if (!identifierPattern.test(trimmed)) {
75
+ return {
76
+ valid: false,
77
+ error: `Invalid ${type} name: must match pattern /^[a-zA-Z_][a-zA-Z0-9_]*$/. Got: "${identifier}"`
78
+ };
79
+ }
80
+ // Check length (reasonable limit to prevent DoS)
81
+ if (trimmed.length > 128) {
82
+ return {
83
+ valid: false,
84
+ error: `Invalid ${type} name: exceeds maximum length of 128 characters`
85
+ };
86
+ }
87
+ return {
88
+ valid: true,
89
+ sanitized: trimmed
90
+ };
91
+ }
92
+ /**
93
+ * Validate table name against whitelist
94
+ */ validateTableName(table) {
95
+ const validation = this.validateIdentifier(table, 'table');
96
+ if (!validation.valid) {
97
+ return validation;
98
+ }
99
+ const sanitized = validation.sanitized.toLowerCase();
100
+ // In strict mode, check against whitelist
101
+ if (this.strictMode && this.allowedTables.size > 0) {
102
+ if (!this.allowedTables.has(sanitized)) {
103
+ return {
104
+ valid: false,
105
+ error: `Table "${table}" is not in the whitelist of allowed tables`
106
+ };
107
+ }
108
+ }
109
+ return {
110
+ valid: true,
111
+ sanitized: validation.sanitized
112
+ };
113
+ }
114
+ /**
115
+ * Validate field name against whitelist for specific table
116
+ */ validateFieldName(field, table) {
117
+ const validation = this.validateIdentifier(field, 'field');
118
+ if (!validation.valid) {
119
+ return validation;
120
+ }
121
+ const sanitized = validation.sanitized.toLowerCase();
122
+ // In strict mode, check against whitelist if available
123
+ if (this.strictMode && table) {
124
+ const tableLower = table.toLowerCase();
125
+ const allowedFieldsForTable = this.allowedFields.get(tableLower);
126
+ if (allowedFieldsForTable && !allowedFieldsForTable.has(sanitized)) {
127
+ return {
128
+ valid: false,
129
+ error: `Field "${field}" is not in the whitelist for table "${table}"`
130
+ };
131
+ }
132
+ }
133
+ return {
134
+ valid: true,
135
+ sanitized: validation.sanitized
136
+ };
137
+ }
138
+ /**
139
+ * Parse SQL SELECT statement
140
+ */ parseSelect(sql) {
141
+ const result = {};
142
+ try {
143
+ // Extract table name
144
+ const tableMatch = sql.match(/FROM\s+(\w+)/i);
145
+ if (tableMatch) {
146
+ const tableValidation = this.validateTableName(tableMatch[1]);
147
+ if (!tableValidation.valid) {
148
+ return {
149
+ error: tableValidation.error
150
+ };
151
+ }
152
+ result.table = tableValidation.sanitized;
153
+ }
154
+ // Extract fields
155
+ const fieldsMatch = sql.match(/SELECT\s+(.*?)\s+FROM/i);
156
+ if (fieldsMatch) {
157
+ const fields = fieldsMatch[1].trim();
158
+ if (fields === '*') {
159
+ result.fields = [
160
+ '*'
161
+ ];
162
+ } else {
163
+ const fieldList = fields.split(',').map((f)=>f.trim());
164
+ const validatedFields = [];
165
+ for (const field of fieldList){
166
+ const fieldValidation = this.validateFieldName(field, result.table);
167
+ if (!fieldValidation.valid) {
168
+ return {
169
+ error: fieldValidation.error
170
+ };
171
+ }
172
+ validatedFields.push(fieldValidation.sanitized);
173
+ }
174
+ result.fields = validatedFields;
175
+ }
176
+ }
177
+ // Extract WHERE clause
178
+ const whereMatch = sql.match(/WHERE\s+(.*?)(?:ORDER BY|GROUP BY|LIMIT|$)/i);
179
+ if (whereMatch) {
180
+ const whereClause = whereMatch[1].trim();
181
+ const whereResult = this.parseWhereClause(whereClause, result.table);
182
+ if (whereResult.error) {
183
+ return {
184
+ error: whereResult.error
185
+ };
186
+ }
187
+ result.where = whereResult.conditions;
188
+ }
189
+ // Extract JOINs
190
+ const joinMatches = sql.matchAll(/(?:INNER |LEFT |RIGHT |)?JOIN\s+(\w+)\s+ON\s+(.*?)(?:WHERE|ORDER BY|GROUP BY|LIMIT|JOIN|$)/gi);
191
+ result.joins = [];
192
+ for (const match of joinMatches){
193
+ const joinTableValidation = this.validateTableName(match[1]);
194
+ if (!joinTableValidation.valid) {
195
+ return {
196
+ error: joinTableValidation.error
197
+ };
198
+ }
199
+ result.joins.push({
200
+ table: joinTableValidation.sanitized,
201
+ on: match[2].trim()
202
+ });
203
+ }
204
+ return result;
205
+ } catch (error) {
206
+ return {
207
+ error: `Failed to parse SELECT statement: ${error instanceof Error ? error.message : 'Unknown error'}`
208
+ };
209
+ }
210
+ }
211
+ /**
212
+ * Parse WHERE clause with validation
213
+ */ parseWhereClause(whereClause, table) {
214
+ const conditions = [];
215
+ try {
216
+ // Simple parser for basic conditions
217
+ // Format: field = ? OR field LIKE ? etc.
218
+ const parts = whereClause.split(/\s+AND\s+/i);
219
+ for (const part of parts){
220
+ const match = part.match(/(\w+)\s*(=|!=|>|>=|<|<=|LIKE|IN|NOT IN)\s*(.+)/i);
221
+ if (match) {
222
+ const fieldValidation = this.validateFieldName(match[1], table);
223
+ if (!fieldValidation.valid) {
224
+ return {
225
+ error: fieldValidation.error
226
+ };
227
+ }
228
+ conditions.push({
229
+ field: fieldValidation.sanitized,
230
+ operator: match[2].toLowerCase(),
231
+ value: match[3] === '?' ? undefined : match[3]
232
+ });
233
+ }
234
+ }
235
+ return {
236
+ conditions
237
+ };
238
+ } catch (error) {
239
+ return {
240
+ error: `Failed to parse WHERE clause: ${error instanceof Error ? error.message : 'Unknown error'}`
241
+ };
242
+ }
243
+ }
244
+ /**
245
+ * Parse SQL INSERT statement with validation
246
+ */ parseInsert(sql) {
247
+ const result = {};
248
+ try {
249
+ // Extract table name
250
+ const tableMatch = sql.match(/INSERT INTO\s+(\w+)/i);
251
+ if (tableMatch) {
252
+ const tableValidation = this.validateTableName(tableMatch[1]);
253
+ if (!tableValidation.valid) {
254
+ return {
255
+ error: tableValidation.error
256
+ };
257
+ }
258
+ result.table = tableValidation.sanitized;
259
+ }
260
+ // Extract fields
261
+ const fieldsMatch = sql.match(/\(([^)]+)\)\s+VALUES/i);
262
+ if (fieldsMatch) {
263
+ const fieldList = fieldsMatch[1].split(',').map((f)=>f.trim());
264
+ const validatedFields = [];
265
+ for (const field of fieldList){
266
+ const fieldValidation = this.validateFieldName(field, result.table);
267
+ if (!fieldValidation.valid) {
268
+ return {
269
+ error: fieldValidation.error
270
+ };
271
+ }
272
+ validatedFields.push(fieldValidation.sanitized);
273
+ }
274
+ result.fields = validatedFields;
275
+ }
276
+ return result;
277
+ } catch (error) {
278
+ return {
279
+ error: `Failed to parse INSERT statement: ${error instanceof Error ? error.message : 'Unknown error'}`
280
+ };
281
+ }
282
+ }
283
+ /**
284
+ * Parse SQL UPDATE statement with validation
285
+ */ parseUpdate(sql) {
286
+ const result = {};
287
+ try {
288
+ // Extract table name
289
+ const tableMatch = sql.match(/UPDATE\s+(\w+)/i);
290
+ if (tableMatch) {
291
+ const tableValidation = this.validateTableName(tableMatch[1]);
292
+ if (!tableValidation.valid) {
293
+ return {
294
+ error: tableValidation.error
295
+ };
296
+ }
297
+ result.table = tableValidation.sanitized;
298
+ }
299
+ // Extract SET clause
300
+ const setMatch = sql.match(/SET\s+(.*?)\s+WHERE/i);
301
+ if (setMatch) {
302
+ const setParts = setMatch[1].split(',');
303
+ const validatedFields = [];
304
+ for (const part of setParts){
305
+ const field = part.split('=')[0].trim();
306
+ const fieldValidation = this.validateFieldName(field, result.table);
307
+ if (!fieldValidation.valid) {
308
+ return {
309
+ error: fieldValidation.error
310
+ };
311
+ }
312
+ validatedFields.push(fieldValidation.sanitized);
313
+ }
314
+ result.fields = validatedFields;
315
+ }
316
+ // Extract WHERE clause
317
+ const whereMatch = sql.match(/WHERE\s+(.*?)$/i);
318
+ if (whereMatch) {
319
+ const whereResult = this.parseWhereClause(whereMatch[1].trim(), result.table);
320
+ if (whereResult.error) {
321
+ return {
322
+ error: whereResult.error
323
+ };
324
+ }
325
+ result.where = whereResult.conditions;
326
+ }
327
+ return result;
328
+ } catch (error) {
329
+ return {
330
+ error: `Failed to parse UPDATE statement: ${error instanceof Error ? error.message : 'Unknown error'}`
331
+ };
332
+ }
333
+ }
334
+ /**
335
+ * Parse SQL DELETE statement with validation
336
+ */ parseDelete(sql) {
337
+ const result = {};
338
+ try {
339
+ // Extract table name
340
+ const tableMatch = sql.match(/DELETE FROM\s+(\w+)/i);
341
+ if (tableMatch) {
342
+ const tableValidation = this.validateTableName(tableMatch[1]);
343
+ if (!tableValidation.valid) {
344
+ return {
345
+ error: tableValidation.error
346
+ };
347
+ }
348
+ result.table = tableValidation.sanitized;
349
+ }
350
+ // Extract WHERE clause
351
+ const whereMatch = sql.match(/WHERE\s+(.*?)$/i);
352
+ if (whereMatch) {
353
+ const whereResult = this.parseWhereClause(whereMatch[1].trim(), result.table);
354
+ if (whereResult.error) {
355
+ return {
356
+ error: whereResult.error
357
+ };
358
+ }
359
+ result.where = whereResult.conditions;
360
+ }
361
+ return result;
362
+ } catch (error) {
363
+ return {
364
+ error: `Failed to parse DELETE statement: ${error instanceof Error ? error.message : 'Unknown error'}`
365
+ };
366
+ }
367
+ }
368
+ };
369
+ /**
370
+ * Query Translator - SECURITY HARDENED
371
+ *
372
+ * Provides bidirectional translation between SQL and Redis commands
373
+ * with comprehensive input validation and SQL injection prevention
374
+ */ export class QueryTranslator {
375
+ parser;
376
+ config;
377
+ constructor(config){
378
+ this.config = {
379
+ allowedTables: config?.allowedTables || [],
380
+ allowedFields: config?.allowedFields || {},
381
+ maxQueryLength: config?.maxQueryLength || 10000,
382
+ maxParams: config?.maxParams || 100,
383
+ strictMode: config?.strictMode !== false
384
+ };
385
+ this.parser = new SQLParser(this.config.allowedTables, this.config.allowedFields, this.config.strictMode);
386
+ }
387
+ /**
388
+ * Validate input parameters
389
+ */ validateInput(sql, params = []) {
390
+ if (!sql || typeof sql !== 'string') {
391
+ return {
392
+ valid: false,
393
+ error: 'SQL query must be a non-empty string'
394
+ };
395
+ }
396
+ if (sql.length > this.config.maxQueryLength) {
397
+ return {
398
+ valid: false,
399
+ error: `SQL query exceeds maximum length of ${this.config.maxQueryLength} characters`
400
+ };
401
+ }
402
+ if (!Array.isArray(params)) {
403
+ return {
404
+ valid: false,
405
+ error: 'Parameters must be an array'
406
+ };
407
+ }
408
+ if (params.length > this.config.maxParams) {
409
+ return {
410
+ valid: false,
411
+ error: `Too many parameters. Maximum: ${this.config.maxParams}`
412
+ };
413
+ }
414
+ // Detect SQL injection patterns in the query
415
+ // These patterns should ONLY appear in specific contexts (after ?)
416
+ const injectionPatterns = [
417
+ /\bOR\b[\s]*(\d+\s*=\s*\d+|'[^']*'\s*=\s*'[^']*'|true|1)/i,
418
+ /\bUNION\b[\s]+(SELECT|ALL)/i,
419
+ /--\s*$/i,
420
+ /\/\*[\s\S]*?\*\//i,
421
+ /;\s*(SELECT|INSERT|UPDATE|DELETE|DROP|TRUNCATE|ALTER)/i,
422
+ /\bDROP\b|\bTRUNCATE\b|\bALTER\b|\bCREATE\b/i,
423
+ /\bEVAL\b|\bEXEC\b|\bSCRIPT\b/i,
424
+ /\x00/
425
+ ];
426
+ // Split query into parts based on ? placeholders
427
+ const parts = sql.split('?');
428
+ // Check structure: should be [prefix, suffix] or [prefix1, middle1, middle2, suffix]
429
+ // Injection attempts will have SQL keywords AFTER the ?
430
+ for(let i = 0; i < parts.length; i++){
431
+ const part = parts[i];
432
+ // First part should contain SELECT/INSERT/UPDATE/DELETE/FROM
433
+ if (i === 0) {
434
+ // Validate it's a valid SQL statement start
435
+ if (!/(SELECT|INSERT|UPDATE|DELETE|FROM)\b/i.test(part)) {
436
+ // Only valid if it's completely empty (error caught elsewhere)
437
+ if (part.trim()) {
438
+ return {
439
+ valid: false,
440
+ error: 'Invalid SQL query structure. Must start with SELECT, INSERT, UPDATE, or DELETE'
441
+ };
442
+ }
443
+ }
444
+ } else if (i === parts.length - 1) {
445
+ // Last part (after last ?) should not have SQL keywords that indicate injection
446
+ if (/\b(OR|UNION|SELECT|INSERT|UPDATE|DELETE|DROP|TRUNCATE)\b/i.test(part)) {
447
+ return {
448
+ valid: false,
449
+ error: 'SQL query contains suspicious injection patterns'
450
+ };
451
+ }
452
+ } else {
453
+ // Middle parts (between ? and ?) should be minimal
454
+ // Should only contain WHERE, AND, OR (as operators), commas, etc.
455
+ // But NOT SELECT, UNION, etc.
456
+ if (/\b(UNION|SELECT|INSERT|UPDATE|DELETE|DROP)\b/i.test(part)) {
457
+ return {
458
+ valid: false,
459
+ error: 'SQL query contains suspicious injection patterns'
460
+ };
461
+ }
462
+ }
463
+ }
464
+ // Check for injection patterns in the entire query
465
+ for (const pattern of injectionPatterns){
466
+ // Skip OR if it's part of valid syntax (after WHERE)
467
+ if (pattern.source.includes('OR') && /WHERE[\s\S]*\?[\s\S]*OR/i.test(sql)) {
468
+ // This could be valid OR in WHERE clause
469
+ const afterQuestion = sql.substring(sql.indexOf('?') + 1);
470
+ if (/\bOR\b[\s]*[\'\"]?\d+['\"]*\s*=\s*[\'\"]?\d+['\"]*|OR\s*'[^']*'\s*=\s*'[^']*'|OR\s*TRUE/i.test(afterQuestion)) {
471
+ return {
472
+ valid: false,
473
+ error: 'SQL query contains SQL injection pattern: OR-based bypass'
474
+ };
475
+ }
476
+ } else if (pattern.test(sql) && !sql.includes('?')) {
477
+ // Pattern found but no parameterization
478
+ return {
479
+ valid: false,
480
+ error: 'SQL query contains suspicious patterns. Use parameterized queries.'
481
+ };
482
+ }
483
+ }
484
+ return {
485
+ valid: true
486
+ };
487
+ }
488
+ /**
489
+ * Validate Redis command structure
490
+ */ validateRedisCommand(command) {
491
+ if (!command || typeof command !== 'object') {
492
+ return {
493
+ valid: false,
494
+ error: 'Redis command must be an object'
495
+ };
496
+ }
497
+ if (!command.command || typeof command.command !== 'string') {
498
+ return {
499
+ valid: false,
500
+ error: 'Redis command name must be a non-empty string'
501
+ };
502
+ }
503
+ const allowedCommands = [
504
+ 'GET',
505
+ 'SET',
506
+ 'HGET',
507
+ 'HGETALL',
508
+ 'HMSET',
509
+ 'HSET',
510
+ 'DEL',
511
+ 'MGET',
512
+ 'MSET'
513
+ ];
514
+ if (!allowedCommands.includes(command.command.toUpperCase())) {
515
+ return {
516
+ valid: false,
517
+ error: `Redis command "${command.command}" is not allowed. Allowed: ${allowedCommands.join(', ')}`
518
+ };
519
+ }
520
+ if (command.key && typeof command.key !== 'string') {
521
+ return {
522
+ valid: false,
523
+ error: 'Redis key must be a string'
524
+ };
525
+ }
526
+ if (command.fields && typeof command.fields !== 'object') {
527
+ return {
528
+ valid: false,
529
+ error: 'Redis fields must be an object'
530
+ };
531
+ }
532
+ if (command.args && !Array.isArray(command.args)) {
533
+ return {
534
+ valid: false,
535
+ error: 'Redis args must be an array'
536
+ };
537
+ }
538
+ return {
539
+ valid: true
540
+ };
541
+ }
542
+ /**
543
+ * Translate SQL query to Redis commands
544
+ */ translateSQLToRedis(sql, params = []) {
545
+ const startTime = Date.now();
546
+ const warnings = [];
547
+ try {
548
+ // Validate inputs
549
+ const inputValidation = this.validateInput(sql, params);
550
+ if (!inputValidation.valid) {
551
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, inputValidation.error || 'Invalid input', {
552
+ sql,
553
+ paramCount: params.length
554
+ });
555
+ }
556
+ // Determine query type
557
+ const queryType = this.getQueryType(sql);
558
+ let redisCommand;
559
+ let recommendedBackend = BackendType.REDIS;
560
+ switch(queryType){
561
+ case 'SELECT':
562
+ {
563
+ const selectParsed = this.parser.parseSelect(sql);
564
+ if (selectParsed.error) {
565
+ throw new StandardError(ErrorCode.PARSE_ERROR, `Failed to parse SELECT statement: ${selectParsed.error}`, {
566
+ sql
567
+ });
568
+ }
569
+ // Check if query is complex (has joins)
570
+ if (selectParsed.joins && selectParsed.joins.length > 0) {
571
+ warnings.push('Complex queries with JOINs are better suited for PostgreSQL');
572
+ recommendedBackend = BackendType.POSTGRES;
573
+ }
574
+ // Translate to Redis HGETALL or GET
575
+ if (selectParsed.where && selectParsed.where.length > 0) {
576
+ const idCondition = selectParsed.where.find((w)=>w.field === 'id');
577
+ if (idCondition) {
578
+ const keyValue = params[0];
579
+ // Validate key value
580
+ if (typeof keyValue !== 'string' && typeof keyValue !== 'number') {
581
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Redis key value must be a string or number', {
582
+ paramValue: typeof keyValue
583
+ });
584
+ }
585
+ const redisKey = `${selectParsed.table}:${keyValue}`;
586
+ redisCommand = {
587
+ command: selectParsed.fields?.[0] === '*' ? 'HGETALL' : 'HGET',
588
+ key: redisKey
589
+ };
590
+ }
591
+ }
592
+ break;
593
+ }
594
+ case 'INSERT':
595
+ {
596
+ const insertParsed = this.parser.parseInsert(sql);
597
+ if (insertParsed.error) {
598
+ throw new StandardError(ErrorCode.PARSE_ERROR, `Failed to parse INSERT statement: ${insertParsed.error}`, {
599
+ sql
600
+ });
601
+ }
602
+ if (insertParsed.table && insertParsed.fields) {
603
+ const idValue = params[0];
604
+ // Validate key value
605
+ if (typeof idValue !== 'string' && typeof idValue !== 'number') {
606
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Redis key value must be a string or number', {
607
+ paramValue: typeof idValue
608
+ });
609
+ }
610
+ const redisKey = `${insertParsed.table}:${idValue}`;
611
+ // Build field-value pairs with validation
612
+ const fields = {};
613
+ for(let i = 0; i < insertParsed.fields.length && i < params.length; i++){
614
+ // Ensure params are not objects/arrays (prevent injection)
615
+ const paramValue = params[i];
616
+ if (typeof paramValue === 'object' && paramValue !== null) {
617
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Parameter values must be primitives (string, number, boolean, null)', {
618
+ paramIndex: i,
619
+ paramType: typeof paramValue
620
+ });
621
+ }
622
+ fields[insertParsed.fields[i]] = paramValue;
623
+ }
624
+ redisCommand = {
625
+ command: 'HMSET',
626
+ key: redisKey,
627
+ fields
628
+ };
629
+ }
630
+ break;
631
+ }
632
+ case 'UPDATE':
633
+ {
634
+ const updateParsed = this.parser.parseUpdate(sql);
635
+ if (updateParsed.error) {
636
+ throw new StandardError(ErrorCode.PARSE_ERROR, `Failed to parse UPDATE statement: ${updateParsed.error}`, {
637
+ sql
638
+ });
639
+ }
640
+ if (updateParsed.table && updateParsed.where) {
641
+ const idCondition = updateParsed.where.find((w)=>w.field === 'id');
642
+ if (idCondition) {
643
+ const keyValue = params[params.length - 1];
644
+ // Validate key value
645
+ if (typeof keyValue !== 'string' && typeof keyValue !== 'number') {
646
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Redis key value must be a string or number', {
647
+ paramValue: typeof keyValue
648
+ });
649
+ }
650
+ const redisKey = `${updateParsed.table}:${keyValue}`;
651
+ redisCommand = {
652
+ command: 'HSET',
653
+ key: redisKey,
654
+ args: params.slice(0, -1)
655
+ };
656
+ }
657
+ }
658
+ break;
659
+ }
660
+ case 'DELETE':
661
+ {
662
+ const deleteParsed = this.parser.parseDelete(sql);
663
+ if (deleteParsed.error) {
664
+ throw new StandardError(ErrorCode.PARSE_ERROR, `Failed to parse DELETE statement: ${deleteParsed.error}`, {
665
+ sql
666
+ });
667
+ }
668
+ if (deleteParsed.table && deleteParsed.where) {
669
+ const idCondition = deleteParsed.where.find((w)=>w.field === 'id');
670
+ if (idCondition) {
671
+ const keyValue = params[0];
672
+ // Validate key value
673
+ if (typeof keyValue !== 'string' && typeof keyValue !== 'number') {
674
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Redis key value must be a string or number', {
675
+ paramValue: typeof keyValue
676
+ });
677
+ }
678
+ const redisKey = `${deleteParsed.table}:${keyValue}`;
679
+ redisCommand = {
680
+ command: 'DEL',
681
+ key: redisKey
682
+ };
683
+ }
684
+ }
685
+ break;
686
+ }
687
+ default:
688
+ warnings.push(`Unsupported SQL query type: ${queryType}`);
689
+ recommendedBackend = BackendType.POSTGRES;
690
+ }
691
+ const executionTime = Date.now() - startTime;
692
+ if (executionTime > 50) {
693
+ warnings.push(`Translation took ${executionTime}ms (target: <50ms)`);
694
+ }
695
+ return {
696
+ success: !!redisCommand,
697
+ redisCommand,
698
+ executionTime,
699
+ recommendedBackend,
700
+ warnings: warnings.length > 0 ? warnings : undefined
701
+ };
702
+ } catch (error) {
703
+ const executionTime = Date.now() - startTime;
704
+ const message = error instanceof StandardError ? error.message : error instanceof Error ? error.message : 'Unknown error';
705
+ return {
706
+ success: false,
707
+ executionTime,
708
+ warnings: [
709
+ `Translation failed: ${message}`
710
+ ]
711
+ };
712
+ }
713
+ }
714
+ /**
715
+ * Translate Redis command to SQL query (with parameterization)
716
+ */ translateRedisToSQL(command) {
717
+ const startTime = Date.now();
718
+ const warnings = [];
719
+ try {
720
+ // Validate Redis command
721
+ const commandValidation = this.validateRedisCommand(command);
722
+ if (!commandValidation.valid) {
723
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, commandValidation.error || 'Invalid Redis command', {
724
+ command: command.command
725
+ });
726
+ }
727
+ let sqlQuery;
728
+ let sqlParams = [];
729
+ // Parse Redis key to extract table and ID
730
+ const keyParts = command.key?.split(':') || [];
731
+ const table = keyParts[0] || 'unknown';
732
+ const id = keyParts[1];
733
+ // Validate table name
734
+ const tableValidation = this.parser['validateTableName'] || ((t)=>({
735
+ valid: true,
736
+ sanitized: t
737
+ }));
738
+ // Since validateTableName is private, we do basic validation
739
+ const tablePattern = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
740
+ if (!tablePattern.test(table)) {
741
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Invalid table name in Redis key', {
742
+ key: command.key
743
+ });
744
+ }
745
+ switch(command.command.toUpperCase()){
746
+ case 'GET':
747
+ case 'HGET':
748
+ case 'HGETALL':
749
+ {
750
+ // SELECT * FROM table WHERE id = ?
751
+ sqlQuery = `SELECT * FROM ${table} WHERE id = ?`;
752
+ sqlParams = [
753
+ id
754
+ ];
755
+ break;
756
+ }
757
+ case 'SET':
758
+ case 'HMSET':
759
+ {
760
+ // INSERT INTO table (field1, field2, ...) VALUES (?, ?, ...)
761
+ if (command.fields) {
762
+ const fields = Object.keys(command.fields);
763
+ const placeholders = fields.map(()=>'?').join(', ');
764
+ sqlQuery = `INSERT INTO ${table} (${fields.join(', ')}) VALUES (${placeholders})`;
765
+ sqlParams = Object.values(command.fields);
766
+ // Validate all params are primitives
767
+ for(let i = 0; i < sqlParams.length; i++){
768
+ if (typeof sqlParams[i] === 'object' && sqlParams[i] !== null) {
769
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Parameter values must be primitives', {
770
+ paramIndex: i
771
+ });
772
+ }
773
+ }
774
+ }
775
+ break;
776
+ }
777
+ case 'HSET':
778
+ {
779
+ // UPDATE table SET field = ? WHERE id = ?
780
+ if (command.args && command.args.length > 0) {
781
+ const field = command.args[0];
782
+ // Validate field name
783
+ if (typeof field !== 'string' || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(field)) {
784
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Invalid field name in HSET command', {
785
+ field
786
+ });
787
+ }
788
+ sqlQuery = `UPDATE ${table} SET ${field} = ? WHERE id = ?`;
789
+ sqlParams = [
790
+ command.args[1],
791
+ id
792
+ ];
793
+ // Validate params
794
+ for(let i = 0; i < sqlParams.length; i++){
795
+ if (typeof sqlParams[i] === 'object' && sqlParams[i] !== null) {
796
+ throw new StandardError(ErrorCode.VALIDATION_FAILED, 'Parameter values must be primitives', {
797
+ paramIndex: i
798
+ });
799
+ }
800
+ }
801
+ }
802
+ break;
803
+ }
804
+ case 'DEL':
805
+ {
806
+ // DELETE FROM table WHERE id = ?
807
+ sqlQuery = `DELETE FROM ${table} WHERE id = ?`;
808
+ sqlParams = [
809
+ id
810
+ ];
811
+ break;
812
+ }
813
+ default:
814
+ warnings.push(`Unsupported Redis command: ${command.command}`);
815
+ }
816
+ const executionTime = Date.now() - startTime;
817
+ if (executionTime > 50) {
818
+ warnings.push(`Translation took ${executionTime}ms (target: <50ms)`);
819
+ }
820
+ return {
821
+ success: !!sqlQuery,
822
+ sqlQuery,
823
+ sqlParams,
824
+ executionTime,
825
+ warnings: warnings.length > 0 ? warnings : undefined
826
+ };
827
+ } catch (error) {
828
+ const executionTime = Date.now() - startTime;
829
+ const message = error instanceof StandardError ? error.message : error instanceof Error ? error.message : 'Unknown error';
830
+ return {
831
+ success: false,
832
+ executionTime,
833
+ warnings: [
834
+ `Translation failed: ${message}`
835
+ ]
836
+ };
837
+ }
838
+ }
839
+ /**
840
+ * Optimize query and provide recommendations
841
+ */ optimizeQuery(request) {
842
+ const result = {
843
+ indexed: [],
844
+ recommendations: []
845
+ };
846
+ // Recommend indexes for filtered fields
847
+ if (request.filters) {
848
+ const indexFields = request.filters.map((f)=>String(f.field));
849
+ result.indexed = indexFields;
850
+ result.indexes = indexFields;
851
+ result.recommendations?.push(`Consider adding indexes on: ${indexFields.join(', ')}`);
852
+ }
853
+ // Estimate query cost
854
+ let cost = 1;
855
+ if (request.joins) {
856
+ cost += request.joins.length * 10; // JOINs are expensive
857
+ }
858
+ if (request.filters) {
859
+ cost += request.filters.length * 2;
860
+ }
861
+ result.estimatedCost = cost;
862
+ // Provide optimization recommendations
863
+ if (request.joins && request.joins.length > 2) {
864
+ result.recommendations?.push('Consider denormalizing data or using materialized views for complex joins');
865
+ }
866
+ if (request.filters && request.filters.length > 5) {
867
+ result.recommendations?.push('Consider composite indexes for multiple filter conditions');
868
+ }
869
+ return result;
870
+ }
871
+ /**
872
+ * Recommend backend based on query characteristics
873
+ */ recommendBackend(request) {
874
+ // Simple key-value access → Redis
875
+ if (request.key && !request.joins) {
876
+ return BackendType.REDIS;
877
+ }
878
+ // Complex queries with JOINs → PostgreSQL
879
+ if (request.joins && request.joins.length > 0) {
880
+ return BackendType.POSTGRES;
881
+ }
882
+ // Session/cache data → Redis
883
+ if (request.dataType === 'cache' || request.dataType === 'session') {
884
+ return BackendType.REDIS;
885
+ }
886
+ // Embedded/local data → SQLite
887
+ if (request.dataType === 'embedded') {
888
+ return BackendType.SQLITE;
889
+ }
890
+ // Default to PostgreSQL for structured data
891
+ return BackendType.POSTGRES;
892
+ }
893
+ /**
894
+ * Get query type from SQL string
895
+ */ getQueryType(sql) {
896
+ const trimmed = sql.trim().toUpperCase();
897
+ if (trimmed.startsWith('SELECT')) return 'SELECT';
898
+ if (trimmed.startsWith('INSERT')) return 'INSERT';
899
+ if (trimmed.startsWith('UPDATE')) return 'UPDATE';
900
+ if (trimmed.startsWith('DELETE')) return 'DELETE';
901
+ return 'UNKNOWN';
902
+ }
903
+ }
904
+
905
+ //# sourceMappingURL=query-translator.js.map