Skip to content

feat: add SRAC document validation foundation - #3271

Draft
devashridatta-dotcom wants to merge 3 commits into
guacsec:mainfrom
devashridatta-dotcom:poc/srac-ingestor
Draft

devashridatta-dotcom wants to merge 3 commits into
guacsec:mainfrom
devashridatta-dotcom:poc/srac-ingestor

Conversation

@devashridatta-dotcom

Copy link
Copy Markdown

Summary

Adds an experimental, read-only SRAC ingestion path to make the product-context use case in #3256 concrete.

The prototype:

  • recognizes and validates 0.2-draft SRAC JSON documents;
  • requires exact product and component pURLs (never name-only matching);
  • supports optional BOM-reference and digest constraints;
  • reports explicit matched, unmatched, ambiguous, and invalid correlation states;
  • preserves assertion source, evidence, review state, and the received document SHA-256;
  • stores assertions as product-scoped HasMetadata with key srac.safety-relevance; and
  • remains read-only: GUAC does not infer or approve a safety decision.

The HasMetadata representation is intentionally experimental so maintainers can evaluate the workflow without committing GUAC to a permanent ontology change.

Demonstration

docs/examples/srac/product-context.srac.json contains two synthetic products using the same component:

  • Product A: asserted safety-related / ASIL-B;
  • Product B: asserted not-safety-related.

docs/srac.md documents the correlation contract and an existing HasMetadata query for retrieving the product-scoped assertions.

Validation

go test -count=1 ./pkg/srac ./pkg/handler/processor/guesser ./pkg/handler/processor/srac ./pkg/ingestor/parser/srac ./pkg/ingestor/parser

All listed packages pass locally. Tests cover schema validation, product-context separation, matched, unmatched, ambiguous, digest-mismatch, document guessing, provenance preservation, and parser integration.

Scope

This PR does not add a native safety predicate to the GUAC ontology and does not claim that SRAC semantics are finalized. It is a small prototype for maintainer feedback on the ingestion extension point and graph representation.

Closes #3256 only if maintainers consider the prototype sufficient; otherwise, relates to #3256.

Signed-off-by: Devashri Datta <devashri.datta@gmail.com>
@devashridatta-dotcom

Copy link
Copy Markdown
Author

@gaganhr94 Thank you for encouraging this prototype and suggesting a fork-based implementation. The experimental read-only SRAC ingestor is now ready for maintainer review. Could you please review it, or have a GUAC maintainer add you as the formal reviewer? GitHub did not allow me, as a fork author, to use the reviewer-assignment control.

@gaganhr94
gaganhr94 self-requested a review October 6, 2026 20:02
@devashridatta-dotcom

Copy link
Copy Markdown
Author

The experimental SRAC ingestion prototype is working for the defined MVP scope.

The following tests pass locally:

go test -count=1 \
  ./pkg/srac \
  ./pkg/handler/processor/guesser \
  ./pkg/handler/processor/srac \
  ./pkg/ingestor/parser/srac \
  ./pkg/ingestor/parser

Validated behavior includes:

  • SRAC JSON document recognition and schema validation;
  • ingestion through a dedicated SRAC parser;
  • product-specific assertions for the same component;
  • preservation of source, evidence, review state, and document SHA-256;
  • exact pURL/version correlation without name-only matching;
  • explicit matched, unmatched, ambiguous, and digest-mismatch results; and
  • read-only projection into product-scoped GUAC HasMetadata.

Therefore, the prototype demonstrates that GUAC can parse and preserve externally authored SRAC safety context without creating or approving safety decisions.

Current limitation: the SRAC document is ingested directly. Automatic discovery through a CycloneDX externalReference, and future native CycloneDX safety-field mapping, remain follow-up work.

I would appreciate maintainer feedback on whether this separate-parser architecture is suitable for the MVP.

@devashridatta-dotcom

Copy link
Copy Markdown
Author

Thanks, Gagan. This is very helpful and aligns with the two-stage path I had in mind.

This draft PR currently implements the first case: a separate SRAC parser using the existing ingestion flow. For the initial prototype, I used product-scoped HasMetadata deliberately as a temporary representation so we could validate parsing, provenance preservation, and deterministic product/component correlation without immediately changing the GUAC ontology.

Based on your feedback in #3256, I propose evolving the MVP toward a dedicated safety-assertion model:

  • a standalone SRAC parser;
  • a safety-assertion database table/predicate linking a product context to a component;
  • fields for safety relevance, classification, rationale, lifecycle/review status, reviewer, evidence, source, and document digest;
  • GraphQL ingestion and read/query support; and
  • no autonomous safety decision creation—GUAC only stores and exposes externally authored assertions.

Later, the SPDX and CycloneDX parsers could map their native safety representations into the same internal model, avoiding separate query behavior for each input format.

For the first reviewable MVP, would you recommend:

  1. adding the dedicated database model and GraphQL layer to this PR while keeping REST as follow-up; or
  2. keeping this PR focused on parsing and opening a second PR for the database and API model?

My preference is GraphQL first, followed by REST only if there is a concrete endpoint requirement.

@devashridatta-dotcom

Copy link
Copy Markdown
Author

The proposed first-class database and GraphQL model has been separated into design draft #3272. This keeps this parser prototype reviewable while maintainers confirm the ontology and backend scope.

@devashridatta-dotcom devashridatta-dotcom changed the title feat: add experimental SRAC ingestion prototype feat: SRAC ingestion prototype Oct 6, 2026
Signed-off-by: Devashri Datta <devashri.datta@gmail.com>
@devashridatta-dotcom

Copy link
Copy Markdown
Author

CI follow-up:

  • Fixed the source-related lint failure by applying the repository's Prettier rules to docs/srac.md in commit c5c1cd97.
  • Re-ran the SRAC-focused Go test packages locally; they pass.
  • The previous integration failure was in the existing live deps.dev collector test Test_depsCollector_RetrieveArtifacts/foreign-types_package_cargo_package: the lookup for pkg:cargo/foreign-types@0.3.2 returned zero results within its polling window. The Tilt and E2E integration jobs passed, and this failing test does not exercise the SRAC parser or fixtures.

A fresh CI run has been triggered by the formatting fix. I have not changed the unrelated deps.dev test.

@gaganhr94 gaganhr94 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devashridatta-dotcom Thanks for putting this together, the parsing and validation pieces are a reasonable starting point.

As discussed in #3256 and agreed in the maintainers meeting, SRAC assertions need their own storage and ontology rather than being projected into HasMetadata. HasMetadata is a generic key/value predicate. Packing the component, classification, evidence, and review state into a JSON string means:

  • the component is never a node in the graph, so "what is the safety context for component X" can't be answered by a graph query, only by fetching every product's metadata and parsing the JSON client-side
  • none of the fields (status, reviewer, classification, evidence digests) are queryable or filterable

Comment thread pkg/ingestor/parser/srac/parser_srac.go Outdated
digest := sha256.Sum256(doc.Blob)
documentDigest := hex.EncodeToString(digest[:])

for _, assertion := range parsed.Assertions {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

srac.Correlate is never called from the ingestion path, so none of the matched/unmatched/ambiguous/invalid handling runs. Every valid assertion is ingested, and PkgMatchTypeSpecificVersion will create the product package node even if it doesn't exist in the graph yet. The PR description and docs say correlation is enforced, but it's only reachable from unit tests. In the reworked design this probably belongs in the certifier for out-of-order ingestion, but either way it has to be wired in.

Comment thread pkg/srac/model.go Outdated
func Correlate(assertion Assertion, candidates []Candidate) CorrelationResult {
var identifierMatches []Candidate
for _, candidate := range candidates {
if candidate.ProductPURL != assertion.Product.PURL || candidate.ComponentPURL != assertion.Component.PURL {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raw string comparison of pURLs will miss equivalent pURLs that differ only in qualifier order, type case, or encoding. Please normalize both sides (e.g. packageurl.FromString(...).ToString()) before comparing, the same way the rest of GUAC canonicalizes pURLs.

Comment thread pkg/srac/model.go Outdated
for _, candidate := range identifierMatches {
if digestsMatch(assertion.Component.Digests, candidate.Digests) {
matches = append(matches, candidate)
} else if len(assertion.Component.Digests) > 0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the candidate has no digest data at all, this reports invalid ("digest mismatch"). Missing data and conflicting data should be different outcomes. I'd expect unmatched (or a separate unknown state) when the candidate has no digests to compare.

@devashridatta-dotcom devashridatta-dotcom changed the title feat: SRAC ingestion prototype feat: add SRAC document validation foundation Oct 23, 2026
@devashridatta-dotcom

Copy link
Copy Markdown
Author

Addressed the review direction in commit 616a53d: removed the HasMetadata projection and unwired correlation path, added canonical pURL handling, and narrowed this PR to SRAC document validation. Graph ingestion and correlation will be implemented through the certifier after the first-class ontology in #3272 is approved.

@devashridatta-dotcom
devashridatta-dotcom marked this pull request as draft October 23, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SRAC proposal: ingest product-specific safety relevance assertions

2 participants