feat(downloads): verify versions from image SBOMs - #762
Closed
castrojo wants to merge 30 commits into
Closed
Conversation
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Digest-bound ORAS/Cosign collector: resolveImageDigest, discoverReferrers, verifyImageProvenance, pullSpdxReferrer, collectVerifiedImageSbom. EvidenceError with codes: image-not-found, missing-provenance, invalid-provenance, missing-sbom, ambiguous-sbom, invalid-sbom. Deterministic ORAS fixtures for dakota (SPDX+provenance) and gaming (no SPDX). Assisted-by: Claude Sonnet 4.5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 4.5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- verifyImageProvenance: remove || true; classify no-attestation messages as missing-provenance, all other cosign failures as invalid-provenance - discoverReferrers: wrap command failure as image-not-found; wrap JSON parse failure as invalid-sbom - pullSpdxReferrer: single finally block removes tempdir exactly once - Tests: replace double-invocation error-code patterns with single toThrow(expect.objectContaining(...)); add invalid-provenance, image-not-found, and malformed-JSON tests; assert rmSync call count is exactly 1 Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: claude-sonnet-5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- spdxPackageVersion: remove highest-version fallback; return undefined on ambiguity - compareVersions: parseInt instead of Number so '8-ogc1' parses as 8 not NaN - Fixture hash replaced with SHA-256 of empty string (unambiguous 64-hex value) - Tests updated: ambiguity regression, suffix ordering, renames highest-version test - scripts/update-dakota-versions.js: commit SBOM-only implementation so update-dakota-versions.test.ts passes from committed state alone Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Records ambiguity rule: spdxPackageVersion returns undefined on multi-version names - Records compareVersions NaN guard: use parseInt not Number for -ogc1 suffixes - Records fixture hash standard: SHA-256 of empty string - Records commit-order rule: implementation before tests that import it - Adds router entry in docs/SKILL.md Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- verifyRegistry now copies record.product onto every verified/unavailable image entry so productStatus(await verifyRegistry(...)) composes directly without caller mutation. - productStatus throws an explicit error on a missing product field instead of silently grouping under 'unknown'. - writeOutputsAtomically stages under destinationRoot/.tmp-* instead of os.tmpdir() so renameSync cannot fail with EXDEV across filesystems. - rmSync cleanup is scoped to the staging subdirectory only, not destinationRoot. - Added tests: product on verified/unavailable entries, compose test for productStatus+verifyRegistry, productStatus throws on missing product, mkdtempSync prefix assertion, cleanup scope assertion, --check-only semantics (required unavailable nonzero, optional omitted zero). Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mmit ProductVersionCard ORAS CLI --descriptor returns JSON natively; --format json is rejected. Regenerated dakota-versions.json via live wrapper (cosign predicate mismatch produces correct unavailable shape). Commits untracked ProductVersionCard.vue required by SectionPicker import. Assisted-by: Claude Sonnet 4.5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use '--type https://slsa.dev/provenance/v1' instead of the short alias 'slsaprovenance'. Live evidence confirms images attest the full URI; the short alias causes 'none of the attestations matched the predicate type' rejection. Both Dakota and Dakota NVIDIA now verify successfully and public/dakota-versions.json is regenerated with real image/SBOM digests. Assisted-by: claude-opus-4.8 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a static x86-64-v3 fallback when the current public JSON lacks packages.baseline so regenerated Dakota metadata keeps the hardware baseline. Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace documentation-cache fetching with direct OCI SBOM verification via the shared orchestrator. Stable values come from verified Syft artifacts on bluefin:stable and bluefin-nvidia-open:stable. LTS streams are status: unavailable until they publish SPDX referrers. ImageChooser now gates version chips on status === verified, preventing unknown or stale values from rendering. The spdx-version-extractor accepts both SPDX versionInfo and Syft version fields. Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…At and versionInfo regression - Strip epoch prefix and .fcNN/.elNN dist-tag in normalizeUserVersion - Serialize checkedAt in stream-versions.yml; update ImageChooser typing - Add YAML serialization test asserting no literal unknown - Add versionInfo precedence regression test in shared extractor - Update sbom-version-extraction skill with Bluefin source and rules Assisted-by: Claude Sonnet 4.6 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 4.6 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Consolidate SBOM verification into a single production command (npm run update:image-versions) that verifies the registry once, projects both Bluefin and Dakota version data, and atomically writes all three outputs: stream-versions.yml, dakota-versions.json, and sbom-audit.json. Switch update-content.yml to daily schedule, add cosign installer, and add deduplicated SBOM issue management via buildSbomIssuePlan. Add sbom-audit.json to all cache save/restore paths for parity. Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
verifyRegistry no longer skips pendingSbom records — all 9 registry entries are attempted and appear in audit.images with status, required flag, and errorCode/error when failing. productStatus distinguishes required vs optional unavailable: required unavailable → product unavailable, only optional → degraded. buildSbomIssuePlan deduplicates by title and lists all affected images in a single issue body when multiple share the same failure type. --check-only exits nonzero on ANY unavailable including optional. Assisted-by: Claude Sonnet 4 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add image version registry, SBOM sources, fail-closed behavior, and live-check commands to content-maintenance and validation skills. Update content-map with generated version data entries. Fix ImageChooser.vue type narrowing for StreamVersions access. Assisted-by: Claude Sonnet 4.5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Auto-fix import sorting, brace style, and manually split multi-statement lines to satisfy style/max-statements-per-line rule. Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ppings Ambiguity was extracted and then dropped: a required field that resolved to two versions silently disappeared from a "verified" image, and the audit kept no record of it. Every entry now carries ambiguous and rejected evidence. Ambiguous or missing required fields make the image unavailable; ambiguous or missing optional fields degrade it, keep the verified values, omit the unresolved field, and alert. Unavailable entries no longer carry values at all, so no projection can leak them; projections accept degraded evidence. Public files keep the verified/unavailable contract the components gate on. Live evidence resolves three of the four known ambiguities: Dakota mesa pins freedesktop-sdk.bst:extensions/mesa/mesa.bst (26.0.6), Dakota systemd pins gnome-build-meta.bst:core-deps/systemd-base.bst (260.2), and Bluefin podman pins foundBy rpm-db-cataloger with the epoch stripped at projection. Bluefin mesa reports two builds from one cataloger, so it stays optional, audited, degraded, and omitted rather than guessed. Trimmed fixtures from the published SBOMs pin each selector. Tooling failure is now distinct from evidence failure. A missing binary, timeout, throttled or unreachable registry, or malformed tool output raises ToolingError and aborts before any output, cache, or deployment; only a genuinely absent image, missing SBOM, or rejected provenance sanitizes a field. Unrecognised tool failures block, because "absent" and "unreachable" cannot be told apart and only one is safe to publish. An explained-field-loss guard refuses to promote any output that drops a field the audit does not explain. Records with pendingSbom or an empty package map stay unavailable with pending-mapping even once their image publishes an SPDX referrer, retaining the resolved digests; publication is not a reviewed mapping. The github-script step imported a relative path, which resolves against the action bundle rather than the checkout and would have thrown at runtime. The logic moved into scripts/lib/sbom-issue-sync.js, loaded through pathToFileURL(path.join(process.cwd(), ...)); the policy test executes the real script bodies through a runner that reproduces the action's referrer semantics, with a negative control proving the old form still fails. Issue listing paginates instead of capping at one page, the generic run-failure issue is deduplicated by exact title, titles use the exact audit errorCode, and bodies carry the workflow run URL plus each image's last successful verification or "none recorded" — which is why the workflow now restores the live-data cache first, using the exact save path list. Documentation records the registry's real owner, the daily workflow as the scheduled live smoke against the manual read-only check, and resolves the spec's ambiguous maximum-acceptable-age requirement: daily checkedAt already proves evidence freshness, and image publication age measures release cadence, so no invented threshold is added. Assisted-by: Claude Sonnet 5 via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Carry last successful timestamps across repeated failures, pass projection status into Dakota field-loss checks, and route legacy update commands through the atomic orchestrator. Assisted-by: GPT-5.6 Sol via GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
Author
|
Closing because this work is intended to remain local for review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
npm run lint(0 errors; existing JSDoc warnings)npm run typechecknpm run test:gate(no new failures; 1222 tests)npm run build/,/dakota/, and/server/, including zero/server-versions.jsonrequestsNotes
/dakota/and/server/remain unlisted production entry points.