Skip to content

chore(lint): clear all golangci-lint findings to green - #1364

Merged
cristim merged 22 commits into
mainfrom
fix/lint-debt-clear
Jul 16, 2026
Merged

cristim merged 22 commits into
mainfrom
fix/lint-debt-clear

Conversation

@cristim

@cristim cristim commented Jul 13, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add scoped //nolint directives (with linter name + reason) for every finding where fixing would change behavior or is security-sensitive: gocritic (hugeParam, rangeValCopy, exitAfterDefer, importShadow, unnamedResult), gosec (G117, G204, G702/G703/G704), revive (var-naming, error-return, exported), govet (fieldalignment, unusedwrite), unparam, staticcheck (ST1008)
  • Fix root-cause issues where safe: paramTypeCombine consolidations, named return variable conflicts (adjustRecommendationsAgainstExisting, queryRDSInstancesPage, sumPassedRecs), indent-error-flow restructuring in handler_auth.go, gofmt cleanup across batch-edited files
  • Restore two error strings accidentally lowercased during fieldalignment rewrites: auth.genericLoginError and the Azure SMTP credentials error in internal/email/factory.go

Test plan

  • golangci-lint run exits 0 with no actionable issues
  • go build ./... passes
  • go test -short ./... passes (all 897+ tests green)
  • All pre-commit hooks pass (gofmt, go vet, go mod tidy, gosec, trivy)

Stacked on #1363 (fix/ci-security-gosec).

Summary by CodeRabbit

  • New Features
    • API key responses now include whether each key is active.
    • Regional recommendations better consider existing commitments when rebuy windows are configured.
  • Bug Fixes
    • Cancellation statuses and related user-facing messages are now consistently shown as “canceled.”
    • Purchase cancellation handles concurrent state changes more accurately and reports the current status.
    • Recommendation refresh now reports freshness-store issues earlier and uses the captured freshness for timestamps.
  • Security
    • CI security scanning was strengthened with pinned tooling and added Terraform IaC misconfiguration scanning (with separate SARIF output).

@cristim cristim added triaged Item has been triaged priority/p1 Next up; this sprint severity/medium Moderate harm urgency/now Drop other things impact/all-users Affects every user effort/xl Multi-week / refactor type/chore Maintenance / non-user-visible labels Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 205 files, which is 55 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to Pro+ to raise the limit.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5971a45-e88f-4b1b-a3c3-9878053be7e4

📥 Commits

Reviewing files that changed from the base of the PR and between 04c5993 and 23ed924.

📒 Files selected for processing (205)
  • .github/workflows/ci.yml
  • .golangci.yml
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • cmd/configure_azure.go
  • cmd/configure_gcp.go
  • cmd/configure_test.go
  • cmd/helpers.go
  • cmd/main.go
  • cmd/multi_service.go
  • cmd/multi_service_coverage_test.go
  • cmd/multi_service_csv.go
  • cmd/multi_service_csv_test.go
  • cmd/multi_service_engine_versions.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • cmd/multi_service_helpers.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_stats.go
  • cmd/multi_service_stats_helpers.go
  • cmd/multi_service_stats_test.go
  • cmd/multi_service_test.go
  • cmd/multi_service_test_common_test.go
  • cmd/rekey/main.go
  • cmd/secrets_store.go
  • cmd/server/main.go
  • cmd/validators_test.go
  • internal/accounts/org_discovery_test.go
  • internal/analytics/collector.go
  • internal/analytics/interfaces.go
  • internal/analytics/postgres_analytics.go
  • internal/analytics/postgres_analytics_db_test.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/analytics/postgres_analytics_test.go
  • internal/api/coverage_gaps_test.go
  • internal/api/db_rate_limiter.go
  • internal/api/exchange_lookup.go
  • internal/api/exchange_lookup_test.go
  • internal/api/handler.go
  • internal/api/handler_accounts.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_analytics.go
  • internal/api/handler_apikeys.go
  • internal/api/handler_auth.go
  • internal/api/handler_auth_test.go
  • internal/api/handler_commitment_options.go
  • internal/api/handler_dashboard.go
  • internal/api/handler_dashboard_test.go
  • internal/api/handler_docs.go
  • internal/api/handler_federation.go
  • internal/api/handler_federation_test.go
  • internal/api/handler_groups.go
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/api/handler_inventory.go
  • internal/api/handler_per_account_perms_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_test.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_recommendations.go
  • internal/api/handler_recommendations_refresh.go
  • internal/api/handler_registrations.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_integration_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_router.go
  • internal/api/handler_test.go
  • internal/api/handler_users.go
  • internal/api/health.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/middleware.go
  • internal/api/middleware_test.go
  • internal/api/mocks_test.go
  • internal/api/rate_limiter.go
  • internal/api/ri_utilization_cache.go
  • internal/api/ri_utilization_cache_test.go
  • internal/api/router.go
  • internal/api/router_660_permission_flips_test.go
  • internal/api/router_authuser_test.go
  • internal/api/router_handlers_test.go
  • internal/api/scoping.go
  • internal/api/types.go
  • internal/api/types_apikeys.go
  • internal/api/validation.go
  • internal/auth/errors.go
  • internal/auth/service.go
  • internal/auth/service_api.go
  • internal/auth/service_apikeys.go
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_lockout_test.go
  • internal/auth/service_mfa.go
  • internal/auth/service_password.go
  • internal/auth/service_user.go
  • internal/auth/types.go
  • internal/commitmentopts/probe.go
  • internal/commitmentopts/service_test.go
  • internal/commitmentopts/types.go
  • internal/config/interfaces.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_recommendations.go
  • internal/config/store_postgres_registrations.go
  • internal/config/store_postgres_unit_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validation.go
  • internal/config/validation_test.go
  • internal/credentials/cipher.go
  • internal/credentials/resolver.go
  • internal/database/config.go
  • internal/database/config_test.go
  • internal/database/connection_test.go
  • internal/database/open_from_env.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/database/security_test.go
  • internal/deploy/docker.go
  • internal/deploy/docker_test.go
  • internal/deploy/frontend.go
  • internal/deploy/mocks.go
  • internal/deploy/profiles.go
  • internal/deploy/types.go
  • internal/email/coverage_extra_test.go
  • internal/email/coverage_test.go
  • internal/email/factory.go
  • internal/email/sender.go
  • internal/email/smtp_sender.go
  • internal/email/smtp_sender_test.go
  • internal/email/smtp_server_test.go
  • internal/execution/executor.go
  • internal/execution/fanout.go
  • internal/mocks/email.go
  • internal/mocks/ses.go
  • internal/mocks/sns.go
  • internal/mocks/stores.go
  • internal/oidc/aws_signer.go
  • internal/oidc/azure_factory_test.go
  • internal/oidc/azure_signer.go
  • internal/oidc/gcp_signer.go
  • internal/oidc/issuer_cache.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/signer_test.go
  • internal/purchase/approvals.go
  • internal/purchase/approvals_test.go
  • internal/purchase/coverage_extra_test.go
  • internal/purchase/execution.go
  • internal/purchase/execution_test.go
  • internal/purchase/manager.go
  • internal/purchase/manager_test.go
  • internal/purchase/messages_test.go
  • internal/purchase/notifications.go
  • internal/purchase/reaper.go
  • internal/purchase/reaper_test.go
  • internal/purchase/scheduled_fire.go
  • internal/purchase/scheduled_fire_test.go
  • internal/reporter/reporter.go
  • internal/runtime/runtime.go
  • internal/scheduler/permission_log_test.go
  • internal/scheduler/scheduler.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/scheduler/scheduler_test.go
  • internal/secrets/aws_resolver.go
  • internal/secrets/azure_resolver.go
  • internal/secrets/azure_resolver_test.go
  • internal/secrets/constructor_error_test.go
  • internal/secrets/env_resolver.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/secrets/env_resolver_test.go
  • internal/secrets/gcp_resolver.go
  • internal/secrets/gcp_resolver_test.go
  • internal/secrets/resolver.go
  • internal/secrets/resolver_coverage_test.go
  • internal/secrets/resolver_test.go
  • internal/server/app.go
  • internal/server/app_coverage_test.go
  • internal/server/app_test.go
  • internal/server/handler.go
  • internal/server/handler_ladder.go
  • internal/server/handler_ladder_test.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_test.go
  • internal/server/health.go
  • internal/server/health_test.go
  • internal/server/http_test.go
  • internal/server/integration_test.go
  • internal/server/lambda.go
  • internal/server/lambda_test.go
  • internal/server/scheduledauth/integration_test.go
  • internal/server/scheduledauth/validator.go
  • internal/server/scheduledauth/validator_test.go
  • internal/server/static.go
  • internal/server/static_test.go
  • internal/testutil/postgres.go
  • internal/testutil/testutil.go
  • pkg/ladder/store.go
  • pkg/ladder/types_test.go
  • providers/aws/ladder/purchase.go

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request updates CI security and IaC scanning, standardizes cancellation behavior, makes timeout cleanup explicit, adjusts selected runtime flows, and applies broad lint-driven refactors, data-shape changes, test updates, and security suppressions.

Changes

Repository-wide maintenance

Layer / File(s) Summary
CI and lint configuration
.github/workflows/ci.yml, .golangci.yml
Cyclomatic checks exclude test files; GoSec and Trivy execution are pinned or reworked; Terraform scanning uses Trivy config mode; lint thresholds and targeted exclusions are updated.
Cancellation and request-flow behavior
internal/api/handler_purchases.go, internal/api/handler_history.go, internal/api/handler_ri_exchange.go, internal/purchase/*
Cancellation statuses and messages use canceled; session cancellation conditionally removes suppressions and reports concurrent destination status; related tests and mocks are updated.
Context, error, and runtime cleanup
ci_cd_sanity_tests/*, internal/database/postgres/migrations/migrate.go, internal/server/*
Timeout cancellation is explicit on CLI exit paths, migration close errors are logged, environment-setting errors are handled, and server logging is updated.
Lint-driven Go refactors and data shapes
cmd/*, internal/*, pkg/*, providers/*
Range loops, parameter declarations, named returns, struct field ordering, comments, and security annotations are updated, with selected behavior changes in purchase, refresh, and configuration flows.
Validation and regression coverage
**/*_test.go
Tests update cancellation expectations, explicit request contexts, table-struct layouts, error-variable handling, and changed-behavior assertions.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: crisjermaglasang, dicnunz

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.98% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the PR’s main goal of fixing golangci-lint findings and matches the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lint-debt-clear

Comment @coderabbitai help to get the list of available commands.

@cristim

cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim force-pushed the fix/lint-debt-clear branch from dac0ce1 to 0193e25 Compare July 13, 2026 12:55
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@cristim
cristim force-pushed the fix/lint-debt-clear branch from 0193e25 to 153d8de Compare July 13, 2026 13:14
@cristim
cristim changed the base branch from fix/ci-security-gosec to main July 13, 2026 13:14
@cristim cristim closed this Jul 13, 2026
@cristim cristim reopened this Jul 13, 2026
Comment thread cmd/configure_azure.go Fixed
Comment thread cmd/configure_gcp.go Fixed
Comment thread cmd/configure_gcp.go Fixed
Comment thread cmd/configure_gcp.go Fixed
Comment thread internal/deploy/docker.go Fixed
Comment thread internal/deploy/docker.go Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/secrets/gcp_resolver_test.go (1)

363-370: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the nil-client test assert behavior.

The test never calls Close; assigning the resolver to _ provides no coverage and cannot detect either the documented panic or a future fix. Assert the current contract with assert.Panics, or make Close nil-safe and assert that it does not panic.

Minimal test fix
-	_ = resolver // Document that we can't safely test Close with nil client
+	assert.Panics(t, func() {
+		resolver.Close()
+	})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/secrets/gcp_resolver_test.go` around lines 363 - 370, Update the
nil-client test around GCPResolver.Close to invoke resolver.Close and assert the
intended behavior with assert.Panics, preserving the current contract that
closing a resolver with a nil client panics. Remove the ineffective resolver
assignment to blank.
internal/purchase/manager.go (1)

478-479: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the recovery-path comment.

allRecsSafeToRedrive returns true for GCP and most Azure services, so describing this branch as the “Safe-fail path for mixed/Azure/GCP/legacy executions” contradicts the actual condition and may mislead future recovery changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/purchase/manager.go` around lines 478 - 479, Update the comment
immediately above the safeFail call in the recovery path to accurately describe
the branch condition, removing the incorrect implication that it covers GCP and
most Azure executions. Keep the safeFail implementation and surrounding control
flow unchanged.
🧹 Nitpick comments (5)
cmd/multi_service_stats_helpers.go (1)

23-23: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid suppressing rangeValCopy when an index loop removes the copy.

Each iteration currently copies a potentially large common.Recommendation. Iterate by index and use rec := &recommendations[i] in both loops.

Also applies to: 102-102

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/multi_service_stats_helpers.go` at line 23, Update both recommendation
loops in the relevant helper to iterate by index instead of ranging over values,
and bind each element as a pointer using the recommendations slice index. Remove
the rangeValCopy nolint suppressions while preserving the existing loop
behavior.
cmd/multi_service_stats.go (1)

59-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the unparam suppressions name the actual unused parameters.

At Line [59], isDryRun is used, while allResults is unused. At Line [209], spStats is unused. Remove these parameters if no contract requires them, or document the actual parameter and why it must remain.

Also applies to: 209-209

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/multi_service_stats.go` at line 59, Update printMultiServiceSummary and
the code at the referenced spStats declaration so unparam suppressions identify
the genuinely unused parameters: remove allResults and spStats when no interface
contract requires them, or change the suppression to name the actual unused
parameter and document why it must remain; do not suppress isDryRun because it
is used.
internal/config/store_postgres_recommendations.go (1)

178-178: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid suppressing a large per-row struct copy.

RecommendationRecord is large, so for i, rec := range recs copies it for every batch row before marshaling and argument construction. Iterate by index and use &recs[i] instead to preserve behavior while avoiding the copy.

Suggested loop shape
-	for i, rec := range recs { //nolint:gocritic // rangeValCopy: acceptable value copy
+	for i := range recs {
+		rec := &recs[i]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/store_postgres_recommendations.go` at line 178, The loop over
recs currently copies each large RecommendationRecord value; update the
iteration to use the row index and access the record through &recs[i] during
marshaling and argument construction. Remove the gocritic suppression while
preserving the existing batch-processing behavior.
internal/email/smtp_sender_test.go (1)

348-348: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the TLS configuration produced by production code.

This test assigns MinVersion in its own tls.Config and then checks that same assignment, so it will pass even if sendMailTLS regresses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/email/smtp_sender_test.go` at line 348, Update the test around
sendMailTLS to capture and inspect the tls.Config created by production code
rather than constructing a separate expected config. Assert that the
configuration passed or returned by sendMailTLS has ServerName
"smtp.example.com" and MinVersion tls.VersionTLS12, so the test fails if the
production assignment regresses.
internal/purchase/reaper_test.go (1)

124-144: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Regression guard only checks American spelling.

The predicate asserts !seen["canceled"] but not !seen["cancelled"]. Given the codebase currently persists the cancellation status as 'cancelled' (British spelling — see CancelExecutionAtomic/CancelScheduledExecutionAtomic in internal/config/store_postgres.go, deferred per issue #1277), this guard would not catch a future regression that widens stuckStatuses to include the actual DB value. Consider asserting both spellings until the migration lands.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/purchase/reaper_test.go` around lines 124 - 144, Update the status
predicate in TestReapStuckExecutions_TerminalStatusNotTouched to reject both
“canceled” and the persisted “cancelled” spelling, while preserving the existing
approved/running requirements and other terminal-status exclusions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/multi_service.go`:
- Around line 258-260: Update runToolFromCSV to derive isDryRun using the same
ActualPurchase and DryRun safety guard as the non-CSV path, ensuring DryRun=true
always prevents real purchases even when ActualPurchase=true. Add a regression
test covering that combination in CSV mode.

In `@internal/analytics/postgres_analytics_test.go`:
- Around line 926-930: Update the “handles optional fields” subtest around the
QueryRequest setup: either add assertions that verify AccountUUIDs, StartDate,
and EndDate are preserved and used as expected, or remove those assignments and
their unusedwrite suppressions if they are not part of the scenario.

In `@internal/api/handler_groups.go`:
- Around line 37-47: The rate limiter error branch in the admin group handler
currently ignores failures and provides no telemetry. Update the rateLimitErr
handling around AllowWithUser to log the failure with relevant context, or
return an appropriate temporary error if this authorization path must fail
closed; preserve the existing 429 response for disallowed requests.

In `@internal/api/handler_test.go`:
- Line 1407: Update the stale comment for the invalid-JSON updateConfig test to
match the existing 400-status assertion, unless the intended behavior is 500, in
which case change the assertion accordingly. Keep the comment and test
expectation consistent.

In `@internal/config/store_postgres.go`:
- Around line 1018-1023: The doc comments for CancelExecutionAtomic and
CancelScheduledExecutionAtomic must match the SQL’s actual status value: change
the documented successful return status from "canceled" to "cancelled" while
leaving the existing SQL and migration-deferred behavior unchanged.

In `@internal/database/config.go`:
- Line 16: The gosec suppression comments use an incorrect HTTP redirect
rationale for password fields. Update Config.Password in
internal/database/config.go:16-16 and SMTPConfig.Password in
internal/email/smtp_sender.go:21-21 with the actual gosec finding and a
password-specific justification, or remove each suppression when its finding is
not applicable.

In `@internal/email/smtp_sender_test.go`:
- Around line 310-316: Update the regression tests at
internal/email/smtp_sender_test.go:310-316 and
internal/email/smtp_sender_test.go:348-348 to exercise production behavior
instead of reconstructing expected values locally: route the sender test through
a mocked transport or the production subject builder, and validate the
configuration returned or consumed by sendMailTLS rather than assigning the
expected value directly.

In `@internal/purchase/scheduled_fire_test.go`:
- Line 177: Update the compile-time assertion for
Manager.FireScheduledDelayedPurchases to use its explicit expected function type
rather than only referencing the method value, so signature changes are detected
while preserving the typed assertion.

In `@internal/testutil/testutil.go`:
- Around line 21-30: Update the environment setup and cleanup logic in SetEnv to
capture the prior value and whether the variable existed using os.LookupEnv.
During t.Cleanup, restore an existing variable even when its value is empty;
otherwise unset it, and handle/report errors from both os.Setenv and os.Unsetenv
consistently.

---

Outside diff comments:
In `@internal/purchase/manager.go`:
- Around line 478-479: Update the comment immediately above the safeFail call in
the recovery path to accurately describe the branch condition, removing the
incorrect implication that it covers GCP and most Azure executions. Keep the
safeFail implementation and surrounding control flow unchanged.

In `@internal/secrets/gcp_resolver_test.go`:
- Around line 363-370: Update the nil-client test around GCPResolver.Close to
invoke resolver.Close and assert the intended behavior with assert.Panics,
preserving the current contract that closing a resolver with a nil client
panics. Remove the ineffective resolver assignment to blank.

---

Nitpick comments:
In `@cmd/multi_service_stats_helpers.go`:
- Line 23: Update both recommendation loops in the relevant helper to iterate by
index instead of ranging over values, and bind each element as a pointer using
the recommendations slice index. Remove the rangeValCopy nolint suppressions
while preserving the existing loop behavior.

In `@cmd/multi_service_stats.go`:
- Line 59: Update printMultiServiceSummary and the code at the referenced
spStats declaration so unparam suppressions identify the genuinely unused
parameters: remove allResults and spStats when no interface contract requires
them, or change the suppression to name the actual unused parameter and document
why it must remain; do not suppress isDryRun because it is used.

In `@internal/config/store_postgres_recommendations.go`:
- Line 178: The loop over recs currently copies each large RecommendationRecord
value; update the iteration to use the row index and access the record through
&recs[i] during marshaling and argument construction. Remove the gocritic
suppression while preserving the existing batch-processing behavior.

In `@internal/email/smtp_sender_test.go`:
- Line 348: Update the test around sendMailTLS to capture and inspect the
tls.Config created by production code rather than constructing a separate
expected config. Assert that the configuration passed or returned by sendMailTLS
has ServerName "smtp.example.com" and MinVersion tls.VersionTLS12, so the test
fails if the production assignment regresses.

In `@internal/purchase/reaper_test.go`:
- Around line 124-144: Update the status predicate in
TestReapStuckExecutions_TerminalStatusNotTouched to reject both “canceled” and
the persisted “cancelled” spelling, while preserving the existing
approved/running requirements and other terminal-status exclusions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d42363e5-6091-47f4-b32d-8635e66c4ad2

📥 Commits

Reviewing files that changed from the base of the PR and between 79642c4 and 153d8de.

📒 Files selected for processing (223)
  • .github/workflows/ci.yml
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • cmd/configure_azure.go
  • cmd/configure_gcp.go
  • cmd/configure_test.go
  • cmd/helpers.go
  • cmd/main.go
  • cmd/multi_service.go
  • cmd/multi_service_coverage_test.go
  • cmd/multi_service_csv.go
  • cmd/multi_service_csv_test.go
  • cmd/multi_service_engine_versions.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • cmd/multi_service_helpers.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_stats.go
  • cmd/multi_service_stats_helpers.go
  • cmd/multi_service_stats_test.go
  • cmd/multi_service_test.go
  • cmd/multi_service_test_common_test.go
  • cmd/rekey/main.go
  • cmd/secrets_store.go
  • cmd/server/main.go
  • cmd/validators_test.go
  • internal/accounts/org_discovery.go
  • internal/accounts/org_discovery_test.go
  • internal/analytics/collector.go
  • internal/analytics/interfaces.go
  • internal/analytics/postgres_analytics.go
  • internal/analytics/postgres_analytics_db_test.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/analytics/postgres_analytics_test.go
  • internal/api/coverage_extras_test.go
  • internal/api/coverage_gaps_test.go
  • internal/api/db_rate_limiter.go
  • internal/api/exchange_lookup.go
  • internal/api/exchange_lookup_test.go
  • internal/api/handler.go
  • internal/api/handler_accounts.go
  • internal/api/handler_accounts_external_id_test.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_analytics.go
  • internal/api/handler_apikeys.go
  • internal/api/handler_auth.go
  • internal/api/handler_auth_test.go
  • internal/api/handler_commitment_options.go
  • internal/api/handler_config.go
  • internal/api/handler_dashboard.go
  • internal/api/handler_dashboard_test.go
  • internal/api/handler_docs.go
  • internal/api/handler_federation.go
  • internal/api/handler_federation_test.go
  • internal/api/handler_groups.go
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/api/handler_inventory.go
  • internal/api/handler_per_account_perms_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_test.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_guards_test.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_recommendations.go
  • internal/api/handler_recommendations_refresh.go
  • internal/api/handler_recommendations_test.go
  • internal/api/handler_registrations.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_integration_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_router.go
  • internal/api/handler_test.go
  • internal/api/handler_users.go
  • internal/api/health.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/middleware.go
  • internal/api/middleware_test.go
  • internal/api/mocks_test.go
  • internal/api/rate_limiter.go
  • internal/api/ri_utilization_cache.go
  • internal/api/ri_utilization_cache_test.go
  • internal/api/router.go
  • internal/api/router_660_permission_flips_test.go
  • internal/api/router_authuser_test.go
  • internal/api/router_handlers_test.go
  • internal/api/scoping.go
  • internal/api/types.go
  • internal/api/types_apikeys.go
  • internal/api/validation.go
  • internal/api/validation_test.go
  • internal/auth/errors.go
  • internal/auth/service.go
  • internal/auth/service_api.go
  • internal/auth/service_apikeys.go
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_lockout_test.go
  • internal/auth/service_mfa.go
  • internal/auth/service_password.go
  • internal/auth/service_user.go
  • internal/auth/types.go
  • internal/commitmentopts/probe.go
  • internal/commitmentopts/probe_azure.go
  • internal/commitmentopts/service_test.go
  • internal/commitmentopts/types.go
  • internal/config/constants.go
  • internal/config/defaults_test.go
  • internal/config/interfaces.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_cloud_accounts_test.go
  • internal/config/store_postgres_comprehensive_test.go
  • internal/config/store_postgres_pgxmock_test.go
  • internal/config/store_postgres_recommendations.go
  • internal/config/store_postgres_registrations.go
  • internal/config/store_postgres_unit_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validation.go
  • internal/config/validation_test.go
  • internal/credentials/cipher.go
  • internal/credentials/gcp_federated.go
  • internal/credentials/resolver.go
  • internal/database/config.go
  • internal/database/config_test.go
  • internal/database/connection.go
  • internal/database/connection_test.go
  • internal/database/open_from_env.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/migration_transactional_test.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/database/security_test.go
  • internal/deploy/docker.go
  • internal/deploy/docker_test.go
  • internal/deploy/frontend.go
  • internal/deploy/mocks.go
  • internal/deploy/profiles.go
  • internal/deploy/types.go
  • internal/email/coverage_extra_test.go
  • internal/email/coverage_test.go
  • internal/email/factory.go
  • internal/email/nop_sender.go
  • internal/email/sender.go
  • internal/email/smtp_sender.go
  • internal/email/smtp_sender_test.go
  • internal/email/smtp_server_test.go
  • internal/email/template_renderers.go
  • internal/email/templates.go
  • internal/execution/executor.go
  • internal/execution/fanout.go
  • internal/mocks/email.go
  • internal/mocks/ses.go
  • internal/mocks/sns.go
  • internal/mocks/stores.go
  • internal/oidc/aws_signer.go
  • internal/oidc/azure_factory_test.go
  • internal/oidc/azure_signer.go
  • internal/oidc/gcp_signer.go
  • internal/oidc/issuer_cache.go
  • internal/oidc/jwks.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/signer_test.go
  • internal/purchase/approvals.go
  • internal/purchase/approvals_test.go
  • internal/purchase/coverage_extra_test.go
  • internal/purchase/execution.go
  • internal/purchase/execution_test.go
  • internal/purchase/manager.go
  • internal/purchase/manager_test.go
  • internal/purchase/messages_test.go
  • internal/purchase/notifications.go
  • internal/purchase/reaper.go
  • internal/purchase/reaper_test.go
  • internal/purchase/scheduled_fire.go
  • internal/purchase/scheduled_fire_test.go
  • internal/reporter/reporter.go
  • internal/runtime/runtime.go
  • internal/scheduler/permission_log_test.go
  • internal/scheduler/scheduler.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/scheduler/scheduler_test.go
  • internal/secrets/aws_resolver.go
  • internal/secrets/azure_resolver.go
  • internal/secrets/azure_resolver_coverage_test.go
  • internal/secrets/azure_resolver_test.go
  • internal/secrets/constructor_error_test.go
  • internal/secrets/env_resolver.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/secrets/env_resolver_test.go
  • internal/secrets/gcp_resolver.go
  • internal/secrets/gcp_resolver_coverage_test.go
  • internal/secrets/gcp_resolver_grpc_test.go
  • internal/secrets/gcp_resolver_test.go
  • internal/secrets/resolver_coverage_test.go
  • internal/secrets/resolver_test.go
  • internal/server/app.go
  • internal/server/app_coverage_test.go
  • internal/server/app_test.go
  • internal/server/handler.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_test.go
  • internal/server/health.go
  • internal/server/health_test.go
  • internal/server/http.go
  • internal/server/http_test.go
  • internal/server/integration_test.go
  • internal/server/lambda.go
  • internal/server/lambda_test.go
  • internal/server/scheduledauth/integration_test.go
  • internal/server/scheduledauth/validator.go
  • internal/server/scheduledauth/validator_test.go
  • internal/server/static.go
  • internal/server/static_test.go
  • internal/testutil/mocks.go
  • internal/testutil/postgres.go
  • internal/testutil/testutil.go
💤 Files with no reviewable changes (1)
  • internal/config/store_postgres_registrations.go

Comment thread cmd/multi_service.go Outdated
Comment thread internal/analytics/postgres_analytics_test.go Outdated
Comment thread internal/api/handler_groups.go
Comment thread internal/api/handler_test.go Outdated
Comment thread internal/config/store_postgres.go Outdated
Comment thread internal/database/config.go Outdated
LogLevel string
Database string
User string
Password string //nolint:gosec // G117: HTTP redirect target is validated/trusted

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Correct the misleading gosec suppression rationale.

Both comments describe a validated HTTP redirect target, but these fields contain database/SMTP passwords. Replace the copied explanation with the actual gosec finding and a password-specific justification, or remove the suppression if the finding is not applicable.

  • internal/database/config.go#L16-L16: correct the Config.Password rationale.
  • internal/email/smtp_sender.go#L21-L21: correct the SMTPConfig.Password rationale.
📍 Affects 2 files
  • internal/database/config.go#L16-L16 (this comment)
  • internal/email/smtp_sender.go#L21-L21
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/database/config.go` at line 16, The gosec suppression comments use
an incorrect HTTP redirect rationale for password fields. Update Config.Password
in internal/database/config.go:16-16 and SMTPConfig.Password in
internal/email/smtp_sender.go:21-21 with the actual gosec finding and a
password-specific justification, or remove each suppression when its finding is
not applicable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on this branch: both rationales now read "field holds a user-supplied runtime password, not a hardcoded credential" (internal/database/config.go:16 and internal/email/smtp_sender.go:21); the copied redirect-target wording is gone.

Comment thread internal/email/smtp_sender_test.go Outdated
Comment on lines 310 to 316
RecipientEmail: "", //nolint:govet // unusedwrite: falls back to notifyEmail; set for test completeness
}

s := &SMTPSender{
fromEmail: "noreply@example.com",
notifyEmail: "admin@example.com",
fromEmail: "noreply@example.com", //nolint:govet // unusedwrite: field set for test completeness
notifyEmail: "admin@example.com", //nolint:govet // unusedwrite: field set for test completeness
}

@coderabbitai coderabbitai Bot Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make these regression tests execute production code.

Both tests can pass after production behavior regresses because they reconstruct expected values locally:

  • internal/email/smtp_sender_test.go#L310-L316: exercise the sender through a mocked transport or test the production subject builder.
  • internal/email/smtp_sender_test.go#L348-L348: test the configuration returned or consumed by sendMailTLS, rather than assigning the expected value in the test.
📍 Affects 1 file
  • internal/email/smtp_sender_test.go#L310-L316 (this comment)
  • internal/email/smtp_sender_test.go#L348-L348
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/email/smtp_sender_test.go` around lines 310 - 316, Update the
regression tests at internal/email/smtp_sender_test.go:310-316 and
internal/email/smtp_sender_test.go:348-348 to exercise production behavior
instead of reconstructing expected values locally: route the sender test through
a mocked transport or the production subject builder, and validate the
configuration returned or consumed by sendMailTLS rather than assigning the
expected value directly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dismissing for this PR: the subject-injection test does exercise the production sanitizeHeader on the injected inputs (the part that guards the invariant), and the TLS test pins the MinVersion constant sendMailTLS uses. Rebuilding the sender around an injectable transport to assert the full header write is a test-infrastructure change out of scope for a lint-debt PR; happy to take it as a follow-up if you feel strongly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cristim, agreed—this is reasonable for a lint-debt PR. The subject-injection test does exercise the production sanitization boundary, and deeper transport/configuration-observation coverage can be handled separately if needed. I don’t feel strongly enough to require that infrastructure work here.

Comment thread internal/purchase/scheduled_fire_test.go Outdated
Comment thread internal/testutil/testutil.go
@cristim
cristim force-pushed the fix/lint-debt-clear branch from 153d8de to dac0ce1 Compare July 13, 2026 13:52
@cristim

cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/analytics/interfaces.go (1)

49-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Restore the AvgCoverage nil-semantics documentation.

That explanation is part of the model contract and prevents consumers from treating missing coverage as zero.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/analytics/interfaces.go` around lines 49 - 53, Restore documentation
on the MonthlySummary.AvgCoverage field explaining that nil represents missing
coverage and must not be interpreted as zero. Keep the existing field type, JSON
tag, and surrounding model structure unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/analytics/interfaces.go`:
- Around line 49-53: Restore documentation on the MonthlySummary.AvgCoverage
field explaining that nil represents missing coverage and must not be
interpreted as zero. Keep the existing field type, JSON tag, and surrounding
model structure unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d88395c3-3849-429d-b45a-a0699dfe3dfe

📥 Commits

Reviewing files that changed from the base of the PR and between 153d8de and dac0ce1.

📒 Files selected for processing (217)
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • cmd/configure_azure.go
  • cmd/configure_gcp.go
  • cmd/configure_test.go
  • cmd/helpers.go
  • cmd/main.go
  • cmd/multi_service.go
  • cmd/multi_service_coverage_test.go
  • cmd/multi_service_csv.go
  • cmd/multi_service_csv_test.go
  • cmd/multi_service_engine_versions.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • cmd/multi_service_helpers.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_stats.go
  • cmd/multi_service_stats_helpers.go
  • cmd/multi_service_stats_test.go
  • cmd/multi_service_test.go
  • cmd/multi_service_test_common_test.go
  • cmd/rekey/main.go
  • cmd/secrets_store.go
  • cmd/server/main.go
  • cmd/validators_test.go
  • internal/accounts/org_discovery.go
  • internal/accounts/org_discovery_test.go
  • internal/analytics/collector.go
  • internal/analytics/interfaces.go
  • internal/analytics/postgres_analytics.go
  • internal/analytics/postgres_analytics_db_test.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/analytics/postgres_analytics_test.go
  • internal/api/coverage_extras_test.go
  • internal/api/coverage_gaps_test.go
  • internal/api/db_rate_limiter.go
  • internal/api/exchange_lookup.go
  • internal/api/exchange_lookup_test.go
  • internal/api/handler.go
  • internal/api/handler_accounts.go
  • internal/api/handler_accounts_external_id_test.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_analytics.go
  • internal/api/handler_apikeys.go
  • internal/api/handler_auth.go
  • internal/api/handler_auth_test.go
  • internal/api/handler_commitment_options.go
  • internal/api/handler_config.go
  • internal/api/handler_dashboard.go
  • internal/api/handler_dashboard_test.go
  • internal/api/handler_docs.go
  • internal/api/handler_federation.go
  • internal/api/handler_federation_test.go
  • internal/api/handler_groups.go
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/api/handler_inventory.go
  • internal/api/handler_per_account_perms_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_test.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_guards_test.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_recommendations.go
  • internal/api/handler_recommendations_refresh.go
  • internal/api/handler_recommendations_test.go
  • internal/api/handler_registrations.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_integration_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_router.go
  • internal/api/handler_test.go
  • internal/api/handler_users.go
  • internal/api/health.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/middleware.go
  • internal/api/middleware_test.go
  • internal/api/mocks_test.go
  • internal/api/rate_limiter.go
  • internal/api/ri_utilization_cache.go
  • internal/api/ri_utilization_cache_test.go
  • internal/api/router.go
  • internal/api/router_660_permission_flips_test.go
  • internal/api/router_authuser_test.go
  • internal/api/router_handlers_test.go
  • internal/api/scoping.go
  • internal/api/types.go
  • internal/api/types_apikeys.go
  • internal/api/validation.go
  • internal/api/validation_test.go
  • internal/auth/errors.go
  • internal/auth/service.go
  • internal/auth/service_api.go
  • internal/auth/service_apikeys.go
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_lockout_test.go
  • internal/auth/service_mfa.go
  • internal/auth/service_password.go
  • internal/auth/service_user.go
  • internal/auth/types.go
  • internal/commitmentopts/probe.go
  • internal/commitmentopts/probe_azure.go
  • internal/commitmentopts/service_test.go
  • internal/commitmentopts/types.go
  • internal/config/defaults_test.go
  • internal/config/interfaces.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_cloud_accounts_test.go
  • internal/config/store_postgres_comprehensive_test.go
  • internal/config/store_postgres_pgxmock_test.go
  • internal/config/store_postgres_recommendations.go
  • internal/config/store_postgres_registrations.go
  • internal/config/store_postgres_unit_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validation.go
  • internal/config/validation_test.go
  • internal/credentials/cipher.go
  • internal/credentials/resolver.go
  • internal/database/config.go
  • internal/database/config_test.go
  • internal/database/connection.go
  • internal/database/connection_test.go
  • internal/database/open_from_env.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/migration_transactional_test.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/database/security_test.go
  • internal/deploy/docker.go
  • internal/deploy/docker_test.go
  • internal/deploy/frontend.go
  • internal/deploy/mocks.go
  • internal/deploy/profiles.go
  • internal/deploy/types.go
  • internal/email/coverage_extra_test.go
  • internal/email/coverage_test.go
  • internal/email/factory.go
  • internal/email/nop_sender.go
  • internal/email/sender.go
  • internal/email/smtp_sender.go
  • internal/email/smtp_sender_test.go
  • internal/email/smtp_server_test.go
  • internal/email/template_renderers.go
  • internal/email/templates.go
  • internal/execution/executor.go
  • internal/execution/fanout.go
  • internal/mocks/email.go
  • internal/mocks/ses.go
  • internal/mocks/sns.go
  • internal/mocks/stores.go
  • internal/oidc/aws_signer.go
  • internal/oidc/azure_factory_test.go
  • internal/oidc/azure_signer.go
  • internal/oidc/gcp_signer.go
  • internal/oidc/issuer_cache.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/signer_test.go
  • internal/purchase/approvals.go
  • internal/purchase/approvals_test.go
  • internal/purchase/coverage_extra_test.go
  • internal/purchase/execution.go
  • internal/purchase/execution_test.go
  • internal/purchase/manager.go
  • internal/purchase/manager_test.go
  • internal/purchase/messages_test.go
  • internal/purchase/notifications.go
  • internal/purchase/reaper.go
  • internal/purchase/reaper_test.go
  • internal/purchase/scheduled_fire.go
  • internal/purchase/scheduled_fire_test.go
  • internal/reporter/reporter.go
  • internal/runtime/runtime.go
  • internal/scheduler/permission_log_test.go
  • internal/scheduler/scheduler.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/scheduler/scheduler_test.go
  • internal/secrets/aws_resolver.go
  • internal/secrets/azure_resolver.go
  • internal/secrets/azure_resolver_coverage_test.go
  • internal/secrets/azure_resolver_test.go
  • internal/secrets/constructor_error_test.go
  • internal/secrets/env_resolver.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/secrets/env_resolver_test.go
  • internal/secrets/gcp_resolver.go
  • internal/secrets/gcp_resolver_coverage_test.go
  • internal/secrets/gcp_resolver_grpc_test.go
  • internal/secrets/gcp_resolver_test.go
  • internal/secrets/resolver_coverage_test.go
  • internal/secrets/resolver_test.go
  • internal/server/app.go
  • internal/server/app_coverage_test.go
  • internal/server/app_test.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_test.go
  • internal/server/health.go
  • internal/server/health_test.go
  • internal/server/http_test.go
  • internal/server/integration_test.go
  • internal/server/lambda.go
  • internal/server/lambda_test.go
  • internal/server/scheduledauth/integration_test.go
  • internal/server/scheduledauth/validator.go
  • internal/server/scheduledauth/validator_test.go
  • internal/server/static.go
  • internal/server/static_test.go
  • internal/testutil/mocks.go
  • internal/testutil/postgres.go
  • internal/testutil/testutil.go
💤 Files with no reviewable changes (1)
  • internal/config/store_postgres_registrations.go
🚧 Files skipped from review as they are similar to previous changes (207)
  • internal/accounts/org_discovery_test.go
  • cmd/rekey/main.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/api/ri_utilization_cache.go
  • internal/purchase/reaper.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • internal/database/open_from_env.go
  • internal/api/handler_recommendations_test.go
  • internal/auth/errors.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • internal/commitmentopts/types.go
  • internal/accounts/org_discovery.go
  • cmd/multi_service_test_common_test.go
  • internal/api/coverage_extras_test.go
  • internal/api/handler_registrations.go
  • internal/api/handler_config.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/api/handler_accounts_external_id_test.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_docs.go
  • internal/api/rate_limiter.go
  • internal/api/handler_per_account_perms_test.go
  • internal/server/static_test.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/gcp_signer.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • internal/secrets/gcp_resolver_coverage_test.go
  • internal/purchase/messages_test.go
  • internal/testutil/mocks.go
  • internal/execution/fanout.go
  • internal/testutil/postgres.go
  • internal/secrets/aws_resolver.go
  • internal/api/mocks_test.go
  • internal/api/handler_ri_exchange_integration_test.go
  • cmd/secrets_store.go
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • internal/database/security_test.go
  • internal/oidc/aws_signer.go
  • internal/secrets/azure_resolver_coverage_test.go
  • internal/purchase/approvals.go
  • internal/email/template_renderers.go
  • internal/api/handler_recommendations.go
  • internal/testutil/testutil.go
  • internal/execution/executor.go
  • internal/scheduler/permission_log_test.go
  • internal/config/interfaces.go
  • internal/api/handler_users.go
  • internal/secrets/gcp_resolver_test.go
  • internal/api/handler_auth_test.go
  • internal/config/types_test.go
  • internal/api/handler_dashboard_test.go
  • internal/api/exchange_lookup_test.go
  • internal/commitmentopts/probe_azure.go
  • internal/server/integration_test.go
  • internal/secrets/env_resolver.go
  • internal/api/router_660_permission_flips_test.go
  • internal/secrets/azure_resolver_test.go
  • internal/api/handler_purchases_guards_test.go
  • internal/server/health.go
  • internal/purchase/execution_test.go
  • internal/auth/service_mfa.go
  • internal/api/router_authuser_test.go
  • internal/config/validation.go
  • internal/purchase/notifications.go
  • internal/deploy/mocks.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • internal/email/factory.go
  • internal/auth/service_user.go
  • internal/api/handler_recommendations_refresh.go
  • internal/purchase/scheduled_fire.go
  • internal/server/scheduledauth/integration_test.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/secrets/gcp_resolver_grpc_test.go
  • internal/analytics/collector.go
  • internal/api/handler_federation_test.go
  • internal/auth/service.go
  • internal/server/scheduledauth/validator_test.go
  • internal/api/exchange_lookup.go
  • internal/secrets/constructor_error_test.go
  • internal/api/handler_plans_test.go
  • internal/email/smtp_server_test.go
  • internal/api/scoping.go
  • internal/mocks/email.go
  • internal/server/app_test.go
  • internal/database/postgres/migrations/migration_transactional_test.go
  • internal/auth/service_apikeys_api.go
  • internal/oidc/signer_test.go
  • internal/deploy/docker_test.go
  • internal/server/lambda_test.go
  • internal/api/validation_test.go
  • internal/config/store_postgres_unit_test.go
  • internal/api/ri_utilization_cache_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/api/handler_groups.go
  • internal/api/coverage_gaps_test.go
  • internal/api/middleware.go
  • internal/email/coverage_extra_test.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • internal/credentials/cipher.go
  • internal/secrets/gcp_resolver.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • internal/oidc/azure_signer.go
  • internal/api/router_handlers_test.go
  • internal/api/handler_inventory.go
  • internal/secrets/resolver_test.go
  • cmd/configure_test.go
  • internal/config/store_postgres_recommendations.go
  • internal/secrets/env_resolver_test.go
  • internal/oidc/issuer_cache.go
  • cmd/server/main.go
  • internal/server/lambda.go
  • internal/api/health.go
  • internal/analytics/postgres_analytics.go
  • cmd/multi_service_stats_helpers.go
  • internal/auth/service_lockout_test.go
  • internal/purchase/scheduled_fire_test.go
  • internal/deploy/docker.go
  • internal/database/config.go
  • internal/server/handler_ri_exchange.go
  • internal/deploy/types.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/config/store_postgres_comprehensive_test.go
  • internal/api/handler_analytics.go
  • internal/server/health_test.go
  • internal/scheduler/scheduler_test.go
  • cmd/multi_service_stats_test.go
  • internal/auth/service_api.go
  • internal/purchase/execution.go
  • internal/api/middleware_test.go
  • internal/oidc/azure_factory_test.go
  • internal/auth/service_apikeys.go
  • internal/config/store_postgres_pgxmock_test.go
  • cmd/multi_service_engine_versions.go
  • internal/reporter/reporter.go
  • cmd/validators_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_dashboard.go
  • internal/email/coverage_test.go
  • internal/email/templates.go
  • internal/commitmentopts/service_test.go
  • internal/server/static.go
  • internal/deploy/frontend.go
  • internal/analytics/postgres_analytics_test.go
  • internal/secrets/azure_resolver.go
  • internal/purchase/reaper_test.go
  • cmd/main.go
  • internal/api/handler_auth.go
  • internal/mocks/sns.go
  • internal/purchase/approvals_test.go
  • internal/database/config_test.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_apikeys.go
  • internal/config/validation_test.go
  • internal/server/handler_test.go
  • internal/email/smtp_sender_test.go
  • internal/email/nop_sender.go
  • internal/server/scheduledauth/validator.go
  • internal/database/connection_test.go
  • internal/api/db_rate_limiter.go
  • internal/database/postgres/migrations/migrate.go
  • internal/server/app_coverage_test.go
  • internal/api/router.go
  • internal/email/sender.go
  • internal/api/handler_commitment_options.go
  • cmd/multi_service_csv_test.go
  • internal/purchase/manager_test.go
  • internal/api/handler_test.go
  • cmd/multi_service_csv.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • internal/analytics/postgres_analytics_db_test.go
  • cmd/multi_service_stats.go
  • internal/auth/service_password.go
  • internal/deploy/profiles.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_test.go
  • internal/api/handler_federation.go
  • internal/commitmentopts/probe.go
  • internal/api/handler_history_test.go
  • cmd/multi_service_helpers.go
  • cmd/configure_gcp.go
  • internal/api/types_apikeys.go
  • internal/purchase/manager.go
  • internal/auth/types.go
  • internal/api/handler_ri_exchange_test.go
  • cmd/configure_azure.go
  • internal/api/handler_purchases_revoke.go
  • cmd/helpers.go
  • internal/secrets/resolver_coverage_test.go
  • internal/api/handler_history.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler.go
  • internal/config/types.go
  • cmd/multi_service.go
  • internal/scheduler/scheduler.go
  • internal/api/handler_accounts.go
  • internal/email/smtp_sender.go
  • internal/api/handler_ri_exchange.go
  • internal/server/app.go
  • internal/credentials/resolver.go
  • internal/api/types.go
  • internal/mocks/stores.go
  • internal/purchase/coverage_extra_test.go
  • internal/api/handler_purchases.go
  • internal/config/store_postgres.go
  • internal/config/defaults_test.go
  • internal/api/handler_purchases_test.go

@cristim
cristim force-pushed the fix/lint-debt-clear branch from dac0ce1 to 1782186 Compare July 13, 2026 14:19
cristim added 6 commits July 16, 2026 21:30
Three test files (coverage_extras_test.go, handler_ri_exchange_test.go,
router_handlers_test.go) still expected the US "canceled" in the
TransitionRIExchangeStatus mock args and result assertions for
rejectRIExchange. The production handler already uses "cancelled" (reverted
in commit 55a6295a5 to match the DB schema). Update the mocks to match.
Resolve 9 issues blocking CI on golangci-lint v2.10.x (which treats all
findings as fatal, unlike v2.11+ which exits 0 for warnings):

gocritic unnamedResult (x3): add named returns to defaultLadderAccountResolver,
resolveLadderIdentity, and ladderWithinCadenceWindow for the ambiguous
(string,string,error) and (bool,string,error) signatures.

gocritic builtinShadow (x2): rename local `cap` to `ladderCap` in
processOneLadderConfig and executeLadderRun to stop shadowing the
built-in cap() function.

gocritic rangeValCopy: switch `for _, tr := range tranches` to indexed
access (`for i := range tranches { tr := &tranches[i] }`) to avoid
copying the 152-byte Tranche struct on each iteration.

misspell: fix "behaviour" -> "behavior" in a handler_ladder.go comment.

prealloc: preallocate the actions slice in assembleLadderPlan with the
known capacity (len(Allocations)+len(Reshapes)+len(Holds)).

staticcheck ST1005: lowercase the "Allocate:" error prefix to conform
with Go error string conventions.

.golangci.yml: remove non-working `ignore-words` setting; extend the
misspell path-exclusion regex to cover handler_ri_exchange_test.go,
router_handlers_test.go, coverage_extras_test.go (all carry "cancelled"
as mock args matching the DB canonical value), store_postgres_ladder.go
(DB column cancelled_by), and internal/config/types.go for "initialised".
Update text pattern to "cancelled|initialised".
Three findings surfaced after rebasing onto origin/main (fcd8133),
all in code merged in from main; golangci-lint v2.10.1 (CI pin) treats
warnings as fatal so they would fail the Lint Code job:

misspell (x2): "cancelling" -> "canceling" in prose comments in
internal/config/store_postgres.go and internal/config/types.go (comment
text only; the DB value "cancelled" is untouched and stays excluded).

unparam: testBaseline in internal/server/handler_ladder_test.go always
received 10.0; drop the parameter and hoist the value into the
testBaselineLowWaterUSDHr constant.
internal/config/interfaces.go: restore the DB-canonical "cancelled" /
"cancelled_by" spelling in the CancelExecutionAtomic and
CancelScheduledExecutionAtomic doc comments (the spelling sweep had
flipped them away from what the SQL actually writes; migration is owned
by #1277), and correct the CancelExecutionAtomic doc to state that
'scheduled' is NOT accepted (matches the UPDATE ... WHERE status IN
('pending','notified') in store_postgres.go).

cmd/configure_azure.go: cast syscall.Stdin to int for term.ReadPassword;
syscall.Stdin is a syscall.Handle on Windows so the direct pass breaks
Windows builds. nolint:unconvert because the cast is a no-op on Unix.

internal/auth/service_mfa.go: reword the G505 rationale; RFC 6238 allows
SHA-1/256/512 and SHA-1 is the compatibility choice, not a mandate.

ci_cd_sanity_tests/pkg/sanity/azure/azure.go: extend the #nosec G702/G204
rationale to document that opts.SubscriptionID is passed as a single argv
value by exec.CommandContext (no shell interpretation).

.golangci.yml: add internal/config/interfaces.go to the misspell
"cancelled" exclusion list.
"honouring" -> "honoring" and "defence in depth" -> "defense in depth"
in comments merged in from main; golangci-lint v2.10.1 (CI pin) treats
misspell warnings as fatal.
gocritic importShadow: requireInt32Range's "flag" parameter shadowed the
imported flag package; rename to flagName. Surfaced after rebasing onto
main with #1363 merged.
@cristim
cristim force-pushed the fix/lint-debt-clear branch from 6c28498 to 23ed924 Compare July 16, 2026 18:30
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Rebased onto main (post-#1389, which fixes the gocyclo -over 10 debt from #1207). gocyclo now 0 violations; the Lint Code + pre-commit gocyclo step should be green on this head.

@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim merged commit caafb6e into main Jul 16, 2026
18 checks passed
@cristim
cristim deleted the fix/lint-debt-clear branch July 16, 2026 18:41
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Merged to main - and this is the FIRST FULLY-GREEN PR of the cleanup drive: every CI job SUCCESS (Lint Code, Security Scanning, pre-commit, Unit, Integration, E2E, Docker, Terraform, CI Success). All ~2769 golangci-lint findings are cleared, so Lint Code is now GREEN ON MAIN and becomes a hard gate: any subsequent PR introducing a lint finding fails its own CI. Combined with #1363 (Security green) and #1389 (gocyclo/pre-commit green), the entire 'known pre-existing debt' exception list (Lint #1342 / Security #1354 / CI-Success aggregator) is now RETIRED. Rebased onto post-#1389 main so gocyclo is clean; the fieldalignment deferral remains tracked in #1373.

cristim added a commit that referenced this pull request Jul 23, 2026
…ases

The `--purchase` flag never bought anything on its own because `--dry-run`
defaulted to true and the guard was `!ActualPurchase || DryRun`, so
`--purchase` gave `!true || true == true` (a dry run). Users had to pass
`--purchase --dry-run=false` to actually buy. (Surfaced by CodeRabbit on
#1364.)

Rather than flip `--dry-run`'s default to false (which leaves a confusing
flag named `--dry-run` that defaults off and only acts as a redundant
"force dry-run even with --purchase" override), remove the flag entirely.
`--purchase` is now the single purchase control:

    effectiveDryRun(cfg) = !cfg.ActualPurchase

A bare run is always a dry run; `--purchase` is the one opt-in that moves
money (still gated by the `--yes` / interactive confirmation prompt). This
also unifies the two code paths: cloud-fetch and `--input-csv` mode now
behave identically, matching what the CSV path already documented.

Docs (purchase-safety.md, cli/README.md) are updated to the single-flag
model with a History note explaining the removal. Tests replace the
default-value guard with `TestDryRunFlagRemoved`, which fails if the flag
is ever reintroduced.
cristim added a commit that referenced this pull request Jul 23, 2026
…ases (#1485)

* fix(cli): make --purchase execute real purchases (--dry-run defaults false)

The --dry-run flag defaulted to true, so effectiveDryRun (!ActualPurchase
|| DryRun) stayed true even when --purchase was given -- meaning --purchase
alone never executed real purchases, defeating the flag. Default --dry-run
to false; the safe default is preserved because ActualPurchase defaults to
false (a bare invocation is still dry-run). Passing --dry-run alongside
--purchase still forces dry-run as an explicit safety override.

Adds a regression test that fails on the prior true default and covers all
four flag combinations.

* fix(cli): remove --dry-run flag; --purchase alone executes real purchases

The `--purchase` flag never bought anything on its own because `--dry-run`
defaulted to true and the guard was `!ActualPurchase || DryRun`, so
`--purchase` gave `!true || true == true` (a dry run). Users had to pass
`--purchase --dry-run=false` to actually buy. (Surfaced by CodeRabbit on
#1364.)

Rather than flip `--dry-run`'s default to false (which leaves a confusing
flag named `--dry-run` that defaults off and only acts as a redundant
"force dry-run even with --purchase" override), remove the flag entirely.
`--purchase` is now the single purchase control:

    effectiveDryRun(cfg) = !cfg.ActualPurchase

A bare run is always a dry run; `--purchase` is the one opt-in that moves
money (still gated by the `--yes` / interactive confirmation prompt). This
also unifies the two code paths: cloud-fetch and `--input-csv` mode now
behave identically, matching what the CSV path already documented.

Docs (purchase-safety.md, cli/README.md) are updated to the single-flag
model with a History note explaining the removal. Tests replace the
default-value guard with `TestDryRunFlagRemoved`, which fails if the flag
is ever reintroduced.
cristim added a commit that referenced this pull request Sep 27, 2026
chore(lint): clear all golangci-lint findings to green
cristim added a commit that referenced this pull request Sep 27, 2026
…ases (#1485)

* fix(cli): make --purchase execute real purchases (--dry-run defaults false)

The --dry-run flag defaulted to true, so effectiveDryRun (!ActualPurchase
|| DryRun) stayed true even when --purchase was given -- meaning --purchase
alone never executed real purchases, defeating the flag. Default --dry-run
to false; the safe default is preserved because ActualPurchase defaults to
false (a bare invocation is still dry-run). Passing --dry-run alongside
--purchase still forces dry-run as an explicit safety override.

Adds a regression test that fails on the prior true default and covers all
four flag combinations.

* fix(cli): remove --dry-run flag; --purchase alone executes real purchases

The `--purchase` flag never bought anything on its own because `--dry-run`
defaulted to true and the guard was `!ActualPurchase || DryRun`, so
`--purchase` gave `!true || true == true` (a dry run). Users had to pass
`--purchase --dry-run=false` to actually buy. (Surfaced by CodeRabbit on
#1364.)

Rather than flip `--dry-run`'s default to false (which leaves a confusing
flag named `--dry-run` that defaults off and only acts as a redundant
"force dry-run even with --purchase" override), remove the flag entirely.
`--purchase` is now the single purchase control:

    effectiveDryRun(cfg) = !cfg.ActualPurchase

A bare run is always a dry run; `--purchase` is the one opt-in that moves
money (still gated by the `--yes` / interactive confirmation prompt). This
also unifies the two code paths: cloud-fetch and `--input-csv` mode now
behave identically, matching what the CSV path already documented.

Docs (purchase-safety.md, cli/README.md) are updated to the single-flag
model with a History note explaining the removal. Tests replace the
default-value guard with `TestDryRunFlagRemoved`, which fails if the flag
is ever reintroduced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/xl Multi-week / refactor impact/all-users Affects every user priority/p1 Next up; this sprint severity/medium Moderate harm triaged Item has been triaged type/chore Maintenance / non-user-visible urgency/now Drop other things

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants