Skip to content

feat(deps): SBOM ingestion + a standalone coverage-measurement script… - #402

Draft
iron-prog wants to merge 5 commits into
hiero-hackers:mainfrom
iron-prog:feat/dependency-network
Draft

iron-prog wants to merge 5 commits into
hiero-hackers:mainfrom
iron-prog:feat/dependency-network

Conversation

@iron-prog

@iron-prog iron-prog commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

Add the first data-layer slice for the repository dependency network proposed in #338.

This slice measures real SBOM availability across the hiero-ledger organization before introducing dependency resolution heuristics or visualization.

What this PR adds

  • Add SBOM package and per-repository coverage records
  • Add GitHub REST SBOM ingestion with explicit ok, disabled, and error outcomes
  • Add purl parsing for common ecosystems, including scoped npm and Maven packages
  • Add a standalone SBOM coverage measurement script
  • Add tests for purl parsing, SBOM parsing, coverage outcomes, and org-wide fan-out
  • Keep dependency resolution, network analysis, charting, and pipeline registration out of this first slice until real coverage is measured

Real SBOM coverage

The coverage measurement was run against the real hiero-ledger organization:

  • 44 repositories scanned
  • 41 repositories have a readable SBOM
  • 3 repositories have SBOM access disabled
  • 0 repositories ended in an error state after retries
  • All 41 readable SBOMs contain at least one dependency
  • 35,263 dependency records were parsed

Readable SBOM coverage:

41 / 44 = 93.18%

Ecosystem breakdown:

Ecosystem Dependencies
npm 31,781
cargo 1,197
maven 961
githubactions 519
pypi 365
golang 358
github 41
swift 38
gem 3
Total 35,263

The current measurement establishes SBOM availability and package ingestion. It does not yet measure how many dependencies resolve to other hiero-ledger repositories. That resolution measurement will be part of the next slice.

Related issue(s)

Fixes #338

Notes for reviewer

This PR intentionally stops at the data/measurement layer.

The real-org measurement confirms that SBOM data is available for the large majority of hiero-ledger repositories, with 35,263 dependency records available for further analysis.

The next slice can therefore focus on dependency resolution and determine how much of this data can be mapped to other repositories in the organization before introducing the dependency network/chart layer.

One bug found during development was that percent-encoded purl namespaces were not decoded correctly (e.g. scoped npm packages). This is covered by the purl parsing tests.

Verification

  • uv run pytest
  • uv run ruff check src tests
  • Real hiero-ledger SBOM coverage measurement
  • SBOM parsing and org fan-out tested with realistic synthetic SPDX payloads, including mixed ok/disabled/error outcomes and root-package exclusion

Checklist

  • I claimed the linked issue with /assign before starting (see contributing guide
  • uv run pytest and uv run ruff check src tests pass locally
  • Tests added/updated for the change (mirroring the src/ layout)
  • Commits are signed and signed-off: git commit -S -s
  • Docs updated if relevant

@coderabbitai

coderabbitai Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: hiero-hackers/analytics/.coderabbit.yml

Review profile: CHILL

Plan: Advanced

Run ID: 7bdf87db-00d2-41b2-95c7-0d2f85596285

📥 Commits

Reviewing files that changed from the base of the PR and between ac144ef and ed55e51.

📒 Files selected for processing (4)
  • scripts/measure_sbom_coverage.py
  • src/hiero_analytics/data_sources/github_rest.py
  • src/hiero_analytics/data_sources/models.py
  • tests/data_sources/test_github_rest.py
💤 Files with no reviewable changes (1)
  • scripts/measure_sbom_coverage.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/hiero_analytics/data_sources/models.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

The change adds models and helpers to retrieve dependency-graph SBOM data for repositories, aggregate results across an organization with retries, and measure coverage with a standalone script.

Changes

SBOM coverage collection

Layer / File(s) Summary
SBOM models, parsing, and repository retrieval
src/hiero_analytics/data_sources/models.py, src/hiero_analytics/data_sources/github_rest.py, tests/data_sources/test_github_rest.py
Adds frozen records for dependency packages and coverage outcomes. PURL parsing normalizes package details. Repository retrieval skips repository-described packages, marks 404 responses as disabled, validates response schemas, and propagates other HTTP errors for retry. Tests cover parsing and response handling.
Organization SBOM aggregation
src/hiero_analytics/data_sources/github_rest.py, tests/data_sources/test_github_rest.py
Adds concurrent organization-wide fetching with retries and error coverage records for repositories that still fail. Tests cover aggregation and retry behavior.
Coverage measurement
scripts/measure_sbom_coverage.py
Adds a script that reports repository coverage and dependency totals by ecosystem, then writes sorted per-repository results to sbom_coverage_raw.csv.

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to ed55e

Some repositories with inaccessible SBOMs may be reported as having disabled dependency graphs, making the coverage results unreliable. Resolve or explicitly accept that ambiguity before merging.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning For the staged SBOM ingestion objective in #338, the PR adds per-repository REST SBOM fetching, purl parsing, ok/disabled/error coverage records, retrying fan-out, coverage measurement, and auto… Treat HTTP 403 as disabled in fetch_repo_sbom, preserve the zero-package coverage record, and add or update an automated 403 test. Keep other failure statuses on the retry and error path. The deferred package-to-repository resolution,…
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main changes: SBOM ingestion and a standalone coverage-measurement script.
Description check ✅ Passed The description directly explains the SBOM ingestion, coverage measurement, parsing, tests, scope, and reported results.
Out of Scope Changes check ✅ Passed The changed files support the SBOM data-layer slice described for #338. They add SBOM models, REST ingestion, purl parsing, organization fan-out, coverage measurement, and related tests. The changes d…
Docstring Coverage ✅ Passed Docstring coverage is 86.36% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 4 files.
Full details: Linked Issues check

Explanation

For the staged SBOM ingestion objective in #338, the PR adds per-repository REST SBOM fetching, purl parsing, ok/disabled/error coverage records, retrying fan-out, coverage measurement, and automated tests. The implementation treats only HTTP 404 as disabled. It propagates HTTP 403 and records an error after retry. Issue #338 requires both 404 and 403 dependency-graph-disabled responses to produce an empty result without an error.

Resolution

Treat HTTP 403 as disabled in fetch_repo_sbom, preserve the zero-package coverage record, and add or update an automated 403 test. Keep other failure statuses on the retry and error path. The deferred package-to-repository resolution, chart, and pipeline work can remain in later slices because this PR states that it implements the initial ingestion and coverage stage.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: fb0710e0-e9e4-45b7-8111-3f1c2d784f57

📥 Commits

Reviewing files that changed from the base of the PR and between b7f59fb and f8bd032.

📒 Files selected for processing (5)
  • measure_sbom_coverage.py
  • src/hiero_analytics/data/dependency_repo_map.yaml
  • src/hiero_analytics/data_sources/github_rest.py
  • src/hiero_analytics/data_sources/models.py
  • tests/data_sources/test_github_rest.py

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.

Comment thread src/hiero_analytics/data_sources/github_rest.py Outdated
…hiero-hackers#338)

First slice of hiero-hackers#338 (repo dependency network chart) -- data layer only,
per the design agreed with exploreriii: measure real SBOM coverage
before building the resolution heuristic or the chart around a guess.

- models.py: DependencyManifestRecord (one parsed SBOM package, purl-based
  ecosystem+name+version, not the raw SPDX name field) and
  SbomCoverageRecord (per-repo fetch outcome: ok/disabled/error -- kept
  distinct from the package list itself, so 'no edges' is distinguishable
  from 'no data', per the issue's coverage-honesty requirement).
- github_rest.py: fetch_repo_sbom (REST SBOM endpoint, 403/404 -> disabled
  mirroring has_codeowners_file's exact contract, any other error ->
  status='error' rather than raising or silently dropping), _parse_purl
  (percent-decoded, handles npm scopes/Maven groupIds/Cargo/PyPI/Go),
  fetch_org_sbom_data (org-wide fan-out via fetch_all_with_retry, always
  exactly one coverage row per input repo).
- data/dependency_repo_map.yaml: the curated-override file, following
  affiliations.yaml's '# manual' convention but explicitly documented as a
  different *kind* of file -- corrections-only, not a comprehensive
  regenerated map. Empty by design until real resolution data exists.
- measure_sbom_coverage.py: standalone script (not a registered pipeline
  yet -- that's gated on this measurement) to answer the actual open
  question: how many hiero-ledger repos have a readable SBOM at all.

Bug caught before committing: the first working version of _parse_purl
didn't percent-decode the namespace/name segment, so a scoped npm package
like '@org/pkg' parsed back out as the literal '%40org/pkg'. Caught by
testing against a realistic synthetic purl, not by inspection.

No resolution heuristic, no chart, no pipeline registration yet -- those
depend on what the coverage script finds when run against real
hiero-ledger data. Deliberately small first slice, per the PR-split plan
agreed in the design comment.

Verified: 738 passed, 95.36% coverage, ruff clean. Data-source and
fan-out logic verified interactively against realistic synthetic SBOM
payloads (SPDX shape, documentDescribes root-exclusion, mixed
ok/disabled/error repos) before writing the formal tests.

Signed-off-by: iron-prog <dt915725@gmail.com>
@iron-prog
iron-prog force-pushed the feat/dependency-network branch from f8bd032 to 848d2ca Compare August 17, 2026 06:32
Signed-off-by: iron-prog <dt915725@gmail.com>

@phillip-nyinomujuni phillip-nyinomujuni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few small questions and one thing I wanted to double check on the SBOM status logic nothing blocking, just curious about the reasoning. Nice clean addition overall, especially the dataclass docstrings.

Comment thread src/hiero_analytics/data_sources/github_rest.py Outdated
Comment thread src/hiero_analytics/data_sources/github_rest.py Outdated
Comment thread src/hiero_analytics/data_sources/models.py Outdated
Comment thread src/hiero_analytics/data_sources/models.py
Comment thread src/hiero_analytics/data_sources/models.py Outdated
@iron-prog
iron-prog marked this pull request as draft August 20, 2026 12:00
Signed-off-by: iron-prog <dt915725@gmail.com>
@iron-prog
iron-prog marked this pull request as ready for review August 20, 2026 18:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 397ac5dc-33cb-4d20-821f-8be20f110f9c

📥 Commits

Reviewing files that changed from the base of the PR and between f8bd032 and 51fe1f9.

📒 Files selected for processing (2)
  • src/hiero_analytics/data_sources/github_rest.py
  • src/hiero_analytics/data_sources/models.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread src/hiero_analytics/data_sources/github_rest.py Outdated
Comment thread src/hiero_analytics/data_sources/github_rest.py Outdated
@iron-prog
iron-prog marked this pull request as draft August 20, 2026 18:57
Signed-off-by: iron-prog <dt915725@gmail.com>
@iron-prog
iron-prog marked this pull request as ready for review September 6, 2026 06:27
@github-actions

github-actions Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

📊 Dashboard preview

The dashboard was built for this PR.

➡️ Download dashboard-preview-402, unzip, then serve it with python3 -m http.server -d . and open the URL it prints. (The app fetches its data over HTTP, so opening index.html directly shows an empty page.)

The artifact is built from this PR — treat it as contributor-authored code and glance at the diff before opening it. It expires after 7 days and is replaced on each new push.

@exploreriii exploreriii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do the results show? what is your opinion should we proceed or not?

Other than that suggest slightly tidying up the code, thank you

Comment thread src/hiero_analytics/data_sources/github_rest.py
Comment thread src/hiero_analytics/data_sources/github_rest.py
Comment thread src/hiero_analytics/data/dependency_repo_map.yaml Outdated
Comment thread scripts/measure_sbom_coverage.py
@exploreriii
exploreriii marked this pull request as draft September 23, 2026 07:53
@iron-prog

Copy link
Copy Markdown
Contributor Author

The SBOM coverage experiment succeeded and provides enough real data to justify the next measurement: dependency resolution.

Signed-off-by: iron-prog <dt915725@gmail.com>
@iron-prog
iron-prog force-pushed the feat/dependency-network branch from 9064a4d to ed55e51 Compare September 24, 2026 12:42
@iron-prog
iron-prog marked this pull request as ready for review September 24, 2026 12:43
@exploreriii

Copy link
Copy Markdown
Contributor

You forgot to lint the code please before requesting a review @iron-prog

@exploreriii
exploreriii marked this pull request as draft September 24, 2026 19:50
@iron-prog

Copy link
Copy Markdown
Contributor Author

You forgot to lint the code please before requesting a review @iron-prog

Sorry for this one

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Repo dependency network chart (SBOM-sourced, hiero-ledger first)

3 participants