Files
coder/site
Jaayden Halko 995d7fe31b feat: add per-license Products section with Coder Agents price gates (#28051)
<img width="1100" height="312" alt="Screenshot 2026-08-17 at 3 43 51 PM"
src="https://github.com/user-attachments/assets/30d21467-93ec-4880-a430-ccd4b494b8f5"
/>


Each license card now always expands to a **Products** section: a Coder
Workspaces box showing active seat usage, and, on Premium licenses, a
Coder Agents box driven by the `agent_runtime_hours_*` license claims
and the merged `agent_runtime_hours` entitlement. The card header gains
a **Type** column (`Trial`/`Standard`), and the left header label now
shows the feature set only (`Premium`/`Enterprise`).

The Coder Agents box renders five states: no allocation (dashed purple
upgrade CTA), unlimited allocation (`-1` sentinel), normal usage,
allocation exceeded (red border and red "Agent hours exceeded" status;
concurrent chats stay Unlimited), and hard limit exceeded (red "Hard
limit exceeded" status; concurrent chats capped at 5, mirroring the
backend's `maxConcurrentRootAgents`, which is not exposed via the API).
Usage and overage indicators only render on the license whose allocation
matches the merged entitlement and which is currently effective,
following the existing AI Governance winning-license pattern via a
generalized `isLicenseApplicableForFeatureUsage` helper; AI Governance
add-on behavior is unchanged.

Stacked on #27985 (base branch `runtime-hours-entitlements`); do not
merge before it.

Notes for review:

- #27985 now grandfathers claim-less Premium licenses into a zero-hour
`agent_runtime_hours` allocation, so the merged entitlement (disabled,
`limit: 0`) and its measured `actual` are always present for Premium
deployments. The upgrade card's "Agent hours used" row therefore renders
universally; the `Premium` story pins that state.


- Agent hours usage now renders with exactly one decimal (e.g.
`16,264.3`, `42.0`), derived from #27985's new `actual_ms` field and
floored to tenths with integer math. The same floored value drives the
exceeded checks, so the displayed number and the red state flip at the
same instant; a fraction past the allocation now trips "Agent hours
exceeded" (`20,000.1 > 20,000`), pinned by the
`PremiumWithAgentHoursExceededByFraction` story. The allocation
denominator stays whole (it comes from the whole-hour license claim).
2026-08-18 20:07:28 +07:00
..