ecdat 0.2.0__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.
Files changed (99) hide show
  1. ecdat-0.2.0/CHANGELOG.md +60 -0
  2. ecdat-0.2.0/LICENSE +21 -0
  3. ecdat-0.2.0/MANIFEST.in +29 -0
  4. ecdat-0.2.0/PKG-INFO +142 -0
  5. ecdat-0.2.0/PYPI_README.md +104 -0
  6. ecdat-0.2.0/README.md +200 -0
  7. ecdat-0.2.0/ecdat/__init__.py +10 -0
  8. ecdat-0.2.0/ecdat/__main__.py +5 -0
  9. ecdat-0.2.0/ecdat/cli/__init__.py +203 -0
  10. ecdat-0.2.0/ecdat/cli/commands/__init__.py +0 -0
  11. ecdat-0.2.0/ecdat/cli/commands/about.py +130 -0
  12. ecdat-0.2.0/ecdat/cli/commands/demo.py +116 -0
  13. ecdat-0.2.0/ecdat/cli/commands/doctor.py +296 -0
  14. ecdat-0.2.0/ecdat/cli/commands/help_cmd.py +205 -0
  15. ecdat-0.2.0/ecdat/cli/commands/scan.py +228 -0
  16. ecdat-0.2.0/ecdat/cli/commands/version_cmd.py +48 -0
  17. ecdat-0.2.0/ecdat/cli/parser.py +87 -0
  18. ecdat-0.2.0/ecdat/demo_project/auth/login.py +75 -0
  19. ecdat-0.2.0/ecdat/demo_project/certs/cert_verify.go +81 -0
  20. ecdat-0.2.0/ecdat/demo_project/keyexchange/channel.go +48 -0
  21. ecdat-0.2.0/ecdat/demo_project/legacy/LegacyCrypto.java +78 -0
  22. ecdat-0.2.0/ecdat/demo_project/payments/payment.py +64 -0
  23. ecdat-0.2.0/ecdat/demo_project/quantum/pqc_utils.py +67 -0
  24. ecdat-0.2.0/ecdat/demo_project/quantum/slh_signer.py +40 -0
  25. ecdat-0.2.0/ecdat/demo_project/tokens/signing.js +54 -0
  26. ecdat-0.2.0/ecdat/py.typed +0 -0
  27. ecdat-0.2.0/ecdat/services/__init__.py +1 -0
  28. ecdat-0.2.0/ecdat/services/crashlog.py +109 -0
  29. ecdat-0.2.0/ecdat/services/demo.py +85 -0
  30. ecdat-0.2.0/ecdat/services/paths.py +52 -0
  31. ecdat-0.2.0/ecdat/services/scanner.py +248 -0
  32. ecdat-0.2.0/ecdat/services/viewmodel.py +326 -0
  33. ecdat-0.2.0/ecdat/tests/__init__.py +0 -0
  34. ecdat-0.2.0/ecdat/tests/conftest.py +17 -0
  35. ecdat-0.2.0/ecdat/tests/test_app_art.py +314 -0
  36. ecdat-0.2.0/ecdat/tests/test_app_cli_meta.py +126 -0
  37. ecdat-0.2.0/ecdat/tests/test_app_cli_scan.py +257 -0
  38. ecdat-0.2.0/ecdat/tests/test_app_crashlog.py +127 -0
  39. ecdat-0.2.0/ecdat/tests/test_app_demo.py +106 -0
  40. ecdat-0.2.0/ecdat/tests/test_app_e2e_cli.py +311 -0
  41. ecdat-0.2.0/ecdat/tests/test_app_packaging.py +593 -0
  42. ecdat-0.2.0/ecdat/tests/test_app_render.py +483 -0
  43. ecdat-0.2.0/ecdat/tests/test_app_scanner.py +238 -0
  44. ecdat-0.2.0/ecdat/tests/test_app_skeleton.py +44 -0
  45. ecdat-0.2.0/ecdat/tests/test_app_ui.py +298 -0
  46. ecdat-0.2.0/ecdat/tests/test_app_viewmodel.py +169 -0
  47. ecdat-0.2.0/ecdat/ui/__init__.py +1 -0
  48. ecdat-0.2.0/ecdat/ui/art3d.py +136 -0
  49. ecdat-0.2.0/ecdat/ui/art_static.py +65 -0
  50. ecdat-0.2.0/ecdat/ui/art_text.py +81 -0
  51. ecdat-0.2.0/ecdat/ui/banner.py +148 -0
  52. ecdat-0.2.0/ecdat/ui/console.py +119 -0
  53. ecdat-0.2.0/ecdat/ui/motion.py +64 -0
  54. ecdat-0.2.0/ecdat/ui/render.py +486 -0
  55. ecdat-0.2.0/ecdat/ui/theme.py +173 -0
  56. ecdat-0.2.0/ecdat.egg-info/PKG-INFO +142 -0
  57. ecdat-0.2.0/ecdat.egg-info/SOURCES.txt +97 -0
  58. ecdat-0.2.0/ecdat.egg-info/dependency_links.txt +1 -0
  59. ecdat-0.2.0/ecdat.egg-info/entry_points.txt +2 -0
  60. ecdat-0.2.0/ecdat.egg-info/requires.txt +9 -0
  61. ecdat-0.2.0/ecdat.egg-info/top_level.txt +2 -0
  62. ecdat-0.2.0/ecdat_core/__init__.py +6 -0
  63. ecdat-0.2.0/ecdat_core/cbom_export.py +287 -0
  64. ecdat-0.2.0/ecdat_core/cli.py +202 -0
  65. ecdat-0.2.0/ecdat_core/detector.py +273 -0
  66. ecdat-0.2.0/ecdat_core/ingestion.py +581 -0
  67. ecdat-0.2.0/ecdat_core/models.py +145 -0
  68. ecdat-0.2.0/ecdat_core/recommender.py +74 -0
  69. ecdat-0.2.0/ecdat_core/risk_engine.py +264 -0
  70. ecdat-0.2.0/ecdat_core/signature_loader.py +204 -0
  71. ecdat-0.2.0/ecdat_core/signatures.json +692 -0
  72. ecdat-0.2.0/ecdat_core/tests/fixtures/cyclonedx/bom-1.6.schema.json +5699 -0
  73. ecdat-0.2.0/ecdat_core/tests/fixtures/cyclonedx/jsf-0.82.schema.json +240 -0
  74. ecdat-0.2.0/ecdat_core/tests/fixtures/cyclonedx/spdx.schema.json +1632 -0
  75. ecdat-0.2.0/ecdat_core/tests/fixtures/demo_repo/auth/login.py +37 -0
  76. ecdat-0.2.0/ecdat_core/tests/fixtures/demo_repo/legacy/cipher.java +28 -0
  77. ecdat-0.2.0/ecdat_core/tests/fixtures/demo_repo/modern/crypto.py +31 -0
  78. ecdat-0.2.0/ecdat_core/tests/fixtures/demo_repo/requirements.txt +5 -0
  79. ecdat-0.2.0/ecdat_core/tests/fixtures/demo_repo/utils/hasher.py +15 -0
  80. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/auth/login.py +75 -0
  81. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/certs/cert_verify.go +81 -0
  82. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/keyexchange/channel.go +48 -0
  83. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/legacy/LegacyCrypto.java +78 -0
  84. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/payments/payment.py +64 -0
  85. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/quantum/pqc_utils.py +67 -0
  86. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/quantum/slh_signer.py +40 -0
  87. ecdat-0.2.0/ecdat_core/tests/fixtures/showcase_repo/tokens/signing.js +54 -0
  88. ecdat-0.2.0/ecdat_core/tests/test_cbom_export.py +419 -0
  89. ecdat-0.2.0/ecdat_core/tests/test_cbom_schema.py +163 -0
  90. ecdat-0.2.0/ecdat_core/tests/test_detector.py +267 -0
  91. ecdat-0.2.0/ecdat_core/tests/test_end_to_end.py +84 -0
  92. ecdat-0.2.0/ecdat_core/tests/test_ingestion.py +625 -0
  93. ecdat-0.2.0/ecdat_core/tests/test_models.py +239 -0
  94. ecdat-0.2.0/ecdat_core/tests/test_recommender.py +151 -0
  95. ecdat-0.2.0/ecdat_core/tests/test_risk_engine.py +250 -0
  96. ecdat-0.2.0/ecdat_core/tests/test_run_scan_sandbox.py +59 -0
  97. ecdat-0.2.0/ecdat_core/tests/test_signature_loader.py +210 -0
  98. ecdat-0.2.0/pyproject.toml +82 -0
  99. ecdat-0.2.0/setup.cfg +4 -0
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to
7
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
+
9
+ ## [0.2.0] - 2026-09-21
10
+
11
+
12
+ ### Added
13
+
14
+ - **New `ecdat` command-line interface.** A pip-installable, terminal-native
15
+ front end for the scanner, with subcommands:
16
+ - `ecdat scan <path-or-url>` — scan a local directory or an `https://` Git
17
+ repository, with `--format pretty|json|cbom|summary`, `--output DIR`,
18
+ `--fail-on critical|high|medium|low`, `--limit N`, `--no-progress`,
19
+ `--quiet`, and `--git-url`.
20
+ - `ecdat demo` — scan the bundled, deliberately-insecure sample project with
21
+ zero setup (and `--path` to materialise a persistent copy).
22
+ - `ecdat doctor` — environment self-check (Python, platform, install
23
+ location, git, terminal, signatures, `ECDAT_HOME`) with a one-line fix per
24
+ failing check.
25
+ - `ecdat about` — credits, project links, and an animated 3D globe.
26
+ - `ecdat help [command]` — command overview and per-command help.
27
+ - `ecdat version` — version, engine, signature count, Python, and OS.
28
+ - Global flags `--version`, `--no-color`, and `--debug`.
29
+ - **Gradient ASCII banner** shown on interactive runs.
30
+ - **Animated 3D globe** in `ecdat about` (opt-out with `--no-anim`, duration
31
+ controlled by `--spin`).
32
+ - **Padlock verdict emblem** in the pretty scan report.
33
+ - **Bundled demo project** (`ecdat/demo_project/`) shipped inside the wheel, so
34
+ `ecdat demo` works with no repository checkout.
35
+ - **Crash-safe error handling.** Expected errors print a friendly message and a
36
+ documented exit code; unexpected errors are written to a local crash log
37
+ under `ECDAT_HOME/logs` with a pointer for bug reports, instead of a raw
38
+ traceback.
39
+ - **Documented exit codes** for scripting and CI: `0` success, `1` findings at
40
+ or above `--fail-on`, `2` usage/validation error, `3` scan/runtime/unexpected
41
+ error, `130` interrupted (`Ctrl-C`).
42
+ - `CHANGELOG.md` and `PYPI_README.md`, and a `[project.scripts]` console entry
43
+ point (`ecdat = "ecdat.cli:main"`).
44
+
45
+ ### Changed
46
+
47
+ - **Distribution renamed to `ecdat`** (previously `ecdat-cbom`). A single wheel
48
+ now ships both import packages: the new app layer (`ecdat`) and the scanner
49
+ engine (`ecdat_core`). `python -m ecdat` behaves identically to the console
50
+ script; the legacy `python -m ecdat_core.cli` entry point is unchanged.
51
+ - **Engine: `run_scan()` gained a `sandboxed=` parameter.** Callers can opt a
52
+ trusted local scan out of the workspace sandbox (the CLI and TUI do this — the
53
+ user is the trust boundary), while the HTTP API keeps the sandbox enabled.
54
+ - Runtime dependency on `rich` added for the CLI/TUI renderers.
55
+
56
+ ### Security
57
+
58
+ - CLI renderers treat scanned repository content (file paths, snippets,
59
+ algorithm names) as untrusted and render it as plain text, so it cannot
60
+ inject terminal escapes or Rich/HTML/Markdown markup.
ecdat-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Errorists Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # MANIFEST.in — controls the SOURCE DISTRIBUTION (sdist) file list.
2
+ # The WHEEL is governed by [tool.setuptools.packages.find] and
3
+ # [tool.setuptools.package-data] in pyproject.toml.
4
+ #
5
+ # This repo is a monorepo (ecdat_core + backend + frontend), but only
6
+ # `ecdat_core` is published on PyPI. Everything else is pruned so
7
+ # `pip download ecdat-cbom` never pulls in the FastAPI backend or the
8
+ # React frontend. LICENSE is handled by [project] license-files and is
9
+ # not re-listed here.
10
+
11
+ include README.md
12
+ include pyproject.toml
13
+ include PYPI_README.md
14
+ include CHANGELOG.md
15
+
16
+ # Ship tests + fixtures in the sdist only (standard practice; tests are not
17
+ # part of the wheel).
18
+ recursive-include ecdat_core/tests *
19
+ recursive-include ecdat/tests *
20
+
21
+ # Never ship the monorepo's non-published areas.
22
+ prune backend
23
+ prune frontend
24
+
25
+ # Housekeeping.
26
+ global-exclude __pycache__
27
+ global-exclude *.py[cod]
28
+ global-exclude *.so
29
+ global-exclude .DS_Store
ecdat-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.4
2
+ Name: ecdat
3
+ Version: 0.2.0
4
+ Summary: Cryptographic discovery and post-quantum readiness scanner — CLI with a gradient ASCII banner and an animated 3D globe (CBOM, CycloneDX 1.6)
5
+ Author: ECDAT Team
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/profm0r14rty/ecdat
8
+ Project-URL: Repository, https://github.com/profm0r14rty/ecdat
9
+ Project-URL: Issues, https://github.com/profm0r14rty/ecdat/issues
10
+ Project-URL: Changelog, https://github.com/profm0r14rty/ecdat/blob/main/CHANGELOG.md
11
+ Keywords: cbom,cli,cryptography,cyclonedx,post-quantum,pqc,quantum,sbom,security
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Security :: Cryptography
25
+ Classifier: Topic :: Software Development :: Quality Assurance
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: pydantic>=2
30
+ Requires-Dist: rich>=13.7
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest; extra == "dev"
33
+ Requires-Dist: pytest-cov; extra == "dev"
34
+ Requires-Dist: jsonschema; extra == "dev"
35
+ Requires-Dist: build; extra == "dev"
36
+ Requires-Dist: twine; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # ecdat
40
+
41
+ **ECDAT** is a [CycloneDX](https://cyclonedx.org/) **Cryptography Bill of
42
+ Materials (CBOM) scanner for post-quantum readiness**. One command finds the
43
+ cryptographic artefacts in a codebase — RSA, ECC, DH, DSA, MD5, SHA-1, DES,
44
+ 3DES, RC4, AES, and others — scores each one's post-quantum risk with Mosca's
45
+ inequality, recommends NIST post-quantum replacements, and emits a real
46
+ CycloneDX 1.6 CBOM next to a dashboard-friendly risk summary.
47
+
48
+ It is a small, self-contained Python package (runtime dependencies: `pydantic`
49
+ and `rich`) — no FastAPI, Postgres, Redis, or Docker required. It runs fully
50
+ offline: the only network access is `git clone` for an explicit URL scan.
51
+
52
+ Why it is more than a lookalike scanner:
53
+
54
+ - **Real CBOM output.** The report is genuine CycloneDX 1.6, validated against
55
+ the official JSON Schema on every scan in the test suite, so Dependency-Track,
56
+ Syft, Grype, and other CycloneDX tooling parse it unchanged.
57
+ - **"Classically broken" is not "quantum vulnerable".** MD5, SHA-1, DES, 3DES,
58
+ and RC4 are reported as broken *today*; RSA, ECC, DH, and DSA as broken *by
59
+ Shor's algorithm*. An actively exploitable hash is never mislabeled
60
+ "quantum-safe".
61
+ - **Offline and private.** No telemetry, no update checks.
62
+ - **Crash-safe.** Expected errors print a clear message and exit code;
63
+ unexpected errors are written to a local crash log instead of a raw
64
+ traceback.
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pipx install ecdat # recommended: isolated and on PATH
70
+ uv tool install ecdat # recommended if you use uv
71
+ pip install ecdat # into the active Python environment
72
+ ```
73
+
74
+ If plain `pip` reports `externally-managed-environment`, that is
75
+ [PEP 668](https://peps.python.org/pep-0668/) protecting your OS Python — use
76
+ `pipx` or `uv tool` (or a virtualenv) instead of forcing the install. On
77
+ Windows, install with `py -m pip install ecdat`; if `ecdat` is not on `PATH`,
78
+ run the CLI as `py -m ecdat …`.
79
+
80
+ ## 60-second tour
81
+
82
+ ```bash
83
+ ecdat demo # scan the bundled sample project
84
+ ecdat scan . # scan the current directory
85
+ ecdat scan https://github.com/<user>/<repo> # scan a public https:// repo
86
+ ecdat about # credits and an animated 3D globe
87
+ ecdat doctor # check your environment
88
+ ```
89
+
90
+ ## Commands
91
+
92
+ | Command | Description |
93
+ |---------|-------------|
94
+ | `ecdat scan <path-or-url>` | Scan a local directory, or an `https://` Git repository |
95
+ | `ecdat demo` | Scan the bundled, deliberately-insecure sample project (zero setup) |
96
+ | `ecdat doctor` | Environment self-check with a one-line fix per problem |
97
+ | `ecdat about` | Credits, project links, and a spinning 3D globe |
98
+ | `ecdat help [command]` | Command overview, or full help for one command |
99
+ | `ecdat version` | Version, engine, signature count, Python, and OS |
100
+
101
+ Global flags: `--version`, `--no-color`, and `--debug`.
102
+
103
+ ## Formats
104
+
105
+ `ecdat scan --format <pretty|json|cbom|summary>`:
106
+
107
+ | Format | Contents |
108
+ |--------|----------|
109
+ | `pretty` | Colourised terminal report (default) |
110
+ | `json` | The full `ScanResult` |
111
+ | `cbom` | A CycloneDX 1.6 CBOM |
112
+ | `summary` | The risk rollup used by dashboards |
113
+
114
+ Payload formats write **only** the payload to stdout; progress, warnings, and
115
+ errors go to stderr — so `ecdat scan . -f cbom > cbom.json` is safe to pipe.
116
+ `ecdat demo` supports `pretty`, `json`, and `summary`.
117
+
118
+ For CI, `ecdat scan . --fail-on high` exits `1` when a finding is at or above
119
+ that level (`quantum-safe` findings never count) and `0` when clean. The other
120
+ exit codes are `2` (usage/validation error), `3` (scan/runtime/unexpected
121
+ error), and `130` (interrupted with `Ctrl-C`).
122
+
123
+ ## Guarantees
124
+
125
+ - **Offline by default.** Only `git clone` for an explicit `https://` URL scan
126
+ touches the network; local scans never do.
127
+ - **No telemetry and no update checks.**
128
+ - **Injection-safe rendering.** File paths, matched snippets, and algorithm
129
+ names from scanned (untrusted) code are rendered as plain text and cannot
130
+ inject terminal escapes or Rich/HTML/Markdown markup.
131
+ - **Validated Git-URL scanning.** Only `https://` URLs are cloned, and the host
132
+ is resolved and checked against private/reserved address ranges before any
133
+ clone runs.
134
+
135
+ ## Links
136
+
137
+ - Source, issues, and documentation: <https://github.com/profm0r14rty/ecdat>
138
+ - Security policy: <https://github.com/profm0r14rty/ecdat/blob/main/SECURITY.md>
139
+ - Changelog: <https://github.com/profm0r14rty/ecdat/blob/main/CHANGELOG.md>
140
+ - Live demo dashboard: <https://ecdat-web.onrender.com>
141
+ - Live demo API: <https://ecdat-api.onrender.com>
142
+ - License (MIT): <https://github.com/profm0r14rty/ecdat/blob/main/LICENSE>
@@ -0,0 +1,104 @@
1
+ # ecdat
2
+
3
+ **ECDAT** is a [CycloneDX](https://cyclonedx.org/) **Cryptography Bill of
4
+ Materials (CBOM) scanner for post-quantum readiness**. One command finds the
5
+ cryptographic artefacts in a codebase — RSA, ECC, DH, DSA, MD5, SHA-1, DES,
6
+ 3DES, RC4, AES, and others — scores each one's post-quantum risk with Mosca's
7
+ inequality, recommends NIST post-quantum replacements, and emits a real
8
+ CycloneDX 1.6 CBOM next to a dashboard-friendly risk summary.
9
+
10
+ It is a small, self-contained Python package (runtime dependencies: `pydantic`
11
+ and `rich`) — no FastAPI, Postgres, Redis, or Docker required. It runs fully
12
+ offline: the only network access is `git clone` for an explicit URL scan.
13
+
14
+ Why it is more than a lookalike scanner:
15
+
16
+ - **Real CBOM output.** The report is genuine CycloneDX 1.6, validated against
17
+ the official JSON Schema on every scan in the test suite, so Dependency-Track,
18
+ Syft, Grype, and other CycloneDX tooling parse it unchanged.
19
+ - **"Classically broken" is not "quantum vulnerable".** MD5, SHA-1, DES, 3DES,
20
+ and RC4 are reported as broken *today*; RSA, ECC, DH, and DSA as broken *by
21
+ Shor's algorithm*. An actively exploitable hash is never mislabeled
22
+ "quantum-safe".
23
+ - **Offline and private.** No telemetry, no update checks.
24
+ - **Crash-safe.** Expected errors print a clear message and exit code;
25
+ unexpected errors are written to a local crash log instead of a raw
26
+ traceback.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pipx install ecdat # recommended: isolated and on PATH
32
+ uv tool install ecdat # recommended if you use uv
33
+ pip install ecdat # into the active Python environment
34
+ ```
35
+
36
+ If plain `pip` reports `externally-managed-environment`, that is
37
+ [PEP 668](https://peps.python.org/pep-0668/) protecting your OS Python — use
38
+ `pipx` or `uv tool` (or a virtualenv) instead of forcing the install. On
39
+ Windows, install with `py -m pip install ecdat`; if `ecdat` is not on `PATH`,
40
+ run the CLI as `py -m ecdat …`.
41
+
42
+ ## 60-second tour
43
+
44
+ ```bash
45
+ ecdat demo # scan the bundled sample project
46
+ ecdat scan . # scan the current directory
47
+ ecdat scan https://github.com/<user>/<repo> # scan a public https:// repo
48
+ ecdat about # credits and an animated 3D globe
49
+ ecdat doctor # check your environment
50
+ ```
51
+
52
+ ## Commands
53
+
54
+ | Command | Description |
55
+ |---------|-------------|
56
+ | `ecdat scan <path-or-url>` | Scan a local directory, or an `https://` Git repository |
57
+ | `ecdat demo` | Scan the bundled, deliberately-insecure sample project (zero setup) |
58
+ | `ecdat doctor` | Environment self-check with a one-line fix per problem |
59
+ | `ecdat about` | Credits, project links, and a spinning 3D globe |
60
+ | `ecdat help [command]` | Command overview, or full help for one command |
61
+ | `ecdat version` | Version, engine, signature count, Python, and OS |
62
+
63
+ Global flags: `--version`, `--no-color`, and `--debug`.
64
+
65
+ ## Formats
66
+
67
+ `ecdat scan --format <pretty|json|cbom|summary>`:
68
+
69
+ | Format | Contents |
70
+ |--------|----------|
71
+ | `pretty` | Colourised terminal report (default) |
72
+ | `json` | The full `ScanResult` |
73
+ | `cbom` | A CycloneDX 1.6 CBOM |
74
+ | `summary` | The risk rollup used by dashboards |
75
+
76
+ Payload formats write **only** the payload to stdout; progress, warnings, and
77
+ errors go to stderr — so `ecdat scan . -f cbom > cbom.json` is safe to pipe.
78
+ `ecdat demo` supports `pretty`, `json`, and `summary`.
79
+
80
+ For CI, `ecdat scan . --fail-on high` exits `1` when a finding is at or above
81
+ that level (`quantum-safe` findings never count) and `0` when clean. The other
82
+ exit codes are `2` (usage/validation error), `3` (scan/runtime/unexpected
83
+ error), and `130` (interrupted with `Ctrl-C`).
84
+
85
+ ## Guarantees
86
+
87
+ - **Offline by default.** Only `git clone` for an explicit `https://` URL scan
88
+ touches the network; local scans never do.
89
+ - **No telemetry and no update checks.**
90
+ - **Injection-safe rendering.** File paths, matched snippets, and algorithm
91
+ names from scanned (untrusted) code are rendered as plain text and cannot
92
+ inject terminal escapes or Rich/HTML/Markdown markup.
93
+ - **Validated Git-URL scanning.** Only `https://` URLs are cloned, and the host
94
+ is resolved and checked against private/reserved address ranges before any
95
+ clone runs.
96
+
97
+ ## Links
98
+
99
+ - Source, issues, and documentation: <https://github.com/profm0r14rty/ecdat>
100
+ - Security policy: <https://github.com/profm0r14rty/ecdat/blob/main/SECURITY.md>
101
+ - Changelog: <https://github.com/profm0r14rty/ecdat/blob/main/CHANGELOG.md>
102
+ - Live demo dashboard: <https://ecdat-web.onrender.com>
103
+ - Live demo API: <https://ecdat-api.onrender.com>
104
+ - License (MIT): <https://github.com/profm0r14rty/ecdat/blob/main/LICENSE>
ecdat-0.2.0/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # ECDAT - Enterprise Cryptographic Discovery & Analysis Tool
2
+
3
+ ECDAT is a Cryptography Bill of Materials (CBOM) scanner for post-quantum readiness assessment. It discovers cryptographic artefacts in source code, assesses their quantum-computing risk using Mosca's algorithm, and recommends NIST post-quantum replacements, outputting a CycloneDX 1.6 CBOM report.
4
+
5
+ ## Install the CLI
6
+
7
+ The `ecdat` command is a standalone, pip-installable scanner — no Docker,
8
+ Postgres, Redis, or API required. It runs fully offline; see
9
+ [Privacy and trust](#privacy-and-trust).
10
+
11
+ ```bash
12
+ pipx install ecdat # recommended: isolated and on PATH
13
+ uv tool install ecdat # recommended if you use uv
14
+ pip install ecdat # into the active Python environment
15
+ ```
16
+
17
+ If `pip install` stops with `error: externally-managed-environment`, that is
18
+ [PEP 668](https://peps.python.org/pep-0668/) protecting your OS Python — use
19
+ `pipx` or `uv tool` (or a virtualenv) rather than forcing the install. On
20
+ Windows, install with `py -m pip install ecdat`; if `ecdat` is not on `PATH`,
21
+ run the CLI as `py -m ecdat …`.
22
+
23
+ Upgrade or remove it later:
24
+
25
+ ```bash
26
+ pipx upgrade ecdat # or: uv tool upgrade ecdat
27
+ pip install --upgrade ecdat
28
+ pipx uninstall ecdat # or: uv tool uninstall ecdat
29
+ ```
30
+
31
+ ### 60-second tour
32
+
33
+ ```bash
34
+ ecdat demo # scan the bundled sample project
35
+ ecdat about # credits and an animated 3D globe
36
+ ecdat scan . # scan the current directory
37
+ ecdat scan https://github.com/<user>/<repo> # scan a public https:// repo
38
+ ecdat help # list every command
39
+ ecdat doctor # check your environment
40
+ ```
41
+
42
+ <!-- screenshots: docs/img/*.png -->
43
+
44
+ ### Commands
45
+
46
+ | Command | What it does |
47
+ |---------|--------------|
48
+ | `ecdat scan <path-or-url>` | Scan a local directory, or an `https://` Git repository |
49
+ | `ecdat demo` | Scan the bundled, deliberately-insecure sample project (zero setup) |
50
+ | `ecdat doctor` | Environment self-check (Python, git, signatures, `ECDAT_HOME`) |
51
+ | `ecdat about` | Credits, project links, and a spinning 3D globe |
52
+ | `ecdat help [command]` | Command overview, or full help for one command |
53
+ | `ecdat version` | Version, engine, signature count, Python, and OS |
54
+
55
+ Global flags: `--version`, `--no-color`, `--debug`.
56
+
57
+ ### Output formats
58
+
59
+ `ecdat scan --format <pretty|json|cbom|summary>`:
60
+
61
+ - `pretty` (default) — the colourised terminal report.
62
+ - `json` — the full `ScanResult`.
63
+ - `cbom` — a CycloneDX 1.6 CBOM.
64
+ - `summary` — the risk rollup used by dashboards.
65
+
66
+ Payload formats write **only** the payload to stdout; progress, warnings, and
67
+ errors go to stderr. That keeps `ecdat scan . -f cbom > cbom.json` safe to
68
+ pipe. `ecdat demo` supports `pretty`, `json`, and `summary`.
69
+
70
+ ### Use in CI
71
+
72
+ ```bash
73
+ ecdat scan . --fail-on high
74
+ ```
75
+
76
+ `--fail-on <critical|high|medium|low>` returns exit code `1` when any finding
77
+ is at or above that level (`quantum-safe` findings never count). Exit codes:
78
+ `0` success · `1` findings at or above `--fail-on` · `2` usage/validation
79
+ error · `3` scan/runtime/unexpected error · `130` interrupted (`Ctrl-C`).
80
+
81
+ ### Privacy and trust
82
+
83
+ - **Runs fully offline.** The only network access is `git clone` for an
84
+ explicit `https://` URL scan; local scans never touch the network.
85
+ - **No telemetry, no update checks.**
86
+ - **Hostile repo content cannot inject escapes or markup.** File paths,
87
+ snippets, and algorithm names from scanned repositories are attacker-
88
+ controlled; the CLI renders them as plain text, never as Rich/HTML/Markdown
89
+ markup. Covered by `ecdat/tests/test_app_render.py`.
90
+
91
+ ## Running locally
92
+
93
+ ### Prerequisites
94
+
95
+ - Docker with Docker Compose (Compose v2+).
96
+
97
+ ### Infrastructure + API + Dashboard
98
+
99
+ From the repo root, build and start the whole stack:
100
+
101
+ ```bash
102
+ docker compose up --build
103
+ ```
104
+
105
+ This brings up four services:
106
+
107
+ | Service | Image / source | Purpose |
108
+ |----------|----------------------|----------------------------------------------------|
109
+ | postgres | `postgres:16-alpine` | Persistent scan database (named volume `postgres_data`) |
110
+ | redis | `redis:7-alpine` | Scan job status keys (`scan:{id}:status`) |
111
+ | api | `backend/Dockerfile` | FastAPI app on `http://localhost:8000`, uvicorn with hot reload |
112
+ | web | `frontend/Dockerfile`| React dashboard at `http://localhost:5173`, nginx serves the build and reverse-proxies `/api` + `/health` to `api` |
113
+
114
+ Database credentials are read from `.env` (copy `.env.example` to `.env` and
115
+ adjust as needed). The compose file falls back to the same dev defaults, so a
116
+ plain `docker compose up --build` works with no `.env` file at all.
117
+
118
+ Smoke test — the API should answer immediately once the containers are up
119
+ (either directly, or through the web container's proxy):
120
+
121
+ ```bash
122
+ curl http://localhost:8000/health
123
+ # {"status":"ok"}
124
+ curl http://localhost:5173/health
125
+ # {"status":"ok"}
126
+ ```
127
+
128
+ The dashboard lives at `http://localhost:5173`. The `web` container keeps the
129
+ frontend bundle's default same-origin `VITE_API_BASE_URL`: nginx serves the
130
+ compiled static files and forwards `/api` + `/health` to the `api` service, so
131
+ no runtime env substitution or CORS config is needed in the containerized flow.
132
+
133
+ Details:
134
+
135
+ - On container start, the API entrypoint (`backend/docker-entrypoint.sh`)
136
+ runs `alembic upgrade head` against Postgres before launching uvicorn.
137
+ - `./backend` is bind-mounted into the container and uvicorn runs with
138
+ `--reload`, so backend code edits take effect without rebuilding.
139
+ - The `api` service waits for both `postgres` and `redis` to report healthy
140
+ (`depends_on.condition: service_healthy`); `web` waits for `api` to start.
141
+
142
+ Tear down with `docker compose down` (add `-v` to also delete the Postgres
143
+ named volume).
144
+
145
+ ## Live Deployment
146
+
147
+ The project is deployed on Render's free tier.
148
+
149
+ - **API**: [https://ecdat-api.onrender.com](https://ecdat-api.onrender.com)
150
+ - **Dashboard**: [https://ecdat-web.onrender.com](https://ecdat-web.onrender.com)
151
+
152
+ **Note on cold starts**: The API sleeps after 15 minutes of inactivity. The first request after sleep will take about a minute to respond while the service warms up. Please hit the `/health` endpoint once before starting the demo to ensure the app is responsive.
153
+
154
+ ## Securing a non-demo deployment (optional API-key auth)
155
+
156
+ By default ECDAT's API is fully open — anyone with the URL can submit scans and
157
+ read everyone's scan history. That's intentional for the public hackathon demo.
158
+ For anything resembling a real deployment, the API ships with a minimal
159
+ single-tier gate: when enabled, every `/api/scans*` endpoint (writes *and*
160
+ reads) requires an `Authorization: Bearer <key>` header. Full multi-tenant
161
+ auth (users, orgs, roles) is deliberately not part of this mechanism.
162
+
163
+ 1. **Generate one or more keys** out-of-band — never reuse committed values:
164
+
165
+ ```bash
166
+ python -c "import secrets; print(secrets.token_urlsafe(32))"
167
+ ```
168
+
169
+ 2. **Enable the gate** by setting two environment variables on the API:
170
+
171
+ - `REQUIRE_API_KEY=true`
172
+ - `API_KEYS=<comma-separated keys>` (whitespace around keys is fine)
173
+
174
+ Where to set them depends on the deployment:
175
+
176
+ - **Docker Compose** — add both to your `.env` (copied from
177
+ `.env.example`); the `api` service passes them through.
178
+ - **Render** — set both in the Web Service's **Environment** panel
179
+ (note: Render's env vars are separate from a local `.env` file) and
180
+ redeploy. Render's env changes apply on the next deploy — the gate reads
181
+ them per request, so no restart is needed once the new env is live.
182
+
183
+ The gate is **off by default**; with `REQUIRE_API_KEY` unset or `false`,
184
+ behavior is unchanged. If you enable it without setting `API_KEYS`, the API
185
+ fails closed (HTTP 500) rather than silently opening up.
186
+
187
+ 3. **Clients** must send the key on every (non-`/health`) request:
188
+
189
+ ```bash
190
+ curl -H "Authorization: Bearer <key>" https://your-api/api/scans
191
+ ```
192
+
193
+ `GET /health` stays public so uptime monitors and warm-keeping pings keep
194
+ working.
195
+
196
+ **Dashboard caveat**: the bundled dashboard is a public-demo artifact — its API
197
+ client sends no auth header, so once you flip the gate on, the dashboard's
198
+ `/api/scans` calls will be rejected (401). A non-demo deployment either uses
199
+ API-keyed clients / CI pipelines, or terminates the key at a same-origin proxy.
200
+ Key entry in the UI is intentionally out of scope for this gate.
@@ -0,0 +1,10 @@
1
+ """ECDAT — Enterprise Cryptographic Discovery & Analysis Tool."""
2
+
3
+ import importlib.metadata
4
+
5
+ DIST_NAME = "ecdat"
6
+
7
+ try:
8
+ __version__ = importlib.metadata.version(DIST_NAME)
9
+ except importlib.metadata.PackageNotFoundError:
10
+ __version__ = "0+unknown"
@@ -0,0 +1,5 @@
1
+ """Allow `python -m ecdat` to run the CLI."""
2
+
3
+ from ecdat.cli import main
4
+
5
+ raise SystemExit(main())