Skip to content

feat(package): on-demand package scan commands (FOU-221)#27

Merged
abhisek merged 3 commits into
mainfrom
feat/package-scan
Jul 23, 2026
Merged

feat(package): on-demand package scan commands (FOU-221)#27
abhisek merged 3 commits into
mainfrom
feat/package-scan

Conversation

@abhisek

@abhisek abhisek commented Jul 23, 2026

Copy link
Copy Markdown
Member

What

Adds the safedep package scan command family — the CLI surface for SafeDep Cloud's on-demand package scanning (safedep/api#177, PackageScanService).

safedep package scan run   <package-ref>          # submit + wait for verdict
safedep package scan get    <package-ref> | --scan-id ID
safedep package scan list  [--ecosystem/--name/--version]
safedep package scan show   <package-ref> | --scan-id ID

A package is any external software component in a supported ecosystem — OSS libraries, VS Code / OpenVSX extensions, GitHub repositories, and more — hence the deliberately generic package domain noun.

Design

  • Identity layer. A target is resolved from the explicit --ecosystem/--name/--version triple (canonical, forward-compatible) or a PURL / GitHub URL (sugar) via dry/api/pb. Ecosystem is mandatory — the backend routes the scan by it — so a resolved ECOSYSTEM_UNSPECIFIED is rejected client-side with guidance rather than forwarded. --ecosystem maps through the generated enum value map, so new ecosystems need at most a dependency bump, never CLI code.
  • run waits by default (capped backoff poll + spinner in rich mode); --wait=false submits only. A MALWARE verdict expands the full report inline in table mode; plain/json keep a stable headline shape so the agent contract does not change with the verdict. The idempotency key derives from the target so repeat runs dedupe server-side; --rescan forces a fresh scan.
  • get/show take a package-ref by default (newest scan for the target), with --scan-id as the direct path for agent orchestration. show omits empty report sections so non-library component reports do not render hollow tables.
  • Output follows the repo's Renderable contract (table/plain/json) with verdict badges (malware/inconclusive/benign).

Verbs

No new verbs: run, get, list, show are all already in the allow-list. verbs.go unchanged.

API bump

Bumps the safedep/api generated bindings to pick up PackageScanService. The same bump widened the MalwareAnalysisService client interface, so the jfrog integration test fake gains the new Internal* methods (test-only change).

Docs

One page per leaf under docs/cmd/, linked from the README command index, per DEVGUIDE.

Testing

  • make build, make test, golangci-lint run ./..., and the convention tests (go test ./internal/cmd/ -run Conventions) all pass locally.
  • Table-driven unit tests cover target resolution (explicit / PURL / custom PURL types / UNSPECIFIED rejection / missing version), the run wait/no-wait/rescan/timeout/malware-report paths, get by ref vs scan-id, list filter building, and show not-completed handling and section rendering.

🤖 Generated with Claude Code

Add the `safedep package scan` command family over the control-plane
PackageScanService: run (submit + wait), get, list, and show.

- Identity layer resolves a target from the explicit --ecosystem/--name
  /--version triple (canonical) or a PURL / GitHub URL via dry/api/pb.
  Ecosystem is mandatory; a resolved UNSPECIFIED is rejected client-side
  so it never reaches the backend, which needs it to route the scan.
- run waits for a verdict by default (backoff poll + spinner), --no-wait
  submits only. A MALWARE verdict expands the full report inline in table
  mode; plain/json keep a stable headline shape. Idempotency key derives
  from the target so repeat runs dedupe; --rescan forces a fresh scan.
- get/show address a scan by package-ref (newest for the target) or by
  --scan-id for agent orchestration. show renders the report with empty
  sections omitted so non-library components do not show hollow tables.
- No new verbs: run/get/list/show are all in the allow-list.
- Bumps the safedep/api generated bindings to pick up PackageScanService;
  updates the jfrog test fake for the widened MalwareAnalysisService
  client interface that came with the bump.

Docs: one page per leaf under docs/cmd, linked from README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@safedep

safedep Bot commented Jul 23, 2026

Copy link
Copy Markdown

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

Package Details
Package Malware Vulnerability Risky License Report
icon buf.build/gen/go/safedep/api/grpc/go @ v1.6.2-20260721112344-78a866a85e69.1
go.mod
ok icon
ok icon
ok icon
🔗
icon buf.build/gen/go/safedep/api/protocolbuffers/go @ v1.36.11-20260721112344-78a866a85e69.1
go.mod
ok icon
ok icon
ok icon
🔗

View complete scan results →

This report is generated by SafeDep Github App

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f0c02f9ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/cmd/packages/run.go
Comment thread internal/cmd/packages/run.go
abhisek and others added 2 commits July 23, 2026 14:05
Address code review on PR #27:

- runScan now returns an error when polling reaches a terminal FAILED
  status, so `package scan run --wait` exits non-zero as documented
  instead of rendering a failed scan as success (P1).
- run rejects `--save` combined with `--wait=false`: the report only
  exists after waiting, so the pairing previously produced neither a
  file nor an error (P2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reports can carry a very large file-evidence list that makes the
decorated table unreadable. The table now truncates file and project
evidence to 20 rows with a footer showing the omitted count and pointing
at --output json. plain and json output remain complete, so no data is
lost for pipelines or programmatic consumers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@abhisek
abhisek merged commit 01d3abd into main Jul 23, 2026
6 checks passed
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