Skip to content

feat(cli): [FDE-2950] sync the API spec, lock command names and add finding actions to CLI and MCP - #172

Open
tim-thacker-nullify wants to merge 11 commits into
mainfrom
timthacker/fde-2950-public-cli-resync
Open

tim-thacker-nullify wants to merge 11 commits into
mainfrom
timthacker/fde-2950-public-cli-resync

Conversation

@tim-thacker-nullify

@tim-thacker-nullify tim-thacker-nullify commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Claude

The CLI's API spec was five months old, so customers such as Latent could not allowlist CSPM findings from the CLI or MCP, and a plain re-sync failed to build and dropped commands (FDE-2950).

Merging releases to customers. Do not merge without Tim's go-ahead.

Generator:

  • Removes stale output. Stale asset-graph.go and infrastructure.go caused the 10 duplicate models (reproduced).
  • Fails on unmapped path prefixes.
  • spec/command-names.lock and spec/mcp-tools.tsv hold names; CI fails on any drop or rename without a recorded decision.

Spec sync to bundle 1b9c3dd: 504 commands become 1013.

  • 534 added, 11 moved with deprecated aliases, 0 renamed, 25 removed, 4 flags retired.
  • All 25 have no route at prod 31b87fcb97ae. They could only return 404 or similar. Listed in CHANGELOG.md.

Finding actions in CLI and MCP, from one verb table:

  • nullify findings gains get, triage, allowlist, unallowlist, archive, false-positive, ticket, feedback. All finding types, including cspm, scpm and sensitive-data secrets.
  • Allowlist requires a reason and an explicit type. Bughunt and SCA warn that prod may not record the type until #17588 deploys.
  • findings list reports returned and truncated. Access failures return an error, not an empty list.
  • MCP: delete ticket, archive and false-positive tools are opt-in (findings-write). fix-status and fix-diff added. Every tool is annotated.

Behaviour changes:

  • nullify fix now waits up to 50 minutes and exits non-zero on a failed run. Use --no-wait for the old fast return.
  • ci gate is unchanged. It is still wrong, but the unified search would make it fail open: FDE-2973.
  • findings list returns triaged findings only, and repository filters match the exact stored name.
  • MCP fix no longer waits and ignores create_pr.
  • list_escalations is removed; its route is gone.

Drift job:

  • Weekly, opens a draft PR and cannot release. Read and write tokens are separate, none during go run.
  • Fails until spec-sync exists (monorepo PR) and SPEC_SYNC_GITHUB_APP_KEY is set. App 359904 install is unconfirmed, and a dedicated app is the better long-term choice.

Not verified:

  • Never run against a live API. All tests use a fake transport. Needs a login to demo.dev.nullify.ai.
  • Drift workflow has never run.
  • Fresh aggressive review of the final head is running.

Overlap: #170 conflicts in writeBaseClient and root.go; regenerate internal/api/client.go after rebase. #166 needs make command-surface after rebase.

Generated code is alone in f3f27ce.

🤖 Generated with Claude Code

tim-thacker-nullify and others added 8 commits November 4, 2026 17:41
…ommand names

The generator never deleted output, so a service that left the spec kept its
old file and redeclared every model type it shared. A path with an unmapped
prefix was dropped without notice, and a command name depended on its siblings,
so a new route renamed an existing command.

Generation now removes its own previous output, fails on an unmapped prefix,
and reads command names from spec/command-names.lock. A locked name stays when
siblings change or when its route leaves the spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated output only: spec/, internal/api, internal/commands and new rows in
spec/command-names.lock. It moves SPEC_REF from the 26 May pin to the newest
commit that updated the bundle. Hand-written code that follows the new API is
in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nds working

Latent could not allowlist or unallowlist CSPM findings from the CLI or MCP, and
nothing protected customers from a dropped command.

- Add internal/findings: one per-type table and one verb table that both the CLI
  and the MCP server use. It replaces the MCP-only table and adds CSPM allowlist,
  unallowlist, archive, mark false positive and triage, plus bug hunt unallowlist.
- Add nullify findings subcommands and MCP tools for those verbs and for feedback.
  Allowlist requires a reason and a user-submittable type; raw nullify api commands
  still follow the spec.
- nullify findings list accepts cspm and scpm, reports returned and truncated, and
  exits non-zero on no access. Fix the wrong API values for secrets, bughunt and scpm.
- nullify fix and nullify_fix_finding share one flow and stop calling removed routes.
- Add spec/command-surface.tsv with a test and scripts/commandsurface. Record each
  moved or removed command in internal/commands/surface_decisions.go; moved commands
  stay as deprecated aliases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…equest

- CI fails when generated output does not match the spec or a command in the base
  branch disappears without a recorded decision.
- spec-drift.yml opens a draft pull request when the pin is behind the monorepo
  bundle. It runs on a free runner, never merges and does not release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k MCP tools

- nullify fix and nullify_fix_finding carry the terminal state and fail on a
  failed or still-running run, and report only a pull request of this run.
- Add secrets_sensitive_data, and accept the type value of a listed finding.
- Send the unallowlistType that the secrets routes require.
- Move archive, unarchive, mark, unmark and delete ticket to the findings-write
  tool set, and annotate every MCP tool as read-only or destructive.
- Restore exit code 3 for API access failures.
- Lock MCP tool names in spec/mcp-tools.tsv and record list_escalations as removed.
- nullify fix waits up to 50 minutes with --timeout, and --no-wait starts the run
  and exits 0. nullify_fix_finding starts the run and returns. Add fix-status and
  fix-diff. A failed diff read keeps the pull request in the result.
- The MCP tool lock also records annotations and tool sets.
- nullify fix refreshes an expired token during the wait, and prints run_id, state
  and check_with when it cannot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Mint a read-only token for nullify and a separate write token for cli, with no
  token in the environment while Go runs.
- Fail first with one message when the app key is missing, and run weekly.
- Read the app key from the spec-sync environment, which only main can deploy to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-nullify-token

- Move the timeout to internal/client, so that api.NewClient and
  NewRefreshingHTTPClient read the same setting.
- Prove that nullify fix never replaces --nullify-token with stored credentials.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tim-thacker-nullify
tim-thacker-nullify marked this pull request as ready for review November 4, 2026 11:33
@tim-thacker-nullify tim-thacker-nullify added the minor Minor version updates (features) label Nov 4, 2026
tim-thacker-nullify and others added 3 commits November 4, 2026 22:50
…n ci gate

- bughunt, sca_dependencies and sca_containers return a warning, because the server
  may not record the required allowlist type. Remove the SCA marks when the spec
  moves past monorepo #17588.
- Accept the monorepo FindingType names secrets_credentials, dast_bughunt and
  dast_pentest.
- ci gate --type accepts scpm and secrets_sensitive_data through the unified search.
  The default set does not change.
- get_findings_for_repo reports truncation and no longer searches cloud findings by
  repository.
- Keep the open pull request when a run ends in failed_iteration, and remove the
  duplicated StillRunning field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Minor version updates (features)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant