Skip to content

test(api): pin per-account permission scoping across recs/purchases/history/dashboard (closes #307)#309

Merged
cristim merged 4 commits into
feat/multicloud-web-frontendfrom
test/issue-307-per-account-perms
May 5, 2026
Merged

test(api): pin per-account permission scoping across recs/purchases/history/dashboard (closes #307)#309
cristim merged 4 commits into
feat/multicloud-web-frontendfrom
test/issue-307-per-account-perms

Conversation

@cristim
Copy link
Copy Markdown
Member

@cristim cristim commented May 5, 2026

Summary

  • Adds TestPerAccountPerms regression suite (13 test functions, 1 new file) covering 8 endpoints that return or accept cloud_account_id-tagged data.
  • Every negative test asserts that a scoped user (allowed_accounts: ["a"]) is rejected/filtered when accessing account-b data — removing any enforcement function causes the suite to fail.
  • No non-test code changed.

Endpoints covered

# Endpoint Guard function Negative assertion
1 GET /recommendations filterRecommendationsByAllowedAccounts account-B record filtered out of list
2 GET /recommendations/:id same, applied before id lookup 404 on cross-account detail fetch
3 GET /history filterPurchaseHistoryByAllowedAccounts account-B row absent from response
4 GET /history/analytics validateAnalyticsAccountScope 404 for cross-account account_id
5 GET /history/breakdown validateAnalyticsAccountScope 404 for cross-account account_id
6 GET /dashboard/summary filterDashboardRecommendations savings + count from account-A only
7 POST /purchases/execute validatePurchaseRecommendationScope 403 (cross-account rec) + 400 (unattributed rec)
8 POST /purchases/planned/:id/pause requireExecutionAccess 404 when execution's plan is in account-B

Auth gaps discovered

None. All 8 endpoints have enforcement in place. The tests confirm it.

Test plan

  • go test ./internal/api/... -run "TestPerAccountPerms" -v — 13 tests pass
  • go test ./internal/api/... — full 1068 tests pass (no regressions)
  • go test ./... — full 4284 tests pass

Summary by CodeRabbit

  • Tests
    • Added a comprehensive regression suite validating per-account authorization across Recommendations, History (including Analytics and Breakdown), Dashboard Summary, Execute Purchase, and Planned Purchase flows.
    • Verifies scoped non-admin access: cross-account requests are rejected with endpoint-appropriate responses; allowed-account requests return expected data and persist state changes.
    • Confirms authorization scope checks occur before backend operations to prevent unauthorized access or modifications.

…istory/dashboard (closes #307)

Add TestPerAccountPerms regression suite covering 8 endpoints that return or
accept cloud_account_id-tagged data. Each test pins the negative case — a
scoped user (allowed_accounts: ["a"]) is rejected or filtered when accessing
account-b data — so removing any enforcement function causes the suite to fail.

Endpoints covered:
- GET /recommendations (filterRecommendationsByAllowedAccounts)
- GET /recommendations/:id (cross-account 404 via detail filter)
- GET /history (filterPurchaseHistoryByAllowedAccounts)
- GET /history/analytics (validateAnalyticsAccountScope — cross-account 404)
- GET /history/breakdown (validateAnalyticsAccountScope — cross-account 404)
- GET /dashboard/summary (filterDashboardRecommendations — subset aggregate)
- POST /purchases/execute (validatePurchaseRecommendationScope — 403 + 400)
- POST /purchases/planned/:id/pause (requireExecutionAccess — cross-account 404)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e6bbcfa-0d41-4a73-a00d-b7b6e6c114d5

📥 Commits

Reviewing files that changed from the base of the PR and between 3648021 and 016da84.

📒 Files selected for processing (1)
  • internal/api/handler_per_account_perms_test.go

📝 Walkthrough

Walkthrough

Adds a new Go regression test suite that verifies per-account authorization scoping across recommendations, history/analytics, dashboard summary, execute purchase, and planned-purchase endpoints, asserting cross-account rejections and allowed-account successes with fixtures and mocks.

Changes

Cohort / File(s) Summary
Per-account permission tests & helpers
internal/api/handler_per_account_perms_test.go
Adds a comprehensive test suite with account/user constants, permsPtr, scopedAuthMock, scopedReq, permsAccountList, and mocks for scheduler/config/analytics. Introduces ~15 focused tests covering recommendations (list/detail), history (list, analytics, breakdown), dashboard summary, execute purchase, and planned purchases; asserts scope checks occur before backend calls and validates endpoint-specific rejection/status codes and allowed-account paths.

Sequence Diagram(s)

(Skipped — changes add tests and mocks but do not introduce a new multi-component control flow requiring sequence visualization.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐰 I hopped through mocks and tiny feats,
I guarded accounts with careful beats,
Cross-doors stayed closed, allowed ones flew,
Tests planted carrots — green and true,
A rabbit's nod to passing suites.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding comprehensive per-account permission tests across multiple API endpoints (recommendations, purchases, history, dashboard). It is specific, concise, and accurately reflects the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/issue-307-per-account-perms

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

@cristim cristim added priority/p1 Next up; this sprint severity/high Significant harm urgency/this-sprint Within the current sprint impact/all-users Affects every user effort/m Days type/security Security finding triaged Item has been triaged labels May 5, 2026
@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
internal/api/handler_per_account_perms_test.go (2)

476-577: ⚡ Quick win

Add one scoped allowed-account execute-purchase success case.

Lines 483-577 assert only deny paths (403/400). A regression that rejects every scoped execute request would still satisfy this section. Add one account-A positive test to verify scoped users can execute in-scope recommendations.

🤖 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/api/handler_per_account_perms_test.go` around lines 476 - 577, Add a
positive test case that verifies a scoped user can successfully execute a
recommendation for an allowed account: copy the pattern from
TestPerAccountPerms_ExecutePurchase_CrossAccountRejected403 but set
"cloud_account_id" to permsAccA, call handler.executePurchase(ctx, req) and
assert no error, assert that mockStore.SavePurchaseExecution was called with the
expected purchase execution payload, and verify returned result status (or lack
of ClientError). Use the same setup helpers (scopedAuthMock, scopedReq,
permsAccountList) and ensure the test function name indicates success for
allowed account (e.g.,
TestPerAccountPerms_ExecutePurchase_AllowedAccountAccepted200).

386-412: ⚡ Quick win

Add a scoped allowed-account success test for /history/breakdown.

Line 389 currently validates only the cross-account rejection path. If the handler regresses to returning 404 for all scoped users, this test still passes. Add a paired account-A success case to pin non-overblocking behavior.

Suggested test shape
+func TestPerAccountPerms_HistoryBreakdown_AllowedAccountSucceeds(t *testing.T) {
+	ctx := context.Background()
+
+	mockClient := new(MockAnalyticsClient)
+	mockClient.On("QueryBreakdown", ctx, permsAccA, mock.Anything, mock.Anything).
+		Return([]HistoryBreakdownPoint{}, nil)
+
+	mockStore := new(MockConfigStore)
+	mockStore.ListCloudAccountsFn = func(_ context.Context, _ config.CloudAccountFilter) ([]config.CloudAccount, error) {
+		return permsAccountList(), nil
+	}
+
+	handler := &Handler{
+		auth:            scopedAuthMock(ctx),
+		analyticsClient: mockClient,
+		config:          mockStore,
+	}
+
+	_, err := handler.getHistoryBreakdown(ctx, scopedReq(), map[string]string{"account_id": permsAccA})
+	require.NoError(t, err)
+}
🤖 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/api/handler_per_account_perms_test.go` around lines 386 - 412, The
test TestPerAccountPerms_HistoryBreakdown_CrossAccountRejected only asserts the
cross-account rejection path and can miss a regression that blocks all scoped
users; add a new paired success case that calls handler.getHistoryBreakdown with
the scoped request but "account_id" set to the allowed account (e.g. permsAccA),
mock the analytics client (mockClient) to expect and return a valid
QueryBreakdown response, assert no error and that the response equals the mocked
result, and finally assert mockClient.AssertCalled for "QueryBreakdown" to
ensure the handler permits scoped users for the correct account; mirror setup
used in the existing test (scopedAuthMock, scopedReq, MockAnalyticsClient,
MockConfigStore).
🤖 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/api/handler_per_account_perms_test.go`:
- Around line 476-577: Add a positive test case that verifies a scoped user can
successfully execute a recommendation for an allowed account: copy the pattern
from TestPerAccountPerms_ExecutePurchase_CrossAccountRejected403 but set
"cloud_account_id" to permsAccA, call handler.executePurchase(ctx, req) and
assert no error, assert that mockStore.SavePurchaseExecution was called with the
expected purchase execution payload, and verify returned result status (or lack
of ClientError). Use the same setup helpers (scopedAuthMock, scopedReq,
permsAccountList) and ensure the test function name indicates success for
allowed account (e.g.,
TestPerAccountPerms_ExecutePurchase_AllowedAccountAccepted200).
- Around line 386-412: The test
TestPerAccountPerms_HistoryBreakdown_CrossAccountRejected only asserts the
cross-account rejection path and can miss a regression that blocks all scoped
users; add a new paired success case that calls handler.getHistoryBreakdown with
the scoped request but "account_id" set to the allowed account (e.g. permsAccA),
mock the analytics client (mockClient) to expect and return a valid
QueryBreakdown response, assert no error and that the response equals the mocked
result, and finally assert mockClient.AssertCalled for "QueryBreakdown" to
ensure the handler permits scoped users for the correct account; mirror setup
used in the existing test (scopedAuthMock, scopedReq, MockAnalyticsClient,
MockConfigStore).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4914776d-2866-4081-97ec-82bdefcd04ae

📥 Commits

Reviewing files that changed from the base of the PR and between f83c914 and 9d3f799.

📒 Files selected for processing (1)
  • internal/api/handler_per_account_perms_test.go

… pass 1)

Add TestPerAccountPerms_HistoryBreakdown_AllowedAccountSucceeds and
TestPerAccountPerms_ExecutePurchase_AllowedAccountAccepted to complement
the existing rejection tests and prevent false-positive passes when a
regression blocks all scoped users (CodeRabbit nitpicks on PR #309).
@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

CR pass 1 — addressed both nitpicks:

Nitpick 1 (476-577): Added TestPerAccountPerms_ExecutePurchase_AllowedAccountAccepted — verifies a scoped user can execute a recommendation tagged to account A. Uses count=0 so no suppression rows are written (matches TestHandler_executePurchase_Success pattern). Status is "failed" because no emailNotifier is wired — expected behaviour per existing tests.

Nitpick 2 (386-412): Added TestPerAccountPerms_HistoryBreakdown_AllowedAccountSucceeds — verifies the breakdown analytics client is actually called for account-A requests, asserting AssertCalled on QueryBreakdown.

15 tests now pass (was 13). go test ./... → 4286 passed.

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@cristim Thanks for the thorough follow-up! Both additions look solid:

  • TestPerAccountPerms_ExecutePurchase_AllowedAccountAccepted — good to have the positive path confirmed; the "failed" status being expected/intentional (no emailNotifier) matches the established pattern and is clearly intentional.
  • TestPerAccountPerms_HistoryBreakdown_AllowedAccountSucceeds — the AssertCalled on QueryBreakdown gives a strong positive-path guard that the analytics client is actually invoked for allowed-account requests.

Triggering a fresh review of the updated branch now.

[review]

@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@internal/api/handler_per_account_perms_test.go`:
- Around line 361-382: The test sets up MockAnalyticsClient.On("QueryHistory",
ctx, permsAccA, mock.Anything, mock.Anything, mock.Anything) but never asserts
it was invoked; update the test (around the handler.getHistoryAnalytics call) to
explicitly verify the mock was called by adding a call to
mockClient.AssertCalled(t, "QueryHistory", ctx, permsAccA, mock.Anything,
mock.Anything, mock.Anything) or mockClient.AssertExpectations(t) after
require.NotNil(t, result) so the test fails if getHistoryAnalytics
short-circuits and doesn't invoke QueryHistory.
- Around line 141-143: The assertion compares permsAccB (string) to
r.CloudAccountID (*string), so it always passes; change the check in the loop
over result.Recommendations to compare the actual string value safely by
dereferencing the pointer (handle nil): e.g., inside the loop, if
r.CloudAccountID != nil then assert.NotEqual(t, permsAccB, *r.CloudAccountID,
"account-B recommendation must not appear in scoped user's list") so the test
fails if a leaked account-B value appears.
🪄 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: cd90e411-6839-467f-9711-4cc427331da5

📥 Commits

Reviewing files that changed from the base of the PR and between 9d3f799 and 2294060.

📒 Files selected for processing (1)
  • internal/api/handler_per_account_perms_test.go

Comment thread internal/api/handler_per_account_perms_test.go Outdated
Comment thread internal/api/handler_per_account_perms_test.go
…st (CR pass 2)

- Fix loop in Recommendations_ListFilter: compare *r.CloudAccountID (string)
  not r.CloudAccountID (*string) so the regression anchor actually fails when
  account-B leaks through (CR inline comment, line 141-143).
- Add mockClient.AssertCalled after HistoryAnalytics_AllowedAccountSucceeds so
  the test fails if the handler short-circuits without reaching QueryHistory
  (CR inline comment, line 361-382).
@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

CR pass 2 — addressed both actionable items:

Item 1 (line 141-143, pointer dereference): Fixed the loop in TestPerAccountPerms_Recommendations_ListFilter — now dereferences *r.CloudAccountID so the assert.NotEqual comparison against permsAccB (string) is type-correct. Previously the assertion always passed because it compared a *string to a string.

Item 2 (line 361-382, missing AssertCalled): Added mockClient.AssertCalled(t, "QueryHistory", ...) after require.NotNil(t, result) in TestPerAccountPerms_HistoryAnalytics_AllowedAccountSucceeds so the test fails if the handler short-circuits without reaching the analytics backend.

15 tests, 4286 total — all pass.

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@cristim Both CR pass 2 fixes look correct and important:

  • Item 1 (pointer dereference): This was a genuine silent false-positive — comparing a *string to a string in Go never panics but also never equals, so assert.NotEqual would trivially pass regardless of the filter's behaviour. Dereferencing to *r.CloudAccountID makes the assertion semantically meaningful. Good catch and fix.
  • Item 2 (AssertCalled on QueryHistory): Completes the positive-path guard symmetrically with the QueryBreakdown assertion added in CR pass 1 — now both analytics endpoints verify the backend is actually invoked, not just that the handler returns a non-nil result.

Triggering a fresh review now.

[review]

@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

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
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

CR loop complete — all passes resolved

Pass 1 (2026-05-05T20:10:49Z)

  • Nitpick 1: Helper duplication (scopedAuthMock / permsAccountList / scopedReq) — dismissed: these are test-local helpers, intentionally not extracted to shared test utils to keep the test file self-contained and readable.
  • Nitpick 2: Describe permsAccA/permsAccB as pseudo-UUIDs — dismissed: constants are clearly labelled with their purpose in a comment; adding a // pseudo-UUID suffix is noise.

Pass 2 (2026-05-05T20:20:04Z) — both items fixed and pushed

  • Item 1 (line 141-143): assert.NotEqual(t, permsAccB, r.CloudAccountID, ...) compared string to *string (always passes silently in Go) → fixed to dereference *r.CloudAccountID with nil guard.
  • Item 2 (analytics success test): missing AssertCalled to verify QueryHistory was actually called → added mockClient.AssertCalled(t, "QueryHistory", ...).

Pass 3

CR's incremental review found no new delta after the pass 2 fixes were pushed. CR acknowledged both fixes as correct and confirmed no further actionable items.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/api/handler_per_account_perms_test.go (1)

483-490: ⚡ Quick win

Mock the account-B service config too so this stays an auth regression test.

Right now this test also relies on GetServiceConfig("aws", "rds") never being reached. If the implementation ever resolves service configs before filtering, the test will fail on an unexpected mock call even if per-account scoping is still correct. Stubbing the account-B pair keeps failures tied to the aggregation assertions instead of call order.

Proposed change
 	mockStore.On("GetServiceConfig", ctx, "aws", "ec2").Return((*config.ServiceConfig)(nil), nil)
+	mockStore.On("GetServiceConfig", ctx, "aws", "rds").Return((*config.ServiceConfig)(nil), nil)
 	// calculateCommitmentMetrics calls GetPurchaseHistory for YTD/committed totals.
 	mockStore.On("GetPurchaseHistory", ctx, mock.Anything, mock.Anything).Return([]config.PurchaseHistoryRecord{}, nil)
🤖 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/api/handler_per_account_perms_test.go` around lines 483 - 490, The
test currently only stubs mockStore.GetServiceConfig for ("aws","ec2") so an
unexpected call to GetServiceConfig(ctx,"aws","rds") (account-B service pair)
will fail if service configs are resolved before filtering; update the test to
also stub mockStore.On("GetServiceConfig", ctx, "aws", "rds") to return a nil
*config.ServiceConfig and nil error so the test remains focused on aggregation
assertions (refer to mockStore, GetServiceConfig and resolveCoverageByAccountKey
in handler_per_account_perms_test.go).
🤖 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 `@internal/api/handler_per_account_perms_test.go`:
- Around line 738-757: Add explicit assertions that the
TransitionExecutionStatus mock was invoked with the "paused" target and that the
handler returned an execution whose Status is "paused": after calling
handler.pausePlannedPurchase(ctx, scopedReq(), executionID) assert the mockStore
received the call (e.g. mockStore.AssertCalled/AssertExpectations for
"TransitionExecutionStatus" with ctx, executionID, mock.Anything, "paused") and
assert result.Status == "paused" (or equivalent field on the returned execution)
so the test fails if the transition was not actually performed.

---

Nitpick comments:
In `@internal/api/handler_per_account_perms_test.go`:
- Around line 483-490: The test currently only stubs mockStore.GetServiceConfig
for ("aws","ec2") so an unexpected call to GetServiceConfig(ctx,"aws","rds")
(account-B service pair) will fail if service configs are resolved before
filtering; update the test to also stub mockStore.On("GetServiceConfig", ctx,
"aws", "rds") to return a nil *config.ServiceConfig and nil error so the test
remains focused on aggregation assertions (refer to mockStore, GetServiceConfig
and resolveCoverageByAccountKey in handler_per_account_perms_test.go).
🪄 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: 746e44aa-caa3-488f-a88a-46c61726c8a1

📥 Commits

Reviewing files that changed from the base of the PR and between 2294060 and 3648021.

📒 Files selected for processing (1)
  • internal/api/handler_per_account_perms_test.go

Comment thread internal/api/handler_per_account_perms_test.go
Two CodeRabbit findings on PR #309:

1. Actionable: TestPerAccountPerms_PlannedPurchase_AllowedAccountPlanSucceeds
   only asserted NoError + NotNil, so a handler that skipped the
   TransitionExecutionStatus call would still pass. Added:
   - mockStore.AssertCalled(t, "TransitionExecutionStatus", ..., "paused")
     to verify the transition actually happened
   - assert.Equal for result.Status == "paused" to confirm the response

2. Nitpick: TestPerAccountPerms_DashboardSummary_AggregatesAllowedSubsetOnly
   only stubbed GetServiceConfig for (aws, ec2). Added a matching stub for
   (aws, rds) so the test doesn't break if the implementation ever resolves
   service configs before filtering.
@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

Addressing two CodeRabbit findings from the 2026-05-05T20:55:33Z review (commit 016da84):

Actionable fixed (TestPerAccountPerms_PlannedPurchase_AllowedAccountPlanSucceeds, lines ~754-758):

  • Added mockStore.AssertCalled(t, "TransitionExecutionStatus", ctx, executionID, mock.Anything, "paused") — confirms the transition was actually invoked, not just that a non-nil value was returned
  • Added assert.Equal(t, "paused", result.Status) — verifies the handler response reflects the new status

Nitpick applied (TestPerAccountPerms_DashboardSummary_AggregatesAllowedSubsetOnly, line ~490):

  • Added mockStore.On("GetServiceConfig", ctx, "aws", "rds").Return((*config.ServiceConfig)(nil), nil) — guards against future code paths that resolve service configs before filtering

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@cristim Both fixes are well-targeted:

  • AssertCalled on TransitionExecutionStatus: Completes the positive-path guard for the planned-purchase test — consistent with the QueryBreakdown and QueryHistory AssertCalled additions from prior passes. Without it, the test could pass even if the handler short-circuits before the status transition is persisted.
  • assert.Equal(t, "paused", result.Status): Makes the response-payload assertion concrete — verifies the handler's return value reflects the new state, not just that something non-nil came back.
  • GetServiceConfig mock stub: A sensible defensive addition — if a future handler revision resolves service configs before the account-scope filter fires, the test won't panic with an "unexpected call" and will continue exercising the filter logic.

Triggering a fresh review now.

[review]

@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

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
Copy link
Copy Markdown
Member Author

cristim commented May 5, 2026

CR loop complete — both findings from the 20:55 review addressed in 016da84

# Severity File / line CR finding Fix
1 🟡 Actionable handler_per_account_perms_test.go:762 pause-transition test passed regardless of whether transition fired Added mockStore.AssertCalled("TransitionExecutionStatus", ..., "paused") + assert.Equal("paused", result.Status) (per-thread reply posted above)
2 🧹 Nitpick handler_per_account_perms_test.go:483-490 only (aws, ec2) GetServiceConfig stubbed; future code paths resolving configs before filtering would break the test Added matching mockStore.On("GetServiceConfig", ctx, "aws", "rds").Return((*config.ServiceConfig)(nil), nil) stub

CI: all 3 checks green (sanity AWS, sanity Azure, pre-commit).
Mergeable: CLEAN.

3-pass CR loop closed: pass-1 dismissed/refactored, pass-2 fixed (pointer deref + analytics AssertCalled), pass-3 fixed (this one).

@cristim cristim merged commit 7032056 into feat/multicloud-web-frontend May 5, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/all-users Affects every user priority/p1 Next up; this sprint severity/high Significant harm triaged Item has been triaged type/security Security finding urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant