bps-kit 1.0.1 → 1.0.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 (368) hide show
  1. package/package.json +1 -1
  2. package/templates/.agents/agents/backend-specialist.md +263 -0
  3. package/templates/.agents/agents/code-archaeologist.md +106 -0
  4. package/templates/.agents/agents/database-architect.md +226 -0
  5. package/templates/.agents/agents/debugger.md +225 -0
  6. package/templates/.agents/agents/devops-engineer.md +242 -0
  7. package/templates/.agents/agents/documentation-writer.md +104 -0
  8. package/templates/.agents/agents/explorer-agent.md +73 -0
  9. package/templates/.agents/agents/frontend-specialist.md +593 -0
  10. package/templates/.agents/agents/game-developer.md +162 -0
  11. package/templates/.agents/agents/mobile-developer.md +377 -0
  12. package/templates/.agents/agents/orchestrator.md +416 -0
  13. package/templates/.agents/agents/penetration-tester.md +188 -0
  14. package/templates/.agents/agents/performance-optimizer.md +187 -0
  15. package/templates/.agents/agents/product-manager.md +112 -0
  16. package/templates/.agents/agents/product-owner.md +95 -0
  17. package/templates/.agents/agents/project-planner.md +406 -0
  18. package/templates/.agents/agents/qa-automation-engineer.md +103 -0
  19. package/templates/.agents/agents/security-auditor.md +170 -0
  20. package/templates/.agents/agents/seo-specialist.md +111 -0
  21. package/templates/.agents/agents/test-engineer.md +158 -0
  22. package/templates/.agents/rules/GEMINI.md +219 -0
  23. package/templates/.agents/scripts/auto_preview.py +148 -0
  24. package/templates/.agents/scripts/checklist.py +217 -0
  25. package/templates/.agents/scripts/session_manager.py +120 -0
  26. package/templates/.agents/scripts/verify_all.py +327 -0
  27. package/templates/.agents/workflows/brainstorm.md +113 -0
  28. package/templates/.agents/workflows/create.md +59 -0
  29. package/templates/.agents/workflows/debug.md +103 -0
  30. package/templates/.agents/workflows/deploy.md +176 -0
  31. package/templates/.agents/workflows/enhance.md +63 -0
  32. package/templates/.agents/workflows/orchestrate.md +237 -0
  33. package/templates/.agents/workflows/plan.md +89 -0
  34. package/templates/.agents/workflows/preview.md +81 -0
  35. package/templates/.agents/workflows/setup-brain.md +39 -0
  36. package/templates/.agents/workflows/status.md +86 -0
  37. package/templates/.agents/workflows/test.md +144 -0
  38. package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
  39. package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
  40. package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
  41. package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
  42. package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
  43. package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
  44. package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
  45. package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
  46. package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
  47. package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  48. package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  49. package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
  50. package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
  51. package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
  52. package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
  53. package/templates/vault/007/scripts/config.py +472 -0
  54. package/templates/vault/007/scripts/full_audit.py +1306 -0
  55. package/templates/vault/007/scripts/quick_scan.py +481 -0
  56. package/templates/vault/007/scripts/requirements.txt +26 -0
  57. package/templates/vault/007/scripts/scanners/__init__.py +0 -0
  58. package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
  59. package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
  60. package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
  61. package/templates/vault/007/scripts/score_calculator.py +693 -0
  62. package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
  63. package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
  64. package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
  65. package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
  66. package/templates/vault/ai-studio-image/scripts/config.py +613 -0
  67. package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
  68. package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
  69. package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
  70. package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
  71. package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
  72. package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
  73. package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
  74. package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
  75. package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
  76. package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
  77. package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
  78. package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
  79. package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
  80. package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
  81. package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
  82. package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
  83. package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
  84. package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
  85. package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
  86. package/templates/vault/claude-monitor/scripts/config.py +69 -0
  87. package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
  88. package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
  89. package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
  90. package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
  91. package/templates/vault/context-agent/scripts/active_context.py +227 -0
  92. package/templates/vault/context-agent/scripts/compressor.py +149 -0
  93. package/templates/vault/context-agent/scripts/config.py +69 -0
  94. package/templates/vault/context-agent/scripts/context_loader.py +155 -0
  95. package/templates/vault/context-agent/scripts/context_manager.py +302 -0
  96. package/templates/vault/context-agent/scripts/models.py +103 -0
  97. package/templates/vault/context-agent/scripts/project_registry.py +132 -0
  98. package/templates/vault/context-agent/scripts/requirements.txt +6 -0
  99. package/templates/vault/context-agent/scripts/search.py +115 -0
  100. package/templates/vault/context-agent/scripts/session_parser.py +206 -0
  101. package/templates/vault/context-agent/scripts/session_summary.py +319 -0
  102. package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
  103. package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
  104. package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
  105. package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
  106. package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
  107. package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
  108. package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
  109. package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
  110. package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
  111. package/templates/vault/docx/scripts/__init__.py +1 -0
  112. package/templates/vault/docx/scripts/document.py +1276 -0
  113. package/templates/vault/docx/scripts/templates/comments.xml +3 -0
  114. package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
  115. package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
  116. package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
  117. package/templates/vault/docx/scripts/templates/people.xml +3 -0
  118. package/templates/vault/docx/scripts/utilities.py +374 -0
  119. package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
  120. package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
  121. package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
  122. package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
  123. package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
  124. package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
  125. package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
  126. package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
  127. package/templates/vault/docx-official/scripts/__init__.py +1 -0
  128. package/templates/vault/docx-official/scripts/document.py +1276 -0
  129. package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
  130. package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
  131. package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
  132. package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
  133. package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
  134. package/templates/vault/docx-official/scripts/utilities.py +374 -0
  135. package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
  136. package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
  137. package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
  138. package/templates/vault/instagram/scripts/account_setup.py +233 -0
  139. package/templates/vault/instagram/scripts/analyze.py +221 -0
  140. package/templates/vault/instagram/scripts/api_client.py +444 -0
  141. package/templates/vault/instagram/scripts/auth.py +411 -0
  142. package/templates/vault/instagram/scripts/comments.py +160 -0
  143. package/templates/vault/instagram/scripts/config.py +111 -0
  144. package/templates/vault/instagram/scripts/db.py +467 -0
  145. package/templates/vault/instagram/scripts/export.py +138 -0
  146. package/templates/vault/instagram/scripts/governance.py +233 -0
  147. package/templates/vault/instagram/scripts/hashtags.py +114 -0
  148. package/templates/vault/instagram/scripts/insights.py +170 -0
  149. package/templates/vault/instagram/scripts/media.py +65 -0
  150. package/templates/vault/instagram/scripts/messages.py +103 -0
  151. package/templates/vault/instagram/scripts/profile.py +58 -0
  152. package/templates/vault/instagram/scripts/publish.py +449 -0
  153. package/templates/vault/instagram/scripts/requirements.txt +5 -0
  154. package/templates/vault/instagram/scripts/run_all.py +189 -0
  155. package/templates/vault/instagram/scripts/schedule.py +189 -0
  156. package/templates/vault/instagram/scripts/serve_api.py +234 -0
  157. package/templates/vault/instagram/scripts/templates.py +155 -0
  158. package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
  159. package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
  160. package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
  161. package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
  162. package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
  163. package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
  164. package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
  165. package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
  166. package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
  167. package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
  168. package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
  169. package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
  170. package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
  171. package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
  172. package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
  173. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
  174. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
  175. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
  176. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
  177. package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
  178. package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
  179. package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
  180. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
  181. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
  182. package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
  183. package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
  184. package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
  185. package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
  186. package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
  187. package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
  188. package/templates/vault/last30days/scripts/last30days.py +521 -0
  189. package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
  190. package/templates/vault/last30days/scripts/lib/cache.py +152 -0
  191. package/templates/vault/last30days/scripts/lib/dates.py +124 -0
  192. package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
  193. package/templates/vault/last30days/scripts/lib/env.py +149 -0
  194. package/templates/vault/last30days/scripts/lib/http.py +152 -0
  195. package/templates/vault/last30days/scripts/lib/models.py +175 -0
  196. package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
  197. package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
  198. package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
  199. package/templates/vault/last30days/scripts/lib/render.py +383 -0
  200. package/templates/vault/last30days/scripts/lib/schema.py +336 -0
  201. package/templates/vault/last30days/scripts/lib/score.py +311 -0
  202. package/templates/vault/last30days/scripts/lib/ui.py +324 -0
  203. package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
  204. package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
  205. package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
  206. package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
  207. package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
  208. package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
  209. package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
  210. package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
  211. package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
  212. package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
  213. package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
  214. package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
  215. package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
  216. package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
  217. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
  218. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
  219. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
  220. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
  221. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
  222. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
  223. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
  224. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
  225. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
  226. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
  227. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
  228. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
  229. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
  230. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
  231. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
  232. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
  233. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
  234. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
  235. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
  236. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
  237. package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
  238. package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
  239. package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
  240. package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
  241. package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
  242. package/templates/vault/mcp-builder/scripts/connections.py +151 -0
  243. package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
  244. package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
  245. package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
  246. package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
  247. package/templates/vault/notebooklm/scripts/__init__.py +81 -0
  248. package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
  249. package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
  250. package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
  251. package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
  252. package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
  253. package/templates/vault/notebooklm/scripts/config.py +44 -0
  254. package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
  255. package/templates/vault/notebooklm/scripts/run.py +102 -0
  256. package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
  257. package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
  258. package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
  259. package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
  260. package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
  261. package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
  262. package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
  263. package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
  264. package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  265. package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
  266. package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
  267. package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
  268. package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
  269. package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
  270. package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
  271. package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
  272. package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
  273. package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
  274. package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
  275. package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
  276. package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
  277. package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
  278. package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
  279. package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
  280. package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
  281. package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
  282. package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
  283. package/templates/vault/pptx/scripts/html2pptx.js +979 -0
  284. package/templates/vault/pptx/scripts/inventory.py +1020 -0
  285. package/templates/vault/pptx/scripts/rearrange.py +231 -0
  286. package/templates/vault/pptx/scripts/replace.py +385 -0
  287. package/templates/vault/pptx/scripts/thumbnail.py +450 -0
  288. package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
  289. package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
  290. package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
  291. package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
  292. package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
  293. package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
  294. package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
  295. package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
  296. package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
  297. package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
  298. package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
  299. package/templates/vault/pptx-official/scripts/replace.py +385 -0
  300. package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
  301. package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
  302. package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
  303. package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
  304. package/templates/vault/scripts/.skill_cache.json +7538 -0
  305. package/templates/vault/scripts/skill_search.py +228 -0
  306. package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
  307. package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
  308. package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
  309. package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
  310. package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
  311. package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
  312. package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
  313. package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
  314. package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
  315. package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
  316. package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
  317. package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
  318. package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
  319. package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
  320. package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
  321. package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
  322. package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
  323. package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
  324. package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
  325. package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
  326. package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
  327. package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
  328. package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
  329. package/templates/vault/skill-sentinel/scripts/config.py +158 -0
  330. package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
  331. package/templates/vault/skill-sentinel/scripts/db.py +354 -0
  332. package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
  333. package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
  334. package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
  335. package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
  336. package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
  337. package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
  338. package/templates/vault/stability-ai/scripts/config.py +266 -0
  339. package/templates/vault/stability-ai/scripts/generate.py +687 -0
  340. package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
  341. package/templates/vault/stability-ai/scripts/styles.py +174 -0
  342. package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
  343. package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
  344. package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
  345. package/templates/vault/telegram/scripts/send_message.py +143 -0
  346. package/templates/vault/telegram/scripts/setup_project.py +103 -0
  347. package/templates/vault/telegram/scripts/test_bot.py +144 -0
  348. package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
  349. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  350. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  351. package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
  352. package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
  353. package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
  354. package/templates/vault/videodb/scripts/ws_listener.py +204 -0
  355. package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  356. package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  357. package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  358. package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
  359. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
  360. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
  361. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
  362. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
  363. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
  364. package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
  365. package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
  366. package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
  367. package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
  368. package/templates/vault/youtube-summarizer/scripts/install-dependencies.sh +28 -0
@@ -0,0 +1,1306 @@
1
+ """007 Full Audit -- Comprehensive 6-phase security audit orchestrator.
2
+
3
+ Executes the complete 007 security audit pipeline:
4
+ Phase 1: Surface Mapping -- file inventory, entry points, dependencies
5
+ Phase 2: Threat Modeling Hints -- identify components for STRIDE analysis
6
+ Phase 3: Security Checklist -- run all scanners, compile results
7
+ Phase 4: Red Team Scenarios -- template-based attack scenarios
8
+ Phase 5: Blue Team Recs -- hardening recommendations per finding
9
+ Phase 6: Verdict -- compute score and emit final verdict
10
+
11
+ Generates a comprehensive Markdown report saved to data/reports/ and prints
12
+ a summary to stdout.
13
+
14
+ Usage:
15
+ python full_audit.py --target /path/to/project
16
+ python full_audit.py --target /path/to/project --output markdown
17
+ python full_audit.py --target /path/to/project --phase 3 --verbose
18
+ python full_audit.py --target /path/to/project --output json
19
+ """
20
+
21
+ import argparse
22
+ import json
23
+ import os
24
+ import re
25
+ import sys
26
+ import time
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Imports from the 007 config hub (same directory)
32
+ # ---------------------------------------------------------------------------
33
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
34
+
35
+ from config import ( # noqa: E402
36
+ BASE_DIR,
37
+ DATA_DIR,
38
+ REPORTS_DIR,
39
+ SCANNABLE_EXTENSIONS,
40
+ SKIP_DIRECTORIES,
41
+ SCORING_WEIGHTS,
42
+ SCORING_LABELS,
43
+ SEVERITY,
44
+ LIMITS,
45
+ ensure_directories,
46
+ get_verdict,
47
+ get_timestamp,
48
+ log_audit_event,
49
+ setup_logging,
50
+ calculate_weighted_score,
51
+ )
52
+
53
+ # ---------------------------------------------------------------------------
54
+ # Import scanners
55
+ # ---------------------------------------------------------------------------
56
+ sys.path.insert(0, str(Path(__file__).resolve().parent / "scanners"))
57
+
58
+ import secrets_scanner # noqa: E402
59
+ import dependency_scanner # noqa: E402
60
+ import injection_scanner # noqa: E402
61
+ import quick_scan # noqa: E402
62
+ import score_calculator # noqa: E402
63
+
64
+ # ---------------------------------------------------------------------------
65
+ # Logger
66
+ # ---------------------------------------------------------------------------
67
+ logger = setup_logging("007-full-audit")
68
+
69
+
70
+ # =========================================================================
71
+ # RED TEAM SCENARIO TEMPLATES
72
+ # =========================================================================
73
+ # Mapping from finding type/pattern -> attack scenario template.
74
+
75
+ _RED_TEAM_TEMPLATES: dict[str, dict] = {
76
+ # --- Secrets ---
77
+ "secret": {
78
+ "title": "Credential Theft via Leaked Secret",
79
+ "persona": "External attacker / Insider",
80
+ "scenario": (
81
+ "Attacker discovers leaked credential ({pattern}) in {file} "
82
+ "and uses it to gain unauthorized access to the associated "
83
+ "service or resource. Depending on the credential scope, "
84
+ "the attacker may escalate to full account takeover."
85
+ ),
86
+ "impact": "Unauthorized access, data exfiltration, lateral movement",
87
+ "difficulty": "Easy (if credential is in public repo) / Medium (if private)",
88
+ },
89
+ # --- Injection ---
90
+ "code_injection": {
91
+ "title": "Remote Code Execution via Code Injection",
92
+ "persona": "Malicious user / Compromised agent",
93
+ "scenario": (
94
+ "Attacker crafts malicious input targeting {pattern} in {file}. "
95
+ "The injected code executes in the server context, allowing "
96
+ "arbitrary command execution, data access, or system compromise."
97
+ ),
98
+ "impact": "Full server compromise, data breach, service disruption",
99
+ "difficulty": "Medium",
100
+ },
101
+ "command_injection": {
102
+ "title": "System Compromise via Command Injection",
103
+ "persona": "Malicious user / API abuser",
104
+ "scenario": (
105
+ "Attacker injects OS commands through {pattern} in {file}. "
106
+ "The shell executes attacker-controlled commands, enabling "
107
+ "file access, reverse shells, or privilege escalation."
108
+ ),
109
+ "impact": "Full system compromise, lateral movement",
110
+ "difficulty": "Medium",
111
+ },
112
+ "sql_injection": {
113
+ "title": "Data Breach via SQL Injection",
114
+ "persona": "Malicious user / Bot",
115
+ "scenario": (
116
+ "Attacker crafts SQL payload targeting {pattern} in {file}. "
117
+ "The malformed query bypasses authentication, extracts sensitive "
118
+ "data, modifies records, or drops tables."
119
+ ),
120
+ "impact": "Data breach, data loss, authentication bypass",
121
+ "difficulty": "Easy to Medium",
122
+ },
123
+ "prompt_injection": {
124
+ "title": "AI Manipulation via Prompt Injection",
125
+ "persona": "Malicious user / Compromised data source",
126
+ "scenario": (
127
+ "Attacker injects adversarial prompt through {pattern} in {file}. "
128
+ "The LLM follows injected instructions, potentially exfiltrating "
129
+ "data, bypassing safety controls, or performing unauthorized actions."
130
+ ),
131
+ "impact": "Data leakage, unauthorized actions, reputation damage",
132
+ "difficulty": "Easy to Medium",
133
+ },
134
+ "xss": {
135
+ "title": "User Account Takeover via XSS",
136
+ "persona": "Malicious user",
137
+ "scenario": (
138
+ "Attacker injects JavaScript through {pattern} in {file}. "
139
+ "The script executes in victim browsers, stealing session tokens, "
140
+ "redirecting users, or performing actions on their behalf."
141
+ ),
142
+ "impact": "Session hijacking, credential theft, phishing",
143
+ "difficulty": "Easy",
144
+ },
145
+ "ssrf": {
146
+ "title": "Internal Network Scanning via SSRF",
147
+ "persona": "External attacker",
148
+ "scenario": (
149
+ "Attacker manipulates server-side request through {pattern} in {file}. "
150
+ "The server makes requests to internal services, cloud metadata endpoints, "
151
+ "or other internal resources on the attacker's behalf."
152
+ ),
153
+ "impact": "Internal network exposure, cloud credential theft, data access",
154
+ "difficulty": "Medium",
155
+ },
156
+ "path_traversal": {
157
+ "title": "Sensitive File Access via Path Traversal",
158
+ "persona": "Malicious user",
159
+ "scenario": (
160
+ "Attacker uses directory traversal sequences (../) through {pattern} "
161
+ "in {file} to access files outside the intended directory, "
162
+ "including configuration files, credentials, or system files."
163
+ ),
164
+ "impact": "Credential exposure, configuration leak, source code theft",
165
+ "difficulty": "Easy",
166
+ },
167
+ # --- Dependencies ---
168
+ "dependency": {
169
+ "title": "Supply Chain Attack via Vulnerable Dependency",
170
+ "persona": "Supply chain attacker",
171
+ "scenario": (
172
+ "Attacker compromises a dependency ({pattern}) used in {file}. "
173
+ "Malicious code in the dependency executes during install or runtime, "
174
+ "exfiltrating secrets, installing backdoors, or modifying behavior."
175
+ ),
176
+ "impact": "Full compromise, backdoor installation, data exfiltration",
177
+ "difficulty": "Hard (requires compromising upstream package)",
178
+ },
179
+ # --- Auth missing ---
180
+ "no_auth": {
181
+ "title": "Unauthorized Access to Unprotected Endpoints",
182
+ "persona": "Any external attacker / Bot",
183
+ "scenario": (
184
+ "Attacker discovers unprotected API endpoints or routes "
185
+ "with no authentication middleware. Direct access allows "
186
+ "data extraction, modification, or service abuse without credentials."
187
+ ),
188
+ "impact": "Data breach, unauthorized actions, resource abuse",
189
+ "difficulty": "Easy",
190
+ },
191
+ # --- Dangerous code ---
192
+ "dangerous_code": {
193
+ "title": "Exploitation of Dangerous Code Pattern",
194
+ "persona": "Malicious user / Insider",
195
+ "scenario": (
196
+ "Attacker exploits dangerous code construct ({pattern}) in {file}. "
197
+ "The construct allows unintended behavior such as arbitrary code "
198
+ "execution, deserialization attacks, or unsafe data processing."
199
+ ),
200
+ "impact": "Code execution, data manipulation, service disruption",
201
+ "difficulty": "Medium",
202
+ },
203
+ }
204
+
205
+ # Fallback template for finding types not explicitly mapped
206
+ _RED_TEAM_FALLBACK = {
207
+ "title": "Exploitation of Security Weakness",
208
+ "persona": "Opportunistic attacker",
209
+ "scenario": (
210
+ "Attacker discovers and exploits security weakness ({pattern}) "
211
+ "in {file}. The specific impact depends on the context and "
212
+ "the attacker's capabilities."
213
+ ),
214
+ "impact": "Variable -- depends on finding severity and context",
215
+ "difficulty": "Variable",
216
+ }
217
+
218
+
219
+ # =========================================================================
220
+ # BLUE TEAM RECOMMENDATION TEMPLATES
221
+ # =========================================================================
222
+
223
+ _BLUE_TEAM_TEMPLATES: dict[str, dict] = {
224
+ "secret": {
225
+ "recommendation": (
226
+ "Move secrets to environment variables, a secrets manager (e.g. AWS "
227
+ "Secrets Manager, HashiCorp Vault), or a .env file excluded from "
228
+ "version control. Add a pre-commit hook (e.g. detect-secrets, "
229
+ "gitleaks) to prevent future leaks. Rotate the compromised credential "
230
+ "immediately."
231
+ ),
232
+ "priority": "CRITICAL",
233
+ "effort": "Low",
234
+ },
235
+ "code_injection": {
236
+ "recommendation": (
237
+ "Remove all uses of eval(), exec(), and Function(). If dynamic "
238
+ "code execution is absolutely necessary, use a sandboxed environment "
239
+ "(e.g. RestrictedPython, vm2 in strict mode) with allowlisted "
240
+ "operations only. Never pass user input to code execution functions."
241
+ ),
242
+ "priority": "CRITICAL",
243
+ "effort": "Medium",
244
+ },
245
+ "command_injection": {
246
+ "recommendation": (
247
+ "Replace os.system(), os.popen(), and subprocess with shell=True "
248
+ "with subprocess.run() using shell=False and a list of arguments. "
249
+ "Never concatenate user input into shell commands. Validate and "
250
+ "sanitize all inputs. Use shlex.quote() if shell is unavoidable."
251
+ ),
252
+ "priority": "CRITICAL",
253
+ "effort": "Low to Medium",
254
+ },
255
+ "sql_injection": {
256
+ "recommendation": (
257
+ "Use parameterized queries (placeholders) for ALL database operations. "
258
+ "Never use f-strings, .format(), or string concatenation in SQL. "
259
+ "Use an ORM (SQLAlchemy, Django ORM) when possible. Add input "
260
+ "validation and type checking before database operations."
261
+ ),
262
+ "priority": "CRITICAL",
263
+ "effort": "Low",
264
+ },
265
+ "prompt_injection": {
266
+ "recommendation": (
267
+ "Separate system prompts from user content using proper message "
268
+ "structure (system/user/assistant roles). Never concatenate user "
269
+ "input directly into system prompts. Add input sanitization, "
270
+ "output filtering, and content safety guardrails. Limit tool "
271
+ "access and implement output validation."
272
+ ),
273
+ "priority": "HIGH",
274
+ "effort": "Medium",
275
+ },
276
+ "xss": {
277
+ "recommendation": (
278
+ "Never set innerHTML or use dangerouslySetInnerHTML with user content. "
279
+ "Use textContent for safe text insertion. Implement Content Security "
280
+ "Policy (CSP) headers. Use template engines with auto-escaping "
281
+ "(Jinja2 with autoescape, React JSX). Sanitize user HTML with "
282
+ "DOMPurify or bleach."
283
+ ),
284
+ "priority": "HIGH",
285
+ "effort": "Low to Medium",
286
+ },
287
+ "ssrf": {
288
+ "recommendation": (
289
+ "Implement URL allowlisting for outbound requests. Block requests "
290
+ "to private IP ranges (10.x, 172.16-31.x, 192.168.x), localhost, "
291
+ "and cloud metadata endpoints (169.254.169.254). Validate and "
292
+ "parse URLs before making requests. Use a dedicated HTTP client "
293
+ "with SSRF protections."
294
+ ),
295
+ "priority": "HIGH",
296
+ "effort": "Medium",
297
+ },
298
+ "path_traversal": {
299
+ "recommendation": (
300
+ "Use Path.resolve() and verify the resolved path starts with the "
301
+ "expected base directory. Never pass raw user input to open() or "
302
+ "file operations. Use os.path.realpath() followed by a prefix check. "
303
+ "Implement a file access allowlist."
304
+ ),
305
+ "priority": "HIGH",
306
+ "effort": "Low",
307
+ },
308
+ "dependency": {
309
+ "recommendation": (
310
+ "Pin all dependency versions with exact versions (not ranges). "
311
+ "Use lock files (pip freeze, package-lock.json, poetry.lock). "
312
+ "Run regular vulnerability scans (safety, npm audit, Snyk). "
313
+ "Remove unused dependencies. Verify package integrity with hashes."
314
+ ),
315
+ "priority": "MEDIUM",
316
+ "effort": "Low",
317
+ },
318
+ "dangerous_code": {
319
+ "recommendation": (
320
+ "Replace dangerous constructs with safe alternatives: "
321
+ "pickle -> json, yaml.load -> yaml.safe_load, eval -> ast.literal_eval "
322
+ "(for literals only). Add input validation before any dynamic operation. "
323
+ "Implement proper error handling and type checking."
324
+ ),
325
+ "priority": "HIGH",
326
+ "effort": "Low to Medium",
327
+ },
328
+ "no_auth": {
329
+ "recommendation": (
330
+ "Add authentication middleware to all endpoints except public "
331
+ "health checks. Implement RBAC/ABAC for authorization. Use "
332
+ "established auth libraries (Flask-Login, Passport.js, Django auth). "
333
+ "Add rate limiting to prevent brute force attacks."
334
+ ),
335
+ "priority": "CRITICAL",
336
+ "effort": "Medium",
337
+ },
338
+ "permission": {
339
+ "recommendation": (
340
+ "Set restrictive file permissions (600 for secrets, 644 for configs, "
341
+ "755 for executables). Never use 777. Run services as non-root users. "
342
+ "Use chown/chmod to enforce ownership."
343
+ ),
344
+ "priority": "MEDIUM",
345
+ "effort": "Low",
346
+ },
347
+ "large_file": {
348
+ "recommendation": (
349
+ "Investigate oversized files for accidentally committed binaries, "
350
+ "databases, or data dumps. Add them to .gitignore. Use Git LFS "
351
+ "for legitimate large files."
352
+ ),
353
+ "priority": "LOW",
354
+ "effort": "Low",
355
+ },
356
+ }
357
+
358
+ _BLUE_TEAM_FALLBACK = {
359
+ "recommendation": (
360
+ "Review the finding in context and apply the principle of least "
361
+ "privilege. Add input validation, proper error handling, and "
362
+ "logging. Consult OWASP guidelines for the specific vulnerability type."
363
+ ),
364
+ "priority": "MEDIUM",
365
+ "effort": "Variable",
366
+ }
367
+
368
+
369
+ # =========================================================================
370
+ # PHASE IMPLEMENTATIONS
371
+ # =========================================================================
372
+
373
+ def _phase1_surface_mapping(target: Path, verbose: bool = False) -> dict:
374
+ """Phase 1: Surface Mapping -- inventory files, entry points, dependencies."""
375
+ logger.info("Phase 1: Surface Mapping")
376
+
377
+ files_by_type: dict[str, int] = {}
378
+ entry_points: list[str] = []
379
+ dependency_files: list[str] = []
380
+ config_files: list[str] = []
381
+ total_files = 0
382
+
383
+ _entry_point_patterns = [
384
+ re.compile(r"""(?i)(?:^main\.py|^app\.py|^server\.py|^index\.\w+|^manage\.py)"""),
385
+ re.compile(r"""(?i)(?:^wsgi\.py|^asgi\.py|^gunicorn|^uvicorn)"""),
386
+ re.compile(r"""(?i)(?:^Dockerfile|^docker-compose)"""),
387
+ re.compile(r"""(?i)(?:\.github[/\\]workflows|Jenkinsfile|\.gitlab-ci)"""),
388
+ ]
389
+
390
+ _dep_file_names = {
391
+ "requirements.txt", "requirements-dev.txt", "requirements-test.txt",
392
+ "setup.py", "setup.cfg", "pyproject.toml", "Pipfile", "Pipfile.lock",
393
+ "package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml",
394
+ "go.mod", "go.sum", "Cargo.toml", "Cargo.lock",
395
+ "Gemfile", "Gemfile.lock", "composer.json", "composer.lock",
396
+ }
397
+
398
+ _config_extensions = {".json", ".yaml", ".yml", ".toml", ".ini", ".cfg", ".conf", ".env"}
399
+
400
+ for root, dirs, filenames in os.walk(target):
401
+ dirs[:] = [d for d in dirs if d not in SKIP_DIRECTORIES]
402
+
403
+ for fname in filenames:
404
+ total_files += 1
405
+ fpath = Path(root) / fname
406
+ suffix = fpath.suffix.lower()
407
+
408
+ # Categorize by extension
409
+ ext_key = suffix if suffix else "(no extension)"
410
+ files_by_type[ext_key] = files_by_type.get(ext_key, 0) + 1
411
+
412
+ # Detect entry points
413
+ for pat in _entry_point_patterns:
414
+ if pat.search(fname) or pat.search(str(fpath)):
415
+ entry_points.append(str(fpath))
416
+ break
417
+
418
+ # Detect dependency files
419
+ if fname.lower() in _dep_file_names:
420
+ dependency_files.append(str(fpath))
421
+
422
+ # Detect config files
423
+ if suffix in _config_extensions or fname.lower().startswith(".env"):
424
+ config_files.append(str(fpath))
425
+
426
+ # Sort by count descending
427
+ sorted_types = sorted(files_by_type.items(), key=lambda x: x[1], reverse=True)
428
+
429
+ return {
430
+ "total_files": total_files,
431
+ "files_by_type": dict(sorted_types),
432
+ "entry_points": sorted(set(entry_points)),
433
+ "dependency_files": sorted(set(dependency_files)),
434
+ "config_files": sorted(set(config_files)),
435
+ }
436
+
437
+
438
+ def _phase2_threat_modeling_hints(surface_map: dict, findings: list[dict]) -> dict:
439
+ """Phase 2: Threat Modeling Hints -- identify components for STRIDE analysis."""
440
+ logger.info("Phase 2: Threat Modeling Hints")
441
+
442
+ components: list[dict] = []
443
+
444
+ # Entry points are high-value STRIDE targets
445
+ for ep in surface_map.get("entry_points", []):
446
+ components.append({
447
+ "component": ep,
448
+ "type": "entry_point",
449
+ "stride_focus": ["Spoofing", "Tampering", "Elevation of Privilege"],
450
+ "reason": "Application entry point -- critical for authentication and authorization",
451
+ })
452
+
453
+ # Dependency files = supply chain
454
+ for dep_file in surface_map.get("dependency_files", []):
455
+ components.append({
456
+ "component": dep_file,
457
+ "type": "dependency_manifest",
458
+ "stride_focus": ["Tampering", "Elevation of Privilege"],
459
+ "reason": "Dependency manifest -- supply chain attack vector",
460
+ })
461
+
462
+ # Config files = information disclosure
463
+ for cfg in surface_map.get("config_files", []):
464
+ components.append({
465
+ "component": cfg,
466
+ "type": "configuration",
467
+ "stride_focus": ["Information Disclosure", "Tampering"],
468
+ "reason": "Configuration file -- may contain secrets or security settings",
469
+ })
470
+
471
+ # Files with critical findings
472
+ critical_files: set[str] = set()
473
+ for f in findings:
474
+ if f.get("severity") in ("CRITICAL", "HIGH"):
475
+ critical_files.add(f.get("file", ""))
476
+
477
+ for cf in sorted(critical_files):
478
+ if cf:
479
+ components.append({
480
+ "component": cf,
481
+ "type": "high_risk_source",
482
+ "stride_focus": [
483
+ "Spoofing", "Tampering", "Repudiation",
484
+ "Information Disclosure", "Denial of Service",
485
+ "Elevation of Privilege",
486
+ ],
487
+ "reason": "Source file with CRITICAL/HIGH severity findings",
488
+ })
489
+
490
+ return {
491
+ "components_for_stride": components,
492
+ "total_components": len(components),
493
+ "recommendation": (
494
+ "Run a formal STRIDE analysis on each component above. "
495
+ "For each STRIDE category, document: attack vector, impact (1-5), "
496
+ "probability (1-5), and proposed mitigation."
497
+ ),
498
+ }
499
+
500
+
501
+ def _phase3_security_checklist(
502
+ secrets_report: dict,
503
+ dep_report: dict,
504
+ inj_report: dict,
505
+ quick_report: dict,
506
+ ) -> dict:
507
+ """Phase 3: Security Checklist -- compile all scanner results."""
508
+ logger.info("Phase 3: Security Checklist")
509
+
510
+ checklist: list[dict] = []
511
+
512
+ # Secrets check
513
+ secrets_count = secrets_report.get("total_findings", 0)
514
+ checklist.append({
515
+ "check": "No hardcoded secrets in source code",
516
+ "status": "PASS" if secrets_count == 0 else "FAIL",
517
+ "details": f"{secrets_count} secret(s) detected",
518
+ "scanner": "secrets_scanner",
519
+ })
520
+
521
+ # Dependency check
522
+ dep_score = dep_report.get("score", 0)
523
+ dep_count = dep_report.get("total_findings", 0)
524
+ checklist.append({
525
+ "check": "Dependencies are secure and pinned",
526
+ "status": "PASS" if dep_score >= 80 else ("WARN" if dep_score >= 50 else "FAIL"),
527
+ "details": f"{dep_count} finding(s), score={dep_score}",
528
+ "scanner": "dependency_scanner",
529
+ })
530
+
531
+ # Injection check
532
+ inj_count = inj_report.get("total_findings", 0)
533
+ inj_critical = inj_report.get("severity_counts", {}).get("CRITICAL", 0)
534
+ checklist.append({
535
+ "check": "No injection vulnerabilities",
536
+ "status": "PASS" if inj_count == 0 else ("FAIL" if inj_critical > 0 else "WARN"),
537
+ "details": f"{inj_count} finding(s), {inj_critical} CRITICAL",
538
+ "scanner": "injection_scanner",
539
+ })
540
+
541
+ # Quick scan check
542
+ quick_score = quick_report.get("score", 0)
543
+ quick_count = quick_report.get("total_findings", 0)
544
+ checklist.append({
545
+ "check": "No dangerous code patterns",
546
+ "status": "PASS" if quick_score >= 80 else ("WARN" if quick_score >= 50 else "FAIL"),
547
+ "details": f"{quick_count} finding(s), score={quick_score}",
548
+ "scanner": "quick_scan",
549
+ })
550
+
551
+ # Summary counts
552
+ pass_count = sum(1 for c in checklist if c["status"] == "PASS")
553
+ warn_count = sum(1 for c in checklist if c["status"] == "WARN")
554
+ fail_count = sum(1 for c in checklist if c["status"] == "FAIL")
555
+
556
+ return {
557
+ "checklist": checklist,
558
+ "summary": {
559
+ "pass": pass_count,
560
+ "warn": warn_count,
561
+ "fail": fail_count,
562
+ "total": len(checklist),
563
+ },
564
+ }
565
+
566
+
567
+ def _phase4_red_team_scenarios(all_findings: list[dict], auth_score: float) -> dict:
568
+ """Phase 4: Red Team Scenarios -- generate attack scenarios from findings."""
569
+ logger.info("Phase 4: Red Team Scenarios")
570
+
571
+ scenarios: list[dict] = []
572
+ seen_types: set[str] = set()
573
+
574
+ # Generate scenarios from findings (one per unique type+file combination,
575
+ # capped to keep the report manageable)
576
+ MAX_SCENARIOS = 20
577
+
578
+ # Sort by severity so we get the most critical first
579
+ severity_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3, "INFO": 4}
580
+ sorted_findings = sorted(
581
+ all_findings,
582
+ key=lambda f: severity_order.get(f.get("severity", "INFO"), 5),
583
+ )
584
+
585
+ for finding in sorted_findings:
586
+ if len(scenarios) >= MAX_SCENARIOS:
587
+ break
588
+
589
+ # Determine the template key
590
+ finding_type = finding.get("type", "")
591
+ injection_type = finding.get("injection_type", "")
592
+ pattern = finding.get("pattern", "unknown")
593
+ file_path = finding.get("file", "unknown")
594
+
595
+ # Choose best template
596
+ if injection_type and injection_type in _RED_TEAM_TEMPLATES:
597
+ template_key = injection_type
598
+ elif finding_type in _RED_TEAM_TEMPLATES:
599
+ template_key = finding_type
600
+ else:
601
+ template_key = None
602
+
603
+ template = (
604
+ _RED_TEAM_TEMPLATES.get(template_key, _RED_TEAM_FALLBACK)
605
+ if template_key
606
+ else _RED_TEAM_FALLBACK
607
+ )
608
+
609
+ # Deduplicate: one scenario per (template_key, file) pair
610
+ dedup_key = f"{template_key or finding_type}:{file_path}"
611
+ if dedup_key in seen_types:
612
+ continue
613
+ seen_types.add(dedup_key)
614
+
615
+ # Interpolate template
616
+ scenario_text = template["scenario"].format(
617
+ pattern=pattern,
618
+ file=file_path,
619
+ )
620
+
621
+ scenarios.append({
622
+ "title": template["title"],
623
+ "persona": template["persona"],
624
+ "scenario": scenario_text,
625
+ "impact": template["impact"],
626
+ "difficulty": template["difficulty"],
627
+ "severity": finding.get("severity", "MEDIUM"),
628
+ "source_finding": {
629
+ "type": finding_type,
630
+ "pattern": pattern,
631
+ "file": file_path,
632
+ "line": finding.get("line", 0),
633
+ },
634
+ })
635
+
636
+ # Add no-auth scenario if auth score is low
637
+ if auth_score < 40 and "no_auth" not in seen_types:
638
+ template = _RED_TEAM_TEMPLATES["no_auth"]
639
+ scenarios.append({
640
+ "title": template["title"],
641
+ "persona": template["persona"],
642
+ "scenario": template["scenario"],
643
+ "impact": template["impact"],
644
+ "difficulty": template["difficulty"],
645
+ "severity": "HIGH",
646
+ "source_finding": {
647
+ "type": "architectural",
648
+ "pattern": "missing_auth",
649
+ "file": "(project-wide)",
650
+ "line": 0,
651
+ },
652
+ })
653
+
654
+ return {
655
+ "scenarios": scenarios,
656
+ "total_scenarios": len(scenarios),
657
+ }
658
+
659
+
660
+ def _phase5_blue_team_recommendations(all_findings: list[dict], auth_score: float) -> dict:
661
+ """Phase 5: Blue Team Recommendations -- hardening advice per finding type."""
662
+ logger.info("Phase 5: Blue Team Recommendations")
663
+
664
+ recommendations: list[dict] = []
665
+ seen_types: set[str] = set()
666
+
667
+ # Group findings by type for consolidated recommendations
668
+ for finding in all_findings:
669
+ finding_type = finding.get("type", "")
670
+ injection_type = finding.get("injection_type", "")
671
+
672
+ # Choose best template key
673
+ if injection_type and injection_type in _BLUE_TEAM_TEMPLATES:
674
+ rec_key = injection_type
675
+ elif finding_type in _BLUE_TEAM_TEMPLATES:
676
+ rec_key = finding_type
677
+ else:
678
+ rec_key = None
679
+
680
+ if rec_key and rec_key not in seen_types:
681
+ seen_types.add(rec_key)
682
+ template = _BLUE_TEAM_TEMPLATES[rec_key]
683
+
684
+ # Count affected findings
685
+ affected = [
686
+ f for f in all_findings
687
+ if f.get("injection_type", "") == rec_key
688
+ or f.get("type", "") == rec_key
689
+ ]
690
+
691
+ recommendations.append({
692
+ "category": rec_key,
693
+ "recommendation": template["recommendation"],
694
+ "priority": template["priority"],
695
+ "effort": template["effort"],
696
+ "affected_findings": len(affected),
697
+ "example_files": sorted(set(
698
+ f.get("file", "") for f in affected[:5]
699
+ )),
700
+ })
701
+
702
+ # Add no-auth recommendation if applicable
703
+ if auth_score < 40 and "no_auth" not in seen_types:
704
+ template = _BLUE_TEAM_TEMPLATES["no_auth"]
705
+ recommendations.append({
706
+ "category": "no_auth",
707
+ "recommendation": template["recommendation"],
708
+ "priority": template["priority"],
709
+ "effort": template["effort"],
710
+ "affected_findings": 0,
711
+ "example_files": [],
712
+ })
713
+
714
+ # Sort by priority (CRITICAL first)
715
+ priority_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
716
+ recommendations.sort(key=lambda r: priority_order.get(r["priority"], 5))
717
+
718
+ return {
719
+ "recommendations": recommendations,
720
+ "total_recommendations": len(recommendations),
721
+ }
722
+
723
+
724
+ def _phase6_verdict(
725
+ target_str: str,
726
+ all_findings: list[dict],
727
+ source_files: list[Path],
728
+ total_source_files: int,
729
+ secrets_report: dict,
730
+ dep_report: dict,
731
+ inj_report: dict,
732
+ quick_report: dict,
733
+ ) -> dict:
734
+ """Phase 6: Verdict -- compute score and emit final verdict."""
735
+ logger.info("Phase 6: Verdict")
736
+
737
+ domain_scores = score_calculator.compute_domain_scores(
738
+ secrets_findings=secrets_report.get("findings", []),
739
+ injection_findings=inj_report.get("findings", []),
740
+ dependency_report=dep_report,
741
+ quick_findings=quick_report.get("findings", []),
742
+ source_files=source_files,
743
+ total_source_files=total_source_files,
744
+ )
745
+
746
+ final_score = calculate_weighted_score(domain_scores)
747
+ verdict = get_verdict(final_score)
748
+
749
+ return {
750
+ "domain_scores": domain_scores,
751
+ "final_score": final_score,
752
+ "verdict": {
753
+ "label": verdict["label"],
754
+ "description": verdict["description"],
755
+ "emoji": verdict["emoji"],
756
+ },
757
+ }
758
+
759
+
760
+ # =========================================================================
761
+ # REPORT GENERATION
762
+ # =========================================================================
763
+
764
+ def _generate_markdown_report(
765
+ target: str,
766
+ phases: dict,
767
+ elapsed: float,
768
+ phases_run: list[int],
769
+ ) -> str:
770
+ """Generate a comprehensive Markdown audit report."""
771
+ lines: list[str] = []
772
+ ts = get_timestamp()
773
+
774
+ lines.append("# 007 -- Full Security Audit Report")
775
+ lines.append("")
776
+ lines.append(f"**Target:** `{target}`")
777
+ lines.append(f"**Timestamp:** {ts}")
778
+ lines.append(f"**Duration:** {elapsed:.2f}s")
779
+ lines.append(f"**Phases executed:** {', '.join(str(p) for p in phases_run)}")
780
+ lines.append("")
781
+ lines.append("---")
782
+ lines.append("")
783
+
784
+ # Phase 1: Surface Mapping
785
+ if 1 in phases_run and "phase1" in phases:
786
+ p1 = phases["phase1"]
787
+ lines.append("## Phase 1: Surface Mapping")
788
+ lines.append("")
789
+ lines.append(f"**Total files:** {p1.get('total_files', 0)}")
790
+ lines.append("")
791
+
792
+ # Files by type
793
+ fbt = p1.get("files_by_type", {})
794
+ if fbt:
795
+ lines.append("### File Types")
796
+ lines.append("")
797
+ lines.append("| Extension | Count |")
798
+ lines.append("|-----------|-------|")
799
+ for ext, count in list(fbt.items())[:20]:
800
+ lines.append(f"| `{ext}` | {count} |")
801
+ lines.append("")
802
+
803
+ # Entry points
804
+ eps = p1.get("entry_points", [])
805
+ if eps:
806
+ lines.append("### Entry Points")
807
+ lines.append("")
808
+ for ep in eps:
809
+ lines.append(f"- `{ep}`")
810
+ lines.append("")
811
+
812
+ # Dependency files
813
+ dfs = p1.get("dependency_files", [])
814
+ if dfs:
815
+ lines.append("### Dependency Files")
816
+ lines.append("")
817
+ for df in dfs:
818
+ lines.append(f"- `{df}`")
819
+ lines.append("")
820
+
821
+ lines.append("---")
822
+ lines.append("")
823
+
824
+ # Phase 2: Threat Modeling Hints
825
+ if 2 in phases_run and "phase2" in phases:
826
+ p2 = phases["phase2"]
827
+ lines.append("## Phase 2: Threat Modeling Hints")
828
+ lines.append("")
829
+ lines.append(f"**Components identified for STRIDE analysis:** {p2.get('total_components', 0)}")
830
+ lines.append("")
831
+
832
+ for comp in p2.get("components_for_stride", [])[:30]:
833
+ lines.append(f"- **`{comp['component']}`** ({comp['type']})")
834
+ lines.append(f" - STRIDE focus: {', '.join(comp['stride_focus'])}")
835
+ lines.append(f" - Reason: {comp['reason']}")
836
+ lines.append("")
837
+ lines.append(f"> {p2.get('recommendation', '')}")
838
+ lines.append("")
839
+ lines.append("---")
840
+ lines.append("")
841
+
842
+ # Phase 3: Security Checklist
843
+ if 3 in phases_run and "phase3" in phases:
844
+ p3 = phases["phase3"]
845
+ summary = p3.get("summary", {})
846
+ lines.append("## Phase 3: Security Checklist")
847
+ lines.append("")
848
+ lines.append(
849
+ f"**Results:** {summary.get('pass', 0)} PASS / "
850
+ f"{summary.get('warn', 0)} WARN / "
851
+ f"{summary.get('fail', 0)} FAIL"
852
+ )
853
+ lines.append("")
854
+ lines.append("| Check | Status | Details | Scanner |")
855
+ lines.append("|-------|--------|---------|---------|")
856
+ for item in p3.get("checklist", []):
857
+ status_icon = {"PASS": "[PASS]", "WARN": "[WARN]", "FAIL": "[FAIL]"}.get(
858
+ item["status"], item["status"]
859
+ )
860
+ lines.append(
861
+ f"| {item['check']} | {status_icon} | {item['details']} | {item['scanner']} |"
862
+ )
863
+ lines.append("")
864
+ lines.append("---")
865
+ lines.append("")
866
+
867
+ # Phase 4: Red Team Scenarios
868
+ if 4 in phases_run and "phase4" in phases:
869
+ p4 = phases["phase4"]
870
+ lines.append("## Phase 4: Red Team Scenarios")
871
+ lines.append("")
872
+ lines.append(f"**Total scenarios:** {p4.get('total_scenarios', 0)}")
873
+ lines.append("")
874
+
875
+ for i, sc in enumerate(p4.get("scenarios", []), start=1):
876
+ lines.append(f"### Scenario {i}: {sc['title']}")
877
+ lines.append("")
878
+ lines.append(f"- **Persona:** {sc['persona']}")
879
+ lines.append(f"- **Severity:** {sc['severity']}")
880
+ lines.append(f"- **Difficulty:** {sc['difficulty']}")
881
+ lines.append(f"- **Impact:** {sc['impact']}")
882
+ lines.append(f"- **Description:** {sc['scenario']}")
883
+ src = sc.get("source_finding", {})
884
+ if src.get("file"):
885
+ lines.append(f"- **Source:** `{src['file']}`:L{src.get('line', 0)} ({src.get('pattern', '')})")
886
+ lines.append("")
887
+
888
+ lines.append("---")
889
+ lines.append("")
890
+
891
+ # Phase 5: Blue Team Recommendations
892
+ if 5 in phases_run and "phase5" in phases:
893
+ p5 = phases["phase5"]
894
+ lines.append("## Phase 5: Blue Team Recommendations")
895
+ lines.append("")
896
+ lines.append(f"**Total recommendations:** {p5.get('total_recommendations', 0)}")
897
+ lines.append("")
898
+
899
+ for rec in p5.get("recommendations", []):
900
+ lines.append(f"### [{rec['priority']}] {rec['category'].replace('_', ' ').title()}")
901
+ lines.append("")
902
+ lines.append(f"**Affected findings:** {rec['affected_findings']}")
903
+ lines.append(f"**Effort:** {rec['effort']}")
904
+ lines.append("")
905
+ lines.append(f"{rec['recommendation']}")
906
+ lines.append("")
907
+ if rec.get("example_files"):
908
+ lines.append("**Example files:**")
909
+ for ef in rec["example_files"]:
910
+ if ef:
911
+ lines.append(f"- `{ef}`")
912
+ lines.append("")
913
+
914
+ lines.append("---")
915
+ lines.append("")
916
+
917
+ # Phase 6: Verdict
918
+ if 6 in phases_run and "phase6" in phases:
919
+ p6 = phases["phase6"]
920
+ domain_scores = p6.get("domain_scores", {})
921
+ final_score = p6.get("final_score", 0)
922
+ verdict = p6.get("verdict", {})
923
+
924
+ lines.append("## Phase 6: Verdict")
925
+ lines.append("")
926
+ lines.append("### Domain Scores")
927
+ lines.append("")
928
+ lines.append("| Domain | Weight | Score |")
929
+ lines.append("|--------|--------|-------|")
930
+ for domain, weight in SCORING_WEIGHTS.items():
931
+ score = domain_scores.get(domain, 0.0)
932
+ label = SCORING_LABELS.get(domain, domain)
933
+ lines.append(f"| {label} | {weight * 100:.0f}% | {score:.1f} |")
934
+ lines.append("")
935
+
936
+ lines.append(f"### Final Score: **{final_score:.1f} / 100**")
937
+ lines.append("")
938
+ lines.append(
939
+ f"### Verdict: **{verdict.get('emoji', '')} {verdict.get('label', 'N/A')}**"
940
+ )
941
+ lines.append("")
942
+ lines.append(f"> {verdict.get('description', '')}")
943
+ lines.append("")
944
+
945
+ lines.append("---")
946
+ lines.append("")
947
+ lines.append("*Generated by 007 -- Licenca para Auditar*")
948
+ lines.append("")
949
+
950
+ return "\n".join(lines)
951
+
952
+
953
+ def _generate_text_summary(
954
+ target: str,
955
+ phases: dict,
956
+ elapsed: float,
957
+ phases_run: list[int],
958
+ ) -> str:
959
+ """Generate a concise text summary for stdout."""
960
+ lines: list[str] = []
961
+
962
+ lines.append("=" * 72)
963
+ lines.append(" 007 FULL SECURITY AUDIT -- SUMMARY")
964
+ lines.append("=" * 72)
965
+ lines.append("")
966
+ lines.append(f" Target: {target}")
967
+ lines.append(f" Timestamp: {get_timestamp()}")
968
+ lines.append(f" Duration: {elapsed:.2f}s")
969
+ lines.append(f" Phases: {', '.join(str(p) for p in phases_run)}")
970
+ lines.append("")
971
+
972
+ # Phase 1 summary
973
+ if "phase1" in phases:
974
+ p1 = phases["phase1"]
975
+ lines.append(f" Phase 1 -- Surface: {p1.get('total_files', 0)} files, "
976
+ f"{len(p1.get('entry_points', []))} entry points, "
977
+ f"{len(p1.get('dependency_files', []))} dep files")
978
+
979
+ # Phase 2 summary
980
+ if "phase2" in phases:
981
+ p2 = phases["phase2"]
982
+ lines.append(f" Phase 2 -- Threat Model Hints: "
983
+ f"{p2.get('total_components', 0)} components for STRIDE")
984
+
985
+ # Phase 3 summary
986
+ if "phase3" in phases:
987
+ p3 = phases["phase3"]
988
+ summary = p3.get("summary", {})
989
+ lines.append(
990
+ f" Phase 3 -- Checklist: "
991
+ f"{summary.get('pass', 0)} PASS / "
992
+ f"{summary.get('warn', 0)} WARN / "
993
+ f"{summary.get('fail', 0)} FAIL"
994
+ )
995
+
996
+ # Phase 4 summary
997
+ if "phase4" in phases:
998
+ p4 = phases["phase4"]
999
+ lines.append(f" Phase 4 -- Red Team: {p4.get('total_scenarios', 0)} attack scenarios")
1000
+
1001
+ # Phase 5 summary
1002
+ if "phase5" in phases:
1003
+ p5 = phases["phase5"]
1004
+ lines.append(f" Phase 5 -- Blue Team: {p5.get('total_recommendations', 0)} recommendations")
1005
+
1006
+ # Phase 6 verdict
1007
+ if "phase6" in phases:
1008
+ p6 = phases["phase6"]
1009
+ final_score = p6.get("final_score", 0)
1010
+ verdict = p6.get("verdict", {})
1011
+ lines.append("")
1012
+ lines.append("-" * 72)
1013
+ lines.append(f" FINAL SCORE: {final_score:.1f} / 100")
1014
+ lines.append(f" VERDICT: {verdict.get('emoji', '')} {verdict.get('label', 'N/A')}")
1015
+ lines.append(f" {verdict.get('description', '')}")
1016
+
1017
+ lines.append("=" * 72)
1018
+ lines.append("")
1019
+
1020
+ return "\n".join(lines)
1021
+
1022
+
1023
+ # =========================================================================
1024
+ # MAIN ENTRY POINT
1025
+ # =========================================================================
1026
+
1027
+ def run_audit(
1028
+ target_path: str,
1029
+ output_format: str = "text",
1030
+ phases_to_run: str = "all",
1031
+ verbose: bool = False,
1032
+ ) -> dict:
1033
+ """Execute the full 6-phase security audit.
1034
+
1035
+ Args:
1036
+ target_path: Path to the directory to audit.
1037
+ output_format: 'text', 'json', or 'markdown'.
1038
+ phases_to_run: 'all' or a comma-separated list of phase numbers (e.g. '1,3,6').
1039
+ verbose: Enable debug-level logging.
1040
+
1041
+ Returns:
1042
+ JSON-compatible audit report dict.
1043
+ """
1044
+ if verbose:
1045
+ logger.setLevel("DEBUG")
1046
+
1047
+ ensure_directories()
1048
+
1049
+ target = Path(target_path).resolve()
1050
+ if not target.exists():
1051
+ logger.error("Target path does not exist: %s", target)
1052
+ sys.exit(1)
1053
+ if not target.is_dir():
1054
+ logger.error("Target is not a directory: %s", target)
1055
+ sys.exit(1)
1056
+
1057
+ # Parse phases
1058
+ if phases_to_run == "all":
1059
+ phases_list = [1, 2, 3, 4, 5, 6]
1060
+ else:
1061
+ try:
1062
+ phases_list = sorted(set(int(p.strip()) for p in phases_to_run.split(",")))
1063
+ if not all(1 <= p <= 6 for p in phases_list):
1064
+ logger.error("Phase numbers must be between 1 and 6.")
1065
+ sys.exit(1)
1066
+ except ValueError:
1067
+ logger.error("Invalid --phase value. Use 'all' or comma-separated numbers (1-6).")
1068
+ sys.exit(1)
1069
+
1070
+ logger.info("Starting full audit of %s (phases: %s)", target, phases_list)
1071
+ start_time = time.time()
1072
+ target_str = str(target)
1073
+
1074
+ # ------------------------------------------------------------------
1075
+ # Run scanners if needed (phases 3-6 need scanner data)
1076
+ # ------------------------------------------------------------------
1077
+ need_scanners = any(p in phases_list for p in [3, 4, 5, 6])
1078
+
1079
+ secrets_report: dict = {"findings": [], "score": 100, "total_findings": 0}
1080
+ dep_report: dict = {"findings": [], "score": 100, "total_findings": 0}
1081
+ inj_report: dict = {"findings": [], "score": 100, "total_findings": 0}
1082
+ quick_report: dict = {"findings": [], "score": 100, "total_findings": 0}
1083
+ all_findings: list[dict] = []
1084
+
1085
+ if need_scanners:
1086
+ logger.info("Running scanners for phases %s...", [p for p in phases_list if p >= 3])
1087
+
1088
+ try:
1089
+ secrets_report = secrets_scanner.run_scan(
1090
+ target_path=target_str, output_format="json", verbose=verbose,
1091
+ )
1092
+ except SystemExit:
1093
+ pass
1094
+
1095
+ try:
1096
+ dep_report = dependency_scanner.run_scan(
1097
+ target_path=target_str, output_format="json", verbose=verbose,
1098
+ )
1099
+ except SystemExit:
1100
+ pass
1101
+
1102
+ try:
1103
+ inj_report = injection_scanner.run_scan(
1104
+ target_path=target_str, output_format="json", verbose=verbose,
1105
+ )
1106
+ except SystemExit:
1107
+ pass
1108
+
1109
+ try:
1110
+ quick_report = quick_scan.run_scan(
1111
+ target_path=target_str, output_format="json", verbose=verbose,
1112
+ )
1113
+ except SystemExit:
1114
+ pass
1115
+
1116
+ # Aggregate and deduplicate
1117
+ raw = (
1118
+ secrets_report.get("findings", [])
1119
+ + dep_report.get("findings", [])
1120
+ + inj_report.get("findings", [])
1121
+ + quick_report.get("findings", [])
1122
+ )
1123
+ all_findings = score_calculator._deduplicate_findings(raw)
1124
+
1125
+ # ------------------------------------------------------------------
1126
+ # Collect source files if needed for phase 6
1127
+ # ------------------------------------------------------------------
1128
+ source_files: list[Path] = []
1129
+ total_source_files = 0
1130
+ if 6 in phases_list:
1131
+ source_files = score_calculator._collect_source_files(target)
1132
+ total_source_files = len(source_files)
1133
+
1134
+ # ------------------------------------------------------------------
1135
+ # Execute phases
1136
+ # ------------------------------------------------------------------
1137
+ phases_data: dict = {}
1138
+
1139
+ if 1 in phases_list:
1140
+ phases_data["phase1"] = _phase1_surface_mapping(target, verbose=verbose)
1141
+
1142
+ if 2 in phases_list:
1143
+ # Phase 2 benefits from phase 1 data and findings
1144
+ surface = phases_data.get("phase1") or _phase1_surface_mapping(target, verbose=verbose)
1145
+ phases_data["phase2"] = _phase2_threat_modeling_hints(surface, all_findings)
1146
+
1147
+ if 3 in phases_list:
1148
+ phases_data["phase3"] = _phase3_security_checklist(
1149
+ secrets_report, dep_report, inj_report, quick_report,
1150
+ )
1151
+
1152
+ # Auth score for phases 4 and 5
1153
+ auth_score = 50.0
1154
+ if 6 in phases_list or 4 in phases_list or 5 in phases_list:
1155
+ if source_files:
1156
+ auth_count = score_calculator._count_pattern_matches(
1157
+ source_files, score_calculator._AUTH_PATTERNS,
1158
+ )
1159
+ if auth_count == 0:
1160
+ auth_score = 25.0
1161
+ else:
1162
+ auth_score = score_calculator._score_from_positive_signals(
1163
+ auth_count, total_source_files, base_score=40, max_score=95,
1164
+ )
1165
+
1166
+ if 4 in phases_list:
1167
+ phases_data["phase4"] = _phase4_red_team_scenarios(all_findings, auth_score)
1168
+
1169
+ if 5 in phases_list:
1170
+ phases_data["phase5"] = _phase5_blue_team_recommendations(all_findings, auth_score)
1171
+
1172
+ if 6 in phases_list:
1173
+ phases_data["phase6"] = _phase6_verdict(
1174
+ target_str=target_str,
1175
+ all_findings=all_findings,
1176
+ source_files=source_files,
1177
+ total_source_files=total_source_files,
1178
+ secrets_report=secrets_report,
1179
+ dep_report=dep_report,
1180
+ inj_report=inj_report,
1181
+ quick_report=quick_report,
1182
+ )
1183
+
1184
+ elapsed = time.time() - start_time
1185
+
1186
+ # ------------------------------------------------------------------
1187
+ # Generate and save Markdown report
1188
+ # ------------------------------------------------------------------
1189
+ md_report = _generate_markdown_report(target_str, phases_data, elapsed, phases_list)
1190
+
1191
+ ts_file = datetime.now(timezone.utc).strftime("%Y-%m-%d_%H-%M-%S")
1192
+ report_filename = f"audit_{ts_file}.md"
1193
+ report_path = REPORTS_DIR / report_filename
1194
+
1195
+ try:
1196
+ report_path.write_text(md_report, encoding="utf-8")
1197
+ logger.info("Markdown report saved to %s", report_path)
1198
+ except OSError as exc:
1199
+ logger.warning("Could not save report: %s", exc)
1200
+
1201
+ # ------------------------------------------------------------------
1202
+ # Audit log
1203
+ # ------------------------------------------------------------------
1204
+ verdict_data = phases_data.get("phase6", {}).get("verdict", {})
1205
+ final_score = phases_data.get("phase6", {}).get("final_score", "N/A")
1206
+
1207
+ log_audit_event(
1208
+ action="full_audit",
1209
+ target=target_str,
1210
+ result=f"score={final_score}, verdict={verdict_data.get('label', 'N/A')}",
1211
+ details={
1212
+ "phases_run": phases_list,
1213
+ "total_findings": len(all_findings),
1214
+ "report_path": str(report_path),
1215
+ "duration_seconds": round(elapsed, 3),
1216
+ },
1217
+ )
1218
+
1219
+ # ------------------------------------------------------------------
1220
+ # Build final report dict
1221
+ # ------------------------------------------------------------------
1222
+ full_report = {
1223
+ "report": "full_audit",
1224
+ "target": target_str,
1225
+ "timestamp": get_timestamp(),
1226
+ "duration_seconds": round(elapsed, 3),
1227
+ "phases_run": phases_list,
1228
+ "phases": phases_data,
1229
+ "total_findings": len(all_findings),
1230
+ "findings": all_findings,
1231
+ "report_path": str(report_path),
1232
+ }
1233
+
1234
+ # ------------------------------------------------------------------
1235
+ # Output
1236
+ # ------------------------------------------------------------------
1237
+ if output_format == "json":
1238
+ print(json.dumps(full_report, indent=2, ensure_ascii=False))
1239
+ elif output_format == "markdown":
1240
+ print(md_report)
1241
+ else:
1242
+ print(_generate_text_summary(target_str, phases_data, elapsed, phases_list))
1243
+ print(f" Full report saved to: {report_path}")
1244
+ print("")
1245
+
1246
+ return full_report
1247
+
1248
+
1249
+ # =========================================================================
1250
+ # CLI
1251
+ # =========================================================================
1252
+
1253
+ if __name__ == "__main__":
1254
+ parser = argparse.ArgumentParser(
1255
+ description=(
1256
+ "007 Full Audit -- Comprehensive 6-phase security audit.\n\n"
1257
+ "Phases:\n"
1258
+ " 1: Surface Mapping -- file inventory, entry points, deps\n"
1259
+ " 2: Threat Modeling Hints -- STRIDE analysis targets\n"
1260
+ " 3: Security Checklist -- run all scanners\n"
1261
+ " 4: Red Team Scenarios -- attack scenario generation\n"
1262
+ " 5: Blue Team Recs -- hardening recommendations\n"
1263
+ " 6: Verdict -- scoring and final verdict"
1264
+ ),
1265
+ epilog=(
1266
+ "Examples:\n"
1267
+ " python full_audit.py --target ./my-project\n"
1268
+ " python full_audit.py --target ./my-project --output markdown\n"
1269
+ " python full_audit.py --target ./my-project --phase 1,3,6\n"
1270
+ " python full_audit.py --target ./my-project --output json --verbose"
1271
+ ),
1272
+ formatter_class=argparse.RawDescriptionHelpFormatter,
1273
+ )
1274
+ parser.add_argument(
1275
+ "--target",
1276
+ required=True,
1277
+ help="Path to the directory to audit (required).",
1278
+ )
1279
+ parser.add_argument(
1280
+ "--output",
1281
+ choices=["text", "json", "markdown"],
1282
+ default="text",
1283
+ help="Output format: 'text' (default), 'json', or 'markdown'.",
1284
+ )
1285
+ parser.add_argument(
1286
+ "--phase",
1287
+ default="all",
1288
+ help=(
1289
+ "Which phases to run: 'all' (default) or comma-separated numbers "
1290
+ "(e.g. '1,3,6'). Range: 1-6."
1291
+ ),
1292
+ )
1293
+ parser.add_argument(
1294
+ "--verbose",
1295
+ action="store_true",
1296
+ default=False,
1297
+ help="Enable verbose/debug logging.",
1298
+ )
1299
+
1300
+ args = parser.parse_args()
1301
+ run_audit(
1302
+ target_path=args.target,
1303
+ output_format=args.output,
1304
+ phases_to_run=args.phase,
1305
+ verbose=args.verbose,
1306
+ )