SBOM POC Discovery Findings Runbook
This runbook captures first-iteration findings for SBOM-based catalog insights implemented in:
- Repository:
ministryofjustice/ministry-of-justice-developer-portal - Implementation branch:
feat/product-catalog-sbom-report
Overview
The POC generates product-level catalog insights from GitHub team repositories and displays them in the Developer Portal products experience.
The implementation has two main stages:
- Catalog generation (data collection, aggregation, and report writing)
- Portal display (products list and product detail pages)
Configured App
Configured app name:
- MoJ Dev Portal SBOM App
Purpose:
- Read-only app used to generate Developer Portal catalog insights from team repositories, SBOM, and Dependabot/code scanning data.
Where it is used:
- Workflow token generation in
.github/workflows/catalog-insights.yml - API calls in
scripts/catalog-insights/gateways/github-sbom-gateway.mjs
How Catalog Is Generated
Primary orchestration entrypoint:
scripts/get_catalog_insights.mjs
Generation flow:
- Reading product metadata from
content/products/products.json - Resolving eligible products using:
catalogInsightsEnabled === true- non-empty
teamName
- Resolving team repositories from:
teamOrg+teamName(default org isministryofjusticeifteamOrgis not set)
- For each resolved repository, collecting:
- SBOM from GitHub Dependency Graph SBOM endpoint
- optional Dependabot alerts
- optional code scanning alerts
- deployment-backed SHA/ref metadata (when available)
- Aggregating to product-level report data:
- status, package totals, ecosystems, licenses
- deduplicated package inventory across repositories
- aggregated vulnerabilities and code scanning summaries
- Applying display policy flags to include/omit selected sections
- Writing generated files under
content/products/catalog_reports/ - Removing legacy files that are no longer used (
sbom-reports.json,catalog-report.json,sbom-sources.json)
Core implementation files:
scripts/get_catalog_insights.mjsscripts/catalog-insights/application/catalog-insights-service.mjsscripts/catalog-insights/application/catalog-report-service.mjsscripts/catalog-insights/application/catalog-display-policy.mjsscripts/catalog-insights/gateways/github-sbom-gateway.mjs
High-Level Design
flowchart TB
A[products.json] --> B[resolve enabled products]
B --> C[resolve team repos]
C --> D[fetch SBOM per repo]
C --> E[fetch Dependabot alerts if enabled]
C --> F[fetch code scanning alerts if enabled]
C --> G[resolve deployment ref]
D --> H[aggregate report per product]
E --> H
F --> H
G --> H
H --> I[apply display policy flags]
I --> J[write catalog_reports/*.json]
J --> K[Dev Portal UI]
Triggers and Execution Paths
Scheduled or manual workflow
Workflow file in implementation branch:
.github/workflows/catalog-insights.yml
Trigger modes:
- Scheduled: every Monday at 06:00 UTC
- Manual:
workflow_dispatch
The workflow:
- Installs dependencies (
npm ci --ignore-scripts) - Generates a GitHub App token using:
DEV_PORTAL_GH_APP_IDDEV_PORTAL_GH_APP_PRIVATE_KEY
- Runs
npm run catalog:sync - Uploads generated
content/products/catalog_reports/artifacts - Creates an automated PR with refreshed report files
Local or manual execution
Run from the ministry-of-justice-developer-portal repository on feat/product-catalog-sbom-report:
export GITHUB_TOKEN=<github-token-with-required-access>
make catalog-insights
Equivalent npm command:
npm run catalog:sync
Optional UI depth control used by the product details page:
export SBOM_MAX_DEPTH=2
Prerequisites
Product enablement requirements
In this POC branch, catalog generation is team-based (not sbomOwner/sbomRepo based).
Each product entry that should be included must define:
catalogInsightsEnabled: trueteamName: "<github-team-slug>"
Recommended optional flags:
teamOrg(defaults toministryofjusticewhen omitted)catalogDeploymentEnvironmentcatalogShowVulnerabilitiescatalogShowCodeScanning
Example product configuration in content/products/products.json:
{
"slug": "example-product",
"catalogInsightsEnabled": true,
"teamName": "example-team-slug",
"teamOrg": "ministryofjustice",
"catalogDeploymentEnvironment": "none",
"catalogShowVulnerabilities": true,
"catalogShowCodeScanning": true
}
Products without catalogInsightsEnabled: true and teamName are skipped.
Current flag flexibility (include or omit sections)
catalogShowVulnerabilitiestrue: vulnerability data is fetched and shown in report/UI.falseor unset: vulnerabilities are omitted from generated report output and hidden in UI tabs/overview rows.
catalogShowCodeScanningtrue: code scanning data is fetched and shown in report/UI.falseor unset: code scanning data is omitted from generated report output and hidden in UI tabs/overview rows.
catalogDeploymentEnvironment- String value like
prod: deployment lookup tries this environment first, then falls back to unfiltered deployments. none: explicitly disables environment filtering and uses unfiltered deployment lookup.- Unset: default deployment environment comes from
CATALOG_DEPLOYMENT_ENV(defaultprod).
- String value like
Authentication requirements
For local/manual runs:
GITHUB_TOKENmust be set
For workflow runs:
DEV_PORTAL_GH_APP_IDsecretDEV_PORTAL_GH_APP_PRIVATE_KEYsecret
Configured app:
- MoJ Dev Portal SBOM App
Required GitHub access
The token/app must be able to query:
- Repository dependency graph SBOM endpoint
- Dependabot alerts endpoint
- Code scanning alerts endpoint
- Team repository listings and deployments metadata used by catalog insights
Outputs
Generated report files are written to:
content/products/catalog_reports/index.jsoncontent/products/catalog_reports/<product-slug>.json
Legacy files are removed during run:
content/products/sbom-reports.jsoncontent/products/catalog-report.jsoncontent/products/sbom-sources.json
How Details Are Displayed In Developer Portal
Catalog insight data is rendered in two places:
- Products list cards (
/products) - Product detail tabs (
/products/[slug])
Products list page
On src/app/products/page.tsx, each product card can show catalog summary data when report data exists:
- Catalog status
- Repository count
- Package count
- Generated timestamp
- Error text (when present)
Card rendering is implemented in src/components/ProductCard.tsx.
Filters that affect card visibility on this page:
- Category radio filters (
all,platforms,apis,tools,sbom,security) - Multi-select tag filters
Intended use:
- Quick health snapshot per product
- Fast narrowing before viewing full insight tabs
Product detail page
On src/app/products/[slug]/page.tsx, catalog insights are shown only when:
product.catalogInsightsEnabled === true- report data exists for the product slug
Detail page sections, intent, and filters:
- Overview
- Intended use: product-level summary and readiness signal.
- Shows: status, completed/failed/pending counts, team, generation date, repository visibility totals, package total, ecosystem/license summary, optional security rollups.
- Filters: none.
- Repositories
- Intended use: repository-by-repository operational view.
- Shows: repo status, package count, ecosystems, deployment SHA/ref/environment/date.
- Filters: repository status dropdown (
all+ statuses present in data such aspublic,private,internal,archived,unknown).
- Ecosystems
- Intended use: package ecosystem composition.
- Shows: ecosystem names and package counts.
- Filters: none.
- Licenses
- Intended use: licensing profile and risk visibility.
- Shows: license names and package counts.
- Filters: none.
- Vulnerabilities
- Intended use: Dependabot vulnerability triage.
- Visibility: shown only when
catalogShowVulnerabilities === true. - Shows: grouped package-level severity, observed/fixed versions, CVE/CVSS, repository.
- Filters: severity dropdown and repository dropdown.
- Code scanning
- Intended use: static-analysis alert triage.
- Visibility: shown only when
catalogShowCodeScanning === true. - Shows: severity, rule, repository, location, tool, alert link.
- Filters: severity dropdown and repository dropdown.
- Packages
- Intended use: dependency inventory and footprint across repositories.
- Shows: package metadata (version, ecosystem, license, purpose, supplier) and associated repositories.
- Filters: ecosystem dropdown.
Feature flags that control include/omit behavior:
catalogShowVulnerabilitiestrue: vulnerabilities are fetched and the Vulnerabilities section is shown.falseor unset: vulnerabilities are omitted from report output and hidden in UI.
catalogShowCodeScanningtrue: code scanning alerts are fetched and the Code scanning section is shown.falseor unset: code scanning data is omitted from report output and hidden in UI.
Data path from generation to UI:
content/products/catalog_reports/index.jsonfeeds product-card summary data.content/products/catalog_reports/<slug>.jsonfeeds product detail tabs.- Page logic maps data by slug and applies feature-flag visibility rules.
Troubleshooting
1. SBOM fetch is skipped
Symptom:
- Logs contain:
Skipping SBOM fetch: GITHUB_TOKEN is not set.
Action:
- Export
GITHUB_TOKENbefore running locally. - For workflow runs, check GitHub App token generation step succeeded.
2. Workflow key parsing fails
Symptom:
- Workflow fails in “Prepare GitHub App private key” or “Generate GitHub App token”.
Action:
- Re-check
DEV_PORTAL_GH_APP_PRIVATE_KEYformatting in GitHub secrets. - Confirm the key matches
DEV_PORTAL_GH_APP_ID.
3. Empty or partial product reports
Symptom:
- Product report exists but missing expected repositories or package data.
Action:
- Confirm
catalogInsightsEnabled: trueand a validteamNameinproducts.json. - Confirm the repository has dependency graph data available.
- Re-run workflow manually and inspect per-product output in generated JSON files.
4. Security endpoints are skipped
Symptom:
- Warnings appear for Dependabot/code-scanning fetch calls with HTTP
403or404.
Action:
- Validate token/app access to repository security endpoints.
- Confirm security features are enabled for target repositories where expected.
5. Product not included in generated catalog reports
Symptom:
- Product does not appear in generated
catalog_reports/index.jsonor product-specific report file is missing.
Action:
- Confirm
catalogInsightsEnabled: true. - Confirm
teamNameexists and matches a valid GitHub team slug. - Confirm token/app can list team repositories.
- Re-run catalog workflow manually and inspect logs for team repository resolution.
Operational Notes
- This runbook is specific to the POC branch implementation and should be updated when changes are promoted to
main. - Generated report files are intended to be reviewed through the workflow-created PR before merge.
- Prefer running the scheduled workflow for regular refresh and manual dispatch for validation or incident response.
- Keep this runbook aligned with the implementation branch while POC work remains outside
main.
Support
- Primary support: Developer Experience Team
- Slack channel:
#developer-experience-alerts