Skip to content

Commit daaf992

Browse files
committed
EPMDEDP-16731: docs: Align terminology and clarify findings pagination
- Replace "codebase" with "project" throughout CLI help text and error messages for terminology consistency - Document unpaginated findings endpoint behavior: server-side cap at 1000 rows, only --source narrows upstream query, --severity filters client-side - Add FindingsServerCap constant to keep cap value in sync across help text and truncation messages - Update sca.md with detailed explanation of filter behavior and pagination limitations Signed-off-by: Sergiy Kulanov <sergiy_kulanov@epam.com>
1 parent ecc4062 commit daaf992

10 files changed

Lines changed: 56 additions & 36 deletions

File tree

docs/sca.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ credentials are required.
1313
| `sca list` | List SCA projects known to Dependency-Track |
1414
| `sca get <codebase>` | Project overview: risk score, severity counts, last BOM import |
1515
| `sca components <codebase>` | Dependencies with outdated / direct / severity filters |
16-
| `sca findings <codebase>` | Flat vulnerability listing (CVE-level) with severity filter + truncation |
16+
| `sca findings <codebase>` | Flat vulnerability listing (CVE-level), unpaginated, server-cap 1000 rows |
1717

1818
All commands accept `-o, --output` with `table` (default) or `json`.
1919

@@ -118,8 +118,10 @@ commons-text 1.9 1.13.1 yes Apache-2.0 5.5 0/1
118118
2 components, page 1 of 1 (page-size 50)
119119
```
120120

121-
Combined filters are **AND** — server-side `--only-outdated` / `--only-direct`
122-
are forwarded to Dep-Track, and `--severity` narrows client-side afterwards:
121+
Combined filters are **AND**`--only-outdated`, `--only-direct`, and
122+
`--severity` are all applied server-side. The portal auto-pages across the
123+
full project (up to a safety cap) to evaluate the severity filter before
124+
paginating; if the cap is reached, the response carries `truncated=true`:
123125

124126
```bash
125127
# Outdated direct dependencies with at least one HIGH or CRITICAL finding
@@ -150,10 +152,14 @@ Filter by upstream vulnerability source (e.g. `NVD`, `GITHUB`, `OSV`):
150152
krci sca findings payments-api --source=NVD
151153
```
152154

153-
Very large projects are capped server-side at 1000 rows with a footer hint:
155+
Very large projects are capped server-side at 1000 rows. `--source` is the
156+
only flag that narrows the upstream query; `--severity` filters client-side
157+
after the cap and cannot recover findings beyond row 1000. To audit a
158+
truncated project for severities, drop `--severity` and post-filter the JSON,
159+
or scope by `--branch` first:
154160

155161
```
156-
(findings truncated to 1000 rows — narrow the query via --severity or --source)
162+
(findings truncated to 1000 rows server-side — only --source narrows the upstream query; --severity filters client-side and cannot recover capped rows)
157163
```
158164

159165
Script-friendly CVE extraction:

internal/portal/sca.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,13 @@ func scaBranchNotFoundErr(err error, body []byte, codebase, branch string) error
211211
bodyLower := strings.ToLower(string(body))
212212
switch {
213213
case branch != "":
214-
return &scaNotFoundError{msg: fmt.Sprintf("codebase %s not found", codebase)}
214+
return &scaNotFoundError{msg: fmt.Sprintf("project %s not found", codebase)}
215215
case strings.Contains(bodyLower, "default_branch_missing"):
216216
return &scaNotFoundError{msg: fmt.Sprintf(
217-
"codebase %s has no spec.defaultBranch configured — pass --branch explicitly", codebase)}
217+
"project %s has no spec.defaultBranch configured — pass --branch explicitly", codebase)}
218218
default:
219219
return &scaNotFoundError{msg: fmt.Sprintf(
220-
"codebase %s not found — use 'krci sca list --search=%s' to find projects known to Dep-Track",
220+
"project %s not found — use 'krci sca list --search=%s' to find projects known to Dep-Track",
221221
codebase, codebase)}
222222
}
223223
}

internal/portal/sca_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func TestSCAService_Get_404_CodebaseNotFound_WithExplicitBranch(t *testing.T) {
224224
if !errors.Is(err, ErrNotFound) {
225225
t.Errorf("want wrap of ErrNotFound, got %v", err)
226226
}
227-
if !strings.Contains(err.Error(), "codebase nope not found") {
227+
if !strings.Contains(err.Error(), "project nope not found") {
228228
t.Errorf("unexpected message: %v", err)
229229
}
230230
}

pkg/cmd/project/deployments/deployments.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ project is registered (CDPipeline.spec.applications) but no Application
4545
exists yet are emitted with "-" placeholders (table) or null values (JSON).
4646
4747
Rows are sorted by deployment ascending, then by Stage.spec.order ascending.`,
48-
Args: cmdutil.ExactArgs(1, "a project (codebase) name",
48+
Args: cmdutil.ExactArgs(1, "a project name",
4949
"to see available projects: krci project list"),
5050
Example: ` # Default
5151
krci project deployments my-app

pkg/cmd/project/project.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
func NewCmdProject(f *cmdutil.Factory) *cobra.Command {
1515
cmd := &cobra.Command{
1616
Use: "project",
17-
Short: "Manage projects (Codebases)",
17+
Short: "Manage projects",
1818
Aliases: []string{"proj"},
1919
}
2020

pkg/cmd/sca/components/components.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func NewCmdComponents(f *cmdutil.Factory, runF func(*ComponentsOptions) error) *
3939
}
4040

4141
cmd := &cobra.Command{
42-
Use: "components <codebase>",
42+
Use: "components <project>",
4343
Short: "List dependencies (components) for an SCA project",
44-
Args: cmdutil.ExactArgs(1, "a KubeRocketCI codebase name",
44+
Args: cmdutil.ExactArgs(1, "a KubeRocketCI project name",
4545
"to see available projects: krci sca list"),
4646
Example: ` # Default branch, first 50 dependencies
4747
krci sca components payments-api
@@ -83,7 +83,8 @@ func NewCmdComponents(f *cmdutil.Factory, runF func(*ComponentsOptions) error) *
8383
cmd.Flags().StringSliceVar(&opts.Severity, "severity", nil,
8484
scainternal.SeverityFlagUsage+
8585
" Applied server-side across all dependencies of the project.")
86-
cmd.Flags().BoolVar(&opts.OnlyOutdated, "only-outdated", false, "Only components marked outdated by Dependency-Track")
86+
cmd.Flags().BoolVar(&opts.OnlyOutdated, "only-outdated", false,
87+
"Only components Dep-Track marks outdated (newer version exists; independent of vulnerability status)")
8788
cmd.Flags().BoolVar(&opts.OnlyDirect, "only-direct", false, "Only direct (non-transitive) dependencies")
8889
cmd.Flags().IntVar(&opts.Page, "page", 1, "Page index (1-based)")
8990
cmd.Flags().IntVar(&opts.PageSize, "page-size", defaultComponentsPageSize, "Page size (max 500)")

pkg/cmd/sca/findings/findings.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,16 @@ func NewCmdFindings(f *cmdutil.Factory, runF func(*FindingsOptions) error) *cobr
4141
}
4242

4343
cmd := &cobra.Command{
44-
Use: "findings <codebase>",
45-
Short: "List Dep-Track vulnerability findings for a codebase",
46-
Args: cmdutil.ExactArgs(1, "a KubeRocketCI codebase name",
44+
Use: "findings <project>",
45+
Short: "List Dep-Track vulnerability findings for a project",
46+
Long: fmt.Sprintf(
47+
"List Dep-Track vulnerability findings for a project.\n\n"+
48+
"Unpaginated: the portal returns a single response capped at %d rows\n"+
49+
"server-side. Only --source narrows the upstream query; --severity is\n"+
50+
"applied client-side after the cap, so it cannot recover findings beyond\n"+
51+
"row %d.",
52+
scainternal.FindingsServerCap, scainternal.FindingsServerCap),
53+
Args: cmdutil.ExactArgs(1, "a KubeRocketCI project name",
4754
"to see available projects: krci sca list"),
4855
Example: ` # All unsuppressed findings, default branch
4956
krci sca findings payments-api
@@ -111,7 +118,10 @@ func findingsRun(ctx context.Context, opts *FindingsOptions) error {
111118
return scainternal.HandleError(opts.IO, opts.OutputFormat, err)
112119
}
113120

114-
// Client-side inclusive severity filter (server does not narrow by severity).
121+
// Client-side inclusive severity filter — server does not narrow by
122+
// severity. Truncated stays as-returned by the server: hiding it after a
123+
// client-side filter would silently drop findings that fell off the cap
124+
// before we ever saw them.
115125
if inclusive := scainternal.ExpandSeverityFlag(opts.Severity); len(inclusive) > 0 {
116126
filtered := make([]portal.SCAFinding, 0, len(result.Items))
117127
for _, f := range result.Items {
@@ -120,11 +130,6 @@ func findingsRun(ctx context.Context, opts *FindingsOptions) error {
120130
}
121131
}
122132
result.Items = filtered
123-
// Once the user has narrowed by --severity, the upstream "1000-row cap"
124-
// hint is misleading: they already supplied the only follow-up flag we
125-
// would have suggested. Clear the flag so neither the table footer nor
126-
// the JSON envelope keeps advertising it.
127-
result.Truncated = false
128133
}
129134

130135
return scainternal.Render(opts.IO, opts.OutputFormat, result, func(w io.Writer, isTTY bool) error {
@@ -174,8 +179,10 @@ func renderTable(w io.Writer, isTTY bool, codebase string, result *portal.SCAFin
174179
if _, err := fmt.Fprintln(w); err != nil {
175180
return err
176181
}
177-
if _, err := fmt.Fprintln(w,
178-
"(findings truncated to 1000 rows — narrow the query via --severity or --source)"); err != nil {
182+
if _, err := fmt.Fprintf(w,
183+
"(findings truncated to %d rows server-side — only --source narrows the upstream query;"+
184+
" --severity filters client-side and cannot recover capped rows)\n",
185+
scainternal.FindingsServerCap); err != nil {
179186
return err
180187
}
181188
}

pkg/cmd/sca/get/get.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ func NewCmdGet(f *cmdutil.Factory, runF func(*GetOptions) error) *cobra.Command
3535
}
3636

3737
cmd := &cobra.Command{
38-
Use: "get <codebase>",
39-
Short: "Show a Dep-Track project's overview for a codebase",
40-
Args: cmdutil.ExactArgs(1, "a KubeRocketCI codebase name",
38+
Use: "get <project>",
39+
Short: "Show SCA scan overview for a project",
40+
Args: cmdutil.ExactArgs(1, "a KubeRocketCI project name",
4141
"to see available projects: krci sca list"),
4242
Example: ` # Uses Codebase.spec.defaultBranch when --branch is omitted
4343
krci sca get payments-api
@@ -118,7 +118,7 @@ func printDetail(w io.Writer, codebase, requestedBranch string, d *portal.SCAPro
118118
}
119119

120120
pairs := []kvPair{
121-
{label: "Codebase", value: codebase},
121+
{label: "Project", value: codebase},
122122
{label: "Branch", value: project.Version},
123123
{label: "Classifier", value: scainternal.OrDash(project.Classifier)},
124124
{label: "Active", value: formatActive(project.Active, styled)},

pkg/cmd/sca/get/get_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestGet_BranchFlagUsageStringIsVerbatim(t *testing.T) {
8787
if !strings.Contains(flag.Usage, "Dep-Track project 'version'") {
8888
t.Errorf("--branch usage must reference Dep-Track version field: %q", flag.Usage)
8989
}
90-
if !strings.Contains(flag.Usage, "krci sca list --search=<codebase>") {
90+
if !strings.Contains(flag.Usage, "krci sca list --search=<project>") {
9191
t.Errorf("--branch usage must hint discovery path: %q", flag.Usage)
9292
}
9393
}
@@ -140,7 +140,7 @@ func TestPrintDetail_HappyPath(t *testing.T) {
140140
t.Fatalf("printDetail: %v", err)
141141
}
142142
out := buf.String()
143-
wants := []string{"svc @ main", "Codebase", "Branch", "Classifier", "Risk score",
143+
wants := []string{"svc @ main", "Project", "Branch", "Classifier", "Risk score",
144144
"Vulnerabilities", "Critical", "Components", "Total"}
145145
for _, w := range wants {
146146
if !strings.Contains(out, w) {

pkg/cmd/sca/internal/validate.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@ import (
1818
// verb. Matches the OpenAPI ceiling.
1919
const MaxPageSize = 500
2020

21+
// FindingsServerCap is the maximum number of rows the portal returns from
22+
// the unpaginated `sca findings` endpoint. Mirrors the server-side ceiling
23+
// documented in the OpenAPI spec; the help text and truncation footer must
24+
// stay in sync with it.
25+
const FindingsServerCap = 1000
26+
2127
// BranchFlagUsage is the verbatim help text for `--branch` across every
2228
// per-codebase sca verb. Spec Requirement "Codebase + Branch Addressing"
2329
// mandates this exact string so users always see the same Dep-Track `version`
2430
// field explanation.
2531
const BranchFlagUsage = "branch name (maps to the Dep-Track project 'version' field). " +
26-
"Defaults to the codebase's spec.defaultBranch. " +
27-
"Run 'krci sca list --search=<codebase>' to discover all recorded versions."
32+
"Defaults to the project's spec.defaultBranch. " +
33+
"Run 'krci sca list --search=<project>' to discover all recorded versions."
2834

2935
// SeverityFlagUsage is the verbatim help text for `--severity` across the
3036
// verbs that expose it. Spec design §D4 mandates this exact string: it
@@ -38,15 +44,15 @@ const SeverityFlagUsage = "minimum severity to include (inclusive). " +
3844
// names by platform convention follow DNS-1123.
3945
func ValidateCodebaseKey(codebase string) error {
4046
if codebase == "" {
41-
return fmt.Errorf("<codebase> must not be empty")
47+
return fmt.Errorf("<project> must not be empty")
4248
}
4349

4450
if len(codebase) > cmdutil.DNS1123SubdomainMaxLength {
45-
return fmt.Errorf("<codebase> must be at most %d characters", cmdutil.DNS1123SubdomainMaxLength)
51+
return fmt.Errorf("<project> must be at most %d characters", cmdutil.DNS1123SubdomainMaxLength)
4652
}
4753

4854
if !cmdutil.IsValidDNS1123Label(codebase) {
49-
return fmt.Errorf("<codebase> must be a valid DNS-1123 name")
55+
return fmt.Errorf("<project> must be a valid DNS-1123 name")
5056
}
5157

5258
return nil

0 commit comments

Comments
 (0)