feat(app): search and switch projects from the command palette - #765
Conversation
Project entries set both suffix and description to the team name, so it appeared twice per row. Drop suffix and keep the description; the palette already renders a checkmark on the right for the active item. Also stop hiding the group when there is only one project in total, and wrap navigateTo so the action matches the void return type CommandItem expects.
🦋 Changeset detectedLatest commit: b283da0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@voidhrithik is attempting to deploy a commit to the HRCD Projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Thank you for following the naming conventions! 🙏 |
📝 WalkthroughWalkthroughThe command palette now loads projects across available teams and creates searchable project commands. OTP endpoints use centralized, environment-aware BotID checks. Project variable validation uses explicit null checks, and project service tests update their module import pattern. ChangesProject command palette
OTP human verification
Validation and test maintenance
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant OTPClient
participant OTPEndpoint
participant requireHuman
participant BotID
OTPClient->>OTPEndpoint: Submit OTP request
OTPEndpoint->>requireHuman: Check request
requireHuman->>BotID: Classify request
BotID-->>requireHuman: Return classification
requireHuman-->>OTPEndpoint: Allow or throw 403
OTPEndpoint-->>OTPClient: Process OTP or return denial
Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/shelve/app/composables/useAppCommands.ts`:
- Around line 20-23: Update the project-loading logic around useProjects to
track loaded and in-flight state per team slug separately from the project array
length. Skip fetching once a team’s response has loaded, including an empty
array, and prevent overlapping watcher invocations from issuing duplicate
requests by marking the team in flight before awaiting $fetch and clearing it
afterward.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 12d53008-bf87-4d5c-855f-ca721ca788c1
📒 Files selected for processing (2)
.changeset/command-palette-projects.mdapps/shelve/app/composables/useAppCommands.ts
useProjects is a useState with no default, so undefined means never loaded and an empty array means the team has no projects. The length check treated both as unloaded, so a team with no projects refetched on every teams change. fetchTeams also runs twice on mount, once from useAppCommands and once from CommandPalette, so both watcher passes saw undefined and issued the same request. Guard with an in-flight set.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/shelve/app/composables/useAppCommands.ts (1)
289-304: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDo not use the first team as the project-description context.
getTeamSlug()falls back toteams.value[0]. On routes withoutteamSlug, the first team’s projects therefore have no description, while other teams showin <team>. Use only an explicit route team for this comparison, or render the team description for every project.Suggested fix
- const currentTeamSlug = getTeamSlug() + const currentTeamSlug = typeof route.params.teamSlug === 'string' + ? route.params.teamSlug + : undefined🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/shelve/app/composables/useAppCommands.ts` around lines 289 - 304, Update the project description logic in the command-building flow to avoid using getTeamSlug(), whose fallback treats the first team as explicitly selected. Compare against only the route’s explicit teamSlug, or consistently include `in <team>` for every project when no explicit team is present, while preserving the current-team omission for an explicitly selected team.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/shelve/app/composables/useAppCommands.ts`:
- Around line 289-304: Update the project description logic in the
command-building flow to avoid using getTeamSlug(), whose fallback treats the
first team as explicitly selected. Compare against only the route’s explicit
teamSlug, or consistently include `in <team>` for every project when no explicit
team is present, while preserving the current-team omission for an explicitly
selected team.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7600eb99-112f-46f0-8184-46e8fe66da1c
📒 Files selected for processing (1)
apps/shelve/app/composables/useAppCommands.ts
Four eslint errors landed on main with HugoRCD#757 and HugoRCD#759, so autofix.ci has failed on every PR opened since. Nothing else in this branch touches those files, but the check stays red until they are fixed. index.put.ts compared a nullish groupId with != null. Now checks undefined and null explicitly, same as audit.ts already does. team-project-context.test.ts destructured ProjectsService, which the variable naming rule rejects. Imports the module namespace instead so the resetModules and dynamic import setup is unchanged.
|
@HugoRCD could you approve the workflow run when you get a chance? The last push needs it. The new commit fixes 4 eslint errors that have been on main since #757 and #759. autofix.ci has been failing on every PR opened since, #696 included. The three Vercel checks are stuck on "Authorization required to deploy", which needs your side too. |
Preview deployments sit behind Vercel Deployment Protection, which redirects the BotID challenge requests to the SSO login. The challenge can never be solved there, so checkBotId classified every OTP request as a bot and sign-in returned 403 Access denied.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/botid-preview-bypass.md:
- Line 5: Resolve the MD041 warning for the changeset by adding a top-level
Markdown heading after its required frontmatter, or update the markdownlint
configuration to exclude .changeset/**/*.md if plain release-note text is
intentional.
In `@apps/shelve/server/utils/auth.ts`:
- Line 25: Update the isDevelopment configuration used by requireHuman so only
the explicitly supported non-production environment, preview, enables
development mode; treat unset and unexpected VERCEL_ENV values as
production-like and keep enforcement enabled. Add tests covering unset, preview,
and production values.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 87ea7fbe-c31f-4c98-9f27-ee91b74335a7
📒 Files selected for processing (6)
.changeset/botid-preview-bypass.mdapps/shelve/server/api/auth/otp/send.post.tsapps/shelve/server/api/auth/otp/verify.post.tsapps/shelve/server/api/teams/[slug]/projects/[projectId]/variables/[variableId]/index.put.tsapps/shelve/server/utils/auth.tsapps/shelve/test/unit/team-project-context.test.ts
| "@shelve/app": patch | ||
| --- | ||
|
|
||
| Only enforce the BotID check on production, so OTP sign-in works on preview deployments. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Resolve the MD041 warning.
markdownlint-cli2 reports that the changeset body has no top-level heading. Exclude .changeset/**/*.md from MD041 if plain release-note text is intentional, or add a heading after the required frontmatter.
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.changeset/botid-preview-bypass.md at line 5, Resolve the MD041 warning for
the changeset by adding a top-level Markdown heading after its required
frontmatter, or update the markdownlint configuration to exclude
.changeset/**/*.md if plain release-note text is intentional.
Source: Linters/SAST tools
| export async function requireHuman(): Promise<void> { | ||
| const verification = await checkBotId({ | ||
| developmentOptions: { | ||
| isDevelopment: process.env.VERCEL_ENV !== 'production', |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n --hidden --glob '!node_modules' --glob '!dist' \
'\bVERCEL_ENV\b|\bNODE_ENV\b' .Repository: HugoRCD/shelve
Length of output: 1783
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- auth utility ---'
cat -n apps/shelve/server/utils/auth.ts
printf '%s\n' '--- auth utility usages ---'
rg -n -C 5 'checkBotId|isDevelopment|utils/auth' apps/shelve
printf '%s\n' '--- environment and deployment configuration ---'
fd -HI -t f 'vercel|environment|env|deploy|package.json|README' . | sort | head -200
rg -n -C 3 'VERCEL_ENV|NODE_ENV|Vercel|production|preview' \
apps/shelve package.json vercel.json .github 2>/dev/null || true
printf '%s\n' '--- deterministic value check ---'
python3 - <<'PY'
values = [None, "", "development", "preview", "production", "staging", "PRODUCTION"]
for value in values:
print(f"{value!r}: isDevelopment={value != 'production'}")
PYRepository: HugoRCD/shelve
Length of output: 39587
🌐 Web query:
Vercel VERCEL_ENV system environment variable production preview development BotID isDevelopment developmentOptions ignored production
💡 Result:
The VERCEL_ENV environment variable is a system-provided variable in Vercel that indicates the environment in which the application is currently running [1][2]. It is available at both build time and runtime [1][3]. The value of VERCEL_ENV is one of the following three strings [1][2]: - production: Used for the live, user-facing version of the application [4][2]. - preview: Used for deployments created from pull requests or non-production branches [4][2]. - development: Used when running the project locally on your machine via the Vercel CLI (e.g., using vercel dev) [5][4][2]. Regarding the specific terms mentioned: - BotID: There is no standard system environment variable named BotID related to Vercel's environment detection. - isDevelopment: This is not a standard Vercel system environment variable. If needed, you can infer this status in your code by checking if VERCEL_ENV === 'development' [1][2]. - developmentOptions: This is not a standard Vercel configuration or environment variable. - ignored: This does not appear to be a relevant term for Vercel's environment variable system. - production: As noted, this is a valid value for VERCEL_ENV [1][2]. In summary, Vercel automatically manages VERCEL_ENV to reflect your current deployment context, and it does not rely on custom variables like BotID or isDevelopment to determine environment state [1][3]. For local development, Vercel provides the vercel env pull command to download your project's environment variables into a local.env file, though system variables like VERCEL_ENV are typically injected automatically by the platform and the CLI [5][6].
Citations:
- 1: https://vercel.com/docs/environment-variables/system-environment-variables
- 2: https://env.dev/guides/vercel-env-variables
- 3: https://vercel.com/docs/git/vercel-for-gitlab
- 4: https://vercel.com/docs/deployments/environments
- 5: https://vercel.com/docs/environment-variables
- 6: https://vercel.com/docs/cli/env
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- requireHuman call sites ---'
rg -n -C 6 '\brequireHuman\b|/otp|OTP|one[- ]time|oneTime' apps/shelve --glob '!node_modules/**' --glob '!dist/**'
printf '%s\n' '--- self-hosting and environment documentation ---'
cat -n apps/lp/content/docs/5.self-hosting/1.vercel.md
cat -n apps/lp/content/docs/5.self-hosting/2.environment-variables.md
cat -n apps/shelve/.env.example
printf '%s\n' '--- environment schema and startup validation ---'
rg -n -C 8 'envSchema|VERCEL|environment variable|runtimeConfig' \
apps/shelve --glob '!node_modules/**' --glob '!dist/**' \
-g '*.ts' -g '*.md' -g '*.example'
printf '%s\n' '--- BotID package metadata and implementation references ---'
rg -n -C 5 'developmentOptions|isDevelopment|checkBotId' \
node_modules/botid node_modules/.pnpm 2>/dev/null | head -240 || trueRepository: HugoRCD/shelve
Length of output: 50372
Fail closed when VERCEL_ENV is unset.
requireHuman() protects both OTP endpoints. The current comparison enables BotID development mode for unset and unexpected values. The repository does not require or validate VERCEL_ENV, so a non-Vercel or misconfigured production deployment can bypass BotID enforcement. Use an explicit non-production allowlist or fail closed for unknown values. Add tests for unset, preview, and production.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/shelve/server/utils/auth.ts` at line 25, Update the isDevelopment
configuration used by requireHuman so only the explicitly supported
non-production environment, preview, enables development mode; treat unset and
unexpected VERCEL_ENV values as production-like and keep enforcement enabled.
Add tests covering unset, preview, and production values.
Source: MCP tools
Continues #686 by @onmax, rebased onto main. Their commit is kept as theirs and my changes sit on top.
Resolves #764.
What changed since #686
suffixon the right and once asdescriptionunder the label. Droppedsuffix, which reverts theCommandPalette.vueandpackages/types/src/Command.tsedits and brings the diff down to one file. The palette already draws a checkmark on the right for the active item, which is what @onmax suggested in the thread.navigateToin a block so the action matches thevoidreturn type onCommandItem.tscrejects the arrow-return form.Duplicate fetches
useProjectsis auseStatewith no default, soundefinedmeans never loaded and[]means the team has no projects. Thelength === 0check treated both as unloaded. The palette mounts on open (Navbar.vuerenders it behindv-if="isSearchActive"), so a team with no projects was refetched every single time you opened the palette.fetchTeams()also runs twice on mount, once inuseAppCommandsand once inCommandPalette.vue. Both watcher passes sawundefinedand issued the same request.Measured locally against Postgres with 3 teams, one of them having no projects:
After the 4 reopens the palette still listed all 5 projects, so the drop to zero is cache hits rather than the group breaking.
Testing
Ran locally against Postgres 16 with seeded data, 3 teams and 5 projects, one team deliberately empty. Confirmed in the browser:
The
TestsandCheck if packages can be builtchecks both pass on CI for this commit, andpnpm --filter @shelve/app testpasses locally too, 117 tests.Changeset added,
@shelve/appminor.On the failing checks
autofix.ciwas failing on 4 lint errors that are already on main, invariables/[variableId]/index.put.tsandtest/unit/team-project-context.test.ts. Neither is auto-fixable by eslint, which is how they got through.autofix.ymlruns onpull_requestonly, so it never runs on main, and every PR opened since #757 and #759 inherits the failure, #696 included.Fixed in its own commit here so the check can go green. Happy to pull it out into a separate PR if you would rather keep this branch to the palette work.
Vercel – shelve-lpandVercel – shelve-vaultstill fail with "Authorization required to deploy". That one needs your side.Summary by CodeRabbit