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.
- pyblastradius-0.4.2/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
- pyblastradius-0.4.2/.github/ISSUE_TEMPLATE/feature_request.yml +38 -0
- pyblastradius-0.4.2/.github/dependabot.yml +22 -0
- pyblastradius-0.4.2/.github/pull_request_template.md +28 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/ci.yml +67 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/example-blast-radius.yml +9 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.github/workflows/publish.yml +4 -4
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/.gitignore +6 -1
- pyblastradius-0.4.2/.graphifyignore +31 -0
- pyblastradius-0.4.2/CHANGELOG.md +249 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/CONTRIBUTING.md +53 -23
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/Cargo.lock +501 -354
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/Cargo.toml +6 -6
- pyblastradius-0.4.2/LICENSE +202 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/PKG-INFO +156 -67
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/README.md +152 -63
- pyblastradius-0.4.2/ROADMAP_HONEST.md +231 -0
- pyblastradius-0.4.2/SECURITY.md +50 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/action.yml +41 -25
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/benches/large_graph.rs +14 -6
- pyblastradius-0.4.2/docs/archive/README.md +36 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/cli.rs +7 -3
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/pyproject.toml +27 -4
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/__init__.py +52 -37
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/analysis.py +4 -4
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/cli.py +38 -26
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/config.py +24 -19
- pyblastradius-0.4.2/python/pyblastradius/discovery.py +41 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/integrations.py +11 -8
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/python/pyblastradius/server.py +63 -26
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/blast_radius.rs +1 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/mod.rs +2 -2
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/simulator.rs +2 -2
- pyblastradius-0.4.2/src/discovery/airflow.rs +885 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/kubernetes.rs +17 -3
- pyblastradius-0.4.2/src/discovery/mod.rs +417 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/otlp.rs +14 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/discovery/terraform.rs +32 -7
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/error.rs +1 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/graph.rs +1 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/serialization.rs +3 -3
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/traversal.rs +2 -2
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/statguardian_integration.rs +1 -1
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/python.rs +223 -9
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/utils/mod.rs +2 -2
- pyblastradius-0.4.2/tests/test_discovery_bindings.py +246 -0
- pyblastradius-0.4.2/tools/graphify/README.md +63 -0
- pyblastradius-0.4.2/tools/graphify/graphify_adapter.py +242 -0
- pyblastradius-0.3.0/CHANGELOG.md +0 -178
- pyblastradius-0.3.0/LICENSE +0 -22
- pyblastradius-0.3.0/python/pyblastradius/discovery.py +0 -118
- pyblastradius-0.3.0/src/discovery/airflow.rs +0 -202
- pyblastradius-0.3.0/src/discovery/mod.rs +0 -10
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/CODE_OF_CONDUCT.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/ARCHITECTURE.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/BUILD_PLAN.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/GAP_ANALYSIS.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/GETTING_STARTED.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/IMPLEMENTATION_CLI.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/IMPLEMENTATION_PYTHON_API.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/INPUT_DESIGN.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/MARKET_RESEARCH.md +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_0_2_COMPLETION.md +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_3_4_COMPLETION.md +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2/docs/archive}/PHASE_4_REFOCUS.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/PRODUCT_VISION.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/QUICK_START.md +0 -0
- {pyblastradius-0.3.0/docs → pyblastradius-0.4.2/docs/archive}/RESEARCH_SUMMARY.md +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/blastradius-complete.yml +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/blastradius-kubernetes.yml +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/python_advanced.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/python_quickstart.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/docs/examples/rest_api_client.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/business-impact/saas-impact.yaml +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/kubernetes/microservices.yaml +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/examples/terraform/infrastructure.tf +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/anomaly_detection.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/criticality.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/analysis/hidden_dependencies.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/graphql.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/integrations.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/api/mod.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/edge.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/mod.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/graph/node.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/data_quality.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/dbt_integration.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/mod.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/integrations/otel_integration.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/lib.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/src/models/mod.rs +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/conftest.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_analysis.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_cli.py +0 -0
- {pyblastradius-0.3.0 → pyblastradius-0.4.2}/tests/test_core_bindings.py +0 -0
- {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
|
-
|
|
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
|
-
|
|
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@
|
|
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
|
-
- [
|
|
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).
|