Skip to content

feat(cliv2): enable CaptureEngine billing lifecycle [IANDT-240] - #7067

Draft
brettgurman-snyk wants to merge 7 commits into
mainfrom
bg/attach-capture-bag
Draft

feat(cliv2): enable CaptureEngine billing lifecycle [IANDT-240]#7067
brettgurman-snyk wants to merge 7 commits into
mainfrom
bg/attach-capture-bag

Conversation

@brettgurman-snyk

@brettgurman-snyk brettgurman-snyk commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Minimal cliv2 host adapter for IANDT-240 lazy-open contributor billing. Registers GAF failure-cleanup hook and calls FinishCommand at tearDown. Capture session opens inside GAF middleware on first billable HTTP — not at command start.

Requires GAF stack: #664#671#681 (pinned pre-release below).

Lazy-open flow

snyk monitor
  → SetCommand("monitor") via existing analytics        # no billing setup at start
  → first billable HTTP → GAF middleware opens session  # #671
  → tearDown → FinishCommand(success)                   # this PR
       → CloseCommandSession + EmitFromCapture → POST contributing_devs

Removed from earlier draft: BeginCommand, WithContributorBillingCapture(), syncActiveBillingCommand / config-key approach.

Diff vs main

File Change
cliv2/pkg/core/main.go EnableIfConfigured at engine creation; FinishCommand in tearDown; removed BeginCommand and WithContributorBillingCapture()
cliv2/go.mod / go.sum Pin GAF lazy-open stack (v0.10.1-0.20260806080023-f868e847d10f); local replace commented out for CI

No contributor_billing.go — lifecycle helpers live in GAF pkg/clibilling.

cliv2 wiring

globalEngine = clibilling.EnableIfConfigured(app.CreateAppEngineWithOptions(...))

globalEngine.GetAnalytics().SetCommand(name)   // cobra + legacy paths — unchanged
err = runWorkflowAndProcessData(globalContext, globalEngine, globalLogger, name)

// tearDown:
clibilling.FinishCommand(teardownCtx, globalEngine, globalConfiguration, exitCode == 0)

Build locally with -tags application (go build -tags application -o ~/bin/snyk-billing ./cmd/cliv2).

Test plan

  • make lint + make test in cliv2
  • Lazy-open E2E validated locally (snyk monitor → mitmweb shows ingest POST at tearDown)
  • CI security check (known failure — tracked separately)
  • Production E2E after GAF stack merges to main

Merge order

GAF #664#671#681this PR → E2E

brettgurman-snyk and others added 3 commits July 30, 2026 04:37
…-240]

Create one command-scoped capture bag for workflow and legacy proxy traffic,
call clibilling.Finish from tearDown on exit code 0, and remove the bespoke
legacy_contributor_billing emit path. Requires GAF 237+238; use local replace
for development until those land on main.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@snyk-io

snyk-io Bot commented Aug 3, 2026

Copy link
Copy Markdown

Snyk checks have failed. 2 issues have been found so far.

Status Scan Engine Critical High Medium Low Total (2)
Open Source Security 0 2 0 0 2 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Delegate bag lifecycle to GAF CaptureEngine (begin/finish at command
boundaries). Remove cliv2 networkinjector ctx and legacycli capture
duplication; GAF HTTP transport injection handles legacy proxy traffic.

Co-authored-by: Cursor <cursoragent@cursor.com>
@brettgurman-snyk brettgurman-snyk changed the title feat(cliv2): attach capture bag and finish billing at teardown [IANDT-240] feat(cliv2): enable CaptureEngine billing lifecycle [IANDT-240] Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️ There are multiple commits on your branch, please squash them locally before merging!
⚠️

"[refactor(cliv2): call clibilling BeginCommand/FinishCommand directly IANDT-240](https://api.github.com/repos/snyk/cli/git/commits/e0fbc5f8e328410326ee627306fd6ce96965be4f)" is too long. Keep the first line of your commit message under 72 characters.

⚠️

"[feat(cliv2): attach capture bag and finish billing in teardown IANDT-240](https://api.github.com/repos/snyk/cli/git/commits/e2e960204fc28fb04dfc66e85aa085f448192d17)" is too long. Keep the first line of your commit message under 72 characters.

Generated by 🚫 dangerJS against e0fbc5f

brettgurman-snyk and others added 3 commits August 3, 2026 01:14
…[IANDT-240]

Remove contributor_billing.go wrapper; host lifecycle helpers now live in GAF.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use pseudo-version from go-application-framework #681 so CI can
compile pkg/clibilling before the tagged release.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop BeginCommand and WithContributorBillingCapture; capture opens on first
billable HTTP and FinishCommand at teardown emits. Pin GAF to lazy-open stack.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor 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.

Verification results

Auto-approval check: this PR is not limited to a dependency bump. Besides the cliv2/go.mod/cliv2/go.sum version bump for go-application-framework, it also changes real logic in cliv2/pkg/core/main.go (wires clibilling.EnableIfConfigured into engine creation, adds clibilling.FinishCommand to teardown, and adds workflow.WithContext(globalContext) to the legacy-CLI invocation). Per policy, only pure dependency-bump PRs are auto-approved, so this one is not being auto-approved. I'm also not requesting changes (per policy this automation never sets a CHANGES_REQUESTED status) — see the findings below for the maintainers to weigh.

Four independent review passes (semantic analysis, adversarial review, security scan, code review) converged on the same core issue, so I'm confident in flagging it even though I'm not blocking the PR.

Critical

  • cliv2/pkg/core/main.go:549clibilling.FinishCommand(teardownCtx, globalEngine, globalConfiguration, exitCode == 0) uses the process exit code as the billing-success signal. But exitCode also encodes "scan found issues" (e.g. iac test --report — one of the two commands clibilling.IsBillableCommand returns true for — exits non-zero on its normal, expected outcome). finalizeContributorBilling skips emission whenever success is false, so a successful, billable scan that merely reports findings has its captured billing session silently discarded — defeating the PR's own purpose for its headline use case.
  • cliv2/pkg/core/main.go:549 — The wait for pending billing emits scales as numRecords * 5s and is not bounded by teardownCtx's own 5s deadline (the wait is a raw time.Duration, decoupled from the context). Any command capturing more than one billing record can make CLI process exit hang well past the 5s budget that teardownCtx/teardownTimeout was explicitly introduced to guarantee.
  • Related: clibilling.EnableIfConfigured registers a GAF post-invoke hook that closes/discards the capture bag on any top-level Invoke error. WORKFLOWID_REPORT_ANALYTICS (via sendInstrumentation) and WORKFLOWID_GLOBAL_CLEANUP, both invoked earlier in the same tearDown, are not exempted from this hook — so a transient analytics/cleanup failure before FinishCommand runs can discard billing data for an otherwise fully successful command.

Should Fix

  • cliv2/pkg/core/main.go:549FinishCommand's bool return value (whether emission completed before the wait budget elapsed) is discarded. Every sibling teardown step in this function logs its outcome; this one fails silently, hiding exactly the failure mode above.
  • No test coverage was added for the new wiring (EnableIfConfigured ordering before Init(), or FinishCommand's derived success value across exit-code cases).

Suggestion

  • cliv2/go.mod:25 — Pinned to a pre-release pseudo-version corresponding to an upstream PR (go-application-framework#681) that is still in draft. Already flagged by the PR's own comment/description as needing a re-pin before merge — just noting it renders here as well.
  • GitHub's security check on this head commit reports "Open Source Security: 2 High", but since no dependency other than the go-application-framework self-reference changed in go.sum, these findings (if genuine) most likely predate this diff rather than being introduced by it. Could not verify details without authenticated Snyk access — worth a human look.

Build, go vet, and go test ./pkg/core/... all pass against the pinned pre-release, and go mod tidy shows no drift, so the dependency bump itself is mechanically clean — the concerns above are all about the new main.go wiring logic.

Open in Web View Automation 

Sent by Cursor Automation: Automatic PR verification

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.

1 participant