Summary
Frontend counterpart to #307. The backend test PR pins per-account permission enforcement in the API layer; this issue covers the UI surfaces and frontend tests that must respect the same allowed_accounts constraint end-to-end.
Scope
A user with allowed_accounts: ["uuid1"] should see a UI consistent with what the API returns:
- Account selectors (recommendations page, history, plans, dashboard provider/account dropdowns) only list
uuid1. Disallowed accounts must not appear at all — not just be disabled.
- List views (recommendations table, purchase history, plans) render only rows for
uuid1. No client-side filtering relying on the user being honest — but also no flicker where disallowed rows briefly render before being hidden.
- Aggregated cards (Dashboard "Potential Monthly Savings", "Effective Coverage", etc.) show aggregates over the allowed subset, matching the backend's filtered aggregate.
- Mutate-by-id flows (override edits, plan saves, purchase approvals) surface a friendly error if the user attempts to act on a disallowed
cloud_account_id (e.g. via deep link or stale tab) — not an unhandled 403 modal.
- Empty states when the user has zero allowed accounts: dashboard renders a "no account access — contact your admin" message instead of a blank skeleton.
Acceptance criteria
- Jest tests in
frontend/src/__tests__/ for each list view + dashboard summary that mock the API returning a filtered subset and assert the UI renders only the allowed rows.
- Jest test that mocks a 403 on a mutate-by-id path and pins the user-facing error copy.
- Account-selector dropdowns are populated from the API's filtered account list, not a hardcoded full list.
- No regression in dashboard render time on the filtered subset (the existing
dashboard.test.ts baseline still passes).
Out of scope
Sibling
Tracking the backend half: #307.
Summary
Frontend counterpart to #307. The backend test PR pins per-account permission enforcement in the API layer; this issue covers the UI surfaces and frontend tests that must respect the same
allowed_accountsconstraint end-to-end.Scope
A user with
allowed_accounts: ["uuid1"]should see a UI consistent with what the API returns:uuid1. Disallowed accounts must not appear at all — not just be disabled.uuid1. No client-side filtering relying on the user being honest — but also no flicker where disallowed rows briefly render before being hidden.cloud_account_id(e.g. via deep link or stale tab) — not an unhandled 403 modal.Acceptance criteria
frontend/src/__tests__/for each list view + dashboard summary that mock the API returning a filtered subset and assert the UI renders only the allowed rows.dashboard.test.tsbaseline still passes).Out of scope
allowed_accountsto users) — separate concern, file separately if needed.Sibling
Tracking the backend half: #307.