Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code c147b1c1e0 fix(auth): pick Apple fallback in single-workspace mode
https://sonarly.com/issue/36998?type=bug

In single-workspace mode, auth flows that resolve a “default workspace” can target the newest seeded workspace (e.g. Empty4) instead of Apple, causing login to fail with a membership error.

Fix: Implemented a targeted backend fix in the default-workspace resolver so single-workspace mode no longer blindly picks the newest workspace.

### What changed
1. **Restored Apple fallback behavior in default workspace selection**
   - File: `packages/twenty-server/src/engine/core-modules/domain/workspace-domains/services/workspace-domains.service.ts`
   - Imported `SEED_APPLE_WORKSPACE_ID`.
   - Updated `getDefaultWorkspace()` selection logic:
     - If exactly one workspace exists, keep returning it.
     - If multiple workspaces exist, select the workspace whose `id` matches `SEED_APPLE_WORKSPACE_ID`.
   - Existing `assertIsDefinedOrThrow(..., WorkspaceNotFoundDefaultError)` remains in place, so misconfigured environments still fail explicitly rather than silently routing to the wrong workspace.

2. **Updated unit test to cover the fixed behavior**
   - File: `packages/twenty-server/src/engine/core-modules/domain/workspace-domains/services/__test__/workspace-domains.service.spec.ts`
   - Imported `SEED_APPLE_WORKSPACE_ID`.
   - Changed the multiple-workspace single-workspace-mode test expectation from “first workspace” to “Apple workspace”.
   - Test now seeds a list where Apple is not first, and asserts Apple is selected.

### Why this fixes the bug
The regression was caused by `workspaces[0]` selection under `createdAt DESC`, which can point to newer empty seeded workspaces (e.g., Empty4). Choosing `SEED_APPLE_WORKSPACE_ID` when multiple workspaces are present aligns runtime behavior with the fallback intent and prevents auth from validating membership against the wrong workspace.
2026-05-12 12:32:54 +00:00
2 changed files with 11 additions and 3 deletions
@@ -8,6 +8,7 @@ import { WorkspaceDomainsService } from 'src/engine/core-modules/domain/workspac
import { PublicDomainEntity } from 'src/engine/core-modules/public-domain/public-domain.entity';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
describe('WorkspaceDomainsService', () => {
let workspaceDomainsService: WorkspaceDomainsService;
@@ -213,7 +214,7 @@ describe('WorkspaceDomainsService', () => {
expect(result?.id).toEqual('workspace-id');
});
it('should return 1st workspace if multiple workspaces when IS_MULTIWORKSPACE_ENABLED=false', async () => {
it('should return Apple workspace if multiple workspaces when IS_MULTIWORKSPACE_ENABLED=false', async () => {
jest
.spyOn(twentyConfigService, 'get')
.mockImplementation((key: string) => {
@@ -230,6 +231,9 @@ describe('WorkspaceDomainsService', () => {
{
id: 'workspace-id1',
},
{
id: SEED_APPLE_WORKSPACE_ID,
},
{
id: 'workspace-id2',
},
@@ -240,7 +244,7 @@ describe('WorkspaceDomainsService', () => {
'https://example.com',
);
expect(result?.id).toEqual('workspace-id1');
expect(result?.id).toEqual(SEED_APPLE_WORKSPACE_ID);
});
it('should return workspace by subdomain', async () => {
@@ -9,6 +9,7 @@ import { buildUrlWithPathnameAndSearchParams } from 'src/engine/core-modules/dom
import { WorkspaceDomainConfig } from 'src/engine/core-modules/domain/workspace-domains/types/workspace-domain-config.type';
import { PublicDomainEntity } from 'src/engine/core-modules/public-domain/public-domain.entity';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@@ -77,7 +78,10 @@ export class WorkspaceDomainsService {
);
}
const foundWorkspace = workspaces[0];
const foundWorkspace =
workspaces.length === 1
? workspaces[0]
: workspaces.find((workspace) => workspace.id === SEED_APPLE_WORKSPACE_ID);
assertIsDefinedOrThrow(foundWorkspace, WorkspaceNotFoundDefaultError);