feat(vulns): add close and reopen commands and --status filter

Merged
TJ
20h ago
+893-29

Adds close and reopen for vulns, matching detail bugs. The commands' API ships in usedetail/detail #19512, with trackerStateName from #19513.

Do not merge until those PRs have deployed. state is a new required field on Vuln, so this CLI should fail to parse vulns list and vulns show from an older backend. This is a draft for that reason. cargo xtask check fails on openapi.json until then, which is expected because it compares against production's spec.

What changed

  • detail vulns close <id>: --state, --dismissal-reason, --notes and --format, with the same prompts and non-interactive validation as bugs close.
  • detail vulns reopen <id>: takes only the ID.
  • vulns list --status: one value. Without it the API defaults to pending, so closed vulns are hidden unless you ask.
  • Display: list adds State and Dismissal. show also adds Notes, State Source and State Updated, which explain a tracker dismissal with no reason.
  • openapi.json: regenerated from a local backend's spec (165 additions, no removals). xtask is unchanged.
  • Docs: docs/HELP.md and the bundled detail-bugs skill.
  • bugs.rs: prompt_notes becomes pub(crate). No other bugs change.

--status takes one value where bugs list takes several, because the API takes one. Reason flags are kebab-case, like not-a-bug.

After the backend deploys

  1. Run cargo xtask generate-openapi and confirm the diff is empty or expected.
  2. Run cargo xtask check, which should then pass.
  3. Mark ready and merge. A version bump and release are separate.

Testing

Against the backend stack on a fork of prod, with a debug binary and an isolated config:

  • Every state and reason, table and JSON output, and interactive prompts in a real pty.
  • Non-interactive errors, with 0 rows written.
  • Another org's vuln gets a 403 on show, close and reopen, with 0 rows written.
  • bugs close, reopen, show and list unchanged.
  • cargo fmt, clippy, check and test pass. Live-API integration tests return early without a key, so those don't all really run.

Not run: this CLI against a backend without the new API, and show on a tracker-set state name (unit test only).

šŸ¤– Generated with Claude Code