Skip to content

feat(site/src/pages/DeploymentSettingsPage/LicensesSettingsPage): add per-license Products section with Coder Agents price gates - #28051

Draft
jaaydenh wants to merge 1 commit into
runtime-hours-entitlementsfrom
license-page-t2yd
Draft

feat(site/src/pages/DeploymentSettingsPage/LicensesSettingsPage): add per-license Products section with Coder Agents price gates#28051
jaaydenh wants to merge 1 commit into
runtime-hours-entitlementsfrom
license-page-t2yd

Conversation

@jaaydenh

@jaaydenh jaaydenh commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-08-12 at 3 53 48 PM

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.

Refs CODAGT-808. The Air-gapped license type is deferred until a license claim defines it.

Notes for review:

  • Tooltip copy for "Total Agent hours" and "Concurrent chats" is placeholder pending product copy.
  • The "Manage usage" link goes to /deployment/groups (deployment-scoped) rather than the mock's default-org groups URL, since the default org is not guaranteed to be named coder.
  • Enforcement in feat: limit concurrent chat agents with pooled admission #27902 currently uncaps concurrency while usage is below the allocation; per this UI, concurrency should only be capped at the hard limit. Flagging so UI and enforcement agree.

… per-license Products section with Coder Agents price gates

Each license card now always expands to a Products section: a Coder
Workspaces box with active seat usage, and (on Premium licenses) a Coder
Agents box driven by the agent_runtime_hours_* license claims and merged
agent_runtime_hours entitlement.

The Coder Agents box renders five states: no allocation (dashed purple
upgrade CTA), unlimited (-1 sentinel), normal usage, allocation exceeded
(red border, red 'Agent hours exceeded' status, chats stay Unlimited),
and hard limit exceeded (red 'Hard limit exceeded' status, chats capped
at 5, mirroring the backend's maxConcurrentRootAgents). Usage and
overage indicators follow the AI Governance winning-license pattern via
a generalized isLicenseApplicableForFeatureUsage helper.

The header gains a Type column (Trial/Standard) and the left label now
shows the feature set only (Premium/Enterprise).
@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

CODAGT-808

@jaaydenh

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f00afbb9a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +19 to +22
// Mirrors the backend's maxConcurrentRootAgents constant, which caps
// concurrent chats once the hard limit is reached. It is not exposed via
// the API, so keep this value in sync with the backend.
const maxConcurrentChatsOverHardLimit = 5;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid claiming a five-chat cap before it is enforced

For Premium licenses with no allocation, or whose displayed usage reaches a hard limit, this constant tells admins that concurrent chats are capped at five. In the reviewed commit, however, decodeAgentRuntimeHours explicitly states that the concurrency-limited mode does not exist yet, and a repository-wide search finds no maxConcurrentRootAgents implementation. Either land the enforcement together with this UI or avoid displaying a fixed cap, otherwise the license page misrepresents the active price gate.

Useful? React with 👍 / 👎.

Comment on lines +112 to +114
: agentHoursAllocation !== undefined &&
agentHoursAllocation > 0 &&
agentHoursAllocation === agentRuntimeHoursFeature?.limit;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use the merged usage period to identify the winning license

When two effective licenses have the same positive allocation, this equality marks both as the winner even though Entitlements.AddFeature selects a single license by feature comparison, with agent-runtime tests confirming that the newest issued-at license supplies the merged limits and usage period. A renewal can therefore make both cards display the same usage, and an older duplicate with a different hard threshold can incorrectly report Hard limit exceeded and the five-chat cap. Match the merged usage period or otherwise uniquely identify the selected license rather than comparing allocation alone.

Useful? React with 👍 / 👎.

Comment on lines +51 to +55
<button
type="button"
aria-label={`${label} information`}
className="m-0 inline-flex appearance-none border-0 bg-transparent p-0 text-content-secondary"
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exercise the new tooltip interactions in Storybook

These new tooltip buttons introduce keyboard and pointer interactions, but the added stories only inspect static metric text and never focus or hover either trigger to verify that its tooltip appears. Add play steps covering the real tooltip interaction and accessible content for both product cards, as required for frontend behavior changes.

AGENTS.md reference: site/AGENTS.md:L9-L10

Useful? React with 👍 / 👎.

Comment on lines +33 to +34
// The Users header field and the Coder Workspaces product card show
// the same seat usage.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove comments that narrate the following assertions

This comment merely paraphrases the immediately following getAllByText(...).toHaveLength(2) assertion, and the same story adds several similar comments immediately before checks for absent products and displayed concurrency. Remove these assertion narrations and retain comments only where they explain non-obvious behavior.

AGENTS.md reference: site/AGENTS.md:L15-L15

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant