license: soft-warn cap policy + /usage endpoint + UsageBanner#239
Merged
Conversation
Adds a Team plan-shaped quota model and switches paid-tier connector /
MCP-server caps from hard 403 to a soft upgrade nudge. Trial still has
a hard cap (it's a sales tool, abuse risk).
New surface:
- GET /api/license/usage → { plan, connectors{current,max,isOver},
mcpServers{...}, users{...}, isOverAny }
- frontend UsageBanner mounted in app/layout.tsx, fetches /usage,
renders an amber banner above the dashboard when any axis is over,
with a localized "Upgrade to {next-tier}" CTA + utm-tagged pricing
link. Dismissible per session.
The website's license.features map already carries maxConnectors,
maxMcpServers and maxUsers — no new contract bytes needed, just a
new endpoint that joins those with Prisma counts.
Backend changes:
- LicenseGuardService.checkCanCreateConnector / -McpServer:
only block when license.plan === 'trial'. Paid tiers go through
silently — the banner does the work.
- New LicenseGuardService.getUsage(userId, organizationId): joins
Prisma counts (connector, mcpServerConfig, user) with the
features payload to return UsageCap[]s.
- LicenseController: new @get('/usage') with optional JWT auth,
same shape as /status — anonymous self-hosted single-user instances
still get their global counts.
Frontend changes:
- New UsageBanner client component (similar shape to TrialBanner)
- license.getUsage() added to lib/api.ts
- Mounted in app/layout.tsx right after TrialBanner
Compatible with the website-side plan: lib/license.ts carries Starter
caps 5/3, Team 15/10, Business unlimited; backend doesn't enforce
these values, only reports them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Today connector / MCP-server caps on paid tiers return 403. With the upcoming pricing restructure (Starter 1u / 5 conn, Team 3u / 15 conn, Business 10u / ∞) we need caps to act as upgrade nudges, not hard blocks. User decision: "soft warn — backend mostra un upgrade nudge dopo N connectors ma non blocca."
Trial keeps a hard 403 (sales tool, abuse risk).
What
Contract
The website's `lib/license.ts` carries the cap values in the license `features` payload — Starter 5/3/1, Team 15/10/3, Business ∞/∞/10. Backend doesn't enforce, only reports.
Plan string "team" is silently accepted (column type is String, no enum migration).
Test plan