Skip to content

docs(adr): add ADR 00022 for advisory-based vendor remediation recommendations - #2620

Draft
ruromero wants to merge 6 commits into
guacsec:mainfrom
ruromero:TC-6011
Draft

ruromero wants to merge 6 commits into
guacsec:mainfrom
ruromero:TC-6011

Conversation

@ruromero

@ruromero ruromero commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds docs/adrs/00022-advisory-based-vendor-remediation.md
  • Documents design decisions for the Vendor Remediation Recommendations feature (TC-5844)
  • Closes two open items deferred from ADR 00008: advisory-based ingest and configurable recommendation patterns
  • Status: ACCEPTED

Changes

  • Context: explains limits of the existing regex heuristic in /purl/recommend and how OSV advisories from Lightwell encode authoritative remediation data via backport_base_version + fixed event
  • Decision: trusted_source: bool importer flag; ingest-time recommendation entity creation; DB JOIN serving; backward-compatible existing endpoint
  • Alternatives considered: rejected separate recommendation_config entity and regex-based ingest-time computation
  • Consequences: ecosystem-agnostic recommendations, zero per-query overhead, full provenance via advisory FK

Test plan

  • ADR file renders correctly in GitHub
  • Format matches existing ADRs (00008, 00021)
  • Open items from ADR 00008 are explicitly addressed in Status section
  • Cross-checked against TC-5996 (trusted_source flag), TC-5997 (recommendation entity), TC-5998 (OSV ingestor hook)

Implements TC-6011

🤖 Generated with Claude Code

Summary by Sourcery

Document a configurable, query-time approach for vendor remediation recommendations while deferring advisory-backed and ingest-time recommendation designs pending further resolution of their operational trade-offs.

Enhancements:

  • Document the design for configurable vendor remediation recommendation patterns and the trade-offs between query-time and ingest-time processing.
  • Record the limitations of advisory, CSAF, VEX, SBOM, pre-release, and digest-based recommendation sources, deferring unresolved approaches to future design work.

Documentation:

  • Add ADR 00022 describing the configurable recommendation-pattern approach for vendor remediation relationships and its open problems.

…endations

Documents the design decisions for the Vendor Remediation Recommendations
feature: trusted_source flag on importers, recommendation entity schema,
ingest-time extraction from OSV advisories, and DB JOIN query integration.
Closes open items deferred by ADR 00008.

Implements TC-6011

Assisted-by: Claude Code
@sourcery-ai

sourcery-ai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds accepted ADR 00022 defining an ingest-time, trusted-source workflow for creating provenance-backed vendor remediation recommendations from OSV advisory data, serving them through database joins while retaining the existing heuristic endpoint as a backward-compatible fallback.

Sequence diagram for trusted-source advisory recommendation ingestion

sequenceDiagram
    participant Importer
    participant Ingestor
    participant Advisory
    participant Database
    participant Recommendation

    Importer->>Ingestor: ingest advisory
    Ingestor->>Importer: trusted_source
    alt trusted source and backport_base_version present
        Ingestor->>Database: resolve upstream and vendor versioned_purl
        alt both versions resolved
            Ingestor->>Recommendation: create recommendation
            Recommendation->>Advisory: store advisory foreign key
            Recommendation->>Database: persist unique remediation pair
        end
    end
Loading

Entity relationship diagram for advisory-backed recommendations

erDiagram
    ADVISORY ||--o{ RECOMMENDATION : establishes
    VERSIONED_PURL ||--o{ RECOMMENDATION : upstream_version
    VERSIONED_PURL ||--o{ RECOMMENDATION : vendor_version

    ADVISORY {
        UUID id PK
    }
    VERSIONED_PURL {
        UUID id PK
    }
    RECOMMENDATION {
        UUID id PK
        UUID upstream_versioned_purl FK
        UUID vendor_versioned_purl FK
        UUID advisory FK
    }
Loading

File-Level Changes

Change Details Files
Documents the accepted architecture for extracting vendor remediation recommendations from authoritative OSV advisories.
  • Defines trusted_source importer configuration, defaulting to false, with an admin override for manual uploads.
  • Specifies ingest-time extraction from backport_base_version and fixed events, resolution to versioned PURLs, and provenance-linked recommendation creation.
  • Defines the recommendation schema, uniqueness constraint, and advisory foreign key for audit and reprocessing.
  • Specifies direct database JOIN consumption, a re-index path, and preservation of the existing heuristic endpoint for backward compatibility.
docs/adrs/00022-advisory-based-vendor-remediation.md
Captures the rationale and trade-offs behind replacing heuristic remediation inference with advisory-authoritative data.
  • Explains the ecosystem, accuracy, and maintenance limitations of the existing regex heuristic.
  • Addresses the deferred ADR 00008 items regarding configurable patterns and advisory-based ingest.
  • Rejects a separate configuration entity, regex-based ingest computation, and per-query heuristic evaluation.
  • Records consequences including ecosystem independence, provenance, operational prerequisites, and fallback behavior.
docs/adrs/00022-advisory-based-vendor-remediation.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="docs/adrs/00022-advisory-based-vendor-remediation.md" line_range="79-81" />
<code_context>
+
+For each OSV advisory ingested from a trusted source, the ingestor hook:
+
+1. Checks `database_specific.backport_base_version` — if absent, skips the advisory.
+2. Extracts the upstream version (`backport_base_version`) and the vendor version (from
+   the `fixed` event in the affected ranges).
+3. Resolves both versions to `versioned_purl` records in the database. If either cannot
+   be resolved (the PURL has not been ingested), the recommendation record is skipped.
</code_context>
<issue_to_address>
**issue (bug_risk):** The extraction design does not define which `fixed` event to select when an advisory contains multiple affected ranges or multiple fixed events, so one advisory can yield several competing vendor versions or an arbitrary remediation pair rather than the claimed unambiguous pair.

**Triggers:** When a trusted OSV advisory contains more than one affected range or more than one `fixed` event.

**Suggested fix:** Specify the selection and validation rules for fixed events, or create a recommendation for each explicitly valid upstream/vendor pair.
</issue_to_address>

### Comment 2
<location path="docs/adrs/00022-advisory-based-vendor-remediation.md" line_range="87-100" />
<code_context>
+
+```
+recommendation
+├── id                        UUID, primary key
+├── upstream_versioned_purl   FK → versioned_purl (the upstream package version)
+├── vendor_versioned_purl     FK → versioned_purl (the vendor/backport package version)
+├── advisory                  FK → advisory (provenance — which advisory established this)
+└── (unique constraint on upstream_versioned_purl + vendor_versioned_purl)
+```
+
+The advisory foreign key provides full provenance: operators can trace every recommendation
+back to the advisory that established it, and re-ingest or retract recommendations by
+reprocessing the advisory.
+
+### Query integration via DB JOIN
</code_context>
<issue_to_address>
**issue (bug_risk):** The unique constraint permits only one recommendation for an upstream/vendor PURL pair, while the advisory foreign key claims to preserve which advisory established the recommendation. When two trusted advisories establish the same pair, the second provenance record cannot be stored, and reprocessing or retracting one advisory cannot be done without affecting the other.

**Triggers:** When multiple trusted advisories establish the same upstream/vendor version pair.

**Suggested fix:** Either allow multiple provenance rows per pair, or separate the unique recommendation pair from a many-to-many advisory provenance relation and define deletion/retraction semantics.

````suggestion
### Recommendation entity schema

```
recommendation
├── id                        UUID, primary key
├── upstream_versioned_purl   FK → versioned_purl (the upstream package version)
├── vendor_versioned_purl     FK → versioned_purl (the vendor/backport package version)
├── advisory                  FK → advisory (provenance — which advisory established this)
└── (unique constraint on upstream_versioned_purl + vendor_versioned_purl + advisory)
```

Multiple provenance rows may exist for the same upstream/vendor pair, with at most one row
per advisory. Re-ingesting an advisory upserts only its own provenance rows. Retracting an
advisory deletes only rows linked to that advisory; the recommendation remains effective
while at least one other advisory provenance row exists.
````
</issue_to_address>

### Comment 3
<location path="docs/adrs/00022-advisory-based-vendor-remediation.md" line_range="9-12" />
<code_context>
+
+ACCEPTED
+
+Closes open items from [ADR 00008](00008-purls-recommendation.md):
+
+* *"Provide a way to return different patterns of recommended purls"* — resolved via the
+  `trusted_source` flag on importers (source-scoped designation, not pattern-based matching).
+* *"Ingest remediation information from advisories and use them to provide more data to
+  results of this endpoint (requires a separate ADR)"* — this is that ADR.
</code_context>
<issue_to_address>
**issue:** The ADR says the deferred item to provide different recommendation patterns is resolved, but `trusted_source` only marks an entire advisory feed as trusted and does not provide configurable patterns or let consumers select different recommendation schemes. The documented decision therefore does not satisfy the open item's stated behavior.

**Triggers:** When deployments need different vendor/versioning schemes or consumers need different recommendation patterns.

**Suggested fix:** Describe this as resolving the advisory-ingest item only, or document a separate mechanism for configurable pattern-based recommendations.

```suggestion
Closes the open advisory-ingest item from [ADR 00008](00008-purls-recommendation.md):
```
</issue_to_address>

Sourcery assessment

Approval pending. 3 findings to address first.

Blocking findings: docs/adrs/00022-advisory-based-vendor-remediation.md:81, docs/adrs/00022-advisory-based-vendor-remediation.md:100, docs/adrs/00022-advisory-based-vendor-remediation.md:12


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docs/adrs/00022-advisory-based-vendor-remediation.md Outdated
Comment thread docs/adrs/00022-advisory-based-vendor-remediation.md Outdated
Comment thread docs/adrs/00022-advisory-based-vendor-remediation.md Outdated
- Fix Lightwell URL to https://www.redhat.com/en/lightwell
- Narrow Status section: trusted_source does not resolve the
  configurable-patterns open item from ADR 00008; only the
  advisory-ingest item is closed here
- Specify fixed-event selection: iterate all affected ranges,
  extract one pair per fixed event, skip ranges without fixed
- Fix unique constraint: (upstream, vendor, advisory) triple
  to allow multiple advisory provenances per recommendation pair,
  with upsert/retract semantics per advisory

Implements TC-6011

Assisted-by: Claude Code

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sourcery assessment

Approved.

The configurable-patterns item is resolved by supersession, not deferral:
advisory-based ingest replaces pattern-matching as the authoritative
mechanism. The regex heuristic is retained for backward compatibility
and is a deprecation candidate.

Implements TC-6011

Assisted-by: Claude Code
@ruromero
ruromero marked this pull request as draft September 3, 2026 11:14
- Add Mechanism 2: query-time trusted-source version-prefix matching
  covers CSAF/RHSA/SBOM formats where backport_base_version is absent
- Document CSAF advisory format limitations (no explicit upstream mapping)
- Add Open Items: digest-based recommendation for same-PURL/different-binary
  case, deferred to future ADR with explanation of when digests are needed
- Add alternatives: OSV-only without query-time fallback (rejected)
- Clarify relationship between the two mechanisms and query latency tradeoffs

Implements TC-6011

Assisted-by: Claude Code
…ndation_patterns

Mechanism 2 now uses operator-supplied regex patterns on the importer config
instead of a hardcoded version-prefix match or ecosystem-specific parsers.
Patterns are scoped to trusted-source importers, require no code change to
support new vendors, and directly close the ADR 00008 open item on configurable
patterns. Documents scope/limitations and pre-release edge cases.

Implements TC-6011

Assisted-by: Claude Code
Status changed from ACCEPTED to PROPOSED. The only decided change is
replacing the hardcoded recommendation regex with configurable
recommendation_patterns per importer (query-time). All advisory-based
ingest-time approaches are deferred: Lightwell backport_base_version is
non-standard OSV and downstream-only; CSAF/SBOM carry no explicit upstream
mapping; ingest-time regex hits a staleness-on-config-change problem with
no clean resolution; digest-based recommendations are a separate problem.
Documents the full design space explored and why each was deferred.

Implements TC-6011

Assisted-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant