diff --git a/apps/sim/app/api/permission-groups/[id]/route.ts b/apps/sim/app/api/permission-groups/[id]/route.ts index 977cb1bbf..10e645374 100644 --- a/apps/sim/app/api/permission-groups/[id]/route.ts +++ b/apps/sim/app/api/permission-groups/[id]/route.ts @@ -9,7 +9,7 @@ import { hasAccessControlAccess } from '@/lib/billing' import { type PermissionGroupConfig, parsePermissionGroupConfig, -} from '@/lib/permission-groups/types' +} from '@/ee/access-control/lib/types' const logger = createLogger('PermissionGroup') diff --git a/apps/sim/app/api/permission-groups/route.ts b/apps/sim/app/api/permission-groups/route.ts index a72726c5a..3d5b1eb2a 100644 --- a/apps/sim/app/api/permission-groups/route.ts +++ b/apps/sim/app/api/permission-groups/route.ts @@ -10,7 +10,7 @@ import { DEFAULT_PERMISSION_GROUP_CONFIG, type PermissionGroupConfig, parsePermissionGroupConfig, -} from '@/lib/permission-groups/types' +} from '@/ee/access-control/lib/types' const logger = createLogger('PermissionGroups') diff --git a/apps/sim/app/api/permission-groups/user/route.ts b/apps/sim/app/api/permission-groups/user/route.ts index e41c82653..b89c3a569 100644 --- a/apps/sim/app/api/permission-groups/user/route.ts +++ b/apps/sim/app/api/permission-groups/user/route.ts @@ -4,7 +4,7 @@ import { and, eq } from 'drizzle-orm' import { NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { isOrganizationOnEnterprisePlan } from '@/lib/billing' -import { parsePermissionGroupConfig } from '@/lib/permission-groups/types' +import { parsePermissionGroupConfig } from '@/ee/access-control/lib/types' export async function GET(req: Request) { const session = await getSession() diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts index e2241137f..db87eaf39 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/index.ts @@ -1,4 +1,3 @@ -export { AccessControl } from './access-control/access-control' export { ApiKeys } from './api-keys/api-keys' export { BYOK } from './byok/byok' export { Copilot } from './copilot/copilot' @@ -10,7 +9,6 @@ export { Files as FileUploads } from './files/files' export { General } from './general/general' export { Integrations } from './integrations/integrations' export { MCP } from './mcp/mcp' -export { SSO } from './sso/sso' export { Subscription } from './subscription/subscription' export { TeamManagement } from './team-management/team-management' export { WorkflowMcpServers } from './workflow-mcp-servers/workflow-mcp-servers' diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx index d2a72a998..ca15c7356 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx @@ -41,7 +41,6 @@ import { getEnv, isTruthy } from '@/lib/core/config/env' import { isHosted } from '@/lib/core/config/feature-flags' import { getUserRole } from '@/lib/workspaces/organization' import { - AccessControl, ApiKeys, BYOK, Copilot, @@ -53,15 +52,15 @@ import { General, Integrations, MCP, - SSO, Subscription, TeamManagement, WorkflowMcpServers, } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components' import { TemplateProfile } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/template-profile/template-profile' +import { AccessControl } from '@/ee/access-control' +import { SSO, ssoKeys, useSSOProviders } from '@/ee/sso' import { generalSettingsKeys, useGeneralSettings } from '@/hooks/queries/general-settings' import { organizationKeys, useOrganizations } from '@/hooks/queries/organization' -import { ssoKeys, useSSOProviders } from '@/hooks/queries/sso' import { subscriptionKeys, useSubscriptionData } from '@/hooks/queries/subscription' import { usePermissionConfig } from '@/hooks/use-permission-config' import { useSettingsModalStore } from '@/stores/modals/settings/store' diff --git a/apps/sim/ee/LICENSE b/apps/sim/ee/LICENSE new file mode 100644 index 000000000..8d8638ae4 --- /dev/null +++ b/apps/sim/ee/LICENSE @@ -0,0 +1,46 @@ +The Sim Enterprise License (the "Enterprise License") +Copyright (c) 2026-present Sim Studio, Inc. + +With regard to the Sim Software: + +This software and associated documentation files (the "Software") may only be +used in production, if you (and any entity that you represent) have agreed to, +and are in compliance with, the Sim Terms of Service available at +https://sim.ai/terms (or other agreement governing the use of the Software, +as mutually agreed by you and Sim Studio, Inc. ("Sim")), and otherwise +have a valid Sim Enterprise subscription ("Enterprise Subscription") +for the correct number of seats as defined in your agreement. + +Subject to the foregoing sentence, you are free to modify this Software and +publish patches to the Software. You agree that Sim and/or its licensors +(as applicable) retain all right, title and interest in and to all such +modifications and/or patches, and all such modifications and/or patches may +only be used, copied, modified, displayed, distributed, or otherwise exploited +with a valid Enterprise Subscription. + +Notwithstanding the foregoing, you may copy and modify the Software for +development and testing purposes, without requiring a subscription. You agree +that Sim and/or its licensors (as applicable) retain all right, title +and interest in and to all such modifications. + +You are not granted any other rights beyond what is expressly stated herein. +Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, +sublicense, and/or sell the Software. + +This Enterprise License applies only to the part of this Software that is not +distributed under the Apache License 2.0. Any part of this Software distributed +under the Apache License 2.0 is copyrighted under that license. The full text +of this Enterprise License shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +For all third party components incorporated into the Sim Software, those +components are licensed under the original license provided by the owner of the +applicable component. diff --git a/apps/sim/ee/README.md b/apps/sim/ee/README.md new file mode 100644 index 000000000..fd25040bc --- /dev/null +++ b/apps/sim/ee/README.md @@ -0,0 +1,69 @@ +# Sim Enterprise Edition + +This directory contains enterprise features that require a valid Sim Enterprise license for production use. + +## Features + +- **SSO**: SAML and OIDC single sign-on authentication +- **Access Control**: Permission groups and role-based access control + +## Structure + +``` +ee/ +├── LICENSE +├── README.md +├── index.ts # Main barrel export +├── sso/ +│ ├── index.ts +│ ├── components/ # SSO settings UI +│ ├── hooks/ # React Query hooks +│ └── lib/ # Utilities and constants +└── access-control/ + ├── index.ts + ├── components/ # Access control settings UI + ├── hooks/ # React Query hooks + └── lib/ # Types and utilities +``` + +**Note:** API routes remain in `app/api/` as required by Next.js routing conventions: +- SSO API: `app/api/auth/sso/` +- Permission Groups API: `app/api/permission-groups/` + +## Licensing + +Code in this directory is **NOT** covered by the Apache 2.0 license. See [LICENSE](./LICENSE) for the Sim Enterprise License terms. + +The rest of the Sim codebase outside this directory is licensed under Apache 2.0. + +## For Open Source Users + +You may delete this directory to use Sim under the Apache 2.0 license only. The application will continue to function without enterprise features. + +## Development & Testing + +You may copy and modify this software for development and testing purposes without requiring an Enterprise subscription. Production use requires a valid license. + +## Enabling Enterprise Features + +Enterprise features are controlled by environment variables and subscription status: + +- `NEXT_PUBLIC_SSO_ENABLED` - Enable SSO for self-hosted instances +- `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` - Enable access control for self-hosted instances + +On the hosted platform (sim.ai), these features are automatically available with an Enterprise subscription. + +## Usage + +```typescript +// Import enterprise components +import { SSO, AccessControl } from '@/ee' + +// Or import specific features +import { SSO, useSSOProviders } from '@/ee/sso' +import { AccessControl, usePermissionGroups } from '@/ee/access-control' +``` + +## Contact + +For Enterprise licensing inquiries, contact [sales@sim.ai](mailto:sales@sim.ai). diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/access-control/access-control.tsx b/apps/sim/ee/access-control/components/access-control.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/access-control/access-control.tsx rename to apps/sim/ee/access-control/components/access-control.tsx index af7db3fcc..0f3b4cb99 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/access-control/access-control.tsx +++ b/apps/sim/ee/access-control/components/access-control.tsx @@ -25,11 +25,9 @@ import { import { Input as BaseInput, Skeleton } from '@/components/ui' import { useSession } from '@/lib/auth/auth-client' import { getSubscriptionStatus } from '@/lib/billing/client' -import type { PermissionGroupConfig } from '@/lib/permission-groups/types' import { getUserColor } from '@/lib/workspaces/colors' import { getUserRole } from '@/lib/workspaces/organization' import { getAllBlocks } from '@/blocks' -import { useOrganization, useOrganizations } from '@/hooks/queries/organization' import { type PermissionGroup, useBulkAddPermissionGroupMembers, @@ -39,7 +37,9 @@ import { usePermissionGroups, useRemovePermissionGroupMember, useUpdatePermissionGroup, -} from '@/hooks/queries/permission-groups' +} from '@/ee/access-control/hooks/permission-groups' +import type { PermissionGroupConfig } from '@/ee/access-control/lib/types' +import { useOrganization, useOrganizations } from '@/hooks/queries/organization' import { useSubscriptionData } from '@/hooks/queries/subscription' import { PROVIDER_DEFINITIONS } from '@/providers/models' import { getAllProviderIds } from '@/providers/utils' diff --git a/apps/sim/hooks/queries/permission-groups.ts b/apps/sim/ee/access-control/hooks/permission-groups.ts similarity index 99% rename from apps/sim/hooks/queries/permission-groups.ts rename to apps/sim/ee/access-control/hooks/permission-groups.ts index 6832d5188..57336eb62 100644 --- a/apps/sim/hooks/queries/permission-groups.ts +++ b/apps/sim/ee/access-control/hooks/permission-groups.ts @@ -1,5 +1,5 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' -import type { PermissionGroupConfig } from '@/lib/permission-groups/types' +import type { PermissionGroupConfig } from '@/ee/access-control/lib/types' import { fetchJson } from '@/hooks/selectors/helpers' export interface PermissionGroup { diff --git a/apps/sim/ee/access-control/index.ts b/apps/sim/ee/access-control/index.ts new file mode 100644 index 000000000..072292a2f --- /dev/null +++ b/apps/sim/ee/access-control/index.ts @@ -0,0 +1,26 @@ +export { AccessControl } from './components/access-control' +export { + type BulkAddMembersData, + type CreatePermissionGroupData, + type DeletePermissionGroupParams, + type PermissionGroup, + type PermissionGroupMember, + permissionGroupKeys, + type UpdatePermissionGroupData, + type UserPermissionConfig, + useAddPermissionGroupMember, + useBulkAddPermissionGroupMembers, + useCreatePermissionGroup, + useDeletePermissionGroup, + usePermissionGroup, + usePermissionGroupMembers, + usePermissionGroups, + useRemovePermissionGroupMember, + useUpdatePermissionGroup, + useUserPermissionConfig, +} from './hooks/permission-groups' +export type { PermissionGroupConfig } from './lib/types' +export { + DEFAULT_PERMISSION_GROUP_CONFIG, + parsePermissionGroupConfig, +} from './lib/types' diff --git a/apps/sim/lib/permission-groups/types.ts b/apps/sim/ee/access-control/lib/types.ts similarity index 100% rename from apps/sim/lib/permission-groups/types.ts rename to apps/sim/ee/access-control/lib/types.ts diff --git a/apps/sim/ee/index.ts b/apps/sim/ee/index.ts new file mode 100644 index 000000000..2eeb0e5c5 --- /dev/null +++ b/apps/sim/ee/index.ts @@ -0,0 +1,34 @@ +/** + * Sim Enterprise Edition + * + * This module contains enterprise features that require a valid + * Sim Enterprise license for production use. + * + * See LICENSE in this directory for terms. + */ + +export type { PermissionGroupConfig } from './access-control' +// Access Control (Permission Groups) +export { + AccessControl, + type BulkAddMembersData, + type CreatePermissionGroupData, + type DeletePermissionGroupParams, + type PermissionGroup, + type PermissionGroupMember, + permissionGroupKeys, + type UpdatePermissionGroupData, + type UserPermissionConfig, + useAddPermissionGroupMember, + useBulkAddPermissionGroupMembers, + useCreatePermissionGroup, + useDeletePermissionGroup, + usePermissionGroup, + usePermissionGroupMembers, + usePermissionGroups, + useRemovePermissionGroupMember, + useUpdatePermissionGroup, + useUserPermissionConfig, +} from './access-control' +// SSO (Single Sign-On) +export { SSO, ssoKeys, useConfigureSSO, useDeleteSSO, useSSOProviders } from './sso' diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/sso/sso.tsx b/apps/sim/ee/sso/components/sso.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/sso/sso.tsx rename to apps/sim/ee/sso/components/sso.tsx index 2657c8204..1794404cf 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/sso/sso.tsx +++ b/apps/sim/ee/sso/components/sso.tsx @@ -11,8 +11,8 @@ import { isBillingEnabled } from '@/lib/core/config/feature-flags' import { cn } from '@/lib/core/utils/cn' import { getBaseUrl } from '@/lib/core/utils/urls' import { getUserRole } from '@/lib/workspaces/organization/utils' +import { useConfigureSSO, useSSOProviders } from '@/ee/sso/hooks/sso' import { useOrganizations } from '@/hooks/queries/organization' -import { useConfigureSSO, useSSOProviders } from '@/hooks/queries/sso' import { useSubscriptionData } from '@/hooks/queries/subscription' const logger = createLogger('SSO') diff --git a/apps/sim/hooks/queries/sso.ts b/apps/sim/ee/sso/hooks/sso.ts similarity index 100% rename from apps/sim/hooks/queries/sso.ts rename to apps/sim/ee/sso/hooks/sso.ts diff --git a/apps/sim/ee/sso/index.ts b/apps/sim/ee/sso/index.ts new file mode 100644 index 000000000..560bffee3 --- /dev/null +++ b/apps/sim/ee/sso/index.ts @@ -0,0 +1,8 @@ +export { SSO } from './components/sso' +export { + ssoKeys, + useConfigureSSO, + useDeleteSSO, + useSSOProviders, +} from './hooks/sso' +export * from './lib/constants' diff --git a/apps/sim/lib/auth/sso/constants.ts b/apps/sim/ee/sso/lib/constants.ts similarity index 100% rename from apps/sim/lib/auth/sso/constants.ts rename to apps/sim/ee/sso/lib/constants.ts diff --git a/apps/sim/executor/types.ts b/apps/sim/executor/types.ts index 6c87eed25..c03240f16 100644 --- a/apps/sim/executor/types.ts +++ b/apps/sim/executor/types.ts @@ -1,6 +1,6 @@ import type { TraceSpan } from '@/lib/logs/types' -import type { PermissionGroupConfig } from '@/lib/permission-groups/types' import type { BlockOutput } from '@/blocks/types' +import type { PermissionGroupConfig } from '@/ee/access-control/lib/types' import type { RunFromBlockContext } from '@/executor/utils/run-from-block' import type { SerializedBlock, SerializedWorkflow } from '@/serializer/types' diff --git a/apps/sim/executor/utils/permission-check.ts b/apps/sim/executor/utils/permission-check.ts index 84cbbc9ae..680180935 100644 --- a/apps/sim/executor/utils/permission-check.ts +++ b/apps/sim/executor/utils/permission-check.ts @@ -7,7 +7,7 @@ import { isAccessControlEnabled, isHosted } from '@/lib/core/config/feature-flag import { type PermissionGroupConfig, parsePermissionGroupConfig, -} from '@/lib/permission-groups/types' +} from '@/ee/access-control/lib/types' import type { ExecutionContext } from '@/executor/types' import { getProviderFromModel } from '@/providers/utils' diff --git a/apps/sim/hooks/use-permission-config.ts b/apps/sim/hooks/use-permission-config.ts index 994656fdc..c7d58228a 100644 --- a/apps/sim/hooks/use-permission-config.ts +++ b/apps/sim/hooks/use-permission-config.ts @@ -1,12 +1,12 @@ import { useMemo } from 'react' import { getEnv, isTruthy } from '@/lib/core/config/env' import { isAccessControlEnabled, isHosted } from '@/lib/core/config/feature-flags' +import { useUserPermissionConfig } from '@/ee/access-control/hooks/permission-groups' import { DEFAULT_PERMISSION_GROUP_CONFIG, type PermissionGroupConfig, -} from '@/lib/permission-groups/types' +} from '@/ee/access-control/lib/types' import { useOrganizations } from '@/hooks/queries/organization' -import { useUserPermissionConfig } from '@/hooks/queries/permission-groups' export interface PermissionConfigResult { config: PermissionGroupConfig diff --git a/apps/sim/lib/auth/auth.ts b/apps/sim/lib/auth/auth.ts index 0a70d7903..40984d87f 100644 --- a/apps/sim/lib/auth/auth.ts +++ b/apps/sim/lib/auth/auth.ts @@ -59,8 +59,8 @@ import { sendEmail } from '@/lib/messaging/email/mailer' import { getFromEmailAddress, getPersonalEmailFrom } from '@/lib/messaging/email/utils' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server' +import { SSO_TRUSTED_PROVIDERS } from '@/ee/sso/lib/constants' import { createAnonymousSession, ensureAnonymousUserExists } from './anonymous' -import { SSO_TRUSTED_PROVIDERS } from './sso/constants' const logger = createLogger('Auth') diff --git a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts index 1e112d3fc..ea940559a 100644 --- a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts +++ b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts @@ -5,7 +5,6 @@ import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool' import { validateSelectorIds } from '@/lib/copilot/validation/selector-validator' -import type { PermissionGroupConfig } from '@/lib/permission-groups/types' import { getBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { extractAndPersistCustomTools } from '@/lib/workflows/persistence/custom-tools-persistence' import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' @@ -15,6 +14,7 @@ import { buildCanonicalIndex, isCanonicalPair } from '@/lib/workflows/subblocks/ import { TriggerUtils } from '@/lib/workflows/triggers/triggers' import { getAllBlocks, getBlock } from '@/blocks/registry' import type { BlockConfig, SubBlockConfig } from '@/blocks/types' +import type { PermissionGroupConfig } from '@/ee/access-control/lib/types' import { EDGE, normalizeName, RESERVED_BLOCK_NAMES } from '@/executor/constants' import { getUserPermissionConfig } from '@/executor/utils/permission-check' import { generateLoopBlocks, generateParallelBlocks } from '@/stores/workflows/workflow/utils'