feat(coverage): per-provider coverage breakdowns (V1) replace placeholder stub - #760
Conversation
…stub The Coverage sub-tab on Inventory & Coverage showed "Per-provider coverage breakdowns are coming soon." Now renders per-provider sections (AWS, Azure, GCP) each with a per-service table showing covered monthly spend, on-demand gap, coverage %, and a proportional bar indicator. Providers with no usage data show "No usage detected for <Provider>" instead of an empty table. Backend: extended handler_inventory.go with getCoverageBreakdown (GET /api/inventory/coverage). Aggregates per-(provider,service) from two existing data sources already in the system: active-commitment MonthlyCost (covered) and recommendation Savings (on-demand gap). No new AWS/Azure/GCP API calls needed. coverage_pct is *float64 (null when both sides are zero) to distinguish "no usage" from "0% covered". Frontend: replaced placeholder div in index.html with a header card + #coverage-providers container. inventory.ts now exports loadCoverageBreakdown(), which renders provider cards using DOM construction (no innerHTML). Wired into switchInventorySubSection and a refresh button. Closes #754.
|
@coderabbitai review |
|
Warning Review limit reached
More reviews will be available in 51 minutes and 2 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR implements the coverage breakdown feature for the inventory & coverage sub-tab. It adds a new backend endpoint ( ChangesCoverage Breakdown Feature
Sequence DiagramsequenceDiagram
participant User
participant Frontend as Frontend UI
participant API as /api/inventory/coverage
participant Store as PurchaseStore
participant Scheduler as RecommendationScheduler
User->>Frontend: Switch to Coverage sub-tab
Frontend->>Frontend: loadCoverageBreakdown()
Frontend->>API: GET /api/inventory/coverage
API->>Store: Fetch active commitments (view:purchases)
Store-->>API: Commitment data by provider/service
API->>Scheduler: Fetch recommendations
Scheduler-->>API: On-demand gaps (best-effort)
API->>API: buildCoverageBreakdown() aggregates & computes %
API-->>Frontend: CoverageBreakdownResponse
Frontend->>Frontend: Render provider cards with services
Frontend->>Frontend: Display coverage % per service & provider
User->>Frontend: Click refresh button
Frontend->>API: GET /api/inventory/coverage (reload)
API-->>Frontend: Updated response
Frontend->>Frontend: Update provider sections in-place
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
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 `@frontend/src/inventory.ts`:
- Around line 319-323: The last table header is created as an empty string which
is inaccessible; update the header creation loop in inventory.ts (the block that
builds headerRow) to use a meaningful label such as "Coverage" or "Coverage bar"
instead of '' and/or add an explicit aria-label (e.g.,
th.setAttribute('aria-label', 'Coverage bar')) on the created <th> so screen
readers can identify the coverage bar column; locate the header generation loop
that iterates over ['Service', 'Covered/mo', 'On-demand gap/mo', 'Coverage %',
''] and replace the empty entry with the chosen non-empty label and optional
aria-label on the <th>.
In `@internal/api/handler_inventory.go`:
- Around line 154-164: Recommendations returned by
h.scheduler.ListRecommendations are aggregated into onDemandByKey without
applying the same account-access scope used for commitments; restrict
aggregation to only recommendations that match the allowed-account scope (the
same filter applied to commitments) by either passing the allowed-accounts into
ListRecommendations (instead of config.RecommendationFilter{}), or
post-filtering recs by account before the loop (e.g., skip recs whose account is
not in the allowed-account set), then sum onDemandByKey using
rec.Provider+":"+rec.Service and rec.Savings only for those allowed recs.
🪄 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: afb41bee-1981-4414-8662-edf2a3409fbe
📒 Files selected for processing (11)
frontend/src/__tests__/api-inventory.test.tsfrontend/src/__tests__/inventory.test.tsfrontend/src/api/index.tsfrontend/src/api/inventory.tsfrontend/src/api/types.tsfrontend/src/index.htmlfrontend/src/inventory.tsinternal/api/handler_inventory.gointernal/api/handler_inventory_test.gointernal/api/router.gointernal/api/types.go
…abel empty coverage <th> getCoverageBreakdown called ListRecommendations with no account scope, so a restricted user received on-demand gap figures computed from recommendations belonging to accounts outside their allowed_accounts list. Apply filterRecommendationsByAllowedAccounts on the recs slice (same pattern used by getRecommendations and getDashboardSummary) before accumulating onDemandByKey. Regression tests added in TestPerAccountPerms_CoverageBreakdown_* (negative: scoped user sees only account-A on-demand gap; positive: admin aggregates both). Also replaces the empty-string last header label in buildServiceTable with "Coverage bar" and adds aria-label="Coverage bar" on that <th> so screen readers can announce the column purpose unambiguously. Addresses two unresolved CodeRabbit findings on PR #760.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary
Inventory & Coverage > Coverage sub-tab previously showed a placeholder:
V1 replaces the stub with real per-provider, per-service breakdowns.
What V1 ships
GET /api/inventory/coveragereturningCoverageBreakdownResponse(per-provider sections, each with a list of service rows: covered, on-demand, coverage_pct).inventory.tsrenders each provider that has data; per-provider empty state when a provider has no usage.Data sources
No new cloud-provider SDK calls. Coverage % derived from data already in the system:
MonthlyCoston active commitments (from purchase history)Savingson current recommendations (the gap the user could be covering)coverage_pctis*float64(Go) /number|null(TS) -- null when both sides are 0, NOT coerced to 0. Matches thefeedback_nullable_not_zeropattern.Files changed (11)
Backend:
internal/api/types.go-- new typesCoverageServiceRow,ProviderCoverageSection,CoverageBreakdownResponseinternal/api/handler_inventory.go--getCoverageBreakdown,buildCoverageBreakdown,coveragePct,splitProviderServiceinternal/api/router.go-- route + handler wrapperinternal/api/handler_inventory_test.go-- 5 new testsFrontend:
frontend/src/api/types.ts,frontend/src/api/inventory.ts,frontend/src/api/index.ts-- typed API clientfrontend/src/inventory.ts--loadCoverageBreakdown+ renderfrontend/src/index.html-- container structure (#coverage-providers,#coverage-refresh-btn)frontend/src/__tests__/inventory.test.ts-- 6 new render tests (full, empty providers, null coverage, error, refresh)frontend/src/__tests__/api-inventory.test.ts-- 2 new API testsTest plan
Deferred to follow-up
Closes #754.
Summary by CodeRabbit
Release Notes
New Features
Tests