Add design-system tier-limit gating and 402 handling - #5285
liamdebeasi wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
Builder reviewed your changes and found 5 potential issues 🔴
Review Details
Code Review Summary
PR #5285 adds a shared Builder DSI tier-limit contract, exposes it through Design and Slides actions, and updates the Design template with proactive quota gating, reactive 402 upgrade messaging, and code-indexing entitlement UI. The server parsing and focused unit coverage are a good foundation, and the fallback upgrade CTA is tested. This is standard risk because it changes shared API/business logic and multiple user-facing creation flows.
Key Findings
- 🔴 HIGH — The Design template passes an unsupported
lockedprop toSourceChoice, producing a TypeScript build error and not actually enforcing the code-source lock. - 🟡 MEDIUM — Slides adds the action and translations but does not integrate the tier-limit query or 402 handling into any creation flow.
- 🟡 MEDIUM — The Figma upload/index path still collapses structured 402 failures into a plain error, losing the upgrade CTA.
- 🟡 MEDIUM — The new public core export lacks a changeset.
- 🟡 MEDIUM — Entitlement fallback behavior permits code indexing when the tier response is unavailable or uses an unrecognized plan, contrary to the Enterprise-only policy; upstream upgrade URLs are also rendered without validation.
🧪 Browser testing: Attempted full verification after confirming the dev server was healthy, but all 15 planned cases were couldnt_verify because browser automation tools were unavailable environment-wide. Source inspection and typecheck independently confirmed the locked prop build failure.
| title={t("designSystemSetup.sections.code.title")} | ||
| selected={sourcePanel === "other" && otherSource === "code"} | ||
| onClick={() => selectOtherSource("code")} | ||
| locked={!codeIndexingAllowed} |
There was a problem hiding this comment.
🔴 Code-source lock prop is not supported by SourceChoice
SourceChoice only declares icon, title, selected, and onClick, so passing locked causes a TypeScript excess-property error and blocks the Design template build. Even if the type were widened, the component currently does not disable or otherwise prevent selecting the locked source; add the prop behavior or gate this call site with a supported implementation.
Additional Info
Reported independently by 3/3 code-review agents and confirmed by source-level typecheck.
| schema: z.object({}), | ||
| readOnly: true, | ||
| http: { method: "GET" }, | ||
| run: async () => fetchBuilderDesignSystemTierLimit(), |
There was a problem hiding this comment.
🟡 Slides tier-limit action is never integrated into creation flows
The action is added, but Slides clients do not query it or consume readDesignSystemTierLimitFailure; the list, setup dialog, and new-deck reference flow still submit the old create/index path. Users at the cap can receive the generic failure and non-Enterprise users can still select code/GitHub indexing, contrary to the PR's stated cross-template behavior.
Additional Info
Reported independently by 3/3 code-review agents.
| ); | ||
| } | ||
|
|
||
| function designSystemIndexFailureMessage( |
There was a problem hiding this comment.
🟡 Figma indexing drops structured tier-limit failures
The new structured failure helper is used for the GitHub and design.md mutations, but the primary Figma upload/index path still converts the response to a plain Error and catches it without readDesignSystemTierLimitFailure. If the proactive check is unavailable or the quota changes mid-flow, the user loses the 402 metadata and actionable upgrade link.
Additional Info
Reported by 1/3 agents; confirmed by tracing the Figma upload helper and catch path.
| "./client/collab": "./dist/client/collab/index.js", | ||
| "./client/composer": "./dist/client/composer/index.js", | ||
| "./client/conversation": "./dist/client/conversation/index.js", | ||
| "./client/design-system-tier-limit": "./dist/client/design-system-tier-limit.js", |
There was a problem hiding this comment.
🟡 public core export has no changeset
This adds a new public @agent-native/core/client/design-system-tier-limit export, but the PR contains no .changeset/*.md. Since packages/core is publishable, the required changeset check will fail and the export will not receive a versioned release.
Additional Info
Reported by 1/3 agents; repository guidance requires changesets for publishable core changes.
| current: null, | ||
| max: null, | ||
| atMax: false, | ||
| codeIndexingAllowed: true, |
There was a problem hiding this comment.
🟡 Unavailable tier responses fail open for Enterprise-only code indexing
Non-2xx and network-error paths return codeIndexingAllowed: true, while the UI treats unavailable status as permission to choose code/GitHub sources. Unknown entitlement should be represented separately or code indexing should remain blocked until the capability is known; non-code creation can still remain available.
Additional Info
Reported by 1/3 agents; based on the explicit Enterprise-only policy and the client gate at `status !== "ok"`.
|
@builderio-bot look at latest PR feedback and fix anything you agree with. Be skeptical. Reply to every comment (directly on the comment thread of each comment) if you fixed it or not and why |
…00b22e04d17f465288cd
|
There was a problem with your request, please try again later. Error id: |
|
@builderio-bot Try again |
|
✅ PR Feedback - Fixes Summary I've fixed the 3 valid feedback items and verified the 2 stale comments. Here's the status: Valid Feedback (Fixed)1. Figma indexing drops structured 402 tier-limit details ✅
2. Public core export lacks a changeset ✅
3. Unavailable tier responses fail open for Enterprise-only code indexing ✅
Stale Feedback (No Action Needed)Comment: Design
Comment: Slides tier-limit action never integrated
Verification
|
Summary
Adds a shared client/server contract for Design System Indexing (DSI) tier limits and wires it into the Design and Slides templates so users are blocked (with actionable upgrade CTAs) both proactively when at their plan's cap and reactively when a create is rejected with HTTP 402.
Problem
Non-Enterprise plans can now create a limited number of design systems, and
/design-systems/v1/indexcan reject over-cap creates with a 402. The Design and Slides UIs had no way to surface that limit before or after the fact — users could open the create flow and hit a generic failure with no explanation or upgrade path, and code/repo indexing (Enterprise-only) wasn't disabled for lower tiers.Solution
Introduced a typed client for reading Builder's
/design-systems/v1/tier-limitendpoint and for parsing structured 402 failures from the create/index call, then used it to gate the "new design system" entry points and code-indexing option in both templates, with localized error/upgrade messaging.Key Changes
packages/core/src/server/builder-design-systems.ts: newfetchBuilderDesignSystemTierLimit()reading plan/current/max/codeIndexingAllowedfrom/design-systems/v1/tier-limit(fails open withstatus: "unavailable"when unreachable);assertBuilderDesignSystemIndexOknow parses 402 responses into a structureddesign_system_tier_limit_exceededaction error with plan/current/max/upgradeUrl details; newdesignSystemTierUpgradeUrl()fallback link.packages/core/src/client/design-system-tier-limit.ts(new): shared client contract exposingDesignSystemTierLimit/DesignSystemTierLimitFailuretypes,readDesignSystemTierLimitFailure()to extract 402 failures from thrown action errors, andisDesignSystemTierAtMax()helper. Exported via@agent-native/core/client/design-system-tier-limit.templates/design/actions/get-design-system-tier-limit.tsandtemplates/slides/actions/get-design-system-tier-limit.ts(new): read-only GET actions exposing the tier-limit check to the client.templates/design/app/pages/DesignSystems.tsx: proactively queries the tier limit, prevents navigating to the create flow when at max, and shows an alert dialog with plan/count messaging and an upgrade link instead.templates/design/app/pages/DesignSystemSetup.tsx: shows a full-page "limit reached" state with upgrade CTA when at max; surfaces structured 402 failures (with upgrade link) on create errors; disables the "code" source choice whencodeIndexingAllowedis false.designSystems.tierLimit*,designSystemSetup.codeIndexingEnterpriseOnly) across all locales in both templates (zh-TWincluded for Slides).packages/core/src/server/builder-design-systems.spec.tscovering 402 handling on create (with/without anupgradeUrlin the body), andfetchBuilderDesignSystemTierLimitbehavior for standard plans, unlimited/Enterprise plans, and unreachable-endpoint fallback.To clone this PR locally use the Github CLI with command
gh pr checkout 5285You can tag me at @BuilderIO for anything you want me to fix or change