pyblastradius 0.3.0__tar.gz → 0.4.2__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 (96) hide show
  1. pyblastradius-0.4.2/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
  2. pyblastradius-0.4.2/.github/ISSUE_TEMPLATE/feature_request.yml +38 -0
  3. pyblastradius-0.4.2/.github/dependabot.yml +22 -0
  4. pyblastradius-0.4.2/.github/pull_request_template.md +28 -0
  5. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/ci.yml +67 -1
  6. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/example-blast-radius.yml +9 -1
  7. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/publish.yml +4 -4
  8. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.gitignore +6 -1
  9. pyblastradius-0.4.2/.graphifyignore +31 -0
  10. pyblastradius-0.4.2/CHANGELOG.md +249 -0
  11. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/CONTRIBUTING.md +53 -23
  12. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/Cargo.lock +501 -354
  13. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/Cargo.toml +6 -6
  14. pyblastradius-0.4.2/LICENSE +202 -0
  15. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/PKG-INFO +156 -67
  16. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/README.md +152 -63
  17. pyblastradius-0.4.2/ROADMAP_HONEST.md +231 -0
  18. pyblastradius-0.4.2/SECURITY.md +50 -0
  19. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/action.yml +41 -25
  20. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/benches/large_graph.rs +14 -6
  21. pyblastradius-0.4.2/docs/archive/README.md +36 -0
  22. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/cli.rs +7 -3
  23. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/pyproject.toml +27 -4
  24. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/__init__.py +52 -37
  25. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/analysis.py +4 -4
  26. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/cli.py +38 -26
  27. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/config.py +24 -19
  28. pyblastradius-0.4.2/python/pyblastradius/discovery.py +41 -0
  29. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/integrations.py +11 -8
  30. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/server.py +63 -26
  31. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/blast_radius.rs +1 -1
  32. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/mod.rs +2 -2
  33. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/simulator.rs +2 -2
  34. pyblastradius-0.4.2/src/discovery/airflow.rs +885 -0
  35. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/kubernetes.rs +17 -3
  36. pyblastradius-0.4.2/src/discovery/mod.rs +417 -0
  37. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/otlp.rs +14 -0
  38. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/terraform.rs +32 -7
  39. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/error.rs +1 -1
  40. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/graph.rs +1 -1
  41. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/serialization.rs +3 -3
  42. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/traversal.rs +2 -2
  43. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/statguardian_integration.rs +1 -1
  44. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/python.rs +223 -9
  45. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/utils/mod.rs +2 -2
  46. pyblastradius-0.4.2/tests/test_discovery_bindings.py +246 -0
  47. pyblastradius-0.4.2/tools/graphify/README.md +63 -0
  48. pyblastradius-0.4.2/tools/graphify/graphify_adapter.py +242 -0
  49. pyblastradius-0.3.0/CHANGELOG.md +0 -178
  50. pyblastradius-0.3.0/LICENSE +0 -22
  51. pyblastradius-0.3.0/python/pyblastradius/discovery.py +0 -118
  52. pyblastradius-0.3.0/src/discovery/airflow.rs +0 -202
  53. pyblastradius-0.3.0/src/discovery/mod.rs +0 -10
  54. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/CODE_OF_CONDUCT.md +0 -0
  55. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/ARCHITECTURE.md +0 -0
  56. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/BUILD_PLAN.md +0 -0
  57. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/GAP_ANALYSIS.md +0 -0
  58. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/GETTING_STARTED.md +0 -0
  59. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/IMPLEMENTATION_CLI.md +0 -0
  60. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/IMPLEMENTATION_PYTHON_API.md +0 -0
  61. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/INPUT_DESIGN.md +0 -0
  62. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/MARKET_RESEARCH.md +0 -0
  63. {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_0_2_COMPLETION.md +0 -0
  64. {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_3_4_COMPLETION.md +0 -0
  65. {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_4_REFOCUS.md +0 -0
  66. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/PRODUCT_VISION.md +0 -0
  67. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/QUICK_START.md +0 -0
  68. {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/RESEARCH_SUMMARY.md +0 -0
  69. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/blastradius-complete.yml +0 -0
  70. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/blastradius-kubernetes.yml +0 -0
  71. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/python_advanced.py +0 -0
  72. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/python_quickstart.py +0 -0
  73. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/rest_api_client.py +0 -0
  74. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/business-impact/saas-impact.yaml +0 -0
  75. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/kubernetes/microservices.yaml +0 -0
  76. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/terraform/infrastructure.tf +0 -0
  77. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/anomaly_detection.rs +0 -0
  78. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/criticality.rs +0 -0
  79. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/hidden_dependencies.rs +0 -0
  80. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/graphql.rs +0 -0
  81. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/integrations.rs +0 -0
  82. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/mod.rs +0 -0
  83. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/edge.rs +0 -0
  84. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/mod.rs +0 -0
  85. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/node.rs +0 -0
  86. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/data_quality.rs +0 -0
  87. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/dbt_integration.rs +0 -0
  88. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/mod.rs +0 -0
  89. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/otel_integration.rs +0 -0
  90. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/lib.rs +0 -0
  91. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/models/mod.rs +0 -0
  92. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/conftest.py +0 -0
  93. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_analysis.py +0 -0
  94. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_cli.py +0 -0
  95. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_core_bindings.py +0 -0
  96. {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_server.py +0 -0
@@ -0,0 +1,62 @@
1
+ name: Bug Report
2
+ description: Report something in PyBlastRadius that is broken
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Before filing: check README.md's "Known Issues" and
9
+ `ROADMAP_HONEST.md` — several discovery engines (Kubernetes,
10
+ Airflow, OpenTelemetry) and integrations are documented as
11
+ not-yet-implemented, not bugs.
12
+
13
+ - type: textarea
14
+ id: description
15
+ attributes:
16
+ label: Description
17
+ description: What happened, and what did you expect instead?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: repro
23
+ attributes:
24
+ label: Steps to Reproduce
25
+ description: Minimal steps/code to reproduce the issue.
26
+ render: shell
27
+ validations:
28
+ required: true
29
+
30
+ - type: textarea
31
+ id: logs
32
+ attributes:
33
+ label: Relevant Output / Traceback
34
+ render: shell
35
+
36
+ - type: input
37
+ id: version
38
+ attributes:
39
+ label: PyBlastRadius Version
40
+ placeholder: "e.g. 0.3.0 (pip show pyblastradius)"
41
+ validations:
42
+ required: true
43
+
44
+ - type: input
45
+ id: python-version
46
+ attributes:
47
+ label: Python Version
48
+ placeholder: "e.g. 3.11.6"
49
+ validations:
50
+ required: true
51
+
52
+ - type: dropdown
53
+ id: os
54
+ attributes:
55
+ label: Operating System
56
+ options:
57
+ - Linux
58
+ - macOS
59
+ - Windows
60
+ - Other
61
+ validations:
62
+ required: true
@@ -0,0 +1,38 @@
1
+ name: Feature Request
2
+ description: Suggest something new for PyBlastRadius
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Check `ROADMAP_HONEST.md` first — your idea may already be listed
9
+ as a known gap (e.g. Kubernetes/Airflow discovery, a served GraphQL
10
+ endpoint, sending the already-built chat/incident-management
11
+ webhook payloads).
12
+
13
+ - type: textarea
14
+ id: summary
15
+ attributes:
16
+ label: Summary
17
+ description: Brief description of the feature.
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: use-case
23
+ attributes:
24
+ label: Use Case
25
+ description: What problem does this solve for you?
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: proposal
31
+ attributes:
32
+ label: Proposed Solution
33
+ description: How should this work, if you have a specific idea?
34
+
35
+ - type: textarea
36
+ id: alternatives
37
+ attributes:
38
+ label: Alternatives Considered
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ # Rust crate dependencies (Cargo.toml / Cargo.lock)
4
+ - package-ecosystem: "cargo"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ open-pull-requests-limit: 10
9
+
10
+ # Python dependencies declared in pyproject.toml
11
+ - package-ecosystem: "pip"
12
+ directory: "/"
13
+ schedule:
14
+ interval: "weekly"
15
+ open-pull-requests-limit: 10
16
+
17
+ # GitHub Actions used in .github/workflows/*.yml and action.yml
18
+ - package-ecosystem: "github-actions"
19
+ directory: "/"
20
+ schedule:
21
+ interval: "weekly"
22
+ open-pull-requests-limit: 10
@@ -0,0 +1,28 @@
1
+ ## Description
2
+
3
+ Brief summary of the change.
4
+
5
+ ## Related Issues
6
+
7
+ Closes #
8
+
9
+ ## Testing
10
+
11
+ - [ ] `cargo test --all-features` passes
12
+ - [ ] `cargo clippy --all-targets -- -D warnings` passes
13
+ - [ ] `cargo fmt -- --check` passes
14
+ - [ ] If this touches `python/` or `src/python.rs`: `maturin develop --release`
15
+ then `pytest tests/ -q` passes
16
+ - [ ] Added/updated tests for the change
17
+ - [ ] Manually verified the change (describe how)
18
+
19
+ ## Honesty Checklist
20
+
21
+ This repo's README/ROADMAP_HONEST.md distinguish tested-and-working from
22
+ built-but-unverified from not-built. If this PR changes feature status:
23
+
24
+ - [ ] Updated README.md's Features/Known Issues/Platform Support sections
25
+ - [ ] Updated `ROADMAP_HONEST.md` if a bucketed item moved (built-not-tested
26
+ -> tested, not-built -> built, etc.)
27
+ - [ ] Did not describe untested code as working, and did not use hedge
28
+ words ("planned", "may") for something that is simply not built
@@ -56,7 +56,12 @@ jobs:
56
56
  components: clippy
57
57
 
58
58
  - name: Run clippy
59
- run: cargo clippy -- -D warnings
59
+ # --all-targets so this actually lints #[cfg(test)] code too --
60
+ # plain `cargo clippy` silently skips test targets, which is how 9
61
+ # real clippy errors (unused imports, len_zero) sat undetected in
62
+ # this repo's own test code until this pass caught them by running
63
+ # `cargo clippy --all-targets` locally.
64
+ run: cargo clippy --all-targets -- -D warnings
60
65
 
61
66
  fmt:
62
67
  name: Format
@@ -92,6 +97,21 @@ jobs:
92
97
  with:
93
98
  files: ./cobertura.xml
94
99
 
100
+ audit:
101
+ name: Security Audit
102
+ runs-on: ubuntu-latest
103
+ steps:
104
+ - uses: actions/checkout@v4
105
+
106
+ - name: Install Rust
107
+ uses: dtolnay/rust-toolchain@stable
108
+
109
+ - name: Install cargo-audit
110
+ run: cargo install cargo-audit --locked
111
+
112
+ - name: Run cargo audit
113
+ run: cargo audit
114
+
95
115
  build:
96
116
  name: Build
97
117
  runs-on: ${{ matrix.os }}
@@ -123,3 +143,49 @@ jobs:
123
143
  with:
124
144
  name: pyblastradius-${{ matrix.os }}
125
145
  path: target/release/pyblastradius*
146
+
147
+ # Lint gate for the Python package (PYBLASTRADIUS-003). Uses the curated
148
+ # ruleset in pyproject.toml ([tool.ruff.lint]); previously the repo had
149
+ # no Python lint at all.
150
+ python-lint:
151
+ name: Python Lint (ruff)
152
+ runs-on: ubuntu-latest
153
+ steps:
154
+ - uses: actions/checkout@v4
155
+
156
+ - name: Set up Python
157
+ uses: actions/setup-python@v5
158
+ with:
159
+ python-version: "3.12"
160
+
161
+ - name: Install ruff
162
+ run: pip install "ruff>=0.5.0"
163
+
164
+ - name: Ruff
165
+ run: ruff check python/
166
+
167
+ # Python-side security scanning (Gemini review: only Rust had a
168
+ # continuous audit). Bandit for code patterns, pip-audit for dependency
169
+ # CVEs, both blocking.
170
+ python-security:
171
+ name: Python Security (bandit + pip-audit)
172
+ runs-on: ubuntu-latest
173
+ steps:
174
+ - uses: actions/checkout@v4
175
+
176
+ - name: Set up Python
177
+ uses: actions/setup-python@v5
178
+ with:
179
+ python-version: "3.12"
180
+
181
+ - name: Install Rust
182
+ uses: dtolnay/rust-toolchain@stable
183
+
184
+ - name: Install scanners
185
+ run: pip install "bandit>=1.7" "pip-audit>=2.7"
186
+
187
+ - name: Bandit
188
+ run: bandit -r python/ -ll
189
+
190
+ - name: pip-audit
191
+ run: pip-audit .
@@ -17,7 +17,15 @@ jobs:
17
17
 
18
18
  - name: Run Blast Radius Analysis
19
19
  id: blast
20
- uses: Mullassery/pyblastradius-action@v1
20
+ # `Mullassery/pyblastradius-action` does not exist (verified via
21
+ # authenticated `gh api repos/Mullassery/pyblastradius-action` ->
22
+ # 404 GraphQL resolution failure). This repo's own root action.yml
23
+ # *is* the composite action (see CONTRIBUTING.md / action.yml), so
24
+ # it's referenced directly here. Pinned to @main rather than a tag
25
+ # because this repo has no `v1` tag/release yet (only v0.1.0,
26
+ # v0.2.0 -- verified via `gh api .../tags` and `.../releases`);
27
+ # repin to a proper version tag once one exists.
28
+ uses: Mullassery/PyBlastRadius@main
21
29
  with:
22
30
  discovery-sources: |
23
31
  kubernetes://
@@ -87,7 +87,7 @@ jobs:
87
87
  - name: Flatten dist directory
88
88
  run: |
89
89
  mkdir -p final_dist
90
- find dist -type f -name "*.whl" -o -name "*.tar.gz" | while read file; do
90
+ find dist -type f \( -name "*.whl" -o -name "*.tar.gz" \) | while read -r file; do
91
91
  cp "$file" final_dist/
92
92
  done
93
93
  ls -la final_dist/
@@ -113,7 +113,7 @@ jobs:
113
113
  path: artifacts/
114
114
 
115
115
  - name: Create Release
116
- uses: softprops/action-gh-release@v1
116
+ uses: softprops/action-gh-release@v2
117
117
  with:
118
118
  files: |
119
119
  artifacts/**/*.whl
@@ -135,9 +135,9 @@ jobs:
135
135
 
136
136
  ## Documentation
137
137
 
138
- - [Quick Start](https://github.com/Mullassery/PyBlastRadius/blob/main/docs/QUICK_START.md)
139
- - [Architecture](https://github.com/Mullassery/PyBlastRadius/blob/main/docs/ARCHITECTURE.md)
138
+ - [README](https://github.com/Mullassery/PyBlastRadius#readme) (Quick Start, Architecture, current status)
140
139
  - [Contributing](https://github.com/Mullassery/PyBlastRadius/blob/main/CONTRIBUTING.md)
140
+ - [Honest roadmap / known gaps](https://github.com/Mullassery/PyBlastRadius/blob/main/ROADMAP_HONEST.md)
141
141
 
142
142
  ## Support
143
143
 
@@ -1,8 +1,11 @@
1
1
  # Rust
2
2
  /target
3
3
  **/*.rs.bk
4
- Cargo.lock
5
4
  *.pdb
5
+ # Cargo.lock is intentionally committed (not ignored): this crate builds a
6
+ # Python extension module + CLI (an application/product, not a pure
7
+ # library), so pinning exact dependency versions makes builds and
8
+ # `cargo audit` reproducible. See ROADMAP_HONEST.md.
6
9
 
7
10
  # Python
8
11
  __pycache__/
@@ -57,3 +60,5 @@ venv/
57
60
  # OS
58
61
  .DS_Store
59
62
  Thumbs.db
63
+
64
+ graphify-out/
@@ -0,0 +1,31 @@
1
+ # Graphify ignore file - https://docs.graphify.com/reference/configuration
2
+ # Keep the scan (and therefore the agent's graph) focused on real source.
3
+ .git/
4
+ .github/
5
+ graphify-out/
6
+
7
+ # Build output / artifacts
8
+ target/
9
+ dist/
10
+ build/
11
+ *.egg-info/
12
+ node_modules/
13
+ .venv/
14
+ venv/
15
+ env/
16
+
17
+ # Caches
18
+ __pycache__/
19
+ *.pyc
20
+ .pytest_cache/
21
+ .mypy_cache/
22
+ .ruff_cache/
23
+ .tox/
24
+ .nox/
25
+ .coverage
26
+ htmlcov/
27
+
28
+ # Vendored / generated
29
+ *.min.js
30
+ *.min.css
31
+ *.lock
@@ -0,0 +1,249 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.4.2] - 2026-10-17
9
+
10
+ ### Fixed
11
+ - Audit remediation: security hardening, correctness fixes, and lint/CI gates.
12
+
13
+ ## [0.4.1] - 2026-10-11
14
+
15
+ ### Fixed
16
+
17
+ - `python/pyblastradius/integrations.py` referenced `Graph` in its type
18
+ annotations without importing it (`ruff` `F821`). A plain top-level import
19
+ would create a circular import because `pyblastradius/__init__.py`
20
+ re-exports names from this module, so `Graph` is now imported under
21
+ `typing.TYPE_CHECKING`. `import pyblastradius.integrations` now succeeds
22
+ cleanly.
23
+
24
+ ## [0.4.0] - 2026-10-05
25
+
26
+ ### Added
27
+
28
+ - **Real Kubernetes and OTLP dependency discovery**, wired up the same way
29
+ Terraform was in v0.3.0. `src/python.rs` gained `PyKubernetesDiscoverer`
30
+ and `PyOtelDiscoverer`, exposing the real, already-tested Rust parsers
31
+ (`src/discovery/kubernetes.rs`, `src/discovery/otlp.rs`) — which existed
32
+ the whole time but were never registered in the `#[pymodule]` block, so
33
+ `pyblastradius.KubernetesDiscoverer`/`OtelDiscoverer` were separate,
34
+ disconnected pure-Python stubs that always returned an empty graph.
35
+ - `KubernetesDiscoverer` now parses real Service/Deployment/StatefulSet/
36
+ DaemonSet YAML and infers edges from container env var references.
37
+ `kubeconfig`/`context` are accepted for interface compatibility with
38
+ the old stub's constructor (and existing `blastradius.yml`/REST API
39
+ payloads) but have no effect — there's no live-cluster API client,
40
+ only local manifest parsing. If `manifests_dir` isn't given, the
41
+ conventional `k8s`/`kubernetes`/`.` directories are probed for the
42
+ first one that exists.
43
+ - `OtelDiscoverer` now runs a real OTLP/gRPC trace receiver bound to
44
+ `endpoint`, collecting whatever spans are actually pushed to it during
45
+ the collection window and deriving edges from real cross-service
46
+ parent/child span pairs. This is a semantic correction, not just a
47
+ wiring fix: the old stub's docstring said it would "connect to OTLP
48
+ collector," but the real implementation is itself a receiver —
49
+ `endpoint` must be a literal `ip:port` listen address, not a hostname
50
+ (the old `"localhost:4317"` default would fail to parse for exactly
51
+ this reason; the new default is `"0.0.0.0:4317"`). `discover()`
52
+ releases the GIL for the full blocking collection window, verified
53
+ with a concurrent-thread test rather than just a lack-of-crash check.
54
+ - `tests/test_discovery_bindings.py` (new, 7 tests) exercises both
55
+ against the real compiled `_core` extension: real manifest parsing,
56
+ real OTLP bind/timeout/empty-window behavior, and the
57
+ `kubeconfig`/`context`/`namespaces` interface-compat notes above.
58
+
59
+ ## [0.3.0] - 2026-08-26
60
+
61
+ ### Added
62
+
63
+ - **Real Terraform dependency discovery.** `TerraformDiscoverer` now parses
64
+ `.tf` files with a real HCL2 parser (`hcl-rs`) instead of the previous
65
+ regex-based extraction (limited to 3 hardcoded AWS resource types, and
66
+ fooled by multi-line blocks, nested blocks, or comments containing
67
+ lookalike declarations). Any `resource "type" "name" { ... }` block is
68
+ discovered now, not just RDS/ElastiCache/ECS. Dependency *edges* are the
69
+ bigger fix: they previously came from a hardcoded example dependency
70
+ list (`api_gateway -> auth_service -> production`, etc.) that had
71
+ nothing to do with the actual `.tf` content being scanned -- edges are
72
+ now derived from real resource references found in each resource's own
73
+ attribute values, both bare traversals
74
+ (`aws_db_instance.production.endpoint`) and interpolated strings
75
+ (`"${aws_db_instance.production.endpoint}"`).
76
+ - **`TerraformDiscoverer` is now reachable from Python at all.** The real
77
+ Rust implementation existed before this release but was never exposed
78
+ via pyo3 -- `pyblastradius.TerraformDiscoverer` (used by `cli.py`,
79
+ `config.py`, `server.py`) resolved to a pure-Python placeholder in
80
+ `pyblastradius/discovery.py` that walked matching files and discarded
81
+ their contents entirely (`# For now, just create mock nodes` / `pass`),
82
+ always returning an empty graph regardless of what `scan`'s
83
+ `terraform://` source pointed at. `pyblastradius/__init__.py` now
84
+ imports the real `_core` binding instead; the fake class has been
85
+ removed from `discovery.py`.
86
+ - **`benches/large_graph.rs`**: real `criterion` benchmarks (graph
87
+ construction, `BlastRadiusAnalyzer::analyze`,
88
+ `CriticalityScorer::score_all`) on layered graphs up to 1,000 nodes with
89
+ realistic fan-out topology. `criterion`/`[profile.bench]` were declared
90
+ in `Cargo.toml` with a `// Benchmarks (add later)` comment, but no
91
+ `benches/` directory or `[[bench]]` target existed before this.
92
+
93
+ ## [0.2.1] - 2026-08-23
94
+
95
+ ### Fixed
96
+
97
+ - `CriticalityScorer`: `criticality_score` was divided by 100 twice, collapsing the
98
+ documented 0-100 scale down to ~0-1. Fixed the double-division.
99
+ - `CriticalityScorer::is_single_point_of_failure`: checked a node's *predecessor's*
100
+ out-degree instead of the node's own in-degree, producing false negatives on branching
101
+ topologies (a node with exactly one predecessor was missed as a SPOF if that predecessor
102
+ also happened to reach other nodes). Fixed to check in-degree directly; added a
103
+ regression test for the branching case.
104
+ - `ColumnLineageTracker::track_column` split `"schema.table.column"` identifiers into only
105
+ their first and last dot-separated segments, discarding the middle table segment --
106
+ `find_downstream_impact()` could never match a real 3-part identifier as a result. Fixed
107
+ with `rsplit_once('.')`.
108
+ - `test_hidden_dependency_detection`'s fixture graph never met
109
+ `detect_from_trace_gaps`'s own documented threshold (a node needs > 3 downstream
110
+ neighbors), so it asserted on an always-empty result regardless of whether detection
111
+ actually worked. Gave the fixture a graph that genuinely exercises the heuristic.
112
+ - `test_blast_radius_analysis` picked its start node via `nodes[0]` after collecting
113
+ `graph.nodes()` (backed by a `HashMap`, whose iteration order isn't stable across
114
+ process runs) into a `Vec` -- flaky depending on which node landed at index 0. Now looks
115
+ up the intended node by name.
116
+ - CI: replaced the archived `actions-rs/toolchain` action (broken/unmaintained) with
117
+ `dtolnay/rust-toolchain@stable` across all jobs; bumped `actions/checkout`,
118
+ `actions/cache`, `actions/upload-artifact`, and `codecov-action` to current major
119
+ versions; pinned Python 3.12 in the Build job (macos-latest's default python3 recently
120
+ became 3.14, which PyO3 0.23.5 rejects); marked the README's ASCII architecture diagram
121
+ as a `text` fence instead of an implicit (and invalid) Rust doctest.
122
+ - `cargo fmt`/`cargo clippy -D warnings` had never actually run cleanly before (blocked by
123
+ the broken CI action above) -- fixed ~50 real warnings surfaced once they could run.
124
+
125
+ No public API changes.
126
+
127
+ ## [Unreleased]
128
+
129
+ ### Fixed
130
+
131
+ - **`action.yml` (the repo's own composite GitHub Action) was completely
132
+ non-functional; rewritten against the real Python API.** It called
133
+ `BlastRadiusAnalyzer(graph)` as a constructor (no `#[new]` exists on
134
+ `PyBlastRadiusAnalyzer` -- `analyze` is a staticmethod), `graph.services()`
135
+ (no such method on `Graph`), and `Graph.merge([graph, sub_graph])` as a
136
+ static call (the real `merge` is an instance method, `graph.merge(other)`,
137
+ mutating in place). It also used the deprecated `::set-output` command,
138
+ which GitHub Actions has disabled, so outputs silently never set even
139
+ before the API bugs. Separately, the top-level `outputs:` block referenced
140
+ `steps.analyze.outputs.*`, but the step with `id: analyze` was the
141
+ discovery step -- the step that actually set outputs was `id: pr_comment`
142
+ -- so outputs would have stayed unset even if every other bug were fixed.
143
+ Rewritten to call the real API (`BlastRadiusAnalyzer.analyze(graph,
144
+ node_id, max_depth=...)`, `graph.nodes()` filtered by `NodeType.Service`,
145
+ instance-method `graph.merge(other)`), write to `$GITHUB_OUTPUT`, and
146
+ renamed step ids so the output step is actually `id: analyze`. Verified
147
+ by extracting and running the exact embedded Python against a synthetic
148
+ Terraform fixture (multiple `aws_ecs_service`/`aws_lambda_function`/
149
+ `aws_db_instance` resources with cross-references) end-to-end, including
150
+ the failure-threshold pass/fail branches and the "no sources discovered"
151
+ and "invalid source URI" edge cases -- no exceptions, real scores/outputs
152
+ produced.
153
+ - **`.github/workflows/example-blast-radius.yml`** referenced
154
+ `Mullassery/pyblastradius-action@v1`, a repo that does not exist (verified
155
+ via authenticated `gh api` -- GraphQL resolution failure, not just a
156
+ blocked-network false negative). Repointed to
157
+ `uses: Mullassery/PyBlastRadius@main`, since this repo's own root
158
+ `action.yml` *is* the composite action and there is no `v1` tag/release
159
+ yet (`gh api .../tags` shows only `v0.1.0`/`v0.2.0`) to pin to instead.
160
+ - **`CONTRIBUTING.md`** referenced `src/bin/cli.rs` and `cargo run --
161
+ --version` in two places (Development Setup, "Adding a New Discovery
162
+ Engine"); both were removed from the crate when the CLI moved to
163
+ `python/pyblastradius/cli.py` (confirmed `cargo run` fails with "a bin
164
+ target must be available" -- no `[[bin]]` in `Cargo.toml`). Updated both
165
+ sections to describe the actual PyO3-binding + Python-CLI wiring path.
166
+ - **`python/pyblastradius/__init__.py`**'s `__license__` still said
167
+ "Proprietary License" after the repo was relicensed to Apache-2.0
168
+ (`pyproject.toml`'s `license = "Apache-2.0"` and the root `LICENSE` file
169
+ already reflected it). Corrected to `"Apache-2.0"`.
170
+
171
+ ### Planned
172
+ - ML-based failure prediction with anomaly consensus scoring
173
+ - Neo4j backend for 100K+ node graphs
174
+ - GraphQL Federation for multi-service deployments
175
+ - Kubernetes Operator for continuous discovery
176
+ - Helm chart for self-hosted deployment
177
+ - Advanced hidden dependency detection (query logs, configuration mining)
178
+
179
+ ## [0.2.0] - 2026-08-05
180
+
181
+ Real git tag (`v0.2.0`), dated from `git log`. No entry existed for this
182
+ release before this pass; added from the verified commit history and the
183
+ Project Status table in README.md rather than reconstructed from memory.
184
+
185
+ ### Added
186
+ - First working `pyblastradius._core` PyO3 extension module — end-to-end
187
+ `import pyblastradius` against real compiled Rust code, not a pure-Python
188
+ placeholder.
189
+ - Real end-to-end analysis via the extension: `Graph`/`Node`/`Edge`,
190
+ `BlastRadiusAnalyzer`, `CriticalityScorer`, `Simulator`.
191
+
192
+ ### Known limitations as of this release
193
+ Discovery engines (Kubernetes, Airflow, OTel) were not implemented yet —
194
+ see Platform Support in README.md for current status of each.
195
+
196
+ ## [0.1.0] - 2026-08-05
197
+
198
+ Real git tag (`v0.1.0`), dated from `git log`.
199
+
200
+ **This entry was originally written before implementation started and
201
+ described intended v1.0 scope, not what had actually shipped** — it listed
202
+ a GraphQL API, Slack/PagerDuty integrations, and full Kubernetes/Airflow/
203
+ OpenTelemetry discovery as "Added" in this release. None of that was true
204
+ at the time and, per README.md's Known Issues (verified 2026-09-19), most
205
+ of it (Kubernetes/Airflow/OTel discovery, the GraphQL endpoint, and sending
206
+ actual Slack/PagerDuty webhooks) is still not implemented today, several
207
+ releases later. Corrected below to only what the actual `v0.1.0` git tag's
208
+ codebase supports; see README.md for the authoritative current-state
209
+ breakdown of every feature.
210
+
211
+ ### Added
212
+ - Initial project scaffold: Rust workspace, `petgraph`-based graph model
213
+ (node/edge types, properties), graph traversal (BFS/DFS/topological
214
+ sort), JSON/GraphML/Dot serialization.
215
+ - Early-stage discovery, analysis, and integration code for Kubernetes,
216
+ Terraform, Airflow, OTel, GraphQL, Slack/PagerDuty, and dbt/StatGuardian
217
+ — present in the codebase from this point on, but not wired up to real
218
+ parsing/live data/Python bindings until later releases (Terraform in
219
+ v0.3.0, the Python extension module itself in v0.2.0). Treat this as
220
+ "code exists" not "feature works" — see README.md Known Issues for what
221
+ is real today.
222
+ - CI/CD scaffold (GitHub Actions), example configs, initial docs.
223
+
224
+ ---
225
+
226
+ ## Release Checklist
227
+
228
+ When preparing a new release:
229
+
230
+ - [ ] Update version in `Cargo.toml`, `pyproject.toml`, and `__init__.py`
231
+ - [ ] Update this `CHANGELOG.md` with new section
232
+ - [ ] Ensure all tests pass (`cargo test`)
233
+ - [ ] Run code quality checks (`cargo clippy`, `cargo fmt`)
234
+ - [ ] Create git tag: `git tag -a v0.1.0 -m "Release v0.1.0"`
235
+ - [ ] Push tag: `git push origin v0.1.0`
236
+ - [ ] Verify wheels built and published on PyPI
237
+ - [ ] Verify release created on GitHub with artifacts
238
+
239
+ ---
240
+
241
+ ## Links
242
+
243
+ - [Documentation](https://github.com/Mullassery/PyBlastRadius/blob/main/docs/)
244
+ - [GitHub Issues](https://github.com/Mullassery/PyBlastRadius/issues)
245
+ - [PyPI Package](https://pypi.org/project/pyblastradius/)
246
+
247
+ ---
248
+
249
+ **Note**: This project follows Semantic Versioning. For updates and feature requests, see [Contributing](CONTRIBUTING.md).