Skip to content

Repository index cannot return unscanned targets #546

Description

@sylvesterkaczmarek

Summary

list-repositories --status not_scanned cannot return any repositories, even though the workbench persists security targets before they have a scan.

Reproduction / evidence

Current upstream main at 37bf87a692fc72d41f7312cc48808d699d204fba has a legitimate zero-scan target state: create_workspace() calls ensure_security_target() as soon as a workspace is created with a target path, before a scan is started.

workbench_native_indexes.list_repositories() nevertheless builds its output only from latest_scan_by_target.items():

repositories = [
    {...}
    for target_id, latest_scan in latest_scan_by_target.items()
    if (target := targets.get(target_id)) is not None
]

Every repository admitted to that list therefore already has at least one scan.

The status filter then contains:

and args.status != "not_scanned"

So when --status not_scanned is requested, every already-scanned row is rejected and targets with zero scans were never present in the collection to begin with. The result is always empty.

Minimal deterministic state:

  1. create two security_targets rows;
  2. add a completed scan for only one target;
  3. call list_repositories(..., status="not_scanned");
  4. current main returns [] instead of the target with no scans.

Expected behavior

Repository indexing should start from all persisted security_targets:

  • scanned targets: scanCount > 0, with latestScan populated;
  • unscanned targets: scanCount == 0, with latestScan: null;
  • status=scanned should return only the former;
  • status=not_scanned should return only the latter;
  • status=open_findings should retain its existing semantics.

Root cause

The implementation uses scan history as the primary repository set rather than using security_targets as the primary set and joining scan summary data onto it. The later not_scanned predicate therefore has no possible matching row.

Suggested fix

Build repository rows from all security_targets, use .get() defaults for scan count/latest scan, and apply explicit scanned / not_scanned predicates based on scanCount.

Add a focused regression with one scanned and one unscanned persisted target.

Impact

The native repository index and any UI/tooling that asks for unscanned repositories cannot surface targets that were configured in a workspace but have not yet been scanned. This makes the documented status selector nonfunctional for that state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions