Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a028f0-a42f-7582-89a8-ebaad7343834
11 KiB
Product Requirements Document — SBOM Nexus
Status: initial extraction baseline
Date: 2026-08-22
Primary coordination: CUST-WP-0062
Initial implementation workplan: SBOM-WP-0001
1. Product summary
SBOM Nexus is a headless service that captures software-composition evidence, normalizes it into immutable per-repository snapshots, reports licence and coverage signals, and selects a bounded oldest-stale queue for recurring catch-up. It replaces State Hub as the SBOM store and product API and supersedes Repo Manager's interim in-process scanner as the durable product owner.
2. Background
The current State Hub implementation provides snapshot and entry tables,
lockfile parsers, manual ingest, latest-snapshot queries, licence grouping,
MCP tools, dashboard views, and a last_sbom_at repository projection. A later
retirement slice reproduced the source-derived scanner in Repo Manager.
The operational trigger for extraction is CUST-WP-0062: a weekly freshness
rule created 75 tasks on 2026-08-17 while 111 of 111 registered repositories
were stale or never scanned. The desired control loop evaluates the fleet once,
selects the N oldest eligible repositories, and attempts no more than N updates
per run. N defaults to 3.
3. Goals
- Establish SBOM Nexus as the single durable SBOM product owner.
- Preserve State Hub's existing snapshot history and compatibility surface.
- Reuse and improve the repository-derived parsers already proven in State Hub and Repo Manager.
- Provide one efficient, deterministic oldest-N catch-up query.
- Record success, empty evidence, unavailable checkout, and ingest failure so a permanently impossible repository cannot block the queue.
- Keep
last_sbom_atprojections truthful throughout cutover. - Give Activity Core a bounded read and ingest contract that can replace the disabled weekly task-flood rule.
4. Non-goals for the extraction release
- Vulnerability correlation or exploitability analysis.
- Full licence-policy adjudication or legal advice.
- Adding ecosystems beyond those already handled by the source implementation.
- Build-time signing, attestations, or admission control.
- A new human dashboard; existing views are retargeted during cutover.
- An unbounded background scanner owned by SBOM Nexus.
5. Users and jobs
| User | Job |
|---|---|
| Fleet operator | Find and update the oldest stale SBOMs without creating an unbounded workload |
| Repository maintainer | Scan a checkout, see parser errors and provenance, and retrieve the current snapshot |
| Activity Core | Fetch at most N ordered targets and record bounded ingest/skip outcomes |
| State Hub compatibility clients | Continue using the current /sbom/* read and ingest contract during migration |
| Compliance/security consumer | Query components, licence distribution, and direct production copyleft triage signals |
| Migration operator | Import historical snapshots while preserving ids, timestamps, sources, and repository association |
6. Functional requirements
FR-1 Repository representation
The service shall maintain the minimum repository projection required for SBOM operations: stable slug, active/in-scope flag, optional checkout path, last attempt time, last successful ingest time, and latest outcome/source. Repo Manager remains upstream authority for repository identity and paths.
FR-2 Source detection and parsing
The extraction release shall detect sources recursively while excluding dependency/build directories. It shall support:
uv.lockandrequirements.txt(Python);package-lock.jsonandyarn.lock(Node);Cargo.lock(Rust);go.sumwithgo.moddirect-dependency hints;.terraform.lock.hcl;ansible/requirements.ymland.yamlbelow anansibledirectory;- reviewed root
sbom-tools.yaml.
Every detected source shall have a repository-relative path, SHA-256 digest, entry count, and any parser error. A repository Git revision is captured when available.
FR-3 Immutable snapshots
Every manual ingest, checkout scan, skip, error, or historical import shall
create a new immutable snapshot. Entries belong to exactly one snapshot.
Previous snapshots remain queryable. Snapshot status and source distinguish at
least ingested, no-checkout, no-manifest, ingest-error, and imported.
FR-4 Current inventory queries
The service shall return:
- all snapshots, optionally filtered by repository;
- a snapshot and its entries;
- entries from the latest snapshot per repository with existing State Hub
filters (
ecosystem,license_spdx,is_direct,is_dev); - the latest repository SBOM view;
- fleet and per-repository freshness metadata.
FR-5 Licence report
The extraction release shall group latest-snapshot entries by SPDX licence text, identify simple copyleft-family triage matches, and count/list direct non-development matches. The API and documentation shall label this as a signal rather than a complete SPDX expression or legal-policy evaluation.
FR-6 Bounded catch-up
GET /sbom/catch-up?limit=N shall:
- default N to 3 and constrain it to 1..25;
- consider only active/in-scope repositories;
- use a configurable stale threshold, initially 30 days;
- order never-attempted repositories first, then oldest attempt, then slug for deterministic ties;
- return no more than N repositories;
- include
stale_count,never_count,total_count, and effectivelimit; - return per target
repo_slug,last_sbom_at,sbom_age_days,has_sbom, andcheckout_availablewhen known.
FR-7 Bounded ingest and skip
A repository ingest operation shall use the registered checkout unless an explicit authorized path is supplied. It shall create one of these terminal outcomes:
ingested: supported sources parsed and snapshot stored;no-checkout: no reachable checkout;no-manifest: checkout exists but no supported source exists;ingest-error: one or more sources could not be parsed.
Every outcome advances the repository's last-attempt time. Only ingested
advances last-success time. This prevents a permanently unavailable repository
from remaining first forever without falsely claiming a successful SBOM.
FR-8 Compatibility
During cutover, SBOM Nexus shall preserve the response intent of State Hub's:
POST /sbom/ingest/;GET /sbom/;GET /sbom/{repo_slug};GET /sbom/snapshots/and/sbom/snapshots/{id};GET /sbom/report/licences/.
Differences required for provenance or correctness shall be additive and documented. State Hub may proxy these routes until callers move.
FR-9 Historical migration
An import tool shall read historical State Hub snapshots in chronological order and recreate their repository association, timestamp, source, entries, and legacy identifier provenance. Import shall be idempotent. Migration must be verified before State Hub rows are retired.
FR-10 Operator interfaces
The repository shall provide commands to run the API, scan a checkout locally, run tests/lint, and import State Hub history. Configuration shall be supplied through explicit environment variables and contain no secrets in source.
7. Data model
Repository 1 ─── * Snapshot 1 ─── * Entry
│
└── source records/errors/provenance
- Repository: slug, active, checkout path, last attempt/success, last status.
- Snapshot: UUID, repository, timestamp, status/source, source revision, entry count, legacy id, structured errors.
- Entry: package name/version, ecosystem, licence text, direct/dev flags, source path.
SQLite remains supported for extraction tests and single-node development. Production uses PostgreSQL through the same transactional store and managed Alembic migrations. Production cutover still requires backup/restore evidence and explicit retention settings.
8. API contract
| Method | Path | Purpose |
|---|---|---|
| GET | /state/health |
Liveness and store readiness |
| PUT | /repositories/{slug} |
Upsert the minimum Repo Manager projection |
| GET | /repositories/ |
List repository SBOM status |
| GET | /sbom/catch-up?limit=N |
Select bounded oldest-stale targets |
| POST | /sbom/{slug}/ingest |
Scan registered checkout and record terminal outcome |
| POST | /sbom/{slug}/skip |
Record an explicit bounded skip outcome |
| POST | /sbom/ingest/ |
State Hub-compatible entry ingest |
| GET | /sbom/ |
Latest entries with filters |
| GET | /sbom/{slug} |
Latest repository view |
| GET | /sbom/snapshots/ |
Snapshot history |
| GET | /sbom/snapshots/{id} |
Snapshot detail |
| GET | /sbom/report/licences/ |
Latest-snapshot licence report |
9. Quality and operational requirements
- Catch-up ordering and bounds are covered by deterministic tests.
- A recorded skip demonstrably advances queue position.
- Ingest is transactional: a snapshot and its entries appear together.
- Paths returned by APIs are repository-relative unless explicitly operator-only.
- Parser failure in one source is visible; it must not silently produce a successful snapshot.
- The API must not follow paths supplied by an untrusted remote caller in the production profile; registered checkout paths are operator-managed inputs.
- Structured logs and metrics shall distinguish attempts, successes, skips, errors, duration, and entry counts before production cutover.
- Backups and a restore drill are required before historical authority moves.
10. Migration and rollout
- Establish this repo, intent, PRD, inventory, package, and tests.
- Implement the compatible API, scanner, persistence, and catch-up contract.
- Register/synchronize repository projections from Repo Manager.
- Import and reconcile State Hub history; compare repository/snapshot/entry counts and sampled licence reports.
- Put State Hub
/sbom/*behind a proxy/strangler and retarget MCP/dashboard. - Enable Activity Core's bounded ingest side effect, then its disabled daily definition; retain the weekly flood disabled.
- Observe at least two successful production fires and verify at most N terminal outcomes per fire.
- Remove State Hub ownership only after compatibility and retention gates pass.
11. Acceptance criteria
- Existing parser fixtures and State Hub-compatible route behaviors pass in SBOM Nexus.
limit=3returns exactly the three oldest eligible stale repositories when at least three exist, with never-attempted repositories first.- Recording a no-checkout or no-manifest outcome removes that repository from the head of the immediate queue.
- Historical State Hub snapshot and entry counts reconcile, with documented treatment of any invalid legacy row.
- State Hub is no longer the permanent SBOM store.
- Activity Core performs no more than N ingests/skips per fire and spawns zero per-repository catch-up tasks.
last_sbom_atcompatibility projections are derived from a documented Nexus timestamp and remain truthful.
12. Deferred product decisions
- Canonical component identity and deduplication across ecosystems.
- Full SPDX expression parsing and policy ownership.
- SPDX/CycloneDX import/export profiles and conformance level.
- Vulnerability, VEX, attestation, signing, and deployment correlation.
- Artifact Store integration and snapshot retention policy.
- Multi-tenant authorization via Tenant Engine and Flex Auth.
- Whether
last_sbom_atcompatibility maps to last attempt or last successful inventory; Nexus retains both so consumers can migrate to precise fields.