Team

Plan Enforcement

How Technical Debt Radar enforces plan limits on both frontend and backend — feature gating, error responses, and the full enforcement matrix.

Plan Enforcement

Technical Debt Radar enforces plan limits at every layer --- API guards on the backend, UI gates on the frontend, and CLI checks before AI operations. When a user attempts to access a feature not included in their plan, they receive a clear error with instructions to upgrade.

Full Enforcement Matrix

This table shows every gated feature and the minimum plan required to access it.

FeatureFreeSoloProTeamEnterprise
CLI: radar scanYesYesYesYesYes
CLI: radar initYesYesYesYesYes
CLI: radar validateYesYesYesYesYes
CLI: radar runYesYesYesYesYes
CLI: radar badgeYesYesYesYesYes
CLI: radar fix---YesYesYesYes
CLI: radar summary---YesYesYesYes
CLI: radar pack------YesYesYes
GitHub Action (deterministic)YesYesYesYesYes
PR merge gate (status check)---YesYesYesYes
AI PR comments------YesYesYes
AI cross-file analysis------YesYesYes
GitLab integration------YesYesYes
Dashboard: debt score---YesYesYesYes
Dashboard: trend charts---YesYesYesYes
Dashboard: arch graph------YesYesYes
Dashboard: policy editor------YesYesYes
Dashboard: rule packs------YesYesYes
Dashboard: team analytics---------YesYes
README badge---YesYesYesYes
Slack notifications------YesYesYes
Webhook API------YesYesYes
Coverage delta tracking------YesYesYes
SSO (SAML/OIDC)------------Yes
Self-hosted deployment------------Yes
SLA guarantee------------Yes

Resource Limits

ResourceFreeSoloProTeamEnterprise
Repositories25UnlimitedUnlimitedUnlimited
Members11UnlimitedUnlimitedUnlimited
Organizations11310Unlimited
AI credits/month0505002,000Unlimited

Backend Enforcement

All plan checks happen server-side in the NestJS API. The frontend never makes the final decision about feature access.

PlanGuard

The PlanGuard is a NestJS guard that checks the organization's active plan before allowing a request to proceed:

@UseGuards(PlanGuard)
@RequiresPlan('pro')
@Post('cross-file-analysis')
async runCrossFileAnalysis(@Body() dto: CrossFileDto) {
  // Only Pro+ orgs reach this handler
}

Error Response Format

When a request is blocked by plan enforcement, the API returns a 403 Forbidden response with a structured error body:

{
  "statusCode": 403,
  "error": "PlanLimitExceeded",
  "message": "AI cross-file analysis requires the Pro plan or higher.",
  "currentPlan": "solo",
  "requiredPlan": "pro",
  "upgradeUrl": "https://app.radar.dev/acme-engineering/settings/billing?upgrade=pro",
  "feature": "cross-file-analysis"
}

Every plan-gated error includes:

FieldDescription
currentPlanThe organization's current plan identifier
requiredPlanThe minimum plan needed for this feature
upgradeUrlDirect link to the billing page with the recommended plan pre-selected
featureMachine-readable feature identifier

Resource Limit Errors

When an organization hits a resource limit (repos, members, orgs), the error format is similar:

{
  "statusCode": 403,
  "error": "ResourceLimitExceeded",
  "message": "Your Solo plan supports up to 5 repositories. You have 5 active repositories.",
  "currentPlan": "solo",
  "requiredPlan": "pro",
  "upgradeUrl": "https://app.radar.dev/acme-engineering/settings/billing?upgrade=pro",
  "resource": "repositories",
  "currentUsage": 5,
  "limit": 5
}

Credit Exhaustion Errors

When AI credits are exhausted:

{
  "statusCode": 403,
  "error": "CreditsExhausted",
  "message": "AI credits exhausted. Deterministic analysis continues. Credits reset on April 15.",
  "currentPlan": "pro",
  "creditsRemaining": 0,
  "creditsTotal": 500,
  "resetDate": "2026-04-15T00:00:00Z",
  "buyCreditsUrl": "https://app.radar.dev/acme-engineering/settings/billing/credits"
}

Frontend Enforcement

The frontend uses plan information to render appropriate UI states. This is a user experience layer --- it does not replace backend enforcement.

Feature Gates

Components check the organization's plan before rendering feature UI:

// Feature is hidden entirely if plan is insufficient
{org.plan >= Plan.PRO && (
  <CrossFileAnalysisPanel />
)}

// Feature shows an upgrade prompt
{org.plan < Plan.PRO ? (
  <UpgradePrompt
    feature="AI Cross-File Analysis"
    requiredPlan="pro"
    currentPlan={org.plan}
  />
) : (
  <CrossFileAnalysisPanel />
)}

Upgrade Prompt Component

When a user encounters a gated feature, the UpgradePrompt component displays:

  • The feature name and a brief description of what it does
  • The user's current plan
  • The required plan with its price
  • A direct link to the upgrade page

This avoids dead-end UI states. Users always know what they need to do and how much it costs.

Disabled States

For features that are visible but not usable on the current plan:

  • Buttons are disabled with a tooltip explaining the plan requirement
  • Menu items show a plan badge (e.g., "PRO" next to "Architecture Graph")
  • Charts show placeholder states with an upgrade call-to-action

CLI Enforcement

The CLI checks plan requirements before making AI API calls:

$ radar fix .
Error: AI Fix Generation requires the Solo plan or higher.
Your current plan: Free

Upgrade at: https://app.radar.dev/settings/billing?upgrade=solo

Tip: You can still identify violations with `radar scan .` (free)
and fix them manually, or use `radar scan --format ai-prompt` to
generate instructions for your own AI tool.

The CLI also checks credit balance before AI operations:

$ radar fix .
Error: AI credits exhausted (0/50 remaining).
Credits reset on: April 15, 2026

Buy more: radar credits buy --pack small
Or use: radar scan --format ai-prompt (free, uses your own AI tool)

How Enforcement Is Implemented

Request arrives
  → AuthGuard: verify JWT token
    → OrgRolesGuard: verify user has role in org
      → PlanGuard: verify org plan includes feature
        → CreditGuard: verify org has available credits (AI only)
          → Handler executes

Each guard runs in order. If any guard rejects the request, the subsequent guards do not execute. This ensures clear, specific error messages --- a user sees "upgrade to Pro" rather than a generic "forbidden" error.

Technical Debt Radar Documentation