From 51ace655e4515226da600208f8c84e0a5825addf Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Tue, 21 Apr 2026 21:10:50 -0700 Subject: [PATCH 1/2] fix(migration): permission group migration error (#4258) --- .../migrations/0194_careless_pete_wisdom.sql | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/packages/db/migrations/0194_careless_pete_wisdom.sql b/packages/db/migrations/0194_careless_pete_wisdom.sql index e1ab6769c3..6c57f39f03 100644 --- a/packages/db/migrations/0194_careless_pete_wisdom.sql +++ b/packages/db/migrations/0194_careless_pete_wisdom.sql @@ -5,6 +5,9 @@ -- permission_group_member table also gains a denormalized workspace_id column -- so the database can enforce the "one group per user per workspace" -- invariant with a composite unique index. +-- +-- Every statement below is written to be idempotent so the migration can be +-- safely re-run after a partial failure. -- 0. Backfill workspace -> organization links for grandfathered workspaces whose -- billed account user is the sole owner of exactly one organization. This is a @@ -29,13 +32,42 @@ WHERE w."organization_id" IS NULL AND w."billed_account_user_id" = owner_orgs."user_id";--> statement-breakpoint -- 1. Add workspace_id columns as nullable so existing rows can coexist during the data migration. -ALTER TABLE "permission_group" ADD COLUMN "workspace_id" text;--> statement-breakpoint -ALTER TABLE "permission_group" ADD CONSTRAINT "permission_group_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "permission_group_member" ADD COLUMN "workspace_id" text;--> statement-breakpoint -ALTER TABLE "permission_group_member" ADD CONSTRAINT "permission_group_member_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "permission_group" ADD COLUMN IF NOT EXISTS "workspace_id" text;--> statement-breakpoint +DO $$ BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_name = 'permission_group_workspace_id_workspace_id_fk' + AND table_name = 'permission_group' + ) THEN + ALTER TABLE "permission_group" + ADD CONSTRAINT "permission_group_workspace_id_workspace_id_fk" + FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") + ON DELETE cascade ON UPDATE no action; + END IF; +END $$;--> statement-breakpoint + +ALTER TABLE "permission_group_member" ADD COLUMN IF NOT EXISTS "workspace_id" text;--> statement-breakpoint +DO $$ BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_name = 'permission_group_member_workspace_id_workspace_id_fk' + AND table_name = 'permission_group_member' + ) THEN + ALTER TABLE "permission_group_member" + ADD CONSTRAINT "permission_group_member_workspace_id_workspace_id_fk" + FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") + ON DELETE cascade ON UPDATE no action; + END IF; +END $$;--> statement-breakpoint + +-- 1b. Relax NOT NULL on permission_group.organization_id before the data migration. +-- Step 3 inserts clone rows with organization_id = NULL to mark them as the new +-- workspace-scoped shape. This DROP NOT NULL is a no-op if already nullable. +ALTER TABLE "permission_group" ALTER COLUMN "organization_id" DROP NOT NULL;--> statement-breakpoint -- 2. Materialize a plan of (source permission group, target workspace, new clone id) -- so we can insert the clone rows AND the member rows with stable references. +-- Temp tables are always fresh per transaction, so this is naturally idempotent. CREATE TEMP TABLE "__permission_group_clone_plan" ( "source_id" text NOT NULL, "cloned_id" text NOT NULL, @@ -49,6 +81,8 @@ JOIN "workspace" w ON w."organization_id" = pg."organization_id" WHERE pg."organization_id" IS NOT NULL;--> statement-breakpoint -- 3. Create the workspace-scoped clone rows using the planned ids. +-- Naturally idempotent: after a successful prior run there are no org-scoped +-- rows left, so the clone plan is empty and this INSERT is a no-op. INSERT INTO "permission_group" ( "id", "workspace_id", @@ -101,6 +135,7 @@ WHERE EXISTS ( );--> statement-breakpoint -- 5. Delete legacy org-scoped rows now that clones exist. +-- Idempotent: no rows match on a re-run. DELETE FROM "permission_group_member" WHERE "permission_group_id" IN ( SELECT "id" FROM "permission_group" WHERE "organization_id" IS NOT NULL @@ -109,20 +144,20 @@ WHERE "permission_group_id" IN ( DELETE FROM "permission_group" WHERE "organization_id" IS NOT NULL;--> statement-breakpoint -- 6. Enforce NOT NULL on both workspace_id columns now that every surviving row has one. +-- SET NOT NULL is a no-op if already NOT NULL. ALTER TABLE "permission_group" ALTER COLUMN "workspace_id" SET NOT NULL;--> statement-breakpoint ALTER TABLE "permission_group_member" ALTER COLUMN "workspace_id" SET NOT NULL;--> statement-breakpoint -- 7. Drop legacy structures and swap indexes. -ALTER TABLE "permission_group" DROP CONSTRAINT "permission_group_organization_id_organization_id_fk";--> statement-breakpoint -DROP INDEX "permission_group_org_name_unique";--> statement-breakpoint -DROP INDEX "permission_group_org_auto_add_unique";--> statement-breakpoint -DROP INDEX "permission_group_member_user_id_unique";--> statement-breakpoint -ALTER TABLE "permission_group" DROP COLUMN "organization_id";--> statement-breakpoint -CREATE UNIQUE INDEX "permission_group_workspace_name_unique" ON "permission_group" USING btree ("workspace_id","name");--> statement-breakpoint -CREATE UNIQUE INDEX "permission_group_workspace_auto_add_unique" ON "permission_group" USING btree ("workspace_id") WHERE auto_add_new_members = true;--> statement-breakpoint -CREATE UNIQUE INDEX "permission_group_member_group_user_unique" ON "permission_group_member" USING btree ("permission_group_id","user_id");--> statement-breakpoint -CREATE UNIQUE INDEX "permission_group_member_workspace_user_unique" ON "permission_group_member" USING btree ("workspace_id","user_id");--> statement-breakpoint +ALTER TABLE "permission_group" DROP CONSTRAINT IF EXISTS "permission_group_organization_id_organization_id_fk";--> statement-breakpoint +DROP INDEX IF EXISTS "permission_group_org_name_unique";--> statement-breakpoint +DROP INDEX IF EXISTS "permission_group_org_auto_add_unique";--> statement-breakpoint +DROP INDEX IF EXISTS "permission_group_member_user_id_unique";--> statement-breakpoint +ALTER TABLE "permission_group" DROP COLUMN IF EXISTS "organization_id";--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "permission_group_workspace_name_unique" ON "permission_group" USING btree ("workspace_id","name");--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "permission_group_workspace_auto_add_unique" ON "permission_group" USING btree ("workspace_id") WHERE auto_add_new_members = true;--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "permission_group_member_group_user_unique" ON "permission_group_member" USING btree ("permission_group_id","user_id");--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "permission_group_member_workspace_user_unique" ON "permission_group_member" USING btree ("workspace_id","user_id");--> statement-breakpoint -- 8. Sweep any residual dead config keys from pre-existing workspace-scoped rows (if any). UPDATE "permission_group" SET "config" = ("config" - 'hideEnvironmentTab' - 'hideTemplates') WHERE "config" ? 'hideEnvironmentTab' OR "config" ? 'hideTemplates'; - From 7941dcde986613dbeca19fbd28e856a85927d54c Mon Sep 17 00:00:00 2001 From: Waleed Date: Tue, 21 Apr 2026 21:18:32 -0700 Subject: [PATCH 2/2] fix(docs): update simstudio.ai URLs to sim.ai in SSO docs (#4257) * fix(docs): update simstudio.ai URLs to sim.ai in SSO docs * improvement(docs): remove plan defaults table from data retention docs * improvement(docs): consolidate self-hosting info at bottom of enterprise docs * improvement(docs): reduce callout and FAQ overuse in enterprise docs * improvement(docs): restore FAQs and genuine-gotcha callouts --- .../docs/en/enterprise/access-control.mdx | 2 +- .../content/docs/en/enterprise/audit-logs.mdx | 5 +- .../docs/en/enterprise/data-retention.mdx | 23 +--- .../docs/content/docs/en/enterprise/index.mdx | 104 +++++++----------- apps/docs/content/docs/en/enterprise/sso.mdx | 36 ++---- .../docs/en/enterprise/whitelabeling.mdx | 7 +- 6 files changed, 58 insertions(+), 119 deletions(-) diff --git a/apps/docs/content/docs/en/enterprise/access-control.mdx b/apps/docs/content/docs/en/enterprise/access-control.mdx index b1ab31105c..0034a296ae 100644 --- a/apps/docs/content/docs/en/enterprise/access-control.mdx +++ b/apps/docs/content/docs/en/enterprise/access-control.mdx @@ -165,7 +165,7 @@ When a user opens Mothership, their permission group is read before any block or Paginate by passing the `nextCursor` value as the `cursor` parameter in the next request. When `nextCursor` is absent, you have reached the last page. - - The API accepts both personal and workspace-scoped API keys. Rate limits apply — the response includes `X-RateLimit-*` headers with your current limit and remaining quota. - +The API accepts both personal and workspace-scoped API keys. Rate limits apply — the response includes `X-RateLimit-*` headers with your current limit and remaining quota. --- diff --git a/apps/docs/content/docs/en/enterprise/data-retention.mdx b/apps/docs/content/docs/en/enterprise/data-retention.mdx index 2590d32408..76510debe0 100644 --- a/apps/docs/content/docs/en/enterprise/data-retention.mdx +++ b/apps/docs/content/docs/en/enterprise/data-retention.mdx @@ -3,7 +3,6 @@ title: Data Retention description: Control how long execution logs, deleted resources, and copilot data are kept before permanent deletion --- -import { Callout } from 'fumadocs-ui/components/callout' import { FAQ } from '@/components/ui/faq' import { Image } from '@/components/ui/image' @@ -55,9 +54,7 @@ Controls how long **Mothership data** is kept, including: - Run checkpoints and async tool calls - Inbox tasks (Sim Mailer) - - Each setting is independent. You can configure a short log retention period alongside a long soft deletion cleanup period, or set any combination that fits your compliance requirements. - +Each setting is independent. You can configure a short log retention period alongside a long soft deletion cleanup period, or any combination that fits your compliance requirements. --- @@ -67,23 +64,9 @@ Retention is configured at the **workspace level**, not organization-wide. Each --- -## Plan defaults +## Defaults -Non-enterprise workspaces use the following automatic defaults. These cannot be changed. - -| Setting | Free | Pro | Team | -|---------|------|-----|------| -| Log retention | 30 days | Not configured | Not configured | -| Soft deletion cleanup | 30 days | 90 days | 90 days | -| Task cleanup | Not configured | Not configured | Not configured | - -"Not configured" means that category of data is not automatically deleted on that plan. - -Enterprise workspaces have no defaults — retention only runs for a setting once you configure it. Until configured, that category of data is not automatically deleted. - - - On Enterprise, setting a period to **Forever** explicitly keeps data indefinitely. Leaving a setting unconfigured has the same effect, but setting it to Forever makes the intent explicit and allows you to change it later without needing to save from scratch. - +By default, all three settings are unconfigured — no data is automatically deleted in any category until you configure it. Setting a period to **Forever** has the same effect as leaving it unconfigured, but makes the intent explicit and allows you to change it later without saving from scratch. --- diff --git a/apps/docs/content/docs/en/enterprise/index.mdx b/apps/docs/content/docs/en/enterprise/index.mdx index a4a7aff19b..1c01d7872f 100644 --- a/apps/docs/content/docs/en/enterprise/index.mdx +++ b/apps/docs/content/docs/en/enterprise/index.mdx @@ -3,7 +3,6 @@ title: Enterprise description: Enterprise features for business organizations --- -import { Callout } from 'fumadocs-ui/components/callout' import { FAQ } from '@/components/ui/faq' Sim Enterprise provides advanced features for organizations with enhanced security, compliance, and management requirements. @@ -26,9 +25,9 @@ Define permission groups on a workspace to control what features and integration 2. Create a permission group with your desired restrictions 3. Add workspace members to the permission group - - Any workspace admin on an Enterprise-entitled workspace can manage permission groups. Users not assigned to any group have full access. Permission restrictions are enforced at both UI and execution time, and apply to workflows based on the workflow's workspace. - +Any workspace admin on an Enterprise-entitled workspace can manage permission groups. Users not assigned to any group have full access. Restrictions are enforced at both UI and execution time, based on the workflow's workspace. + +See the [Access Control guide](/docs/enterprise/access-control) for full details. --- @@ -40,69 +39,46 @@ See the [SSO setup guide](/docs/enterprise/sso) for step-by-step instructions an --- -## Self-Hosted Configuration +## Whitelabeling -For self-hosted deployments, enterprise features can be enabled via environment variables without requiring billing. +Replace Sim's default branding — logos, product name, and favicons — with your own. See the [whitelabeling guide](/docs/enterprise/whitelabeling). -### Environment Variables +--- -| Variable | Description | -|----------|-------------| -| `ORGANIZATIONS_ENABLED`, `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` | Enable team/organization management | -| `ACCESS_CONTROL_ENABLED`, `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | Permission groups for access restrictions | -| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Single Sign-On with SAML/OIDC | -| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Polling Groups for email triggers | -| `INBOX_ENABLED`, `NEXT_PUBLIC_INBOX_ENABLED` | Sim Mailer inbox for outbound email | -| `WHITELABELING_ENABLED`, `NEXT_PUBLIC_WHITELABELING_ENABLED` | Custom branding and white-labeling | -| `AUDIT_LOGS_ENABLED`, `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` | Audit logging for compliance and monitoring | -| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Globally disable workspace/organization invitations | - -### Organization Management - -When billing is disabled, use the Admin API to manage organizations: - -```bash -# Create an organization -curl -X POST https://your-instance/api/v1/admin/organizations \ - -H "x-admin-key: YOUR_ADMIN_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name": "My Organization", "ownerId": "user-id-here"}' - -# Add a member -curl -X POST https://your-instance/api/v1/admin/organizations/{orgId}/members \ - -H "x-admin-key: YOUR_ADMIN_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"userId": "user-id-here", "role": "admin"}' -``` - -### Workspace Members - -When invitations are disabled, use the Admin API to manage workspace memberships directly: - -```bash -# Add a user to a workspace -curl -X POST https://your-instance/api/v1/admin/workspaces/{workspaceId}/members \ - -H "x-admin-key: YOUR_ADMIN_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"userId": "user-id-here", "permissions": "write"}' - -# Remove a user from a workspace -curl -X DELETE "https://your-instance/api/v1/admin/workspaces/{workspaceId}/members?userId=user-id-here" \ - -H "x-admin-key: YOUR_ADMIN_API_KEY" -``` - -### Notes - -- Access Control is scoped per workspace. Set `ACCESS_CONTROL_ENABLED` and `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` to enable it on every workspace in a self-hosted deployment, bypassing the Enterprise plan check. -- When `DISABLE_INVITATIONS` is set, users cannot send invitations. Use the Admin API to manage workspace and organization memberships instead. +## Audit Logs + +Track configuration and security-relevant actions across your organization for compliance and monitoring. See the [audit logs guide](/docs/enterprise/audit-logs). + +--- + +## Data Retention + +Configure how long execution logs, soft-deleted resources, and Mothership data are kept before permanent deletion. See the [data retention guide](/docs/enterprise/data-retention). + +--- + +--- + +## Self-hosted setup + +Self-hosted deployments enable enterprise features via environment variables instead of billing. + +| Variable | Description | +|----------|-------------| +| `ORGANIZATIONS_ENABLED`, `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` | Team and organization management | +| `ACCESS_CONTROL_ENABLED`, `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | Permission groups | +| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | SAML and OIDC sign-in | +| `WHITELABELING_ENABLED`, `NEXT_PUBLIC_WHITELABELING_ENABLED` | Custom branding | +| `AUDIT_LOGS_ENABLED`, `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` | Audit logging | +| `NEXT_PUBLIC_DATA_RETENTION_ENABLED` | Data retention configuration | +| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Polling groups for email triggers | +| `INBOX_ENABLED`, `NEXT_PUBLIC_INBOX_ENABLED` | Sim Mailer inbox | +| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Disable invitations; manage membership via Admin API | + +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 and workspace membership. diff --git a/apps/docs/content/docs/en/enterprise/sso.mdx b/apps/docs/content/docs/en/enterprise/sso.mdx index 8cc264d7dc..ca04c0b918 100644 --- a/apps/docs/content/docs/en/enterprise/sso.mdx +++ b/apps/docs/content/docs/en/enterprise/sso.mdx @@ -62,16 +62,14 @@ The **Callback URL** shown in the form is the endpoint your identity provider mu **OIDC providers** (Okta, Microsoft Entra ID, Google Workspace, Auth0): ``` -https://simstudio.ai/api/auth/sso/callback/{provider-id} +https://sim.ai/api/auth/sso/callback/{provider-id} ``` **SAML providers** (ADFS, Shibboleth): ``` -https://simstudio.ai/api/auth/sso/saml2/callback/{provider-id} +https://sim.ai/api/auth/sso/saml2/callback/{provider-id} ``` -For self-hosted, replace `simstudio.ai` with your instance hostname. - ### 5. Save and test Click **Save**. To test, sign out and use the **Sign in with SSO** button on the login page. Enter an email address at your configured domain — Sim will redirect you to your identity provider. @@ -92,7 +90,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the 2. Select **OIDC - OpenID Connect**, then **Web Application** 3. Set the **Sign-in redirect URI** to your Sim callback URL: ``` - https://simstudio.ai/api/auth/sso/callback/okta + https://sim.ai/api/auth/sso/callback/okta ``` 4. Under **Assignments**, grant access to the relevant users or groups 5. Copy the **Client ID** and **Client Secret** from the app's **General** tab @@ -109,9 +107,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the | Client ID | From Okta app | | Client Secret | From Okta app | - - The issuer URL uses Okta's default authorization server (`/oauth2/default`), which is pre-configured on every Okta org. If you created a custom authorization server, replace `default` with your server name. - +The issuer URL uses Okta's default authorization server, which is pre-configured on every Okta org. If you created a custom authorization server, replace `default` with your server name. @@ -124,7 +120,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the 1. Go to **Microsoft Entra ID → App registrations → New registration** 2. Under **Redirect URI**, select **Web** and enter your Sim callback URL: ``` - https://simstudio.ai/api/auth/sso/callback/azure-ad + https://sim.ai/api/auth/sso/callback/azure-ad ``` 3. After registration, go to **Certificates & secrets → New client secret** and copy the value immediately — it won't be shown again 4. Go to **Overview** and copy the **Application (client) ID** and **Directory (tenant) ID** @@ -140,10 +136,6 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the | Client ID | Application (client) ID | | Client Secret | Secret value | - - Replace `{tenant-id}` with your Directory (tenant) ID from the app's Overview page. Sim auto-discovers token and JWKS endpoints from the issuer. - - @@ -156,7 +148,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the 2. Set the application type to **Web application** 3. Add your Sim callback URL to **Authorized redirect URIs**: ``` - https://simstudio.ai/api/auth/sso/callback/google-workspace + https://sim.ai/api/auth/sso/callback/google-workspace ``` 4. Copy the **Client ID** and **Client Secret** @@ -187,14 +179,12 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the 2. Choose **Claims aware**, then **Enter data about the relying party manually** 3. Set the **Relying party identifier** (Entity ID) to your Sim base URL: ``` - https://simstudio.ai + https://sim.ai ``` - For self-hosted, use your instance's base URL (e.g. `https://sim.company.com`) 4. Add an endpoint: **SAML Assertion Consumer Service** (HTTP POST) with the URL: ``` - https://simstudio.ai/api/auth/sso/saml2/callback/adfs + https://sim.ai/api/auth/sso/saml2/callback/adfs ``` - For self-hosted: `https://sim.company.com/api/auth/sso/saml2/callback/adfs` 5. Export the **Token-signing certificate** from **Certificates**: right-click → **View Certificate → Details → Copy to File**, choose **Base-64 encoded X.509 (.CER)**. The `.cer` file is PEM-encoded — rename it to `.pem` before pasting its contents into Sim. 6. Note the **ADFS Federation Service endpoint URL** (e.g. `https://adfs.company.com/adfs/ls`) @@ -204,7 +194,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the |-------|-------| | Provider Type | SAML | | Provider ID | `adfs` | -| Issuer URL | `https://simstudio.ai` | +| Issuer URL | `https://sim.ai` | | Domain | `company.com` | | Entry Point URL | `https://adfs.company.com/adfs/ls` | | Certificate | Contents of the `.pem` file | @@ -223,7 +213,7 @@ Click **Save**. To test, sign out and use the **Sign in with SSO** button on the Once SSO is configured, users with your domain (`company.com`) can sign in through your identity provider: -1. User goes to `simstudio.ai` and clicks **Sign in with SSO** +1. User goes to `sim.ai` and clicks **Sign in with SSO** 2. They enter their work email (e.g. `alice@company.com`) 3. Sim redirects them to your identity provider 4. After authenticating, they are returned to Sim and added to your organization automatically @@ -235,10 +225,6 @@ Users who sign in via SSO for the first time are automatically provisioned and a Password-based login remains available. Forcing all organization members to use SSO exclusively is not yet supported. - - **Self-hosted:** Automatic organization provisioning requires `ORGANIZATIONS_ENABLED=true` in addition to `SSO_ENABLED=true`. Without it, SSO authentication still works — users get a valid session — but they are not automatically added to an organization. - - --- - Whitelabeling applies only to members of your organization. Public-facing pages (login, marketing) are not affected. - +Whitelabeling applies only to members of your organization. Public-facing pages (login, marketing) are not affected. --- @@ -103,4 +100,4 @@ WHITELABELING_ENABLED=true NEXT_PUBLIC_WHITELABELING_ENABLED=true ``` -Once enabled, configure branding through **Settings → Enterprise → Whitelabeling** the same way as Sim Cloud. +Once enabled, configure branding through **Settings → Enterprise → Whitelabeling** the same way.