kekkai-cli 1.1.0__tar.gz → 1.1.1__tar.gz
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.
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/PKG-INFO +33 -13
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/README.md +32 -12
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/pyproject.toml +2 -3
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/cli.py +124 -33
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/dojo_import.py +9 -1
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/output.py +1 -1
- kekkai_cli-1.1.1/src/kekkai/report/unified.py +226 -0
- kekkai_cli-1.1.1/src/kekkai/triage/__init__.py +86 -0
- kekkai_cli-1.1.1/src/kekkai/triage/loader.py +196 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/PKG-INFO +33 -13
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/SOURCES.txt +4 -33
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/entry_points.txt +0 -1
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/top_level.txt +0 -1
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_dojo_import.py +30 -0
- kekkai_cli-1.1.1/tests/test_triage_loader.py +283 -0
- kekkai_cli-1.1.1/tests/test_unified_report.py +529 -0
- kekkai_cli-1.1.0/src/kekkai/triage/__init__.py +0 -33
- kekkai_cli-1.1.0/src/portal/__init__.py +0 -19
- kekkai_cli-1.1.0/src/portal/api.py +0 -155
- kekkai_cli-1.1.0/src/portal/auth.py +0 -103
- kekkai_cli-1.1.0/src/portal/enterprise/__init__.py +0 -45
- kekkai_cli-1.1.0/src/portal/enterprise/audit.py +0 -435
- kekkai_cli-1.1.0/src/portal/enterprise/licensing.py +0 -408
- kekkai_cli-1.1.0/src/portal/enterprise/rbac.py +0 -276
- kekkai_cli-1.1.0/src/portal/enterprise/saml.py +0 -595
- kekkai_cli-1.1.0/src/portal/ops/__init__.py +0 -53
- kekkai_cli-1.1.0/src/portal/ops/backup.py +0 -553
- kekkai_cli-1.1.0/src/portal/ops/log_shipper.py +0 -469
- kekkai_cli-1.1.0/src/portal/ops/monitoring.py +0 -517
- kekkai_cli-1.1.0/src/portal/ops/restore.py +0 -469
- kekkai_cli-1.1.0/src/portal/ops/secrets.py +0 -408
- kekkai_cli-1.1.0/src/portal/ops/upgrade.py +0 -591
- kekkai_cli-1.1.0/src/portal/tenants.py +0 -340
- kekkai_cli-1.1.0/src/portal/uploads.py +0 -259
- kekkai_cli-1.1.0/src/portal/web.py +0 -393
- kekkai_cli-1.1.0/tests/test_enterprise_audit.py +0 -288
- kekkai_cli-1.1.0/tests/test_enterprise_licensing.py +0 -367
- kekkai_cli-1.1.0/tests/test_enterprise_rbac.py +0 -224
- kekkai_cli-1.1.0/tests/test_enterprise_saml.py +0 -326
- kekkai_cli-1.1.0/tests/test_ops_backup.py +0 -318
- kekkai_cli-1.1.0/tests/test_ops_log_shipper.py +0 -366
- kekkai_cli-1.1.0/tests/test_ops_monitoring.py +0 -379
- kekkai_cli-1.1.0/tests/test_ops_restore.py +0 -299
- kekkai_cli-1.1.0/tests/test_ops_secrets.py +0 -331
- kekkai_cli-1.1.0/tests/test_ops_upgrade.py +0 -418
- kekkai_cli-1.1.0/tests/test_portal_api.py +0 -157
- kekkai_cli-1.1.0/tests/test_portal_auth.py +0 -226
- kekkai_cli-1.1.0/tests/test_portal_tenants.py +0 -347
- kekkai_cli-1.1.0/tests/test_portal_uploads.py +0 -378
- kekkai_cli-1.1.0/tests/test_portal_web.py +0 -386
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/setup.cfg +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/hipaa.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/mappings.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/owasp.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/owasp_agentic.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/pci_dss.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/compliance/soc2.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/config.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/dojo.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/fix/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/fix/audit.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/fix/differ.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/fix/engine.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/fix/prompts.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/github/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/github/commenter.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/github/models.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/github/sanitizer.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/errors.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/extract.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/manager.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/manifest.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/installer/verify.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/manifest.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/paths.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/policy.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/report/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/report/compliance_matrix.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/report/generator.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/report/html.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/report/pdf.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/runner.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/backends/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/backends/base.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/backends/docker.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/backends/native.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/base.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/container.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/falco.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/gitleaks.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/semgrep.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/trivy.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/url_policy.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/scanners/zap.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/artifacts.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/chunking.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/core.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/mermaid.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/model_adapter.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/prompts.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/redaction.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/threatflow/sanitizer.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/app.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/audit.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/ignore.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/models.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/screens.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai/triage/widgets.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/dependency_links.txt +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_cli.egg-info/requires.txt +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/ci/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/ci/benchmarks.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/ci/metadata.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/ci/validators.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/docker/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/docker/metadata.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/docker/sbom.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/docker/security.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/docker/signing.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/redaction.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/slsa/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/slsa/verify.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/windows/__init__.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/windows/chocolatey.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/windows/installer.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/windows/scoop.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/src/kekkai_core/windows/validators.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_cli_output.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_compliance.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_fix_engine.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_github_commenter_filter.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_github_commenter_format.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_github_commenter_limit.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_github_commenter_sanitize.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_installer_checksum.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_installer_extract.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_installer_manager.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_installer_manifest.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_installer_platform.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_cli.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_config.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_dojo.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_dojo_cli.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_manifest.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_paths.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_kekkai_runner.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_mermaid.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_policy.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_redaction.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_report.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_backends.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_base.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_container.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_digest_defaults.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_falco.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_gitleaks.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_native.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_semgrep.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_trivy.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_scanner_zap.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_slsa_provenance.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_threatflow_chunking.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_threatflow_model_adapter.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_threatflow_prompts.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_threatflow_redaction.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_threatflow_sanitizer.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_triage_audit.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_triage_ignore.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_triage_models.py +0 -0
- {kekkai_cli-1.1.0 → kekkai_cli-1.1.1}/tests/test_url_policy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kekkai-cli
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Kekkai monorepo (local-first AppSec orchestration + compliance checker)
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -28,7 +28,7 @@ Requires-Dist: httpx>=0.24.0
|
|
|
28
28
|
|
|
29
29
|
Stop juggling security tools. **Kekkai orchestrates your entire AppSec lifecycle** — from AI-powered threat modeling to vulnerability management — in a single CLI.
|
|
30
30
|
|
|
31
|
-

|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
@@ -104,6 +104,8 @@ kekkai upload
|
|
|
104
104
|
|
|
105
105
|
Generate STRIDE-aligned threat models and Mermaid.js Data Flow Diagrams from your codebase.
|
|
106
106
|
|
|
107
|
+

|
|
108
|
+
|
|
107
109
|
```bash
|
|
108
110
|
# Ollama (recommended - easy setup, privacy-preserving)
|
|
109
111
|
ollama pull mistral
|
|
@@ -177,6 +179,10 @@ kekkai triage
|
|
|
177
179
|
|
|
178
180
|
Automate security enforcement in your pipelines.
|
|
179
181
|
|
|
182
|
+
<p align="center">
|
|
183
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-scan.png" alt="Kekkai Scanning" width="650"/>
|
|
184
|
+
</p>
|
|
185
|
+
|
|
180
186
|
```bash
|
|
181
187
|
# Fail on any critical or high findings
|
|
182
188
|
kekkai scan --ci --fail-on high
|
|
@@ -212,6 +218,10 @@ kekkai scan --ci --fail-on medium --max-findings 5
|
|
|
212
218
|
|
|
213
219
|
Spin up a complete vulnerability management platform locally.
|
|
214
220
|
|
|
221
|
+
<p align="center">
|
|
222
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo.png" alt="Kekkai Dojo" width="650"/>
|
|
223
|
+
</p>
|
|
224
|
+
|
|
215
225
|
```bash
|
|
216
226
|
kekkai dojo up --wait # Start DefectDojo (Nginx, Postgres, Redis, Celery)
|
|
217
227
|
kekkai dojo status # Check service health
|
|
@@ -225,6 +235,14 @@ kekkai dojo down # Stop and clean up (removes volumes)
|
|
|
225
235
|
- Pre-configured for Kekkai imports
|
|
226
236
|
- Clean teardown (no orphaned volumes)
|
|
227
237
|
|
|
238
|
+
<p align="center">
|
|
239
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/Active-Engagements-kekkai-dojo.png" alt="Kekkai Dojo" width="850"/>
|
|
240
|
+
</p>
|
|
241
|
+
|
|
242
|
+
<p align="center">
|
|
243
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo-dashboard-findings.png" alt="Kekkai Dojo" width="850"/>
|
|
244
|
+
</p
|
|
245
|
+
|
|
228
246
|
[Full Dojo Documentation →](docs/dojo/dojo.md)
|
|
229
247
|
|
|
230
248
|
---
|
|
@@ -283,24 +301,26 @@ pip install kekkai-cli
|
|
|
283
301
|
|
|
284
302
|
---
|
|
285
303
|
|
|
286
|
-
## Enterprise Features
|
|
304
|
+
## Enterprise Features
|
|
287
305
|
|
|
288
|
-
For
|
|
306
|
+
For organizations that need advanced capabilities, **Kekkai Enterprise** provides:
|
|
289
307
|
|
|
290
308
|
| Feature | Description |
|
|
291
309
|
|---------|-------------|
|
|
292
|
-
| **
|
|
293
|
-
| **
|
|
294
|
-
| **
|
|
295
|
-
| **
|
|
310
|
+
| **Multi-Tenant Portal** | Web dashboard for managing multiple teams/projects ([Learn More](docs/portal/README.md)) |
|
|
311
|
+
| **SAML 2.0 SSO** | Integrate with Okta, Azure AD, Google Workspace |
|
|
312
|
+
| **Role-Based Access Control** | Fine-grained permissions per team/project |
|
|
313
|
+
| **Advanced Operations** | Automated backup/restore, monitoring, zero-downtime upgrades ([Learn More](docs/ops/README.md)) |
|
|
314
|
+
| **Compliance Reporting** | Map findings to OWASP, PCI-DSS, HIPAA, SOC 2 |
|
|
296
315
|
| **Audit Logging** | Cryptographically signed compliance trails |
|
|
297
316
|
|
|
298
|
-
**
|
|
299
|
-
- CLI
|
|
300
|
-
-
|
|
301
|
-
-
|
|
317
|
+
**Architecture:**
|
|
318
|
+
- Open-source CLI remains fully functional standalone
|
|
319
|
+
- Enterprise features available in separate private repository for licensed customers
|
|
320
|
+
- Optional integration: CLI can sync results to enterprise portal
|
|
321
|
+
- Self-hosted or Kademos-managed deployment options
|
|
302
322
|
|
|
303
|
-
[Contact us for
|
|
323
|
+
[Contact us for enterprise access →](mailto:sales@kademos.org)
|
|
304
324
|
|
|
305
325
|
---
|
|
306
326
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
Stop juggling security tools. **Kekkai orchestrates your entire AppSec lifecycle** — from AI-powered threat modeling to vulnerability management — in a single CLI.
|
|
19
19
|
|
|
20
|
-

|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -93,6 +93,8 @@ kekkai upload
|
|
|
93
93
|
|
|
94
94
|
Generate STRIDE-aligned threat models and Mermaid.js Data Flow Diagrams from your codebase.
|
|
95
95
|
|
|
96
|
+

|
|
97
|
+
|
|
96
98
|
```bash
|
|
97
99
|
# Ollama (recommended - easy setup, privacy-preserving)
|
|
98
100
|
ollama pull mistral
|
|
@@ -166,6 +168,10 @@ kekkai triage
|
|
|
166
168
|
|
|
167
169
|
Automate security enforcement in your pipelines.
|
|
168
170
|
|
|
171
|
+
<p align="center">
|
|
172
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-scan.png" alt="Kekkai Scanning" width="650"/>
|
|
173
|
+
</p>
|
|
174
|
+
|
|
169
175
|
```bash
|
|
170
176
|
# Fail on any critical or high findings
|
|
171
177
|
kekkai scan --ci --fail-on high
|
|
@@ -201,6 +207,10 @@ kekkai scan --ci --fail-on medium --max-findings 5
|
|
|
201
207
|
|
|
202
208
|
Spin up a complete vulnerability management platform locally.
|
|
203
209
|
|
|
210
|
+
<p align="center">
|
|
211
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo.png" alt="Kekkai Dojo" width="650"/>
|
|
212
|
+
</p>
|
|
213
|
+
|
|
204
214
|
```bash
|
|
205
215
|
kekkai dojo up --wait # Start DefectDojo (Nginx, Postgres, Redis, Celery)
|
|
206
216
|
kekkai dojo status # Check service health
|
|
@@ -214,6 +224,14 @@ kekkai dojo down # Stop and clean up (removes volumes)
|
|
|
214
224
|
- Pre-configured for Kekkai imports
|
|
215
225
|
- Clean teardown (no orphaned volumes)
|
|
216
226
|
|
|
227
|
+
<p align="center">
|
|
228
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/Active-Engagements-kekkai-dojo.png" alt="Kekkai Dojo" width="850"/>
|
|
229
|
+
</p>
|
|
230
|
+
|
|
231
|
+
<p align="center">
|
|
232
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo-dashboard-findings.png" alt="Kekkai Dojo" width="850"/>
|
|
233
|
+
</p
|
|
234
|
+
|
|
217
235
|
[Full Dojo Documentation →](docs/dojo/dojo.md)
|
|
218
236
|
|
|
219
237
|
---
|
|
@@ -272,24 +290,26 @@ pip install kekkai-cli
|
|
|
272
290
|
|
|
273
291
|
---
|
|
274
292
|
|
|
275
|
-
## Enterprise Features
|
|
293
|
+
## Enterprise Features
|
|
276
294
|
|
|
277
|
-
For
|
|
295
|
+
For organizations that need advanced capabilities, **Kekkai Enterprise** provides:
|
|
278
296
|
|
|
279
297
|
| Feature | Description |
|
|
280
298
|
|---------|-------------|
|
|
281
|
-
| **
|
|
282
|
-
| **
|
|
283
|
-
| **
|
|
284
|
-
| **
|
|
299
|
+
| **Multi-Tenant Portal** | Web dashboard for managing multiple teams/projects ([Learn More](docs/portal/README.md)) |
|
|
300
|
+
| **SAML 2.0 SSO** | Integrate with Okta, Azure AD, Google Workspace |
|
|
301
|
+
| **Role-Based Access Control** | Fine-grained permissions per team/project |
|
|
302
|
+
| **Advanced Operations** | Automated backup/restore, monitoring, zero-downtime upgrades ([Learn More](docs/ops/README.md)) |
|
|
303
|
+
| **Compliance Reporting** | Map findings to OWASP, PCI-DSS, HIPAA, SOC 2 |
|
|
285
304
|
| **Audit Logging** | Cryptographically signed compliance trails |
|
|
286
305
|
|
|
287
|
-
**
|
|
288
|
-
- CLI
|
|
289
|
-
-
|
|
290
|
-
-
|
|
306
|
+
**Architecture:**
|
|
307
|
+
- Open-source CLI remains fully functional standalone
|
|
308
|
+
- Enterprise features available in separate private repository for licensed customers
|
|
309
|
+
- Optional integration: CLI can sync results to enterprise portal
|
|
310
|
+
- Self-hosted or Kademos-managed deployment options
|
|
291
311
|
|
|
292
|
-
[Contact us for
|
|
312
|
+
[Contact us for enterprise access →](mailto:sales@kademos.org)
|
|
293
313
|
|
|
294
314
|
---
|
|
295
315
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kekkai-cli"
|
|
3
|
-
version = "1.1.
|
|
3
|
+
version = "1.1.1"
|
|
4
4
|
description = "Kekkai monorepo (local-first AppSec orchestration + compliance checker)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -13,7 +13,6 @@ dependencies = [
|
|
|
13
13
|
|
|
14
14
|
[project.scripts]
|
|
15
15
|
kekkai = "kekkai.cli:main"
|
|
16
|
-
kekkai-portal = "portal.web:main"
|
|
17
16
|
|
|
18
17
|
[tool.ruff]
|
|
19
18
|
target-version = "py312"
|
|
@@ -56,7 +55,7 @@ source = ["src"]
|
|
|
56
55
|
[tool.coverage.report]
|
|
57
56
|
show_missing = true
|
|
58
57
|
skip_covered = false
|
|
59
|
-
fail_under =
|
|
58
|
+
fail_under = 68
|
|
60
59
|
exclude_lines = [
|
|
61
60
|
"pragma: no cover",
|
|
62
61
|
"if TYPE_CHECKING:",
|
|
@@ -604,6 +604,36 @@ def _command_scan(
|
|
|
604
604
|
)
|
|
605
605
|
manifest.write_manifest(run_dir / "run.json", run_manifest)
|
|
606
606
|
|
|
607
|
+
# Generate unified report (aggregates all scanner findings)
|
|
608
|
+
if scan_results:
|
|
609
|
+
from .report.unified import UnifiedReportError, generate_unified_report
|
|
610
|
+
|
|
611
|
+
# Determine output path for unified report
|
|
612
|
+
if output_path:
|
|
613
|
+
# --output flag provided: use it for unified report
|
|
614
|
+
unified_report_path = Path(output_path).expanduser().resolve()
|
|
615
|
+
# Security: Validate path (ASVS V5.3.3)
|
|
616
|
+
if not is_within_base(base_dir, unified_report_path):
|
|
617
|
+
# Allow explicit paths outside base_dir, but warn
|
|
618
|
+
console.print(
|
|
619
|
+
f"[warning]Writing outside kekkai home: {unified_report_path}[/warning]"
|
|
620
|
+
)
|
|
621
|
+
else:
|
|
622
|
+
# Default: save in run directory
|
|
623
|
+
unified_report_path = run_dir / "kekkai-report.json"
|
|
624
|
+
|
|
625
|
+
try:
|
|
626
|
+
generate_unified_report(
|
|
627
|
+
scan_results=scan_results,
|
|
628
|
+
output_path=unified_report_path,
|
|
629
|
+
run_id=run_id,
|
|
630
|
+
commit_sha=commit_sha,
|
|
631
|
+
)
|
|
632
|
+
console.print(f"[success]Unified report:[/success] {unified_report_path}")
|
|
633
|
+
except UnifiedReportError as e:
|
|
634
|
+
err_msg = sanitize_error(str(e))
|
|
635
|
+
console.print(f"[warning]Failed to generate unified report: {err_msg}[/warning]")
|
|
636
|
+
|
|
607
637
|
# Collect all findings for policy evaluation
|
|
608
638
|
all_findings: list[Finding] = []
|
|
609
639
|
scan_errors: list[str] = []
|
|
@@ -822,6 +852,26 @@ def _resolve_github_repo(override: str | None) -> tuple[str | None, str | None]:
|
|
|
822
852
|
return None, None
|
|
823
853
|
|
|
824
854
|
|
|
855
|
+
def _normalize_scanner_name(stem: str) -> str:
|
|
856
|
+
"""Normalize filename stem to scanner name.
|
|
857
|
+
|
|
858
|
+
Strips the "-results" suffix from scanner output filenames.
|
|
859
|
+
|
|
860
|
+
Examples:
|
|
861
|
+
gitleaks-results -> gitleaks
|
|
862
|
+
trivy-results -> trivy
|
|
863
|
+
semgrep-results -> semgrep
|
|
864
|
+
custom-scanner -> custom-scanner
|
|
865
|
+
|
|
866
|
+
Args:
|
|
867
|
+
stem: File stem (name without extension).
|
|
868
|
+
|
|
869
|
+
Returns:
|
|
870
|
+
Normalized scanner name.
|
|
871
|
+
"""
|
|
872
|
+
return stem.removesuffix("-results")
|
|
873
|
+
|
|
874
|
+
|
|
825
875
|
def _create_scanner(
|
|
826
876
|
name: str,
|
|
827
877
|
zap_target_url: str | None = None,
|
|
@@ -1106,22 +1156,57 @@ def _threatflow_banner() -> str:
|
|
|
1106
1156
|
def _command_triage(parsed: argparse.Namespace) -> int:
|
|
1107
1157
|
"""Run interactive triage TUI."""
|
|
1108
1158
|
from .triage import run_triage
|
|
1159
|
+
from .triage.loader import load_findings_from_path
|
|
1109
1160
|
|
|
1110
1161
|
input_path_str = cast(str | None, getattr(parsed, "input", None))
|
|
1111
1162
|
output_path_str = cast(str | None, getattr(parsed, "output", None))
|
|
1112
1163
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1164
|
+
# Default to latest run if no input specified
|
|
1165
|
+
if not input_path_str:
|
|
1166
|
+
runs_dir = app_base_dir() / "runs"
|
|
1167
|
+
if runs_dir.exists():
|
|
1168
|
+
run_dirs = sorted(
|
|
1169
|
+
[d for d in runs_dir.iterdir() if d.is_dir()],
|
|
1170
|
+
key=lambda d: d.stat().st_mtime,
|
|
1171
|
+
)
|
|
1172
|
+
if run_dirs:
|
|
1173
|
+
input_path = run_dirs[-1]
|
|
1174
|
+
console.print(f"[info]Using latest run: {input_path.name}[/info]\n")
|
|
1175
|
+
else:
|
|
1176
|
+
console.print("[danger]No scan runs found. Run 'kekkai scan' first.[/danger]")
|
|
1177
|
+
return 1
|
|
1178
|
+
else:
|
|
1179
|
+
console.print("[danger]No scan runs found. Run 'kekkai scan' first.[/danger]")
|
|
1180
|
+
return 1
|
|
1181
|
+
else:
|
|
1182
|
+
input_path = Path(input_path_str).expanduser().resolve()
|
|
1115
1183
|
|
|
1116
|
-
if
|
|
1117
|
-
console.print(f"[danger]Error:[/danger] Input
|
|
1184
|
+
if not input_path.exists():
|
|
1185
|
+
console.print(f"[danger]Error:[/danger] Input not found: {input_path}")
|
|
1118
1186
|
return 1
|
|
1119
1187
|
|
|
1188
|
+
output_path = Path(output_path_str).expanduser().resolve() if output_path_str else None
|
|
1189
|
+
|
|
1120
1190
|
console.print("[bold cyan]Kekkai Triage[/bold cyan] - Interactive Finding Review")
|
|
1121
1191
|
console.print("Use j/k to navigate, f=false positive, c=confirmed, d=deferred")
|
|
1122
1192
|
console.print("Press Ctrl+S to save, q to quit\n")
|
|
1123
1193
|
|
|
1124
|
-
|
|
1194
|
+
# Use new loader that supports raw scanner outputs
|
|
1195
|
+
findings, errors = load_findings_from_path(input_path)
|
|
1196
|
+
|
|
1197
|
+
if errors:
|
|
1198
|
+
console.print("[warning]Warnings:[/warning]")
|
|
1199
|
+
for err in errors[:5]: # Limit to first 5
|
|
1200
|
+
console.print(f" - {err}")
|
|
1201
|
+
console.print()
|
|
1202
|
+
|
|
1203
|
+
if not findings:
|
|
1204
|
+
console.print("[warning]No findings to triage.[/warning]")
|
|
1205
|
+
return 0
|
|
1206
|
+
|
|
1207
|
+
console.print(f"[info]Loaded {len(findings)} finding(s)[/info]\n")
|
|
1208
|
+
|
|
1209
|
+
return run_triage(findings=findings, output_path=output_path)
|
|
1125
1210
|
|
|
1126
1211
|
|
|
1127
1212
|
def _command_fix(parsed: argparse.Namespace) -> int:
|
|
@@ -1414,9 +1499,13 @@ def _command_upload(parsed: argparse.Namespace) -> int:
|
|
|
1414
1499
|
console.print(f"Product: {product_name}")
|
|
1415
1500
|
console.print(f"Engagement: {engagement_name}")
|
|
1416
1501
|
|
|
1417
|
-
# Find and load scan results
|
|
1418
|
-
scan_files =
|
|
1419
|
-
|
|
1502
|
+
# Find and load scan results - prefer *-results.json first
|
|
1503
|
+
scan_files = sorted(run_dir.glob("*-results.json"))
|
|
1504
|
+
if not scan_files:
|
|
1505
|
+
# Fallback to all JSON (excluding metadata files)
|
|
1506
|
+
scan_files = sorted(
|
|
1507
|
+
[f for f in run_dir.glob("*.json") if f.name not in ("run.json", "policy-result.json")]
|
|
1508
|
+
)
|
|
1420
1509
|
|
|
1421
1510
|
if not scan_files:
|
|
1422
1511
|
console.print(f"[danger]Error:[/danger] No scan results found in {run_dir}")
|
|
@@ -1429,35 +1518,39 @@ def _command_upload(parsed: argparse.Namespace) -> int:
|
|
|
1429
1518
|
scanners_map: dict[str, Scanner] = {}
|
|
1430
1519
|
|
|
1431
1520
|
for scan_file in scan_files:
|
|
1432
|
-
|
|
1521
|
+
# Normalize scanner name: "gitleaks-results" -> "gitleaks"
|
|
1522
|
+
scanner_name = _normalize_scanner_name(scan_file.stem)
|
|
1433
1523
|
console.print(f" Loading {scanner_name}...")
|
|
1434
1524
|
|
|
1525
|
+
# Load raw JSON
|
|
1435
1526
|
try:
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
except _json.JSONDecodeError as e:
|
|
1527
|
+
raw_text = scan_file.read_text(encoding="utf-8")
|
|
1528
|
+
_json.loads(raw_text) # Validate JSON syntax
|
|
1529
|
+
except (OSError, _json.JSONDecodeError) as e:
|
|
1439
1530
|
console.print(f" [warning]Skipped (invalid JSON): {e}[/warning]")
|
|
1440
1531
|
continue
|
|
1441
1532
|
|
|
1442
|
-
#
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1533
|
+
# Create scanner and use canonical parser
|
|
1534
|
+
scanner = _create_scanner(scanner_name)
|
|
1535
|
+
if not scanner:
|
|
1536
|
+
console.print(" [warning]Skipped (unknown scanner)[/warning]")
|
|
1537
|
+
continue
|
|
1538
|
+
|
|
1539
|
+
# Use canonical scanner parser (reuses validated logic)
|
|
1540
|
+
findings = scanner.parse(raw_text)
|
|
1541
|
+
|
|
1542
|
+
scan_results.append(
|
|
1543
|
+
ScanResult(
|
|
1544
|
+
scanner=scanner.name, # Use canonical scanner name
|
|
1545
|
+
success=True,
|
|
1546
|
+
findings=findings,
|
|
1547
|
+
raw_output_path=scan_file,
|
|
1548
|
+
duration_ms=0,
|
|
1454
1549
|
)
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
if scanner:
|
|
1458
|
-
scanners_map[scanner_name] = scanner
|
|
1550
|
+
)
|
|
1551
|
+
scanners_map[scanner.name] = scanner
|
|
1459
1552
|
|
|
1460
|
-
|
|
1553
|
+
console.print(f" {len(findings)} finding(s)")
|
|
1461
1554
|
|
|
1462
1555
|
if not scan_results:
|
|
1463
1556
|
console.print("[danger]Error:[/danger] No valid scan results to upload")
|
|
@@ -1493,11 +1586,9 @@ def _command_upload(parsed: argparse.Namespace) -> int:
|
|
|
1493
1586
|
)
|
|
1494
1587
|
|
|
1495
1588
|
success_count = 0
|
|
1496
|
-
scanner_names_list = list(scanners_map.keys())
|
|
1497
1589
|
for idx, ir in enumerate(import_results):
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
)
|
|
1590
|
+
# Label based on actual scan_results order (not scanners_map keys)
|
|
1591
|
+
scanner_label = scan_results[idx].scanner if idx < len(scan_results) else f"scanner-{idx}"
|
|
1501
1592
|
if ir.success:
|
|
1502
1593
|
success_count += 1
|
|
1503
1594
|
console.print(
|
|
@@ -61,7 +61,15 @@ class DojoClient:
|
|
|
61
61
|
|
|
62
62
|
try:
|
|
63
63
|
with urlopen(req, timeout=self._timeout) as resp: # noqa: S310 # nosec B310
|
|
64
|
-
|
|
64
|
+
raw_bytes = resp.read() # Call once and store result
|
|
65
|
+
if not raw_bytes: # Check bytes, not method
|
|
66
|
+
return {}
|
|
67
|
+
try:
|
|
68
|
+
result: dict[str, Any] = json.loads(raw_bytes.decode())
|
|
69
|
+
return result
|
|
70
|
+
except json.JSONDecodeError:
|
|
71
|
+
# Empty or invalid JSON response - return empty dict
|
|
72
|
+
return {}
|
|
65
73
|
except HTTPError as exc:
|
|
66
74
|
error_body = exc.read().decode() if exc.fp else str(exc)
|
|
67
75
|
raise RuntimeError(f"Dojo API error {exc.code}: {error_body}") from exc
|