Lightwell vulnerabilities live in the same backend as the rest of content-sources: database migrations, compose, and tests follow the normal app workflow. This doc covers the lightwell-specific seed data, sqlc store, schema reference, and read API.
Use the standard dev environment (see README.md): copy configs/config.yaml.example to configs/config.yaml, then:
make compose-up
If you hit migration issues on an old local DB (e.g. from superseded lightwell migrations during development), reset and re-migrate:
make test-db-migrations
The seed script loads mock vulnerabilities into two demo customers (demo-customer-1, demo-customer-2). Statuses include On Hold and Unremediated. Each Unremediated row stores one supported resolution_reason, and the list API returns the customer explanation for that selection. Two rows set duplicate_of to a canonical vulnerability_id (not present in the mock):
psql "sslmode=disable dbname=content user=content host=localhost port=5433 password=content" -f db/seeds/lightwell_vulnerabilities.sql
Or through the compose postgres container:
docker compose exec -T postgres-content psql "sslmode=disable dbname=content user=content host=localhost port=5432 password=content" -f - < db/seeds/lightwell_vulnerabilities.sql
Adjust connection parameters to match your configs/config.yaml if they differ from the compose defaults.
Advisories and the package mirror are loaded by scripts/create_lightwell_repo.sh after it creates the Pulp repositories and imports them. That script inserts one advisory (and a release row per published_versions entry) only for seed rows whose stage is Lightwell Network, using the vulnerability purl as package_name and component_version as package_version. Java advisories are attached to lightwell/java/remediated or lightwell/java/predisclosure, Python advisories to lightwell/python/remediated or lightwell/python/predisclosure, and JavaScript advisories to lightwell/javascript/remediated. See Lightwell packages:
./scripts/create_lightwell_repo.sh
With the API running, authenticated clients can call:
GET /api/content-sources/v1/lightwell/beacon/vulnerabilities/customers/ — distinct customer IDsGET /api/content-sources/v1/lightwell/beacon/vulnerabilities/ltwlsupt-ticket-ids/?customer_id=demo-customer-1 — distinct Lightwell support ticket IDs for a customerGET /api/content-sources/v1/lightwell/beacon/vulnerabilities/?customer_id=demo-customer-1 — filtered, paginated list with aggregatescustomer_id is required on the list and ltwlsupt-ticket-ids endpoints. Filters (severity, status, complexity, ltwlsupt_ticket_id, flag) accept comma-separated values. flag accepts embargo and duplicate (OR). search requires at least 2 characters when provided.
Jira workflow status is stored as a Beacon status. A published fix promotes Validation to Lightwell Network. Once stored, Lightwell Network stays Lightwell Network if a later sync would only move it back to Validation.
| Jira status | Stored as |
|---|---|
| New | Submitted |
| Backlog | Classified |
| To Do | Classified |
| In Progress | Fix in Progress |
| Review | Fix in Progress |
| On Hold | On Hold |
| Verified | Validation |
| Release Pending | Validation |
| Released | Validation |
| Closed | Validation |
| Anything else | Submitted |
Jira resolution can override that, or drop the issue. Won’t Do and Not a Bug are stored as Unremediated with resolution_reason set to the explanation. The database keeps the Jira selection; the list API returns the explanation sentence. Those resolution names are not stored.
| Jira resolution | Result |
|---|---|
| Done | Stored from the workflow status above. No explanation. |
| Won’t Do | Stored as Unremediated. Explanation comes from Lightwell Closure Reasoning Context. Selection Not a Customer is ignored and the issue is deleted. |
| Not a Bug | Stored as Unremediated. Explanation comes from VEX Justification. |
| Duplicate | Ignored. Deleted if it was stored before. |
| Obsolete | Ignored. Deleted if it was stored before. |
| Cannot Reproduce | Ignored. Deleted if it was stored before. |
| Won’t Fix | Ignored. Deleted if it was stored before. |
Ignored resolutions are logged at warning level with the message beacon_ignored_resolution, plus issue, resolution, and detail when the selection is Not a Customer.
Integration tests use the configured database and roll back per test:
CONFIG_PATH="$(pwd)/configs/" go test ./pkg/lightwell/db/store/... ./pkg/dao/... ./pkg/handler/...
Or via make (runs all pkg/ tests):
make test-unit
After changing pkg/lightwell/db/queries/*.sql or the migration schema:
make sqlc-generate-lightwell
This runs the sqlc version pinned in mk/sqlc.mk (the same pin used by the sqlcdiff CI job). Generated code is written to pkg/lightwell/db/store/.
sqlc uses pkg/lightwell/db/schema.sql (final table snapshot plus lightwell_filtered_vulnerabilities) rather than parsing rename migrations directly. Update that file when the lightwell schema changes. List/count queries share filters through that function because sqlc has no query fragments.