FinOps Copilot Seat Report Was Discarding Its Own Best Field
A report is only as honest as the fields it chooses to show, and this release is entirely about fields ZopNight’s Copilot seat report was already fetching from Microsoft and simply never displaying. Every change here is a direct follow-up to the seat-effectiveness feature shipped a few releases earlier, and every one of them was verified against either a live customer tenant or the exact code running in production, not against documentation or a guess.
The most consequential of the five is a parsing bug that made a trial subscription indistinguishable from a paid one that’s renewing that day.
A Trial and a Renewal Look Identical Except for One Field
Microsoft’s own API reports an active trial with status “Enabled” and a nextLifecycleDateTime, a response indistinguishable from a genuinely paid subscription on the day it renews. The one field that actually tells the two apart, isTrial, was already present in the response ZopNight’s discoverer receives. It sends no field-selection parameter on the subscriptions endpoint, so nothing was being withheld by Microsoft. The field simply got dropped the moment the response was parsed into ZopNight’s own model.
This was confirmed directly against a live customer tenant: a Microsoft 365 Copilot for Business subscription came back with isTrial set to true, status Enabled, and 25 seats, a combination that would previously have been reported as a paid renewal, since no downstream code ever checked the one field that said otherwise. The fix adds a fourth case to the logic that decides which direction a renewal date should be read in, specifically because on a trial, the normal renewal-direction assumption is the wrong one to apply.
An Error Badge That Couldn’t Tell You What To Do Next
A failed license assignment previously surfaced as a single generic “Error” badge, with no indication of what actually went wrong. The fix surfaces licenseAssignmentState.error using the vendor’s own word for the failure, verbatim, next to a plain-English explanation ZopNight adds on top of it. That distinction matters because a count violation and a dependency violation require opposite remediations: one means there aren’t enough licenses to go around, the other means a license depends on another one that isn’t assigned, and an admin fixing the wrong one wastes the fix entirely.
| Signal | What it tells an admin |
|---|---|
| CountViolation | Not enough licenses exist for this assignment; the fix is to buy or free up more |
| DependencyViolation | This license depends on another that isn’t assigned; the fix is to assign the prerequisite first |
| An unrecognized vendor error word | Still shown as-is, unglossed, rather than silently vanishing |
| Graph’s own literal “None” | Dropped entirely, since it’s the vendor’s own spelling of no error at all |
An error word ZopNight has no existing translation for still reaches the admin exactly as Microsoft phrased it, rather than disappearing into a lookup table that only recognizes what it was built to recognize. That one decision is what keeps an error Microsoft introduces next year from silently vanishing the day it first appears.
Silence Isn’t a Claim: assignedByGroup and belowThreshold
A license assigned through a group membership behaves differently when someone tries to reclaim it than one assigned directly to a person, so the report now marks group-assigned licenses explicitly. It renders only when a group actually exists behind the assignment, and deliberately doesn’t turn an empty value into a claim. An empty assignedByGroup field means either the license was assigned directly, or that fact was simply never reported back, and the report refuses to guess which. It shows the group’s internal id rather than its display name, since resolving a name would require a broader permission scope than this feature needs.
A separate fix closes a gap in the seat-count math itself: seats sitting unused below the activity threshold were previously left out of the breakdown entirely, which meant the visible numbers didn’t add up to the account’s actual total seat count. They’re now included, so the reported figures reconcile instead of leaving an unexplained gap an admin had to notice and question on their own. Two smaller fields round this out: activeDayRate on each seat, and daysSinceLastActivity on every Copilot surface a seat touches.
Verified Against Prod, Not Inferred
What separates this release from a routine bug-fix list is the verification standard behind every line of it. Nothing here is described from reading Microsoft’s documentation and assuming the behavior matches. Every fact was checked against either a real customer tenant or the specific code version already running in production. That standard is why a subtle bug like a discarded boolean field, one that would otherwise hide silently behind a status value that looks correct in every other respect, actually got caught instead of shipping quietly forward into the next release as well.
