synapse-hub 2.2.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/.agents/agents/failure-analyst.md +11 -0
  2. package/.agents/agents/live-explorer.md +28 -0
  3. package/.agents/agents/orchestrator.md +20 -4
  4. package/.agents/agents/pom-crafter.md +12 -0
  5. package/.agents/agents/quality-gatekeeper.md +19 -4
  6. package/.agents/agents/test-runner.md +11 -0
  7. package/.agents/rules/communication-style.md +40 -0
  8. package/.agents/rules/context-engineering.md +23 -0
  9. package/.agents/rules/git-push-protocol.md +11 -17
  10. package/.agents/rules/graphify.md +14 -14
  11. package/.agents/rules/lessons-learned.md +3 -3
  12. package/.agents/rules/mandatory-playwright-live.md +29 -29
  13. package/.agents/rules/mobile_appium_rules.md +132 -0
  14. package/.agents/rules/performance_testing_rules.md +74 -0
  15. package/.agents/rules/skill-precedence.md +1 -1
  16. package/.agents/rules/systematic-debugging.md +6 -6
  17. package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +64 -215
  18. package/.agents/skills/agent-orchestration-multi-agent-optimize/examples/swarm_workload_config.json +12 -0
  19. package/.agents/skills/antigravity-test-sentinel/SKILL.md +3 -3
  20. package/.agents/skills/antigravity-test-sentinel/examples/dod_gate_policy.json +11 -0
  21. package/.agents/skills/api-network-mocking-interception/SKILL.md +1 -1
  22. package/.agents/skills/api-network-mocking-interception/examples/network_route_stub.json +9 -0
  23. package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +9 -9
  24. package/.agents/skills/api-spec-to-e2e-matrix/examples/sample_openapi.json +19 -0
  25. package/.agents/skills/architecture-decision-records/SKILL.md +35 -412
  26. package/.agents/skills/architecture-decision-records/examples/0001-record-architecture-decisions.md +12 -0
  27. package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +4 -1
  28. package/.agents/skills/auth-session-and-cookie-manager/examples/storage_state_sample.json +11 -0
  29. package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +80 -186
  30. package/.agents/skills/backend-load-and-stress-patterns/examples/k6_load_test_sample.js +13 -0
  31. package/.agents/skills/bats-testing-patterns/SKILL.md +1 -1
  32. package/.agents/skills/bats-testing-patterns/examples/cli_runner_test.bats +6 -0
  33. package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -614
  34. package/.agents/skills/clean-pom-crafter/SKILL.md +21 -3
  35. package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -28
  36. package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -138
  37. package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +2 -2
  38. package/.agents/skills/code-refactoring-refactor-clean/examples/refactored_page_sample.groovy +9 -0
  39. package/.agents/skills/code-refactoring-refactor-clean/resources/implementation-playbook.md +9 -7
  40. package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +5 -5
  41. package/.agents/skills/db-state-verifier-and-seeder/examples/db_fixture_seed.json +12 -0
  42. package/.agents/skills/e2e-testing-patterns/SKILL.md +1 -1
  43. package/.agents/skills/e2e-testing-patterns/examples/playwright_sharded_config.ts +12 -0
  44. package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -522
  45. package/.agents/skills/failure-autopsy-and-healing/SKILL.md +17 -3
  46. package/.agents/skills/failure-autopsy-and-healing/examples/sample_junit_failure.xml +8 -0
  47. package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -64
  48. package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -56
  49. package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -98
  50. package/.agents/skills/file-and-report-validator/SKILL.md +1 -1
  51. package/.agents/skills/file-and-report-validator/examples/sample_export_schema.json +14 -0
  52. package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +3 -3
  53. package/.agents/skills/flaky-test-sentinel-and-quarantine/examples/quarantine_registry.json +11 -0
  54. package/.agents/skills/gherkin-to-suite/SKILL.md +103 -0
  55. package/.agents/skills/gherkin-to-suite/examples/checkout.feature +39 -0
  56. package/.agents/skills/gherkin-to-suite/examples/suite_report_sample.json +334 -0
  57. package/.agents/skills/github-actions-templates/SKILL.md +47 -304
  58. package/.agents/skills/github-actions-templates/examples/matrix_test_pipeline.yml +8 -0
  59. package/.agents/skills/graphify-impact-analyzer/SKILL.md +6 -6
  60. package/.agents/skills/graphify-impact-analyzer/examples/dependency_blast_radius.json +8 -0
  61. package/.agents/skills/katalon-cli-runner/SKILL.md +2 -2
  62. package/.agents/skills/katalon-cli-runner/examples/headless_kre_exec.sh +3 -0
  63. package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -209
  64. package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -155
  65. package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -67
  66. package/.agents/skills/lam-script-generator/SKILL.md +42 -1
  67. package/.agents/skills/lam-script-generator/examples/user_story_sample.md +8 -0
  68. package/.agents/skills/lean-code-ladder/SKILL.md +83 -0
  69. package/.agents/skills/lean-code-ladder/examples/ladder_walkthrough.md +37 -0
  70. package/.agents/skills/meta-prompt-crafter/SKILL.md +107 -0
  71. package/.agents/skills/meta-prompt-crafter/examples/qa_prompt_template.md +35 -0
  72. package/.agents/skills/persistent-planning-files/SKILL.md +108 -0
  73. package/.agents/skills/persistent-planning-files/examples/task_plan_example.md +56 -0
  74. package/.agents/skills/playwright-live-interaction/SKILL.md +49 -1
  75. package/.agents/skills/playwright-live-interaction/examples/live_probe_script.js +5 -0
  76. package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -160
  77. package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -75
  78. package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -388
  79. package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -134
  80. package/.agents/skills/playwright-webapp-testing/SKILL.md +93 -0
  81. package/.agents/skills/playwright-webapp-testing/examples/server_lifecycle_playwright.py +63 -0
  82. package/.agents/skills/rbt-manual-testing/SKILL.md +150 -0
  83. package/.agents/skills/rbt-manual-testing/examples/checkout_rbt_manual_suite.md +25 -0
  84. package/.agents/skills/security-dast-sentinel/SKILL.md +57 -135
  85. package/.agents/skills/security-dast-sentinel/examples/dast_scan_config.json +10 -0
  86. package/.agents/skills/self-healing-locator/SKILL.md +24 -10
  87. package/.agents/skills/self-healing-locator/examples/aom_diff_sample.json +16 -0
  88. package/.agents/skills/skillspector-security-guard/SKILL.md +32 -90
  89. package/.agents/skills/skillspector-security-guard/examples/safe_mcp_config.json +12 -0
  90. package/.agents/skills/surgical-coding-principles/SKILL.md +89 -0
  91. package/.agents/skills/surgical-coding-principles/examples/surgical_vs_scope_creep.md +46 -0
  92. package/.agents/skills/synthetic-test-data-generator/SKILL.md +3 -3
  93. package/.agents/skills/synthetic-test-data-generator/examples/idempotent_data_recipe.json +9 -0
  94. package/.agents/skills/systematic-debugging/SKILL.md +100 -0
  95. package/.agents/skills/systematic-debugging/examples/four_phase_case.md +44 -0
  96. package/.agents/skills/test-driven-development/SKILL.md +114 -0
  97. package/.agents/skills/test-driven-development/examples/red_green_refactor_qa.md +78 -0
  98. package/.agents/skills/token-and-context-optimizer/SKILL.md +1 -1
  99. package/.agents/skills/token-and-context-optimizer/examples/distilled_log_sample.txt +3 -0
  100. package/.agents/skills/verification-before-completion/SKILL.md +100 -0
  101. package/.agents/skills/verification-before-completion/examples/evidence_log_example.md +46 -0
  102. package/.agents/skills/visual-regression-sentinel/SKILL.md +21 -1
  103. package/.agents/skills/visual-regression-sentinel/examples/visual_mask_rules.json +9 -0
  104. package/.agents/skills/wcag-audit-patterns/SKILL.md +3 -3
  105. package/.agents/skills/wcag-audit-patterns/examples/wcag_compliance_checklist.json +10 -0
  106. package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -541
  107. package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +1 -1
  108. package/.agents/skills/web-vitals-and-performance-profiler/examples/cwv_budget_policy.json +6 -0
  109. package/.agents/templates/completion_report.md +57 -57
  110. package/.agents/workflows/analyze_requirement_document.md +18 -0
  111. package/.agents/workflows/export_testcases_excel.md +32 -0
  112. package/.agents/workflows/generate_combinatorial_test_data.md +28 -0
  113. package/.agents/workflows/generate_cross_module_test_plan.md +37 -0
  114. package/.agents/workflows/generate_manual_testcases_rbt.md +56 -0
  115. package/.agents/workflows/generate_requirements_from_website.md +25 -0
  116. package/.agents/workflows/generate_testcases_from_requirements.md +21 -0
  117. package/.agents/workflows/graphify.md +10 -10
  118. package/.agents/workflows/verify.md +2 -2
  119. package/.cursor/rules/language.mdc +7 -7
  120. package/.cursor/rules/synapse-qa.mdc +23 -0
  121. package/.cursorrules +7 -0
  122. package/.pre-commit-hooks.yaml +14 -0
  123. package/.windsurfrules +7 -0
  124. package/AGENTS.md +54 -15
  125. package/CLAUDE.md +35 -12
  126. package/LICENSE +30 -0
  127. package/NOTICE +180 -0
  128. package/README.en.md +325 -0
  129. package/README.md +247 -512
  130. package/action.yml +51 -0
  131. package/benchmarks/qa_eval/README.md +71 -0
  132. package/benchmarks/qa_eval/build_dataset.py +677 -0
  133. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +22 -0
  134. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +22 -0
  135. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +22 -0
  136. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +22 -0
  137. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +22 -0
  138. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +21 -0
  139. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +21 -0
  140. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +21 -0
  141. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +21 -0
  142. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +21 -0
  143. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +23 -0
  144. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +23 -0
  145. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +23 -0
  146. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +23 -0
  147. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +23 -0
  148. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +22 -0
  149. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +22 -0
  150. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +22 -0
  151. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +22 -0
  152. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +23 -0
  153. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +22 -0
  154. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +22 -0
  155. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +22 -0
  156. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +22 -0
  157. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +22 -0
  158. package/benchmarks/qa_eval/eval_runner.py +418 -0
  159. package/benchmarks/qa_eval/reports/AB_METHODOLOGY_REPORT.md +83 -0
  160. package/benchmarks/qa_eval/reports/BENCHMARK_REPORT.md +69 -0
  161. package/benchmarks/qa_eval/reports/eval_results.json +105 -0
  162. package/bin/agent-qa.js +10 -3
  163. package/docs/ARCHITECTURE.md +107 -0
  164. package/docs/CI_CD_INTEGRATION.md +94 -0
  165. package/docs/CLI_REFERENCE.md +157 -0
  166. package/docs/CONTRIBUTING.md +91 -0
  167. package/docs/PLUGIN_DEVELOPMENT_GUIDE.md +126 -0
  168. package/docs/TOKEN_QUOTA_PLAYBOOK.md +41 -0
  169. package/docs/adopted-ecosystem-tools.md +87 -0
  170. package/docs/schemas/synapse.config.schema.json +64 -0
  171. package/examples/cypress-ecommerce-suite/README.md +45 -0
  172. package/examples/cypress-ecommerce-suite/cypress/e2e/checkout.cy.js +17 -0
  173. package/examples/cypress-ecommerce-suite/cypress/pages/BasePage.js +29 -0
  174. package/examples/cypress-ecommerce-suite/cypress/pages/CartPage.js +51 -0
  175. package/examples/cypress-ecommerce-suite/cypress.config.js +13 -0
  176. package/examples/cypress-ecommerce-suite/package.json +13 -0
  177. package/examples/katalon-suite/Keywords/pages/BasePage.groovy +19 -0
  178. package/examples/katalon-suite/Keywords/pages/DashboardPage.groovy +29 -0
  179. package/examples/katalon-suite/Keywords/pages/LoginPage.groovy +45 -0
  180. package/examples/katalon-suite/Profiles/default.glbl +12 -0
  181. package/examples/katalon-suite/README.md +18 -0
  182. package/examples/katalon-suite/Scripts/Auth/TC_LoginSuccess/Script1234567890.groovy +12 -0
  183. package/examples/katalon-suite/Scripts/Dashboard/TC_ViewSummary/Script1234567891.groovy +15 -0
  184. package/examples/katalon-suite/katalon_suite.prj +21 -0
  185. package/examples/playwright-crm-suite/README.md +40 -0
  186. package/examples/playwright-crm-suite/package.json +14 -0
  187. package/examples/playwright-crm-suite/pages/BasePage.ts +37 -0
  188. package/examples/playwright-crm-suite/pages/CustomerPage.ts +57 -0
  189. package/examples/playwright-crm-suite/pages/LoginPage.ts +32 -0
  190. package/examples/playwright-crm-suite/playwright.config.ts +27 -0
  191. package/examples/playwright-crm-suite/tests/auth.spec.ts +22 -0
  192. package/examples/playwright-crm-suite/tests/customers.spec.ts +33 -0
  193. package/examples/plugins/sample-custom-plugin/README.md +14 -0
  194. package/examples/plugins/sample-custom-plugin/plugin.json +16 -0
  195. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/SKILL.md +29 -0
  196. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/examples/audit_fixture.json +8 -0
  197. package/examples/plugins/sample-custom-plugin/tools/custom_security_headers.py +125 -0
  198. package/examples/practices/README.md +22 -0
  199. package/examples/practices/requirements/crm/requirements_contracts.md +292 -0
  200. package/examples/practices/requirements/crm/requirements_customers.md +462 -0
  201. package/examples/practices/requirements/crm/requirements_login.md +202 -0
  202. package/examples/practices/requirements/crm/requirements_projects.md +396 -0
  203. package/examples/practices/requirements/crm/requirements_tasks.md +343 -0
  204. package/examples/practices/requirements/ecommerce/requirements_category_brand.txt +402 -0
  205. package/examples/practices/requirements/jira/KAN-5/KAN-1/2026-04-03_04-28-27.png +0 -0
  206. package/examples/practices/requirements/jira/KAN-5/KAN-1/KAN-1_requirement.md +52 -0
  207. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-19.png +0 -0
  208. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-57.png +0 -0
  209. package/examples/practices/requirements/jira/KAN-5/KAN-4/KAN-4_requirement.md +119 -0
  210. package/examples/practices/requirements/jira/KAN-5/KAN-5_overview.md +9 -0
  211. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-08.png +0 -0
  212. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-23.png +0 -0
  213. package/examples/practices/requirements/jira/KAN-5/KAN-6/KAN-6_requirement.md +32 -0
  214. package/examples/practices/testcases/api/book_management_api_test_cases.md +144 -0
  215. package/examples/practices/testcases/api/user_management_api_test_cases.md +139 -0
  216. package/examples/practices/testcases/crm/test_cases_crm_login.md +148 -0
  217. package/examples/practices/testcases/crm/test_cases_customers.md +156 -0
  218. package/examples/pytest-api-suite/README.md +45 -0
  219. package/examples/pytest-api-suite/conftest.py +31 -0
  220. package/examples/pytest-api-suite/pages/user_api_client.py +36 -0
  221. package/examples/pytest-api-suite/requirements.txt +2 -0
  222. package/examples/pytest-api-suite/tests/test_user_api.py +44 -0
  223. package/examples/selenium-suite/README.md +18 -0
  224. package/examples/selenium-suite/pages/base_page.py +27 -0
  225. package/examples/selenium-suite/pages/login_page.py +29 -0
  226. package/examples/selenium-suite/pages/order_page.py +25 -0
  227. package/examples/selenium-suite/pytest.ini +6 -0
  228. package/examples/selenium-suite/requirements.txt +2 -0
  229. package/examples/selenium-suite/tests/test_login.py +10 -0
  230. package/examples/selenium-suite/tests/test_order.py +10 -0
  231. package/package.json +22 -7
  232. package/scripts/generate_skill_examples.py +244 -0
  233. package/scripts/install.ps1 +112 -0
  234. package/scripts/install_global_plugin.ps1 +94 -0
  235. package/scripts/install_global_plugin.sh +49 -0
  236. package/scripts/lint_skills.ps1 +57 -0
  237. package/scripts/package_dist.py +323 -0
  238. package/scripts/setup.sh +59 -0
  239. package/scripts/update_hub.ps1 +19 -0
  240. package/scripts/update_hub.sh +15 -0
  241. package/skills_manifest.json +209 -6
  242. package/synapse.config.json +30 -0
  243. package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +7 -7
  244. package/templates/PROJECT_STATE_TEMPLATE.md +1 -1
  245. package/templates/ai_bridges/CLAUDE.md +33 -16
  246. package/templates/ai_bridges/copilot-instructions.md +14 -21
  247. package/templates/ai_bridges/cursor_synapse_qa.mdc +17 -20
  248. package/templates/ai_bridges/windsurfrules +21 -21
  249. package/templates/ci/github-actions-synapse.yml +71 -4
  250. package/templates/welcome.html.tmpl +1674 -0
  251. package/tools/.infer_baseline.json +1102 -0
  252. package/tools/TOOLS_RUNBOOK.md +92 -130
  253. package/tools/__init__.py +26 -0
  254. package/tools/agent_canary.py +501 -501
  255. package/tools/analyze_project.py +31 -17
  256. package/tools/api_fuzzer.py +278 -6
  257. package/tools/author_integrity.py +6 -6
  258. package/tools/auto_heal.py +1 -1
  259. package/tools/browser_helpers.js +105 -7
  260. package/tools/bug_reporter.py +31 -1
  261. package/tools/bump_version.py +23 -3
  262. package/tools/cache_resolver.py +248 -14
  263. package/tools/check_env.py +55 -14
  264. package/tools/check_version_sync.py +153 -0
  265. package/tools/ci_healing_hook.py +1 -1
  266. package/tools/cli.py +263 -13
  267. package/tools/count_tokens.py +1257 -0
  268. package/tools/dashboard_generator.py +2638 -0
  269. package/tools/db_sandbox.py +198 -20
  270. package/tools/e2e_flow_prober.ps1 +12 -64
  271. package/tools/e2e_flow_prober.py +99 -0
  272. package/tools/e2e_flow_prober.sh +4 -0
  273. package/tools/export_postman_collection.py +29 -7
  274. package/tools/flaky_detector.py +4 -3
  275. package/tools/generate_allure_report.ps1 +12 -29
  276. package/tools/generate_allure_report.py +77 -0
  277. package/tools/generate_allure_report.sh +4 -0
  278. package/tools/generate_jmx_plan.py +299 -68
  279. package/tools/generate_test_reports.ps1 +12 -134
  280. package/tools/generate_test_reports.py +133 -0
  281. package/tools/generate_test_reports.sh +4 -0
  282. package/tools/gherkin_suite.py +758 -0
  283. package/tools/git_pre_commit_guard.py +12 -6
  284. package/tools/goldfish_review.py +366 -0
  285. package/tools/heal_pr_automator.py +1 -1
  286. package/tools/heuristic_locator_matcher.py +170 -21
  287. package/tools/infer_linter.py +612 -70
  288. package/tools/jtl_analyzer.py +1 -1
  289. package/tools/lint_ai_docs.py +64 -0
  290. package/tools/matrix_sharder.py +1 -1
  291. package/tools/mcp_excel_server.ps1 +12 -250
  292. package/tools/mcp_excel_server.py +249 -0
  293. package/tools/mcp_excel_server.sh +4 -0
  294. package/tools/mcp_server.py +368 -144
  295. package/tools/md_to_xlsx.py +307 -0
  296. package/tools/micro_mutator.py +300 -69
  297. package/tools/omni_transpiler.py +2 -2
  298. package/tools/output_formatter.py +128 -0
  299. package/tools/pinpoint_failure.py +88 -88
  300. package/tools/project_state.py +2 -2
  301. package/tools/repo_map.py +1 -1
  302. package/tools/safety_firewall.py +197 -33
  303. package/tools/setup_project.py +294 -30
  304. package/tools/skillspector.py +8 -8
  305. package/tools/spec_drift_sentinel.py +439 -0
  306. package/tools/sync_agent_rules.py +248 -0
  307. package/tools/telemetry_correlator.py +45 -0
  308. package/tools/test_impact.py +51 -12
  309. package/tools/tms_sync_bridge.py +21 -5
  310. package/tools/universal_ir.py +3 -0
  311. package/tools/update_sentinel.py +87 -15
  312. package/tools/verify_all.ps1 +13 -0
  313. package/tools/verify_all.py +463 -79
  314. package/tools/visual_diff_canvas.py +1 -0
  315. package/tools/visual_som_helper.py +1 -1
  316. package/tools/watch_mode.py +305 -0
  317. package/tools/welcome_page.py +291 -0
@@ -0,0 +1,462 @@
1
+ # Tài Liệu Yêu Cầu (Requirements) — Module Customers
2
+
3
+ > **Hệ thống:** Perfex CRM
4
+ > **URL Module:** `https://crm.anhtester.com/admin/clients`
5
+ > **Phiên bản:** Quan sát ngày 03/04/2026
6
+ > **Người thực hiện:** Antigravity AI Agent
7
+ > **Vai trò truy cập:** Admin (`admin@example.com`)
8
+
9
+ ---
10
+
11
+ ## 1. Tổng Quan (Overview)
12
+
13
+ Module **Customers** là module quản lý thông tin khách hàng (Clients) trong hệ thống CRM. Module cho phép người dùng Admin quản lý toàn bộ vòng đời của khách hàng bao gồm: tạo mới, xem chi tiết, chỉnh sửa, xóa, import/export dữ liệu, quản lý liên hệ (Contacts), và thực hiện các thao tác hàng loạt (Bulk Actions).
14
+
15
+ ### 1.1. Các Trang Chính
16
+
17
+ | Trang | URL | Mô tả |
18
+ |:------|:----|:------|
19
+ | Danh sách Customers | `/admin/clients` | Hiển thị tổng hợp và bảng dữ liệu khách hàng |
20
+ | Thêm mới Customer | `/admin/clients/client` | Form tạo khách hàng mới |
21
+ | Chi tiết Customer | `/admin/clients/client/{id}` | Xem/chỉnh sửa thông tin chi tiết khách hàng |
22
+ | Import Customers | `/admin/clients/import` | Import khách hàng từ file CSV |
23
+ | Danh sách Contacts | `/admin/clients` → nút Contacts | Xem tất cả liên hệ của mọi khách hàng |
24
+
25
+ ### 1.2. Customers Summary (Bảng Tóm Tắt)
26
+
27
+ Trang danh sách hiển thị bảng tóm tắt thống kê ở phần đầu gồm:
28
+
29
+ | Chỉ số | Mô tả |
30
+ |:-------|:------|
31
+ | **Total Customers** | Tổng số khách hàng trong hệ thống |
32
+ | **Active Customers** | Số khách hàng đang hoạt động |
33
+ | **Inactive Customers** | Số khách hàng không hoạt động |
34
+ | **Active Contacts** | Tổng số liên hệ đang hoạt động |
35
+ | **Inactive Contacts** | Tổng số liên hệ không hoạt động |
36
+ | **Contacts Logged In Today** | Số liên hệ đăng nhập trong ngày |
37
+
38
+ ---
39
+
40
+ ## 2. Yêu Cầu Chức Năng (Functional Requirements)
41
+
42
+ ### FR-CUST-001: Xem Danh Sách Khách Hàng
43
+
44
+ **Mô tả:** Là một Admin, tôi muốn xem danh sách tất cả khách hàng trong hệ thống để có cái nhìn tổng quan về cơ sở khách hàng.
45
+
46
+ **Tiêu chí chấp nhận:**
47
+ - Hệ thống hiển thị bảng dữ liệu (DataTable) với các cột: `#` (ID), `Company`, `Primary Contact`, `Primary Email`, `Phone`, `Active` (Toggle switch), `Groups`, `Date Created`.
48
+ - Bảng hỗ trợ phân trang với dropdown chọn số lượng hiển thị: 25, 50, 100.
49
+ - Bảng hỗ trợ sắp xếp (sort) theo từng cột bằng cách click vào tiêu đề cột.
50
+ - Mỗi dòng có checkbox ở cột đầu tiên để chọn cho Bulk Actions.
51
+ - Cột `Company` hiển thị tên công ty dạng link, click để vào trang chi tiết.
52
+ - Cột `Phone` hiển thị số điện thoại dạng link.
53
+ - Cột `Active` hiển thị toggle switch cho phép bật/tắt trạng thái khách hàng ngay tại bảng.
54
+ - Cột `Groups` hiển thị các nhóm (tag/badge) mà khách hàng thuộc về.
55
+ - Có thanh tìm kiếm (Search) ở góc phải trên của bảng.
56
+
57
+ ---
58
+
59
+ ### FR-CUST-002: Tạo Mới Khách Hàng (New Customer)
60
+
61
+ **Mô tả:** Là một Admin, tôi muốn tạo mới một khách hàng với đầy đủ thông tin cơ bản và địa chỉ thanh toán/giao hàng.
62
+
63
+ **Tiêu chí chấp nhận:**
64
+ - Click nút **"+ New Customer"** trên trang danh sách sẽ chuyển đến form tạo mới tại `/admin/clients/client`.
65
+ - Form chia thành 2 tab: **Customer Details** và **Billing & Shipping**.
66
+ - Tab **Customer Details** là tab mặc định khi mở form.
67
+ - Trường **Company** là trường bắt buộc duy nhất (đánh dấu `*` màu đỏ).
68
+ - Khi nhấn **Save** mà không điền trường Company, hệ thống hiển thị thông báo lỗi `"This field is required."` màu đỏ bên dưới trường Company.
69
+ - Có 2 nút submit:
70
+ - **"Save and create contact"**: Lưu khách hàng và chuyển sang form tạo Contact.
71
+ - **"Save"**: Lưu khách hàng.
72
+ - Sau khi lưu thành công, hệ thống chuyển về trang chi tiết khách hàng vừa tạo.
73
+
74
+ ---
75
+
76
+ ### FR-CUST-003: Xem & Chỉnh Sửa Chi Tiết Khách Hàng (Customer Detail)
77
+
78
+ **Mô tả:** Là một Admin, tôi muốn xem và chỉnh sửa đầy đủ thông tin của một khách hàng cụ thể.
79
+
80
+ **Tiêu chí chấp nhận:**
81
+ - URL trang chi tiết có dạng: `/admin/clients/client/{customer_id}`.
82
+ - Header hiển thị: `#{ID} {Company Name}` kèm dropdown action (chứa chức năng Delete).
83
+ - Phía bên phải header hiển thị label **"Profile"**.
84
+ - Trang chia thành 2 phần:
85
+ - **Sidebar trái**: Danh sách 19 tab liên quan.
86
+ - **Nội dung chính (bên phải)**: Form chỉnh sửa thông tin.
87
+
88
+ #### Sidebar trái — Danh sách Tab:
89
+
90
+ | STT | Tab | Mô tả |
91
+ |:----|:----|:------|
92
+ | 1 | **Profile** | Thông tin hồ sơ (3 sub-tab: Customer Details, Billing & Shipping, Customer Admins) |
93
+ | 2 | **Contacts** | Danh sách liên hệ của khách hàng |
94
+ | 3 | **Notes** | Ghi chú nội bộ |
95
+ | 4 | **Statement** | Bản kê tài chính |
96
+ | 5 | **Invoices** | Danh sách hóa đơn |
97
+ | 6 | **Payments** | Lịch sử thanh toán |
98
+ | 7 | **Proposals** | Đề xuất/báo giá |
99
+ | 8 | **Credit Notes** | Ghi chú tín dụng |
100
+ | 9 | **Estimates** | Báo giá |
101
+ | 10 | **Subscriptions** | Đăng ký dịch vụ |
102
+ | 11 | **Expenses** | Chi phí liên quan |
103
+ | 12 | **Contracts** | Hợp đồng |
104
+ | 13 | **Projects** | Dự án |
105
+ | 14 | **Tasks** | Công việc |
106
+ | 15 | **Tickets** | Hỗ trợ / Sự cố |
107
+ | 16 | **Files** | Tệp đính kèm |
108
+ | 17 | **Vault** | Kho lưu trữ an toàn |
109
+ | 18 | **Reminders** | Nhắc nhở |
110
+ | 19 | **Map** | Bản đồ địa chỉ |
111
+
112
+ - Form Profile có 3 sub-tab:
113
+ - **Customer Details**: Hiển thị và cho phép chỉnh sửa thông tin cơ bản (giống form tạo mới).
114
+ - **Billing & Shipping**: Địa chỉ thanh toán và giao hàng.
115
+ - **Customer Admins**: Danh sách admin quản lý khách hàng.
116
+ - Nút **Save** ở góc dưới bên phải cho phép lưu thay đổi.
117
+
118
+ ---
119
+
120
+ ### FR-CUST-004: Xóa Khách Hàng (Delete Customer)
121
+
122
+ **Mô tả:** Là một Admin, tôi muốn xóa một khách hàng khỏi hệ thống khi cần.
123
+
124
+ **Tiêu chí chấp nhận:**
125
+ - Trên trang chi tiết khách hàng, click dropdown bên cạnh `#{ID} {Company Name}` → chọn **Delete**.
126
+ - Hệ thống hiển thị hộp thoại xác nhận trước khi xóa.
127
+ - Sau khi xóa, hệ thống chuyển về trang danh sách Customers.
128
+
129
+ ---
130
+
131
+ ### FR-CUST-005: Quản Lý Contacts (Liên Hệ) Của Khách Hàng
132
+
133
+ **Mô tả:** Là một Admin, tôi muốn quản lý danh sách liên hệ của từng khách hàng.
134
+
135
+ **Tiêu chí chấp nhận:**
136
+ - Truy cập tab **Contacts** trong trang chi tiết khách hàng.
137
+ - Bảng dữ liệu Contacts gồm các cột: `Full Name`, `Email`, `Position`, `Phone`, `Active` (toggle), `Last Login`.
138
+ - Có nút **"New Contact"** để thêm liên hệ mới.
139
+ - Có nút **Export** để xuất dữ liệu contacts.
140
+ - Có thanh tìm kiếm (Search) và dropdown chọn số lượng hiển thị (mặc định 25).
141
+ - Nếu chưa có contact nào, bảng hiển thị **"No entries found"**.
142
+
143
+ #### Trang Contacts Tổng Hợp (Tất cả khách hàng):
144
+ - Truy cập bằng nút **"Contacts"** trên trang danh sách Customers.
145
+ - Bảng hiển thị tất cả contacts của mọi khách hàng.
146
+ - Các cột: `First Name`, `Last Name`, `Email`, `Company`, `Phone`, `Position`, `Last Login`, `Active`.
147
+ - Có toggle switch để bật/tắt trạng thái Active ngay tại bảng.
148
+ - Tên contact là link dẫn đến trang chi tiết.
149
+
150
+ ---
151
+
152
+ ### FR-CUST-006: Import Khách Hàng (Import Customers)
153
+
154
+ **Mô tả:** Là một Admin, tôi muốn import dữ liệu khách hàng từ file CSV để nạp hàng loạt.
155
+
156
+ **Tiêu chí chấp nhận:**
157
+ - Click nút **"Import Customers"** trên trang danh sách → chuyển đến `/admin/clients/import`.
158
+ - Trang Import hiển thị:
159
+ - **Hướng dẫn**: Yêu cầu file CSV, mã hóa UTF-8, định dạng ngày `Y-m-d`, tránh import email trùng lặp.
160
+ - **Nút "Download Sample"**: Tải file CSV mẫu.
161
+ - **Danh sách cột dữ liệu** (các trường bắt buộc đánh dấu `*`):
162
+ - Bắt buộc: `Firstname*`, `Lastname*`, `Email*`, `Company*`
163
+ - Không bắt buộc: `Contact phonenumber`, `Position`, `Vat`, `Phonenumber`, `Country`, `City`, `Zip`, `State`, `Address`
164
+ - **Trường chọn file CSV** (Choose CSV File).
165
+ - **Dropdown Groups**: Chọn nhóm để gán cho khách hàng import.
166
+ - **Trường "Default password for all contacts"**: Mật khẩu mặc định cho contacts mới.
167
+ - Có 2 nút chức năng:
168
+ - **"Import"**: Thực hiện import dữ liệu thực.
169
+ - **"Simulate Import"**: Chạy giả lập để kiểm tra lỗi trước khi import thật.
170
+
171
+ ---
172
+
173
+ ### FR-CUST-007: Export Dữ Liệu Khách Hàng (Export Customers)
174
+
175
+ **Mô tả:** Là một Admin, tôi muốn xuất dữ liệu khách hàng ra các định dạng khác nhau.
176
+
177
+ **Tiêu chí chấp nhận:**
178
+ - Click nút **"Export"** trên bảng dữ liệu → hiển thị dropdown với 4 tùy chọn:
179
+ - **Excel** (.xlsx)
180
+ - **CSV** (.csv)
181
+ - **PDF** (.pdf)
182
+ - **Print** (In trực tiếp từ trình duyệt)
183
+
184
+ ---
185
+
186
+ ### FR-CUST-008: Thao Tác Hàng Loạt (Bulk Actions)
187
+
188
+ **Mô tả:** Là một Admin, tôi muốn thực hiện các thao tác hàng loạt trên nhiều khách hàng cùng lúc.
189
+
190
+ **Tiêu chí chấp nhận:**
191
+ - Chọn ít nhất 1 khách hàng bằng checkbox trong bảng.
192
+ - Click nút **"Bulk Actions"** → hiển thị modal dialog với:
193
+ - **Checkbox "Mass Delete"**: Đánh dấu để xóa hàng loạt các khách hàng đã chọn.
194
+ - **Dropdown "Groups"**: Gán nhóm cho các khách hàng đã chọn.
195
+ - **Cảnh báo**: _"If you do not select any group all groups assigned to the selected customers will be removed."_ (Nếu không chọn nhóm nào, tất cả nhóm đã gán cho khách hàng sẽ bị gỡ bỏ).
196
+ - **Nút "Confirm"**: Xác nhận thực hiện thao tác.
197
+ - **Nút "Close"**: Đóng modal mà không thực hiện.
198
+
199
+ ---
200
+
201
+ ### FR-CUST-009: Tìm Kiếm & Lọc Dữ Liệu (Search & Filter)
202
+
203
+ **Mô tả:** Là một Admin, tôi muốn tìm kiếm và lọc danh sách khách hàng theo nhiều tiêu chí.
204
+
205
+ **Tiêu chí chấp nhận:**
206
+
207
+ #### Tìm kiếm nhanh:
208
+ - Ô tìm kiếm (**"Search..."**) ở góc phải trên bảng.
209
+ - Tìm kiếm real-time khi nhập ký tự.
210
+
211
+ #### Bộ lọc nâng cao (Filter):
212
+ - Click biểu tượng **filter** (hình phễu) ở góc phải trên cùng trang.
213
+ - Chọn **"New Filter"** → hiển thị giao diện tạo bộ lọc.
214
+ - Sử dụng **"Add Rule"** để thêm các tiêu chí lọc.
215
+
216
+ **Các tiêu chí lọc khả dụng:**
217
+
218
+ | Nhóm | Tiêu chí |
219
+ |:-----|:---------|
220
+ | Thông tin cơ bản | Phone, Active (trạng thái), City, Zip Code, State, Country |
221
+ | Liên kết dữ liệu | Invoices, Estimates, Proposals, Projects, Contract Types, Groups |
222
+ | Phân quyền | Responsible Admin, Customers assigned to me |
223
+ | Trạng thái đặc biệt | Requires Registration Confirmation |
224
+
225
+ ---
226
+
227
+ ## 3. Đặc Tả Trường Dữ Liệu (Field Specifications)
228
+
229
+ ### 3.1. Tab Customer Details (Thông tin khách hàng)
230
+
231
+ | Tên Trường (Label) | Loại (UI Type) | Bắt Buộc | ID/Selector | Giá Trị Mặc Định | Ràng Buộc/Ghi Chú |
232
+ |:--------------------|:---------------|:---------|:------------|:------------------|:-------------------|
233
+ | **Company** | Text Input | **Có (*)** | `company` | — | Trường bắt buộc duy nhất. Validation message: `"This field is required."` |
234
+ | **VAT Number** | Text Input | Không | `vat` | — | Mã số thuế GTGT |
235
+ | **Phone** | Text Input | Không | `phonenumber` | — | Số điện thoại công ty |
236
+ | **Website** | Text Input | Không | `website` | — | URL website. Có nút icon 🌐 mở link ngoài |
237
+ | **Groups** | Dropdown (Multi-select) | Không | `groups` | Nothing selected | Cho phép chọn nhiều nhóm. Có nút **"+"** để thêm nhóm mới nhanh |
238
+ | **Currency** | Dropdown (Single-select) | Không | `default_currency` | System Default | Danh sách các loại tiền tệ (VD: USD, VND, EUR...) |
239
+ | **Default Language** | Dropdown (Single-select) | Không | `default_language` | System Default | Danh sách ngôn ngữ (VD: Vietnamese, English...) |
240
+ | **Address** | Textarea | Không | `address` | — | Địa chỉ chi tiết, có thể nhập nhiều dòng |
241
+ | **City** | Text Input | Không | `city` | — | Tên thành phố |
242
+ | **State** | Text Input | Không | `state` | — | Tên tỉnh/bang |
243
+ | **Zip Code** | Text Input | Không | `zip` | — | Mã bưu điện |
244
+ | **Country** | Dropdown (Single-select) | Không | `country` | Nothing selected | Danh sách các quốc gia |
245
+
246
+ ---
247
+
248
+ ### 3.2. Tab Billing & Shipping (Địa chỉ Thanh Toán & Giao Hàng)
249
+
250
+ Tab này chia thành 2 cột song song: **Billing Address** (trái) và **Shipping Address** (phải).
251
+
252
+ #### Chức năng copy nhanh:
253
+ - **"Same as Customer Info"**: Copy thông tin địa chỉ từ tab Customer Details sang Billing Address.
254
+ - **"Copy Billing Address"**: Copy thông tin Billing Address sang Shipping Address.
255
+
256
+ #### Billing Address (Địa chỉ Thanh Toán):
257
+
258
+ | Tên Trường | Loại | Bắt Buộc | ID/Selector |
259
+ |:-----------|:-----|:---------|:------------|
260
+ | Street | Textarea | Không | `billing_street` |
261
+ | City | Text Input | Không | `billing_city` |
262
+ | State | Text Input | Không | `billing_state` |
263
+ | Zip Code | Text Input | Không | `billing_zip` |
264
+ | Country | Dropdown | Không | `billing_country` |
265
+
266
+ #### Shipping Address (Địa chỉ Giao Hàng):
267
+
268
+ | Tên Trường | Loại | Bắt Buộc | ID/Selector |
269
+ |:-----------|:-----|:---------|:------------|
270
+ | Street | Textarea | Không | `shipping_street` |
271
+ | City | Text Input | Không | `shipping_city` |
272
+ | State | Text Input | Không | `shipping_state` |
273
+ | Zip Code | Text Input | Không | `shipping_zip` |
274
+ | Country | Dropdown | Không | `shipping_country` |
275
+
276
+ ---
277
+
278
+ ### 3.3. Import Customers — Đặc Tả Cột Dữ Liệu
279
+
280
+ | Tên Cột (Column) | Bắt Buộc | Ghi Chú |
281
+ |:------------------|:---------|:--------|
282
+ | **Firstname** | **Có (*)** | Tên (first name) của liên hệ |
283
+ | **Lastname** | **Có (*)** | Họ (last name) của liên hệ |
284
+ | **Email** | **Có (*)** | Email liên hệ. Kiểm tra trùng lặp khi import |
285
+ | **Company** | **Có (*)** | Tên công ty khách hàng |
286
+ | Contact phonenumber | Không | Số điện thoại liên hệ |
287
+ | Position | Không | Chức vụ |
288
+ | Vat | Không | Mã số thuế |
289
+ | Phonenumber | Không | Số điện thoại công ty |
290
+ | Country | Không | Quốc gia |
291
+ | City | Không | Thành phố |
292
+ | Zip | Không | Mã bưu điện |
293
+ | State | Không | Tỉnh/bang |
294
+ | Address | Không | Địa chỉ |
295
+
296
+ ---
297
+
298
+ ### 3.4. Bảng Customers — Đặc Tả Cột Danh Sách
299
+
300
+ | Tên Cột | Mô Tả | Sắp Xếp | Ghi Chú |
301
+ |:---------|:------|:---------|:--------|
302
+ | Checkbox | Chọn để thực hiện Bulk Actions | Không | Có checkbox "Chọn tất cả" ở header |
303
+ | **#** | ID khách hàng (tự động sinh) | Có | Số tăng dần |
304
+ | **Company** | Tên công ty | Có | Link dẫn đến chi tiết. Sắp xếp A-Z mặc định |
305
+ | **Primary Contact** | Liên hệ chính | Có | Hiển thị tên contact chính (nếu có) |
306
+ | **Primary Email** | Email chính | Có | Email của contact chính |
307
+ | **Phone** | Số điện thoại | Có | Link gọi điện |
308
+ | **Active** | Trạng thái hoạt động | Có | Toggle switch bật/tắt |
309
+ | **Groups** | Nhóm khách hàng | Có | Hiển thị dạng badge/tag |
310
+ | **Date Created** | Ngày tạo | Có | Format: `dd-mm-yyyy HH:mm:ss` |
311
+
312
+ ---
313
+
314
+ ## 4. Quy Tắc Nghiệp Vụ & Validation (Business Rules & Validations)
315
+
316
+ ### 4.1. Validation Khi Tạo/Chỉnh Sửa Khách Hàng
317
+
318
+ | Trường | Quy Tắc | Thông Báo Lỗi | Loại Validation |
319
+ |:-------|:--------|:---------------|:----------------|
320
+ | **Company** | Bắt buộc nhập, không được để trống | `"This field is required."` | Client-side (JavaScript) |
321
+
322
+ > **Ghi chú:** Dựa trên quan sát UI, chỉ có trường **Company** có validation bắt buộc phía client. Các trường còn lại đều không bắt buộc.
323
+
324
+ ### 4.2. Quy Tắc Import
325
+
326
+ | Quy Tắc | Mô Tả |
327
+ |:---------|:------|
328
+ | Định dạng file | Bắt buộc CSV, mã hóa UTF-8 |
329
+ | Định dạng ngày | `Y-m-d` (VD: 2026-04-03) |
330
+ | Trùng lặp Email | Hệ thống kiểm tra trùng lặp email khi import |
331
+ | Trường bắt buộc | `Firstname`, `Lastname`, `Email`, `Company` |
332
+ | Simulate Import | Cho phép chạy thử nghiệm trước khi import thật |
333
+ | Mật khẩu mặc định | Có thể thiết lập mật khẩu mặc định cho tất cả contacts khi import |
334
+
335
+ ### 4.3. Quy Tắc Bulk Actions
336
+
337
+ | Quy Tắc | Mô Tả |
338
+ |:---------|:------|
339
+ | Điều kiện kích hoạt | Phải chọn ít nhất 1 khách hàng bằng checkbox |
340
+ | Mass Delete | Checkbox cho phép xóa hàng loạt khách hàng đã chọn |
341
+ | Groups | Gán nhóm hàng loạt. Nếu không chọn nhóm nào → tất cả nhóm hiện tại sẽ bị gỡ bỏ |
342
+ | Xác nhận | Bắt buộc click **"Confirm"** để thực hiện |
343
+
344
+ ### 4.4. Quy Tắc Toggle Active
345
+
346
+ | Quy Tắc | Mô Tả |
347
+ |:---------|:------|
348
+ | Thao tác | Click toggle switch để bật/tắt trạng thái Active |
349
+ | Phạm vi | Thay đổi trạng thái ngay tại bảng danh sách, không cần vào chi tiết |
350
+ | Hiệu lực | Thay đổi được lưu ngay lập tức (không cần nhấn Save) |
351
+
352
+ ---
353
+
354
+ ## 5. Luồng Xử Lý Chính (User Flows)
355
+
356
+ ### 5.1. Luồng Tạo Mới Khách Hàng
357
+
358
+ ```
359
+ 1. Admin truy cập trang Customers (/admin/clients)
360
+ 2. Click nút "+ New Customer"
361
+ 3. Hệ thống chuyển đến form tạo mới (/admin/clients/client)
362
+ 4. Tab "Customer Details" hiển thị mặc định
363
+ 5. Admin nhập thông tin:
364
+ a. Nhập Company (bắt buộc)
365
+ b. Nhập các trường tùy chọn: VAT, Phone, Website, Groups, Currency, Language, Address...
366
+ 6. (Tùy chọn) Chuyển sang tab "Billing & Shipping" để nhập địa chỉ thanh toán/giao hàng
367
+ 7. Click "Save" hoặc "Save and create contact"
368
+ - Nếu thiếu Company → Hiển thị lỗi "This field is required."
369
+ - Nếu hợp lệ → Lưu thành công → Chuyển đến trang chi tiết khách hàng mới
370
+ ```
371
+
372
+ ### 5.2. Luồng Chỉnh Sửa Khách Hàng
373
+
374
+ ```
375
+ 1. Admin truy cập trang Customers
376
+ 2. Click vào tên Company trong bảng
377
+ 3. Hệ thống chuyển đến trang chi tiết (/admin/clients/client/{id})
378
+ 4. Tab "Profile" → Sub-tab "Customer Details" hiển thị mặc định
379
+ 5. Admin chỉnh sửa thông tin cần thiết
380
+ 6. Click "Save" để lưu thay đổi
381
+ ```
382
+
383
+ ### 5.3. Luồng Xóa Khách Hàng
384
+
385
+ ```
386
+ 1. Admin truy cập trang chi tiết khách hàng
387
+ 2. Click dropdown bên cạnh "#{ID} {Company Name}"
388
+ 3. Chọn "Delete"
389
+ 4. Hệ thống hiển thị hộp thoại xác nhận
390
+ 5. Xác nhận → Khách hàng bị xóa → Chuyển về danh sách
391
+ ```
392
+
393
+ ### 5.4. Luồng Import Khách Hàng
394
+
395
+ ```
396
+ 1. Admin truy cập trang Customers
397
+ 2. Click nút "Import Customers"
398
+ 3. Hệ thống chuyển đến trang Import (/admin/clients/import)
399
+ 4. (Tùy chọn) Click "Download Sample" để tải file mẫu
400
+ 5. Chuẩn bị file CSV theo cấu trúc yêu cầu
401
+ 6. Chọn file CSV (Choose CSV File)
402
+ 7. (Tùy chọn) Chọn Groups và thiết lập Default Password
403
+ 8. Click "Simulate Import" để kiểm tra lỗi dữ liệu trước
404
+ 9. Nếu kết quả mô phỏng OK → Click "Import" để thực hiện import thật
405
+ ```
406
+
407
+ ### 5.5. Luồng Export Dữ Liệu
408
+
409
+ ```
410
+ 1. Admin truy cập trang Customers
411
+ 2. Click nút "Export" trên bảng dữ liệu
412
+ 3. Chọn định dạng: Excel / CSV / PDF / Print
413
+ 4. Hệ thống tải file hoặc mở cửa sổ in
414
+ ```
415
+
416
+ ### 5.6. Luồng Thao Tác Hàng Loạt (Bulk Actions)
417
+
418
+ ```
419
+ 1. Admin truy cập trang Customers
420
+ 2. Chọn một hoặc nhiều khách hàng bằng checkbox
421
+ 3. Click nút "Bulk Actions"
422
+ 4. Modal dialog hiển thị:
423
+ a. Đánh dấu "Mass Delete" nếu muốn xóa hàng loạt
424
+ b. Chọn Groups nếu muốn gán nhóm hàng loạt
425
+ 5. Click "Confirm" để thực hiện
426
+ ```
427
+
428
+ ---
429
+
430
+ ## 6. Yêu Cầu Phi Chức Năng (Non-Functional Requirements)
431
+
432
+ | Yêu Cầu | Mô Tả |
433
+ |:---------|:------|
434
+ | **Responsive** | Giao diện tương thích trên Desktop (tối ưu 1920x1080) |
435
+ | **DataTable Performance** | Bảng dữ liệu hỗ trợ phân trang, tránh load toàn bộ dữ liệu cùng lúc |
436
+ | **Real-time Search** | Tìm kiếm nhanh real-time khi nhập ký tự |
437
+ | **Toggle Instant** | Toggle Active/Inactive lưu ngay lập tức không cần reload |
438
+ | **Sort Multi-column** | Hỗ trợ sắp xếp theo từng cột |
439
+ | **Browser Support** | Hỗ trợ các trình duyệt chính: Chrome, Firefox, Edge |
440
+
441
+ ---
442
+
443
+ ## 7. Câu Hỏi / Làm Rõ Với PO-User
444
+
445
+ > Các câu hỏi bên dưới cần được làm rõ với Product Owner vì không thể xác nhận chỉ từ UI:
446
+
447
+ | # | Câu Hỏi | Lý Do |
448
+ |:--|:--------|:------|
449
+ | 1 | Trường **Company** có ràng buộc về **độ dài tối đa** (maxlength) không? | Không quan sát được thuộc tính maxlength trên UI |
450
+ | 2 | Trường **Phone** có cần validation định dạng số điện thoại không? | Trên UI không có validation client-side cho trường này |
451
+ | 3 | Trường **Website** có cần validation định dạng URL hợp lệ không? | Không quan sát được validation |
452
+ | 4 | Trường **VAT Number** có cần kiểm tra định dạng theo quốc gia không? | Không có validation rõ ràng trên UI |
453
+ | 5 | Khi **xóa khách hàng**, dữ liệu liên quan (Invoices, Projects, Contacts...) có bị cascade xóa không? | Không thể xác nhận từ UI |
454
+ | 6 | Có giới hạn **số lượng contacts** cho mỗi khách hàng không? | Không quan sát được |
455
+ | 7 | Trường **Email** trong Import có kiểm tra định dạng email hợp lệ không? | Cần xác nhận server-side validation |
456
+ | 8 | Tab **Customer Admins** trong Profile có chức năng gì cụ thể? | Chưa inspect sâu tab này |
457
+ | 9 | Khi toggle **Active/Inactive**, có gửi notification hay email không? | Không quan sát được hành vi backend |
458
+ | 10 | **Quyền hạn (Permissions)**: Các vai trò khác (Staff, không phải Admin) có quyền thao tác gì trên module Customers? | Chỉ test với tài khoản Admin |
459
+
460
+ ---
461
+
462
+ > **Ghi chú cuối:** Tài liệu này được xây dựng dựa trên việc inspect trực tiếp giao diện UI bằng Playwright MCP với tài khoản Admin. Các quy tắc nghiệp vụ ẩn (server-side validation, business logic phức tạp) cần được xác nhận thêm với đội phát triển hoặc Product Owner.
@@ -0,0 +1,202 @@
1
+ # TÀI LIỆU YÊU CẦU - MODULE LOGIN
2
+
3
+ | Thông tin | Chi tiết |
4
+ |-----------|----------|
5
+ | Module | Login |
6
+ | Hệ thống | Perfex CRM - Anh Tester Demo |
7
+ | URL | https://crm.anhtester.com/admin/authentication |
8
+ | Ngày tạo | 2026-04-02 |
9
+
10
+ ---
11
+
12
+ ## 1. TỔNG QUAN
13
+
14
+ Module Login là cổng vào chính của hệ thống CRM Perfex. Người dùng phải xác thực thành công bằng Email và Mật khẩu trước khi truy cập vào Dashboard, Customers, Projects và các module khác.
15
+
16
+ Tính năng phụ trợ:
17
+ - Ghi nhớ đăng nhập (Remember me)
18
+ - Khôi phục mật khẩu (Forgot Password)
19
+ - Bảo vệ CSRF token
20
+
21
+ ---
22
+
23
+ ## 2. YÊU CẦU CHỨC NĂNG
24
+
25
+ ### 2.1. Đăng nhập (Login)
26
+
27
+ > Là một người dùng, tôi muốn đăng nhập bằng email và mật khẩu để truy cập trang quản trị CRM.
28
+
29
+ | ID | Tiêu chí chấp nhận |
30
+ |------|------|
31
+ | AC-01 | Nhập đúng Email và Password, click Login -> chuyển hướng đến Dashboard (/admin/) |
32
+ | AC-02 | Để trống Email -> thông báo "The Email Address field is required." |
33
+ | AC-03 | Để trống Password -> thông báo "The Password field is required." |
34
+ | AC-04 | Để trống cả hai trường -> hiển thị đồng thời cả hai thông báo AC-02 và AC-03 |
35
+ | AC-05 | Email sai định dạng (thiếu @) -> trình duyệt hiển thị cảnh báo HTML5 validation |
36
+ | AC-06 | Email/password sai -> thông báo "Invalid email or password" |
37
+ | AC-07 | Tick "Remember me" + đăng nhập thành công -> phiên được duy trì sau khi đóng trình duyệt |
38
+
39
+ ### 2.2. Khôi phục Mật khẩu (Forgot Password)
40
+
41
+ > Là một người dùng quên mật khẩu, tôi muốn yêu cầu gửi email khôi phục để lấy lại quyền truy cập.
42
+
43
+ | ID | Tiêu chí chấp nhận |
44
+ |------|------|
45
+ | AC-08 | Click "Forgot Password?" -> chuyển đến /admin/authentication/forgot_password |
46
+ | AC-09 | Nhập email hợp lệ + click "Confirm" -> hệ thống gửi email khôi phục |
47
+ | AC-10 | Để trống Email + click "Confirm" -> trình duyệt cảnh báo HTML5 (trường có required) |
48
+
49
+ ### 2.3. Đăng xuất (Logout)
50
+
51
+ | ID | Tiêu chí chấp nhận |
52
+ |------|------|
53
+ | AC-11 | Từ Dashboard, click profile dropdown -> chọn Logout -> chuyển về trang Login |
54
+
55
+ ---
56
+
57
+ ## 3. ĐẶC TẢ TRƯỜNG DỮ LIỆU
58
+
59
+ ### 3.1. Trang Login
60
+
61
+ | Tên trường | Loại UI | HTML Type | Bắt buộc | ID | Name | Ghi chú |
62
+ |------------|---------|-----------|----------|----|------|---------|
63
+ | Email Address | Textbox | email | Có (*) | email | email | Server-side validation + HTML5 email format. Class: form-control |
64
+ | Password | Textbox (masked) | password | Có (*) | password | password | Hiển thị dạng masked. Class: form-control |
65
+ | Remember me | Checkbox | checkbox | Không | remember | remember | Mặc định: không tick. Value = "estimate" |
66
+ | Login | Button | submit | N/A | N/A | N/A | Class: btn btn-primary btn-block |
67
+ | Forgot Password? | Link | anchor | N/A | N/A | N/A | Chuyển đến trang forgot_password |
68
+ | csrf_token_name | Hidden | hidden | N/A | N/A | csrf_token_name | CSRF token tự động sinh bởi server |
69
+
70
+ (*) Không có thuộc tính "required" trên HTML, nhưng server-side validation kiểm tra và trả lỗi nếu để trống.
71
+
72
+ ### 3.2. Trang Forgot Password
73
+
74
+ | Tên trường | Loại UI | HTML Type | Bắt buộc | ID | Name | Ghi chú |
75
+ |------------|---------|-----------|----------|----|------|---------|
76
+ | Email Address | Textbox | email | Có | email | email | Có thuộc tính "required" (client-side) |
77
+ | Confirm | Button | submit | N/A | N/A | N/A | Class: btn btn-primary btn-block |
78
+
79
+ ---
80
+
81
+ ## 4. LUỒNG XỬ LÝ
82
+
83
+ ### 4.1. Đăng nhập thành công (Happy Path)
84
+
85
+ 1. Truy cập https://crm.anhtester.com/admin/authentication
86
+ 2. Trang Login hiển thị form: Email, Password, Remember me, nút Login, link Forgot Password
87
+ 3. Nhập Email hợp lệ (vd: admin@example.com)
88
+ 4. Nhập Password đúng (vd: 123456)
89
+ 5. (Tùy chọn) Tick "Remember me"
90
+ 6. Click "Login"
91
+ 7. Xác thực thành công -> chuyển hướng đến Dashboard (https://crm.anhtester.com/admin/)
92
+ 8. Trang Dashboard hiển thị với tiêu đề "Dashboard"
93
+
94
+ ### 4.2. Thất bại - Để trống tất cả trường
95
+
96
+ 1. Truy cập trang Login
97
+ 2. Không nhập gì, click "Login"
98
+ 3. Hiển thị 2 thông báo lỗi server-side: "The Email Address field is required." và "The Password field is required."
99
+ 4. Thông báo trong `<div class="alert alert-danger text-center">`
100
+ 5. Vẫn ở lại trang Login
101
+
102
+ ### 4.3. Thất bại - Để trống Email
103
+
104
+ 1. Để trống Email, nhập Password bất kỳ
105
+ 2. Click "Login"
106
+ 3. Thông báo: "The Email Address field is required."
107
+
108
+ ### 4.4. Thất bại - Để trống Password
109
+
110
+ 1. Nhập Email hợp lệ, để trống Password
111
+ 2. Click "Login"
112
+ 3. Thông báo: "The Password field is required."
113
+
114
+ ### 4.5. Thất bại - Email sai định dạng
115
+
116
+ 1. Nhập Email không có @ (vd: "invalidemail")
117
+ 2. Click "Login"
118
+ 3. Trình duyệt chặn form, hiển thị HTML5 tooltip: "Please include an '@' in the email address."
119
+ 4. Đây là client-side validation, không phải server-side
120
+
121
+ ### 4.6. Thất bại - Sai tài khoản/mật khẩu
122
+
123
+ 1. Nhập Email hợp lệ nhưng sai (vd: wrong@example.com) + Password bất kỳ
124
+ 2. Click "Login"
125
+ 3. Thông báo server-side: "Invalid email or password"
126
+ 4. Thông báo chung, không tiết lộ email sai hay password sai (thiết kế bảo mật)
127
+
128
+ ### 4.7. Khôi phục mật khẩu
129
+
130
+ 1. Click "Forgot Password?" từ trang Login
131
+ 2. Chuyển đến /admin/authentication/forgot_password
132
+ 3. Nhập Email đã đăng ký
133
+ 4. Click "Confirm"
134
+ 5. Hệ thống gửi email hướng dẫn đặt lại mật khẩu
135
+
136
+ ---
137
+
138
+ ## 5. TỔNG HỢP THÔNG BÁO LỖI
139
+
140
+ | # | Thông báo | Loại | Điều kiện |
141
+ |---|-----------|------|-----------|
142
+ | 1 | The Email Address field is required. | Server-side (alert-danger) | Email để trống |
143
+ | 2 | The Password field is required. | Server-side (alert-danger) | Password để trống |
144
+ | 3 | Invalid email or password | Server-side (alert-danger) | Email/password sai |
145
+ | 4 | Please include an '@' in the email address. | Client-side (HTML5 tooltip) | Email thiếu @ |
146
+
147
+ - Server-side: hiển thị trong `<div class="alert alert-danger text-center">`, phía trên form
148
+ - Client-side: tooltip của trình duyệt khi input type="email" nhận giá trị không hợp lệ
149
+
150
+ ---
151
+
152
+ ## 6. CẤU TRÚC GIAO DIỆN
153
+
154
+ ```
155
+ +--------------------------------------------------+
156
+ | [Logo: Anh Tester - Automation Testing] |
157
+ | Login (H1) |
158
+ | +--------------------------------------------+ |
159
+ | | [Thông báo lỗi - nếu có] | |
160
+ | | Email Address | |
161
+ | | [____________________________________] | |
162
+ | | Password | |
163
+ | | [____________________________________] | |
164
+ | | [ ] Remember me | |
165
+ | | [=========== Login ===========] | |
166
+ | | Forgot Password? | |
167
+ | +--------------------------------------------+ |
168
+ +--------------------------------------------------+
169
+ ```
170
+
171
+ - Background: màu xám nhạt (#eef0f8)
172
+ - Form card: màu trắng, bo tròn, shadow nhẹ
173
+ - Nút Login: xanh dương (btn-primary), full width (btn-block)
174
+ - Link Forgot Password: màu cam, dưới nút Login
175
+
176
+ ---
177
+
178
+ ## 7. YÊU CẦU PHI CHỨC NĂNG
179
+
180
+ | ID | Nội dung |
181
+ |----|----------|
182
+ | NFR-01 | Bảo mật: CSRF token (trường ẩn csrf_token_name) |
183
+ | NFR-02 | Bảo mật: Password hiển thị dạng masked, không hiện plaintext |
184
+ | NFR-03 | Bảo mật: Thông báo chung "Invalid email or password" không tiết lộ tài khoản tồn tại |
185
+ | NFR-04 | Tương thích: HTML5 input type="email", Chrome/Firefox/Edge/Safari |
186
+ | NFR-05 | Giao diện: Responsive, Bootstrap (form-control, btn, alert) |
187
+ | NFR-06 | Hiệu năng: Form POST /admin/authentication, tải nhanh |
188
+
189
+ ---
190
+
191
+ ## 8. CÂU HỎI CẦN LÀM RÕ VỚI PO/USER
192
+
193
+ | ID | Câu hỏi |
194
+ |----|---------|
195
+ | Q-01 | Có giới hạn số lần đăng nhập sai liên tiếp không? (Account lockout) |
196
+ | Q-02 | Có yêu cầu độ phức tạp mật khẩu tối thiểu không? |
197
+ | Q-03 | "Remember me" duy trì phiên trong bao lâu? |
198
+ | Q-04 | Link khôi phục mật khẩu có thời hạn hết hạn không? |
199
+ | Q-05 | Có hỗ trợ Social Login / SSO không? |
200
+ | Q-06 | Có CAPTCHA sau nhiều lần đăng nhập thất bại không? |
201
+ | Q-07 | Email có giới hạn độ dài tối đa không? (HTML không có maxlength) |
202
+ | Q-08 | Password có giới hạn độ dài min/max không? (HTML không có minlength/maxlength) |