Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a028f0-a42f-7582-89a8-ebaad7343834
156 lines
9.4 KiB
Markdown
156 lines
9.4 KiB
Markdown
# State Hub SBOM extraction review
|
|
|
|
**Reviewed:** 2026-08-22
|
|
|
|
**Coordination:** `CUST-WP-0062-T01`, `STATE-WP-0079`, `RMGR-WP-0008`,
|
|
`ACTIVITY-WP-0030`
|
|
|
|
## Outcome
|
|
|
|
The SBOM capability is a coherent product embedded in State Hub, with a newer
|
|
derived-scanner copy in Repo Manager and an already-prepared Activity Core
|
|
consumer contract. The target ownership is:
|
|
|
|
- **SBOM Nexus:** scanning, ingest, snapshots, entries, history, reports,
|
|
freshness, catch-up, import/export;
|
|
- **Repo Manager:** repository identity, active status, and checkout/path
|
|
representation; invoke Nexus rather than retain a second scanner;
|
|
- **State Hub:** temporary compatibility façade and repository freshness
|
|
projection only;
|
|
- **Activity Core:** recurrence and the at-most-N side effect;
|
|
- **dashboard/MCP/CLI callers:** retarget to Nexus or the temporary façade.
|
|
|
|
This corrects a timing overlap in the retirement work: `RMGR-WP-0008` built a
|
|
good repository-derived scanner before `CUST-WP-0062` established the dedicated
|
|
Nexus. That scanner is the best extraction source, but Repo Manager is not the
|
|
durable SBOM product owner.
|
|
|
|
## Current behavior
|
|
|
|
State Hub stores an immutable snapshot container and entries keyed to a managed
|
|
repository. Manual ingest creates a snapshot, stores entries, and updates
|
|
`ManagedRepo.last_sbom_at`. Reads return snapshot history, snapshot detail,
|
|
latest entries per repository, a repository view, and a licence grouping with a
|
|
simple copyleft-family signal.
|
|
|
|
Its ingest script recursively recognizes eight source families and posts the
|
|
merged result to the API. MCP, the `statehub` CLI, Make targets, onboarding,
|
|
repository health, summary caches, and dashboard pages depend on these routes.
|
|
|
|
Repo Manager subsequently improved the derivation step with source-path and
|
|
SHA-256 provenance, Git revision, canonical generation time, structured parser
|
|
errors, and direct-production copyleft findings. Its snapshot schema is
|
|
`repo-manager.sbom-snapshot.v1`.
|
|
|
|
Activity Core already contains a disabled/test-double consumer for the desired
|
|
Nexus endpoint. It expects `GET /sbom/catch-up?limit=N`, defaults to 3, bounds N
|
|
to 1..25, and requires the Nexus to return an ordered `repos` list plus fleet
|
|
counts. The old weekly task-flood definition is disabled.
|
|
|
|
## Artifact and caller disposition
|
|
|
|
| Existing surface | Location | Disposition | Target/action |
|
|
| --- | --- | --- | --- |
|
|
| `SBOMSnapshot` model/table | `state-hub/api/models/sbom_snapshot.py`, migrations | move/import | Nexus snapshot store; retain legacy id/timestamp/source provenance |
|
|
| `SBOMEntry` model/table and ecosystem enum | `state-hub/api/models/sbom_entry.py`, migrations | move/import | Nexus entries; retain compatibility field names |
|
|
| manual ingest | `POST /sbom/ingest/` | move + proxy | Implement compat route in Nexus; State Hub proxies during cutover |
|
|
| snapshot list/detail | `GET /sbom/snapshots/*` | move + proxy | Nexus owns history and response contract |
|
|
| latest entry filters | `GET /sbom/` | move + proxy | Nexus owns current projections |
|
|
| repository view | `GET /sbom/{slug}` | move + proxy | Nexus owns inventory; join/sync minimal repo projection |
|
|
| licence report | `GET /sbom/report/licences/` | move + proxy | Nexus owns qualified signal and later SPDX policy integration |
|
|
| parser/detection script | `state-hub/scripts/ingest_sbom.py` | move, then retire | Extract improved Repo Manager variant into independent Nexus scanner |
|
|
| derived scanner | `repo-manager/src/repo_manager/sbom.py` | move/replace | Make Nexus the implementation; Repo Manager becomes caller/adapter |
|
|
| scanner CLI | `rmgr sbom scan`, `licence-report` | retarget | Preserve CLI UX by calling Nexus/local Nexus library during transition |
|
|
| State Hub Make target | `make ingest-sbom` | retarget | Invoke Nexus CLI/API; retain temporary alias with deprecation notice |
|
|
| `statehub ingest-sbom` | `custodian_cli.py` | retarget | Invoke Nexus, not State Hub-local script |
|
|
| tool capture script/prompt | `scripts/capture_sbom_tools.py`, `prompts/sbom-capture-agent.md` | move later | Nexus operator workflow; keep reviewed manifest as repository authority |
|
|
| MCP resources | `state://sbom/*` | retarget/proxy | Fetch Nexus; later publish Nexus-native MCP if useful |
|
|
| MCP ingest/report tools | `ingest_sbom_tool`, `get_licence_report` | retarget | Call Nexus contracts |
|
|
| dashboard SBOM page/data loader | `dashboard/src/sbom.md`, `data/sbom.json.py` | retarget | Read Nexus or façade; no new dashboard in extraction release |
|
|
| repo/dashboard coverage cards | repos/overview pages | projection | Consume Nexus freshness projection |
|
|
| `ManagedRepo.last_sbom_at`, `sbom_source` | State Hub repo model | strangle/projection | Keep compatible fields, written/synchronized from Nexus during cutover |
|
|
| summary cache revision | `api/services/summary_cache.py` | adapt | Revision from Nexus projection/event, not local SBOM tables |
|
|
| State summary licence scan | `api/routers/state.py` | adapt | Consume Nexus report/projection |
|
|
| DoI criterion C8 | `api/doi_engine.py`, `policies/repo-doi.md` | retarget | Query precise Nexus attempt/success state |
|
|
| edge cache `/sbom/` | `api/edge/read_cache.py` | retire/retarget | Cache façade only while compatibility route exists |
|
|
| repo registration optional ingest | `scripts/register_project.sh` and onboarding docs | retarget | Register projection then invoke Nexus ingest |
|
|
| repository synchronization view | `dashboard/src/repo-sync.md` | retarget | Use Nexus status |
|
|
| Activity Core bulk status resolver | old `repo_sbom_status` | retire | Replace with one Nexus catch-up query |
|
|
| daily bounded consumer | `activity_core/context_resolvers/sbom_nexus.py` | retain/activate later | Contract is accepted input for Nexus implementation |
|
|
| weekly task flood | `weekly-sbom-staleness` | retire | Keep disabled; no one-task-per-stale-repo behavior |
|
|
| historical State Hub rows | 22 snapshots/18 repos in RMGR evidence | import + retain | Import history; reconcile counts; delete only after retention gate |
|
|
|
|
## Extracted source coverage
|
|
|
|
The first Nexus scanner preserves the proven coverage common to State Hub and
|
|
Repo Manager:
|
|
|
|
| Source | Ecosystem | Important behavior |
|
|
| --- | --- | --- |
|
|
| `uv.lock` | Python | all locked packages |
|
|
| `requirements.txt` | Python | declared lines marked direct |
|
|
| `package-lock.json` | Node | package metadata, dev/direct hints, licence when present |
|
|
| `yarn.lock` | Node | locked package/version extraction |
|
|
| `Cargo.lock` | Rust | all locked packages |
|
|
| `go.sum` + `go.mod` | Go | deduplicated modules; direct hint from `go.mod` |
|
|
| `.terraform.lock.hcl` | Terraform | provider/version entries |
|
|
| `ansible/requirements.y[a]ml` | Ansible | collections and roles under `ansible` directories |
|
|
| root `sbom-tools.yaml` | Tool/declared | reviewed escape hatch including licence and direct/dev flags |
|
|
|
|
Excluded directories remain `.git`, VCS metadata, virtual environments,
|
|
`node_modules`, caches, distribution/build outputs, Rust `target`, tox, and
|
|
nox environments.
|
|
|
|
## Contract differences and improvements
|
|
|
|
1. Nexus records `last_attempt_at` separately from `last_success_at`. State
|
|
Hub's single `last_sbom_at` cannot truthfully express a skipped scan.
|
|
2. Every attempt has a terminal status. `no-checkout` and `no-manifest` are
|
|
successful control-loop outcomes but not successful inventories.
|
|
3. Parser errors are stored with the snapshot; they are not silently reduced to
|
|
empty entries.
|
|
4. Source paths, digests, and Git revision are retained from the Repo Manager
|
|
implementation.
|
|
5. Copyleft substring matching remains compatibility triage. It is explicitly
|
|
not an SPDX expression evaluator or legal conclusion.
|
|
6. Catch-up uses last attempt for queue fairness and last success for inventory
|
|
truth. Consumers can display both rather than infer one from the other.
|
|
|
|
## Historical migration requirements
|
|
|
|
The migration must enumerate State Hub snapshots by repository and oldest
|
|
first, fetch each snapshot detail, upsert the repository projection, and insert
|
|
the snapshot with its legacy UUID and timestamp. It must be idempotent on the
|
|
legacy UUID and compare:
|
|
|
|
- repository count;
|
|
- snapshot count per repository and total;
|
|
- entry count per snapshot and total;
|
|
- earliest/latest timestamps;
|
|
- sampled current-repository views;
|
|
- licence group and direct-production copyleft counts.
|
|
|
|
Fresh repository scans do not replace imported history. They become later
|
|
snapshots based on current source evidence.
|
|
|
|
## Cutover gates
|
|
|
|
- Nexus production store, migrations, backup, and restore evidence exist.
|
|
- Historical import reconciles before State Hub deletion is considered.
|
|
- State Hub compatibility tests pass through the façade.
|
|
- Repo Manager no longer presents its scanner as independent SBOM authority.
|
|
- Dashboard, MCP, CLI, DoI, summary, and onboarding callers are inventoried and
|
|
retargeted.
|
|
- Activity Core's ingest side effect is integrated but remains bounded by the
|
|
resolver's effective limit.
|
|
- Two production daily fires record at most N terminal outcomes and zero spawned
|
|
per-repository tasks.
|
|
- Weekly fleet task-flood behavior remains disabled.
|
|
|
|
## Review conclusion
|
|
|
|
Extraction is feasible without changing supported ecosystems. The principal
|
|
risk is not parser migration; it is authority and history cutover across three
|
|
temporarily overlapping implementations. The first Nexus slice therefore pins
|
|
the compatibility and catch-up contracts, while production ownership remains a
|
|
separate gated task requiring State Hub and Repo Manager adapter changes.
|