icdev 0.0.3__py3-none-any.whl

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 (1214) hide show
  1. args/agent_config.yaml +113 -0
  2. args/audit_regimes/cisa_sbd.json +381 -0
  3. args/audit_regimes/cmmc_l2.json +906 -0
  4. args/audit_regimes/dod_cssp.json +393 -0
  5. args/audit_regimes/dodi_5000_87.json +297 -0
  6. args/audit_regimes/fedramp_moderate.json +650 -0
  7. args/audit_regimes/ieee_1012.json +373 -0
  8. args/audit_regimes/nist_800_171.json +624 -0
  9. args/audit_regimes/nist_800_53.json +907 -0
  10. args/cloudforge_blueprints/aws_commercial.yaml +29 -0
  11. args/cloudforge_blueprints/aws_govcloud_il4.yaml +34 -0
  12. args/cloudforge_blueprints/aws_govcloud_il5.yaml +38 -0
  13. args/cloudforge_blueprints/azure_commercial.yaml +28 -0
  14. args/cloudforge_blueprints/azure_gov_il4.yaml +32 -0
  15. args/cloudforge_blueprints/azure_gov_il5.yaml +36 -0
  16. args/cloudforge_blueprints/gcp_commercial.yaml +28 -0
  17. args/cloudforge_blueprints/oci_commercial.yaml +28 -0
  18. args/cloudforge_config.yaml +231 -0
  19. args/cloudforge_runbook_templates/backup_verify.yaml +98 -0
  20. args/cloudforge_runbook_templates/dr_failover.yaml +107 -0
  21. args/cloudforge_runbook_templates/health_check.yaml +97 -0
  22. args/cloudforge_runbook_templates/incident_response.yaml +101 -0
  23. args/cloudforge_runbook_templates/migration_cutover.yaml +105 -0
  24. args/cloudforge_runbook_templates/patch_rollout.yaml +92 -0
  25. args/cloudforge_runbook_templates/zone_provision.yaml +93 -0
  26. args/code_pattern_config.yaml +151 -0
  27. args/code_quality_config.yaml +47 -0
  28. args/compliance_config.yaml +17 -0
  29. args/control_inheritance.yaml +177 -0
  30. args/csp_mcp_config.yaml +41 -0
  31. args/cui_markings.yaml +35 -0
  32. args/databridge_config.yaml +232 -0
  33. args/db_config.yaml +116 -0
  34. args/decision_tables/agent_trust_decision.yaml +143 -0
  35. args/decision_tables/ato_boundary_impact.yaml +132 -0
  36. args/decision_tables/deployment_approval.yaml +152 -0
  37. args/degradation_matrix.yaml +163 -0
  38. args/devsecops_config.yaml +286 -0
  39. args/endpoint_security_config.yaml +207 -0
  40. args/exit_criteria.yaml +102 -0
  41. args/feature_flags.yaml +235 -0
  42. args/file_access_tiers.yaml +88 -0
  43. args/forge_studio/blueprint_config.yaml +27 -0
  44. args/forge_studio/component_catalog.json +411 -0
  45. args/forge_studio/workflow_templates.yaml +103 -0
  46. args/govcon_config.yaml +41 -0
  47. args/harness_config.yaml +67 -0
  48. args/innovation_config.yaml +321 -0
  49. args/knowledge_graph_config.yaml +113 -0
  50. args/llm_config.yaml +222 -0
  51. args/marketplace_config.yaml +260 -0
  52. args/monitoring_config.yaml +127 -0
  53. args/mosa_config.yaml +190 -0
  54. args/observability_tracing_config.yaml +170 -0
  55. args/owasp_agentic_config.yaml +171 -0
  56. args/pipeline_gates.yaml +197 -0
  57. args/project_defaults.yaml +235 -0
  58. args/prompt_chains.yaml +163 -0
  59. args/rag_config.yaml +167 -0
  60. args/research_config.yaml +89 -0
  61. args/resilience_config.yaml +197 -0
  62. args/ricoas_config.yaml +191 -0
  63. args/security_gates.yaml +763 -0
  64. args/storage_config.yaml +63 -0
  65. args/writeguard_config.yaml +131 -0
  66. args/zta_config.yaml +247 -0
  67. context/__init__.py +6 -0
  68. context/agent/__init__.py +6 -0
  69. context/agent/response_schemas/__init__.py +6 -0
  70. context/agent/response_schemas/debate_position.json +46 -0
  71. context/agent/response_schemas/fitness_scorecard.json +74 -0
  72. context/agent/response_schemas/review_decision.json +39 -0
  73. context/agent/response_schemas/task_decomposition.json +82 -0
  74. context/agent/response_schemas/veto_decision.json +40 -0
  75. context/agentic/__init__.py +6 -0
  76. context/agentic/architecture_patterns.md +269 -0
  77. context/agentic/capability_registry.yaml +223 -0
  78. context/agentic/csp_integration.md +30 -0
  79. context/agentic/csp_mcp_registry.yaml +280 -0
  80. context/agentic/fitness_rubric.md +56 -0
  81. context/agentic/governance_baseline.md +205 -0
  82. context/ci/__init__.py +6 -0
  83. context/ci/worktree_templates.json +44 -0
  84. context/cloud/__init__.py +6 -0
  85. context/cloud/csp_service_registry.json +739 -0
  86. context/compliance/__init__.py +6 -0
  87. context/compliance/ai_rmf_crosswalk.yaml +226 -0
  88. context/compliance/atlas_mitigations.json +293 -0
  89. context/compliance/atlas_techniques.json +833 -0
  90. context/compliance/cisa_sbd_requirements.json +477 -0
  91. context/compliance/cjis_security_policy.json +522 -0
  92. context/compliance/cmmc_practices.json +2494 -0
  93. context/compliance/cmmc_report_template.md +142 -0
  94. context/compliance/cnssi_1253_overlay.json +109 -0
  95. context/compliance/control_crosswalk.json +1914 -0
  96. context/compliance/control_families/__init__.py +6 -0
  97. context/compliance/csp_certifications.json +251 -0
  98. context/compliance/cssp_report_template.md +193 -0
  99. context/compliance/cui_templates/__init__.py +6 -0
  100. context/compliance/cui_templates/banner_block.txt +4 -0
  101. context/compliance/cui_templates/code_header.txt +8 -0
  102. context/compliance/cui_templates/document_template.md +35 -0
  103. context/compliance/data_type_framework_map.json +321 -0
  104. context/compliance/data_type_registry.json +147 -0
  105. context/compliance/dod_cssp_8530.json +463 -0
  106. context/compliance/eu_ai_act_annex_iii.json +108 -0
  107. context/compliance/export_templates/__init__.py +6 -0
  108. context/compliance/export_templates/emass_controls.csv.j2 +4 -0
  109. context/compliance/export_templates/evidence_package.md.j2 +39 -0
  110. context/compliance/export_templates/executive_summary.md.j2 +55 -0
  111. context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
  112. context/compliance/fedramp_20x_ksi_schemas.json +133 -0
  113. context/compliance/fedramp_high_baseline.json +4370 -0
  114. context/compliance/fedramp_moderate_baseline.json +2183 -0
  115. context/compliance/fedramp_report_template.md +181 -0
  116. context/compliance/fips_200_areas.json +362 -0
  117. context/compliance/gao_ai_accountability.json +262 -0
  118. context/compliance/hipaa_security_rule.json +720 -0
  119. context/compliance/hitrust_csf_v11.json +930 -0
  120. context/compliance/impact_level_profiles.json +251 -0
  121. context/compliance/incident_response_template.md +1110 -0
  122. context/compliance/iso27001_2022_controls.json +750 -0
  123. context/compliance/iso27001_nist_bridge.json +382 -0
  124. context/compliance/iso42001_controls.json +254 -0
  125. context/compliance/ivv_checklist_template.md +80 -0
  126. context/compliance/ivv_report_template.md +116 -0
  127. context/compliance/ivv_requirements.json +372 -0
  128. context/compliance/mosa_crosswalk.json +327 -0
  129. context/compliance/mosa_framework.json +250 -0
  130. context/compliance/narrative_templates/AC.md.j2 +101 -0
  131. context/compliance/narrative_templates/AU.md.j2 +106 -0
  132. context/compliance/narrative_templates/IA.md.j2 +104 -0
  133. context/compliance/narrative_templates/SC.md.j2 +102 -0
  134. context/compliance/narrative_templates/SI.md.j2 +111 -0
  135. context/compliance/narrative_templates/__init__.py +6 -0
  136. context/compliance/narrative_templates/default.md.j2 +50 -0
  137. context/compliance/narrative_templates/executive_summary.j2 +27 -0
  138. context/compliance/narrative_templates/poam_milestone.j2 +19 -0
  139. context/compliance/narrative_templates/ssp_section.j2 +11 -0
  140. context/compliance/nist_800_171_controls.json +1552 -0
  141. context/compliance/nist_800_207_crosswalk.json +399 -0
  142. context/compliance/nist_800_207_zta.json +258 -0
  143. context/compliance/nist_800_53.json +324 -0
  144. context/compliance/nist_ai_600_1_genai.json +326 -0
  145. context/compliance/nist_ai_rmf.json +206 -0
  146. context/compliance/nist_sp_800_60_types.json +1667 -0
  147. context/compliance/omb_m25_21_high_impact_ai.json +248 -0
  148. context/compliance/omb_m26_04_unbiased_ai.json +262 -0
  149. context/compliance/owasp_agentic_asi.json +133 -0
  150. context/compliance/owasp_agentic_threats.json +285 -0
  151. context/compliance/owasp_llm_top10.json +274 -0
  152. context/compliance/pci_dss_v4.json +510 -0
  153. context/compliance/poam_template.md +117 -0
  154. context/compliance/safeai_controls.json +512 -0
  155. context/compliance/sbd_report_template.md +77 -0
  156. context/compliance/siem_config_templates/__init__.py +6 -0
  157. context/compliance/siem_config_templates/filebeat.yml +213 -0
  158. context/compliance/siem_config_templates/log_sources.json +208 -0
  159. context/compliance/soc2_trust_criteria.json +661 -0
  160. context/compliance/ssp_template.md +432 -0
  161. context/compliance/stig_templates/__init__.py +6 -0
  162. context/compliance/stig_templates/webapp_stig.json +139 -0
  163. context/compliance/xai_requirements.json +108 -0
  164. context/dashboard/__init__.py +6 -0
  165. context/dashboard/nlq_examples.json +50 -0
  166. context/dashboard/schema_descriptions.json +23 -0
  167. context/icdev_methodology.md +100 -0
  168. context/integration/__init__.py +6 -0
  169. context/integration/approval_workflows.json +32 -0
  170. context/integration/gitlab_field_mappings.json +33 -0
  171. context/integration/jira_field_mappings.json +32 -0
  172. context/integration/reqif_export_schema.json +23 -0
  173. context/integration/servicenow_field_mappings.json +22 -0
  174. context/languages/__init__.py +6 -0
  175. context/languages/framework_patterns.json +205 -0
  176. context/languages/language_registry.json +279 -0
  177. context/llm/__init__.py +6 -0
  178. context/llm/example_provider.py +89 -0
  179. context/marketplace/assets/writeguard-core.yaml +100 -0
  180. context/marketplace/assets/writeguard-govcon.yaml +45 -0
  181. context/marketplace/assets/writeguard-style-guides.yaml +44 -0
  182. context/mbse/__init__.py +6 -0
  183. context/mbse/des_report_template.md +162 -0
  184. context/mbse/des_requirements.json +411 -0
  185. context/mbse/digital_thread_patterns.json +403 -0
  186. context/mbse/reqif_schema.json +280 -0
  187. context/mbse/sysml_element_types.json +432 -0
  188. context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
  189. context/oscal/README.md +43 -0
  190. context/patterns/__init__.py +6 -0
  191. context/profiles/__init__.py +6 -0
  192. context/profiles/dod_baseline_v1.yaml +145 -0
  193. context/profiles/fedramp_baseline_v1.yaml +143 -0
  194. context/profiles/financial_baseline_v1.yaml +142 -0
  195. context/profiles/healthcare_baseline_v1.yaml +135 -0
  196. context/profiles/law_enforcement_v1.yaml +129 -0
  197. context/profiles/startup_v1.yaml +134 -0
  198. context/rag/source_mappings.json +42 -0
  199. context/requirements/__init__.py +6 -0
  200. context/requirements/ambiguity_patterns.json +97 -0
  201. context/requirements/boundary_impact_rules.json +123 -0
  202. context/requirements/default_constitutions.json +67 -0
  203. context/requirements/document_extraction_rules.json +58 -0
  204. context/requirements/gap_patterns.json +108 -0
  205. context/requirements/readiness_rubric.json +78 -0
  206. context/requirements/red_alternative_patterns.json +210 -0
  207. context/requirements/safe_templates.json +72 -0
  208. context/requirements/spec_quality_checklist.json +122 -0
  209. context/research/regulatory_registry.json +114 -0
  210. context/research/verticals/cybersecurity.json +127 -0
  211. context/research/verticals/defense.json +104 -0
  212. context/research/verticals/fintech.json +125 -0
  213. context/research/verticals/healthcare.json +118 -0
  214. context/research/verticals/logistics.json +117 -0
  215. context/research/verticals/trading.json +145 -0
  216. context/simulation/__init__.py +6 -0
  217. context/simulation/architecture_patterns.json +36 -0
  218. context/simulation/coa_templates.json +38 -0
  219. context/simulation/cost_models.json +23 -0
  220. context/simulation/risk_categories.json +46 -0
  221. context/supply_chain/__init__.py +6 -0
  222. context/supply_chain/isa_templates.json +129 -0
  223. context/supply_chain/nist_800_161_controls.json +247 -0
  224. context/supply_chain/scrm_risk_matrix.json +147 -0
  225. context/templates/__init__.py +6 -0
  226. context/templates/ansible/__init__.py +6 -0
  227. context/templates/ansible/playbooks/__init__.py +6 -0
  228. context/templates/ansible/roles/__init__.py +6 -0
  229. context/templates/gitlab_ci/__init__.py +6 -0
  230. context/templates/grafana/__init__.py +6 -0
  231. context/templates/kubernetes/__init__.py +6 -0
  232. context/templates/project/__init__.py +6 -0
  233. context/templates/project/api/__init__.py +6 -0
  234. context/templates/project/cli/__init__.py +6 -0
  235. context/templates/project/data_pipeline/__init__.py +6 -0
  236. context/templates/project/iac/__init__.py +6 -0
  237. context/templates/project/javascript_frontend/__init__.py +6 -0
  238. context/templates/project/javascript_frontend/src/__init__.py +6 -0
  239. context/templates/project/javascript_frontend/tests/__init__.py +6 -0
  240. context/templates/project/microservice/__init__.py +6 -0
  241. context/templates/project/python_backend/__init__.py +6 -0
  242. context/templates/project/python_backend/src/__init__.py +6 -0
  243. context/templates/project/python_backend/tests/__init__.py +6 -0
  244. context/templates/project/python_backend/tests/features/__init__.py +6 -0
  245. context/templates/project/python_backend/tests/steps/__init__.py +6 -0
  246. context/templates/terraform/__init__.py +6 -0
  247. context/templates/terraform/govcloud_base/__init__.py +6 -0
  248. context/templates/terraform/modules/__init__.py +6 -0
  249. context/tone/__init__.py +6 -0
  250. context/writing/grammar_rules/common_errors.json +306 -0
  251. context/writing/grammar_rules/govcon_vocabulary.json +113 -0
  252. context/writing/style_guides/academic.yaml +43 -0
  253. context/writing/style_guides/business.yaml +42 -0
  254. context/writing/style_guides/government.yaml +59 -0
  255. context/writing/style_guides/proposal.yaml +58 -0
  256. context/writing/style_guides/technical.yaml +43 -0
  257. docs/adr/README.md +66 -0
  258. docs/adr/connector-forge-decisions.md +318 -0
  259. docs/adr/core-decisions.md +289 -0
  260. docs/adr/db-decisions.md +94 -0
  261. docs/adr/harness-decisions.md +122 -0
  262. docs/adr/innovation-decisions.md +262 -0
  263. docs/adr/marketplace-decisions.md +109 -0
  264. docs/adr/sbd-decisions.md +109 -0
  265. docs/adr/scale-engine-decisions.md +108 -0
  266. docs/adr/writeguard-decisions.md +136 -0
  267. docs/architecture/bounded-contexts.md +1032 -0
  268. docs/features/phase-65-writeguard.md +139 -0
  269. docs/features/phase-66-marketplace-commerce.md +79 -0
  270. docs/features/phase-67-knowledge-ingestion-rag-autodraft.md +97 -0
  271. docs/features/phase-68-enhanced-autodraft-pipeline.md +109 -0
  272. docs/features/phase-69-proposalai-marketplace-module.md +131 -0
  273. docs/features/phase-70-databridge.md +214 -0
  274. docs/features/phase-71-databridge-messaging.md +102 -0
  275. docs/implementation-plan-architecture-evolution.md +614 -0
  276. docs/marketplace/CONTRIBUTING.md +124 -0
  277. docs/marketplace/module_manifest_schema.yaml +83 -0
  278. docs/research/ai-architecture-patterns-2024-2026.md +1236 -0
  279. docs/research/app-builder-platform-analysis.md +582 -0
  280. docs/research/architecture-patterns-c4-ddd-agentic.md +871 -0
  281. docs/research/flowable-boat-competitive-analysis.md +426 -0
  282. docs/research/modern-dev-practices-2024-2026.md +1615 -0
  283. docs/research/secure-by-design-cloudyrion-adaptation.md +270 -0
  284. goals/agent_management.md +144 -0
  285. goals/ai_accountability.md +90 -0
  286. goals/ai_narratives.md +79 -0
  287. goals/ai_transparency.md +76 -0
  288. goals/ato_simulator.md +78 -0
  289. goals/audit_engine.md +177 -0
  290. goals/bite_sized_plans.md +225 -0
  291. goals/boundary_supply_chain.md +206 -0
  292. goals/brainstorming_gate.md +186 -0
  293. goals/build_app.md +604 -0
  294. goals/cato_live_evidence.md +77 -0
  295. goals/cloudforge.md +106 -0
  296. goals/code_intelligence.md +197 -0
  297. goals/compliance_workflow.md +858 -0
  298. goals/connector_forge.md +133 -0
  299. goals/databridge.md +128 -0
  300. goals/deploy_workflow.md +390 -0
  301. goals/developer_scorecard.md +78 -0
  302. goals/devsecops_workflow.md +408 -0
  303. goals/firmware_sbom.md +79 -0
  304. goals/forge_hub.md +78 -0
  305. goals/golden_path.md +77 -0
  306. goals/harness_engineering.md +91 -0
  307. goals/integration_testing.md +189 -0
  308. goals/knowledge_graph.md +128 -0
  309. goals/maintenance_audit.md +196 -0
  310. goals/manifest.md +50 -0
  311. goals/monitoring.md +126 -0
  312. goals/mosa_workflow.md +463 -0
  313. goals/multi_agent_orchestration.md +68 -0
  314. goals/observability_traceability_xai.md +154 -0
  315. goals/owasp_agentic_security.md +395 -0
  316. goals/pr_intelligence.md +78 -0
  317. goals/requirements_intake.md +213 -0
  318. goals/secure_by_design.md +135 -0
  319. goals/security_scan.md +381 -0
  320. goals/self_healing.md +120 -0
  321. goals/simulation_engine.md +111 -0
  322. goals/subagent_review.md +205 -0
  323. goals/systematic_debugging.md +257 -0
  324. goals/tdd_workflow.md +403 -0
  325. goals/template_exchange.md +77 -0
  326. goals/thread_heatmap.md +77 -0
  327. goals/threat_modeler.md +77 -0
  328. goals/verification_iron_law.md +192 -0
  329. goals/vsm_dashboard.md +76 -0
  330. goals/writeguard.md +89 -0
  331. goals/zero_trust_architecture.md +403 -0
  332. hardprompts/__init__.py +6 -0
  333. hardprompts/agent/__init__.py +6 -0
  334. hardprompts/agent/agentic_architect.md +100 -0
  335. hardprompts/agent/debate_prompt.md +32 -0
  336. hardprompts/agent/fitness_evaluation.md +48 -0
  337. hardprompts/agent/governance_review.md +214 -0
  338. hardprompts/agent/reviewer_prompt.md +34 -0
  339. hardprompts/agent/skill_design.md +172 -0
  340. hardprompts/agent/task_decomposition.md +275 -0
  341. hardprompts/agent/veto_check_prompt.md +33 -0
  342. hardprompts/architect/__init__.py +6 -0
  343. hardprompts/architect/api_design.md +283 -0
  344. hardprompts/architect/data_model.md +277 -0
  345. hardprompts/architect/system_design.md +180 -0
  346. hardprompts/builder/__init__.py +6 -0
  347. hardprompts/builder/code_generation.md +59 -0
  348. hardprompts/builder/refactor.md +58 -0
  349. hardprompts/builder/scaffold_project.md +69 -0
  350. hardprompts/builder/test_generation.md +87 -0
  351. hardprompts/ci/__init__.py +6 -0
  352. hardprompts/ci/worktree_setup.md +35 -0
  353. hardprompts/compliance/__init__.py +6 -0
  354. hardprompts/compliance/cmmc_assessment.md +63 -0
  355. hardprompts/compliance/cssp_assessment.md +75 -0
  356. hardprompts/compliance/cui_marking.md +86 -0
  357. hardprompts/compliance/fedramp_assessment.md +55 -0
  358. hardprompts/compliance/ivv_assessment.md +96 -0
  359. hardprompts/compliance/poam_generation.md +57 -0
  360. hardprompts/compliance/sbd_assessment.md +101 -0
  361. hardprompts/compliance/security_categorization.md +74 -0
  362. hardprompts/compliance/ssp_generation.md +56 -0
  363. hardprompts/compliance/stig_evaluation.md +63 -0
  364. hardprompts/dashboard/__init__.py +6 -0
  365. hardprompts/dashboard/nlq_system_prompt.md +26 -0
  366. hardprompts/infra/__init__.py +6 -0
  367. hardprompts/infra/k8s_manifests.md +118 -0
  368. hardprompts/infra/pipeline_generation.md +160 -0
  369. hardprompts/infra/terraform_generation.md +92 -0
  370. hardprompts/integration/__init__.py +6 -0
  371. hardprompts/integration/approval_review.md +17 -0
  372. hardprompts/integration/jira_mapping.md +25 -0
  373. hardprompts/integration/servicenow_mapping.md +14 -0
  374. hardprompts/knowledge/__init__.py +6 -0
  375. hardprompts/knowledge/pattern_detection.md +73 -0
  376. hardprompts/knowledge/recommendation_engine.md +90 -0
  377. hardprompts/knowledge/root_cause_analysis.md +91 -0
  378. hardprompts/maintenance/__init__.py +6 -0
  379. hardprompts/maintenance/maintenance_assessment.md +82 -0
  380. hardprompts/mbse/__init__.py +6 -0
  381. hardprompts/mbse/digital_thread.md +67 -0
  382. hardprompts/mbse/model_import.md +62 -0
  383. hardprompts/mbse/model_to_code.md +65 -0
  384. hardprompts/modernization/__init__.py +6 -0
  385. hardprompts/modernization/legacy_analysis.md +93 -0
  386. hardprompts/modernization/migration_planning.md +150 -0
  387. hardprompts/modernization/seven_r_assessment.md +107 -0
  388. hardprompts/proposal_draft.md +53 -0
  389. hardprompts/rag_citation.md +12 -0
  390. hardprompts/rag_rerank.md +31 -0
  391. hardprompts/requirements/__init__.py +6 -0
  392. hardprompts/requirements/bdd_generation.md +35 -0
  393. hardprompts/requirements/clarification_prioritization.md +29 -0
  394. hardprompts/requirements/decomposition.md +60 -0
  395. hardprompts/requirements/document_extraction.md +45 -0
  396. hardprompts/requirements/gap_detection.md +70 -0
  397. hardprompts/requirements/intake_conversation.md +101 -0
  398. hardprompts/requirements/readiness_assessment.md +39 -0
  399. hardprompts/requirements/spec_quality.md +33 -0
  400. hardprompts/requirements/traceability_analysis.md +23 -0
  401. hardprompts/security/__init__.py +6 -0
  402. hardprompts/security/endpoint_security.md +78 -0
  403. hardprompts/security/threat_model.md +70 -0
  404. hardprompts/security/vulnerability_assessment.md +81 -0
  405. hardprompts/simulation/__init__.py +6 -0
  406. hardprompts/simulation/architecture_impact.md +27 -0
  407. hardprompts/simulation/coa_alternative.md +27 -0
  408. hardprompts/simulation/coa_generation.md +25 -0
  409. hardprompts/simulation/compliance_impact.md +28 -0
  410. hardprompts/simulation/cost_estimation.md +33 -0
  411. hardprompts/simulation/risk_assessment.md +28 -0
  412. hardprompts/translation/code_translation.md +68 -0
  413. hardprompts/translation/dependency_suggestion.md +44 -0
  414. hardprompts/translation/test_translation.md +64 -0
  415. hardprompts/translation/translation_repair.md +59 -0
  416. icdev-0.0.3.dist-info/METADATA +909 -0
  417. icdev-0.0.3.dist-info/RECORD +1214 -0
  418. icdev-0.0.3.dist-info/WHEEL +5 -0
  419. icdev-0.0.3.dist-info/entry_points.txt +9 -0
  420. icdev-0.0.3.dist-info/licenses/LICENSE +201 -0
  421. icdev-0.0.3.dist-info/licenses/NOTICE +11 -0
  422. icdev-0.0.3.dist-info/top_level.txt +7 -0
  423. memory/MEMORY.md +52 -0
  424. memory/logs/2026-02-14.md +17 -0
  425. memory/logs/2026-03-03.md +2 -0
  426. memory/logs/__init__.py +1 -0
  427. tools/a2a/icdev_callback_client.py +210 -0
  428. tools/agent/cards/architect_card.json +29 -0
  429. tools/agent/cards/builder_card.json +34 -0
  430. tools/agent/cards/compliance_card.json +29 -0
  431. tools/agent/cards/connector_forge_card.json +49 -0
  432. tools/agent/cards/devsecops_zta_card.json +24 -0
  433. tools/agent/cards/knowledge_card.json +29 -0
  434. tools/agent/cards/monitor_card.json +29 -0
  435. tools/agent/cards/orchestrator_card.json +29 -0
  436. tools/agent/cards/requirements_analyst_card.json +24 -0
  437. tools/agent/cards/security_card.json +29 -0
  438. tools/agent/cards/simulation_card.json +24 -0
  439. tools/agent/cards/supply_chain_card.json +24 -0
  440. tools/analysis/__init__.py +1 -0
  441. tools/analysis/code_analyzer.py +770 -0
  442. tools/analysis/runtime_feedback.py +379 -0
  443. tools/analytics/__init__.py +2 -0
  444. tools/analytics/scorecard.py +538 -0
  445. tools/analytics/vsm_engine.py +612 -0
  446. tools/architecture/__init__.py +2 -0
  447. tools/architecture/adr_extractor.py +393 -0
  448. tools/audit/__init__.py +1 -0
  449. tools/audit/audit_logger.py +199 -0
  450. tools/audit/audit_query.py +153 -0
  451. tools/audit/decision_recorder.py +73 -0
  452. tools/audit_engine/__init__.py +12 -0
  453. tools/audit_engine/ai_advisor.py +906 -0
  454. tools/audit_engine/cli.py +286 -0
  455. tools/audit_engine/comparator.py +305 -0
  456. tools/audit_engine/eject_scaffolder.py +399 -0
  457. tools/audit_engine/engine.py +614 -0
  458. tools/audit_engine/git_fetcher.py +341 -0
  459. tools/audit_engine/regime_loader.py +200 -0
  460. tools/audit_engine/regime_updater.py +325 -0
  461. tools/audit_engine/report_card.py +289 -0
  462. tools/audit_engine/scanner.py +684 -0
  463. tools/audit_engine/self_heal.py +1042 -0
  464. tools/ci/__init__.py +2 -0
  465. tools/ci/connectors/__init__.py +2 -0
  466. tools/ci/connectors/base_connector.py +80 -0
  467. tools/ci/connectors/connector_registry.py +188 -0
  468. tools/ci/connectors/mattermost_connector.py +159 -0
  469. tools/ci/connectors/slack_connector.py +197 -0
  470. tools/ci/core/__init__.py +2 -0
  471. tools/ci/core/air_gap_detector.py +115 -0
  472. tools/ci/core/comment_handler.py +192 -0
  473. tools/ci/core/conversation_manager.py +480 -0
  474. tools/ci/core/event_envelope.py +500 -0
  475. tools/ci/core/event_router.py +444 -0
  476. tools/ci/core/failure_parser.py +397 -0
  477. tools/ci/core/recovery_engine.py +527 -0
  478. tools/ci/gate_enforcer.py +361 -0
  479. tools/ci/modules/__init__.py +2 -0
  480. tools/ci/modules/agent.py +271 -0
  481. tools/ci/modules/git_ops.py +175 -0
  482. tools/ci/modules/state.py +117 -0
  483. tools/ci/modules/vcs.py +303 -0
  484. tools/ci/modules/workflow_ops.py +295 -0
  485. tools/ci/modules/worktree.py +337 -0
  486. tools/ci/pipeline_config_generator.py +558 -0
  487. tools/ci/pr_intelligence.py +485 -0
  488. tools/ci/triggers/__init__.py +2 -0
  489. tools/ci/triggers/gitlab_task_monitor.py +327 -0
  490. tools/ci/triggers/poll_trigger.py +237 -0
  491. tools/ci/triggers/webhook_server.py +356 -0
  492. tools/ci/workflows/__init__.py +2 -0
  493. tools/ci/workflows/icdev_build.py +140 -0
  494. tools/ci/workflows/icdev_comply.py +284 -0
  495. tools/ci/workflows/icdev_document.py +152 -0
  496. tools/ci/workflows/icdev_e2e.py +188 -0
  497. tools/ci/workflows/icdev_patch.py +186 -0
  498. tools/ci/workflows/icdev_plan.py +202 -0
  499. tools/ci/workflows/icdev_plan_build.py +41 -0
  500. tools/ci/workflows/icdev_plan_build_test.py +46 -0
  501. tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
  502. tools/ci/workflows/icdev_review.py +126 -0
  503. tools/ci/workflows/icdev_sdlc.py +261 -0
  504. tools/ci/workflows/icdev_test.py +240 -0
  505. tools/cli/__init__.py +1 -0
  506. tools/cli/output_formatter.py +756 -0
  507. tools/cloudforge/__init__.py +12 -0
  508. tools/cloudforge/airgap/__init__.py +2 -0
  509. tools/cloudforge/airgap/il_classifier.py +70 -0
  510. tools/cloudforge/airgap/offline_validator.py +42 -0
  511. tools/cloudforge/airgap/shift_emulator.py +155 -0
  512. tools/cloudforge/airgap/sneakernet.py +91 -0
  513. tools/cloudforge/cd_hub/__init__.py +2 -0
  514. tools/cloudforge/cd_hub/canary_deployer.py +88 -0
  515. tools/cloudforge/cd_hub/gitops_renderer.py +123 -0
  516. tools/cloudforge/cd_hub/hub_controller.py +143 -0
  517. tools/cloudforge/cd_hub/pipeline_bridge.py +30 -0
  518. tools/cloudforge/cd_hub/rollback_engine.py +29 -0
  519. tools/cloudforge/cd_hub/spoke_agent.py +51 -0
  520. tools/cloudforge/compliance/__init__.py +2 -0
  521. tools/cloudforge/compliance/ato_accelerator.py +272 -0
  522. tools/cloudforge/compliance/control_inheritor.py +127 -0
  523. tools/cloudforge/compliance/evidence_generator.py +129 -0
  524. tools/cloudforge/compliance/poam_bridge.py +41 -0
  525. tools/cloudforge/compliance/ssp_bridge.py +52 -0
  526. tools/cloudforge/compliance/stig_bridge.py +41 -0
  527. tools/cloudforge/container_forge/__init__.py +2 -0
  528. tools/cloudforge/container_forge/bigbang_renderer.py +85 -0
  529. tools/cloudforge/container_forge/hardener.py +169 -0
  530. tools/cloudforge/container_forge/image_scanner_bridge.py +33 -0
  531. tools/cloudforge/container_forge/runtime_policy.py +87 -0
  532. tools/cloudforge/container_forge/sbom_bridge.py +42 -0
  533. tools/cloudforge/finops/__init__.py +2 -0
  534. tools/cloudforge/finops/anomaly_detector.py +78 -0
  535. tools/cloudforge/finops/budget_tracker.py +96 -0
  536. tools/cloudforge/finops/chargeback.py +69 -0
  537. tools/cloudforge/finops/cost_collector.py +141 -0
  538. tools/cloudforge/finops/optimizer.py +55 -0
  539. tools/cloudforge/hybrid/__init__.py +2 -0
  540. tools/cloudforge/hybrid/connection_manager.py +141 -0
  541. tools/cloudforge/hybrid/dns_federator.py +56 -0
  542. tools/cloudforge/hybrid/health_monitor.py +108 -0
  543. tools/cloudforge/hybrid/identity_federator.py +53 -0
  544. tools/cloudforge/hybrid/network_bridge.py +68 -0
  545. tools/cloudforge/hybrid/topology_manager.py +147 -0
  546. tools/cloudforge/hybrid/workload_abstractor.py +92 -0
  547. tools/cloudforge/iac/__init__.py +2 -0
  548. tools/cloudforge/iac/drift_detector.py +154 -0
  549. tools/cloudforge/iac/module_library.py +265 -0
  550. tools/cloudforge/iac/opentofu_adapter.py +89 -0
  551. tools/cloudforge/iac/pulumi_renderer.py +292 -0
  552. tools/cloudforge/iac/state_backend.py +146 -0
  553. tools/cloudforge/iac/terraform_renderer.py +626 -0
  554. tools/cloudforge/landing_zone/__init__.py +2 -0
  555. tools/cloudforge/landing_zone/blueprint_loader.py +98 -0
  556. tools/cloudforge/landing_zone/blueprint_validator.py +113 -0
  557. tools/cloudforge/landing_zone/zone_provisioner.py +306 -0
  558. tools/cloudforge/landing_zone/zone_state.py +143 -0
  559. tools/cloudforge/mbse_thread/__init__.py +2 -0
  560. tools/cloudforge/mbse_thread/ato_thread_weaver.py +111 -0
  561. tools/cloudforge/mbse_thread/control_tracer.py +68 -0
  562. tools/cloudforge/mbse_thread/system_boundary.py +83 -0
  563. tools/cloudforge/metastore/__init__.py +2 -0
  564. tools/cloudforge/metastore/dependency_graph.py +202 -0
  565. tools/cloudforge/metastore/discovery.py +192 -0
  566. tools/cloudforge/metastore/registry.py +185 -0
  567. tools/cloudforge/metastore/rto_tracker.py +92 -0
  568. tools/cloudforge/metastore/runbook_linker.py +82 -0
  569. tools/cloudforge/migration/__init__.py +2 -0
  570. tools/cloudforge/migration/assessor.py +187 -0
  571. tools/cloudforge/migration/cutover_orchestrator.py +117 -0
  572. tools/cloudforge/migration/databridge_bridge.py +92 -0
  573. tools/cloudforge/migration/planner.py +98 -0
  574. tools/cloudforge/migration/risk_scorer.py +97 -0
  575. tools/cloudforge/migration/validation_runner.py +45 -0
  576. tools/cloudforge/migration/workload_inventory.py +107 -0
  577. tools/cloudforge/provider.py +319 -0
  578. tools/cloudforge/providers/__init__.py +2 -0
  579. tools/cloudforge/providers/aws_commercial.py +92 -0
  580. tools/cloudforge/providers/aws_govcloud.py +229 -0
  581. tools/cloudforge/providers/aws_secret.py +83 -0
  582. tools/cloudforge/providers/azure_commercial.py +80 -0
  583. tools/cloudforge/providers/azure_gov.py +91 -0
  584. tools/cloudforge/providers/azure_secret.py +71 -0
  585. tools/cloudforge/providers/gcp.py +102 -0
  586. tools/cloudforge/providers/oci.py +102 -0
  587. tools/cloudforge/registry.py +140 -0
  588. tools/cloudforge/runbooks/__init__.py +2 -0
  589. tools/cloudforge/runbooks/ai_generator.py +119 -0
  590. tools/cloudforge/runbooks/dag_validator.py +219 -0
  591. tools/cloudforge/runbooks/engine.py +470 -0
  592. tools/cloudforge/runbooks/models.py +99 -0
  593. tools/cloudforge/runbooks/snippet_library.py +158 -0
  594. tools/cloudforge/runbooks/template_loader.py +122 -0
  595. tools/cloudforge/runbooks/visualization.py +108 -0
  596. tools/cloudforge/siem/__init__.py +2 -0
  597. tools/cloudforge/siem/alert_rules.py +86 -0
  598. tools/cloudforge/siem/correlation_engine.py +61 -0
  599. tools/cloudforge/siem/log_aggregator.py +113 -0
  600. tools/cloudforge/siem/siem_dashboard_data.py +28 -0
  601. tools/cloudforge/supply_chain/__init__.py +2 -0
  602. tools/cloudforge/supply_chain/bridge.py +33 -0
  603. tools/cloudforge/supply_chain/iac_dependency_scanner.py +36 -0
  604. tools/cloudforge/supply_chain/provider_trust_scorer.py +54 -0
  605. tools/compat/__init__.py +21 -0
  606. tools/compat/cli_harmonizer.py +251 -0
  607. tools/compat/datetime_utils.py +18 -0
  608. tools/compat/db_utils.py +190 -0
  609. tools/compat/platform_utils.py +123 -0
  610. tools/compliance/__init__.py +1 -0
  611. tools/compliance/accountability_manager.py +391 -0
  612. tools/compliance/ai_accountability_audit.py +287 -0
  613. tools/compliance/ai_impact_assessor.py +267 -0
  614. tools/compliance/ai_incident_response.py +295 -0
  615. tools/compliance/ai_inventory_manager.py +233 -0
  616. tools/compliance/ai_reassessment_scheduler.py +250 -0
  617. tools/compliance/ai_transparency_audit.py +247 -0
  618. tools/compliance/atlas_assessor.py +276 -0
  619. tools/compliance/atlas_report_generator.py +1199 -0
  620. tools/compliance/base_assessor.py +591 -0
  621. tools/compliance/cato_live_engine.py +607 -0
  622. tools/compliance/cato_monitor.py +1371 -0
  623. tools/compliance/cato_scheduler.py +698 -0
  624. tools/compliance/cjis_assessor.py +76 -0
  625. tools/compliance/classification_manager.py +1340 -0
  626. tools/compliance/cmmc_assessor.py +1478 -0
  627. tools/compliance/cmmc_report_generator.py +1087 -0
  628. tools/compliance/compliance_detector.py +452 -0
  629. tools/compliance/compliance_exporter.py +418 -0
  630. tools/compliance/compliance_status.py +810 -0
  631. tools/compliance/control_mapper.py +488 -0
  632. tools/compliance/crosswalk_engine.py +1208 -0
  633. tools/compliance/cssp_assessor.py +1032 -0
  634. tools/compliance/cssp_evidence_collector.py +716 -0
  635. tools/compliance/cssp_report_generator.py +1103 -0
  636. tools/compliance/cui_marker.py +387 -0
  637. tools/compliance/diagram_validator.py +599 -0
  638. tools/compliance/emass/__init__.py +2 -0
  639. tools/compliance/emass/emass_client.py +822 -0
  640. tools/compliance/emass/emass_export.py +758 -0
  641. tools/compliance/emass/emass_sync.py +807 -0
  642. tools/compliance/eu_ai_act_classifier.py +193 -0
  643. tools/compliance/evidence_collector.py +459 -0
  644. tools/compliance/fairness_assessor.py +310 -0
  645. tools/compliance/fedramp_20x_ksi_emitter.py +692 -0
  646. tools/compliance/fedramp_assessor.py +1795 -0
  647. tools/compliance/fedramp_authorization_packager.py +137 -0
  648. tools/compliance/fedramp_ksi_generator.py +349 -0
  649. tools/compliance/fedramp_report_generator.py +1115 -0
  650. tools/compliance/fips199_categorizer.py +869 -0
  651. tools/compliance/fips200_validator.py +304 -0
  652. tools/compliance/firmware_sbom.py +646 -0
  653. tools/compliance/gao_ai_assessor.py +228 -0
  654. tools/compliance/gao_evidence_builder.py +302 -0
  655. tools/compliance/hipaa_assessor.py +78 -0
  656. tools/compliance/hitrust_assessor.py +49 -0
  657. tools/compliance/incident_response_plan.py +705 -0
  658. tools/compliance/inheritance_engine.py +693 -0
  659. tools/compliance/iso27001_assessor.py +92 -0
  660. tools/compliance/iso42001_assessor.py +114 -0
  661. tools/compliance/ivv_assessor.py +2314 -0
  662. tools/compliance/ivv_report_generator.py +1649 -0
  663. tools/compliance/model_card_generator.py +291 -0
  664. tools/compliance/mosa_assessor.py +117 -0
  665. tools/compliance/multi_regime_assessor.py +441 -0
  666. tools/compliance/narrative_generator.py +1012 -0
  667. tools/compliance/narrative_quality_gate.py +701 -0
  668. tools/compliance/narrative_workflow.py +814 -0
  669. tools/compliance/nist_800_207_assessor.py +191 -0
  670. tools/compliance/nist_ai_600_1_assessor.py +185 -0
  671. tools/compliance/nist_ai_rmf_assessor.py +110 -0
  672. tools/compliance/nist_lookup.py +244 -0
  673. tools/compliance/omb_m25_21_assessor.py +225 -0
  674. tools/compliance/omb_m26_04_assessor.py +185 -0
  675. tools/compliance/oscal_catalog_adapter.py +395 -0
  676. tools/compliance/oscal_generator.py +2157 -0
  677. tools/compliance/oscal_tools.py +1182 -0
  678. tools/compliance/oscal_validator.py +692 -0
  679. tools/compliance/owasp_agentic_assessor.py +227 -0
  680. tools/compliance/owasp_asi_assessor.py +197 -0
  681. tools/compliance/owasp_llm_assessor.py +245 -0
  682. tools/compliance/pci_dss_assessor.py +80 -0
  683. tools/compliance/pi_compliance_tracker.py +1447 -0
  684. tools/compliance/poam_generator.py +388 -0
  685. tools/compliance/resolve_marking.py +272 -0
  686. tools/compliance/sbd_assessor.py +2070 -0
  687. tools/compliance/sbd_report_generator.py +1223 -0
  688. tools/compliance/sbom_generator.py +993 -0
  689. tools/compliance/siem_config_generator.py +661 -0
  690. tools/compliance/slsa_attestation_generator.py +479 -0
  691. tools/compliance/soc2_assessor.py +77 -0
  692. tools/compliance/ssp_generator.py +556 -0
  693. tools/compliance/stig_checker.py +712 -0
  694. tools/compliance/swft_evidence_bundler.py +326 -0
  695. tools/compliance/system_card_generator.py +303 -0
  696. tools/compliance/template_exchange.py +513 -0
  697. tools/compliance/traceability_matrix.py +1268 -0
  698. tools/compliance/universal_classification_manager.py +1159 -0
  699. tools/compliance/xacta/__init__.py +2 -0
  700. tools/compliance/xacta/xacta_client.py +438 -0
  701. tools/compliance/xacta/xacta_export.py +546 -0
  702. tools/compliance/xacta/xacta_sync.py +322 -0
  703. tools/compliance/xai_assessor.py +231 -0
  704. tools/core/__init__.py +2 -0
  705. tools/core/circuit_breaker.py +353 -0
  706. tools/core/compliance_sidecar.py +344 -0
  707. tools/core/container.py +110 -0
  708. tools/core/errors.py +256 -0
  709. tools/core/feature_flags.py +311 -0
  710. tools/core/task_dlq.py +350 -0
  711. tools/dashboard/__init__.py +2 -0
  712. tools/dashboard/app.py +6288 -0
  713. tools/dashboard/templates/agent_evolution.html +287 -0
  714. tools/dashboard/templates/agents/list.html +71 -0
  715. tools/dashboard/templates/agents.html +132 -0
  716. tools/dashboard/templates/architecture.html +289 -0
  717. tools/dashboard/templates/ato_simulator.html +170 -0
  718. tools/dashboard/templates/audit_engine.html +844 -0
  719. tools/dashboard/templates/base.html +236 -0
  720. tools/dashboard/templates/cato_live.html +116 -0
  721. tools/dashboard/templates/cloudforge.html +195 -0
  722. tools/dashboard/templates/cloudforge_finops.html +111 -0
  723. tools/dashboard/templates/cloudforge_hybrid.html +122 -0
  724. tools/dashboard/templates/cloudforge_metastore.html +234 -0
  725. tools/dashboard/templates/cloudforge_migration.html +87 -0
  726. tools/dashboard/templates/cloudforge_runbooks.html +201 -0
  727. tools/dashboard/templates/cloudforge_siem.html +94 -0
  728. tools/dashboard/templates/compliance_accel.html +292 -0
  729. tools/dashboard/templates/crashes.html +122 -0
  730. tools/dashboard/templates/databridge.html +305 -0
  731. tools/dashboard/templates/databridge_analytics.html +195 -0
  732. tools/dashboard/templates/databridge_mapping.html +345 -0
  733. tools/dashboard/templates/databridge_messaging.html +321 -0
  734. tools/dashboard/templates/decisions.html +258 -0
  735. tools/dashboard/templates/devices.html +151 -0
  736. tools/dashboard/templates/devsecops_maturity.html +278 -0
  737. tools/dashboard/templates/edge_ai.html +128 -0
  738. tools/dashboard/templates/firmware.html +120 -0
  739. tools/dashboard/templates/firmware_sbom.html +193 -0
  740. tools/dashboard/templates/forge_hub.html +196 -0
  741. tools/dashboard/templates/forge_studio.html +379 -0
  742. tools/dashboard/templates/forge_studio_analytics.html +360 -0
  743. tools/dashboard/templates/forge_studio_builder.html +1637 -0
  744. tools/dashboard/templates/forge_studio_compliance.html +310 -0
  745. tools/dashboard/templates/forge_studio_deploy.html +573 -0
  746. tools/dashboard/templates/forge_studio_enterprise.html +888 -0
  747. tools/dashboard/templates/forge_studio_marketplace.html +502 -0
  748. tools/dashboard/templates/forge_studio_workflow.html +696 -0
  749. tools/dashboard/templates/golden_path.html +175 -0
  750. tools/dashboard/templates/govcon.html +280 -0
  751. tools/dashboard/templates/harness.html +148 -0
  752. tools/dashboard/templates/index.html +207 -0
  753. tools/dashboard/templates/intelligence.html +336 -0
  754. tools/dashboard/templates/knowledge/index.html +190 -0
  755. tools/dashboard/templates/knowledge_graph.html +739 -0
  756. tools/dashboard/templates/login.html +51 -0
  757. tools/dashboard/templates/marketplace.html +336 -0
  758. tools/dashboard/templates/marketplace_admin.html +247 -0
  759. tools/dashboard/templates/missions.html +403 -0
  760. tools/dashboard/templates/narratives.html +154 -0
  761. tools/dashboard/templates/pr_intelligence.html +151 -0
  762. tools/dashboard/templates/proposals/detail.html +300 -0
  763. tools/dashboard/templates/proposals/list.html +52 -0
  764. tools/dashboard/templates/proposals/sam_detail.html +132 -0
  765. tools/dashboard/templates/proposals/section_detail.html +375 -0
  766. tools/dashboard/templates/research.html +222 -0
  767. tools/dashboard/templates/resilience.html +300 -0
  768. tools/dashboard/templates/scorecard.html +162 -0
  769. tools/dashboard/templates/simulator.html +131 -0
  770. tools/dashboard/templates/template_exchange.html +147 -0
  771. tools/dashboard/templates/thread_heatmap.html +151 -0
  772. tools/dashboard/templates/threat_model.html +195 -0
  773. tools/dashboard/templates/vsm.html +141 -0
  774. tools/dashboard/templates/writeguard.html +277 -0
  775. tools/databridge/__init__.py +5 -0
  776. tools/databridge/agent/__init__.py +2 -0
  777. tools/databridge/agent/daemon.py +227 -0
  778. tools/databridge/agent/tunnel.py +101 -0
  779. tools/databridge/agent/ws_relay.py +91 -0
  780. tools/databridge/analytics.py +167 -0
  781. tools/databridge/arrow_pipeline.py +327 -0
  782. tools/databridge/connection_manager.py +424 -0
  783. tools/databridge/connector.py +331 -0
  784. tools/databridge/connectors/__init__.py +2 -0
  785. tools/databridge/connectors/argocd_connector.py +160 -0
  786. tools/databridge/connectors/avro_connector.py +203 -0
  787. tools/databridge/connectors/azure_blob.py +63 -0
  788. tools/databridge/connectors/cdc_connector.py +205 -0
  789. tools/databridge/connectors/csv_connector.py +172 -0
  790. tools/databridge/connectors/datadog_connector.py +153 -0
  791. tools/databridge/connectors/discord_messaging.py +215 -0
  792. tools/databridge/connectors/dynamics365.py +151 -0
  793. tools/databridge/connectors/elasticsearch_connector.py +145 -0
  794. tools/databridge/connectors/email_base.py +114 -0
  795. tools/databridge/connectors/excel_connector.py +175 -0
  796. tools/databridge/connectors/fsspec_base.py +300 -0
  797. tools/databridge/connectors/gcs.py +53 -0
  798. tools/databridge/connectors/github_connector.py +138 -0
  799. tools/databridge/connectors/gitlab_connector.py +132 -0
  800. tools/databridge/connectors/gmail_connector.py +182 -0
  801. tools/databridge/connectors/hdfs.py +57 -0
  802. tools/databridge/connectors/health_base.py +401 -0
  803. tools/databridge/connectors/hubspot.py +124 -0
  804. tools/databridge/connectors/imap_connector.py +171 -0
  805. tools/databridge/connectors/jenkins_connector.py +138 -0
  806. tools/databridge/connectors/jira_connector.py +86 -0
  807. tools/databridge/connectors/json_connector.py +184 -0
  808. tools/databridge/connectors/kafka_connector.py +246 -0
  809. tools/databridge/connectors/kinesis_connector.py +238 -0
  810. tools/databridge/connectors/local_fs.py +30 -0
  811. tools/databridge/connectors/matrix.py +197 -0
  812. tools/databridge/connectors/mattermost_messaging.py +184 -0
  813. tools/databridge/connectors/messaging_base.py +172 -0
  814. tools/databridge/connectors/mssql.py +63 -0
  815. tools/databridge/connectors/mysql.py +57 -0
  816. tools/databridge/connectors/netsuite.py +170 -0
  817. tools/databridge/connectors/o365_mail.py +196 -0
  818. tools/databridge/connectors/oracle.py +65 -0
  819. tools/databridge/connectors/pagerduty_connector.py +162 -0
  820. tools/databridge/connectors/parquet_connector.py +131 -0
  821. tools/databridge/connectors/postgresql.py +58 -0
  822. tools/databridge/connectors/s3.py +65 -0
  823. tools/databridge/connectors/saas_base.py +198 -0
  824. tools/databridge/connectors/salesforce.py +126 -0
  825. tools/databridge/connectors/sap.py +89 -0
  826. tools/databridge/connectors/servicenow.py +60 -0
  827. tools/databridge/connectors/signal_messaging.py +150 -0
  828. tools/databridge/connectors/slack_messaging.py +203 -0
  829. tools/databridge/connectors/smtp_connector.py +126 -0
  830. tools/databridge/connectors/soap_base.py +258 -0
  831. tools/databridge/connectors/splunk_connector.py +171 -0
  832. tools/databridge/connectors/sql_base.py +310 -0
  833. tools/databridge/connectors/sqlite_connector.py +76 -0
  834. tools/databridge/connectors/teams.py +148 -0
  835. tools/databridge/connectors/telegram.py +192 -0
  836. tools/databridge/connectors/whatsapp.py +137 -0
  837. tools/databridge/data_profiler.py +99 -0
  838. tools/databridge/forge/__init__.py +6 -0
  839. tools/databridge/forge/base_selector.py +150 -0
  840. tools/databridge/forge/code_generator.py +206 -0
  841. tools/databridge/forge/community_hub.py +539 -0
  842. tools/databridge/forge/forge_agent.py +306 -0
  843. tools/databridge/forge/import_handler.py +133 -0
  844. tools/databridge/forge/integration_tester.py +127 -0
  845. tools/databridge/forge/marketplace_publisher.py +164 -0
  846. tools/databridge/forge/promoter.py +159 -0
  847. tools/databridge/forge/sandbox_manager.py +257 -0
  848. tools/databridge/forge/spec_parser.py +358 -0
  849. tools/databridge/forge/static_validator.py +363 -0
  850. tools/databridge/forge/templates/__init__.py +591 -0
  851. tools/databridge/format_converter.py +188 -0
  852. tools/databridge/mapping_engine.py +348 -0
  853. tools/databridge/messaging/__init__.py +5 -0
  854. tools/databridge/messaging/agent_bridge.py +254 -0
  855. tools/databridge/messaging/message_envelope.py +111 -0
  856. tools/databridge/messaging/message_logger.py +204 -0
  857. tools/databridge/messaging/messaging_daemon.py +326 -0
  858. tools/databridge/messaging/oauth2_manager.py +411 -0
  859. tools/databridge/pii_detector.py +221 -0
  860. tools/databridge/registry.py +352 -0
  861. tools/databridge/relay_server.py +105 -0
  862. tools/databridge/scale/__init__.py +16 -0
  863. tools/databridge/scale/backpressure.py +134 -0
  864. tools/databridge/scale/chunked_pipeline.py +169 -0
  865. tools/databridge/scale/connection_pool.py +293 -0
  866. tools/databridge/scale/engine.py +492 -0
  867. tools/databridge/scale/worker_pool.py +140 -0
  868. tools/databridge/scale/write_batcher.py +250 -0
  869. tools/databridge/schema_engine.py +324 -0
  870. tools/databridge/stream_manager.py +225 -0
  871. tools/databridge/sync_engine.py +411 -0
  872. tools/databridge/transforms.py +302 -0
  873. tools/db/__init__.py +1 -0
  874. tools/db/backup.py +312 -0
  875. tools/db/backup_manager.py +832 -0
  876. tools/db/init_icdev_db.py +7753 -0
  877. tools/db/init_sparkpilot_db.py +431 -0
  878. tools/db/migrate.py +177 -0
  879. tools/db/migrate_innovation_audit.py +165 -0
  880. tools/db/migration_runner.py +548 -0
  881. tools/db/migrations/001_baseline/meta.json +9 -0
  882. tools/db/migrations/001_baseline/up.py +67 -0
  883. tools/db/migrations/002_memory_enhancements/down.sql +8 -0
  884. tools/db/migrations/002_memory_enhancements/meta.json +9 -0
  885. tools/db/migrations/002_memory_enhancements/up.py +119 -0
  886. tools/db/migrations/003_dev_profiles/meta.json +8 -0
  887. tools/db/migrations/003_dev_profiles/up.py +93 -0
  888. tools/db/migrations/004_innovation_engine/down.py +19 -0
  889. tools/db/migrations/004_innovation_engine/up.py +227 -0
  890. tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
  891. tools/db/migrations/005_phase_37_ai_security/up.py +257 -0
  892. tools/db/migrations/006_phase_36_evolution/down.py +21 -0
  893. tools/db/migrations/006_phase_36_evolution/up.py +323 -0
  894. tools/db/migrations/007_phase_38_cloud/down.py +14 -0
  895. tools/db/migrations/007_phase_38_cloud/up.py +110 -0
  896. tools/db/migrations/008_phase36_37_integration/up.py +55 -0
  897. tools/db/migrations/__init__.py +2 -0
  898. tools/db/pg_migrate.py +642 -0
  899. tools/db/storage.py +1080 -0
  900. tools/decisions/__init__.py +2 -0
  901. tools/decisions/dmn_engine.py +695 -0
  902. tools/devsecops/__init__.py +2 -0
  903. tools/devsecops/attestation_manager.py +449 -0
  904. tools/devsecops/network_segmentation_generator.py +604 -0
  905. tools/devsecops/pdp_config_generator.py +1246 -0
  906. tools/devsecops/pipeline_security_generator.py +475 -0
  907. tools/devsecops/policy_generator.py +644 -0
  908. tools/devsecops/profile_manager.py +374 -0
  909. tools/devsecops/service_mesh_generator.py +1063 -0
  910. tools/devsecops/zta_maturity_scorer.py +355 -0
  911. tools/devsecops/zta_terraform_generator.py +1301 -0
  912. tools/edge_ai/__init__.py +2 -0
  913. tools/edge_ai/model_manager.py +200 -0
  914. tools/embedded/__init__.py +2 -0
  915. tools/embedded/cmake_generator.py +318 -0
  916. tools/embedded/crash_analyzer.py +191 -0
  917. tools/embedded/nl_to_firmware.py +277 -0
  918. tools/events/__init__.py +1 -0
  919. tools/events/event_bus.py +199 -0
  920. tools/finetune/pair_generator.py +832 -0
  921. tools/fleet/__init__.py +2 -0
  922. tools/fleet/device_registry.py +148 -0
  923. tools/fleet/ota_manager.py +153 -0
  924. tools/forge_studio/__init__.py +13 -0
  925. tools/forge_studio/analytics/__init__.py +0 -0
  926. tools/forge_studio/analytics/process_miner.py +383 -0
  927. tools/forge_studio/audit.py +183 -0
  928. tools/forge_studio/blueprint/__init__.py +2 -0
  929. tools/forge_studio/blueprint/build_tracker.py +317 -0
  930. tools/forge_studio/blueprint/export_engine.py +441 -0
  931. tools/forge_studio/blueprint/parent_client.py +335 -0
  932. tools/forge_studio/catalog/__init__.py +2 -0
  933. tools/forge_studio/catalog/component_registry.py +176 -0
  934. tools/forge_studio/catalog/schema_validator.py +193 -0
  935. tools/forge_studio/compliance/__init__.py +1 -0
  936. tools/forge_studio/compliance/compliance_wiring.py +554 -0
  937. tools/forge_studio/deploy/__init__.py +1 -0
  938. tools/forge_studio/deploy/airgap_packager.py +466 -0
  939. tools/forge_studio/deploy/deploy_engine.py +1792 -0
  940. tools/forge_studio/deploy/env_manager.py +431 -0
  941. tools/forge_studio/eject/__init__.py +2 -0
  942. tools/forge_studio/eject/docker_compose_generator.py +237 -0
  943. tools/forge_studio/eject/eject_engine.py +230 -0
  944. tools/forge_studio/eject/expo_scaffolder.py +303 -0
  945. tools/forge_studio/eject/nextjs_scaffolder.py +338 -0
  946. tools/forge_studio/enterprise/__init__.py +0 -0
  947. tools/forge_studio/enterprise/custom_frameworks.py +826 -0
  948. tools/forge_studio/enterprise/hardening_engine.py +1530 -0
  949. tools/forge_studio/enterprise/sso_manager.py +718 -0
  950. tools/forge_studio/enterprise/whitelabel_engine.py +887 -0
  951. tools/forge_studio/formula/__init__.py +0 -0
  952. tools/forge_studio/formula/expression_engine.py +562 -0
  953. tools/forge_studio/formula/formula_registry.py +265 -0
  954. tools/forge_studio/generator/__init__.py +2 -0
  955. tools/forge_studio/generator/app_generator.py +584 -0
  956. tools/forge_studio/generator/complexity_detector.py +368 -0
  957. tools/forge_studio/generator/prompt_templates.py +104 -0
  958. tools/forge_studio/generator/spec_builder.py +192 -0
  959. tools/forge_studio/intake_bridge.py +898 -0
  960. tools/forge_studio/marketplace/__init__.py +0 -0
  961. tools/forge_studio/marketplace/component_hub.py +428 -0
  962. tools/forge_studio/models.py +369 -0
  963. tools/forge_studio/renderer/__init__.py +2 -0
  964. tools/forge_studio/renderer/json_render_engine.py +623 -0
  965. tools/forge_studio/renderer/layout_engine.py +214 -0
  966. tools/forge_studio/renderer/rn_component_map.py +182 -0
  967. tools/forge_studio/supabase/__init__.py +2 -0
  968. tools/forge_studio/supabase/auth_generator.py +283 -0
  969. tools/forge_studio/supabase/migration_generator.py +93 -0
  970. tools/forge_studio/supabase/schema_generator.py +281 -0
  971. tools/forge_studio/tenant_manager.py +387 -0
  972. tools/forge_studio/workflow/__init__.py +2 -0
  973. tools/forge_studio/workflow/bpmn_adapter.py +489 -0
  974. tools/govcon/draft_orchestrator.py +1151 -0
  975. tools/govcon/engine_enrichment.py +373 -0
  976. tools/govcon/knowledge_base.py +487 -0
  977. tools/govcon/knowledge_ingestion.py +510 -0
  978. tools/govcon/sam_scanner.py +754 -0
  979. tools/harness/__init__.py +6 -0
  980. tools/harness/exit_criteria_evaluator.py +231 -0
  981. tools/harness/maturity_assessor.py +347 -0
  982. tools/harness/scaffold_harness.py +416 -0
  983. tools/harness/trace_analyzer.py +281 -0
  984. tools/infra/__init__.py +1 -0
  985. tools/infra/ansible_generator.py +867 -0
  986. tools/infra/dockerfile_generator.py +359 -0
  987. tools/infra/infra_status.py +384 -0
  988. tools/infra/ironbank_metadata_generator.py +403 -0
  989. tools/infra/k8s_generator.py +1000 -0
  990. tools/infra/pipeline_generator.py +830 -0
  991. tools/infra/rollback.py +389 -0
  992. tools/infra/terraform_generator.py +1140 -0
  993. tools/infra/terraform_generator_azure.py +1252 -0
  994. tools/infra/terraform_generator_gcp.py +951 -0
  995. tools/infra/terraform_generator_ibm.py +359 -0
  996. tools/infra/terraform_generator_oci.py +918 -0
  997. tools/infra/terraform_generator_onprem.py +318 -0
  998. tools/knowledge/__init__.py +1 -0
  999. tools/knowledge/knowledge_ingest.py +281 -0
  1000. tools/knowledge/pattern_detector.py +681 -0
  1001. tools/knowledge/recommendation_engine.py +449 -0
  1002. tools/knowledge/self_heal_analyzer.py +492 -0
  1003. tools/knowledge_graph/__init__.py +2 -0
  1004. tools/knowledge_graph/graph_rag.py +498 -0
  1005. tools/knowledge_graph/ingester.py +406 -0
  1006. tools/knowledge_graph/insight_generator.py +369 -0
  1007. tools/knowledge_graph/text_network.py +832 -0
  1008. tools/llm/__init__.py +72 -0
  1009. tools/llm/anthropic_provider.py +170 -0
  1010. tools/llm/azure_openai_provider.py +338 -0
  1011. tools/llm/bedrock_provider.py +315 -0
  1012. tools/llm/embedding_provider.py +438 -0
  1013. tools/llm/gemini_provider.py +381 -0
  1014. tools/llm/ibm_watsonx_provider.py +231 -0
  1015. tools/llm/oci_genai_provider.py +462 -0
  1016. tools/llm/ollama_provider.py +350 -0
  1017. tools/llm/openai_provider.py +225 -0
  1018. tools/llm/prompt_registry.py +447 -0
  1019. tools/llm/provider.py +355 -0
  1020. tools/llm/provider_sdk.py +175 -0
  1021. tools/llm/router.py +1124 -0
  1022. tools/llm/semantic_cache.py +394 -0
  1023. tools/llm/vertex_ai_provider.py +374 -0
  1024. tools/maintenance/__init__.py +2 -0
  1025. tools/maintenance/dependency_scanner.py +1016 -0
  1026. tools/maintenance/maintenance_auditor.py +804 -0
  1027. tools/maintenance/remediation_engine.py +957 -0
  1028. tools/maintenance/vulnerability_checker.py +978 -0
  1029. tools/manifest.md +1066 -0
  1030. tools/marketplace/asset_installer.py +639 -0
  1031. tools/marketplace/feedback_validator.py +359 -0
  1032. tools/marketplace/license_client.py +458 -0
  1033. tools/marketplace/module_crypto.py +544 -0
  1034. tools/marketplace/module_runtime.py +236 -0
  1035. tools/marketplace/token_store.py +264 -0
  1036. tools/mbse/__init__.py +3 -0
  1037. tools/mbse/des_assessor.py +1173 -0
  1038. tools/mbse/des_report_generator.py +787 -0
  1039. tools/mbse/diagram_extractor.py +792 -0
  1040. tools/mbse/digital_thread.py +1650 -0
  1041. tools/mbse/model_code_generator.py +1115 -0
  1042. tools/mbse/model_control_mapper.py +410 -0
  1043. tools/mbse/pi_model_tracker.py +1079 -0
  1044. tools/mbse/reqif_parser.py +1468 -0
  1045. tools/mbse/sync_engine.py +1789 -0
  1046. tools/mbse/thread_heatmap.py +445 -0
  1047. tools/mbse/xmi_parser.py +1558 -0
  1048. tools/mcp/builder_server.py +64 -0
  1049. tools/mcp/compliance_server.py +64 -0
  1050. tools/mcp/connector_forge_server.py +155 -0
  1051. tools/mcp/core_server.py +64 -0
  1052. tools/mcp/devsecops_server.py +11 -0
  1053. tools/mcp/devsecops_zta_server.py +64 -0
  1054. tools/mcp/knowledge_server.py +64 -0
  1055. tools/mcp/monitor_server.py +64 -0
  1056. tools/mcp/ops_server.py +300 -0
  1057. tools/mcp/requirements_analyst_server.py +64 -0
  1058. tools/mcp/requirements_server.py +11 -0
  1059. tools/mcp/security_server.py +64 -0
  1060. tools/mcp/simulation_server.py +64 -0
  1061. tools/mcp/supply_chain_server.py +64 -0
  1062. tools/mcp/tool_registry.py +299 -0
  1063. tools/memory/__init__.py +2 -0
  1064. tools/memory/auto_capture.py +346 -0
  1065. tools/memory/embed_memory.py +157 -0
  1066. tools/memory/history_compressor.py +334 -0
  1067. tools/memory/hybrid_search.py +235 -0
  1068. tools/memory/maintenance_cron.py +288 -0
  1069. tools/memory/memory_consolidation.py +439 -0
  1070. tools/memory/memory_db.py +132 -0
  1071. tools/memory/memory_read.py +101 -0
  1072. tools/memory/memory_write.py +221 -0
  1073. tools/memory/semantic_search.py +138 -0
  1074. tools/memory/time_decay.py +434 -0
  1075. tools/missions/__init__.py +2 -0
  1076. tools/missions/mission_engine.py +459 -0
  1077. tools/monitor/__init__.py +1 -0
  1078. tools/monitor/alert_correlator.py +486 -0
  1079. tools/monitor/auto_resolver.py +603 -0
  1080. tools/monitor/health_checker.py +507 -0
  1081. tools/monitor/heartbeat_daemon.py +779 -0
  1082. tools/monitor/log_analyzer.py +507 -0
  1083. tools/monitor/metric_collector.py +484 -0
  1084. tools/mosa/__init__.py +10 -0
  1085. tools/mosa/icd_generator.py +358 -0
  1086. tools/mosa/modular_design_analyzer.py +682 -0
  1087. tools/mosa/mosa_code_enforcer.py +348 -0
  1088. tools/mosa/tsp_generator.py +265 -0
  1089. tools/observability/__init__.py +100 -0
  1090. tools/observability/genai_attributes.py +88 -0
  1091. tools/observability/instrumentation.py +140 -0
  1092. tools/observability/mlflow_exporter.py +193 -0
  1093. tools/observability/otel_tracer.py +168 -0
  1094. tools/observability/provenance/__init__.py +3 -0
  1095. tools/observability/provenance/prov_recorder.py +322 -0
  1096. tools/observability/shap/__init__.py +3 -0
  1097. tools/observability/shap/agent_shap.py +274 -0
  1098. tools/observability/sqlite_tracer.py +360 -0
  1099. tools/observability/trace_context.py +205 -0
  1100. tools/observability/tracer.py +230 -0
  1101. tools/orchestration/__init__.py +1 -0
  1102. tools/orchestration/peer_channels.py +254 -0
  1103. tools/orchestration/saga_coordinator.py +390 -0
  1104. tools/project/__init__.py +1 -0
  1105. tools/project/manifest_loader.py +418 -0
  1106. tools/project/project_create.py +350 -0
  1107. tools/project/project_list.py +171 -0
  1108. tools/project/project_scaffold.py +1715 -0
  1109. tools/project/project_status.py +478 -0
  1110. tools/project/session_context_builder.py +752 -0
  1111. tools/project/validate_manifest.py +54 -0
  1112. tools/rag/corrective_rag.py +582 -0
  1113. tools/rag/source_registry.py +482 -0
  1114. tools/requirements/__init__.py +1 -0
  1115. tools/requirements/ai_governance_scorer.py +207 -0
  1116. tools/requirements/boundary_analyzer.py +1281 -0
  1117. tools/requirements/clarification_engine.py +605 -0
  1118. tools/requirements/complexity_scorer.py +369 -0
  1119. tools/requirements/consistency_analyzer.py +789 -0
  1120. tools/requirements/constitution_manager.py +592 -0
  1121. tools/requirements/decomposition_engine.py +764 -0
  1122. tools/requirements/document_extractor.py +1002 -0
  1123. tools/requirements/elicitation_techniques.py +508 -0
  1124. tools/requirements/gap_detector.py +260 -0
  1125. tools/requirements/intake_engine.py +2175 -0
  1126. tools/requirements/prd_generator.py +839 -0
  1127. tools/requirements/prd_validator.py +584 -0
  1128. tools/requirements/readiness_scorer.py +302 -0
  1129. tools/requirements/spec_organizer.py +1015 -0
  1130. tools/requirements/spec_quality_checker.py +1083 -0
  1131. tools/requirements/traceability_builder.py +566 -0
  1132. tools/research/__init__.py +3 -0
  1133. tools/research/academic_scanner.py +130 -0
  1134. tools/research/build_buy_analyzer.py +229 -0
  1135. tools/research/challenge_scorer.py +280 -0
  1136. tools/research/community_scanner.py +174 -0
  1137. tools/research/cross_engine_bridge.py +124 -0
  1138. tools/research/dossier_generator.py +305 -0
  1139. tools/research/landscape_scanner.py +315 -0
  1140. tools/research/regulatory_scanner.py +248 -0
  1141. tools/research/research_manager.py +469 -0
  1142. tools/research/source_scanner.py +150 -0
  1143. tools/research/vertical_loader.py +118 -0
  1144. tools/saas/__init__.py +0 -0
  1145. tools/saas/licensing/__init__.py +0 -0
  1146. tools/saas/licensing/license_validator.py +345 -0
  1147. tools/scaffold/__init__.py +2 -0
  1148. tools/scaffold/golden_path.py +504 -0
  1149. tools/security/__init__.py +1 -0
  1150. tools/security/agent_output_validator.py +330 -0
  1151. tools/security/agent_trust_scorer.py +652 -0
  1152. tools/security/ai_bom_generator.py +718 -0
  1153. tools/security/ai_telemetry_logger.py +469 -0
  1154. tools/security/atlas_red_team.py +541 -0
  1155. tools/security/code_pattern_scanner.py +382 -0
  1156. tools/security/confabulation_detector.py +265 -0
  1157. tools/security/container_scanner.py +489 -0
  1158. tools/security/dependency_auditor.py +942 -0
  1159. tools/security/endpoint_security_scanner.py +626 -0
  1160. tools/security/mcp_tool_authorizer.py +242 -0
  1161. tools/security/output_verifier.py +427 -0
  1162. tools/security/prompt_injection_detector.py +737 -0
  1163. tools/security/sast_runner.py +946 -0
  1164. tools/security/secret_detector.py +376 -0
  1165. tools/security/threat_modeler.py +678 -0
  1166. tools/security/tool_chain_validator.py +357 -0
  1167. tools/security/vuln_scanner.py +536 -0
  1168. tools/simulation/__init__.py +2 -0
  1169. tools/simulation/ato_simulator.py +517 -0
  1170. tools/simulation/coa_generator.py +1539 -0
  1171. tools/simulation/monte_carlo.py +745 -0
  1172. tools/simulation/scenario_manager.py +1060 -0
  1173. tools/simulation/simulation_engine.py +1091 -0
  1174. tools/simulator/__init__.py +2 -0
  1175. tools/simulator/sim_runner.py +272 -0
  1176. tools/supply_chain/__init__.py +2 -0
  1177. tools/supply_chain/cve_triager.py +690 -0
  1178. tools/supply_chain/dependency_graph.py +630 -0
  1179. tools/supply_chain/isa_manager.py +526 -0
  1180. tools/supply_chain/scrm_assessor.py +531 -0
  1181. tools/supply_chain/slsa_verifier.py +473 -0
  1182. tools/testing/__init__.py +2 -0
  1183. tools/testing/acceptance_validator.py +411 -0
  1184. tools/testing/api_surface_extractor.py +749 -0
  1185. tools/testing/claude_dir_validator.py +831 -0
  1186. tools/testing/data_types.py +199 -0
  1187. tools/testing/e2e_runner.py +715 -0
  1188. tools/testing/fuzz_cli.py +306 -0
  1189. tools/testing/health_check.py +483 -0
  1190. tools/testing/platform_check.py +143 -0
  1191. tools/testing/production_audit.py +1836 -0
  1192. tools/testing/production_remediate.py +803 -0
  1193. tools/testing/screenshot_validator.py +538 -0
  1194. tools/testing/smoke_test.py +283 -0
  1195. tools/testing/test_agent_models.py +117 -0
  1196. tools/testing/test_orchestrator.py +957 -0
  1197. tools/testing/utils.py +229 -0
  1198. tools/writeguard/__init__.py +1 -0
  1199. tools/writeguard/main.py +1 -0
  1200. tools/writing/__init__.py +7 -0
  1201. tools/writing/ai_content_detector.py +316 -0
  1202. tools/writing/analysis_engine.py +454 -0
  1203. tools/writing/batch_analyzer.py +276 -0
  1204. tools/writing/coherence_analyzer.py +221 -0
  1205. tools/writing/govcon_bridge.py +509 -0
  1206. tools/writing/grammar_checker.py +270 -0
  1207. tools/writing/plagiarism_detector.py +106 -0
  1208. tools/writing/readability_scorer.py +201 -0
  1209. tools/writing/rewriter.py +96 -0
  1210. tools/writing/signal_registrar.py +167 -0
  1211. tools/writing/snippet_manager.py +276 -0
  1212. tools/writing/style_enforcer.py +220 -0
  1213. tools/writing/style_guide_manager.py +438 -0
  1214. tools/writing/tone_profiler.py +168 -0
@@ -0,0 +1,2070 @@
1
+ #!/usr/bin/env python3
2
+ # CUI // SP-CTI
3
+ """SbD assessment tool per CISA Secure by Design and DoDI 5000.87.
4
+
5
+ Loads SbD requirements from cisa_sbd_requirements.json, performs automated checks
6
+ where possible, stores results in sbd_assessments table, evaluates SbD gates,
7
+ applies CUI markings, and logs audit events."""
8
+
9
+ import argparse
10
+ import json
11
+ import os
12
+ import re
13
+ import sys
14
+ from datetime import datetime, timezone
15
+ from pathlib import Path
16
+ from tools.db.storage import get_connection
17
+ DB_PATH = None # Storage layer handles path resolution (D-DB-20)
18
+
19
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent
20
+ SBD_REQUIREMENTS_PATH = BASE_DIR / "context" / "compliance" / "cisa_sbd_requirements.json"
21
+
22
+
23
+ # -----------------------------------------------------------------
24
+ # Database helpers
25
+ # -----------------------------------------------------------------
26
+
27
+
28
+ def _get_project(conn, project_id):
29
+ """Load project data from the projects table."""
30
+ row = conn.execute(
31
+ "SELECT * FROM projects WHERE id = ?", (project_id,)
32
+ ).fetchone()
33
+ if not row:
34
+ raise ValueError(f"Project '{project_id}' not found.")
35
+ return dict(row)
36
+
37
+
38
+ # -----------------------------------------------------------------
39
+ # Configuration helpers
40
+ # -----------------------------------------------------------------
41
+
42
+ def _load_cui_config():
43
+ """Load CUI marking configuration."""
44
+ try:
45
+ sys.path.insert(0, str(BASE_DIR / "tools" / "compliance"))
46
+ from cui_marker import load_cui_config
47
+ return load_cui_config()
48
+ except ImportError:
49
+ return {
50
+ "document_header": (
51
+ "////////////////////////////////////////////////////////////////////\n"
52
+ "CONTROLLED UNCLASSIFIED INFORMATION (CUI) // SP-CTI\n"
53
+ "Distribution: Distribution D -- Authorized DoD Personnel Only\n"
54
+ "////////////////////////////////////////////////////////////////////"
55
+ ),
56
+ "document_footer": (
57
+ "////////////////////////////////////////////////////////////////////\n"
58
+ "CUI // SP-CTI | Department of Defense\n"
59
+ "////////////////////////////////////////////////////////////////////"
60
+ ),
61
+ }
62
+
63
+
64
+ def _load_sbd_requirements():
65
+ """Load SbD requirements from the JSON catalog."""
66
+ if not SBD_REQUIREMENTS_PATH.exists():
67
+ raise FileNotFoundError(
68
+ f"SbD requirements file not found: {SBD_REQUIREMENTS_PATH}\n"
69
+ "Expected: context/compliance/cisa_sbd_requirements.json"
70
+ )
71
+ with open(SBD_REQUIREMENTS_PATH, "r", encoding="utf-8") as f:
72
+ return json.load(f)
73
+
74
+
75
+ def _log_audit_event(conn, project_id, action, details, file_path=None):
76
+ """Log an audit trail event (append-only, NIST AU compliant)."""
77
+ try:
78
+ conn.execute(
79
+ """INSERT INTO audit_trail
80
+ (project_id, event_type, actor, action, details,
81
+ affected_files, classification)
82
+ VALUES (?, ?, ?, ?, ?, ?, ?)""",
83
+ (
84
+ project_id,
85
+ "sbd_assessed",
86
+ "icdev-compliance-engine",
87
+ action,
88
+ json.dumps(details),
89
+ json.dumps([str(file_path)] if file_path else []),
90
+ "CUI",
91
+ ),
92
+ )
93
+ conn.commit()
94
+ except Exception as e:
95
+ print(f"Warning: Could not log audit event: {e}", file=sys.stderr)
96
+
97
+
98
+ # Directories to skip during file scanning (child app copies, build
99
+ # artifacts, VCS, virtual envs). Pruning these avoids walking thousands
100
+ # of duplicated files under .tmp/children* which caused timeouts.
101
+ _SKIP_DIRS = {
102
+ ".tmp", ".git", "node_modules", "__pycache__", ".aws-sam",
103
+ ".venv", "venv", ".tox", ".mypy_cache", ".pytest_cache",
104
+ "dist", "build", ".eggs", "htmlcov",
105
+ }
106
+
107
+
108
+ # -----------------------------------------------------------------
109
+ # Auto-check helper: walk project files matching extensions
110
+ # -----------------------------------------------------------------
111
+
112
+ def _scan_files(project_dir, extensions, patterns, threshold=1):
113
+ """Scan project files for regex patterns.
114
+
115
+ Args:
116
+ project_dir: Root directory to walk.
117
+ extensions: Tuple of file extensions to include (e.g. ('.py', '.md')).
118
+ patterns: List of regex patterns to search for.
119
+ threshold: Minimum number of files with matches to consider satisfied.
120
+
121
+ Returns:
122
+ Tuple of (matched_files, total_scanned).
123
+ """
124
+ matched_files = []
125
+ total_scanned = 0
126
+ for root, dirs, files in os.walk(project_dir):
127
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
128
+ for fname in files:
129
+ if not fname.endswith(extensions):
130
+ continue
131
+ fpath = os.path.join(root, fname)
132
+ total_scanned += 1
133
+ try:
134
+ with open(fpath, "r", encoding="utf-8", errors="ignore") as f:
135
+ content = f.read()
136
+ for pattern in patterns:
137
+ if re.search(pattern, content, re.IGNORECASE):
138
+ matched_files.append(fpath)
139
+ break
140
+ except Exception:
141
+ continue
142
+ return matched_files, total_scanned
143
+
144
+
145
+ def _dir_or_file_exists(project_dir, dir_names=None, glob_patterns=None):
146
+ """Check if specific directories or file globs exist under project_dir.
147
+
148
+ Args:
149
+ project_dir: Root directory to search.
150
+ dir_names: List of directory names to look for.
151
+ glob_patterns: List of glob patterns to match files.
152
+
153
+ Returns:
154
+ List of found paths.
155
+ """
156
+ found = []
157
+ project_path = Path(project_dir)
158
+
159
+ if dir_names:
160
+ for dname in dir_names:
161
+ candidate = project_path / dname
162
+ if candidate.is_dir():
163
+ found.append(str(candidate))
164
+ # Also check one level deeper (e.g. infra/terraform/)
165
+ for child in project_path.rglob(dname):
166
+ if child.is_dir() and str(child) not in found:
167
+ found.append(str(child))
168
+
169
+ if glob_patterns:
170
+ for gp in glob_patterns:
171
+ for match in project_path.rglob(gp):
172
+ if str(match) not in found:
173
+ found.append(str(match))
174
+
175
+ return found
176
+
177
+
178
+ # -----------------------------------------------------------------
179
+ # Auto-check functions (20 checks)
180
+ # Each returns a dict:
181
+ # {"status": "satisfied"|"not_satisfied"|"partially_satisfied"
182
+ # |"not_applicable",
183
+ # "evidence": "description of what was found",
184
+ # "details": "specifics"}
185
+ # -----------------------------------------------------------------
186
+
187
+ def _check_mfa_patterns(project_dir):
188
+ """SBD-01: Scan auth code for MFA/2FA/TOTP/FIDO multi-factor patterns."""
189
+ auth_patterns = [
190
+ r"\bMFA\b|multi.factor|MultiFactor",
191
+ r"\b2FA\b|two.factor|TwoFactor",
192
+ r"\bTOTP\b|totp|time.based.one.time",
193
+ r"\bFIDO\b|fido2|WebAuthn|webauthn",
194
+ r"authenticator|Authenticator",
195
+ r"otp_secret|otp_verify|verify_otp",
196
+ ]
197
+ extensions = (".py", ".js", ".ts", ".java", ".yaml", ".yml")
198
+ matched, total = _scan_files(project_dir, extensions, auth_patterns)
199
+
200
+ if total == 0:
201
+ return {
202
+ "status": "not_satisfied",
203
+ "evidence": "No source or config files found to assess.",
204
+ "details": "Project directory lacks applicable files.",
205
+ }
206
+
207
+ if matched:
208
+ return {
209
+ "status": "satisfied",
210
+ "evidence": (
211
+ f"MFA/multi-factor authentication patterns found in "
212
+ f"{len(matched)} file(s)."
213
+ ),
214
+ "details": "; ".join(os.path.basename(f) for f in matched[:5]),
215
+ }
216
+
217
+ # Check if any auth-related code exists at all
218
+ auth_code_patterns = [
219
+ r"login|authenticate|auth|password|credential",
220
+ ]
221
+ auth_files, _ = _scan_files(project_dir, extensions, auth_code_patterns)
222
+ if not auth_files:
223
+ return {
224
+ "status": "not_satisfied",
225
+ "evidence": "No authentication code detected in project.",
226
+ "details": "No auth-related patterns found; cannot verify MFA support.",
227
+ }
228
+
229
+ return {
230
+ "status": "not_satisfied",
231
+ "evidence": (
232
+ f"Authentication code found in {len(auth_files)} file(s) but no "
233
+ "MFA/2FA/TOTP/FIDO patterns detected."
234
+ ),
235
+ "details": "Multi-factor authentication is required but not implemented.",
236
+ }
237
+
238
+
239
+ def _check_default_passwords(project_dir):
240
+ """SBD-02: Scan for hardcoded/default passwords (inverse check).
241
+
242
+ Returns satisfied if NO default passwords are found.
243
+ """
244
+ bad_patterns = [
245
+ r"password\s*=\s*[\"'][^\"']+[\"']",
246
+ r"default_password",
247
+ r"admin.*password|password.*admin",
248
+ r"password123|passw0rd|qwerty|letmein",
249
+ r"changeme|change_me|CHANGEME",
250
+ ]
251
+ extensions = (".py", ".js", ".ts", ".yaml", ".yml", ".json", ".conf", ".env")
252
+ matched, total = _scan_files(project_dir, extensions, bad_patterns)
253
+
254
+ if total == 0:
255
+ return {
256
+ "status": "not_satisfied",
257
+ "evidence": "No source or config files found to assess.",
258
+ "details": "Project directory lacks applicable files.",
259
+ }
260
+
261
+ if matched:
262
+ return {
263
+ "status": "not_satisfied",
264
+ "evidence": (
265
+ f"Default/hardcoded password patterns detected in "
266
+ f"{len(matched)} file(s)."
267
+ ),
268
+ "details": (
269
+ "Files with potential default passwords: "
270
+ + "; ".join(os.path.basename(f) for f in matched[:5])
271
+ ),
272
+ }
273
+
274
+ return {
275
+ "status": "satisfied",
276
+ "evidence": (
277
+ f"Scanned {total} file(s) -- no default or hardcoded password "
278
+ "patterns detected."
279
+ ),
280
+ "details": "No instances of hardcoded passwords, changeme, or default credentials.",
281
+ }
282
+
283
+
284
+ def _check_memory_safe_language(project_dir):
285
+ """SBD-03: Assess ratio of memory-safe to memory-unsafe language files."""
286
+ safe_extensions = (".py", ".java", ".go", ".rs", ".cs", ".rb", ".kt")
287
+ unsafe_extensions = (".c", ".cpp", ".cc", ".cxx", ".h", ".hpp")
288
+
289
+ safe_count = 0
290
+ unsafe_count = 0
291
+
292
+ for root, dirs, files in os.walk(project_dir):
293
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
294
+ for fname in files:
295
+ lower = fname.lower()
296
+ if any(lower.endswith(ext) for ext in safe_extensions):
297
+ safe_count += 1
298
+ elif any(lower.endswith(ext) for ext in unsafe_extensions):
299
+ unsafe_count += 1
300
+
301
+ total = safe_count + unsafe_count
302
+ if total == 0:
303
+ return {
304
+ "status": "not_satisfied",
305
+ "evidence": "No recognized programming language files found.",
306
+ "details": "Cannot determine memory safety profile.",
307
+ }
308
+
309
+ safe_ratio = safe_count / total
310
+ if safe_ratio > 0.9:
311
+ return {
312
+ "status": "satisfied",
313
+ "evidence": (
314
+ f"Memory-safe languages: {safe_count}/{total} files "
315
+ f"({safe_ratio:.0%})."
316
+ ),
317
+ "details": (
318
+ f"Safe: {safe_count} | Unsafe: {unsafe_count}. "
319
+ "Exceeds 90% threshold."
320
+ ),
321
+ }
322
+ elif safe_ratio > 0.5:
323
+ return {
324
+ "status": "partially_satisfied",
325
+ "evidence": (
326
+ f"Memory-safe languages: {safe_count}/{total} files "
327
+ f"({safe_ratio:.0%})."
328
+ ),
329
+ "details": (
330
+ f"Safe: {safe_count} | Unsafe: {unsafe_count}. "
331
+ "Between 50-90%. Must exceed 90% for full satisfaction."
332
+ ),
333
+ }
334
+ else:
335
+ return {
336
+ "status": "not_satisfied",
337
+ "evidence": (
338
+ f"Memory-safe languages: {safe_count}/{total} files "
339
+ f"({safe_ratio:.0%})."
340
+ ),
341
+ "details": (
342
+ f"Safe: {safe_count} | Unsafe: {unsafe_count}. "
343
+ "At or below 50%. Significant memory safety risk."
344
+ ),
345
+ }
346
+
347
+
348
+ def _check_memory_safety_tooling(project_dir):
349
+ """SBD-04: Scan build configs for memory-safety analysis tooling."""
350
+ # First check if there is any memory-unsafe code
351
+ unsafe_extensions = (".c", ".cpp", ".cc", ".cxx", ".h", ".hpp")
352
+ has_unsafe = False
353
+ for root, dirs, files in os.walk(project_dir):
354
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
355
+ for fname in files:
356
+ if any(fname.lower().endswith(ext) for ext in unsafe_extensions):
357
+ has_unsafe = True
358
+ break
359
+ if has_unsafe:
360
+ break
361
+
362
+ if not has_unsafe:
363
+ return {
364
+ "status": "not_applicable",
365
+ "evidence": "No memory-unsafe language files (C/C++) found in project.",
366
+ "details": "Memory safety tooling check is not applicable.",
367
+ }
368
+
369
+ tooling_patterns = [
370
+ r"AddressSanitizer|ASAN|asan",
371
+ r"-fsanitize\s*=",
372
+ r"Valgrind|valgrind",
373
+ r"\bMSAN\b|MemorySanitizer",
374
+ r"\bTSAN\b|ThreadSanitizer",
375
+ r"\bUBSAN\b|UndefinedBehaviorSanitizer",
376
+ r"clang.tidy|cppcheck|coverity",
377
+ ]
378
+ # Build config extensions plus common build system files
379
+ extensions = (".cfg", ".ini", ".yaml", ".yml", ".toml")
380
+ matched, total = _scan_files(project_dir, extensions, tooling_patterns)
381
+
382
+ # Also check Makefile and CMakeLists.txt specifically
383
+ build_files = _dir_or_file_exists(
384
+ project_dir,
385
+ glob_patterns=["Makefile", "makefile", "CMakeLists.txt", "*.cmake"],
386
+ )
387
+ build_matches = []
388
+ for bf_path in build_files:
389
+ try:
390
+ with open(bf_path, "r", encoding="utf-8", errors="ignore") as f:
391
+ content = f.read()
392
+ for pattern in tooling_patterns:
393
+ if re.search(pattern, content, re.IGNORECASE):
394
+ build_matches.append(bf_path)
395
+ break
396
+ except Exception:
397
+ continue
398
+
399
+ all_matched = list(set(matched + build_matches))
400
+ if all_matched:
401
+ return {
402
+ "status": "satisfied",
403
+ "evidence": (
404
+ f"Memory safety tooling patterns found in "
405
+ f"{len(all_matched)} file(s)."
406
+ ),
407
+ "details": "; ".join(os.path.basename(f) for f in all_matched[:5]),
408
+ }
409
+
410
+ return {
411
+ "status": "not_satisfied",
412
+ "evidence": (
413
+ "Memory-unsafe code present but no memory safety tooling detected."
414
+ ),
415
+ "details": (
416
+ "Expected: AddressSanitizer, -fsanitize, Valgrind, MSAN, TSAN, "
417
+ "or equivalent tooling in build configurations."
418
+ ),
419
+ }
420
+
421
+
422
+ def _check_patch_cadence(project_dir):
423
+ """SBD-05: Look for automated dependency update tooling."""
424
+ found = _dir_or_file_exists(
425
+ project_dir,
426
+ glob_patterns=[
427
+ "dependabot.yml",
428
+ "dependabot.yaml",
429
+ "renovate.json",
430
+ ".renovaterc",
431
+ ".renovaterc.json",
432
+ ],
433
+ )
434
+ # Also check .github/dependabot.yml path
435
+ github_dependabot = _dir_or_file_exists(
436
+ project_dir,
437
+ dir_names=[".github"],
438
+ )
439
+ if github_dependabot:
440
+ dep_files = _dir_or_file_exists(
441
+ project_dir,
442
+ glob_patterns=[".github/dependabot.yml", ".github/dependabot.yaml"],
443
+ )
444
+ found.extend(dep_files)
445
+
446
+ # Check for pip-compile, poetry.lock freshness indicators
447
+ lock_files = _dir_or_file_exists(
448
+ project_dir,
449
+ glob_patterns=[
450
+ "requirements*.txt",
451
+ "poetry.lock",
452
+ "Pipfile.lock",
453
+ "package-lock.json",
454
+ "yarn.lock",
455
+ "pnpm-lock.yaml",
456
+ ],
457
+ )
458
+
459
+ all_found = list(set(found))
460
+ if all_found:
461
+ return {
462
+ "status": "satisfied",
463
+ "evidence": (
464
+ f"Automated dependency update tooling found: "
465
+ f"{len(all_found)} artifact(s)."
466
+ ),
467
+ "details": "; ".join(os.path.basename(f) for f in all_found[:5]),
468
+ }
469
+
470
+ if lock_files:
471
+ return {
472
+ "status": "partially_satisfied",
473
+ "evidence": (
474
+ f"Lock files found ({len(lock_files)}) indicating dependency "
475
+ "management, but no automated update tooling (Dependabot, "
476
+ "Renovate) detected."
477
+ ),
478
+ "details": "; ".join(os.path.basename(f) for f in lock_files[:5]),
479
+ }
480
+
481
+ return {
482
+ "status": "not_satisfied",
483
+ "evidence": "No automated dependency update tooling detected.",
484
+ "details": (
485
+ "Expected: .github/dependabot.yml, renovate.json, .renovaterc, "
486
+ "or equivalent automated patch management configuration."
487
+ ),
488
+ }
489
+
490
+
491
+ def _check_vuln_disclosure(project_dir):
492
+ """SBD-06: Look for vulnerability disclosure policy files."""
493
+ found = _dir_or_file_exists(
494
+ project_dir,
495
+ glob_patterns=[
496
+ "SECURITY.md",
497
+ "SECURITY.txt",
498
+ "security.txt",
499
+ "security.md",
500
+ ],
501
+ )
502
+ # Also check .well-known/security.txt
503
+ well_known = _dir_or_file_exists(
504
+ project_dir,
505
+ glob_patterns=[".well-known/security.txt"],
506
+ )
507
+ found.extend(well_known)
508
+
509
+ all_found = list(set(found))
510
+ if all_found:
511
+ return {
512
+ "status": "satisfied",
513
+ "evidence": (
514
+ f"Vulnerability disclosure policy found: "
515
+ f"{len(all_found)} file(s)."
516
+ ),
517
+ "details": "; ".join(os.path.basename(f) for f in all_found[:5]),
518
+ }
519
+
520
+ return {
521
+ "status": "not_satisfied",
522
+ "evidence": "No vulnerability disclosure policy detected.",
523
+ "details": (
524
+ "Expected: SECURITY.md, .well-known/security.txt, SECURITY.txt, "
525
+ "or equivalent disclosure policy file."
526
+ ),
527
+ }
528
+
529
+
530
+ def _check_audit_logging_complete(project_dir):
531
+ """SBD-08: Scan for comprehensive audit logging patterns.
532
+
533
+ Checks for multiple distinct log event types.
534
+ """
535
+ event_type_patterns = [
536
+ (r"login|auth.*log|authentication.*log", "authentication_logging"),
537
+ (r"access.*log|access_log|request.*log", "access_logging"),
538
+ (r"change.*log|change_log|modification.*log|update.*log", "change_logging"),
539
+ (r"error.*log|error_log|exception.*log", "error_logging"),
540
+ (r"security.*event|security.*log|security_event", "security_logging"),
541
+ ]
542
+ extensions = (".py", ".js", ".ts", ".java", ".yaml", ".yml")
543
+ found_types = set()
544
+ evidence_files = []
545
+
546
+ for root, dirs, files in os.walk(project_dir):
547
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
548
+ for fname in files:
549
+ if not fname.endswith(extensions):
550
+ continue
551
+ fpath = os.path.join(root, fname)
552
+ try:
553
+ with open(fpath, "r", encoding="utf-8", errors="ignore") as f:
554
+ content = f.read()
555
+ for pattern, event_type in event_type_patterns:
556
+ if re.search(pattern, content, re.IGNORECASE):
557
+ found_types.add(event_type)
558
+ if fpath not in evidence_files:
559
+ evidence_files.append(fpath)
560
+ except Exception:
561
+ continue
562
+
563
+ # Also check for generic structured logging patterns
564
+ struct_patterns = [
565
+ r"audit_trail|AuditTrail",
566
+ r"logging\.getLogger|getLogger",
567
+ r"structlog|structured.log",
568
+ ]
569
+ struct_matched, _ = _scan_files(project_dir, extensions, struct_patterns)
570
+ if struct_matched:
571
+ found_types.add("structured_logging")
572
+ for sf in struct_matched:
573
+ if sf not in evidence_files:
574
+ evidence_files.append(sf)
575
+
576
+ count = len(found_types)
577
+ if count >= 3:
578
+ return {
579
+ "status": "satisfied",
580
+ "evidence": (
581
+ f"Comprehensive audit logging detected: {count} distinct "
582
+ f"log event types across {len(evidence_files)} file(s)."
583
+ ),
584
+ "details": (
585
+ f"Event types: {', '.join(sorted(found_types))}. "
586
+ f"Files: {'; '.join(os.path.basename(f) for f in evidence_files[:5])}"
587
+ ),
588
+ }
589
+ elif count >= 1:
590
+ return {
591
+ "status": "partially_satisfied",
592
+ "evidence": (
593
+ f"Partial audit logging detected: {count} distinct log event "
594
+ f"type(s) found."
595
+ ),
596
+ "details": (
597
+ f"Event types: {', '.join(sorted(found_types))}. "
598
+ "Need 3+ distinct log event types for full compliance."
599
+ ),
600
+ }
601
+
602
+ return {
603
+ "status": "not_satisfied",
604
+ "evidence": "No audit logging patterns detected in source files.",
605
+ "details": (
606
+ "Expected: authentication logging, access logging, change logging, "
607
+ "error logging, or security event logging patterns."
608
+ ),
609
+ }
610
+
611
+
612
+ def _check_tls_config(project_dir):
613
+ """SBD-11: Scan for TLS 1.2+/1.3 and detect insecure protocols."""
614
+ secure_patterns = [
615
+ r"TLS\s*1\.[23]|TLSv1_[23]|tls_version.*1\.[23]",
616
+ r"TLS_1_2|TLS_1_3|PROTOCOL_TLS",
617
+ r"\bHTTPS\b|https://",
618
+ r"ssl_context|SSLContext",
619
+ r"mTLS|mutual.TLS",
620
+ r"strong.cipher|ECDHE|AES.GCM|CHACHA20",
621
+ ]
622
+ insecure_patterns = [
623
+ r"SSLv2|SSLv3|PROTOCOL_SSLv",
624
+ r"TLSv1_0|TLS\s*1\.0|TLS_1_0",
625
+ r"TLSv1_1|TLS\s*1\.1|TLS_1_1",
626
+ r"verify\s*=\s*False|CERT_NONE|check_hostname\s*=\s*False",
627
+ r"ssl_verify.*false|tls_verify.*false",
628
+ ]
629
+ extensions = (".py", ".yaml", ".yml", ".conf", ".tf", ".json")
630
+
631
+ secure_matched, total = _scan_files(project_dir, extensions, secure_patterns)
632
+ insecure_matched, _ = _scan_files(project_dir, extensions, insecure_patterns)
633
+
634
+ if total == 0:
635
+ return {
636
+ "status": "not_satisfied",
637
+ "evidence": "No configuration or source files found to assess.",
638
+ "details": "Project directory lacks files with expected extensions.",
639
+ }
640
+
641
+ if secure_matched and not insecure_matched:
642
+ return {
643
+ "status": "satisfied",
644
+ "evidence": (
645
+ f"TLS configuration patterns found in {len(secure_matched)} "
646
+ f"file(s) with no insecure protocol patterns detected."
647
+ ),
648
+ "details": "; ".join(
649
+ os.path.basename(f) for f in secure_matched[:5]
650
+ ),
651
+ }
652
+ elif secure_matched and insecure_matched:
653
+ return {
654
+ "status": "partially_satisfied",
655
+ "evidence": (
656
+ f"TLS patterns found in {len(secure_matched)} file(s), but "
657
+ f"insecure patterns also detected in {len(insecure_matched)} "
658
+ f"file(s)."
659
+ ),
660
+ "details": (
661
+ "Insecure files: "
662
+ + "; ".join(
663
+ os.path.basename(f) for f in insecure_matched[:5]
664
+ )
665
+ + ". Remove SSLv3, TLSv1.0, TLSv1.1, and verify=False usage."
666
+ ),
667
+ }
668
+
669
+ return {
670
+ "status": "not_satisfied",
671
+ "evidence": "No TLS configuration patterns detected.",
672
+ "details": (
673
+ "Expected: TLS 1.2+, strong ciphers, SSLContext configuration. "
674
+ "No HTTPS or TLS patterns found in project files."
675
+ ),
676
+ }
677
+
678
+
679
+ def _check_encryption_at_rest(project_dir):
680
+ """SBD-12: Scan for encryption-at-rest configuration patterns."""
681
+ patterns = [
682
+ r"\bFIPS\b|fips_mode|FIPS.140",
683
+ r"AES.256|AES_256|aes256",
684
+ r"encryption.at.rest|encrypt_at_rest|encrypted_at_rest",
685
+ r"storage_encrypted|StorageEncrypted|encrypted\s*=\s*true",
686
+ r"\bKMS\b|kms_key|aws_kms|key_management",
687
+ r"server.side.encryption|SSE.S3|SSE.KMS|SSEAlgorithm",
688
+ ]
689
+ extensions = (".py", ".yaml", ".yml", ".tf", ".json", ".conf")
690
+ matched, total = _scan_files(project_dir, extensions, patterns)
691
+
692
+ if total == 0:
693
+ return {
694
+ "status": "not_satisfied",
695
+ "evidence": "No configuration files found to assess.",
696
+ "details": "Project directory lacks applicable config files.",
697
+ }
698
+
699
+ if matched:
700
+ return {
701
+ "status": "satisfied",
702
+ "evidence": (
703
+ f"Encryption-at-rest patterns found in "
704
+ f"{len(matched)} file(s)."
705
+ ),
706
+ "details": "; ".join(os.path.basename(f) for f in matched[:5]),
707
+ }
708
+
709
+ return {
710
+ "status": "not_satisfied",
711
+ "evidence": "No encryption-at-rest patterns detected.",
712
+ "details": (
713
+ "Expected: FIPS, AES-256, KMS, storage_encrypted, or "
714
+ "server-side encryption configuration patterns."
715
+ ),
716
+ }
717
+
718
+
719
+ def _check_rbac_least_priv(project_dir):
720
+ """SBD-14: Scan for RBAC / role / permission / least-privilege patterns."""
721
+ patterns = [
722
+ r"@login_required|@permission_required|@requires_auth",
723
+ r"@Secured|@PreAuthorize|@RolesAllowed",
724
+ r"role_required|check_permission|has_permission",
725
+ r"\bRBAC\b|role.based.access",
726
+ r"RoleBinding|ClusterRole|ClusterRoleBinding",
727
+ r"least.privilege|minimum.privilege|principle.of.least",
728
+ r"from\s+flask_login|from\s+django\.contrib\.auth",
729
+ ]
730
+ extensions = (".py", ".yaml", ".yml", ".js", ".ts", ".java")
731
+ matched, total = _scan_files(project_dir, extensions, patterns)
732
+
733
+ if total == 0:
734
+ return {
735
+ "status": "not_satisfied",
736
+ "evidence": "No source files found to assess for RBAC patterns.",
737
+ "details": "Project directory lacks applicable source files.",
738
+ }
739
+
740
+ if matched:
741
+ return {
742
+ "status": "satisfied",
743
+ "evidence": (
744
+ f"RBAC / least-privilege patterns found in "
745
+ f"{len(matched)} file(s)."
746
+ ),
747
+ "details": "; ".join(os.path.basename(f) for f in matched[:5]),
748
+ }
749
+
750
+ return {
751
+ "status": "not_satisfied",
752
+ "evidence": "No RBAC or least-privilege access control patterns detected.",
753
+ "details": (
754
+ "Expected: @login_required, role_required, RBAC, RoleBinding, "
755
+ "or least-privilege patterns."
756
+ ),
757
+ }
758
+
759
+
760
+ def _check_input_validation(project_dir):
761
+ """SBD-16: Scan for input validation libraries and patterns."""
762
+ patterns = [
763
+ r"\bpydantic\b|from\s+pydantic|import\s+pydantic",
764
+ r"\bmarshmallow\b|from\s+marshmallow|import\s+marshmallow",
765
+ r"\bcerberus\b|from\s+cerberus|import\s+cerberus",
766
+ r"\bvoluptuous\b|from\s+voluptuous|import\s+voluptuous",
767
+ r"\bJoi\b|require\(['\"]joi|from\s+['\"]joi",
768
+ r"\bZod\b|from\s+['\"]zod|import.*\bzod\b",
769
+ r"@Valid|@NotNull|@NotBlank|@NotEmpty|@Size",
770
+ r"validate_input|sanitize_input|input_validation",
771
+ r"sanitize|validator\.validate|form\.validate",
772
+ ]
773
+ extensions = (".py", ".js", ".ts", ".java")
774
+ matched, total = _scan_files(project_dir, extensions, patterns)
775
+
776
+ if total == 0:
777
+ return {
778
+ "status": "not_satisfied",
779
+ "evidence": "No source files found to assess for input validation.",
780
+ "details": "Project directory lacks applicable source files.",
781
+ }
782
+
783
+ if len(matched) >= 2:
784
+ return {
785
+ "status": "satisfied",
786
+ "evidence": (
787
+ f"Input validation patterns found in "
788
+ f"{len(matched)} file(s)."
789
+ ),
790
+ "details": "; ".join(os.path.basename(f) for f in matched[:5]),
791
+ }
792
+ elif len(matched) == 1:
793
+ return {
794
+ "status": "partially_satisfied",
795
+ "evidence": (
796
+ f"Input validation patterns found in only 1 file: "
797
+ f"{os.path.basename(matched[0])}."
798
+ ),
799
+ "details": (
800
+ "Validation found in a single file. Should be applied "
801
+ "consistently across all input handling code."
802
+ ),
803
+ }
804
+
805
+ return {
806
+ "status": "not_satisfied",
807
+ "evidence": "No input validation patterns detected.",
808
+ "details": (
809
+ "Expected: pydantic, marshmallow, cerberus, Joi, Zod, @Valid, "
810
+ "validate_input, or sanitize patterns."
811
+ ),
812
+ }
813
+
814
+
815
+ def _check_output_encoding(project_dir):
816
+ """SBD-17: Scan for XSS prevention / output encoding patterns."""
817
+ patterns = [
818
+ r"escape\(\)|html\.escape|cgi\.escape",
819
+ r"\bmarkupsafe\b|from\s+markupsafe|Markup\(",
820
+ r"\bbleach\b|bleach\.clean|bleach\.sanitize",
821
+ r"DOMPurify|dompurify|sanitizeHtml|sanitize_html",
822
+ r"htmlspecialchars|htmlentities",
823
+ r"Content.Security.Policy|CSP|content_security_policy",
824
+ r"auto_escape|autoescape|autoescaping",
825
+ ]
826
+ extensions = (".py", ".js", ".ts", ".java", ".html", ".jinja", ".jinja2")
827
+ matched, total = _scan_files(project_dir, extensions, patterns)
828
+
829
+ if total == 0:
830
+ return {
831
+ "status": "not_satisfied",
832
+ "evidence": "No source or template files found to assess.",
833
+ "details": "Project directory lacks applicable files.",
834
+ }
835
+
836
+ if matched:
837
+ return {
838
+ "status": "satisfied",
839
+ "evidence": (
840
+ f"Output encoding / XSS prevention patterns found in "
841
+ f"{len(matched)} file(s)."
842
+ ),
843
+ "details": "; ".join(os.path.basename(f) for f in matched[:5]),
844
+ }
845
+
846
+ return {
847
+ "status": "not_satisfied",
848
+ "evidence": "No output encoding or XSS prevention patterns detected.",
849
+ "details": (
850
+ "Expected: escape(), markupsafe, bleach, DOMPurify, "
851
+ "sanitizeHtml, CSP headers, or auto-escaping configuration."
852
+ ),
853
+ }
854
+
855
+
856
+ def _check_security_headers(project_dir):
857
+ """SBD-18: Scan for security response headers configuration."""
858
+ header_patterns = [
859
+ (r"Content.Security.Policy|content_security_policy|CSP", "CSP"),
860
+ (
861
+ r"Strict.Transport.Security|strict_transport_security|HSTS",
862
+ "HSTS",
863
+ ),
864
+ (r"X.Frame.Options|x_frame_options|DENY|SAMEORIGIN", "X-Frame-Options"),
865
+ (
866
+ r"X.Content.Type.Options|x_content_type_options|nosniff",
867
+ "X-Content-Type-Options",
868
+ ),
869
+ (
870
+ r"Access.Control.Allow.Origin|CORS|cors_allowed|cors_origins",
871
+ "CORS",
872
+ ),
873
+ ]
874
+ extensions = (".py", ".js", ".ts", ".yaml", ".yml", ".conf", ".json")
875
+ found_headers = set()
876
+ evidence_files = []
877
+
878
+ for root, dirs, files in os.walk(project_dir):
879
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
880
+ for fname in files:
881
+ if not fname.endswith(extensions):
882
+ continue
883
+ fpath = os.path.join(root, fname)
884
+ try:
885
+ with open(fpath, "r", encoding="utf-8", errors="ignore") as f:
886
+ content = f.read()
887
+ for pattern, header_name in header_patterns:
888
+ if re.search(pattern, content, re.IGNORECASE):
889
+ found_headers.add(header_name)
890
+ if fpath not in evidence_files:
891
+ evidence_files.append(fpath)
892
+ except Exception:
893
+ continue
894
+
895
+ count = len(found_headers)
896
+ if count >= 3:
897
+ return {
898
+ "status": "satisfied",
899
+ "evidence": (
900
+ f"{count} distinct security headers configured: "
901
+ f"{', '.join(sorted(found_headers))}."
902
+ ),
903
+ "details": (
904
+ "Files: "
905
+ + "; ".join(os.path.basename(f) for f in evidence_files[:5])
906
+ ),
907
+ }
908
+ elif count >= 1:
909
+ return {
910
+ "status": "partially_satisfied",
911
+ "evidence": (
912
+ f"Only {count} security header(s) detected: "
913
+ f"{', '.join(sorted(found_headers))}."
914
+ ),
915
+ "details": (
916
+ "Need 3+ of: CSP, HSTS, X-Frame-Options, "
917
+ "X-Content-Type-Options, CORS for full compliance."
918
+ ),
919
+ }
920
+
921
+ return {
922
+ "status": "not_satisfied",
923
+ "evidence": "No security response headers detected.",
924
+ "details": (
925
+ "Expected: Content-Security-Policy, Strict-Transport-Security, "
926
+ "X-Frame-Options, X-Content-Type-Options, or CORS configuration."
927
+ ),
928
+ }
929
+
930
+
931
+ def _check_secure_error_handling(project_dir):
932
+ """SBD-19: Check for secure error handling and no debug info leakage."""
933
+ secure_patterns = [
934
+ r"DEBUG\s*=\s*False",
935
+ r"@app\.errorhandler|custom.error.handler|error_handler",
936
+ r"error_page|custom_error_response",
937
+ r"app\.config\[.DEBUG.\]\s*=\s*False",
938
+ ]
939
+ insecure_patterns = [
940
+ r"DEBUG\s*=\s*True",
941
+ r"traceback\.print_exc|print_exc\(\)",
942
+ r"print\s*\(.*traceback|print\s*\(.*stack",
943
+ r"stack_trace.*response|stacktrace.*response",
944
+ r"app\.config\[.DEBUG.\]\s*=\s*True",
945
+ ]
946
+ extensions = (".py", ".js", ".ts", ".yaml", ".yml", ".conf")
947
+
948
+ secure_matched, total = _scan_files(
949
+ project_dir, extensions, secure_patterns
950
+ )
951
+ insecure_matched, _ = _scan_files(
952
+ project_dir, extensions, insecure_patterns
953
+ )
954
+
955
+ if total == 0:
956
+ return {
957
+ "status": "not_satisfied",
958
+ "evidence": "No source or config files found to assess.",
959
+ "details": "Project directory lacks applicable files.",
960
+ }
961
+
962
+ if secure_matched and not insecure_matched:
963
+ return {
964
+ "status": "satisfied",
965
+ "evidence": (
966
+ f"Secure error handling patterns found in "
967
+ f"{len(secure_matched)} file(s) with no insecure patterns."
968
+ ),
969
+ "details": "; ".join(
970
+ os.path.basename(f) for f in secure_matched[:5]
971
+ ),
972
+ }
973
+ elif secure_matched and insecure_matched:
974
+ return {
975
+ "status": "partially_satisfied",
976
+ "evidence": (
977
+ f"Secure error handling in {len(secure_matched)} file(s), "
978
+ f"but insecure patterns in {len(insecure_matched)} file(s)."
979
+ ),
980
+ "details": (
981
+ "Insecure files: "
982
+ + "; ".join(
983
+ os.path.basename(f) for f in insecure_matched[:5]
984
+ )
985
+ + ". Remove DEBUG=True and stack trace exposure in responses."
986
+ ),
987
+ }
988
+ elif insecure_matched and not secure_matched:
989
+ return {
990
+ "status": "not_satisfied",
991
+ "evidence": (
992
+ f"Insecure error handling patterns detected in "
993
+ f"{len(insecure_matched)} file(s) with no secure patterns."
994
+ ),
995
+ "details": (
996
+ "Files: "
997
+ + "; ".join(
998
+ os.path.basename(f) for f in insecure_matched[:5]
999
+ )
1000
+ + ". DEBUG=True, traceback exposure, or stack traces "
1001
+ "in responses detected."
1002
+ ),
1003
+ }
1004
+
1005
+ return {
1006
+ "status": "not_satisfied",
1007
+ "evidence": "No error handling patterns detected (secure or insecure).",
1008
+ "details": (
1009
+ "Expected: DEBUG=False, custom error handlers, and absence of "
1010
+ "DEBUG=True or traceback exposure in responses."
1011
+ ),
1012
+ }
1013
+
1014
+
1015
+ def _check_sbom_freshness(project_dir):
1016
+ """SBD-21: Check for SBOM files and their freshness (within 30 days)."""
1017
+ found = _dir_or_file_exists(
1018
+ project_dir,
1019
+ glob_patterns=[
1020
+ "*sbom*.json",
1021
+ "*bom*.xml",
1022
+ "*sbom*.xml",
1023
+ "*cyclonedx*",
1024
+ "*spdx*",
1025
+ ],
1026
+ )
1027
+
1028
+ if not found:
1029
+ return {
1030
+ "status": "not_satisfied",
1031
+ "evidence": "No SBOM artifacts detected in the project.",
1032
+ "details": (
1033
+ "Expected: *sbom*.json, *bom*.xml, *cyclonedx*, or *spdx* "
1034
+ "files."
1035
+ ),
1036
+ }
1037
+
1038
+ now = datetime.now(timezone.utc)
1039
+ fresh_files = []
1040
+ stale_files = []
1041
+ for fpath in found:
1042
+ try:
1043
+ mtime = datetime.utcfromtimestamp(os.path.getmtime(fpath))
1044
+ age_days = (now - mtime).days
1045
+ if age_days <= 30:
1046
+ fresh_files.append((fpath, age_days))
1047
+ else:
1048
+ stale_files.append((fpath, age_days))
1049
+ except Exception:
1050
+ stale_files.append((fpath, -1))
1051
+
1052
+ if fresh_files and not stale_files:
1053
+ return {
1054
+ "status": "satisfied",
1055
+ "evidence": (
1056
+ f"SBOM artifact(s) found and fresh: {len(fresh_files)} "
1057
+ f"file(s) modified within 30 days."
1058
+ ),
1059
+ "details": "; ".join(
1060
+ f"{os.path.basename(f)} ({d}d old)" for f, d in fresh_files[:5]
1061
+ ),
1062
+ }
1063
+ elif fresh_files and stale_files:
1064
+ return {
1065
+ "status": "partially_satisfied",
1066
+ "evidence": (
1067
+ f"{len(fresh_files)} fresh SBOM(s) but "
1068
+ f"{len(stale_files)} stale SBOM(s) detected."
1069
+ ),
1070
+ "details": (
1071
+ "Stale: "
1072
+ + "; ".join(
1073
+ f"{os.path.basename(f)} ({d}d old)"
1074
+ for f, d in stale_files[:5]
1075
+ )
1076
+ ),
1077
+ }
1078
+
1079
+ return {
1080
+ "status": "partially_satisfied",
1081
+ "evidence": (
1082
+ f"SBOM artifact(s) found but all are stale (>30 days old): "
1083
+ f"{len(stale_files)} file(s)."
1084
+ ),
1085
+ "details": (
1086
+ "Stale: "
1087
+ + "; ".join(
1088
+ f"{os.path.basename(f)} ({d}d old)" for f, d in stale_files[:5]
1089
+ )
1090
+ + ". Regenerate SBOM to meet freshness requirement."
1091
+ ),
1092
+ }
1093
+
1094
+
1095
+ def _check_dep_vuln_scanning(project_dir):
1096
+ """SBD-22: Look for dependency vulnerability scanning tooling or results."""
1097
+ # Check for scanning tool configs
1098
+ found_configs = _dir_or_file_exists(
1099
+ project_dir,
1100
+ glob_patterns=[
1101
+ ".snyk",
1102
+ ".safety",
1103
+ ".safety-policy.yml",
1104
+ "audit-report.json",
1105
+ "dependency-check-report*",
1106
+ "pip-audit-report*",
1107
+ "npm-audit-report*",
1108
+ ],
1109
+ )
1110
+
1111
+ # Scan CI config files for audit commands
1112
+ ci_patterns = [
1113
+ r"pip.audit|pip_audit|pipaudit",
1114
+ r"npm\s+audit|yarn\s+audit",
1115
+ r"\bsafety\b.*check|safety\s+scan",
1116
+ r"\bsnyk\b.*test|snyk\s+monitor",
1117
+ r"dependency.check|DependencyCheck",
1118
+ r"trivy\s+fs|grype\s+dir",
1119
+ ]
1120
+ ci_extensions = (
1121
+ ".yaml", ".yml", ".json", ".toml", ".cfg", ".ini",
1122
+ )
1123
+ ci_matched, _ = _scan_files(project_dir, ci_extensions, ci_patterns)
1124
+
1125
+ all_found = list(set(found_configs + ci_matched))
1126
+ if all_found:
1127
+ return {
1128
+ "status": "satisfied",
1129
+ "evidence": (
1130
+ f"Dependency vulnerability scanning tooling/results found: "
1131
+ f"{len(all_found)} artifact(s)."
1132
+ ),
1133
+ "details": "; ".join(
1134
+ os.path.basename(f) for f in all_found[:5]
1135
+ ),
1136
+ }
1137
+
1138
+ return {
1139
+ "status": "not_satisfied",
1140
+ "evidence": "No dependency vulnerability scanning tooling or results detected.",
1141
+ "details": (
1142
+ "Expected: pip-audit, npm audit, safety, Snyk configs, "
1143
+ ".snyk, audit-report.json, or dependency-check-report files."
1144
+ ),
1145
+ }
1146
+
1147
+
1148
+ def _check_threat_model(project_dir):
1149
+ """SBD-24: Look for threat model artifacts."""
1150
+ found = _dir_or_file_exists(
1151
+ project_dir,
1152
+ glob_patterns=[
1153
+ "threat-model*",
1154
+ "threat_model*",
1155
+ "STRIDE*",
1156
+ "PASTA*",
1157
+ "threat-analysis*",
1158
+ "threat_analysis*",
1159
+ "attack-tree*",
1160
+ "attack_tree*",
1161
+ ],
1162
+ )
1163
+ # Also check for threat model directories
1164
+ found_dirs = _dir_or_file_exists(
1165
+ project_dir,
1166
+ dir_names=[
1167
+ "threat-model",
1168
+ "threat_model",
1169
+ "threat-modeling",
1170
+ "threat_modeling",
1171
+ ],
1172
+ )
1173
+ # Check within docs/ or security/ subdirectories
1174
+ nested_found = _dir_or_file_exists(
1175
+ project_dir,
1176
+ glob_patterns=[
1177
+ "docs/threat-model*",
1178
+ "docs/threat_model*",
1179
+ "security/threat-model*",
1180
+ "security/threat_model*",
1181
+ ],
1182
+ )
1183
+
1184
+ all_found = list(set(found + found_dirs + nested_found))
1185
+ if all_found:
1186
+ return {
1187
+ "status": "satisfied",
1188
+ "evidence": (
1189
+ f"Threat model artifact(s) found: {len(all_found)} item(s)."
1190
+ ),
1191
+ "details": "; ".join(
1192
+ os.path.basename(f) for f in all_found[:5]
1193
+ ),
1194
+ }
1195
+
1196
+ return {
1197
+ "status": "not_satisfied",
1198
+ "evidence": "No threat model artifacts detected.",
1199
+ "details": (
1200
+ "Expected: threat-model.md, threat_model.*, STRIDE.*, PASTA.*, "
1201
+ "threat-analysis.*, attack-tree.*, or threat-model/ directory."
1202
+ ),
1203
+ }
1204
+
1205
+
1206
+ def _check_no_default_creds(project_dir):
1207
+ """SBD-28: Scan config files for default credential patterns (inverse check).
1208
+
1209
+ Returns satisfied if NO default credentials are found.
1210
+ """
1211
+ bad_patterns = [
1212
+ r"admin[:/]admin|admin/admin",
1213
+ r"root[:/]root|root/root",
1214
+ r"password123|passw0rd",
1215
+ r"changeme|change_me|CHANGEME",
1216
+ r"default[_\s]*password|default[_\s]*credential",
1217
+ r"test[:/]test|test/test",
1218
+ r"username.*=.*admin.*\n.*password.*=.*admin",
1219
+ ]
1220
+ extensions = (
1221
+ ".yaml", ".yml", ".json", ".conf", ".env",
1222
+ ".ini", ".cfg", ".properties",
1223
+ )
1224
+ matched, total = _scan_files(project_dir, extensions, bad_patterns)
1225
+
1226
+ if total == 0:
1227
+ return {
1228
+ "status": "not_satisfied",
1229
+ "evidence": "No configuration files found to assess.",
1230
+ "details": "Project directory lacks applicable config files.",
1231
+ }
1232
+
1233
+ if matched:
1234
+ return {
1235
+ "status": "not_satisfied",
1236
+ "evidence": (
1237
+ f"Default credential patterns detected in "
1238
+ f"{len(matched)} config file(s)."
1239
+ ),
1240
+ "details": (
1241
+ "Files with potential default credentials: "
1242
+ + "; ".join(os.path.basename(f) for f in matched[:5])
1243
+ + ". Remove admin/admin, root/root, changeme, test/test, "
1244
+ "and other default credential patterns."
1245
+ ),
1246
+ }
1247
+
1248
+ return {
1249
+ "status": "satisfied",
1250
+ "evidence": (
1251
+ f"Scanned {total} config file(s) -- no default credential "
1252
+ "patterns detected."
1253
+ ),
1254
+ "details": (
1255
+ "No instances of admin/admin, root/root, changeme, test/test, "
1256
+ "or other default credential patterns."
1257
+ ),
1258
+ }
1259
+
1260
+
1261
+ def _check_secure_config_baselines(project_dir):
1262
+ """SBD-29: Check Dockerfiles for STIG hardening and secure config baselines."""
1263
+ # Check Dockerfiles for hardening
1264
+ dockerfiles = _dir_or_file_exists(
1265
+ project_dir,
1266
+ glob_patterns=["Dockerfile*", "*.dockerfile"],
1267
+ )
1268
+
1269
+ hardened_docker = 0
1270
+ docker_evidence = []
1271
+ for df_path in dockerfiles:
1272
+ try:
1273
+ with open(df_path, "r", encoding="utf-8", errors="ignore") as f:
1274
+ content = f.read()
1275
+ except Exception:
1276
+ continue
1277
+
1278
+ checks = {
1279
+ "non_root_user": bool(
1280
+ re.search(r"USER\s+(?!root)\S+", content)
1281
+ ),
1282
+ "drop_capabilities": bool(
1283
+ re.search(
1284
+ r"drop.*ALL|securityContext.*drop|cap_drop",
1285
+ content,
1286
+ re.IGNORECASE | re.DOTALL,
1287
+ )
1288
+ ),
1289
+ "read_only_rootfs": bool(
1290
+ re.search(
1291
+ r"readOnlyRootFilesystem|read.only",
1292
+ content,
1293
+ re.IGNORECASE,
1294
+ )
1295
+ ),
1296
+ "minimal_base": bool(
1297
+ re.search(
1298
+ r"FROM.*(:slim|:alpine|-slim|-minimal|distroless|hardened)",
1299
+ content,
1300
+ re.IGNORECASE,
1301
+ )
1302
+ ),
1303
+ }
1304
+ passed = sum(checks.values())
1305
+ if passed >= 2:
1306
+ hardened_docker += 1
1307
+ docker_evidence.append(
1308
+ f"{os.path.basename(df_path)}: {passed}/4 hardening checks"
1309
+ )
1310
+
1311
+ # Check for insecure configs
1312
+ insecure_config_patterns = [
1313
+ r"DEBUG\s*=\s*True|DEBUG\s*:\s*true",
1314
+ r"Access.Control.Allow.Origin.*\*|CORS.*\*|allow_origins.*\*",
1315
+ r"AllowOverride\s+All|PermitRootLogin\s+yes",
1316
+ ]
1317
+ config_extensions = (".py", ".yaml", ".yml", ".conf", ".json", ".ini")
1318
+ insecure_matched, _ = _scan_files(
1319
+ project_dir, config_extensions, insecure_config_patterns
1320
+ )
1321
+
1322
+ has_hardened = hardened_docker > 0
1323
+ has_insecure = len(insecure_matched) > 0
1324
+
1325
+ if has_hardened and not has_insecure:
1326
+ return {
1327
+ "status": "satisfied",
1328
+ "evidence": (
1329
+ f"Secure config baselines detected: {hardened_docker} "
1330
+ f"hardened Dockerfile(s), no insecure configuration patterns."
1331
+ ),
1332
+ "details": "; ".join(docker_evidence),
1333
+ }
1334
+ elif has_hardened and has_insecure:
1335
+ return {
1336
+ "status": "partially_satisfied",
1337
+ "evidence": (
1338
+ f"Hardened Dockerfile(s) found ({hardened_docker}), but "
1339
+ f"insecure config patterns in {len(insecure_matched)} file(s)."
1340
+ ),
1341
+ "details": (
1342
+ "Hardened: " + "; ".join(docker_evidence)
1343
+ + " | Insecure configs: "
1344
+ + "; ".join(
1345
+ os.path.basename(f) for f in insecure_matched[:5]
1346
+ )
1347
+ ),
1348
+ }
1349
+ elif not has_hardened and dockerfiles:
1350
+ return {
1351
+ "status": "not_satisfied",
1352
+ "evidence": (
1353
+ f"Dockerfiles found ({len(dockerfiles)}) but none pass "
1354
+ "STIG hardening checks."
1355
+ ),
1356
+ "details": (
1357
+ "Expected: non-root USER, drop ALL capabilities, "
1358
+ "read-only rootfs, minimal base image."
1359
+ ),
1360
+ }
1361
+
1362
+ # No Dockerfiles -- check configs only
1363
+ secure_config_patterns = [
1364
+ r"DEBUG\s*=\s*False|DEBUG\s*:\s*false",
1365
+ r"security.*hardening|stig.*compliance|cis.*benchmark",
1366
+ ]
1367
+ secure_matched, _ = _scan_files(
1368
+ project_dir, config_extensions, secure_config_patterns
1369
+ )
1370
+
1371
+ if secure_matched and not has_insecure:
1372
+ return {
1373
+ "status": "partially_satisfied",
1374
+ "evidence": (
1375
+ f"Secure configuration patterns found in "
1376
+ f"{len(secure_matched)} file(s) but no Dockerfiles to assess."
1377
+ ),
1378
+ "details": "; ".join(
1379
+ os.path.basename(f) for f in secure_matched[:5]
1380
+ ),
1381
+ }
1382
+
1383
+ return {
1384
+ "status": "not_satisfied",
1385
+ "evidence": "No secure configuration baselines detected.",
1386
+ "details": (
1387
+ "Expected: STIG-hardened Dockerfiles (non-root USER, drop ALL), "
1388
+ "DEBUG=False, no wildcard CORS, no permissive security settings."
1389
+ ),
1390
+ }
1391
+
1392
+
1393
+ def _check_cui_markings(project_dir):
1394
+ """SBD-31: Scan Python and Markdown files for CUI marking strings.
1395
+
1396
+ Returns satisfied if >80% of files contain CUI markings.
1397
+ """
1398
+ patterns = [
1399
+ r"CUI\s*//\s*SP-CTI",
1400
+ r"CONTROLLED UNCLASSIFIED INFORMATION",
1401
+ r"\(CUI\)",
1402
+ ]
1403
+ matched, total = _scan_files(project_dir, (".py", ".md"), patterns)
1404
+
1405
+ if total == 0:
1406
+ return {
1407
+ "status": "not_satisfied",
1408
+ "evidence": "No Python or Markdown files found to assess.",
1409
+ "details": "Project directory contains no .py or .md files.",
1410
+ }
1411
+
1412
+ ratio = len(matched) / total
1413
+ if ratio > 0.8:
1414
+ return {
1415
+ "status": "satisfied",
1416
+ "evidence": (
1417
+ f"CUI markings found in {len(matched)}/{total} files "
1418
+ f"({ratio:.0%})."
1419
+ ),
1420
+ "details": f"Threshold: >80%. Files scanned: {total}.",
1421
+ }
1422
+ elif ratio > 0.4:
1423
+ return {
1424
+ "status": "partially_satisfied",
1425
+ "evidence": (
1426
+ f"CUI markings found in {len(matched)}/{total} files "
1427
+ f"({ratio:.0%})."
1428
+ ),
1429
+ "details": "Some files lack CUI markings. Must exceed 80% coverage.",
1430
+ }
1431
+ else:
1432
+ return {
1433
+ "status": "not_satisfied",
1434
+ "evidence": (
1435
+ f"CUI markings found in only {len(matched)}/{total} files "
1436
+ f"({ratio:.0%})."
1437
+ ),
1438
+ "details": (
1439
+ "Majority of files lack CUI markings. "
1440
+ "Requires >80% coverage."
1441
+ ),
1442
+ }
1443
+
1444
+
1445
+ # -----------------------------------------------------------------
1446
+ # Requirement-to-check mapping
1447
+ # -----------------------------------------------------------------
1448
+
1449
+ AUTO_CHECKS = {
1450
+ "SBD-01": _check_mfa_patterns,
1451
+ "SBD-02": _check_default_passwords,
1452
+ "SBD-03": _check_memory_safe_language,
1453
+ "SBD-04": _check_memory_safety_tooling,
1454
+ "SBD-05": _check_patch_cadence,
1455
+ "SBD-06": _check_vuln_disclosure,
1456
+ "SBD-08": _check_audit_logging_complete,
1457
+ "SBD-11": _check_tls_config,
1458
+ "SBD-12": _check_encryption_at_rest,
1459
+ "SBD-14": _check_rbac_least_priv,
1460
+ "SBD-16": _check_input_validation,
1461
+ "SBD-17": _check_output_encoding,
1462
+ "SBD-18": _check_security_headers,
1463
+ "SBD-19": _check_secure_error_handling,
1464
+ "SBD-21": _check_sbom_freshness,
1465
+ "SBD-22": _check_dep_vuln_scanning,
1466
+ "SBD-24": _check_threat_model,
1467
+ "SBD-28": _check_no_default_creds,
1468
+ "SBD-29": _check_secure_config_baselines,
1469
+ "SBD-31": _check_cui_markings,
1470
+ }
1471
+
1472
+
1473
+ # -----------------------------------------------------------------
1474
+ # Core assessment function
1475
+ # -----------------------------------------------------------------
1476
+
1477
+ def run_sbd_assessment(
1478
+ project_id,
1479
+ domain="all",
1480
+ project_dir=None,
1481
+ gate=False,
1482
+ output_path=None,
1483
+ db_path=None,
1484
+ ):
1485
+ """Run SbD assessment per CISA Secure by Design and DoDI 5000.87.
1486
+
1487
+ Args:
1488
+ project_id: The project identifier.
1489
+ domain: Filter to a specific SbD domain or "all".
1490
+ project_dir: Project directory for automated file-based checks.
1491
+ gate: If True, evaluate the SbD gate (0 critical not_satisfied = pass).
1492
+ output_path: Override output directory for the assessment report.
1493
+ db_path: Override database path.
1494
+
1495
+ Returns:
1496
+ Dict with assessment results, summary, gate result, and output file path.
1497
+ """
1498
+ conn = get_connection(db_path=db_path)
1499
+ try:
1500
+ project = _get_project(conn, project_id)
1501
+
1502
+ # Load SbD requirements catalog
1503
+ sbd_data = _load_sbd_requirements()
1504
+ metadata = sbd_data.get("metadata", {})
1505
+ requirements = sbd_data.get("requirements", [])
1506
+
1507
+ # Filter by domain if specified
1508
+ if domain != "all":
1509
+ requirements = [
1510
+ r for r in requirements
1511
+ if r.get("domain") == domain
1512
+ ]
1513
+ if not requirements:
1514
+ raise ValueError(
1515
+ f"No requirements found for domain '{domain}'. "
1516
+ "Valid domains: Authentication, Memory Safety, "
1517
+ "Vulnerability Mgmt, Intrusion Evidence, Cryptography, "
1518
+ "Access Control, Input Handling, Error Handling, "
1519
+ "Supply Chain, Threat Modeling, Defense in Depth, "
1520
+ "Secure Defaults, CUI Compliance, DoD Software Assurance."
1521
+ )
1522
+
1523
+ # Resolve project directory for auto-checks
1524
+ if project_dir and Path(project_dir).is_dir():
1525
+ can_auto_check = True
1526
+ elif (
1527
+ project.get("directory_path")
1528
+ and Path(project["directory_path"]).is_dir()
1529
+ ):
1530
+ project_dir = project["directory_path"]
1531
+ can_auto_check = True
1532
+ else:
1533
+ can_auto_check = False
1534
+
1535
+ now = datetime.now(timezone.utc)
1536
+ results = []
1537
+
1538
+ # -- Assess each requirement --
1539
+ for req in requirements:
1540
+ req_id = req["id"]
1541
+ automation_level = req.get("automation_level", "manual")
1542
+ status = "not_assessed"
1543
+ evidence = ""
1544
+ details = ""
1545
+ notes = ""
1546
+
1547
+ if automation_level == "auto" and can_auto_check:
1548
+ if req_id in AUTO_CHECKS:
1549
+ try:
1550
+ check_result = AUTO_CHECKS[req_id](project_dir)
1551
+ status = check_result["status"]
1552
+ evidence = check_result["evidence"]
1553
+ details = check_result.get("details", "")
1554
+ except Exception as e:
1555
+ status = "not_assessed"
1556
+ evidence = f"Auto-check error: {e}"
1557
+ notes = "Auto-check failed; manual review required."
1558
+ else:
1559
+ # Auto-level requirement without a mapped check function
1560
+ status = "not_assessed"
1561
+ evidence = (
1562
+ "No automated check implemented for this requirement."
1563
+ )
1564
+ notes = "Manual review required."
1565
+
1566
+ elif automation_level == "auto" and not can_auto_check:
1567
+ status = "not_assessed"
1568
+ evidence = (
1569
+ "No project directory available for automated scanning."
1570
+ )
1571
+ notes = "Provide --project-dir to enable auto-checks."
1572
+
1573
+ elif automation_level == "semi" and can_auto_check:
1574
+ # Run partial check if a mapped function exists
1575
+ if req_id in AUTO_CHECKS:
1576
+ try:
1577
+ check_result = AUTO_CHECKS[req_id](project_dir)
1578
+ status = check_result["status"]
1579
+ evidence = check_result["evidence"]
1580
+ details = check_result.get("details", "")
1581
+ notes = (
1582
+ "Semi-automated check completed. "
1583
+ "Manual review required to verify full compliance."
1584
+ )
1585
+ except Exception as e:
1586
+ status = "not_assessed"
1587
+ evidence = f"Partial auto-check error: {e}"
1588
+ notes = (
1589
+ "Semi-automated check failed; "
1590
+ "full manual review required."
1591
+ )
1592
+ else:
1593
+ status = "not_assessed"
1594
+ evidence = (
1595
+ "Semi-automated: no automated component implemented."
1596
+ )
1597
+ notes = (
1598
+ f"Manual review required. Evidence needed: "
1599
+ f"{req.get('evidence_required', 'See requirement description.')}"
1600
+ )
1601
+
1602
+ elif automation_level == "semi" and not can_auto_check:
1603
+ status = "not_assessed"
1604
+ evidence = (
1605
+ "Semi-automated check requires project directory."
1606
+ )
1607
+ notes = (
1608
+ f"Manual review required. Evidence needed: "
1609
+ f"{req.get('evidence_required', 'See requirement description.')}"
1610
+ )
1611
+
1612
+ else:
1613
+ # manual automation_level
1614
+ status = "not_assessed"
1615
+ evidence = "Manual assessment required."
1616
+ notes = (
1617
+ f"This requirement must be verified manually. "
1618
+ f"Evidence needed: "
1619
+ f"{req.get('evidence_required', 'See requirement description.')}"
1620
+ )
1621
+
1622
+ result_entry = {
1623
+ "requirement_id": req_id,
1624
+ "domain": req.get("domain", ""),
1625
+ "title": req.get("title", ""),
1626
+ "description": req.get("description", ""),
1627
+ "priority": req.get("priority", "medium"),
1628
+ "automation_level": automation_level,
1629
+ "nist_controls": req.get("nist_controls", []),
1630
+ "cisa_commitment": req.get("cisa_commitment", ""),
1631
+ "status": status,
1632
+ "evidence": evidence,
1633
+ "details": details,
1634
+ "notes": notes,
1635
+ }
1636
+ results.append(result_entry)
1637
+
1638
+ # -- Upsert into sbd_assessments table --
1639
+ # Uses INSERT OR REPLACE on UNIQUE(project_id, requirement_id)
1640
+ try:
1641
+ conn.execute(
1642
+ """INSERT OR REPLACE INTO sbd_assessments
1643
+ (project_id, assessment_date, assessor, domain,
1644
+ requirement_id, status, evidence_description,
1645
+ evidence_path, automation_result, cisa_commitment,
1646
+ notes, updated_at)
1647
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
1648
+ (
1649
+ project_id,
1650
+ now.isoformat(),
1651
+ "icdev-compliance-engine",
1652
+ req.get("domain", ""),
1653
+ req_id,
1654
+ status,
1655
+ evidence,
1656
+ details if details else None,
1657
+ json.dumps({
1658
+ "automation_level": automation_level,
1659
+ "check_function": (
1660
+ AUTO_CHECKS[req_id].__name__
1661
+ if req_id in AUTO_CHECKS
1662
+ else None
1663
+ ),
1664
+ }),
1665
+ req.get("cisa_commitment", ""),
1666
+ notes if notes else None,
1667
+ now.isoformat(),
1668
+ ),
1669
+ )
1670
+ except Exception as e:
1671
+ print(
1672
+ f"Warning: Could not upsert assessment for {req_id}: {e}",
1673
+ file=sys.stderr,
1674
+ )
1675
+
1676
+ conn.commit()
1677
+
1678
+ # -- Build summary by domain --
1679
+ domain_order = [
1680
+ "Authentication",
1681
+ "Memory Safety",
1682
+ "Vulnerability Mgmt",
1683
+ "Intrusion Evidence",
1684
+ "Cryptography",
1685
+ "Access Control",
1686
+ "Input Handling",
1687
+ "Error Handling",
1688
+ "Supply Chain",
1689
+ "Threat Modeling",
1690
+ "Defense in Depth",
1691
+ "Secure Defaults",
1692
+ "CUI Compliance",
1693
+ "DoD Software Assurance",
1694
+ ]
1695
+ summary = {}
1696
+ for d in domain_order:
1697
+ summary[d] = {
1698
+ "total": 0,
1699
+ "satisfied": 0,
1700
+ "partially_satisfied": 0,
1701
+ "not_satisfied": 0,
1702
+ "not_assessed": 0,
1703
+ "not_applicable": 0,
1704
+ "risk_accepted": 0,
1705
+ }
1706
+
1707
+ for r in results:
1708
+ d = r["domain"]
1709
+ if d not in summary:
1710
+ summary[d] = {
1711
+ "total": 0,
1712
+ "satisfied": 0,
1713
+ "partially_satisfied": 0,
1714
+ "not_satisfied": 0,
1715
+ "not_assessed": 0,
1716
+ "not_applicable": 0,
1717
+ "risk_accepted": 0,
1718
+ }
1719
+ summary[d]["total"] += 1
1720
+ st = r["status"]
1721
+ if st in summary[d]:
1722
+ summary[d][st] += 1
1723
+
1724
+ # -- Gate evaluation --
1725
+ critical_not_satisfied = 0
1726
+ critical_failures = []
1727
+ for r in results:
1728
+ if (
1729
+ r["priority"] == "critical"
1730
+ and r["status"] == "not_satisfied"
1731
+ ):
1732
+ critical_not_satisfied += 1
1733
+ critical_failures.append(
1734
+ f"{r['requirement_id']}: {r['title']}"
1735
+ )
1736
+
1737
+ gate_passed = critical_not_satisfied == 0
1738
+ gate_result = {
1739
+ "evaluated": gate,
1740
+ "passed": gate_passed,
1741
+ "critical_not_satisfied": critical_not_satisfied,
1742
+ "critical_failures": critical_failures,
1743
+ "reason": (
1744
+ "PASS: 0 critical-priority requirements have status "
1745
+ "not_satisfied"
1746
+ if gate_passed
1747
+ else (
1748
+ f"FAIL: {critical_not_satisfied} critical-priority "
1749
+ f"requirement(s) not satisfied: "
1750
+ f"{', '.join(critical_failures)}"
1751
+ )
1752
+ ),
1753
+ }
1754
+
1755
+ # -- Generate Markdown assessment report --
1756
+ cui_config = _load_cui_config()
1757
+ doc_header = cui_config.get(
1758
+ "document_header", "CUI // SP-CTI"
1759
+ ).strip()
1760
+ doc_footer = cui_config.get(
1761
+ "document_footer", "CUI // SP-CTI"
1762
+ ).strip()
1763
+
1764
+ lines = [
1765
+ doc_header,
1766
+ "",
1767
+ "# SbD Assessment Report -- CISA Secure by Design / DoDI 5000.87",
1768
+ "",
1769
+ f"**Project:** {project.get('name', project_id)} ({project_id})",
1770
+ f"**Assessment Date:** {now.strftime('%Y-%m-%d %H:%M UTC')}",
1771
+ "**Assessor:** ICDEV Compliance Engine (automated)",
1772
+ f"**Domain Scope:** {domain}",
1773
+ (
1774
+ f"**CISA SbD Revision:** "
1775
+ f"{metadata.get('revision', 'N/A')}"
1776
+ ),
1777
+ "**Classification:** CUI // SP-CTI",
1778
+ "",
1779
+ "---",
1780
+ "",
1781
+ "## Executive Summary",
1782
+ "",
1783
+ ]
1784
+
1785
+ # Summary table
1786
+ lines.append(
1787
+ "| Domain | Total | Satisfied | Partial | Not Satisfied "
1788
+ "| Not Assessed | N/A | Risk Accepted |"
1789
+ )
1790
+ lines.append(
1791
+ "|--------|-------|-----------|---------|---------------"
1792
+ "|--------------|-----|---------------|"
1793
+ )
1794
+
1795
+ grand_total = {
1796
+ "total": 0,
1797
+ "satisfied": 0,
1798
+ "partially_satisfied": 0,
1799
+ "not_satisfied": 0,
1800
+ "not_assessed": 0,
1801
+ "not_applicable": 0,
1802
+ "risk_accepted": 0,
1803
+ }
1804
+
1805
+ for d in domain_order:
1806
+ s = summary.get(d, {})
1807
+ if s.get("total", 0) == 0:
1808
+ continue
1809
+ lines.append(
1810
+ f"| {d} | {s['total']} | {s['satisfied']} | "
1811
+ f"{s['partially_satisfied']} | {s['not_satisfied']} | "
1812
+ f"{s['not_assessed']} | {s['not_applicable']} | "
1813
+ f"{s['risk_accepted']} |"
1814
+ )
1815
+ for key in grand_total:
1816
+ grand_total[key] += s.get(key, 0)
1817
+
1818
+ lines.append(
1819
+ f"| **Total** | **{grand_total['total']}** | "
1820
+ f"**{grand_total['satisfied']}** | "
1821
+ f"**{grand_total['partially_satisfied']}** | "
1822
+ f"**{grand_total['not_satisfied']}** | "
1823
+ f"**{grand_total['not_assessed']}** | "
1824
+ f"**{grand_total['not_applicable']}** | "
1825
+ f"**{grand_total['risk_accepted']}** |"
1826
+ )
1827
+ lines.append("")
1828
+
1829
+ # Gate evaluation section
1830
+ if gate:
1831
+ gate_label = (
1832
+ "PASS" if gate_result["passed"] else "**FAIL**"
1833
+ )
1834
+ lines.extend([
1835
+ "## SbD Gate Evaluation",
1836
+ "",
1837
+ f"**Gate Result:** {gate_label}",
1838
+ (
1839
+ "**Criteria:** 0 critical-priority requirements "
1840
+ "with status not_satisfied"
1841
+ ),
1842
+ f"**Critical Failures:** {critical_not_satisfied}",
1843
+ "",
1844
+ ])
1845
+ if critical_failures:
1846
+ lines.append("**Failed Requirements:**")
1847
+ for cf in critical_failures:
1848
+ lines.append(f"- {cf}")
1849
+ lines.append("")
1850
+
1851
+ lines.extend(["---", ""])
1852
+
1853
+ # -- Detailed findings per domain --
1854
+ lines.append("## Detailed Findings")
1855
+ lines.append("")
1856
+
1857
+ for d in domain_order:
1858
+ domain_results = [r for r in results if r["domain"] == d]
1859
+ if not domain_results:
1860
+ continue
1861
+
1862
+ lines.append(f"### {d}")
1863
+ lines.append("")
1864
+
1865
+ for r in domain_results:
1866
+ status_display = r["status"].replace("_", " ").title()
1867
+ priority_display = r["priority"].upper()
1868
+ nist_str = (
1869
+ ", ".join(r["nist_controls"])
1870
+ if r["nist_controls"]
1871
+ else "N/A"
1872
+ )
1873
+ cisa_str = r.get("cisa_commitment", "N/A") or "N/A"
1874
+
1875
+ lines.extend([
1876
+ f"#### {r['requirement_id']}: {r['title']}",
1877
+ "",
1878
+ f"**Priority:** {priority_display} ",
1879
+ f"**Status:** {status_display} ",
1880
+ f"**Automation Level:** {r['automation_level']} ",
1881
+ f"**NIST Controls:** {nist_str} ",
1882
+ f"**CISA Commitment:** {cisa_str}",
1883
+ "",
1884
+ f"**Evidence:** {r['evidence']}",
1885
+ "",
1886
+ ])
1887
+ if r["details"]:
1888
+ lines.append(f"**Details:** {r['details']}")
1889
+ lines.append("")
1890
+ if r["notes"]:
1891
+ lines.append(f"**Notes:** {r['notes']}")
1892
+ lines.append("")
1893
+
1894
+ lines.extend(["---", ""])
1895
+
1896
+ # Append CUI footer
1897
+ lines.extend([doc_footer, ""])
1898
+ content = "\n".join(lines)
1899
+
1900
+ # -- Write output file --
1901
+ if output_path:
1902
+ out_dir = Path(output_path)
1903
+ else:
1904
+ dir_path = project.get("directory_path", "")
1905
+ if dir_path:
1906
+ out_dir = Path(dir_path) / "compliance"
1907
+ else:
1908
+ out_dir = BASE_DIR / ".tmp" / "compliance" / project_id
1909
+ out_dir.mkdir(parents=True, exist_ok=True)
1910
+
1911
+ domain_suffix = (
1912
+ domain.lower().replace(" ", "_")
1913
+ if domain != "all"
1914
+ else "all"
1915
+ )
1916
+ out_file = (
1917
+ out_dir
1918
+ / f"sbd_cisa_{project_id}_{domain_suffix}_"
1919
+ f"{now.strftime('%Y%m%d_%H%M%S')}.md"
1920
+ )
1921
+
1922
+ with open(out_file, "w", encoding="utf-8") as f:
1923
+ f.write(content)
1924
+
1925
+ # -- Log audit event --
1926
+ _log_audit_event(
1927
+ conn,
1928
+ project_id,
1929
+ f"SbD assessment completed ({domain})",
1930
+ {
1931
+ "domain": domain,
1932
+ "requirements_assessed": len(results),
1933
+ "summary": {k: v for k, v in grand_total.items()},
1934
+ "gate_result": gate_result,
1935
+ "output_file": str(out_file),
1936
+ },
1937
+ out_file,
1938
+ )
1939
+
1940
+ # -- Console output --
1941
+ print("SbD assessment completed:")
1942
+ print(f" File: {out_file}")
1943
+ print(f" Scope: {domain}")
1944
+ print(f" Requirements assessed: {len(results)}")
1945
+ for d in domain_order:
1946
+ s = summary.get(d, {})
1947
+ if s.get("total", 0) == 0:
1948
+ continue
1949
+ print(
1950
+ f" {d}: "
1951
+ f"SAT={s['satisfied']} "
1952
+ f"PARTIAL={s['partially_satisfied']} "
1953
+ f"NOT_SAT={s['not_satisfied']} "
1954
+ f"NOT_ASSESSED={s['not_assessed']}"
1955
+ )
1956
+
1957
+ if gate:
1958
+ print(f"\n Gate: {gate_result['reason']}")
1959
+
1960
+ return {
1961
+ "output_file": str(out_file),
1962
+ "results": results,
1963
+ "summary": summary,
1964
+ "gate_result": gate_result,
1965
+ }
1966
+
1967
+ finally:
1968
+ conn.close()
1969
+
1970
+
1971
+ def assess_project(
1972
+ project_id,
1973
+ domain="all",
1974
+ project_dir=None,
1975
+ gate=False,
1976
+ output_path=None,
1977
+ db_path=None,
1978
+ ):
1979
+ """Alias for run_sbd_assessment (MCP compatibility)."""
1980
+ return run_sbd_assessment(
1981
+ project_id,
1982
+ domain=domain,
1983
+ project_dir=project_dir,
1984
+ gate=gate,
1985
+ output_path=output_path,
1986
+ db_path=db_path,
1987
+ )
1988
+
1989
+
1990
+ # -----------------------------------------------------------------
1991
+ # CLI entrypoint
1992
+ # -----------------------------------------------------------------
1993
+
1994
+ if __name__ == "__main__":
1995
+ parser = argparse.ArgumentParser(
1996
+ description="Run SbD assessment per CISA Secure by Design"
1997
+ )
1998
+ parser.add_argument(
1999
+ "--project-id", required=True, help="Project ID"
2000
+ )
2001
+ parser.add_argument(
2002
+ "--domain",
2003
+ default="all",
2004
+ choices=[
2005
+ "all",
2006
+ "Authentication",
2007
+ "Memory Safety",
2008
+ "Vulnerability Mgmt",
2009
+ "Intrusion Evidence",
2010
+ "Cryptography",
2011
+ "Access Control",
2012
+ "Input Handling",
2013
+ "Error Handling",
2014
+ "Supply Chain",
2015
+ "Threat Modeling",
2016
+ "Defense in Depth",
2017
+ "Secure Defaults",
2018
+ "CUI Compliance",
2019
+ "DoD Software Assurance",
2020
+ ],
2021
+ help="SbD domain to assess (default: all)",
2022
+ )
2023
+ parser.add_argument(
2024
+ "--project-dir",
2025
+ help="Project directory for automated file-based checks",
2026
+ )
2027
+ parser.add_argument(
2028
+ "--gate",
2029
+ action="store_true",
2030
+ help="Evaluate SbD gate (0 critical not_satisfied = pass)",
2031
+ )
2032
+ parser.add_argument(
2033
+ "--output-dir",
2034
+ help="Output directory for the assessment report",
2035
+ )
2036
+ parser.add_argument(
2037
+ "--db-path",
2038
+ type=Path,
2039
+ default=DB_PATH,
2040
+ help="Override database path",
2041
+ )
2042
+ parser.add_argument("--json", action="store_true", dest="json_output", help="JSON output")
2043
+ args = parser.parse_args()
2044
+
2045
+ try:
2046
+ result = run_sbd_assessment(
2047
+ project_id=args.project_id,
2048
+ domain=args.domain,
2049
+ project_dir=args.project_dir,
2050
+ gate=args.gate,
2051
+ output_path=args.output_dir,
2052
+ db_path=args.db_path,
2053
+ )
2054
+ print(
2055
+ json.dumps(
2056
+ {
2057
+ "output_file": result.get("output_file"),
2058
+ "summary": result.get("summary"),
2059
+ "gate_result": result.get("gate_result"),
2060
+ },
2061
+ indent=2,
2062
+ )
2063
+ )
2064
+
2065
+ if args.gate and not result["gate_result"]["passed"]:
2066
+ sys.exit(1)
2067
+
2068
+ except (FileNotFoundError, ValueError) as e:
2069
+ print(f"ERROR: {e}", file=sys.stderr)
2070
+ sys.exit(1)