Repository navigation
Feat/admin grant custom reviews - #35
Conversation
Admins need to give custom review instructions to specific free users without changing their plan. A new boolean column on workspaces, custom_reviews_granted (not null, default false), records that grant separately from billing, so a workspace's plan and its feature grant stay independent.
Generated with drizzle-kit. Adds workspaces.custom_reviews_granted (boolean, not null, default false). The change is additive and every existing workspace starts without the grant. Already applied to the database.
Schema snapshot generated by drizzle-kit alongside the custom reviews grant migration, used to diff future migrations.
Adds the 0006_cultured_spirit entry so drizzle-kit migrate applies the custom reviews grant migration.
WorkspaceBilling gains canCustomizeReviews, true when the workspace is on a paid plan or an admin has granted the feature. Every place that gates custom review instructions can now ask billing one question instead of checking the plan itself. Adds setCustomReviewsGranted(workspaceId, granted) to turn the grant on or off.
effectiveReviewGuidance()'s second parameter was named `paid`. It's now `enabled`, since the guidance also applies to free workspaces with an admin grant. Behaviour is unchanged.
The settings page shows the Custom review instructions card, and the server accepts saving it, whenever billing.canCustomizeReviews is true. That covers paid plans and free workspaces with an admin grant. Workspaces without either are still rejected on save.
Webhook-triggered reviews resolve the workspace's guidance with billing.canCustomizeReviews instead of checking for a paid plan, so admin-granted free workspaces get their instructions and minimum severity applied.
Scans resolve the workspace's guidance with billing.canCustomizeReviews, matching PR reviews, so admin-granted free workspaces get their settings applied to scans too.
- AdminUserRow includes customReviewsGranted, read from workspaces.custom_reviews_granted, for the users table. - setCustomReviewsGrantAsAdmin(workspaceId, granted) grants or revokes the feature. As with the other admin actions, the API route re-checks the admin before calling it.
POST /api/admin/custom-reviews with { workspaceId, granted } turns
custom review instructions on or off for a workspace. Like the other
admin routes, it re-checks on the server that the caller is an admin
(403 otherwise). It returns 400 unless workspaceId is a string and
granted is a boolean.
Regenerated by the TanStack router generator to include the new admin API route.
Add a "Custom reviews" column to the admin users table: - Free workspaces get a switch to grant or revoke the feature. It shows the current state, has a tooltip, is disabled while saving, and refreshes the table when the save succeeds. - Paid workspaces show "included", since their plan already has it. - Users without a workspace show nothing. The table's minimum width grows to fit the new column.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Jargons review
Found 2 issues worth a look:
🟡 Medium — Inconsistent canCustomizeReviews logic
src/server/workspace.ts:164
The canCustomizeReviews property in WorkspaceBilling is derived from plan !== 'free' || (rows[0]?.customReviewsGranted ?? false). However, in getWorkspaceSettings and updateReviewPreferences, the check !billing.canCustomizeReviews is used to determine if custom review instructions are allowed. This creates a potential inconsistency where customReviewsGranted might be true, but billing.canCustomizeReviews is still false if plan is 'free' and customReviewsGranted is also false. The logic should consistently use the canCustomizeReviews property from WorkspaceBilling after it's been calculated.
Suggestion: Ensure that billing.canCustomizeReviews is correctly calculated and consistently used across all relevant functions. The current implementation of getWorkspaceBilling correctly calculates canCustomizeReviews, so the issue is in how isPaidPlan(billing.plan) was replaced. The updateReviewPreferences function should directly use billing.canCustomizeReviews instead of re-evaluating parts of its logic.
🔵 Low — Missing updatedAt field in workspaces table update
src/server/billing.ts:79
The setCustomReviewsGranted function updates the customReviewsGranted field but does not update the updatedAt timestamp for the workspaces table. This can lead to an inaccurate updatedAt value, which might be used for auditing or caching purposes.
Suggestion: Add updatedAt: new Date() to the .set() call in setCustomReviewsGranted to ensure the updatedAt timestamp is updated whenever the customReviewsGranted field changes.
🔧 Suggested fixes: open the fix PR →
Summary
Admins can now give custom review instructions to any Free user from
/admin→ Users, without changing their plan. Paid plans already include it.Changes
billing.canCustomizeReviews: one check (paid plan or admin grant) used by settings, saving, PR reviews and scansPOST /api/admin/custom-reviews(re-checks on the server that the caller is an admin)