Skip to content

fix(cli): let the server enforce slug-length plan limits - #208

Merged
Brooooooklyn merged 3 commits into
mainfrom
fix/short-slug-prompt-paid-plan
May 18, 2026
Merged

Brooooooklyn merged 3 commits into
mainfrom
fix/short-slug-prompt-paid-plan

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented May 18, 2026 •

Copy link
Copy Markdown
Member

Summary

  • The deploy / AI-setup slug prompt rejected any slug of 5 characters or fewer unconditionally (validateProjectSlug), so a Pro user trying to deploy with a short slug like oxc could never get past the prompt — even though the API correctly gates length <= 5 on user.plan === 'free'.
  • Drop the client-side length rule and let the server decide. Format check (lowercase alphanumeric + dashes) stays client-side.
  • Add 403 to isRetryableCreateError so free-plan users who try a short slug get re-prompted rather than the deploy bailing out.

Test plan

  • vp test run packages/void/test/unit/deploy-project-setup.test.ts — replaced the old "rejects short slugs" assertion with one that asserts short slugs pass the client validator; added a new test that mocks a PlatformApiError(403) and verifies the prompt loops and succeeds on a longer second slug.
  • vp run --filter ./packages/void typecheck — clean.

🤖 Generated with Claude Code


Note

Medium Risk
Moderate risk: changes project-creation retry behavior and error handling for 403 responses, which could affect interactive flows or cause unexpected re-prompts if server error formats differ.

Overview
Allows short project slugs through the CLI validator and defers plan-based slug-length enforcement to the server.

Introduces createProjectWithSlugRetry to centralize the “prompt slug → call createProject → re-prompt on retryable errors” loop, and reuses it in both deploy/link (promptAndCreateProject) and the AI setup flow in index.ts.

Expands retryable create errors to include slug-related 403 responses (detected by scanning both error.code and error.body for “slug”), while avoiding retries for unrelated 403s; unit tests are updated/added to cover these cases.

Reviewed by Cursor Bugbot for commit b8cb4bf. Bugbot is set up for automated code reviews on this repo. Configure here.

The deploy/AI-setup slug prompt rejected any slug of 5 characters or
fewer unconditionally, even for paid users — so a Pro user trying to
deploy with a short slug (e.g. `oxc`) could never get past the prompt.
The plan-aware check already exists on the API; trust it and re-prompt
on 403 so free-plan users still get a smooth retry loop.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@netlify

netlify Bot commented May 18, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for staging-void-cloud ready!

Name Link
🔨 Latest commit b8cb4bf
🔍 Latest deploy log https://app.netlify.com/projects/staging-void-cloud/deploys/6a0b326383963f00088d1167
😎 Deploy Preview https://deploy-preview-208--staging-void-cloud.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread packages/void/src/cli/create-project.ts
Comment thread packages/void/src/cli/project-slug.ts
Address review feedback on the slug-length plan rejection retry loop:

- isRetryableCreateError now only retries on 403 when the error message
  mentions "slug" — prevents infinite re-prompt loops on unrelated 403s
  like the "account suspended" response from the auth middleware.
- runAiSetupPrompt (dev-server AI prompt) now retries on slug-related
  403s instead of bailing with a generic "Failed to create project"
  error. Previously the client-side length check shielded this path;
  removing it exposed the gap.
- Add a test asserting non-slug 403s are surfaced (not retried).

@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: 92ad011345

ℹ️ 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 thread packages/void/src/cli/create-project.ts Outdated

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 92ad011. Configure here.

Comment thread packages/void/src/index.ts
… full 403 body

- Extract createProjectWithSlugRetry from promptAndCreateProject so the
  AI-setup path in index.ts reuses the same retry loop instead of duplicating
  prompt/error/log logic (Cursor Bugbot review on 92ad011).
- Widen isSlugRelatedError to inspect both error.code and error.body instead
  of short-circuiting with `code ?? body`, so a future 403 response with a
  generic top-level code (e.g. "forbidden") and a slug message in `message`
  still triggers the re-prompt (Codex P2 review on 92ad011).
- Add a unit test covering the generic-code + slug-in-message case.
@Brooooooklyn
Brooooooklyn merged commit b45dbe5 into main May 18, 2026
10 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/short-slug-prompt-paid-plan branch May 18, 2026 16:04
@cpojer

cpojer commented May 18, 2026

Copy link
Copy Markdown
Member

I added it previously to the CLI because it gave faster feedback to the user. Sorry, didn't realize that the Pro plan can side-step the slug length check.

cpojer pushed a commit that referenced this pull request Sep 11, 2026
* fix(ci): invoke built void CLI directly in smoke test

The nightly Smoke Test has failed on every run for weeks at the
"Deploy kitchen-sink" step with:

    error: Command 'void' not found in node_modules/.bin

Root cause: the `void` package bin points at dist/cli/cli.mjs, which is
gitignored and only produced by the `vp run build` step. pnpm links bins
at install time, so the pre-build installs skip node_modules/.bin/void
(the "Failed to create bin ... ENOENT ...dist/cli/cli.mjs" warnings). The
post-build `vp install` meant to re-link it short-circuits with "Already
up to date" and never re-creates the symlink, so `vp exec void` fails.

Fix: run the freshly built CLI directly via `node
node_modules/void/dist/cli/cli.mjs deploy` — deterministic and free of
pnpm's bin-linking timing. `void deploy` runs `vite build` internally
(vite's bin links normally) and never spawns the `void` bin, so bypassing
the symlink is safe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump framework submodule to v0.10.2

Advances the framework submodule cad3c32 (void v0.9.3) -> 83307db
(origin/main, void v0.10.2) so the nightly smoke test exercises the
current framework. 19 commits, all already merged to framework main —
the old pointer is an ancestor, so this is a clean fast-forward.

The platform links void / @void/react via link: and kitchen-sink uses
workspace:*, so this moves dashboard/api/kitchen-sink onto void 0.10.2.
Verified locally against 0.10.2: void/@void/react/@void/vue deps
unchanged, hono stays ^4.12.18 (catalog pins 4.12.18), no pnpm-lock
drift, and vp run build:all + vp run check + lint + fmt all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cpojer pushed a commit that referenced this pull request Sep 11, 2026
…cates (#209)

Tests 5 (KV) and 8 (Queues) passed a predicate to page.waitForResponse
whose parameter is `response`, but the body referenced an undefined `r`,
so every run threw `page.waitForResponse: r is not defined`
(ReferenceError). `r` is a leftover from renaming the param `r` ->
`response` in #45 that missed these two `.request()` calls.

Latent since #45 (Mar 22) — the smoke test never reached the test phase
until the deploy step was unblocked in #208. With deploy fixed, 9/11
tests pass and only these two failed for this reason.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants