Skip to content

feat(analysis): add provider and source filtering to analysis requests - #595

Open
ruromero wants to merge 1 commit into
guacsec:mainfrom
ruromero:TC-5409
Open

feat(analysis): add provider and source filtering to analysis requests#595
ruromero wants to merge 1 commit into
guacsec:mainfrom
ruromero:TC-5409

Conversation

@ruromero

@ruromero ruromero commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add --providers and --sources CLI flags to stack, component, and stack-batch commands
  • Add TRUSTIFY_DA_PROVIDERS and TRUSTIFY_DA_SOURCES env var fallbacks
  • Extract shared appendAnalysisQueryParams() helper in analysis.js
  • 9 new tests covering URL construction and HTTP integration

Implements TC-5409

Test plan

  • Unit tests verify URL construction with providers/sources params
  • Unit tests verify env var fallback
  • Integration tests verify params forwarded to mock backend
  • npm run lint passes
  • npm test passes

Summary by Sourcery

Add support for configuring analysis providers and sources across CLI commands and backend requests.

New Features:

  • Expose providers and sources filtering via new CLI flags on component, stack, and stack-batch analysis commands.
  • Support TRUSTIFY_DA_PROVIDERS and TRUSTIFY_DA_SOURCES options and environment variables to control analysis filtering.

Enhancements:

  • Introduce a shared appendAnalysisQueryParams helper to centralize construction of analysis query parameters, including recommend, providers, and sources.
  • Extend the analysis options type to include providers and sources configuration.

Tests:

  • Add unit tests for URL query construction with providers, sources, and recommend parameters, including env var fallbacks.
  • Add integration-style tests to verify providers and sources query parameters are forwarded to the backend in stack analysis requests.

Add support for passing `providers` and `sources` query parameters to
the DA `/api/v5/analysis` and `/api/v5/batch-analysis` endpoints. This
allows callers to filter which vulnerability providers and sources are
used in analysis reports.

- Extract shared `appendAnalysisQueryParams()` helper that consolidates
  recommend, providers, and sources query parameter logic
- Add `--providers` and `--sources` CLI flags to stack, component, and
  stack-batch commands
- Support `TRUSTIFY_DA_PROVIDERS` and `TRUSTIFY_DA_SOURCES` env vars as
  fallbacks when CLI flags are not provided
- Add unit tests for URL construction, env var fallback, and HTTP
  request forwarding

Implements TC-5409

Assisted-by: Claude Code
@sourcery-ai

sourcery-ai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds provider/source filtering support to analysis requests by wiring new CLI flags through to shared URL query construction logic, including env-var fallbacks, and extending tests to cover URL building and HTTP forwarding.

Sequence diagram for provider/source filtering in analysis requests

sequenceDiagram
    actor User
    participant CLI_stack as cli.stack
    participant client
    participant requestStack
    participant appendAnalysisQueryParams
    participant Backend

    User ->> CLI_stack: run stack --providers p1,p2 --sources s1
    CLI_stack ->> client: stackAnalysis(manifest, html, opts)
    client ->> requestStack: requestStack(provider, manifest, url, html, opts)
    requestStack ->> appendAnalysisQueryParams: appendAnalysisQueryParams(finalUrl, opts)

    alt [TRUSTIFY_DA_RECOMMEND is false]
        appendAnalysisQueryParams ->> appendAnalysisQueryParams: url.searchParams.append(recommend,false)
    end

    alt [providers set via CLI or TRUSTIFY_DA_PROVIDERS]
        appendAnalysisQueryParams ->> appendAnalysisQueryParams: url.searchParams.append(providers,providers)
    end

    alt [sources set via CLI or TRUSTIFY_DA_SOURCES]
        appendAnalysisQueryParams ->> appendAnalysisQueryParams: url.searchParams.append(sources,sources)
    end

    requestStack ->> Backend: fetch(finalUrl, fetchOptions)
Loading

File-Level Changes

Change Details Files
Introduce shared helper for adding analysis query parameters and reuse it across all analysis request functions.
  • Export new appendAnalysisQueryParams helper from analysis module.
  • Move existing recommend=false query param logic into helper.
  • Extend helper to append providers and sources query params using getCustom with env/opts fallback.
  • Update requestStack, requestComponent, requestStackBatch, and requestImages to use helper for URL query construction instead of inlined logic.
src/analysis.js
Plumb providers and sources configuration from CLI to the analysis options object.
  • Add providers and sources options to component, stack, and stackBatch command builders with appropriate descriptions.
  • In each CLI handler, map --providers/--sources flags to TRUSTIFY_DA_PROVIDERS and TRUSTIFY_DA_SOURCES keys on opts when present.
  • Preserve existing workspaceDir and failFast behavior while extending opts handling.
src/cli.js
Extend options type definition to cover new provider/source settings.
  • Update Options JSDoc typedef to include TRUSTIFY_DA_PROVIDERS and TRUSTIFY_DA_SOURCES fields so they are recognized in consumers and tooling.
src/index.js
Add tests to validate provider/source URL query parameters and HTTP integration.
  • Add unit tests verifying providers and sources are appended to analysis URLs from opts.
  • Add unit tests ensuring TRUSTIFY_DA_PROVIDERS and TRUSTIFY_DA_SOURCES env vars act as fallbacks when opts are empty.
  • Add unit test ensuring recommend=false can be combined with providers/sources in the query string.
  • Add integration-style tests verifying providers and sources query params reach the backend during stack analysis via requestStack.
test/analysis.test.js

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

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In appendAnalysisQueryParams, consider using url.searchParams.set rather than append so repeat invocations (or future callers) don’t accumulate duplicate recommend/providers/sources query params.
  • The providers/sources CLI wiring is duplicated across component, stack, and stackBatch handlers; a small helper to apply these options to an opts object would keep the behavior consistent and reduce copy/paste.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In appendAnalysisQueryParams, consider using url.searchParams.set rather than append so repeat invocations (or future callers) don’t accumulate duplicate recommend/providers/sources query params.
- The providers/sources CLI wiring is duplicated across component, stack, and stackBatch handlers; a small helper to apply these options to an opts object would keep the behavior consistent and reduce copy/paste.

## Individual Comments

### Comment 1
<location path="src/analysis.js" line_range="247-259" />
<code_context>
+ * @param {URL} url - the URL object to append query parameters to
+ * @param {import("index.js").Options} [opts={}] - options containing parameter overrides
+ */
+function appendAnalysisQueryParams(url, opts = {}) {
+	if (getCustom('TRUSTIFY_DA_RECOMMEND', 'true', opts) === 'false') {
+		url.searchParams.append('recommend', 'false');
+	}
+	const providers = getCustom('TRUSTIFY_DA_PROVIDERS', null, opts);
+	if (providers) {
+		url.searchParams.append('providers', providers);
+	}
+	const sources = getCustom('TRUSTIFY_DA_SOURCES', null, opts);
+	if (sources) {
+		url.searchParams.append('sources', sources);
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Use `set` instead of `append` for query params to avoid accidental duplicates

If this helper is called multiple times with the same URL (or the URL is reused), `searchParams.append` on `recommend`, `providers`, and `sources` will create duplicate query params. Using `searchParams.set` keeps the function idempotent and prevents subtle issues as call sites change.

```suggestion
function appendAnalysisQueryParams(url, opts = {}) {
	if (getCustom('TRUSTIFY_DA_RECOMMEND', 'true', opts) === 'false') {
		url.searchParams.set('recommend', 'false');
	}
	const providers = getCustom('TRUSTIFY_DA_PROVIDERS', null, opts);
	if (providers) {
		url.searchParams.set('providers', providers);
	}
	const sources = getCustom('TRUSTIFY_DA_SOURCES', null, opts);
	if (sources) {
		url.searchParams.set('sources', sources);
	}
}
```
</issue_to_address>

### Comment 2
<location path="test/analysis.test.js" line_range="236-241" />
<code_context>
+			expect(url.searchParams.get('sources')).to.equal('osv,nvd')
+		})
+
+		/** Verifies that no providers or sources params are added when neither is set. */
+		test('does not append providers or sources when neither is set', () => {
+			const url = new URL('http://example.com/api/v5/analysis')
+			analysis.appendAnalysisQueryParams(url, {})
+			expect(url.searchParams.has('providers')).to.equal(false)
+			expect(url.searchParams.has('sources')).to.equal(false)
+		})
+
</code_context>
<issue_to_address>
**suggestion (testing):** Cover behavior of recommend param when true/unspecified to avoid regressions

`appendAnalysisQueryParams` is only tested for the `recommend=false` case. Since this helper now owns the `recommend` param, please add tests that:
- Call it with no `TRUSTIFY_DA_RECOMMEND` configured and verify the `recommend` query param is not added (or whatever the default behavior should be).
- Optionally, set `TRUSTIFY_DA_RECOMMEND='true'` via opts and/or env and verify `recommend` is still not added.
This will lock in the expectation that only `false` produces a `recommend` query param, preserving previous behavior.

Suggested implementation:

```javascript
		/** Verifies that no providers or sources params are added when neither is set. */
		test('does not append providers or sources when neither is set', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, {})
			expect(url.searchParams.has('providers')).to.equal(false)
			expect(url.searchParams.has('sources')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is not configured. */
		test('does not append recommend when not configured', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, {})
			expect(url.searchParams.has('recommend')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is set to true via opts. */
		test('does not append recommend when TRUSTIFY_DA_RECOMMEND is true in opts', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, { TRUSTIFY_DA_RECOMMEND: 'true' })
			expect(url.searchParams.has('recommend')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is set to true via env. */
		test('does not append recommend when TRUSTIFY_DA_RECOMMEND is true in env', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			const originalEnv = process.env.TRUSTIFY_DA_RECOMMEND
			process.env.TRUSTIFY_DA_RECOMMEND = 'true'
			try {
				analysis.appendAnalysisQueryParams(url, {})
				expect(url.searchParams.has('recommend')).to.equal(false)
			} finally {
				process.env.TRUSTIFY_DA_RECOMMEND = originalEnv
			}
		})

```

These tests assume:
1. `appendAnalysisQueryParams` currently only appends the `recommend` query param when it resolves to `false`, and never when it is unset or `true`.
2. The rest of the file already imports or defines `analysis`, `expect`, and the test runner functions (e.g., `suite`, `test`), and uses Node's global `process` object.

If the helper’s behavior differs (e.g., it appends `recommend=true`), you should adjust the `expect(url.searchParams.has('recommend')).to.equal(false)` assertions to reflect the actual desired behavior.
</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.

Comment thread src/analysis.js
Comment on lines +247 to +259
function appendAnalysisQueryParams(url, opts = {}) {
if (getCustom('TRUSTIFY_DA_RECOMMEND', 'true', opts) === 'false') {
url.searchParams.append('recommend', 'false');
}
const providers = getCustom('TRUSTIFY_DA_PROVIDERS', null, opts);
if (providers) {
url.searchParams.append('providers', providers);
}
const sources = getCustom('TRUSTIFY_DA_SOURCES', null, opts);
if (sources) {
url.searchParams.append('sources', sources);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Use set instead of append for query params to avoid accidental duplicates

If this helper is called multiple times with the same URL (or the URL is reused), searchParams.append on recommend, providers, and sources will create duplicate query params. Using searchParams.set keeps the function idempotent and prevents subtle issues as call sites change.

Suggested change
function appendAnalysisQueryParams(url, opts = {}) {
if (getCustom('TRUSTIFY_DA_RECOMMEND', 'true', opts) === 'false') {
url.searchParams.append('recommend', 'false');
}
const providers = getCustom('TRUSTIFY_DA_PROVIDERS', null, opts);
if (providers) {
url.searchParams.append('providers', providers);
}
const sources = getCustom('TRUSTIFY_DA_SOURCES', null, opts);
if (sources) {
url.searchParams.append('sources', sources);
}
}
function appendAnalysisQueryParams(url, opts = {}) {
if (getCustom('TRUSTIFY_DA_RECOMMEND', 'true', opts) === 'false') {
url.searchParams.set('recommend', 'false');
}
const providers = getCustom('TRUSTIFY_DA_PROVIDERS', null, opts);
if (providers) {
url.searchParams.set('providers', providers);
}
const sources = getCustom('TRUSTIFY_DA_SOURCES', null, opts);
if (sources) {
url.searchParams.set('sources', sources);
}
}

Comment thread test/analysis.test.js
Comment on lines +236 to +241
/** Verifies that no providers or sources params are added when neither is set. */
test('does not append providers or sources when neither is set', () => {
const url = new URL('http://example.com/api/v5/analysis')
analysis.appendAnalysisQueryParams(url, {})
expect(url.searchParams.has('providers')).to.equal(false)
expect(url.searchParams.has('sources')).to.equal(false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Cover behavior of recommend param when true/unspecified to avoid regressions

appendAnalysisQueryParams is only tested for the recommend=false case. Since this helper now owns the recommend param, please add tests that:

  • Call it with no TRUSTIFY_DA_RECOMMEND configured and verify the recommend query param is not added (or whatever the default behavior should be).
  • Optionally, set TRUSTIFY_DA_RECOMMEND='true' via opts and/or env and verify recommend is still not added.
    This will lock in the expectation that only false produces a recommend query param, preserving previous behavior.

Suggested implementation:

		/** Verifies that no providers or sources params are added when neither is set. */
		test('does not append providers or sources when neither is set', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, {})
			expect(url.searchParams.has('providers')).to.equal(false)
			expect(url.searchParams.has('sources')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is not configured. */
		test('does not append recommend when not configured', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, {})
			expect(url.searchParams.has('recommend')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is set to true via opts. */
		test('does not append recommend when TRUSTIFY_DA_RECOMMEND is true in opts', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			analysis.appendAnalysisQueryParams(url, { TRUSTIFY_DA_RECOMMEND: 'true' })
			expect(url.searchParams.has('recommend')).to.equal(false)
		})

		/** Verifies that recommend param is not appended when TRUSTIFY_DA_RECOMMEND is set to true via env. */
		test('does not append recommend when TRUSTIFY_DA_RECOMMEND is true in env', () => {
			const url = new URL('http://example.com/api/v5/analysis')
			const originalEnv = process.env.TRUSTIFY_DA_RECOMMEND
			process.env.TRUSTIFY_DA_RECOMMEND = 'true'
			try {
				analysis.appendAnalysisQueryParams(url, {})
				expect(url.searchParams.has('recommend')).to.equal(false)
			} finally {
				process.env.TRUSTIFY_DA_RECOMMEND = originalEnv
			}
		})

These tests assume:

  1. appendAnalysisQueryParams currently only appends the recommend query param when it resolves to false, and never when it is unset or true.
  2. The rest of the file already imports or defines analysis, expect, and the test runner functions (e.g., suite, test), and uses Node's global process object.

If the helper’s behavior differs (e.g., it appends recommend=true), you should adjust the expect(url.searchParams.has('recommend')).to.equal(false) assertions to reflect the actual desired behavior.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.01%. Comparing base (156bb77) to head (647bdc1).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #595   +/-   ##
=======================================
  Coverage   91.01%   91.01%           
=======================================
  Files          38       38           
  Lines        8001     8001           
  Branches     1395     1395           
=======================================
  Hits         7282     7282           
  Misses        719      719           
Flag Coverage Δ
unit-tests 91.01% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

2 participants