Skip to content

Commit da64840

Browse files
committed
fix(webapp): activate managed-cloud orgs via select-plan, not at creation
New managed-cloud orgs were created already activated, so they skipped the select-plan flow that provisions their billing entitlement — leaving the free-tier usage cap unenforced. Create managed-cloud orgs deactivated so they're routed through select-plan, which activates them once a plan is selected. Self-hosters have no billing gate and remain active immediately. Rename the Organization.v3Enabled Prisma field to isActivated (mapped to the existing v3Enabled column, so the database and billing service are unchanged) to better reflect what the flag now gates.
1 parent c7861be commit da64840

9 files changed

Lines changed: 22 additions & 13 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
New managed-cloud orgs were created already activated, so they skipped the select-plan flow that provisions their billing entitlement — leaving the free-tier usage cap unenforced. Managed-cloud orgs are now created deactivated and routed through select-plan, which activates them once a plan is selected. Self-hosters have no billing gate and remain active immediately.

apps/webapp/app/models/admin.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function adminGetOrganizations(userId: string, { page, search }: Se
131131
slug: true,
132132
title: true,
133133
v2Enabled: true,
134-
v3Enabled: true,
134+
isActivated: true,
135135
deletedAt: true,
136136
members: {
137137
select: {

apps/webapp/app/models/organization.server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export async function createOrganization(
8686
);
8787
}
8888

89-
const _features = featuresForUrl(new URL(env.APP_ORIGIN));
89+
const features = featuresForUrl(new URL(env.APP_ORIGIN));
9090

9191
const organization = await prisma.organization.create({
9292
data: {
@@ -102,7 +102,10 @@ export async function createOrganization(
102102
role: "ADMIN",
103103
},
104104
},
105-
v3Enabled: true,
105+
// Managed-cloud orgs start deactivated so they're routed through
106+
// select-plan, which provisions their billing entitlement and activates
107+
// them. Self-hosters have no billing gate, so they're active immediately.
108+
isActivated: !features.isManagedCloud,
106109
},
107110
include: {
108111
members: true,

apps/webapp/app/models/project.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export async function createProject(
3232
select: {
3333
id: true,
3434
slug: true,
35-
v3Enabled: true,
35+
isActivated: true,
3636
maximumConcurrencyLimit: true,
3737
maximumProjectCount: true,
3838
},
@@ -49,7 +49,7 @@ export async function createProject(
4949
}
5050

5151
if (version === "v3") {
52-
if (!organization.v3Enabled) {
52+
if (!organization.isActivated) {
5353
throw new Error(`Organization can't create v3 projects.`);
5454
}
5555
}

apps/webapp/app/routes/_app.orgs.$organizationSlug_.projects.new/route.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
118118
select: {
119119
id: true,
120120
title: true,
121-
v3Enabled: true,
121+
isActivated: true,
122122
v2Enabled: true,
123123
hasRequestedV3: true,
124124
_count: {
@@ -138,7 +138,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
138138
}
139139

140140
const { isManagedCloud } = featuresForRequest(request);
141-
if (isManagedCloud && !organization.v3Enabled) {
141+
if (isManagedCloud && !organization.isActivated) {
142142
return redirect(selectPlanPath({ slug: organizationSlug }));
143143
}
144144

@@ -151,7 +151,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
151151
title: organization.title,
152152
slug: organizationSlug,
153153
projectsCount: organization._count.projects,
154-
v3Enabled: organization.v3Enabled,
154+
isActivated: organization.isActivated,
155155
v2Enabled: organization.v2Enabled,
156156
hasRequestedV3: organization.hasRequestedV3,
157157
},
@@ -324,7 +324,7 @@ export default function Page() {
324324
const { organization, message } = useTypedLoaderData<typeof loader>();
325325
const lastSubmission = useActionData();
326326

327-
const canCreateV3Projects = organization.v3Enabled;
327+
const canCreateV3Projects = organization.isActivated;
328328

329329
const [form, { projectName, projectVersion }] = useForm({
330330
id: "create-project",

apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const loader = dashboardLoader(
4343
throw new Response(null, { status: 404, statusText: "Organization not found" });
4444
}
4545

46-
if (organization.v3Enabled) {
46+
if (organization.isActivated) {
4747
return redirect(organizationPath({ slug: organizationSlug }));
4848
}
4949

apps/webapp/test/helpers/seedTestEnvironment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export async function seedTestEnvironment(prisma: PrismaClient) {
1616
data: {
1717
title: `e2e-test-org-${suffix}`,
1818
slug: `e2e-org-${suffix}`,
19-
v3Enabled: true,
19+
isActivated: true,
2020
},
2121
});
2222

apps/webapp/test/helpers/seedTestUserProject.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function seedTestUserProject(
3535
data: {
3636
title: `e2e-pat-org-${suffix}`,
3737
slug: `e2e-pat-org-${suffix}`,
38-
v3Enabled: true,
38+
isActivated: true,
3939
members: { create: { userId: user.id, role: "ADMIN" } },
4040
},
4141
});

internal-packages/database/prisma/schema.prisma

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ model Organization {
212212
213213
runsEnabled Boolean @default(true)
214214
215-
v3Enabled Boolean @default(false)
215+
isActivated Boolean @default(false) @map("v3Enabled")
216216
217217
/// @deprecated
218218
v2Enabled Boolean @default(false)

0 commit comments

Comments
 (0)