Skip to content

Commit c809845

Browse files
improvement(self-host): enterprise features enabling (#6028)
* improvement(self-host): enterprise features enabling * chore(helm): bump chart to 1.3.0 for the enterprise self-host values values.yaml gained the ENTERPRISE_ENABLED switch and INSTANCE_ORG_* keys, and the feature-flag envDefaults moved from "false" to empty so the master switch can resolve them. Additive and backward compatible, so a minor bump. * fix(self-host): address review findings on instance org and org delete Drop the per-process instance-org id cache. It went stale once the organization was deleted through the Admin API, and clearing it from the delete handler would only heal the replica that served that request. The lookup runs on the signup path against a single-row table, so re-reading costs nothing and keeps every replica self-correcting. Scope the org-delete subscription conflict to entitled statuses. Matching any row regardless of status let a canceled subscription — which bills nobody — permanently block deletion. * fix(admin): block org delete on any live subscription, not just entitled ones ENTITLED_SUBSCRIPTION_STATUSES excludes trialing, so a trial — which grants no entitlement but is a live Stripe subscription that will convert — slipped past the delete guard and could be stranded against a removed organization id. Adds TERMINAL_SUBSCRIPTION_STATUSES and inverts the predicate: block unless the row is finished. Expressed as the terminal set so a status Stripe adds later defaults to blocking, which is the safe direction for a destructive operation. * fix(self-host): resolve SSO and access-control in the UI, not the raw env var Nine client consumers still read NEXT_PUBLIC_SSO_ENABLED / NEXT_PUBLIC_ACCESS_CONTROL_ENABLED directly while the server gates and settings nav had moved to the resolver. With only ENTERPRISE_ENABLED set that produced dead ends: the SSO settings section appeared but ssoClient() was never registered and no login button rendered, and the Access Control section appeared but its page reported "not entitled". Points every consumer at isSsoEnabled / isAccessControlEnabled so visibility and capability come from one place. * fix(admin): validate retention workspace targets on the Admin API too retentionOverrides and per-workspace PII rules both name a workspace, and neither field is a foreign key. The settings UI rejected ids belonging to another organization; the Admin API did not, so the two paths could persist different data for the same org. Extracts the check as getForeignWorkspaceTargetsReason and points both routes at it, so they cannot drift apart again. * fix(self-host): close three review findings on admin routes and cleanup Make org delete atomic. detachOrganizationWorkspaces committed on its own, so a failed delete left workspaces detached and re-billed while the organization, its members, and its settings survived. Adds a Tx variant so both commit together. Gate the admin session-policy PATCH on entitlement, matching the settings UI. Without it the stored policy was inert — getSessionPolicy resolves to no-op when the feature is off, so the one eager clamp would be undone on the next refresh. Stop emitting plan-wide housekeeping when billing is off. It is keyed to the hosted free-tier 30-day window, the same default the per-workspace pass deliberately refuses to apply off-hosted. * fix(admin): gate whitelabel on entitlement and emit detach audits post-commit The Admin whitelabel PATCH skipped the entitlement check the settings UI runs, so an admin key could set branding the product had not granted the org. detachOrganizationWorkspacesTx also wrote its audit rows inside the caller's transaction, contradicting its own doc comment — a rolled-back delete would have left audit history describing detachments that never happened. It now returns the rows and callers emit them after commit. * fix(self-host): refuse instance-org resolution when the slug is ambiguous organization.slug has no unique constraint, and the lookup took the first of however many matched. The choice is unordered, so two replicas could resolve different organizations and split new signups between them. Resolution is now three-state. Ambiguity is distinct from absence, so it both declines to adopt an arbitrary organization and declines to provision another one on top of the duplicates.
1 parent 591702b commit c809845

60 files changed

Lines changed: 3446 additions & 309 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/docs/content/docs/en/platform/enterprise/index.mdx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,17 @@ Clone a workspace into a linked child, then push or pull **deployed** workflow c
8181

8282
## Self-hosted setup
8383

84-
Self-hosted deployments enable enterprise features via environment variables instead of billing.
85-
86-
| Variable | Description |
87-
|----------|-------------|
88-
| `ORGANIZATIONS_ENABLED`, `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` | Team and organization management |
89-
| `ACCESS_CONTROL_ENABLED`, `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | Permission groups |
90-
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | SAML and OIDC sign-in |
91-
| `WHITELABELING_ENABLED`, `NEXT_PUBLIC_WHITELABELING_ENABLED` | Custom branding |
92-
| `AUDIT_LOGS_ENABLED`, `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` | Audit logging |
93-
| `NEXT_PUBLIC_DATA_RETENTION_ENABLED` | Data retention configuration |
94-
| `DATA_DRAINS_ENABLED`, `NEXT_PUBLIC_DATA_DRAINS_ENABLED` | Data drains |
95-
| `FORKING_ENABLED`, `NEXT_PUBLIC_FORKING_ENABLED` | Workspace forking |
96-
| `INBOX_ENABLED`, `NEXT_PUBLIC_INBOX_ENABLED` | Sim Mailer inbox |
97-
| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Disable invitations; manage membership via Admin API |
98-
99-
Once enabled, each feature is configured through the same Settings UI as Sim Cloud. When invitations are disabled, use the Admin API (`x-admin-key` header) to manage organization membership and workspace access. Internal members join the organization; external workspace members only receive access to a specific workspace.
84+
Self-hosted deployments unlock enterprise features through environment configuration instead of billing. One switch turns on the whole set:
85+
86+
```bash
87+
ENTERPRISE_ENABLED=true
88+
NEXT_PUBLIC_ENTERPRISE_ENABLED=true
89+
```
90+
91+
Each feature also keeps its own flag, so you can enable them one at a time or switch a single feature back off.
92+
93+
Most of these features read their settings from the organization that owns a workspace, so a deployment also needs an organization model — either one instance-wide organization that every user joins automatically, or organizations you provision yourself through the Admin API.
94+
95+
See the [self-hosted enterprise guide](/platform/enterprise/self-hosted) for the full variable list, both organization patterns, the Admin API reference, and troubleshooting.
96+
97+
Once enabled, each feature is configured through the same Settings UI as Sim Cloud. When invitations are disabled (`DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS`), use the Admin API (`x-admin-key` header) to manage organization membership and workspace access. Internal members join the organization; external workspace members only receive access to a specific workspace.

apps/docs/content/docs/en/platform/enterprise/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"title": "Enterprise",
33
"pages": [
44
"index",
5+
"self-hosted",
56
"sso",
67
"verified-domains",
78
"session-policies",
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
---
2+
title: Self-hosted Enterprise
3+
description: Run the full enterprise feature set on a self-hosted deployment without billing
4+
---
5+
6+
import { Callout } from 'fumadocs-ui/components/callout'
7+
import { Step, Steps } from 'fumadocs-ui/components/steps'
8+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
9+
10+
On Sim Cloud, enterprise features are unlocked by an Enterprise subscription. Self-hosted deployments have no subscription, so they are unlocked by environment configuration instead.
11+
12+
There are two parts to getting this right, and skipping the second is the most common reason features appear to do nothing:
13+
14+
1. **Enable the features** with `ENTERPRISE_ENABLED`.
15+
2. **Give them an organization to apply to.** Whitelabeling, PII redaction, permission groups, data drains, and audit scoping all read their settings from the organization that owns a workspace. A deployment where everyone works in personal workspaces has no organization for those settings to come from.
16+
17+
## Enable the feature set
18+
19+
Set the master switch and its client twin. Both are required — the server value decides access, and the `NEXT_PUBLIC_` value decides what the settings UI shows.
20+
21+
```bash
22+
ENTERPRISE_ENABLED=true
23+
NEXT_PUBLIC_ENTERPRISE_ENABLED=true
24+
```
25+
26+
That turns on organizations, permission groups, SSO, whitelabeling, audit logs, session policies, data retention, data drains, workspace forks, and the inbox.
27+
28+
### Turning one feature off
29+
30+
Every feature keeps its own flag, and an explicitly set flag always wins over the master switch. To run the suite without data drains:
31+
32+
```bash
33+
ENTERPRISE_ENABLED=true
34+
NEXT_PUBLIC_ENTERPRISE_ENABLED=true
35+
DATA_DRAINS_ENABLED=false
36+
NEXT_PUBLIC_DATA_DRAINS_ENABLED=false
37+
```
38+
39+
The individual flags also work on their own if you would rather opt in one at a time and leave the master switch unset.
40+
41+
| Feature | Server variable | Client variable |
42+
|---------|-----------------|-----------------|
43+
| Everything below | `ENTERPRISE_ENABLED` | `NEXT_PUBLIC_ENTERPRISE_ENABLED` |
44+
| Organizations | `ORGANIZATIONS_ENABLED` | `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` |
45+
| Permission groups | `ACCESS_CONTROL_ENABLED` | `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` |
46+
| SAML and OIDC sign-in | `SSO_ENABLED` | `NEXT_PUBLIC_SSO_ENABLED` |
47+
| Custom branding | `WHITELABELING_ENABLED` | `NEXT_PUBLIC_WHITELABELING_ENABLED` |
48+
| Audit logs | `AUDIT_LOGS_ENABLED` | `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` |
49+
| Session policies | `SESSION_POLICIES_ENABLED` | `NEXT_PUBLIC_SESSION_POLICIES_ENABLED` |
50+
| Data retention deletion | `DATA_RETENTION_ENABLED` | `NEXT_PUBLIC_DATA_RETENTION_ENABLED` |
51+
| Data drains | `DATA_DRAINS_ENABLED` | `NEXT_PUBLIC_DATA_DRAINS_ENABLED` |
52+
| Workspace forks | `FORKING_ENABLED` ||
53+
| Sim Mailer inbox | `INBOX_ENABLED` | `NEXT_PUBLIC_INBOX_ENABLED` |
54+
55+
<Callout type="warning">
56+
Data retention is the one feature that deletes data. Its flag controls the cleanup pass, not the settings screen — retention windows are always configurable. Nothing is ever deleted until you enable it, and even then only against windows you configured explicitly. Sim never applies the hosted plan defaults to a self-hosted deployment.
57+
</Callout>
58+
59+
## Choose an organization model
60+
61+
### Pattern 1: one organization for the whole instance
62+
63+
Best when everyone on the deployment belongs to the same company. Set a name and every user joins that organization automatically at signup, with their workspaces created org-owned.
64+
65+
```bash
66+
INSTANCE_ORG_NAME="Acme Inc"
67+
```
68+
69+
Optionally pin the slug and the owner:
70+
71+
```bash
72+
INSTANCE_ORG_SLUG=acme-inc
73+
INSTANCE_ORG_OWNER_EMAIL=admin@acme.com
74+
```
75+
76+
The organization is created the first time a user signs up. If `INSTANCE_ORG_OWNER_EMAIL` is not set, or names a user who does not exist yet, the first user to sign up becomes the owner; move ownership later with the Admin API. Provisioning is idempotent and safe across multiple replicas.
77+
78+
<Callout type="info">
79+
Instance-organization mode only applies when billing is disabled. With billing enabled, organizations are created through the normal subscription flow and these variables are ignored.
80+
</Callout>
81+
82+
#### Existing deployments
83+
84+
Users and workspaces created before you set `INSTANCE_ORG_NAME` stay where they are. Move them across once with the backfill script, which adds every user to the organization and attaches their workspaces:
85+
86+
```bash
87+
# Preview
88+
DATABASE_URL=... INSTANCE_ORG_NAME="Acme Inc" \
89+
bun run apps/sim/scripts/consolidate-users-into-organization.ts
90+
91+
# Apply
92+
DATABASE_URL=... INSTANCE_ORG_NAME="Acme Inc" \
93+
bun run apps/sim/scripts/consolidate-users-into-organization.ts --apply
94+
```
95+
96+
It is a dry run unless you pass `--apply`, and it is safe to re-run. Users who already belong to a different organization are reported and skipped, since a user can only belong to one.
97+
98+
### Pattern 2: many organizations you manage yourself
99+
100+
Best when one deployment serves several teams that should not see each other's data. Leave `INSTANCE_ORG_NAME` unset and provision organizations through the Admin API.
101+
102+
Set an admin key first:
103+
104+
```bash
105+
ADMIN_API_KEY=$(openssl rand -hex 32)
106+
```
107+
108+
<Steps>
109+
<Step>
110+
### Create an organization
111+
112+
The owner must not already belong to another organization.
113+
114+
```bash
115+
curl -X POST https://sim.example.com/api/v1/admin/organizations \
116+
-H "x-admin-key: $ADMIN_API_KEY" \
117+
-H "Content-Type: application/json" \
118+
-d '{"name": "Acme Inc", "ownerId": "user_123", "slug": "acme-inc"}'
119+
```
120+
</Step>
121+
122+
<Step>
123+
### Add members
124+
125+
```bash
126+
curl -X POST https://sim.example.com/api/v1/admin/organizations/$ORG_ID/members \
127+
-H "x-admin-key: $ADMIN_API_KEY" \
128+
-H "Content-Type: application/json" \
129+
-d '{"userId": "user_456", "role": "member"}'
130+
```
131+
</Step>
132+
133+
<Step>
134+
### Move a workspace into the organization
135+
136+
Organization-scoped features only apply to workspaces the organization owns.
137+
138+
```bash
139+
curl -X POST https://sim.example.com/api/v1/admin/dashboard/workspaces/$WORKSPACE_ID/move \
140+
-H "x-admin-key: $ADMIN_API_KEY" \
141+
-H "Content-Type: application/json" \
142+
-d "{\"destinationOrganizationId\": \"$ORG_ID\"}"
143+
```
144+
</Step>
145+
146+
<Step>
147+
### Configure organization settings
148+
149+
Branding, retention, and session policies can be set from the API instead of the UI.
150+
151+
<Tabs items={['Whitelabel', 'Data retention', 'Session policy']}>
152+
<Tab value="Whitelabel">
153+
```bash
154+
curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/whitelabel \
155+
-H "x-admin-key: $ADMIN_API_KEY" \
156+
-H "Content-Type: application/json" \
157+
-d '{"brandName": "Acme AI", "hidePoweredBySim": true}'
158+
```
159+
</Tab>
160+
<Tab value="Data retention">
161+
```bash
162+
curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/data-retention \
163+
-H "x-admin-key: $ADMIN_API_KEY" \
164+
-H "Content-Type: application/json" \
165+
-d '{"logRetentionHours": 2160}'
166+
```
167+
</Tab>
168+
<Tab value="Session policy">
169+
```bash
170+
curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/session-policy \
171+
-H "x-admin-key: $ADMIN_API_KEY" \
172+
-H "Content-Type: application/json" \
173+
-d '{"maxSessionHours": 168, "idleTimeoutHours": 48}'
174+
```
175+
</Tab>
176+
</Tabs>
177+
</Step>
178+
</Steps>
179+
180+
Deleting an organization requires echoing its slug, because the delete cascades to members, invitations, and permission groups, and detaches its workspaces:
181+
182+
```bash
183+
curl -X DELETE "https://sim.example.com/api/v1/admin/organizations/$ORG_ID?confirmSlug=acme-inc" \
184+
-H "x-admin-key: $ADMIN_API_KEY"
185+
```
186+
187+
## Verifying it worked
188+
189+
If a feature is enabled but nothing appears, check these in order.
190+
191+
**The settings section is missing.** The `NEXT_PUBLIC_` twin is not set, or the app was not restarted after adding it. Client variables are read at build and boot.
192+
193+
**The section appears but the API returns 403.** The server-side variable is missing while its client twin is set. Set both.
194+
195+
**The feature is on but has no effect inside a workspace.** The workspace is not owned by an organization. Check `workspace_mode` and `organization_id`:
196+
197+
```sql
198+
SELECT id, name, workspace_mode, organization_id FROM workspace;
199+
```
200+
201+
A workspace showing `personal` or a null `organization_id` will not pick up branding, PII redaction, permission groups, or drains. Use the backfill script or the workspace move endpoint.
202+
203+
**Retention is configured but nothing is deleted.** `DATA_RETENTION_ENABLED` is unset. Configuring windows and running the cleanup pass are separate switches by design.
204+
205+
## Related
206+
207+
- [Environment variables](/platform/self-hosting/environment-variables)
208+
- [Single Sign-On](/platform/enterprise/sso)
209+
- [Access control](/platform/enterprise/access-control)
210+
- [Roles and permissions](/platform/permissions)
211+
- [Workspaces](/platform/workspaces)

apps/docs/content/docs/en/platform/self-hosting/environment-variables.mdx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,19 @@ import { Callout } from 'fumadocs-ui/components/callout'
7070
| `ALLOWED_LOGIN_EMAILS` | Restrict signups to specific emails (comma-separated) |
7171
| `DISABLE_REGISTRATION` | Set to `true` to disable new user signups |
7272

73+
## Enterprise Features
74+
75+
Enterprise features are unlocked by configuration rather than billing on self-hosted deployments. One switch turns on the full set; per-feature flags below it override the switch either way.
76+
77+
| Variable | Description |
78+
|----------|-------------|
79+
| `ENTERPRISE_ENABLED`, `NEXT_PUBLIC_ENTERPRISE_ENABLED` | Enable the whole enterprise feature set |
80+
| `INSTANCE_ORG_NAME` | Name of the organization every user joins automatically at signup |
81+
| `INSTANCE_ORG_SLUG` | Slug for that organization (derived from the name when omitted) |
82+
| `INSTANCE_ORG_OWNER_EMAIL` | Owner of that organization (defaults to the first user to sign up) |
83+
84+
Most enterprise features read their settings from the organization that owns a workspace, so enabling the flags alone is not enough — the deployment also needs an organization model. See the [self-hosted enterprise guide](/platform/enterprise/self-hosted) for the per-feature flags, both organization patterns, and the Admin API.
85+
7386
## File Storage
7487

7588
By default Sim writes uploads to local disk. For production, point it at AWS S3, Azure Blob, or Google Cloud Storage. See [Object Storage](/platform/self-hosting/object-storage) for the full setup, bucket layout, and IAM policy.

apps/docs/content/docs/en/platform/self-hosting/index.mdx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ Open [http://localhost:3000](http://localhost:3000)
5555
</Card>
5656
</Cards>
5757

58+
## Enterprise Features
59+
60+
Organizations, SSO, permission groups, audit logs, whitelabeling, session policies, data retention, and data drains all run on a self-hosted deployment — no billing or subscription required. One switch turns on the set:
61+
62+
```bash
63+
ENTERPRISE_ENABLED=true
64+
NEXT_PUBLIC_ENTERPRISE_ENABLED=true
65+
```
66+
67+
Most of these features read their settings from the organization that owns a workspace, so enabling the flags is only half of it — your deployment also needs an organization model. Set `INSTANCE_ORG_NAME` to put every user in one shared organization automatically, or provision organizations yourself through the Admin API.
68+
69+
See the [self-hosted enterprise guide](/platform/enterprise/self-hosted) for both patterns, the per-feature flags, and troubleshooting.
70+
5871
## Architecture
5972

6073
| Component | Port | Description |

apps/sim/.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,34 @@ API_ENCRYPTION_KEY=your_api_encryption_key # Use `openssl rand -hex 32` to gener
141141
# ADMIN_API_KEY= # Use `openssl rand -hex 32` to generate. Enables admin API for workflow export/import.
142142
# Usage: curl -H "x-admin-key: your_key" https://your-instance/api/v1/admin/workspaces
143143

144+
# Enterprise Features (Optional - self-hosted). One switch enables organizations, SSO,
145+
# permission groups, audit logs, whitelabeling, session policies, data retention, data
146+
# drains, forks, and the inbox. Set both — the server value grants access, the
147+
# NEXT_PUBLIC_ value decides what the settings UI shows.
148+
# Docs: https://docs.sim.ai/platform/enterprise/self-hosted
149+
# ENTERPRISE_ENABLED=true
150+
# NEXT_PUBLIC_ENTERPRISE_ENABLED=true
151+
152+
# Per-feature overrides. An explicitly set flag wins over ENTERPRISE_ENABLED, so use these
153+
# to enable one feature on its own or to switch a single feature back off.
154+
# ACCESS_CONTROL_ENABLED= / NEXT_PUBLIC_ACCESS_CONTROL_ENABLED= # Permission groups
155+
# SSO_ENABLED= / NEXT_PUBLIC_SSO_ENABLED= # SAML and OIDC sign-in
156+
# WHITELABELING_ENABLED= / NEXT_PUBLIC_WHITELABELING_ENABLED= # Custom branding
157+
# AUDIT_LOGS_ENABLED= / NEXT_PUBLIC_AUDIT_LOGS_ENABLED= # Audit logging
158+
# SESSION_POLICIES_ENABLED= / NEXT_PUBLIC_SESSION_POLICIES_ENABLED=
159+
# DATA_RETENTION_ENABLED= / NEXT_PUBLIC_DATA_RETENTION_ENABLED= # Runs retention deletion — off by default
160+
# DATA_DRAINS_ENABLED= / NEXT_PUBLIC_DATA_DRAINS_ENABLED= # Export streams
161+
# FORKING_ENABLED= # Workspace forks
162+
# ORGANIZATIONS_ENABLED= / NEXT_PUBLIC_ORGANIZATIONS_ENABLED= # Organizations only
163+
164+
# Instance organization (Optional). Most enterprise features read their settings from the
165+
# organization that owns a workspace, so a deployment needs an organization for them to
166+
# apply. Setting a name puts every user in one shared org at signup and makes their
167+
# workspaces org-owned. Leave unset to manage organizations yourself via the Admin API.
168+
# INSTANCE_ORG_NAME=Acme Inc
169+
# INSTANCE_ORG_SLUG=acme-inc # Optional — derived from the name when unset
170+
# INSTANCE_ORG_OWNER_EMAIL=admin@acme.com # Optional — defaults to the first user to sign up
171+
144172
# Limits (Optional - self-hosted). With billing disabled (BILLING_ENABLED unset), no plan
145173
# limits are enforced. Explicitly setting a free-tier variable below opts that specific
146174
# limit back in at the configured value.

apps/sim/app/(auth)/components/sso-login-button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22
import { Chip, cn } from '@sim/emcn'
33
import { useRouter } from 'next/navigation'
4-
import { getEnv, isTruthy } from '@/lib/core/config/env'
4+
import { isSsoEnabled } from '@/lib/core/config/env-flags'
55
import { AUTH_BUTTON_CLASS } from '@/app/(auth)/components/constants'
66

77
interface SSOLoginButtonProps {
@@ -17,7 +17,7 @@ export function SSOLoginButton({
1717
}: SSOLoginButtonProps) {
1818
const router = useRouter()
1919

20-
if (!isTruthy(getEnv('NEXT_PUBLIC_SSO_ENABLED'))) {
20+
if (!isSsoEnabled) {
2121
return null
2222
}
2323

apps/sim/app/(auth)/login/login-form.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import { useRouter, useSearchParams } from 'next/navigation'
1616
import { requestJson } from '@/lib/api/client/request'
1717
import { forgetPasswordContract } from '@/lib/api/contracts'
1818
import { client } from '@/lib/auth/auth-client'
19-
import { getEnv, isFalsy, isTruthy } from '@/lib/core/config/env'
19+
import { getEnv, isFalsy } from '@/lib/core/config/env'
20+
import { isSsoEnabled } from '@/lib/core/config/env-flags'
2021
import { validateCallbackUrl } from '@/lib/core/security/input-validation'
2122
import { getBaseUrl } from '@/lib/core/utils/urls'
2223
import { quickValidateEmail } from '@/lib/messaging/email/validation'
@@ -343,7 +344,7 @@ export default function LoginPage({
343344
}
344345
}
345346

346-
const ssoEnabled = isTruthy(getEnv('NEXT_PUBLIC_SSO_ENABLED'))
347+
const ssoEnabled = isSsoEnabled
347348
const emailEnabled = !isFalsy(getEnv('NEXT_PUBLIC_EMAIL_PASSWORD_SIGNUP_ENABLED'))
348349
const hasSocial = githubAvailable || googleAvailable || microsoftAvailable
349350
const hasOnlySSO = ssoEnabled && !emailEnabled && !hasSocial

apps/sim/app/(auth)/signup/signup-form.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { createLogger } from '@sim/logger'
66
import { useRouter, useSearchParams } from 'next/navigation'
77
import { usePostHog } from 'posthog-js/react'
88
import { client, useSession } from '@/lib/auth/auth-client'
9-
import { getEnv, isFalsy, isTruthy } from '@/lib/core/config/env'
9+
import { getEnv, isFalsy } from '@/lib/core/config/env'
10+
import { isSsoEnabled } from '@/lib/core/config/env-flags'
1011
import { validateCallbackUrl } from '@/lib/core/security/input-validation'
1112
import { quickValidateEmail } from '@/lib/messaging/email/validation'
1213
import { captureClientEvent, captureEvent } from '@/lib/posthog/client'
@@ -360,7 +361,7 @@ function SignupFormContent({
360361
}
361362
}
362363

363-
const ssoEnabled = isTruthy(getEnv('NEXT_PUBLIC_SSO_ENABLED'))
364+
const ssoEnabled = isSsoEnabled
364365
const emailEnabled =
365366
!isFalsy(getEnv('NEXT_PUBLIC_EMAIL_PASSWORD_SIGNUP_ENABLED')) && emailSignupEnabled
366367
const hasSocial = githubAvailable || googleAvailable || microsoftAvailable

0 commit comments

Comments
 (0)