Skip to content

doc(adr): add ADR 00011 for CSAF remediation support#2179

Merged
dejanb merged 1 commit intomainfrom
adr/remediations
Jan 19, 2026
Merged

doc(adr): add ADR 00011 for CSAF remediation support#2179
dejanb merged 1 commit intomainfrom
adr/remediations

Conversation

@dejanb
Copy link
Contributor

@dejanb dejanb commented Dec 10, 2025

Propose ingesting CSAF remediation guidance and exposing it via APIs. Remediations provide actionable guidance (upgrade paths, workarounds) alongside vulnerability status information.

Assisted-by: Claude

Summary by Sourcery

Documentation:

  • Add ADR 00011 describing schema, ingestion flow, and API changes to support CSAF remediation guidance linked to vulnerability status records.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 10, 2025

Reviewer's Guide

Adds a new architecture decision record (ADR 00011) defining how CSAF remediation guidance will be modeled, stored, ingested, and exposed via existing status APIs, including schema, ingestion flow, and query patterns.

Sequence diagram for CSAF remediation ingestion flow

sequenceDiagram
    participant CsafIngestion as CsafIngestionService
    participant StatusCreator as StatusCreator
    participant ResolveCache as ResolveProductIdCache
    participant RemediationCreator as RemediationCreator
    participant DB as Database

    CsafIngestion->>StatusCreator: create_status_records(csaf_document)
    StatusCreator->>ResolveCache: resolve_product_ids(csaf_product_ids)
    ResolveCache-->>StatusCreator: product_id_to_status_mapping
    StatusCreator->>DB: insert_purl_status_records()
    StatusCreator->>DB: insert_product_status_records()
    StatusCreator-->>CsafIngestion: status_creation_result_with_mapping

    CsafIngestion->>RemediationCreator: create_remediations(csaf_remediations, mapping)
    RemediationCreator->>DB: insert_into_remediation(advisory_id, vulnerability_id, category, details, url, data)
    RemediationCreator->>DB: insert_into_remediation_purl_status(remediation_id, purl_status_ids)
    RemediationCreator->>DB: insert_into_remediation_product_status(remediation_id, product_status_ids)
    RemediationCreator-->>CsafIngestion: remediation_creation_result
Loading

Sequence diagram for API status query with remediations

sequenceDiagram
    actor Client
    participant Api as StatusApiService
    participant DB as Database

    Client->>Api: GET /v2/purl/{key}
    Api->>DB: SELECT purl_status_with_remediations(purl_key)
    DB-->>Api: purl_status_rows_with_joined_remediations
    Api->>Api: map_rows_to_PurlStatus_and_RemediationSummary
    Api-->>Client: PurlDetails_with_status_and_remediations

    Client->>Api: POST /v3/vulnerability/analyze
    Api->>DB: query_analysis_status_with_remediations(sbom_or_purls)
    DB-->>Api: analysis_rows_with_remediations
    Api->>Api: build_AnalysisResponse_with_PurlStatus_and_RemediationSummary
    Api-->>Client: AnalysisResponse
Loading

ER diagram for CSAF remediation schema additions

erDiagram
    advisory_vulnerability {
        UUID advisory_id
        VARCHAR vulnerability_id
    }

    remediation {
        UUID id
        UUID advisory_id
        VARCHAR vulnerability_id
        VARCHAR category
        TEXT details
        VARCHAR url
        JSONB data
    }

    purl_status {
        UUID id
        %% existing_columns
        TEXT existing_columns
    }

    product_status {
        UUID id
        %% existing_columns
        TEXT existing_columns
    }

    remediation_purl_status {
        UUID remediation_id
        UUID purl_status_id
    }

    remediation_product_status {
        UUID remediation_id
        UUID product_status_id
    }

    advisory_vulnerability ||--o{ remediation : has_remediation

    remediation ||--o{ remediation_purl_status : links_purl_status
    purl_status ||--o{ remediation_purl_status : is_target_of

    remediation ||--o{ remediation_product_status : links_product_status
    product_status ||--o{ remediation_product_status : is_target_of
Loading

Class diagram for remediation API models and status aggregation

classDiagram
    class RemediationSummary {
        Uuid id
        String category
        Option~String~ details
        Option~String~ url
        Option~JsonValue~ data
    }

    class PurlStatus {
        /* existing_fields */
        String status
        String vulnerability_id
        List~RemediationSummary~ remediations
    }

    class SbomStatus {
        /* existing_fields */
        String status
        String vulnerability_id
        List~RemediationSummary~ remediations
    }

    class PurlDetails {
        /* existing_fields */
        List~PurlStatus~ statuses
    }

    class SbomAdvisory {
        /* existing_fields */
        List~SbomStatus~ statuses
    }

    class AnalysisResponse {
        /* existing_fields */
        List~PurlStatus~ purl_statuses
    }

    PurlStatus "1" --> "*" RemediationSummary : has
    SbomStatus "1" --> "*" RemediationSummary : has

    PurlDetails "1" --> "*" PurlStatus : includes
    SbomAdvisory "1" --> "*" SbomStatus : includes
    AnalysisResponse "1" --> "*" PurlStatus : includes
Loading

File-Level Changes

Change Details Files
Document schema and relational model for storing CSAF remediation guidance and linking it to existing status records.
  • Introduce a remediation table keyed by advisory and vulnerability with category, details, URL, and JSONB metadata fields.
  • Define junction tables to associate remediations with purl_status and product_status records using composite primary keys and cascade deletes.
  • Specify indexes on advisory/vulnerability and status foreign keys to keep remediation lookups efficient.
docs/adrs/00011-csaf-remediation.md
Describe ingestion flow changes needed to create remediation records and link them to resolved product status entries.
  • Extend the ingestion design so StatusCreator tracks created status records per CSAF product_id.
  • Introduce a RemediationCreator component concept that uses the product_id-to-status mapping and existing ResolveProductIdCache to populate remediation and junction tables.
docs/adrs/00011-csaf-remediation.md
Define API surface and query patterns for exposing remediations alongside vulnerability status responses.
  • Add a RemediationSummary API model containing basic remediation fields and optional JSONB metadata.
  • Augment PurlStatus and SbomStatus response models to include a list of associated remediations, and enumerate affected endpoints.
  • Specify SQL join patterns using LEFT JOIN from status tables to remediation junction tables to retrieve remediations with minimal impact on queries without remediations.
docs/adrs/00011-csaf-remediation.md

Possibly linked issues

  • #(unknown): PR provides the ADR that defines CSAF remediation extraction and API exposure requested by the issue, partially fulfilling it.

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

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In the 'Related ADRs' and 'References' sections the Markdown link syntax is inverted, e.g. (ADR 00008)[00008-purls-recommendation.md]; update these to [ADR 00008](00008-purls-recommendation.md) and similarly for the CSAF test data path so the links render correctly.
  • Consider clarifying in the ADR how conflicting or overlapping remediations will be handled when multiple advisories reference the same vulnerability/package pair (e.g., prioritization or deduplication rules), since the schema allows multiple remediation records to attach to the same status.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the 'Related ADRs' and 'References' sections the Markdown link syntax is inverted, e.g. `(ADR 00008)[00008-purls-recommendation.md]`; update these to `[ADR 00008](00008-purls-recommendation.md)` and similarly for the CSAF test data path so the links render correctly.
- Consider clarifying in the ADR how conflicting or overlapping remediations will be handled when multiple advisories reference the same vulnerability/package pair (e.g., prioritization or deduplication rules), since the schema allows multiple remediation records to attach to the same status.

## Individual Comments

### Comment 1
<location> `docs/adrs/00011-csaf-remediation.md:93` </location>
<code_context>
+### Design Choices
+
+- Remediations link to **specific purl_status/product_status records**
+- Keep statuses (category) as VARCHAR. Having separate statuses table have added more complexity to queries than benefits.
+- Normalize only important remediation fields, while keeping the rest in JSON blob
+
</code_context>

<issue_to_address>
**suggestion (typo):** Fix subject–verb agreement in the explanation about a separate statuses table.

The sentence is grammatically off. Consider: "Having a separate statuses table would have added more complexity to queries than benefits" or "Having a separate statuses table has added more complexity to queries than benefits," depending on the tense you want.

```suggestion
- Remediations link to **specific purl_status/product_status records**
- Keep statuses (category) as VARCHAR. Having a separate statuses table has added more complexity to queries than benefits.
```
</issue_to_address>

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.

@dejanb dejanb requested a review from ctron December 10, 2025 15:59
@codecov
Copy link

codecov bot commented Dec 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.65%. Comparing base (63dc503) to head (823f741).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2179      +/-   ##
==========================================
- Coverage   68.66%   68.65%   -0.01%     
==========================================
  Files         379      379              
  Lines       21449    21449              
  Branches    21449    21449              
==========================================
- Hits        14727    14726       -1     
+ Misses       5855     5851       -4     
- Partials      867      872       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.


**Modified Response Structures:**

Add `remediations: Vec<RemediationSummary>` to:
Copy link
Contributor

Choose a reason for hiding this comment

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

I know we did simply add new information to all existing fields in the past. But is that the right idea? Why not start by adding it to the endpoints that require it today.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the ADR to consider adding the new information only to endpoints related to dependency analytics for now. We should consider other APIs later on.

Copy link
Member

Choose a reason for hiding this comment

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

Adding it to PurlStatus later will mean that /v3/vulnerability/analyze won't get it until "phase 2", I'm not sure how that will interact with @ruromero changing to v3 over v2

Copy link
Contributor

Choose a reason for hiding this comment

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

From DA perspective that is just a matter of adapting the endpoint and response.

Copy link
Member

Choose a reason for hiding this comment

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

I guess my only concern is: v2 analyze doesnt give any version range info (as v3 analyze returns purl statuses), so if we only add remediation support to v2 analyze for now, we'll be kinda split between all the new stuff being half in v2 and half in v3. But we can always start with v2 analyze for now and focus mainly on the actual implementation rather than what-endpoint-has-what

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added some clarifications about this. The analyze API should contain remediations, there's a bit of description on how we can achieve this without modifying PurlStatus and example of the response.

@dejanb dejanb requested review from Strum355 and ctron January 12, 2026 13:51
@dejanb dejanb requested a review from ruromero January 19, 2026 14:41
@dejanb dejanb enabled auto-merge January 19, 2026 15:57
@dejanb dejanb added this pull request to the merge queue Jan 19, 2026
Merged via the queue into main with commit 6d3ea81 Jan 19, 2026
6 checks passed
@dejanb dejanb deleted the adr/remediations branch January 19, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants