[codex] ungate automations#4734
Conversation
|
Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews. |
📝 WalkthroughWalkthroughSubscription-based gating for automations is removed across the stack: DB selection, tRPC mutations, dispatch host resolution, and frontend paywall/demo/docs/pricing were updated to no longer require paid subscriptions. ChangesAutomations feature ungating
Sequence DiagramsequenceDiagram
participant Client
participant automationRouter as automationRouter
participant requireActiveOrgMembership as requireActiveOrgMembership
participant dispatchAutomation as dispatchAutomation
Client->>automationRouter: create / setEnabled / runNow
automationRouter->>requireActiveOrgMembership: verify membership
requireActiveOrgMembership-->>automationRouter: membership confirmed
automationRouter->>dispatchAutomation: dispatch (when applicable)
dispatchAutomation-->>automationRouter: outcome (no skipped_unpaid)
automationRouter-->>Client: response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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 |
|
Ready to review this PR? Stage has broken it down into 6 individual chapters for you: Chapters generated by Stage for commit cd3fbaf on May 19, 2026 9:23pm UTC. |
Greptile SummaryThis PR removes all Pro-plan gates from the Automations feature, making it available to every authenticated user. The changes span the full stack: cron scheduler, tRPC mutations, desktop route guard, and sidebar navigation.
Confidence Score: 5/5Safe to merge — all paywall removal points are consistent across the cron scheduler, dispatch pipeline, tRPC mutations, and desktop UI with no dangling references. Every layer of the paywall (frontend route guard, sidebar gate, tRPC subscription checks, cron subscription filter, and dispatch defense-in-depth) is removed in a coordinated, internally consistent way. The skipped_unpaid outcome variant is eliminated from both the type definition and all call sites. The third caller of dispatchAutomation (dispatch/[id]/route.ts) never pattern-matched on skipped_unpaid and is unaffected. No dangling references to GATED_FEATURES.AUTOMATIONS remain after the constants change. No files require special attention.
|
| Filename | Overview |
|---|---|
| apps/api/src/app/api/automations/evaluate/route.ts | Removes the EXISTS subquery that filtered out automations from non-paid orgs; the cron scheduler now dispatches all enabled, due automations regardless of subscription status. |
| apps/desktop/src/renderer/components/Paywall/constants.ts | Removes AUTOMATIONS from GATED_FEATURES, PRO_FEATURES, and FEATURE_ID_MAP; no dangling references remain since GATED_FEATURES.TASKS still anchors the other usages. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/automations/layout.tsx | Removes the paywall useEffect guard that redirected free-tier users away from /automations; the layout now simply renders the outlet for all authenticated users. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx | Removes gateFeature(GATED_FEATURES.AUTOMATIONS, ...) wrapper from the automations nav handler; GATED_FEATURES and gateFeature are still legitimately imported for the Tasks gate. |
| packages/trpc/src/router/automation/automation.ts | Replaces requireActiveOrgMembershipWithSubscription + requirePaidSubscription with plain requireActiveOrgMembership on create, setEnabled, and runNow; also removes the skipped_unpaid outcome handler from runNow, consistent with its removal from DispatchOutcome. |
| packages/trpc/src/router/automation/dispatch.ts | Removes subscription join and paidPlan guard from resolveTargetHost and drops the skipped_unpaid variant from DispatchOutcome; the only caller outside this package (dispatch/[id]/route.ts) serialises the outcome as JSON and never pattern-matched on skipped_unpaid, so no breakage. |
Sequence Diagram
sequenceDiagram
participant QStash
participant EvaluateRoute as evaluate/route.ts
participant DispatchRoute as dispatch/[id]/route.ts
participant DispatchFn as dispatchAutomation()
participant DB as Database
QStash->>EvaluateRoute: POST (signed)
EvaluateRoute->>DB: "SELECT automations WHERE enabled=true AND nextRunAt<=now"
Note over EvaluateRoute,DB: (subscription check removed)
DB-->>EvaluateRoute: due automations
EvaluateRoute->>QStash: batchJSON dispatch jobs
EvaluateRoute->>DB: advance nextRunAt for each
QStash->>DispatchRoute: POST automationId + scheduledFor
DispatchRoute->>DB: fetch automation
DispatchRoute->>DispatchFn: dispatchAutomation()
DispatchFn->>DB: resolveTargetHost (host only, no subscription join)
alt host found and online
DispatchFn->>DB: insert automationRuns (dispatching)
DispatchFn-->>DispatchRoute: dispatched
else host offline or missing
DispatchFn->>DB: insert automationRuns (skipped_offline)
DispatchFn-->>DispatchRoute: skipped_offline
end
DispatchRoute-->>QStash: 200 ok outcome
Reviews (1): Last reviewed commit: "ungate automations" | Re-trigger Greptile
3334e61 to
3b14ffb
Compare
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
3b14ffb to
cd3fbaf
Compare
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)
packages/trpc/src/router/automation/dispatch.ts (1)
172-198:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix host ordering to select the most recently updated online host.
Line 197 uses
orderBy(v2Hosts.updatedAt)withoutdesc(). In Drizzle ORM,orderBy(column)defaults to ascending order, so withlimit(1), the fallback path selects the oldest online host instead of the most recently updated one. This causes untargeted automations to dispatch to stale machines.Suggested fix
-import { and, eq } from "drizzle-orm"; +import { and, desc, eq } from "drizzle-orm"; ... - .orderBy(v2Hosts.updatedAt) + .orderBy(desc(v2Hosts.updatedAt))🤖 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 `@packages/trpc/src/router/automation/dispatch.ts` around lines 172 - 198, The query that selects the host is ordering by v2Hosts.updatedAt in ascending order, so limit(1) returns the oldest online host; change the ordering to descending to pick the most recently updated online host. In the dbWs select block that assigns to host (the query using v2Hosts, v2UsersHosts, and the where on automation.ownerUserId/organizationId), replace orderBy(v2Hosts.updatedAt) with an orderBy specifying descending order on v2Hosts.updatedAt (e.g., orderBy(desc(v2Hosts.updatedAt)) or the ORM's desc operator) so the limit(1) returns the latest updated host.
🤖 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 `@packages/trpc/src/router/automation/dispatch.ts`:
- Around line 172-198: The query that selects the host is ordering by
v2Hosts.updatedAt in ascending order, so limit(1) returns the oldest online
host; change the ordering to descending to pick the most recently updated online
host. In the dbWs select block that assigns to host (the query using v2Hosts,
v2UsersHosts, and the where on automation.ownerUserId/organizationId), replace
orderBy(v2Hosts.updatedAt) with an orderBy specifying descending order on
v2Hosts.updatedAt (e.g., orderBy(desc(v2Hosts.updatedAt)) or the ORM's desc
operator) so the limit(1) returns the latest updated host.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8c4be6f1-9b1f-4940-bca6-ff5d5cd4d406
📒 Files selected for processing (15)
apps/api/src/app/api/automations/evaluate/route.tsapps/desktop/src/renderer/components/Paywall/components/FeaturePreview/FeaturePreview.tsxapps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/AutomationsDemo/AutomationsDemo.tsxapps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/AutomationsDemo/index.tsapps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/SlackIntegrationDemo/SlackIntegrationDemo.tsxapps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/SlackIntegrationDemo/index.tsapps/desktop/src/renderer/components/Paywall/constants.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/automations/layout.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsxapps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsxapps/docs/content/docs/automations.mdxapps/marketing/src/app/pricing/constants.tspackages/sdk/src/resources/automations.tspackages/trpc/src/router/automation/automation.tspackages/trpc/src/router/automation/dispatch.ts
💤 Files with no reviewable changes (3)
- apps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/AutomationsDemo/AutomationsDemo.tsx
- apps/docs/content/docs/automations.mdx
- apps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/AutomationsDemo/index.ts
✅ Files skipped from review due to trivial changes (3)
- apps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/SlackIntegrationDemo/index.ts
- apps/desktop/src/renderer/components/Paywall/components/FeaturePreview/components/SlackIntegrationDemo/SlackIntegrationDemo.tsx
- packages/sdk/src/resources/automations.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx
- apps/desktop/src/renderer/components/Paywall/components/FeaturePreview/FeaturePreview.tsx
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/automations/layout.tsx
- apps/api/src/app/api/automations/evaluate/route.ts
- packages/trpc/src/router/automation/automation.ts
Summary
Why
Automations should be available to all authenticated users instead of being gated behind Pro.
Validation
Summary by cubic
Ungated Automations for all authenticated users across the app and backend. Removed Pro checks in desktop, API, TRPC, and dispatch, and updated docs, SDK, and pricing to reflect free availability.
PRO_FEATURES; took Automations out ofGATED_FEATURES,PRO_FEATURES, andFEATURE_ID_MAP; updated plan comparison to show Automations on Free.skipped_unpaidhandling.resolveTargetHostreturns host only and still checks online status.Written for commit cd3fbaf. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
New Features
New Features / Access
Documentation
UI / Marketing