@hoanghainh/komagu 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/assess/lsa/scripts/attack_chains.py +573 -0
  3. package/assess/lsa/scripts/baseline.py +14 -0
  4. package/assess/lsa/scripts/findings_to_sarif.py +11 -0
  5. package/assess/lsa/scripts/forecast.py +544 -0
  6. package/assess/lsa/scripts/merge_findings.py +14 -0
  7. package/assess/lsa/scripts/render_report.py +86 -0
  8. package/assess/lsa/tests/test_attack_chains.py +292 -0
  9. package/assess/lsa/tests/test_forecast.py +160 -0
  10. package/contracts/schemas/api-inventory-diff.schema.json +213 -0
  11. package/contracts/schemas/attack-chain.schema.json +181 -0
  12. package/contracts/schemas/bas-scenario.schema.json +217 -0
  13. package/contracts/schemas/evidence-manifest.schema.json +117 -0
  14. package/contracts/schemas/finding.schema.json +7 -0
  15. package/contracts/schemas/forecast.schema.json +172 -0
  16. package/governance/scs/__init__.py +21 -0
  17. package/governance/scs/mapping.py +133 -0
  18. package/governance/scs/pack.py +354 -0
  19. package/operate/cli/__init__.py +1 -1
  20. package/operate/cli/commands/evidence.py +138 -0
  21. package/operate/cli/commands/inventory.py +187 -0
  22. package/operate/cli/commands/simulate.py +175 -58
  23. package/operate/cli/main.py +7 -3
  24. package/operate/inventory/__init__.py +22 -0
  25. package/operate/inventory/api_inventory.py +566 -0
  26. package/operate/simulate/__init__.py +16 -0
  27. package/operate/simulate/engine.py +370 -0
  28. package/operate/simulate/loader.py +158 -0
  29. package/operate/simulate/scenarios/idc-frontier-ransomware.json +47 -0
  30. package/operate/simulate/scenarios/metabase-cve-2026-72898.json +84 -0
  31. package/operate/simulate/scenarios/times-car-breach.json +74 -0
  32. package/operate/simulate/scenarios.py +52 -0
  33. package/operate/tests/test_api_inventory.py +239 -0
  34. package/operate/tests/test_declarative_scenarios.py +169 -0
  35. package/operate/tests/test_evidence_pack.py +128 -0
  36. package/package.json +1 -1
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env python3
2
+ """Comprehensive unit tests for METI SCS Evidence Pack and Gap Report (#271).
3
+
4
+ Validates:
5
+ 1. evidence-manifest.schema.json schema conformity.
6
+ 2. Control mapping evaluation and readiness rating logic (★3, ★4, GAP).
7
+ 3. ZIP archive bundling, SHA-256 cryptographic digests, and manifest structure.
8
+ 4. Bilingual gap report generation (gap-report.ja.md and gap-report.md).
9
+ 5. CLI execution `komagu evidence`, argument parsing, and quality gating (--require-tier).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import os
16
+ import sys
17
+ import tempfile
18
+ import unittest
19
+ import zipfile
20
+ from pathlib import Path
21
+
22
+ PROJECT_ROOT = Path(__file__).resolve().parents[2]
23
+ if str(PROJECT_ROOT) not in sys.path:
24
+ sys.path.insert(0, str(PROJECT_ROOT))
25
+
26
+ from assess.lsa.scripts.merge_findings import load_validator
27
+ from governance.scs.mapping import SCS_CONTROLS
28
+ from governance.scs.pack import EvidencePackBuilder
29
+ from operate.cli.main import main as cli_main
30
+
31
+
32
+ class TestEvidencePack(unittest.TestCase):
33
+ def setUp(self) -> None:
34
+ self.validate_schema = load_validator("evidence-manifest.schema.json")
35
+
36
+ def test_schema_conformity_on_evaluated_manifest(self) -> None:
37
+ """Generated evidence manifest must strictly conform to evidence-manifest.schema.json."""
38
+ with tempfile.TemporaryDirectory() as tmp_dir:
39
+ # Create synthetic audit artifacts
40
+ audit_dir = Path(tmp_dir) / "audit"
41
+ audit_dir.mkdir()
42
+ (audit_dir / "findings.sarif").write_text("{}", encoding="utf-8")
43
+ (audit_dir / "sbom-cyclonedx.json").write_text("{}", encoding="utf-8")
44
+ (audit_dir / "api-inventory-diff.json").write_text("{}", encoding="utf-8")
45
+ (audit_dir / "coraza.conf").write_text("SecRuleEngine On", encoding="utf-8")
46
+ (audit_dir / "bas-evidence.json").write_text("{}", encoding="utf-8")
47
+
48
+ builder = EvidencePackBuilder(
49
+ audit_dirs=[audit_dir],
50
+ project_name="Test Enterprise Portal",
51
+ target_system="Production-Kubernetes",
52
+ )
53
+ arts = builder.discover_artifacts()
54
+ ctrls, readiness = builder.evaluate_controls(arts)
55
+ manifest = builder.generate_manifest(ctrls, readiness, arts)
56
+
57
+ errs = self.validate_schema(manifest)
58
+ self.assertEqual(errs, [], f"Schema validation errors: {errs}")
59
+ self.assertEqual(manifest["project_name"], "Test Enterprise Portal")
60
+ self.assertEqual(manifest["overall_readiness"]["rating"], "SCS-★4-READY")
61
+
62
+ def test_pack_builder_generates_zip_and_reports(self) -> None:
63
+ """build_pack must package evidence-pack.zip, manifest JSON, and bilingual reports."""
64
+ with tempfile.TemporaryDirectory() as tmp_dir:
65
+ audit_dir = Path(tmp_dir) / "audit"
66
+ audit_dir.mkdir()
67
+ (audit_dir / "findings.sarif").write_text('{"runs": []}', encoding="utf-8")
68
+ (audit_dir / "sbom-cyclonedx.json").write_text('{"bomFormat": "CycloneDX"}', encoding="utf-8")
69
+
70
+ out_dir = Path(tmp_dir) / "output"
71
+
72
+ builder = EvidencePackBuilder(
73
+ audit_dirs=[audit_dir],
74
+ project_name="Tokyo Logistics Monolith",
75
+ )
76
+ zip_p, manifest_p, ja_p, en_p = builder.build_pack(out_dir)
77
+
78
+ self.assertTrue(zip_p.is_file())
79
+ self.assertTrue(manifest_p.is_file())
80
+ self.assertTrue(ja_p.is_file())
81
+ self.assertTrue(en_p.is_file())
82
+
83
+ # Verify Japanese report content
84
+ ja_content = ja_p.read_text(encoding="utf-8")
85
+ self.assertIn("サプライチェーン・サイバーセキュリティ", ja_content)
86
+ self.assertIn("NIST CSF 2.0", ja_content)
87
+ self.assertIn("Tokyo Logistics Monolith", ja_content)
88
+
89
+ # Verify English report content
90
+ en_content = en_p.read_text(encoding="utf-8")
91
+ self.assertIn("METI Supply Chain Security", en_content)
92
+ self.assertIn("Tokyo Logistics Monolith", en_content)
93
+
94
+ # Verify ZIP contents
95
+ with zipfile.ZipFile(zip_p, "r") as zf:
96
+ names = zf.namelist()
97
+ self.assertIn("evidence-manifest.json", names)
98
+ self.assertIn("gap-report.ja.md", names)
99
+ self.assertIn("gap-report.md", names)
100
+ self.assertIn("artifacts/findings.sarif", names)
101
+ self.assertIn("artifacts/sbom-cyclonedx.json", names)
102
+
103
+ def test_cli_evidence_command_execution_and_gating(self) -> None:
104
+ """Test `komagu evidence` CLI invocation and tier requirements."""
105
+ with tempfile.TemporaryDirectory() as tmp_dir:
106
+ audit_dir = Path(tmp_dir) / "audit"
107
+ audit_dir.mkdir()
108
+ (audit_dir / "findings.sarif").write_text("{}", encoding="utf-8")
109
+
110
+ out_dir = Path(tmp_dir) / "pack"
111
+
112
+ # Execute without gate -> should succeed
113
+ code = cli_main(["evidence", "--audit-dir", str(audit_dir), "--output-dir", str(out_dir)])
114
+ self.assertEqual(code, 0)
115
+ self.assertTrue((out_dir / "evidence-pack.zip").is_file())
116
+
117
+ # Require tier 4 with only 1 artifact -> should fail quality gate
118
+ code_gate = cli_main([
119
+ "evidence",
120
+ "--audit-dir", str(audit_dir),
121
+ "--output-dir", str(out_dir),
122
+ "--require-tier", "4",
123
+ ])
124
+ self.assertEqual(code_gate, 1)
125
+
126
+
127
+ if __name__ == "__main__":
128
+ unittest.main()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoanghainh/komagu",
3
- "version": "2.2.1",
3
+ "version": "2.3.0",
4
4
  "description": "Security-First Legacy Modernization Platform CLI (LSA Kit, IAM Perimeter, Cross-User Testing)",
5
5
  "main": "remediate/authz/nodejs/src/index.js",
6
6
  "types": "remediate/authz/nodejs/src/index.d.ts",