thanh-kit 2.5.0 → 2.5.2

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 (886) hide show
  1. package/dist/index.js +20 -61
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/.ck.json +60 -0
  5. package/templates/.ckignore +27 -0
  6. package/templates/.mcp.json.example +23 -0
  7. package/templates/agents/brainstormer.md +18 -2
  8. package/templates/agents/code-reviewer.md +122 -142
  9. package/templates/agents/code-simplifier.md +50 -100
  10. package/templates/agents/debugger.md +27 -11
  11. package/templates/agents/docs-manager.md +100 -38
  12. package/templates/agents/fullstack-developer.md +15 -3
  13. package/templates/agents/git-manager.md +11 -386
  14. package/templates/agents/journal-writer.md +13 -8
  15. package/templates/agents/mcp-manager.md +21 -6
  16. package/templates/agents/planner.md +24 -8
  17. package/templates/agents/project-manager.md +17 -121
  18. package/templates/agents/researcher.md +22 -7
  19. package/templates/agents/tester.md +23 -7
  20. package/templates/agents/ui-ux-designer.md +23 -14
  21. package/templates/{commands → command-archive}/ask.md +5 -5
  22. package/templates/{commands → command-archive}/ck-help.md +18 -2
  23. package/templates/command-archive/docs/init.md +38 -0
  24. package/templates/command-archive/docs/summarize.md +22 -0
  25. package/templates/command-archive/docs/update.md +76 -0
  26. package/templates/command-archive/journal.md +18 -0
  27. package/templates/{commands → command-archive}/kanban.md +5 -7
  28. package/templates/{commands → command-archive}/plan/archive.md +2 -2
  29. package/templates/command-archive/plan/red-team.md +200 -0
  30. package/templates/command-archive/plan/validate.md +188 -0
  31. package/templates/command-archive/preview.md +283 -0
  32. package/templates/command-archive/review/codebase/parallel.md +122 -0
  33. package/templates/{commands → command-archive}/test/ui.md +3 -3
  34. package/templates/{commands → command-archive}/use-mcp.md +6 -2
  35. package/templates/command-archive/worktree.md +109 -0
  36. package/templates/hooks/__tests__/ck-config-utils.test.cjs +557 -0
  37. package/templates/hooks/__tests__/descriptive-name.test.cjs +292 -0
  38. package/templates/hooks/__tests__/dev-rules-reminder.test.cjs +336 -0
  39. package/templates/hooks/__tests__/integration/path-resolution.test.cjs +319 -0
  40. package/templates/hooks/__tests__/privacy-block.test.cjs +273 -0
  41. package/templates/hooks/__tests__/session-init.test.cjs +308 -0
  42. package/templates/hooks/__tests__/skill-dedup.test.cjs +527 -0
  43. package/templates/hooks/__tests__/subagent-init.test.cjs +622 -0
  44. package/templates/hooks/__tests__/task-completed-handler.test.cjs +246 -0
  45. package/templates/hooks/__tests__/team-context-inject.test.cjs +804 -0
  46. package/templates/hooks/__tests__/teammate-idle-handler.test.cjs +254 -0
  47. package/templates/hooks/cook-after-plan-reminder.cjs +72 -0
  48. package/templates/hooks/descriptive-name.cjs +47 -0
  49. package/templates/hooks/dev-rules-reminder.cjs +37 -214
  50. package/templates/hooks/lib/__tests__/README.md +240 -0
  51. package/templates/hooks/lib/__tests__/ck-config-utils.test.cjs +613 -1
  52. package/templates/hooks/lib/__tests__/context-builder.test.cjs +468 -0
  53. package/templates/hooks/lib/__tests__/project-detector.test.cjs +754 -0
  54. package/templates/hooks/lib/__tests__/statusline-integration.test.cjs +678 -0
  55. package/templates/hooks/lib/__tests__/statusline.test.cjs +689 -0
  56. package/templates/hooks/lib/ck-config-utils.cjs +146 -21
  57. package/templates/hooks/lib/colors.cjs +95 -0
  58. package/templates/hooks/lib/config-counter.cjs +103 -0
  59. package/templates/hooks/lib/context-builder.cjs +616 -0
  60. package/templates/hooks/lib/git-info-cache.cjs +143 -0
  61. package/templates/hooks/lib/hook-logger.cjs +92 -0
  62. package/templates/hooks/lib/privacy-checker.cjs +297 -0
  63. package/templates/hooks/lib/project-detector.cjs +474 -0
  64. package/templates/hooks/lib/scout-checker.cjs +263 -0
  65. package/templates/hooks/lib/transcript-parser.cjs +181 -0
  66. package/templates/hooks/notifications/discord_notify.sh +17 -4
  67. package/templates/hooks/notifications/docs/discord-hook-setup.md +26 -10
  68. package/templates/hooks/notifications/docs/telegram-hook-setup.md +24 -6
  69. package/templates/hooks/notifications/notify.cjs +0 -0
  70. package/templates/hooks/notifications/send-discord.sh +0 -0
  71. package/templates/hooks/notifications/telegram_notify.sh +17 -4
  72. package/templates/hooks/post-edit-simplify-reminder.cjs +156 -0
  73. package/templates/hooks/privacy-block.cjs +97 -188
  74. package/templates/hooks/scout-block/broad-pattern-detector.cjs +4 -6
  75. package/templates/hooks/scout-block/error-formatter.cjs +0 -0
  76. package/templates/hooks/scout-block/path-extractor.cjs +102 -13
  77. package/templates/hooks/scout-block/pattern-matcher.cjs +16 -1
  78. package/templates/hooks/scout-block/tests/{test-broad-pattern-detector.js → test-broad-pattern-detector.cjs} +1 -61
  79. package/templates/hooks/scout-block/tests/{test-build-command-allowlist.js → test-build-command-allowlist.cjs} +1 -1
  80. package/templates/hooks/scout-block/tests/{test-error-formatter.js → test-error-formatter.cjs} +1 -1
  81. package/templates/hooks/scout-block/tests/{test-full-flow-edge-cases.js → test-full-flow-edge-cases.cjs} +1 -1
  82. package/templates/hooks/scout-block/tests/{test-monorepo-scenarios.js → test-monorepo-scenarios.cjs} +1 -1
  83. package/templates/hooks/scout-block/tests/{test-path-extractor.js → test-path-extractor.cjs} +1 -1
  84. package/templates/hooks/scout-block/tests/{test-pattern-matcher.js → test-pattern-matcher.cjs} +1 -1
  85. package/templates/hooks/scout-block.cjs +100 -87
  86. package/templates/hooks/session-init.cjs +197 -330
  87. package/templates/hooks/skill-dedup.cjs +268 -0
  88. package/templates/hooks/subagent-init.cjs +75 -22
  89. package/templates/hooks/task-completed-handler.cjs +118 -0
  90. package/templates/hooks/team-context-inject.cjs +176 -0
  91. package/templates/hooks/teammate-idle-handler.cjs +121 -0
  92. package/templates/hooks/tests/scout-block/broad-pattern-detector.test.cjs +231 -0
  93. package/templates/hooks/tests/scout-block/fixtures/ckignore-custom.txt +6 -0
  94. package/templates/hooks/tests/scout-block/fixtures/ckignore-default.txt +13 -0
  95. package/templates/hooks/tests/scout-block/fixtures/ckignore-negation.txt +8 -0
  96. package/templates/hooks/tests/scout-block/path-extractor.test.cjs +527 -0
  97. package/templates/hooks/tests/scout-block/pattern-matcher.test.cjs +293 -0
  98. package/templates/hooks/tests/scout-block/scout-checker.test.cjs +741 -0
  99. package/templates/hooks/tests/{test-ckignore.js → test-ckignore.cjs} +0 -0
  100. package/templates/hooks/tests/{test-modularization-hook.js → test-modularization-hook.cjs} +0 -0
  101. package/templates/hooks/tests/{test-privacy-block.js → test-privacy-block.cjs} +1 -1
  102. package/templates/hooks/tests/test-scout-block.cjs +315 -0
  103. package/templates/hooks/usage-context-awareness.cjs +179 -0
  104. package/templates/metadata.json +104 -0
  105. package/templates/{workflows → rules}/development-rules.md +12 -53
  106. package/templates/rules/orchestration-protocol.md +43 -0
  107. package/templates/{workflows → rules}/primary-workflow.md +16 -4
  108. package/templates/rules/team-coordination-rules.md +90 -0
  109. package/templates/schemas/ck-config.schema.json +381 -0
  110. package/templates/scripts/README.md +94 -198
  111. package/templates/scripts/ck-help.py +19 -855
  112. package/templates/scripts/commands_data.yaml +3 -621
  113. package/templates/scripts/fix-shebang-permissions.sh +50 -0
  114. package/templates/scripts/generate_catalogs.py +37 -8
  115. package/templates/scripts/resolve_env.py +0 -0
  116. package/templates/scripts/scan_commands.py +14 -96
  117. package/templates/scripts/scan_skills.py +59 -19
  118. package/templates/scripts/set-active-plan.cjs +8 -3
  119. package/templates/scripts/skills_data.yaml +2 -596
  120. package/templates/scripts/test-ck-help.py +15 -0
  121. package/templates/scripts/test_ck_help.py +139 -0
  122. package/templates/scripts/test_ck_help_integration.py +72 -0
  123. package/templates/scripts/validate-docs.cjs +342 -0
  124. package/templates/scripts/win_compat.py +0 -0
  125. package/templates/scripts/worktree.cjs +4 -652
  126. package/templates/scripts/worktree.test.cjs +5 -330
  127. package/templates/settings.json +104 -239
  128. package/templates/skills/README.md +95 -255
  129. package/templates/skills/THIRD_PARTY_NOTICES.md +405 -0
  130. package/templates/skills/agent-browser/SKILL.md +294 -0
  131. package/templates/skills/agent-browser/references/.gitkeep +0 -0
  132. package/templates/skills/agent-browser/references/agent-browser-vs-chrome-devtools.md +112 -0
  133. package/templates/skills/agent-browser/references/browserbase-cloud-setup.md +161 -0
  134. package/templates/skills/ai-artist/SKILL.md +103 -56
  135. package/templates/skills/ai-artist/data/awesome-prompts.csv +3592 -0
  136. package/templates/skills/ai-artist/data/lighting.csv +19 -0
  137. package/templates/skills/ai-artist/data/nano-banana-templates.csv +17 -0
  138. package/templates/skills/ai-artist/data/platforms.csv +11 -0
  139. package/templates/skills/ai-artist/data/styles.csv +26 -0
  140. package/templates/skills/ai-artist/data/techniques.csv +19 -0
  141. package/templates/skills/ai-artist/data/use-cases.csv +16 -0
  142. package/templates/skills/ai-artist/references/awesome-nano-banana-pro-prompts.md +8575 -0
  143. package/templates/skills/ai-artist/references/nano-banana.md +78 -1
  144. package/templates/skills/ai-artist/references/validation-workflow.md +117 -0
  145. package/templates/skills/ai-artist/scripts/core.py +197 -0
  146. package/templates/skills/ai-artist/scripts/extract_prompts.py +102 -0
  147. package/templates/skills/ai-artist/scripts/generate.py +370 -0
  148. package/templates/skills/ai-artist/scripts/search.py +147 -0
  149. package/templates/skills/ai-multimodal/SKILL.md +4 -3
  150. package/templates/skills/ai-multimodal/scripts/check_setup.py +12 -2
  151. package/templates/skills/ai-multimodal/scripts/document_converter.py +0 -0
  152. package/templates/skills/ai-multimodal/scripts/gemini_batch_process.py +3 -2
  153. package/templates/skills/ai-multimodal/scripts/media_optimizer.py +0 -0
  154. package/templates/skills/ask/SKILL.md +58 -0
  155. package/templates/skills/backend-development/SKILL.md +3 -2
  156. package/templates/skills/better-auth/SKILL.md +3 -2
  157. package/templates/skills/better-auth/scripts/better_auth_init.py +3 -3
  158. package/templates/skills/bootstrap/SKILL.md +101 -0
  159. package/templates/skills/bootstrap/references/shared-phases.md +59 -0
  160. package/templates/skills/bootstrap/references/workflow-auto.md +52 -0
  161. package/templates/skills/bootstrap/references/workflow-fast.md +50 -0
  162. package/templates/skills/bootstrap/references/workflow-full.md +60 -0
  163. package/templates/skills/bootstrap/references/workflow-parallel.md +59 -0
  164. package/templates/{commands/brainstorm.md → skills/brainstorm/SKILL.md} +21 -18
  165. package/templates/skills/chrome-devtools/SKILL.md +221 -68
  166. package/templates/skills/chrome-devtools/scripts/README.md +18 -0
  167. package/templates/skills/chrome-devtools/scripts/__tests__/error-handling.test.js +102 -0
  168. package/templates/skills/chrome-devtools/scripts/aria-snapshot.js +2 -1
  169. package/templates/skills/chrome-devtools/scripts/click.js +2 -1
  170. package/templates/skills/chrome-devtools/scripts/connect-chrome.js +146 -0
  171. package/templates/skills/chrome-devtools/scripts/console.js +3 -1
  172. package/templates/skills/chrome-devtools/scripts/evaluate.js +6 -3
  173. package/templates/skills/chrome-devtools/scripts/fill.js +2 -1
  174. package/templates/skills/chrome-devtools/scripts/import-cookies.js +205 -0
  175. package/templates/skills/chrome-devtools/scripts/inject-auth.js +2 -1
  176. package/templates/skills/chrome-devtools/scripts/install-deps.sh +0 -0
  177. package/templates/skills/chrome-devtools/scripts/install.sh +0 -0
  178. package/templates/skills/chrome-devtools/scripts/lib/browser.js +60 -4
  179. package/templates/skills/chrome-devtools/scripts/navigate.js +86 -2
  180. package/templates/skills/chrome-devtools/scripts/network.js +3 -1
  181. package/templates/skills/chrome-devtools/scripts/performance.js +3 -1
  182. package/templates/skills/chrome-devtools/scripts/screenshot.js +2 -1
  183. package/templates/skills/chrome-devtools/scripts/select-ref.js +2 -1
  184. package/templates/skills/chrome-devtools/scripts/snapshot.js +2 -1
  185. package/templates/skills/chrome-devtools/scripts/ws-debug.js +44 -0
  186. package/templates/skills/chrome-devtools/scripts/ws-full-debug.js +107 -0
  187. package/templates/skills/ck-help/SKILL.md +102 -0
  188. package/templates/skills/ck-help/scripts/ck-help.py +1321 -0
  189. package/templates/skills/ck-help/scripts/commands_data.yaml +3 -0
  190. package/templates/skills/ck-help/scripts/skills_data.yaml +593 -0
  191. package/templates/skills/code-review/SKILL.md +97 -93
  192. package/templates/skills/code-review/references/code-review-reception.md +113 -209
  193. package/templates/skills/code-review/references/codebase-scan-workflow.md +29 -0
  194. package/templates/skills/code-review/references/edge-case-scouting.md +119 -0
  195. package/templates/skills/code-review/references/parallel-review-workflow.md +69 -0
  196. package/templates/skills/code-review/references/requesting-code-review.md +115 -104
  197. package/templates/skills/code-review/references/task-management-reviews.md +140 -0
  198. package/templates/skills/code-review/references/verification-before-completion.md +138 -138
  199. package/templates/skills/coding-level/SKILL.md +56 -0
  200. package/templates/skills/common/README.md +120 -0
  201. package/templates/skills/common/api_key_helper.py +411 -0
  202. package/templates/skills/common/api_key_rotator.py +248 -0
  203. package/templates/skills/context-engineering/SKILL.md +108 -0
  204. package/templates/skills/context-engineering/references/context-compression.md +84 -0
  205. package/templates/skills/context-engineering/references/context-degradation.md +93 -0
  206. package/templates/skills/context-engineering/references/context-fundamentals.md +75 -0
  207. package/templates/skills/context-engineering/references/context-optimization.md +82 -0
  208. package/templates/skills/context-engineering/references/evaluation.md +89 -0
  209. package/templates/skills/context-engineering/references/memory-systems.md +88 -0
  210. package/templates/skills/context-engineering/references/multi-agent-patterns.md +90 -0
  211. package/templates/skills/context-engineering/references/project-development.md +97 -0
  212. package/templates/skills/context-engineering/references/runtime-awareness.md +202 -0
  213. package/templates/skills/context-engineering/references/tool-design.md +86 -0
  214. package/templates/skills/context-engineering/scripts/compression_evaluator.py +349 -0
  215. package/templates/skills/context-engineering/scripts/context_analyzer.py +317 -0
  216. package/templates/skills/context-engineering/scripts/tests/test_edge_cases.py +246 -0
  217. package/templates/skills/cook/README.md +86 -0
  218. package/templates/skills/cook/SKILL.md +113 -0
  219. package/templates/skills/cook/references/intent-detection.md +101 -0
  220. package/templates/skills/cook/references/review-cycle.md +75 -0
  221. package/templates/skills/cook/references/subagent-patterns.md +75 -0
  222. package/templates/skills/cook/references/workflow-steps.md +172 -0
  223. package/templates/skills/copywriting/SKILL.md +94 -0
  224. package/templates/skills/copywriting/references/copy-formulas.md +150 -0
  225. package/templates/skills/copywriting/references/cta-patterns.md +168 -0
  226. package/templates/skills/copywriting/references/email-copy.md +193 -0
  227. package/templates/skills/copywriting/references/headline-templates.md +140 -0
  228. package/templates/skills/copywriting/references/landing-page-copy.md +175 -0
  229. package/templates/skills/copywriting/references/power-words.md +189 -0
  230. package/templates/skills/copywriting/references/social-media-copy.md +222 -0
  231. package/templates/skills/copywriting/references/workflow-cro.md +83 -0
  232. package/templates/skills/copywriting/references/workflow-enhance.md +32 -0
  233. package/templates/skills/copywriting/references/workflow-fast.md +29 -0
  234. package/templates/skills/copywriting/references/workflow-good.md +39 -0
  235. package/templates/skills/copywriting/references/writing-styles.md +247 -0
  236. package/templates/skills/copywriting/scripts/extract-writing-styles.py +308 -0
  237. package/templates/skills/copywriting/templates/copy-brief.md +49 -0
  238. package/templates/skills/databases/SKILL.md +7 -155
  239. package/templates/skills/databases/analytics.md +198 -0
  240. package/templates/skills/databases/db-design.md +188 -0
  241. package/templates/skills/databases/incremental-etl.md +213 -0
  242. package/templates/skills/databases/scripts/db_backup.py +0 -0
  243. package/templates/skills/databases/scripts/db_migrate.py +3 -2
  244. package/templates/skills/databases/scripts/db_performance_check.py +3 -2
  245. package/templates/skills/databases/stacks/bigquery.md +231 -0
  246. package/templates/skills/databases/stacks/d1_cloudflare.md +137 -0
  247. package/templates/skills/databases/stacks/mysql.md +216 -0
  248. package/templates/skills/databases/stacks/postgres.md +235 -0
  249. package/templates/skills/databases/stacks/sqlite.md +244 -0
  250. package/templates/skills/databases/transactional.md +176 -0
  251. package/templates/skills/debug/SKILL.md +121 -0
  252. package/templates/skills/debug/references/frontend-verification.md +103 -0
  253. package/templates/skills/debug/references/investigation-methodology.md +101 -0
  254. package/templates/skills/debug/references/log-and-ci-analysis.md +97 -0
  255. package/templates/skills/debug/references/performance-diagnostics.md +113 -0
  256. package/templates/skills/debug/references/reporting-standards.md +122 -0
  257. package/templates/skills/debug/references/task-management-debugging.md +155 -0
  258. package/templates/skills/devops/SKILL.md +65 -253
  259. package/templates/skills/devops/references/kubernetes-basics.md +99 -0
  260. package/templates/skills/devops/references/kubernetes-helm-advanced.md +75 -0
  261. package/templates/skills/devops/references/kubernetes-helm.md +81 -0
  262. package/templates/skills/devops/references/kubernetes-kubectl.md +74 -0
  263. package/templates/skills/devops/references/kubernetes-security-advanced.md +98 -0
  264. package/templates/skills/devops/references/kubernetes-security.md +95 -0
  265. package/templates/skills/devops/references/kubernetes-troubleshooting-advanced.md +74 -0
  266. package/templates/skills/devops/references/kubernetes-troubleshooting.md +49 -0
  267. package/templates/skills/devops/references/kubernetes-workflows-advanced.md +75 -0
  268. package/templates/skills/devops/references/kubernetes-workflows.md +78 -0
  269. package/templates/skills/devops/scripts/cloudflare_deploy.py +0 -0
  270. package/templates/skills/devops/scripts/docker_optimize.py +3 -2
  271. package/templates/skills/docs/SKILL.md +55 -0
  272. package/templates/skills/docs/references/init-workflow.md +32 -0
  273. package/templates/skills/docs/references/summarize-workflow.md +18 -0
  274. package/templates/skills/docs/references/update-workflow.md +59 -0
  275. package/templates/skills/docs-seeker/SKILL.md +3 -2
  276. package/templates/skills/docs-seeker/scripts/analyze-llms-txt.js +0 -0
  277. package/templates/skills/docs-seeker/scripts/detect-topic.js +0 -0
  278. package/templates/skills/docs-seeker/scripts/fetch-docs.js +0 -0
  279. package/templates/skills/docs-seeker/scripts/tests/run-tests.js +0 -0
  280. package/templates/skills/docs-seeker/scripts/tests/test-analyze-llms.js +0 -0
  281. package/templates/skills/docs-seeker/scripts/tests/test-detect-topic.js +0 -0
  282. package/templates/skills/docs-seeker/scripts/tests/test-fetch-docs.js +0 -0
  283. package/templates/skills/docs-seeker/scripts/utils/env-loader.js +0 -0
  284. package/templates/skills/document-skills/docx/SKILL.md +2 -2
  285. package/templates/skills/document-skills/docx/ooxml/scripts/pack.py +0 -0
  286. package/templates/skills/document-skills/docx/ooxml/scripts/unpack.py +0 -0
  287. package/templates/skills/document-skills/docx/ooxml/scripts/validate.py +0 -0
  288. package/templates/skills/document-skills/docx/scripts/document.py +0 -0
  289. package/templates/skills/document-skills/docx/scripts/utilities.py +0 -0
  290. package/templates/skills/document-skills/pdf/SKILL.md +2 -2
  291. package/templates/skills/document-skills/pptx/SKILL.md +2 -2
  292. package/templates/skills/document-skills/pptx/ooxml/scripts/pack.py +0 -0
  293. package/templates/skills/document-skills/pptx/ooxml/scripts/unpack.py +0 -0
  294. package/templates/skills/document-skills/pptx/ooxml/scripts/validate.py +0 -0
  295. package/templates/skills/document-skills/pptx/scripts/inventory.py +0 -0
  296. package/templates/skills/document-skills/pptx/scripts/rearrange.py +0 -0
  297. package/templates/skills/document-skills/pptx/scripts/replace.py +0 -0
  298. package/templates/skills/document-skills/pptx/scripts/thumbnail.py +0 -0
  299. package/templates/skills/document-skills/xlsx/SKILL.md +2 -2
  300. package/templates/skills/document-skills/xlsx/recalc.py +3 -2
  301. package/templates/skills/find-skills/SKILL.md +134 -0
  302. package/templates/skills/fix/SKILL.md +111 -0
  303. package/templates/skills/fix/references/complexity-assessment.md +72 -0
  304. package/templates/skills/fix/references/mode-selection.md +46 -0
  305. package/templates/skills/fix/references/parallel-exploration.md +100 -0
  306. package/templates/skills/fix/references/review-cycle.md +77 -0
  307. package/templates/skills/fix/references/skill-activation-matrix.md +78 -0
  308. package/templates/skills/fix/references/task-orchestration.md +103 -0
  309. package/templates/skills/fix/references/workflow-ci.md +28 -0
  310. package/templates/skills/fix/references/workflow-deep.md +122 -0
  311. package/templates/skills/fix/references/workflow-logs.md +72 -0
  312. package/templates/skills/fix/references/workflow-quick.md +59 -0
  313. package/templates/skills/fix/references/workflow-standard.md +111 -0
  314. package/templates/skills/fix/references/workflow-test.md +75 -0
  315. package/templates/skills/fix/references/workflow-types.md +33 -0
  316. package/templates/skills/fix/references/workflow-ui.md +75 -0
  317. package/templates/skills/frontend-design/SKILL.md +78 -91
  318. package/templates/skills/frontend-design/references/ai-multimodal-overview.md +6 -6
  319. package/templates/skills/frontend-design/references/animejs.md +395 -395
  320. package/templates/skills/frontend-design/references/asset-generation.md +4 -4
  321. package/templates/skills/frontend-design/references/visual-analysis-overview.md +1 -1
  322. package/templates/skills/frontend-design/references/workflow-3d.md +102 -0
  323. package/templates/skills/frontend-design/references/workflow-describe.md +87 -0
  324. package/templates/skills/frontend-design/references/workflow-immersive.md +87 -0
  325. package/templates/skills/frontend-design/references/workflow-quick.md +57 -0
  326. package/templates/skills/frontend-design/references/workflow-screenshot.md +63 -0
  327. package/templates/skills/frontend-design/references/workflow-video.md +74 -0
  328. package/templates/skills/frontend-development/SKILL.md +4 -3
  329. package/templates/skills/git/SKILL.md +114 -0
  330. package/templates/skills/git/references/branch-management.md +88 -0
  331. package/templates/skills/git/references/commit-standards.md +46 -0
  332. package/templates/skills/git/references/gh-cli-guide.md +109 -0
  333. package/templates/skills/git/references/safety-protocols.md +69 -0
  334. package/templates/skills/git/references/workflow-commit.md +58 -0
  335. package/templates/skills/git/references/workflow-merge.md +48 -0
  336. package/templates/skills/git/references/workflow-pr.md +58 -0
  337. package/templates/skills/git/references/workflow-push.md +52 -0
  338. package/templates/skills/gkg/SKILL.md +91 -0
  339. package/templates/skills/gkg/references/cli-commands.md +106 -0
  340. package/templates/skills/gkg/references/http-api.md +102 -0
  341. package/templates/skills/gkg/references/language-support.md +57 -0
  342. package/templates/skills/gkg/references/mcp-tools.md +99 -0
  343. package/templates/skills/google-adk-python/SKILL.md +91 -195
  344. package/templates/skills/google-adk-python/references/agent-types-and-architecture.md +128 -0
  345. package/templates/skills/google-adk-python/references/callbacks-plugins-observability.md +117 -0
  346. package/templates/skills/google-adk-python/references/deployment-cloud-run-vertex-gke.md +138 -0
  347. package/templates/skills/google-adk-python/references/evaluation-testing-cli.md +112 -0
  348. package/templates/skills/google-adk-python/references/multi-agent-and-a2a-protocol.md +145 -0
  349. package/templates/skills/google-adk-python/references/sessions-state-memory-artifacts.md +131 -0
  350. package/templates/skills/google-adk-python/references/tools-and-mcp-integration.md +146 -0
  351. package/templates/skills/install.ps1 +130 -26
  352. package/templates/skills/install.sh +383 -63
  353. package/templates/{commands/journal.md → skills/journal/SKILL.md} +5 -1
  354. package/templates/skills/kanban/SKILL.md +99 -0
  355. package/templates/skills/markdown-novel-viewer/SKILL.md +314 -0
  356. package/templates/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
  357. package/templates/skills/markdown-novel-viewer/assets/favicon.png +0 -0
  358. package/templates/skills/markdown-novel-viewer/assets/novel-theme.css +16 -0
  359. package/templates/skills/markdown-novel-viewer/assets/reader.js +838 -0
  360. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-base.css +54 -0
  361. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-components.css +180 -0
  362. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-content.css +176 -0
  363. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-header.css +217 -0
  364. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-mermaid.css +153 -0
  365. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-overlays.css +202 -0
  366. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-responsive.css +285 -0
  367. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-sidebar.css +359 -0
  368. package/templates/skills/markdown-novel-viewer/assets/styles/novel-theme-variables.css +56 -0
  369. package/templates/skills/markdown-novel-viewer/assets/template.html +149 -0
  370. package/templates/skills/markdown-novel-viewer/bun.lock +38 -0
  371. package/templates/skills/markdown-novel-viewer/package.json +15 -0
  372. package/templates/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
  373. package/templates/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +335 -0
  374. package/templates/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +571 -0
  375. package/templates/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
  376. package/templates/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
  377. package/templates/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
  378. package/templates/skills/markdown-novel-viewer/scripts/tests/server.test.cjs +283 -0
  379. package/templates/skills/markdown-novel-viewer/tests/dashboard-assets.test.cjs +340 -0
  380. package/templates/skills/markdown-novel-viewer/tests/dashboard-renderer.test.cjs +404 -0
  381. package/templates/skills/markdown-novel-viewer/tests/http-server.test.cjs +271 -0
  382. package/templates/skills/markdown-novel-viewer/tests/run-tests.cjs +51 -0
  383. package/templates/skills/markdown-novel-viewer/tests/test-framework.cjs +154 -0
  384. package/templates/skills/markdown-novel-viewer/tests/verify-xss.cjs +90 -0
  385. package/templates/skills/mcp-builder/SKILL.md +3 -2
  386. package/templates/skills/mcp-builder/scripts/evaluation.py +9 -1
  387. package/templates/skills/mcp-management/SKILL.md +8 -7
  388. package/templates/skills/mcp-management/references/gemini-cli-integration.md +16 -10
  389. package/templates/skills/mcp-management/scripts/cli.ts +0 -0
  390. package/templates/skills/mcp-management/scripts/dist/analyze-tools.js +0 -0
  391. package/templates/skills/mcp-management/scripts/dist/cli.js +0 -0
  392. package/templates/skills/mcp-management/scripts/dist/mcp-client.js +0 -0
  393. package/templates/skills/mcp-management/scripts/mcp-client.ts +0 -0
  394. package/templates/skills/media-processing/SKILL.md +3 -2
  395. package/templates/skills/media-processing/scripts/batch-remove-background.sh +0 -0
  396. package/templates/skills/media-processing/scripts/batch_resize.py +0 -0
  397. package/templates/skills/media-processing/scripts/media_convert.py +0 -0
  398. package/templates/skills/media-processing/scripts/remove-background.sh +0 -0
  399. package/templates/skills/media-processing/scripts/remove-bg-node.js +0 -0
  400. package/templates/skills/media-processing/scripts/tests/test_batch_resize.py +0 -0
  401. package/templates/skills/media-processing/scripts/tests/test_media_convert.py +0 -0
  402. package/templates/skills/media-processing/scripts/tests/test_video_optimize.py +0 -0
  403. package/templates/skills/media-processing/scripts/video_optimize.py +0 -0
  404. package/templates/skills/mermaidjs-v11/SKILL.md +116 -0
  405. package/templates/skills/mermaidjs-v11/references/cli-usage.md +228 -0
  406. package/templates/skills/mermaidjs-v11/references/configuration.md +232 -0
  407. package/templates/skills/mermaidjs-v11/references/diagram-types.md +315 -0
  408. package/templates/skills/mermaidjs-v11/references/examples.md +344 -0
  409. package/templates/skills/mermaidjs-v11/references/integration.md +310 -0
  410. package/templates/skills/mintlify/SKILL.md +121 -0
  411. package/templates/skills/mintlify/references/ai-features-and-integrations-reference.md +756 -0
  412. package/templates/skills/mintlify/references/api-documentation-components-reference.md +873 -0
  413. package/templates/skills/mintlify/references/deployment-and-continuous-integration-reference.md +674 -0
  414. package/templates/skills/mintlify/references/docs-json-configuration-reference.md +724 -0
  415. package/templates/skills/mintlify/references/mdx-components-reference.md +551 -0
  416. package/templates/skills/mintlify/references/navigation-structure-and-organization-reference.md +775 -0
  417. package/templates/skills/mobile-development/SKILL.md +3 -2
  418. package/templates/skills/payment-integration/README.md +44 -12
  419. package/templates/skills/payment-integration/SKILL.md +82 -97
  420. package/templates/skills/payment-integration/references/creem/api.md +139 -0
  421. package/templates/skills/payment-integration/references/creem/checkouts.md +99 -0
  422. package/templates/skills/payment-integration/references/creem/licensing.md +136 -0
  423. package/templates/skills/payment-integration/references/creem/overview.md +65 -0
  424. package/templates/skills/payment-integration/references/creem/sdk.md +161 -0
  425. package/templates/skills/payment-integration/references/creem/subscriptions.md +129 -0
  426. package/templates/skills/payment-integration/references/creem/webhooks.md +120 -0
  427. package/templates/skills/payment-integration/references/implementation-workflows.md +43 -0
  428. package/templates/skills/payment-integration/references/multi-provider-order-management-patterns.md +821 -0
  429. package/templates/skills/payment-integration/references/paddle/api.md +116 -0
  430. package/templates/skills/payment-integration/references/paddle/best-practices.md +130 -0
  431. package/templates/skills/payment-integration/references/paddle/overview.md +57 -0
  432. package/templates/skills/payment-integration/references/paddle/paddle-js.md +106 -0
  433. package/templates/skills/payment-integration/references/paddle/sdk.md +131 -0
  434. package/templates/skills/payment-integration/references/paddle/subscriptions.md +118 -0
  435. package/templates/skills/payment-integration/references/paddle/webhooks.md +112 -0
  436. package/templates/skills/payment-integration/references/polar/best-practices.md +781 -361
  437. package/templates/skills/payment-integration/references/sepay/best-practices.md +870 -268
  438. package/templates/skills/payment-integration/references/stripe/stripe-best-practices.md +32 -0
  439. package/templates/skills/payment-integration/references/stripe/stripe-cli.md +148 -0
  440. package/templates/skills/payment-integration/references/stripe/stripe-js.md +116 -0
  441. package/templates/skills/payment-integration/references/stripe/stripe-sdks.md +84 -0
  442. package/templates/skills/payment-integration/references/stripe/stripe-upgrade.md +175 -0
  443. package/templates/skills/payment-integration/scripts/checkout-helper.js +0 -0
  444. package/templates/skills/payment-integration/scripts/polar-webhook-verify.js +0 -0
  445. package/templates/skills/payment-integration/scripts/sepay-webhook-verify.js +0 -0
  446. package/templates/skills/payment-integration/scripts/test-scripts.js +0 -0
  447. package/templates/skills/plan/SKILL.md +137 -0
  448. package/templates/skills/plan/references/archive-workflow.md +53 -0
  449. package/templates/skills/{planning → plan}/references/codebase-understanding.md +1 -1
  450. package/templates/skills/{planning → plan}/references/output-standards.md +15 -1
  451. package/templates/skills/{planning → plan}/references/plan-organization.md +12 -19
  452. package/templates/skills/plan/references/red-team-personas.md +69 -0
  453. package/templates/skills/plan/references/red-team-workflow.md +77 -0
  454. package/templates/skills/{planning → plan}/references/research-phase.md +2 -2
  455. package/templates/skills/plan/references/task-management.md +132 -0
  456. package/templates/skills/plan/references/validate-question-framework.md +80 -0
  457. package/templates/skills/plan/references/validate-workflow.md +65 -0
  458. package/templates/skills/plan/references/workflow-modes.md +145 -0
  459. package/templates/skills/plans-kanban/SKILL.md +167 -0
  460. package/templates/skills/plans-kanban/assets/dashboard-template.html +119 -0
  461. package/templates/skills/plans-kanban/assets/dashboard.css +1594 -0
  462. package/templates/skills/plans-kanban/assets/dashboard.js +596 -0
  463. package/templates/skills/plans-kanban/assets/favicon.png +0 -0
  464. package/templates/skills/plans-kanban/package.json +13 -0
  465. package/templates/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
  466. package/templates/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
  467. package/templates/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
  468. package/templates/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
  469. package/templates/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
  470. package/templates/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
  471. package/templates/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
  472. package/templates/skills/plans-kanban/scripts/server.cjs +260 -0
  473. package/templates/skills/preview/SKILL.md +75 -0
  474. package/templates/skills/preview/references/generation-modes.md +95 -0
  475. package/templates/skills/preview/references/view-mode.md +42 -0
  476. package/templates/skills/problem-solving/SKILL.md +3 -2
  477. package/templates/skills/project-management/SKILL.md +122 -0
  478. package/templates/skills/project-management/references/documentation-triggers.md +60 -0
  479. package/templates/skills/project-management/references/hydration-workflow.md +85 -0
  480. package/templates/skills/project-management/references/progress-tracking.md +96 -0
  481. package/templates/skills/project-management/references/reporting-patterns.md +94 -0
  482. package/templates/skills/project-management/references/task-operations.md +85 -0
  483. package/templates/skills/react-best-practices/AGENTS.md +2249 -0
  484. package/templates/skills/react-best-practices/README.md +123 -0
  485. package/templates/skills/react-best-practices/SKILL.md +122 -0
  486. package/templates/skills/react-best-practices/metadata.json +15 -0
  487. package/templates/skills/react-best-practices/rules/_sections.md +46 -0
  488. package/templates/skills/react-best-practices/rules/_template.md +28 -0
  489. package/templates/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  490. package/templates/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  491. package/templates/skills/react-best-practices/rules/async-api-routes.md +38 -0
  492. package/templates/skills/react-best-practices/rules/async-defer-await.md +80 -0
  493. package/templates/skills/react-best-practices/rules/async-dependencies.md +36 -0
  494. package/templates/skills/react-best-practices/rules/async-parallel.md +28 -0
  495. package/templates/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  496. package/templates/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  497. package/templates/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  498. package/templates/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  499. package/templates/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  500. package/templates/skills/react-best-practices/rules/bundle-preload.md +50 -0
  501. package/templates/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  502. package/templates/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  503. package/templates/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  504. package/templates/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  505. package/templates/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  506. package/templates/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  507. package/templates/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  508. package/templates/skills/react-best-practices/rules/js-early-exit.md +50 -0
  509. package/templates/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  510. package/templates/skills/react-best-practices/rules/js-index-maps.md +37 -0
  511. package/templates/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  512. package/templates/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  513. package/templates/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  514. package/templates/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  515. package/templates/skills/react-best-practices/rules/rendering-activity.md +26 -0
  516. package/templates/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  517. package/templates/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  518. package/templates/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  519. package/templates/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  520. package/templates/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  521. package/templates/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  522. package/templates/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  523. package/templates/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  524. package/templates/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  525. package/templates/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  526. package/templates/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  527. package/templates/skills/react-best-practices/rules/rerender-memo.md +44 -0
  528. package/templates/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  529. package/templates/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  530. package/templates/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  531. package/templates/skills/react-best-practices/rules/server-cache-react.md +26 -0
  532. package/templates/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  533. package/templates/skills/react-best-practices/rules/server-serialization.md +38 -0
  534. package/templates/skills/remotion/SKILL.md +44 -0
  535. package/templates/skills/remotion/rules/3d.md +86 -0
  536. package/templates/skills/remotion/rules/animations.md +29 -0
  537. package/templates/skills/remotion/rules/assets/charts-bar-chart.tsx +173 -0
  538. package/templates/skills/remotion/rules/assets/text-animations-typewriter.tsx +100 -0
  539. package/templates/skills/remotion/rules/assets/text-animations-word-highlight.tsx +108 -0
  540. package/templates/skills/remotion/rules/assets.md +78 -0
  541. package/templates/skills/remotion/rules/audio.md +172 -0
  542. package/templates/skills/remotion/rules/calculate-metadata.md +104 -0
  543. package/templates/skills/remotion/rules/can-decode.md +75 -0
  544. package/templates/skills/remotion/rules/charts.md +58 -0
  545. package/templates/skills/remotion/rules/compositions.md +146 -0
  546. package/templates/skills/remotion/rules/display-captions.md +126 -0
  547. package/templates/skills/remotion/rules/extract-frames.md +229 -0
  548. package/templates/skills/remotion/rules/fonts.md +152 -0
  549. package/templates/skills/remotion/rules/get-audio-duration.md +58 -0
  550. package/templates/skills/remotion/rules/get-video-dimensions.md +68 -0
  551. package/templates/skills/remotion/rules/get-video-duration.md +58 -0
  552. package/templates/skills/remotion/rules/gifs.md +138 -0
  553. package/templates/skills/remotion/rules/images.md +130 -0
  554. package/templates/skills/remotion/rules/import-srt-captions.md +67 -0
  555. package/templates/skills/remotion/rules/lottie.md +68 -0
  556. package/templates/skills/remotion/rules/measuring-dom-nodes.md +35 -0
  557. package/templates/skills/remotion/rules/measuring-text.md +143 -0
  558. package/templates/skills/remotion/rules/sequencing.md +106 -0
  559. package/templates/skills/remotion/rules/tailwind.md +11 -0
  560. package/templates/skills/remotion/rules/text-animations.md +20 -0
  561. package/templates/skills/remotion/rules/timing.md +179 -0
  562. package/templates/skills/remotion/rules/transcribe-captions.md +19 -0
  563. package/templates/skills/remotion/rules/transitions.md +122 -0
  564. package/templates/skills/remotion/rules/trimming.md +53 -0
  565. package/templates/skills/remotion/rules/videos.md +171 -0
  566. package/templates/skills/repomix/SKILL.md +3 -2
  567. package/templates/skills/repomix/scripts/repomix_batch.py +0 -0
  568. package/templates/skills/research/SKILL.md +9 -6
  569. package/templates/skills/scout/SKILL.md +89 -0
  570. package/templates/skills/scout/references/external-scouting.md +140 -0
  571. package/templates/skills/scout/references/internal-scouting.md +119 -0
  572. package/templates/skills/scout/references/task-management-scouting.md +125 -0
  573. package/templates/skills/sequential-thinking/SKILL.md +3 -2
  574. package/templates/skills/sequential-thinking/scripts/format-thought.js +0 -0
  575. package/templates/skills/sequential-thinking/scripts/process-thought.js +0 -0
  576. package/templates/skills/shader/SKILL.md +113 -0
  577. package/templates/skills/shader/references/glsl-cellular-voronoi-worley-noise-patterns.md +142 -0
  578. package/templates/skills/shader/references/glsl-colors-rgb-hsb-gradients-mixing-color-spaces.md +143 -0
  579. package/templates/skills/shader/references/glsl-fbm-fractional-brownian-motion-turbulence-octaves.md +146 -0
  580. package/templates/skills/shader/references/glsl-fundamentals-data-types-vectors-precision-coordinates.md +104 -0
  581. package/templates/skills/shader/references/glsl-noise-random-perlin-simplex-cellular-voronoi.md +115 -0
  582. package/templates/skills/shader/references/glsl-pattern-symmetry-truchet-domain-warping.md +134 -0
  583. package/templates/skills/shader/references/glsl-patterns-tiling-fract-matrices-transformations.md +133 -0
  584. package/templates/skills/shader/references/glsl-procedural-textures-clouds-marble-wood-terrain.md +144 -0
  585. package/templates/skills/shader/references/glsl-shader-builtin-functions-complete-api-reference.md +112 -0
  586. package/templates/skills/shader/references/glsl-shapes-polygon-star-polar-sdf-combinations.md +124 -0
  587. package/templates/skills/shader/references/glsl-shapes-sdf-circles-rectangles-polar-distance-fields.md +106 -0
  588. package/templates/skills/shader/references/glsl-shaping-functions-step-smoothstep-curves-interpolation.md +141 -0
  589. package/templates/skills/shopify/SKILL.md +3 -2
  590. package/templates/skills/shopify/scripts/shopify_init.py +5 -5
  591. package/templates/skills/skill-creator/SKILL.md +91 -238
  592. package/templates/skills/skill-creator/references/benchmark-optimization-guide.md +86 -0
  593. package/templates/skills/skill-creator/references/distribution-guide.md +79 -0
  594. package/templates/skills/skill-creator/references/mcp-skills-integration.md +71 -0
  595. package/templates/skills/skill-creator/references/metadata-quality-criteria.md +76 -0
  596. package/templates/skills/skill-creator/references/plugin-marketplace-hosting.md +104 -0
  597. package/templates/skills/skill-creator/references/plugin-marketplace-overview.md +89 -0
  598. package/templates/skills/skill-creator/references/plugin-marketplace-schema.md +93 -0
  599. package/templates/skills/skill-creator/references/plugin-marketplace-sources.md +103 -0
  600. package/templates/skills/skill-creator/references/plugin-marketplace-troubleshooting.md +76 -0
  601. package/templates/skills/skill-creator/references/script-quality-criteria.md +106 -0
  602. package/templates/skills/skill-creator/references/skill-anatomy-and-requirements.md +76 -0
  603. package/templates/skills/skill-creator/references/skill-creation-workflow.md +95 -0
  604. package/templates/skills/skill-creator/references/skill-design-patterns.md +75 -0
  605. package/templates/skills/skill-creator/references/skillmark-benchmark-criteria.md +102 -0
  606. package/templates/skills/skill-creator/references/structure-organization-criteria.md +114 -0
  607. package/templates/skills/skill-creator/references/testing-and-iteration.md +78 -0
  608. package/templates/skills/skill-creator/references/token-efficiency-criteria.md +74 -0
  609. package/templates/skills/skill-creator/references/troubleshooting-guide.md +80 -0
  610. package/templates/skills/skill-creator/references/validation-checklist.md +83 -0
  611. package/templates/skills/skill-creator/references/writing-effective-instructions.md +88 -0
  612. package/templates/skills/skill-creator/references/yaml-frontmatter-reference.md +91 -0
  613. package/templates/skills/skill-creator/scripts/debug.zip +0 -0
  614. package/templates/skills/skill-creator/scripts/encoding_utils.py +36 -0
  615. package/templates/skills/skill-creator/scripts/init_skill.py +9 -4
  616. package/templates/skills/skill-creator/scripts/package_skill.py +5 -0
  617. package/templates/skills/skill-creator/scripts/quick_validate.py +6 -2
  618. package/templates/skills/tanstack/SKILL.md +141 -0
  619. package/templates/skills/tanstack/references/tanstack-ai.md +97 -0
  620. package/templates/skills/tanstack/references/tanstack-form.md +125 -0
  621. package/templates/skills/tanstack/references/tanstack-start.md +100 -0
  622. package/templates/skills/team/SKILL.md +285 -0
  623. package/templates/skills/team/references/agent-teams-controls-and-modes.md +107 -0
  624. package/templates/skills/team/references/agent-teams-examples-and-best-practices.md +182 -0
  625. package/templates/skills/team/references/agent-teams-official-docs.md +175 -0
  626. package/templates/skills/template-skill/SKILL.md +1 -1
  627. package/templates/skills/test/SKILL.md +109 -0
  628. package/templates/skills/test/references/report-format.md +58 -0
  629. package/templates/skills/test/references/test-execution-workflow.md +103 -0
  630. package/templates/skills/test/references/ui-testing-workflow.md +65 -0
  631. package/templates/skills/threejs/SKILL.md +106 -53
  632. package/templates/skills/threejs/data/api-reference.csv +61 -0
  633. package/templates/skills/threejs/data/categories.csv +14 -0
  634. package/templates/skills/threejs/data/examples-all.csv +557 -0
  635. package/templates/skills/threejs/data/use-cases.csv +21 -0
  636. package/templates/skills/threejs/references/00-fundamentals.md +487 -0
  637. package/templates/skills/threejs/references/11-materials-advanced.md +1 -1
  638. package/templates/skills/threejs/references/11-materials.md +519 -0
  639. package/templates/skills/threejs/references/17-shader.md +641 -0
  640. package/templates/skills/threejs/references/18-geometry.md +547 -0
  641. package/templates/skills/threejs/scripts/core.py +236 -0
  642. package/templates/skills/threejs/scripts/extract_examples.py +688 -0
  643. package/templates/skills/threejs/scripts/generate_csv_from_json.py +135 -0
  644. package/templates/skills/threejs/scripts/search.py +77 -0
  645. package/templates/skills/ui-styling/SKILL.md +3 -2
  646. package/templates/skills/ui-styling/scripts/shadcn_add.py +0 -0
  647. package/templates/skills/ui-styling/scripts/tailwind_config_gen.py +1 -1
  648. package/templates/skills/ui-ux-pro-max/SKILL.md +69 -32
  649. package/templates/skills/ui-ux-pro-max/data/charts.csv +25 -25
  650. package/templates/skills/ui-ux-pro-max/data/colors.csv +96 -96
  651. package/templates/skills/ui-ux-pro-max/data/landing.csv +30 -30
  652. package/templates/skills/ui-ux-pro-max/data/products.csv +96 -96
  653. package/templates/skills/ui-ux-pro-max/data/prompts.csv +20 -20
  654. package/templates/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
  655. package/templates/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
  656. package/templates/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
  657. package/templates/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  658. package/templates/skills/ui-ux-pro-max/data/stacks/react.csv +54 -54
  659. package/templates/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
  660. package/templates/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
  661. package/templates/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -50
  662. package/templates/skills/ui-ux-pro-max/data/styles.csv +58 -58
  663. package/templates/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  664. package/templates/skills/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
  665. package/templates/skills/ui-ux-pro-max/scripts/design_system.py +494 -0
  666. package/templates/skills/ui-ux-pro-max/scripts/search.py +84 -61
  667. package/templates/skills/use-mcp/SKILL.md +42 -0
  668. package/templates/skills/watzup/SKILL.md +12 -0
  669. package/templates/skills/web-design-guidelines/SKILL.md +36 -0
  670. package/templates/skills/web-frameworks/SKILL.md +4 -3
  671. package/templates/skills/web-frameworks/scripts/nextjs_init.py +13 -13
  672. package/templates/skills/web-frameworks/scripts/turborepo_migrate.py +0 -0
  673. package/templates/skills/web-testing/SKILL.md +97 -0
  674. package/templates/skills/web-testing/references/accessibility-testing.md +84 -0
  675. package/templates/skills/web-testing/references/api-testing.md +78 -0
  676. package/templates/skills/web-testing/references/ci-cd-testing-workflows.md +121 -0
  677. package/templates/skills/web-testing/references/component-testing.md +94 -0
  678. package/templates/skills/web-testing/references/contract-testing.md +146 -0
  679. package/templates/skills/web-testing/references/cross-browser-checklist.md +72 -0
  680. package/templates/skills/web-testing/references/database-testing.md +139 -0
  681. package/templates/skills/web-testing/references/e2e-testing-playwright.md +119 -0
  682. package/templates/skills/web-testing/references/functional-testing-checklist.md +88 -0
  683. package/templates/skills/web-testing/references/interactive-testing-patterns.md +89 -0
  684. package/templates/skills/web-testing/references/load-testing-k6.md +93 -0
  685. package/templates/skills/web-testing/references/mobile-gesture-testing.md +85 -0
  686. package/templates/skills/web-testing/references/performance-core-web-vitals.md +124 -0
  687. package/templates/skills/web-testing/references/playwright-component-testing.md +115 -0
  688. package/templates/skills/web-testing/references/pre-release-checklist.md +75 -0
  689. package/templates/skills/web-testing/references/security-checklists.md +81 -0
  690. package/templates/skills/web-testing/references/security-testing-overview.md +92 -0
  691. package/templates/skills/web-testing/references/shadow-dom-testing.md +70 -0
  692. package/templates/skills/web-testing/references/test-data-management.md +131 -0
  693. package/templates/skills/web-testing/references/test-flakiness-mitigation.md +86 -0
  694. package/templates/skills/web-testing/references/testing-pyramid-strategy.md +76 -0
  695. package/templates/skills/web-testing/references/unit-integration-testing.md +138 -0
  696. package/templates/skills/web-testing/references/visual-regression.md +92 -0
  697. package/templates/skills/web-testing/references/vulnerability-payloads.md +93 -0
  698. package/templates/skills/web-testing/scripts/analyze-test-results.js +280 -0
  699. package/templates/skills/web-testing/scripts/init-playwright.js +233 -0
  700. package/templates/skills/worktree/SKILL.md +96 -0
  701. package/templates/skills/worktree/scripts/worktree.cjs +916 -0
  702. package/templates/skills/worktree/scripts/worktree.test.cjs +792 -0
  703. package/templates/statusline.cjs +477 -244
  704. package/templates/statusline.ps1 +0 -1
  705. package/templates/statusline.sh +0 -1
  706. package/templates/agents/README.md +0 -172
  707. package/templates/agents/copywriter.md +0 -113
  708. package/templates/agents/database-admin.md +0 -97
  709. package/templates/agents/scout-external.md +0 -146
  710. package/templates/agents/scout.md +0 -260
  711. package/templates/commands/README.md +0 -251
  712. package/templates/commands/bootstrap/auto/fast.md +0 -111
  713. package/templates/commands/bootstrap/auto/parallel.md +0 -66
  714. package/templates/commands/bootstrap/auto.md +0 -115
  715. package/templates/commands/bootstrap.md +0 -137
  716. package/templates/commands/build.md +0 -39
  717. package/templates/commands/checkpoint.md +0 -156
  718. package/templates/commands/code/auto.md +0 -170
  719. package/templates/commands/code/no-test.md +0 -158
  720. package/templates/commands/code/parallel.md +0 -55
  721. package/templates/commands/code-simplifier.md +0 -71
  722. package/templates/commands/code.md +0 -176
  723. package/templates/commands/compact.md +0 -57
  724. package/templates/commands/content/cro.md +0 -43
  725. package/templates/commands/content/enhance.md +0 -14
  726. package/templates/commands/content/fast.md +0 -13
  727. package/templates/commands/content/good.md +0 -16
  728. package/templates/commands/context.md +0 -48
  729. package/templates/commands/cook/auto/fast.md +0 -26
  730. package/templates/commands/cook/auto/parallel.md +0 -49
  731. package/templates/commands/cook/auto.md +0 -15
  732. package/templates/commands/cook/fast.md +0 -47
  733. package/templates/commands/cook/hard.md +0 -80
  734. package/templates/commands/cook/parallel.md +0 -90
  735. package/templates/commands/cook.md +0 -105
  736. package/templates/commands/create-feature.md +0 -48
  737. package/templates/commands/db-migrate.md +0 -52
  738. package/templates/commands/debug.md +0 -13
  739. package/templates/commands/design/3d.md +0 -83
  740. package/templates/commands/design/describe.md +0 -23
  741. package/templates/commands/design/fast.md +0 -31
  742. package/templates/commands/design/good.md +0 -35
  743. package/templates/commands/design/screenshot.md +0 -34
  744. package/templates/commands/design/video.md +0 -34
  745. package/templates/commands/docs/init.md +0 -39
  746. package/templates/commands/docs/summarize.md +0 -31
  747. package/templates/commands/docs/update.md +0 -57
  748. package/templates/commands/feature.md +0 -62
  749. package/templates/commands/fix/ci.md +0 -17
  750. package/templates/commands/fix/fast.md +0 -19
  751. package/templates/commands/fix/hard.md +0 -39
  752. package/templates/commands/fix/logs.md +0 -26
  753. package/templates/commands/fix/parallel.md +0 -54
  754. package/templates/commands/fix/test.md +0 -20
  755. package/templates/commands/fix/types.md +0 -9
  756. package/templates/commands/fix/ui.md +0 -48
  757. package/templates/commands/fix-issue.md +0 -177
  758. package/templates/commands/fix.md +0 -43
  759. package/templates/commands/generate-dto.md +0 -67
  760. package/templates/commands/git/cm.md +0 -5
  761. package/templates/commands/git/cp.md +0 -4
  762. package/templates/commands/git/merge.md +0 -40
  763. package/templates/commands/git/pr.md +0 -48
  764. package/templates/commands/integrate/polar.md +0 -28
  765. package/templates/commands/integrate/sepay.md +0 -28
  766. package/templates/commands/investigate.md +0 -324
  767. package/templates/commands/lint.md +0 -47
  768. package/templates/commands/migration.md +0 -111
  769. package/templates/commands/performance.md +0 -110
  770. package/templates/commands/plan/ci.md +0 -33
  771. package/templates/commands/plan/cro.md +0 -69
  772. package/templates/commands/plan/fast.md +0 -86
  773. package/templates/commands/plan/hard.md +0 -103
  774. package/templates/commands/plan/parallel.md +0 -152
  775. package/templates/commands/plan/preview.md +0 -40
  776. package/templates/commands/plan/two.md +0 -52
  777. package/templates/commands/plan/validate.md +0 -132
  778. package/templates/commands/plan.md +0 -36
  779. package/templates/commands/pr.md +0 -49
  780. package/templates/commands/preview.md +0 -87
  781. package/templates/commands/release-notes.md +0 -144
  782. package/templates/commands/review/post-task.md +0 -157
  783. package/templates/commands/review-changes.md +0 -46
  784. package/templates/commands/review.md +0 -56
  785. package/templates/commands/scout/ext.md +0 -35
  786. package/templates/commands/scout.md +0 -283
  787. package/templates/commands/security.md +0 -119
  788. package/templates/commands/skill/add.md +0 -36
  789. package/templates/commands/skill/create.md +0 -29
  790. package/templates/commands/skill/fix-logs.md +0 -22
  791. package/templates/commands/skill/optimize/auto.md +0 -25
  792. package/templates/commands/skill/optimize.md +0 -34
  793. package/templates/commands/skill/plan.md +0 -45
  794. package/templates/commands/worktree.md +0 -126
  795. package/templates/hooks/.python-cache.json +0 -1
  796. package/templates/hooks/README.md +0 -246
  797. package/templates/hooks/backend-csharp-context.cjs +0 -223
  798. package/templates/hooks/design-system-context.cjs +0 -185
  799. package/templates/hooks/frontend-typescript-context.cjs +0 -233
  800. package/templates/hooks/lib/ck-paths.cjs +0 -110
  801. package/templates/hooks/lib/context-tracker.cjs +0 -335
  802. package/templates/hooks/notify-waiting.js +0 -117
  803. package/templates/hooks/post-edit-prettier.cjs +0 -189
  804. package/templates/hooks/post-task-review.cjs +0 -142
  805. package/templates/hooks/scss-styling-context.cjs +0 -213
  806. package/templates/hooks/session-end.cjs +0 -35
  807. package/templates/hooks/tests/test-context-tracker.cjs +0 -454
  808. package/templates/hooks/tests/test-scout-block.js +0 -163
  809. package/templates/hooks/workflow-router.cjs +0 -326
  810. package/templates/hooks/write-compact-marker.cjs +0 -159
  811. package/templates/memory/session-log.md +0 -186
  812. package/templates/router/README.md +0 -294
  813. package/templates/router/agents-guide.md +0 -38
  814. package/templates/router/commands-guide.md +0 -122
  815. package/templates/router/decision-flow.md +0 -92
  816. package/templates/router/skills-guide.md +0 -127
  817. package/templates/router/workflows-guide.md +0 -68
  818. package/templates/scripts/__pycache__/win_compat.cpython-312.pyc +0 -0
  819. package/templates/scripts/plan-preview.cjs +0 -921
  820. package/templates/skills/arch-cross-service-integration/SKILL.md +0 -48
  821. package/templates/skills/arch-performance-optimization/SKILL.md +0 -306
  822. package/templates/skills/arch-security-review/SKILL.md +0 -344
  823. package/templates/skills/branch-comparison/SKILL.md +0 -150
  824. package/templates/skills/bug-diagnosis/SKILL.md +0 -309
  825. package/templates/skills/claude-code/references/advanced-features.md +0 -399
  826. package/templates/skills/claude-code/references/agent-skills.md +0 -399
  827. package/templates/skills/claude-code/references/api-reference.md +0 -498
  828. package/templates/skills/claude-code/references/best-practices.md +0 -447
  829. package/templates/skills/claude-code/references/cicd-integration.md +0 -428
  830. package/templates/skills/claude-code/references/common-workflows.md +0 -119
  831. package/templates/skills/claude-code/references/configuration.md +0 -480
  832. package/templates/skills/claude-code/references/enterprise-features.md +0 -472
  833. package/templates/skills/claude-code/references/getting-started.md +0 -252
  834. package/templates/skills/claude-code/references/hooks-and-plugins.md +0 -444
  835. package/templates/skills/claude-code/references/hooks-comprehensive.md +0 -622
  836. package/templates/skills/claude-code/references/ide-integration.md +0 -316
  837. package/templates/skills/claude-code/references/mcp-integration.md +0 -386
  838. package/templates/skills/claude-code/references/slash-commands.md +0 -489
  839. package/templates/skills/claude-code/references/troubleshooting.md +0 -456
  840. package/templates/skills/claude-code/skill.md +0 -60
  841. package/templates/skills/debugging/SKILL.md +0 -84
  842. package/templates/skills/developer-growth-analysis/SKILL.md +0 -322
  843. package/templates/skills/documentation/SKILL.md +0 -134
  844. package/templates/skills/domain-name-brainstormer/SKILL.md +0 -212
  845. package/templates/skills/dual-pass-review/SKILL.md +0 -249
  846. package/templates/skills/feature-docs/SKILL.md +0 -294
  847. package/templates/skills/feature-implementation/SKILL.md +0 -262
  848. package/templates/skills/feature-investigation/SKILL.md +0 -346
  849. package/templates/skills/frontend-design-pro/SKILL.md +0 -58
  850. package/templates/skills/package-upgrade/SKILL.md +0 -189
  851. package/templates/skills/plan-analysis/SKILL.md +0 -191
  852. package/templates/skills/planning/SKILL.md +0 -115
  853. package/templates/skills/planning-with-files/SKILL.md +0 -160
  854. package/templates/skills/planning-with-files/examples.md +0 -202
  855. package/templates/skills/planning-with-files/reference.md +0 -110
  856. package/templates/skills/project-index/SKILL.md +0 -97
  857. package/templates/skills/project-index/scripts/scan-structure.js +0 -417
  858. package/templates/skills/project-index/scripts/scan_structure.py +0 -450
  859. package/templates/skills/readme-improvement/SKILL.md +0 -177
  860. package/templates/skills/skill-share/SKILL.md +0 -80
  861. package/templates/skills/tasks-code-review/SKILL.md +0 -298
  862. package/templates/skills/tasks-documentation/SKILL.md +0 -328
  863. package/templates/skills/tasks-spec-update/SKILL.md +0 -318
  864. package/templates/skills/tasks-test-generation/SKILL.md +0 -433
  865. package/templates/skills/test-generation/SKILL.md +0 -203
  866. package/templates/skills/webapp-testing/LICENSE.txt +0 -202
  867. package/templates/skills/webapp-testing/SKILL.md +0 -96
  868. package/templates/skills/webapp-testing/examples/console_logging.py +0 -35
  869. package/templates/skills/webapp-testing/examples/element_discovery.py +0 -40
  870. package/templates/skills/webapp-testing/examples/static_html_automation.py +0 -33
  871. package/templates/skills/webapp-testing/scripts/with_server.py +0 -106
  872. package/templates/workflows/README.md +0 -241
  873. package/templates/workflows/orchestration-protocol.md +0 -16
  874. /package/templates/{commands → command-archive}/coding-level.md +0 -0
  875. /package/templates/{commands → command-archive}/review/codebase.md +0 -0
  876. /package/templates/{commands → command-archive}/test.md +0 -0
  877. /package/templates/{commands → command-archive}/watzup.md +0 -0
  878. /package/templates/hooks/scout-block/vendor/{ignore.js → ignore.cjs} +0 -0
  879. /package/templates/{workflows → rules}/documentation-management.md +0 -0
  880. /package/templates/skills/{debugging → debug}/references/defense-in-depth.md +0 -0
  881. /package/templates/skills/{debugging → debug}/references/root-cause-tracing.md +0 -0
  882. /package/templates/skills/{debugging → debug}/references/systematic-debugging.md +0 -0
  883. /package/templates/skills/{debugging → debug}/references/verification.md +0 -0
  884. /package/templates/skills/{debugging → debug}/scripts/find-polluter.sh +0 -0
  885. /package/templates/skills/{debugging → debug}/scripts/find-polluter.test.md +0 -0
  886. /package/templates/skills/{planning → plan}/references/solution-design.md +0 -0
@@ -1,337 +1,939 @@
1
1
  # SePay Best Practices
2
2
 
3
- Security, patterns, and monitoring for production SePay integrations.
3
+ Production-proven patterns for Vietnamese bank transfer payments via SePay/VietQR, covering transaction parsing, webhook handling, order matching, currency conversion, and error handling.
4
4
 
5
- ## Security
5
+ ## Environment Configuration
6
6
 
7
- ### Credential Management
8
- ```javascript
9
- // Good: Environment variables
10
- const client = new SePayClient({
11
- merchant_id: process.env.SEPAY_MERCHANT_ID,
12
- secret_key: process.env.SEPAY_SECRET_KEY,
13
- env: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox'
14
- });
7
+ ### Required Environment Variables
8
+ ```bash
9
+ # Core API
10
+ SEPAY_API_TOKEN=xxx # Bearer token for SePay API
11
+ SEPAY_WEBHOOK_API_KEY=xxx # API key for webhook authentication
12
+ SEPAY_API_URL=https://my.sepay.vn/userapi # Base URL (optional)
13
+
14
+ # Bank Account Details
15
+ SEPAY_ACCOUNT_NUMBER=0123456789 # Bank account for transfers
16
+ SEPAY_ACCOUNT_NAME=COMPANY_NAME # Account holder name
17
+ SEPAY_BANK_NAME=Vietcombank # Bank name (VietQR recognized)
18
+ ```
19
+
20
+ ### Product Pricing in VND
21
+ ```typescript
22
+ // lib/sepay.ts
23
+ const VND_PRICES = {
24
+ engineer_kit: 2450000, // ~$100 USD
25
+ marketing_kit: 2450000, // ~$100 USD
26
+ combo: 3650000, // ~$149 USD
27
+ } as const;
28
+
29
+ const USD_TO_VND_RATE = 24500; // 1 USD ≈ 24,500 VND
30
+ ```
31
+
32
+ ## Transaction Content Format
33
+
34
+ ### Standard Format
35
+ ```
36
+ CLAUDEKIT {order-uuid}
37
+ ```
38
+ Example: `CLAUDEKIT 4e4635f4-0478-4080-a5c5-48da91f97f1e`
39
+
40
+ ### Team Checkout Format
41
+ ```
42
+ TEAM{8-hex-chars}
43
+ ```
44
+ Example: `TEAM4E4635F4`
45
+
46
+ ### Why These Formats
47
+ - UUID ensures global uniqueness
48
+ - `CLAUDEKIT` prefix for easy visual identification
49
+ - Short team prefix fits bank memo limits
50
+ - Case-insensitive matching handles bank transformations
51
+
52
+ ## QR Code Generation
53
+
54
+ ### VietQR URL Pattern
55
+ ```typescript
56
+ // lib/sepay.ts
57
+ export function generateVietQRUrl(
58
+ accountNumber: string,
59
+ bankName: string,
60
+ amount: number,
61
+ content: string
62
+ ): string {
63
+ const params = new URLSearchParams({
64
+ acc: accountNumber,
65
+ bank: bankName,
66
+ amount: String(Math.floor(amount)), // Integer only
67
+ des: content,
68
+ });
69
+
70
+ return `https://qr.sepay.vn/img?${params.toString()}`;
71
+ }
72
+ ```
73
+
74
+ ### Usage Example
75
+ ```typescript
76
+ const qrUrl = generateVietQRUrl(
77
+ process.env.SEPAY_ACCOUNT_NUMBER!,
78
+ process.env.SEPAY_BANK_NAME!,
79
+ 2450000,
80
+ `CLAUDEKIT ${orderId}`
81
+ );
82
+ // Returns: https://qr.sepay.vn/img?acc=0123456789&bank=Vietcombank&amount=2450000&des=CLAUDEKIT+uuid
83
+ ```
15
84
 
16
- // Bad: Hardcoded credentials
17
- const client = new SePayClient({
18
- merchant_id: 'SP-TEST-12345',
19
- secret_key: 'spsk_test_xxxxxxx'
85
+ ## Checkout API Implementation
86
+
87
+ ### Standard SePay Checkout
88
+ ```typescript
89
+ // app/api/checkout/sepay/route.ts
90
+ import { NextResponse } from 'next/server';
91
+ import { z } from 'zod';
92
+
93
+ const checkoutSchema = z.object({
94
+ email: z.string().email(),
95
+ name: z.string().optional(),
96
+ productType: z.enum(['engineer_kit', 'marketing_kit', 'combo']),
97
+ githubUsername: z.string().min(1),
98
+ couponCode: z.string().optional(),
99
+ vatInvoiceRequested: z.boolean().optional(),
100
+ taxId: z.string().regex(/^\d{10}$|^\d{13}$/).optional(), // 10 or 13 digits
20
101
  });
102
+
103
+ export async function POST(request: Request) {
104
+ try {
105
+ const body = await request.json();
106
+ const data = checkoutSchema.parse(body);
107
+
108
+ // 1. Normalize email
109
+ const normalizedEmail = data.email.toLowerCase().trim();
110
+
111
+ // 2. Get base price
112
+ const originalAmount = VND_PRICES[data.productType];
113
+ let finalAmount = originalAmount;
114
+ let discountMetadata: Record<string, any> = { originalAmount };
115
+
116
+ // 3. CRITICAL: Apply discounts in correct order
117
+ // Step A: Apply coupon FIRST
118
+ if (data.couponCode) {
119
+ const couponResult = await validateCouponForVND(data.couponCode, originalAmount);
120
+ if (couponResult.valid) {
121
+ finalAmount = originalAmount - couponResult.discountAmountVND;
122
+ discountMetadata.couponCode = data.couponCode;
123
+ discountMetadata.couponDiscountAmount = couponResult.discountAmountVND;
124
+ discountMetadata.couponId = couponResult.couponId;
125
+ }
126
+ }
127
+
128
+ // Step B: Apply referral SECOND (on post-coupon amount)
129
+ const referralCode = getReferralCodeFromCookie(request);
130
+ if (referralCode) {
131
+ const referralResult = await calculateReferralDiscountVND(
132
+ referralCode,
133
+ finalAmount, // Post-coupon amount
134
+ normalizedEmail
135
+ );
136
+ if (referralResult.valid && referralResult.discountAmount > 0) {
137
+ // Validate calculation
138
+ if (referralResult.discountAmount <= 0) {
139
+ return NextResponse.json(
140
+ { error: 'Invalid discount calculation' },
141
+ { status: 400 }
142
+ );
143
+ }
144
+ finalAmount -= referralResult.discountAmount;
145
+ discountMetadata.referralCode = referralCode;
146
+ discountMetadata.referralDiscountAmount = referralResult.discountAmount;
147
+ discountMetadata.referrerId = referralResult.referrerId;
148
+ }
149
+ }
150
+
151
+ // 4. Validate final amount
152
+ if (finalAmount <= 0) {
153
+ return NextResponse.json(
154
+ { error: 'Invalid final amount' },
155
+ { status: 400 }
156
+ );
157
+ }
158
+
159
+ // 5. Encrypt sensitive data if VAT invoice requested
160
+ let encryptedTaxId: string | null = null;
161
+ if (data.vatInvoiceRequested && data.taxId) {
162
+ encryptedTaxId = await encrypt(data.taxId);
163
+ }
164
+
165
+ // 6. Create order record
166
+ const orderId = crypto.randomUUID();
167
+ const transactionContent = `CLAUDEKIT ${orderId}`;
168
+
169
+ const order = await db.insert(orders).values({
170
+ id: orderId,
171
+ email: normalizedEmail,
172
+ productType: data.productType,
173
+ amount: finalAmount,
174
+ currency: 'VND',
175
+ status: 'pending',
176
+ paymentProvider: 'sepay',
177
+ paymentId: transactionContent, // Used for matching
178
+ referredBy: discountMetadata.referrerId,
179
+ discountAmount: originalAmount - finalAmount,
180
+ metadata: JSON.stringify({
181
+ ...discountMetadata,
182
+ githubUsername: data.githubUsername,
183
+ vatInvoiceRequested: data.vatInvoiceRequested,
184
+ encryptedTaxId,
185
+ }),
186
+ }).returning();
187
+
188
+ // 7. Generate payment instructions
189
+ const qrCode = generateVietQRUrl(
190
+ process.env.SEPAY_ACCOUNT_NUMBER!,
191
+ process.env.SEPAY_BANK_NAME!,
192
+ finalAmount,
193
+ transactionContent
194
+ );
195
+
196
+ return NextResponse.json({
197
+ orderId: order[0].id,
198
+ paymentMethod: 'bank_transfer',
199
+ payment: {
200
+ bankName: process.env.SEPAY_BANK_NAME,
201
+ accountNumber: process.env.SEPAY_ACCOUNT_NUMBER,
202
+ accountName: process.env.SEPAY_ACCOUNT_NAME,
203
+ amount: finalAmount,
204
+ currency: 'VND',
205
+ content: transactionContent,
206
+ qrCode,
207
+ instructions: [
208
+ 'Open your banking app',
209
+ 'Scan the QR code or transfer manually',
210
+ 'Use the exact transfer content shown',
211
+ 'Payment will be confirmed automatically',
212
+ ],
213
+ },
214
+ statusCheckUrl: `/api/orders/${order[0].id}/status`,
215
+ });
216
+
217
+ } catch (error) {
218
+ if (error instanceof z.ZodError) {
219
+ return NextResponse.json({ error: error.errors }, { status: 400 });
220
+ }
221
+ console.error('SePay checkout error:', error);
222
+ return NextResponse.json(
223
+ { error: 'Failed to create checkout' },
224
+ { status: 500 }
225
+ );
226
+ }
227
+ }
21
228
  ```
22
229
 
23
- ### Webhook Security
24
- 1. **IP Whitelisting:** Restrict endpoint to SePay IPs
25
- 2. **API Key Verification:** Validate authorization header
26
- 3. **HTTPS Only:** Never accept HTTP webhooks
27
- 4. **Validate Payload:** Check all required fields exist
28
- 5. **Duplicate Detection:** Use transaction ID for deduplication
29
-
30
- ### Transaction Verification
31
- ```javascript
32
- // Always verify payment status via API, don't trust only redirects
33
- app.get('/payment/success', async (req, res) => {
34
- const orderId = req.query.order_id;
35
-
36
- // Verify via API call
37
- const order = await sePayClient.order.retrieve(orderId);
38
-
39
- if (order.status === 'completed') {
40
- await updateOrderStatus(orderId, 'paid');
41
- res.redirect(`/order/${orderId}/confirmation`);
230
+ ## Webhook Handling
231
+
232
+ ### Webhook Authentication (Timing-Safe)
233
+ ```typescript
234
+ // app/api/webhooks/sepay/route.ts
235
+ import { timingSafeEqual } from 'crypto';
236
+ import { NextResponse } from 'next/server';
237
+
238
+ function verifyWebhookAuth(request: Request): boolean {
239
+ const authHeader = request.headers.get('Authorization');
240
+ if (!authHeader) return false;
241
+
242
+ const expectedKey = process.env.SEPAY_WEBHOOK_API_KEY!;
243
+
244
+ // Support both "Bearer" and "Apikey" formats
245
+ let providedKey: string;
246
+ if (authHeader.startsWith('Bearer ')) {
247
+ providedKey = authHeader.slice(7);
248
+ } else if (authHeader.startsWith('Apikey ')) {
249
+ providedKey = authHeader.slice(7);
42
250
  } else {
43
- res.redirect(`/order/${orderId}/pending`);
251
+ return false;
44
252
  }
45
- });
253
+
254
+ // Timing-safe comparison to prevent timing attacks
255
+ try {
256
+ const expected = Buffer.from(expectedKey);
257
+ const provided = Buffer.from(providedKey);
258
+ if (expected.length !== provided.length) return false;
259
+ return timingSafeEqual(expected, provided);
260
+ } catch {
261
+ return false;
262
+ }
263
+ }
264
+
265
+ export async function POST(request: Request) {
266
+ // 1. Verify authentication
267
+ if (!verifyWebhookAuth(request)) {
268
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
269
+ }
270
+
271
+ const payload = await request.json();
272
+
273
+ // 2. Extract event ID for idempotency
274
+ const eventId = String(payload.id || payload.transaction_id || Date.now());
275
+
276
+ // 3. Check for duplicate
277
+ const existingEvent = await db.select()
278
+ .from(webhookEvents)
279
+ .where(eq(webhookEvents.eventId, eventId))
280
+ .limit(1);
281
+
282
+ if (existingEvent.length > 0) {
283
+ console.log(`Duplicate SePay webhook ignored: ${eventId}`);
284
+ return NextResponse.json({ success: true });
285
+ }
286
+
287
+ // 4. Record event BEFORE processing (idempotency)
288
+ await db.insert(webhookEvents).values({
289
+ id: crypto.randomUUID(),
290
+ provider: 'sepay',
291
+ eventType: 'transaction',
292
+ eventId,
293
+ payload: JSON.stringify(payload),
294
+ processed: false,
295
+ });
296
+
297
+ try {
298
+ await processTransaction(payload);
299
+
300
+ await db.update(webhookEvents)
301
+ .set({ processed: true, processedAt: new Date() })
302
+ .where(eq(webhookEvents.eventId, eventId));
303
+
304
+ } catch (error) {
305
+ // Log error but return 200 to prevent retry loop
306
+ await db.update(webhookEvents)
307
+ .set({
308
+ processed: true,
309
+ processedAt: new Date(),
310
+ error: error instanceof Error ? error.message : 'Unknown error',
311
+ })
312
+ .where(eq(webhookEvents.eventId, eventId));
313
+ }
314
+
315
+ // Always return 200 to prevent SePay retries
316
+ return NextResponse.json({ success: true });
317
+ }
46
318
  ```
47
319
 
48
- ## Implementation Patterns
320
+ ### Webhook Payload Structure
321
+ ```typescript
322
+ interface SepayWebhookPayload {
323
+ id: number; // Transaction ID (unique key)
324
+ gateway: string; // Bank name (e.g., "Vietcombank")
325
+ transactionDate: string; // "2025-01-07 10:30:00"
326
+ accountNumber: string; // Account number
327
+ code?: string; // Optional payment code
328
+ content: string; // Transaction memo - CRITICAL for matching
329
+ transferType: 'in' | 'out'; // Only process 'in'
330
+ transferAmount: number; // Amount in VND
331
+ accumulated: number; // Balance after transaction
332
+ subAccount?: string;
333
+ referenceCode?: string;
334
+ description?: string;
335
+ }
336
+ ```
49
337
 
50
- ### Payment Flow Pattern
51
- ```javascript
52
- class PaymentService {
53
- async createPayment(order) {
54
- // 1. Create order in your system
55
- const paymentCode = `ORDER_${order.id}_${Date.now()}`;
56
- await this.savePaymentCode(order.id, paymentCode);
338
+ ## Order Matching Strategy
339
+
340
+ ### Multi-Strategy Fallback Chain
341
+ ```typescript
342
+ // lib/sepay.ts
343
+ export async function findOrderByTransaction(
344
+ payload: SepayWebhookPayload
345
+ ): Promise<{ order: Order | null; matchMethod: string }> {
346
+ const { content, transferAmount, transactionDate } = payload;
347
+
348
+ // Strategy 1: Parse Order ID from content (preferred)
349
+ const parsedOrderId = parseOrderIdFromContent(content);
350
+ if (parsedOrderId) {
351
+ const order = await db.select()
352
+ .from(orders)
353
+ .where(eq(orders.id, parsedOrderId))
354
+ .limit(1);
355
+
356
+ if (order[0]) {
357
+ return { order: order[0], matchMethod: 'content-parse' };
358
+ }
359
+ }
57
360
 
58
- // 2. Generate checkout form
59
- const fields = this.client.checkout.initOneTimePaymentFields({
60
- order_invoice_number: paymentCode,
61
- order_amount: order.total,
62
- currency: 'VND',
63
- success_url: `${config.baseUrl}/payment/success?order=${order.id}`,
64
- error_url: `${config.baseUrl}/payment/error?order=${order.id}`,
65
- cancel_url: `${config.baseUrl}/payment/cancel?order=${order.id}`,
66
- order_description: `Payment for Order #${order.id}`,
361
+ // Strategy 2: Team payment ID match
362
+ const teamMatch = content.match(/TEAM([A-F0-9]{8})/i);
363
+ if (teamMatch) {
364
+ const teamPaymentId = `TEAM${teamMatch[1].toUpperCase()}`;
365
+ const order = await db.select()
366
+ .from(orders)
367
+ .where(eq(orders.paymentId, teamPaymentId))
368
+ .limit(1);
369
+
370
+ if (order[0]) {
371
+ return { order: order[0], matchMethod: 'team-payment-id' };
372
+ }
373
+ }
374
+
375
+ // Strategy 3: Amount + timestamp window (±30 minutes)
376
+ const transactionTime = new Date(transactionDate);
377
+ const windowStart = new Date(transactionTime.getTime() - 30 * 60 * 1000);
378
+ const windowEnd = new Date(transactionTime.getTime() + 30 * 60 * 1000);
379
+
380
+ const windowMatches = await db.select()
381
+ .from(orders)
382
+ .where(and(
383
+ eq(orders.status, 'pending'),
384
+ eq(orders.paymentProvider, 'sepay'),
385
+ eq(orders.amount, transferAmount),
386
+ gte(orders.createdAt, windowStart),
387
+ lte(orders.createdAt, windowEnd)
388
+ ))
389
+ .limit(10);
390
+
391
+ if (windowMatches.length === 1) {
392
+ return { order: windowMatches[0], matchMethod: 'timestamp-window' };
393
+ }
394
+
395
+ if (windowMatches.length > 1) {
396
+ // Multiple matches - select closest by creation time
397
+ const closest = windowMatches.reduce((prev, curr) => {
398
+ const prevDiff = Math.abs(prev.createdAt.getTime() - transactionTime.getTime());
399
+ const currDiff = Math.abs(curr.createdAt.getTime() - transactionTime.getTime());
400
+ return currDiff < prevDiff ? curr : prev;
67
401
  });
402
+ return { order: closest, matchMethod: 'timestamp-window-closest' };
403
+ }
68
404
 
69
- return fields;
405
+ // Strategy 4: Amount only (last resort - single match only)
406
+ const amountMatches = await db.select()
407
+ .from(orders)
408
+ .where(and(
409
+ eq(orders.status, 'pending'),
410
+ eq(orders.paymentProvider, 'sepay'),
411
+ eq(orders.amount, transferAmount)
412
+ ))
413
+ .limit(2);
414
+
415
+ if (amountMatches.length === 1) {
416
+ console.warn(`⚠️ Amount-only match for ${transferAmount} VND - verify manually`);
417
+ return { order: amountMatches[0], matchMethod: 'amount-only' };
70
418
  }
71
419
 
72
- async verifyPayment(orderId) {
73
- const paymentCode = await this.getPaymentCode(orderId);
74
- const payment = await this.client.order.retrieve(paymentCode);
420
+ // No match found
421
+ console.error(`❌ Could not match order:
422
+ Content: "${content}"
423
+ Amount: ${transferAmount} VND
424
+ Transaction Date: ${transactionDate}`);
425
+
426
+ return { order: null, matchMethod: 'none' };
427
+ }
428
+ ```
75
429
 
76
- return {
77
- isPaid: payment.status === 'completed',
78
- amount: payment.amount,
79
- paidAt: payment.completed_at,
80
- };
430
+ ### UUID Parsing with Bank Transformations
431
+ ```typescript
432
+ // lib/sepay.ts
433
+ export function parseOrderIdFromContent(content: string): string | null {
434
+ if (!content) return null;
435
+
436
+ // Pattern 1: Standard "CLAUDEKIT {uuid}"
437
+ const claudekitMatch = content.match(/CLAUDEKIT\s+([\w-]+)/i);
438
+ if (claudekitMatch) {
439
+ return normalizeUUID(claudekitMatch[1]);
440
+ }
441
+
442
+ // Pattern 2: UUID anywhere in content (banks may strip/transform content)
443
+ // Match 8-4-4-4-12 hex with optional dashes
444
+ const uuidMatch = content.match(
445
+ /([0-9A-F]{8}-?[0-9A-F]{4}-?[0-9A-F]{4}-?[0-9A-F]{4}-?[0-9A-F]{12})/i
446
+ );
447
+ if (uuidMatch) {
448
+ return normalizeUUID(uuidMatch[1]);
81
449
  }
450
+
451
+ return null;
452
+ }
453
+
454
+ function normalizeUUID(input: string): string | null {
455
+ // Remove dashes and validate
456
+ const cleaned = input.replace(/-/g, '');
457
+
458
+ if (cleaned.length !== 32) return null;
459
+ if (!/^[0-9a-f]+$/i.test(cleaned)) return null;
460
+
461
+ // Re-format to standard UUID format
462
+ return [
463
+ cleaned.slice(0, 8),
464
+ cleaned.slice(8, 12),
465
+ cleaned.slice(12, 16),
466
+ cleaned.slice(16, 20),
467
+ cleaned.slice(20),
468
+ ].join('-').toLowerCase();
82
469
  }
83
470
  ```
84
471
 
85
- ### Webhook Resilience Pattern
86
- ```javascript
87
- async function handleWebhook(data) {
88
- const maxRetries = 3;
89
- let attempt = 0;
472
+ ### Handled Content Formats
473
+ ```
474
+ CLAUDEKIT 4e4635f4-0478-4080-a5c5-48da91f97f1e ✅ Standard
475
+ CLAUDEKIT 4e4635f404784080a5c548da91f97f1e ✅ Bank stripped dashes
476
+ CLAUDEKIT4e4635f404784080a5c548da91f97f1e ✅ No space
477
+ 4e4635f404784080a5c548da91f97f1e-CLAUDEKIT ✅ Reversed
478
+ claudekit 4e4635f4-0478-4080-a5c5-48da91f97f1e ✅ Lowercase
479
+ BankAPINotify 4e4635f404784080a5c548da91f97f1e... ✅ Extra prefix
480
+ 4e4635f404784080a5c548da91f97f1e ✅ UUID only
481
+ ```
482
+
483
+ ## Transaction Processing
484
+
485
+ ### Complete Processing Flow
486
+ ```typescript
487
+ async function processTransaction(payload: SepayWebhookPayload) {
488
+ // 1. Only process incoming transfers
489
+ if (payload.transferType !== 'in') {
490
+ console.log('Skipping outbound transfer');
491
+ return;
492
+ }
493
+
494
+ // 2. Find matching order
495
+ const { order, matchMethod } = await findOrderByTransaction(payload);
496
+ if (!order) {
497
+ console.error('No matching order found');
498
+ return;
499
+ }
500
+
501
+ // 3. Verify amount (allow overpayment)
502
+ if (payload.transferAmount < order.amount) {
503
+ console.error(`Underpayment: expected ${order.amount}, got ${payload.transferAmount}`);
504
+ return;
505
+ }
506
+ if (payload.transferAmount > order.amount) {
507
+ console.log(`Overpayment accepted: expected ${order.amount}, got ${payload.transferAmount}`);
508
+ }
509
+
510
+ // 4. Update order with transaction details
511
+ const existingMetadata = order.metadata ? JSON.parse(order.metadata) : {};
512
+ await db.update(orders)
513
+ .set({
514
+ status: 'completed',
515
+ paymentId: String(payload.id),
516
+ metadata: JSON.stringify({
517
+ ...existingMetadata, // Preserve discount info
518
+ gateway: payload.gateway,
519
+ transactionDate: payload.transactionDate,
520
+ accountNumber: payload.accountNumber,
521
+ transferAmount: payload.transferAmount,
522
+ content: payload.content,
523
+ matchMethod,
524
+ transactionId: payload.id,
525
+ }),
526
+ updatedAt: new Date(),
527
+ })
528
+ .where(eq(orders.id, order.id));
529
+
530
+ // 5. Create license (non-blocking)
531
+ try {
532
+ await createLicense(order);
533
+ } catch (error) {
534
+ console.error('Failed to create license:', error);
535
+ }
536
+
537
+ // 6. Send confirmation email (non-blocking)
538
+ try {
539
+ await sendOrderConfirmation(order, payload);
540
+ } catch (error) {
541
+ console.error('Failed to send confirmation:', error);
542
+ }
90
543
 
91
- while (attempt < maxRetries) {
544
+ // 7. Create referral commission (non-blocking)
545
+ if (order.referredBy) {
92
546
  try {
93
- await db.transaction(async (trx) => {
94
- // Check duplicate
95
- const exists = await trx('transactions')
96
- .where('sepay_id', data.id)
97
- .first();
98
-
99
- if (exists) return;
100
-
101
- // Save transaction
102
- await trx('transactions').insert({
103
- sepay_id: data.id,
104
- amount: data.transferAmount,
105
- content: data.content,
106
- reference_code: data.referenceCode,
107
- });
108
-
109
- // Process payment
110
- const order = await findOrderByPaymentCode(data.content);
111
- if (order) {
112
- await markOrderAsPaid(order.id, trx);
113
- }
547
+ // Commission based on actual paid amount
548
+ await createCommission({
549
+ orderId: order.id,
550
+ referrerId: order.referredBy,
551
+ baseAmount: payload.transferAmount, // Actual paid amount
552
+ currency: 'VND',
114
553
  });
554
+ } catch (error) {
555
+ console.error('Failed to create commission:', error);
556
+ }
557
+ }
115
558
 
116
- return { success: true };
559
+ // 8. Update referrer tier (non-blocking)
560
+ if (order.referredBy) {
561
+ try {
562
+ const usdConversion = await convertVndToUsd(payload.transferAmount);
563
+ await updateReferrerTier(order.referredBy, usdConversion.usdCents, order.id);
117
564
  } catch (error) {
118
- attempt++;
119
- if (attempt >= maxRetries) throw error;
120
- await sleep(1000 * attempt); // Exponential backoff
565
+ console.error('Failed to update tier:', error);
121
566
  }
122
567
  }
123
- }
124
- ```
125
568
 
126
- ### Reconciliation Pattern
127
- ```javascript
128
- async function reconcilePayments(fromDate, toDate) {
129
- // Get all pending orders
130
- const pendingOrders = await Order.findPending();
131
-
132
- // Fetch SePay transactions in batches
133
- let sinceId = 0;
134
- const batchSize = 1000;
135
-
136
- while (true) {
137
- const transactions = await sePayClient.transaction.list({
138
- transaction_date_min: fromDate,
139
- transaction_date_max: toDate,
140
- transfer_type: 'in',
141
- since_id: sinceId,
142
- limit: batchSize,
143
- });
569
+ // 9. Grant GitHub access (non-blocking)
570
+ try {
571
+ const metadata = JSON.parse(order.metadata || '{}');
572
+ await inviteToGitHub(metadata.githubUsername, order.productType);
573
+ } catch (error) {
574
+ console.error('Failed to invite to GitHub:', error);
575
+ }
144
576
 
145
- if (transactions.length === 0) break;
577
+ // 10. Sync Polar discount redemption (non-blocking)
578
+ const metadata = JSON.parse(order.metadata || '{}');
579
+ if (metadata.couponId && metadata.couponCode) {
580
+ try {
581
+ await syncPolarDiscountWithRetry(order.id, metadata.couponId, metadata.couponCode);
582
+ } catch (error) {
583
+ console.error('Failed to sync Polar discount:', error);
584
+ await sendDiscordAlert('Polar discount sync failed', { orderId: order.id });
585
+ }
586
+ }
146
587
 
147
- // Match and update
148
- for (const transaction of transactions) {
149
- const order = pendingOrders.find(o =>
150
- transaction.content.includes(o.payment_code)
151
- );
588
+ // 11. Send sales notification (non-blocking)
589
+ try {
590
+ await sendSalesNotification({
591
+ ...order,
592
+ gateway: payload.gateway,
593
+ transactionId: payload.id,
594
+ });
595
+ } catch (error) {
596
+ console.error('Failed to send Discord notification:', error);
597
+ }
598
+ }
599
+ ```
152
600
 
153
- if (order) {
154
- await order.markAsPaid(transaction);
155
- }
601
+ ## Currency Conversion
602
+
603
+ ### VND to USD with Multi-Layer Fallback
604
+ ```typescript
605
+ // lib/currency.ts
606
+ const EXCHANGE_RATE_CACHE_TTL = 60 * 60 * 1000; // 1 hour
607
+ const FALLBACK_VND_TO_USD = 24500; // Conservative fallback
608
+
609
+ let exchangeRateCache: {
610
+ rate: number;
611
+ timestamp: number;
612
+ source: 'api' | 'cached' | 'expired' | 'fallback';
613
+ } | null = null;
614
+
615
+ export async function convertVndToUsd(vndAmount: number): Promise<{
616
+ usdCents: number;
617
+ rate: number;
618
+ source: string;
619
+ }> {
620
+ const now = Date.now();
621
+
622
+ // Layer 1: Fresh cache
623
+ if (exchangeRateCache && now - exchangeRateCache.timestamp < EXCHANGE_RATE_CACHE_TTL) {
624
+ const usdCents = Math.round((vndAmount / exchangeRateCache.rate) * 100);
625
+ return { usdCents, rate: exchangeRateCache.rate, source: 'cached' };
626
+ }
627
+
628
+ // Layer 2: Try live API
629
+ try {
630
+ const response = await fetch(
631
+ 'https://api.exchangerate-api.com/v4/latest/USD',
632
+ { signal: AbortSignal.timeout(5000) }
633
+ );
634
+ const data = await response.json();
635
+ const rate = data.rates.VND;
636
+
637
+ exchangeRateCache = { rate, timestamp: now, source: 'api' };
638
+ const usdCents = Math.round((vndAmount / rate) * 100);
639
+ return { usdCents, rate, source: 'api' };
640
+
641
+ } catch (error) {
642
+ console.warn('Exchange rate API failed:', error);
643
+
644
+ // Layer 3: Expired cache (better than nothing)
645
+ if (exchangeRateCache) {
646
+ const usdCents = Math.round((vndAmount / exchangeRateCache.rate) * 100);
647
+ return { usdCents, rate: exchangeRateCache.rate, source: 'expired_cache' };
156
648
  }
157
649
 
158
- sinceId = transactions[transactions.length - 1].id;
650
+ // Layer 4: Hardcoded fallback
651
+ const usdCents = Math.round((vndAmount / FALLBACK_VND_TO_USD) * 100);
652
+ return { usdCents, rate: FALLBACK_VND_TO_USD, source: 'fallback' };
159
653
  }
160
654
  }
161
655
  ```
162
656
 
163
- ## Performance Optimization
164
-
165
- ### Caching
166
- ```javascript
167
- // Cache bank list
168
- const getBankList = memoize(
169
- async () => {
170
- const response = await fetch('https://qr.sepay.vn/banks.json');
171
- return response.json();
172
- },
173
- { maxAge: 86400000 } // 24 hours
174
- );
657
+ ### USD Discount to VND
658
+ ```typescript
659
+ // When Polar discount is in USD, convert to VND for SePay checkout
660
+ export function convertUsdDiscountToVnd(
661
+ discount: { type: 'fixed' | 'percentage'; amount?: number; basisPoints?: number },
662
+ amountVND: number
663
+ ): number {
664
+ if (discount.type === 'percentage') {
665
+ // Basis points: 1000 = 10%, 10000 = 100%
666
+ const percentage = (discount.basisPoints || 0) / 10000;
667
+ return Math.round(amountVND * percentage);
668
+ } else {
669
+ // Fixed amount in USD cents → VND
670
+ const usdDollars = (discount.amount || 0) / 100;
671
+ return Math.round(usdDollars * 24500); // Use conservative rate
672
+ }
673
+ }
674
+ ```
175
675
 
176
- // Cache QR codes for fixed amounts
177
- const qrCache = new Map();
676
+ ## Invoice Email Template
677
+
678
+ ### HTML Invoice Generation
679
+ ```typescript
680
+ // lib/emails/sepay-invoice.ts
681
+ export function generateSepayInvoice(order: Order, transaction: TransactionInfo): string {
682
+ const metadata = JSON.parse(order.metadata || '{}');
683
+ const invoiceNumber = `INV-${format(new Date(), 'yyyyMMdd')}-${order.id.slice(-8).toUpperCase()}`;
684
+
685
+ // Format VND with Vietnamese locale
686
+ const formatVND = (amount: number) =>
687
+ new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(amount);
688
+
689
+ // Escape HTML to prevent XSS
690
+ const escapeHtml = (text: string) =>
691
+ text.replace(/[&<>"']/g, char => ({
692
+ '&': '&amp;',
693
+ '<': '&lt;',
694
+ '>': '&gt;',
695
+ '"': '&quot;',
696
+ "'": '&#39;',
697
+ })[char] || char);
698
+
699
+ return `
700
+ <!DOCTYPE html>
701
+ <html>
702
+ <head>
703
+ <style>
704
+ .invoice { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; }
705
+ .header { background: linear-gradient(135deg, #ff6b6b, #feca57); padding: 20px; }
706
+ .status { background: #10b981; color: white; padding: 4px 12px; border-radius: 4px; }
707
+ .amount { font-size: 24px; font-weight: bold; }
708
+ .savings { color: #10b981; }
709
+ </style>
710
+ </head>
711
+ <body>
712
+ <div class="invoice">
713
+ <div class="header">
714
+ <h1>Invoice</h1>
715
+ <span class="status">PAID</span>
716
+ </div>
717
+
718
+ <table>
719
+ <tr><td>Invoice #:</td><td>${invoiceNumber}</td></tr>
720
+ <tr><td>Customer:</td><td>${escapeHtml(metadata.name || order.email)}</td></tr>
721
+ <tr><td>Email:</td><td>${escapeHtml(order.email)}</td></tr>
722
+ <tr><td>Payment Date:</td><td>${format(new Date(transaction.transactionDate), 'dd/MM/yyyy HH:mm')}</td></tr>
723
+ <tr><td>Transaction Ref:</td><td>${transaction.transactionId || 'N/A'}</td></tr>
724
+ </table>
725
+
726
+ <h3>Order Details</h3>
727
+ <table>
728
+ <tr><td>Product:</td><td>${getProductName(order.productType)}</td></tr>
729
+ <tr><td>Original Price:</td><td>${formatVND(metadata.originalAmount || order.amount)}</td></tr>
730
+ ${metadata.couponDiscountAmount ? `
731
+ <tr><td>Coupon (${metadata.couponCode}):</td><td>-${formatVND(metadata.couponDiscountAmount)}</td></tr>
732
+ ` : ''}
733
+ ${metadata.referralDiscountAmount ? `
734
+ <tr><td>Referral Discount (20%):</td><td>-${formatVND(metadata.referralDiscountAmount)}</td></tr>
735
+ ` : ''}
736
+ ${order.discountAmount > 0 ? `
737
+ <tr class="savings"><td>Total Savings:</td><td>-${formatVND(order.discountAmount)}</td></tr>
738
+ ` : ''}
739
+ <tr class="amount"><td>Total Paid:</td><td>${formatVND(order.amount)}</td></tr>
740
+ </table>
741
+
742
+ <p>Thank you for your purchase!</p>
743
+ <p>Support: support@claudekit.com</p>
744
+ </div>
745
+ </body>
746
+ </html>
747
+ `;
748
+ }
749
+ ```
178
750
 
179
- function getCachedQRUrl(account, bank, amount) {
180
- const key = `${account}-${bank}-${amount}`;
181
- if (!qrCache.has(key)) {
182
- const url = generateQRUrl(account, bank, amount);
183
- qrCache.set(key, url);
751
+ ## Error Handling Patterns
752
+
753
+ ### Always Return 200 to SePay
754
+ ```typescript
755
+ // Webhook must always return 200 to prevent retry loop
756
+ export async function POST(request: Request) {
757
+ try {
758
+ // ... processing
759
+ } catch (error) {
760
+ // Log error but don't fail
761
+ console.error('Webhook processing error:', error);
762
+ await logWebhookError(error);
184
763
  }
185
- return qrCache.get(key);
764
+
765
+ // ALWAYS return 200
766
+ return NextResponse.json({ success: true });
186
767
  }
187
768
  ```
188
769
 
189
- ### Rate Limit Management
190
- ```javascript
191
- const RateLimiter = require('bottleneck');
770
+ ### Non-Blocking Post-Payment Operations
771
+ ```typescript
772
+ // Wrap each operation in try-catch
773
+ const operations = [
774
+ { name: 'License', fn: () => createLicense(order) },
775
+ { name: 'Email', fn: () => sendOrderConfirmation(order) },
776
+ { name: 'Commission', fn: () => createCommission(order) },
777
+ { name: 'GitHub', fn: () => inviteToGitHub(username, productType) },
778
+ { name: 'Discord', fn: () => sendSalesNotification(order) },
779
+ ];
780
+
781
+ for (const op of operations) {
782
+ try {
783
+ await op.fn();
784
+ console.log(`✅ ${op.name} completed`);
785
+ } catch (error) {
786
+ console.error(`❌ ${op.name} failed:`, error);
787
+ // Continue - don't block other operations
788
+ }
789
+ }
790
+ ```
192
791
 
193
- const limiter = new RateLimiter({
194
- maxConcurrent: 1,
195
- minTime: 500, // 2 requests per second
196
- reservoir: 100,
197
- reservoirRefreshAmount: 100,
198
- reservoirRefreshInterval: 60000, // per minute
199
- });
792
+ ### Amount Validation
793
+ ```typescript
794
+ // Reject underpayment, accept overpayment
795
+ if (transferAmount < order.amount) {
796
+ console.error(`Underpayment: expected ${order.amount}, received ${transferAmount}`);
797
+ await flagOrderForReview(order.id, 'underpayment');
798
+ return; // Don't process
799
+ }
200
800
 
201
- // Wrap API calls
202
- const apiCall = limiter.wrap(async (endpoint, params) => {
203
- return await sePayClient.api.call(endpoint, params);
204
- });
801
+ if (transferAmount > order.amount) {
802
+ console.log(`Overpayment: expected ${order.amount}, received ${transferAmount}`);
803
+ // Continue processing - customer paid more than required
804
+ }
205
805
  ```
206
806
 
207
- ### Async Processing
208
- ```javascript
209
- // Queue webhook processing
210
- app.post('/webhook/sepay', async (req, res) => {
211
- // Respond immediately
212
- res.json({ success: true });
213
-
214
- // Queue for background processing
215
- await webhookQueue.add('process-sepay-webhook', req.body, {
216
- attempts: 3,
217
- backoff: {
218
- type: 'exponential',
219
- delay: 2000,
220
- },
221
- });
222
- });
807
+ ## Testing Patterns
223
808
 
224
- // Process in background worker
225
- webhookQueue.process('process-sepay-webhook', async (job) => {
226
- await handleWebhook(job.data);
227
- });
228
- ```
809
+ ### Unit Tests for UUID Parsing
810
+ ```typescript
811
+ // __tests__/lib/sepay.test.ts
812
+ describe('parseOrderIdFromContent', () => {
813
+ it('parses standard format', () => {
814
+ expect(parseOrderIdFromContent('CLAUDEKIT 4e4635f4-0478-4080-a5c5-48da91f97f1e'))
815
+ .toBe('4e4635f4-0478-4080-a5c5-48da91f97f1e');
816
+ });
229
817
 
230
- ## Monitoring & Logging
231
-
232
- ### Essential Metrics
233
- ```javascript
234
- const metrics = {
235
- payment_initiated: counter('sepay_payment_initiated_total'),
236
- payment_success: counter('sepay_payment_success_total'),
237
- payment_failed: counter('sepay_payment_failed_total'),
238
- webhook_received: counter('sepay_webhook_received_total'),
239
- webhook_processed: counter('sepay_webhook_processed_total'),
240
- api_errors: counter('sepay_api_errors_total'),
241
- processing_time: histogram('sepay_processing_duration_seconds'),
242
- };
243
-
244
- // Track metrics
245
- metrics.payment_initiated.inc();
246
- const timer = metrics.processing_time.startTimer();
247
- // ... process payment
248
- timer();
249
- ```
818
+ it('handles bank dash-stripping', () => {
819
+ expect(parseOrderIdFromContent('CLAUDEKIT 4e4635f404784080a5c548da91f97f1e'))
820
+ .toBe('4e4635f4-0478-4080-a5c5-48da91f97f1e');
821
+ });
250
822
 
251
- ### Structured Logging
252
- ```javascript
253
- logger.info('Payment initiated', {
254
- order_id: order.id,
255
- amount: order.total,
256
- payment_method: 'sepay',
257
- customer_id: customer.id,
258
- });
823
+ it('handles real-world Vietnamese bank memo', () => {
824
+ expect(parseOrderIdFromContent('BankAPINotify 4e4635f404784080a5c548da91f97f1e-CHUYEN TIEN'))
825
+ .toBe('4e4635f4-0478-4080-a5c5-48da91f97f1e');
826
+ });
259
827
 
260
- logger.info('Webhook received', {
261
- transaction_id: webhook.id,
262
- amount: webhook.transferAmount,
263
- type: webhook.transferType,
264
- reference: webhook.referenceCode,
828
+ it('returns null for invalid content', () => {
829
+ expect(parseOrderIdFromContent('CLAUDEKIT')).toBeNull();
830
+ expect(parseOrderIdFromContent('4e4635f4-0478')).toBeNull();
831
+ expect(parseOrderIdFromContent('104588021672-CLAUDEKIT')).toBeNull();
832
+ });
265
833
  });
834
+ ```
266
835
 
267
- logger.error('Payment failed', {
268
- order_id: order.id,
269
- error: error.message,
270
- stack: error.stack,
271
- sepay_response: response,
272
- });
836
+ ### Webhook Integration Test Script
837
+ ```bash
838
+ #!/bin/bash
839
+ # scripts/test-sepay-webhook.sh
840
+
841
+ BASE_URL="http://localhost:3000/api/webhooks/sepay"
842
+ API_KEY="your-test-key"
843
+
844
+ # Test 1: Valid Bearer token
845
+ echo "Test 1: Bearer token auth"
846
+ curl -X POST "$BASE_URL" \
847
+ -H "Authorization: Bearer $API_KEY" \
848
+ -H "Content-Type: application/json" \
849
+ -d '{"id":12345,"content":"CLAUDEKIT test-uuid","transferAmount":2450000,"transferType":"in"}'
850
+
851
+ # Test 2: Valid Apikey format
852
+ echo "Test 2: Apikey auth"
853
+ curl -X POST "$BASE_URL" \
854
+ -H "Authorization: Apikey $API_KEY" \
855
+ -d '{"id":12346,"content":"CLAUDEKIT test-uuid","transferAmount":2450000,"transferType":"in"}'
856
+
857
+ # Test 3: Missing auth (should return 401)
858
+ echo "Test 3: No auth (expect 401)"
859
+ curl -X POST "$BASE_URL" \
860
+ -d '{"id":12347,"content":"test","transferAmount":100000,"transferType":"in"}'
861
+
862
+ # Test 4: Invalid key (should return 401)
863
+ echo "Test 4: Invalid key (expect 401)"
864
+ curl -X POST "$BASE_URL" \
865
+ -H "Authorization: Bearer wrong-key" \
866
+ -d '{"id":12348,"content":"test","transferAmount":100000,"transferType":"in"}'
273
867
  ```
274
868
 
275
- ### Alerting
276
- ```javascript
277
- // Alert on high failure rate
278
- if (failureRate > 0.1) { // 10%
279
- alert.send({
280
- severity: 'high',
281
- message: 'SePay payment failure rate exceeds 10%',
282
- details: { failureRate, total, failed },
283
- });
869
+ ## Database Schema
870
+
871
+ ### Orders Table Extensions for SePay
872
+ ```typescript
873
+ // Fields used specifically for SePay
874
+ {
875
+ paymentId: text('payment_id'), // Transaction content or TEAM{8} code
876
+ paymentProvider: literal('sepay'), // Distinguishes from Polar
877
+ currency: literal('VND'), // Always VND for SePay
878
+ amount: integer('amount'), // In VND (no decimals)
284
879
  }
285
880
 
286
- // Alert on webhook delivery failures
287
- if (webhookFailures > 10) {
288
- alert.send({
289
- severity: 'medium',
290
- message: 'SePay webhook delivery failures',
291
- details: { failures: webhookFailures },
292
- });
881
+ // Metadata JSON includes:
882
+ {
883
+ gateway: string, // Bank name from webhook
884
+ transactionDate: string, // Webhook timestamp
885
+ transactionId: number, // SePay transaction ID
886
+ transferAmount: number, // Actual received amount
887
+ matchMethod: string, // How order was matched
888
+ content: string, // Original transaction memo
889
+ encryptedTaxId?: string, // For VAT invoices
293
890
  }
294
891
  ```
295
892
 
296
- ## Testing Strategy
297
-
298
- ### Sandbox Testing Checklist
299
- - [ ] Successful payment flow
300
- - [ ] Failed payment handling
301
- - [ ] Canceled payment handling
302
- - [ ] Webhook delivery and processing
303
- - [ ] Duplicate webhook handling
304
- - [ ] Rate limit handling
305
- - [ ] Error scenarios (network, timeout, invalid data)
306
- - [ ] Payment verification via API
307
- - [ ] QR code generation
308
- - [ ] Order reconciliation
309
-
310
- ### Load Testing
311
- ```javascript
312
- // Simulate high volume
313
- for (let i = 0; i < 1000; i++) {
314
- await createPayment({
315
- amount: 100000,
316
- orderId: `LOAD_TEST_${i}`,
317
- });
318
- await sleep(100); // Respect rate limits
319
- }
893
+ ### Recommended Indexes
894
+ ```sql
895
+ CREATE INDEX idx_orders_sepay_pending ON orders (status, payment_provider, amount)
896
+ WHERE status = 'pending' AND payment_provider = 'sepay';
897
+
898
+ CREATE INDEX idx_orders_sepay_timestamp ON orders (created_at)
899
+ WHERE payment_provider = 'sepay';
900
+
901
+ CREATE INDEX idx_orders_payment_id ON orders (payment_id)
902
+ WHERE payment_provider = 'sepay';
320
903
  ```
321
904
 
322
905
  ## Production Checklist
323
906
 
324
907
  - [ ] Environment variables configured
325
- - [ ] Production credentials obtained
326
- - [ ] HTTPS enabled for all endpoints
327
- - [ ] Webhook endpoint publicly accessible
328
- - [ ] IP whitelisting configured
329
- - [ ] Error monitoring set up
330
- - [ ] Logging infrastructure ready
331
- - [ ] Alerting configured
332
- - [ ] Rate limiting implemented
908
+ - [ ] Bank account verified and active
909
+ - [ ] Webhook endpoint publicly accessible (HTTPS)
910
+ - [ ] Webhook API key set and verified
911
+ - [ ] Timing-safe auth comparison implemented
912
+ - [ ] Idempotency handling tested with duplicate webhooks
913
+ - [ ] UUID parsing tested with real Vietnamese bank memos
914
+ - [ ] Amount validation (underpayment rejection) tested
915
+ - [ ] Overpayment handling verified
916
+ - [ ] Currency conversion fallback chain tested
917
+ - [ ] Invoice email template tested
918
+ - [ ] Error monitoring enabled
919
+ - [ ] Structured logging in place
333
920
  - [ ] Database indexes created
334
- - [ ] Reconciliation job scheduled
335
- - [ ] Backup strategy in place
336
- - [ ] Documentation updated
337
- - [ ] Team trained on operations
921
+ - [ ] Polar discount sync tested (for shared coupons)
922
+ - [ ] Team payment ID format tested
923
+ - [ ] Non-blocking operations wrapped in try-catch
924
+ - [ ] Always-200 webhook response verified
925
+
926
+ ## Common Pitfalls
927
+
928
+ 1. **Not handling bank dash-stripping** - Banks may remove dashes from UUIDs
929
+ 2. **Rejecting overpayments** - Should accept; customer paid more
930
+ 3. **Blocking webhook on non-critical failures** - Wrap in try-catch, continue
931
+ 4. **Not using timing-safe comparison** - Vulnerable to timing attacks
932
+ 5. **Returning non-200 on error** - Causes SePay retry loops
933
+ 6. **Using raw exchange rates without fallback** - API can fail
934
+ 7. **Applying discounts in wrong order** - Always coupon first, then referral
935
+ 8. **Not logging matchMethod** - Hard to debug failed matches
936
+ 9. **Not preserving checkout metadata** - Lose discount audit trail
937
+ 10. **Synchronous Polar discount sync** - Can fail; use retry with backoff
938
+ 11. **Case-sensitive content matching** - Banks may uppercase/lowercase
939
+ 12. **Missing amount-only match safety** - Reject ambiguous matches