A FinOps Overview Card That Can Outscore the Savings Page
A savings total answers one question. It doesn’t answer what actually happened to the hundreds of recommendations that produced it. ZopNight’s new Recommendations Overview screen, now the first entry under Recommendations, answers that second question directly: which recommendations were raised, which were applied, which were dismissed, and which were confirmed fixed, filterable by cloud, account, category, or status, with every row opening straight into that specific recommendation. The Savings, Compliance, Risk, and Advisory pages each pick up a matching Verified resolved card, counting recommendations actually confirmed fixed in the customer’s own cloud account rather than merely marked applied in ZopNight’s records.
A Card and Its Chart Can’t Disagree, by Construction
Two new endpoints sit behind this page. One returns a single row per recommendation that had any activity in the requested window: when it was raised, what action was taken, whether that action was verified, its current status, its verdict, and the savings figure attached to it. The other returns the summary cards themselves, paired with a daily series that’s zero-filled for every day with no activity at all.
That second endpoint works this way on purpose: each summary card’s number is computed as the literal sum of its own daily series column, not calculated separately and placed next to the chart. A card and its own chart are structurally incapable of disagreeing, because they’re reading the same arithmetic, not two independent calculations that happen to usually match. A related fix in the same release closed a gap in the org-wide activity feed: calling it without a specific recommendation id used to fail outright with a 400 error, and now returns a bounded, paged feed of events across the whole organization instead.
Two Numbers Allowed to Disagree on Purpose
This screen’s lifecycle counts are deliberately not floored against whatever the Savings page shows for the same period, which means the Overview card can legitimately display a larger number than the Savings page does. That’s not a bug sitting quietly in the release notes. It’s a stated decision, because the two pages are measuring genuinely different things. Savings counts dollars attached to currently-relevant recommendations. Lifecycle counts every recommendation that had activity in a window, including ones whose relationship to the current savings figure has already changed. Forcing the two to match would mean silently discarding real activity just to keep a number tidy.
A Rewrite Proven Identical, Not Just Faster
The query behind the history page was rewritten to pull candidate recommendation ids directly from index ranges when no filter narrows the result down, rather than scanning a broader set and filtering afterward. Measured at a 90-day window against 50,000 recommendations, the rewritten version runs 2.2 times faster than the original. Speed alone isn’t what made this safe to ship. The rewritten version was checked against the original across 494 separately compared pages of results, confirming the two approaches return identical data before the faster one replaced the original query path entirely.
A Filter That Was Read, Branched On, and Never Applied
A single bug, found and fixed in the same release that renamed this page to Recommendations Overview, is worth sitting with longer than its size suggests. A resource_uid parameter was accepted by four separate endpoints covering recommended resources, resource counts, rules, and rule counts. That parameter was read. It was checked. But it was only ever used to decide whether to drop a savings-amount floor on the results, and was never actually applied as a filter against the data itself.
| Endpoint | What resource_uid was supposed to do | What it actually did |
|---|---|---|
| Resources, resource counts, rules, rule counts | Scope results to one specific resource | Only adjusted the savings floor, never filtered |
| A request for exactly one resource | Return that one resource | Returned 8,491 resources locally instead of 1 |
The distance between those two outcomes is enormous and entirely silent. Every piece of code calling these endpoints with a specific resource id was quietly getting back the entire organization’s full resource set instead, and nothing about the response shape would have signaled that anything was wrong. The MCP tool that wraps one of these endpoints forwarded the same parameter straight through, so the identical fix repaired it automatically the moment the underlying endpoint was corrected.
Progress, Not Just a Lifecycle Label
The page’s own table column changed from a generic lifecycle label to Progress, carrying an explanatory tooltip, and a recommendation that’s been confirmed fixed now reads plainly as RESOLVED in that column rather than a more technical status string. Timeline rows became whole-line clickable links, opening directly into the recommendation’s own status tab, scoped by a resource identifier that renders as a removable chip when one is available, falling back to a plain name search when it isn’t. None of these are large changes individually. Together they’re the difference between a page that logs activity and one a person can actually use to answer what happened to a specific recommendation without hunting for it.
